Geometry.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author kile / http://kile.stravaganza.org/
  4. * @author alteredq / http://alteredqualia.com/
  5. * @author mikael emtinger / http://gomo.se/
  6. * @author zz85 / http://www.lab4games.net/zz85/blog
  7. * @author bhouston / http://exocortex.com
  8. */
  9. THREE.Geometry = function () {
  10. this.id = THREE.GeometryIdCount ++;
  11. this.uuid = THREE.Math.generateUUID();
  12. this.name = '';
  13. this.vertices = [];
  14. this.colors = []; // one-to-one vertex colors, used in ParticleSystem and Line
  15. this.faces = [];
  16. this.faceVertexUvs = [[]];
  17. this.morphTargets = [];
  18. this.morphColors = [];
  19. this.morphNormals = [];
  20. this.skinWeights = [];
  21. this.skinIndices = [];
  22. this.lineDistances = [];
  23. this.boundingBox = null;
  24. this.boundingSphere = null;
  25. this.hasTangents = false;
  26. this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
  27. // update flags
  28. this.verticesNeedUpdate = false;
  29. this.elementsNeedUpdate = false;
  30. this.uvsNeedUpdate = false;
  31. this.normalsNeedUpdate = false;
  32. this.tangentsNeedUpdate = false;
  33. this.colorsNeedUpdate = false;
  34. this.lineDistancesNeedUpdate = false;
  35. this.buffersNeedUpdate = false;
  36. };
  37. THREE.Geometry.prototype = {
  38. constructor: THREE.Geometry,
  39. applyMatrix: function ( matrix ) {
  40. var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
  41. for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
  42. var vertex = this.vertices[ i ];
  43. vertex.applyMatrix4( matrix );
  44. }
  45. for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
  46. var face = this.faces[ i ];
  47. face.normal.applyMatrix3( normalMatrix ).normalize();
  48. for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
  49. face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
  50. }
  51. }
  52. if ( this.boundingBox instanceof THREE.Box3 ) {
  53. this.computeBoundingBox();
  54. }
  55. if ( this.boundingSphere instanceof THREE.Sphere ) {
  56. this.computeBoundingSphere();
  57. }
  58. },
  59. computeFaceNormals: function () {
  60. var cb = new THREE.Vector3(), ab = new THREE.Vector3();
  61. for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
  62. var face = this.faces[ f ];
  63. var vA = this.vertices[ face.a ];
  64. var vB = this.vertices[ face.b ];
  65. var vC = this.vertices[ face.c ];
  66. cb.subVectors( vC, vB );
  67. ab.subVectors( vA, vB );
  68. cb.cross( ab );
  69. cb.normalize();
  70. face.normal.copy( cb );
  71. }
  72. },
  73. computeVertexNormals: function ( areaWeighted ) {
  74. var v, vl, f, fl, face, vertices;
  75. vertices = new Array( this.vertices.length );
  76. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  77. vertices[ v ] = new THREE.Vector3();
  78. }
  79. if ( areaWeighted ) {
  80. // vertex normals weighted by triangle areas
  81. // http://www.iquilezles.org/www/articles/normals/normals.htm
  82. var vA, vB, vC, vD;
  83. var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
  84. db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
  85. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  86. face = this.faces[ f ];
  87. vA = this.vertices[ face.a ];
  88. vB = this.vertices[ face.b ];
  89. vC = this.vertices[ face.c ];
  90. cb.subVectors( vC, vB );
  91. ab.subVectors( vA, vB );
  92. cb.cross( ab );
  93. vertices[ face.a ].add( cb );
  94. vertices[ face.b ].add( cb );
  95. vertices[ face.c ].add( cb );
  96. }
  97. } else {
  98. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  99. face = this.faces[ f ];
  100. vertices[ face.a ].add( face.normal );
  101. vertices[ face.b ].add( face.normal );
  102. vertices[ face.c ].add( face.normal );
  103. }
  104. }
  105. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  106. vertices[ v ].normalize();
  107. }
  108. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  109. face = this.faces[ f ];
  110. face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
  111. face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
  112. face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
  113. }
  114. },
  115. computeMorphNormals: function () {
  116. var i, il, f, fl, face;
  117. // save original normals
  118. // - create temp variables on first access
  119. // otherwise just copy (for faster repeated calls)
  120. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  121. face = this.faces[ f ];
  122. if ( ! face.__originalFaceNormal ) {
  123. face.__originalFaceNormal = face.normal.clone();
  124. } else {
  125. face.__originalFaceNormal.copy( face.normal );
  126. }
  127. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  128. for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  129. if ( ! face.__originalVertexNormals[ i ] ) {
  130. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  131. } else {
  132. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  133. }
  134. }
  135. }
  136. // use temp geometry to compute face and vertex normals for each morph
  137. var tmpGeo = new THREE.Geometry();
  138. tmpGeo.faces = this.faces;
  139. for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  140. // create on first access
  141. if ( ! this.morphNormals[ i ] ) {
  142. this.morphNormals[ i ] = {};
  143. this.morphNormals[ i ].faceNormals = [];
  144. this.morphNormals[ i ].vertexNormals = [];
  145. var dstNormalsFace = this.morphNormals[ i ].faceNormals;
  146. var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  147. var faceNormal, vertexNormals;
  148. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  149. face = this.faces[ f ];
  150. faceNormal = new THREE.Vector3();
  151. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
  152. dstNormalsFace.push( faceNormal );
  153. dstNormalsVertex.push( vertexNormals );
  154. }
  155. }
  156. var morphNormals = this.morphNormals[ i ];
  157. // set vertices to morph target
  158. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  159. // compute morph normals
  160. tmpGeo.computeFaceNormals();
  161. tmpGeo.computeVertexNormals();
  162. // store morph normals
  163. var faceNormal, vertexNormals;
  164. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  165. face = this.faces[ f ];
  166. faceNormal = morphNormals.faceNormals[ f ];
  167. vertexNormals = morphNormals.vertexNormals[ f ];
  168. faceNormal.copy( face.normal );
  169. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  170. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  171. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  172. }
  173. }
  174. // restore original normals
  175. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  176. face = this.faces[ f ];
  177. face.normal = face.__originalFaceNormal;
  178. face.vertexNormals = face.__originalVertexNormals;
  179. }
  180. },
  181. computeTangents: function () {
  182. // based on http://www.terathon.com/code/tangent.html
  183. // tangents go to vertices
  184. var f, fl, v, vl, i, il, vertexIndex,
  185. face, uv, vA, vB, vC, uvA, uvB, uvC,
  186. x1, x2, y1, y2, z1, z2,
  187. s1, s2, t1, t2, r, t, test,
  188. tan1 = [], tan2 = [],
  189. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  190. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  191. n = new THREE.Vector3(), w;
  192. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  193. tan1[ v ] = new THREE.Vector3();
  194. tan2[ v ] = new THREE.Vector3();
  195. }
  196. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  197. vA = context.vertices[ a ];
  198. vB = context.vertices[ b ];
  199. vC = context.vertices[ c ];
  200. uvA = uv[ ua ];
  201. uvB = uv[ ub ];
  202. uvC = uv[ uc ];
  203. x1 = vB.x - vA.x;
  204. x2 = vC.x - vA.x;
  205. y1 = vB.y - vA.y;
  206. y2 = vC.y - vA.y;
  207. z1 = vB.z - vA.z;
  208. z2 = vC.z - vA.z;
  209. s1 = uvB.x - uvA.x;
  210. s2 = uvC.x - uvA.x;
  211. t1 = uvB.y - uvA.y;
  212. t2 = uvC.y - uvA.y;
  213. r = 1.0 / ( s1 * t2 - s2 * t1 );
  214. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  215. ( t2 * y1 - t1 * y2 ) * r,
  216. ( t2 * z1 - t1 * z2 ) * r );
  217. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  218. ( s1 * y2 - s2 * y1 ) * r,
  219. ( s1 * z2 - s2 * z1 ) * r );
  220. tan1[ a ].add( sdir );
  221. tan1[ b ].add( sdir );
  222. tan1[ c ].add( sdir );
  223. tan2[ a ].add( tdir );
  224. tan2[ b ].add( tdir );
  225. tan2[ c ].add( tdir );
  226. }
  227. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  228. face = this.faces[ f ];
  229. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  230. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  231. }
  232. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  233. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  234. face = this.faces[ f ];
  235. for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
  236. n.copy( face.vertexNormals[ i ] );
  237. vertexIndex = face[ faceIndex[ i ] ];
  238. t = tan1[ vertexIndex ];
  239. // Gram-Schmidt orthogonalize
  240. tmp.copy( t );
  241. tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
  242. // Calculate handedness
  243. tmp2.crossVectors( face.vertexNormals[ i ], t );
  244. test = tmp2.dot( tan2[ vertexIndex ] );
  245. w = (test < 0.0) ? -1.0 : 1.0;
  246. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  247. }
  248. }
  249. this.hasTangents = true;
  250. },
  251. computeLineDistances: function ( ) {
  252. var d = 0;
  253. var vertices = this.vertices;
  254. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  255. if ( i > 0 ) {
  256. d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
  257. }
  258. this.lineDistances[ i ] = d;
  259. }
  260. },
  261. computeBoundingBox: function () {
  262. if ( this.boundingBox === null ) {
  263. this.boundingBox = new THREE.Box3();
  264. }
  265. this.boundingBox.setFromPoints( this.vertices );
  266. },
  267. computeBoundingSphere: function () {
  268. if ( this.boundingSphere === null ) {
  269. this.boundingSphere = new THREE.Sphere();
  270. }
  271. this.boundingSphere.setFromPoints( this.vertices );
  272. },
  273. merge: function ( geometry, matrix, materialIndexOffset ) {
  274. var normalMatrix,
  275. vertexOffset = this.vertices.length,
  276. uvPosition = this.faceVertexUvs[ 0 ].length,
  277. vertices1 = this.vertices,
  278. vertices2 = geometry.vertices,
  279. faces1 = this.faces,
  280. faces2 = geometry.faces,
  281. uvs1 = this.faceVertexUvs[ 0 ],
  282. uvs2 = geometry.faceVertexUvs[ 0 ];
  283. if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
  284. if ( matrix !== undefined ) {
  285. normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
  286. }
  287. // vertices
  288. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  289. var vertex = vertices2[ i ];
  290. var vertexCopy = vertex.clone();
  291. if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
  292. vertices1.push( vertexCopy );
  293. }
  294. // faces
  295. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  296. var face = faces2[ i ], faceCopy, normal, color,
  297. faceVertexNormals = face.vertexNormals,
  298. faceVertexColors = face.vertexColors;
  299. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  300. faceCopy.normal.copy( face.normal );
  301. if ( normalMatrix !== undefined ) {
  302. faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
  303. }
  304. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  305. normal = faceVertexNormals[ j ].clone();
  306. if ( normalMatrix !== undefined ) {
  307. normal.applyMatrix3( normalMatrix ).normalize();
  308. }
  309. faceCopy.vertexNormals.push( normal );
  310. }
  311. faceCopy.color.copy( face.color );
  312. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  313. color = faceVertexColors[ j ];
  314. faceCopy.vertexColors.push( color.clone() );
  315. }
  316. faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
  317. faces1.push( faceCopy );
  318. }
  319. // uvs
  320. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  321. var uv = uvs2[ i ], uvCopy = [];
  322. if ( uv === undefined ) {
  323. continue;
  324. }
  325. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  326. uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
  327. }
  328. uvs1.push( uvCopy );
  329. }
  330. },
  331. /*
  332. * Checks for duplicate vertices with hashmap.
  333. * Duplicated vertices are removed
  334. * and faces' vertices are updated.
  335. */
  336. mergeVertices: function () {
  337. var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
  338. var unique = [], changes = [];
  339. var v, key;
  340. var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
  341. var precision = Math.pow( 10, precisionPoints );
  342. var i,il, face;
  343. var indices, k, j, jl, u;
  344. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  345. v = this.vertices[ i ];
  346. key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
  347. if ( verticesMap[ key ] === undefined ) {
  348. verticesMap[ key ] = i;
  349. unique.push( this.vertices[ i ] );
  350. changes[ i ] = unique.length - 1;
  351. } else {
  352. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  353. changes[ i ] = changes[ verticesMap[ key ] ];
  354. }
  355. };
  356. // if faces are completely degenerate after merging vertices, we
  357. // have to remove them from the geometry.
  358. var faceIndicesToRemove = [];
  359. for( i = 0, il = this.faces.length; i < il; i ++ ) {
  360. face = this.faces[ i ];
  361. face.a = changes[ face.a ];
  362. face.b = changes[ face.b ];
  363. face.c = changes[ face.c ];
  364. indices = [ face.a, face.b, face.c ];
  365. var dupIndex = -1;
  366. // if any duplicate vertices are found in a Face3
  367. // we have to remove the face as nothing can be saved
  368. for ( var n = 0; n < 3; n ++ ) {
  369. if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
  370. dupIndex = n;
  371. faceIndicesToRemove.push( i );
  372. break;
  373. }
  374. }
  375. }
  376. for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
  377. var idx = faceIndicesToRemove[ i ];
  378. this.faces.splice( idx, 1 );
  379. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  380. this.faceVertexUvs[ j ].splice( idx, 1 );
  381. }
  382. }
  383. // Use unique set of vertices
  384. var diff = this.vertices.length - unique.length;
  385. this.vertices = unique;
  386. return diff;
  387. },
  388. // Geometry splitting
  389. makeGroups: ( function () {
  390. var geometryGroupCounter = 0;
  391. return function ( usesFaceMaterial, maxVerticesInGroup ) {
  392. var f, fl, face, materialIndex,
  393. groupHash, hash_map = {};
  394. var numMorphTargets = this.morphTargets.length;
  395. var numMorphNormals = this.morphNormals.length;
  396. this.geometryGroups = {};
  397. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  398. face = this.faces[ f ];
  399. materialIndex = usesFaceMaterial ? face.materialIndex : 0;
  400. if ( ! ( materialIndex in hash_map ) ) {
  401. hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
  402. }
  403. groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
  404. if ( ! ( groupHash in this.geometryGroups ) ) {
  405. this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
  406. }
  407. if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) {
  408. hash_map[ materialIndex ].counter += 1;
  409. groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
  410. if ( ! ( groupHash in this.geometryGroups ) ) {
  411. this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
  412. }
  413. }
  414. this.geometryGroups[ groupHash ].faces3.push( f );
  415. this.geometryGroups[ groupHash ].vertices += 3;
  416. }
  417. this.geometryGroupsList = [];
  418. for ( var g in this.geometryGroups ) {
  419. this.geometryGroups[ g ].id = geometryGroupCounter ++;
  420. this.geometryGroupsList.push( this.geometryGroups[ g ] );
  421. }
  422. };
  423. } )(),
  424. clone: function () {
  425. var geometry = new THREE.Geometry();
  426. var vertices = this.vertices;
  427. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  428. geometry.vertices.push( vertices[ i ].clone() );
  429. }
  430. var faces = this.faces;
  431. for ( var i = 0, il = faces.length; i < il; i ++ ) {
  432. geometry.faces.push( faces[ i ].clone() );
  433. }
  434. var uvs = this.faceVertexUvs[ 0 ];
  435. for ( var i = 0, il = uvs.length; i < il; i ++ ) {
  436. var uv = uvs[ i ], uvCopy = [];
  437. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  438. uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
  439. }
  440. geometry.faceVertexUvs[ 0 ].push( uvCopy );
  441. }
  442. return geometry;
  443. },
  444. dispose: function () {
  445. this.dispatchEvent( { type: 'dispose' } );
  446. }
  447. };
  448. THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
  449. THREE.GeometryIdCount = 0;
粤ICP备19079148号