Geometry.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  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. Object.defineProperty( this, 'id', { value: THREE.GeometryIdCount ++ } );
  11. this.uuid = THREE.Math.generateUUID();
  12. this.name = '';
  13. this.type = 'Geometry';
  14. this.vertices = [];
  15. this.colors = [];
  16. this.faces = [];
  17. this.faceVertexUvs = [ [] ];
  18. this.morphTargets = [];
  19. this.morphColors = [];
  20. this.morphNormals = [];
  21. this.skinWeights = [];
  22. this.skinIndices = [];
  23. this.lineDistances = [];
  24. this.boundingBox = null;
  25. this.boundingSphere = null;
  26. this.hasTangents = 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.groupsNeedUpdate = 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 !== null ) {
  53. this.computeBoundingBox();
  54. }
  55. if ( this.boundingSphere !== null ) {
  56. this.computeBoundingSphere();
  57. }
  58. this.verticesNeedUpdate = true;
  59. this.normalsNeedUpdate = true;
  60. },
  61. rotateX: function () {
  62. // rotate geometry around world x-axis
  63. var m1;
  64. return function rotateX( angle ) {
  65. if ( m1 === undefined ) m1 = new THREE.Matrix4();
  66. m1.makeRotationX( angle );
  67. this.applyMatrix( m1 );
  68. return this;
  69. };
  70. }(),
  71. rotateY: function () {
  72. // rotate geometry around world y-axis
  73. var m1;
  74. return function rotateY( angle ) {
  75. if ( m1 === undefined ) m1 = new THREE.Matrix4();
  76. m1.makeRotationY( angle );
  77. this.applyMatrix( m1 );
  78. return this;
  79. };
  80. }(),
  81. rotateZ: function () {
  82. // rotate geometry around world z-axis
  83. var m1;
  84. return function rotateZ( angle ) {
  85. if ( m1 === undefined ) m1 = new THREE.Matrix4();
  86. m1.makeRotationZ( angle );
  87. this.applyMatrix( m1 );
  88. return this;
  89. };
  90. }(),
  91. translate: function () {
  92. // translate geometry
  93. var m1;
  94. return function translate( x, y, z ) {
  95. if ( m1 === undefined ) m1 = new THREE.Matrix4();
  96. m1.makeTranslation( x, y, z );
  97. this.applyMatrix( m1 );
  98. return this;
  99. };
  100. }(),
  101. scale: function () {
  102. // scale geometry
  103. var m1;
  104. return function scale( x, y, z ) {
  105. if ( m1 === undefined ) m1 = new THREE.Matrix4();
  106. m1.makeScale( x, y, z );
  107. this.applyMatrix( m1 );
  108. return this;
  109. };
  110. }(),
  111. lookAt: function () {
  112. var obj;
  113. return function lookAt( vector ) {
  114. if ( obj === undefined ) obj = new THREE.Object3D();
  115. obj.lookAt( vector );
  116. obj.updateMatrix();
  117. this.applyMatrix( obj.matrix );
  118. };
  119. }(),
  120. fromBufferGeometry: function ( geometry ) {
  121. var scope = this;
  122. var indices = geometry.index !== null ? geometry.index.array : undefined;
  123. var attributes = geometry.attributes;
  124. var vertices = attributes.position.array;
  125. var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
  126. var colors = attributes.color !== undefined ? attributes.color.array : undefined;
  127. var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
  128. var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
  129. var tangents = attributes.tangent !== undefined ? attributes.tangent.array : undefined;
  130. if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
  131. if ( tangents !== undefined ) this.hasTangents = true;
  132. var tempNormals = [];
  133. var tempUVs = [];
  134. var tempUVs2 = [];
  135. var tempTangents = [];
  136. for ( var i = 0, j = 0, k = 0; i < vertices.length; i += 3, j += 2, k += 4 ) {
  137. scope.vertices.push( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
  138. if ( normals !== undefined ) {
  139. tempNormals.push( new THREE.Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) );
  140. }
  141. if ( colors !== undefined ) {
  142. scope.colors.push( new THREE.Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) );
  143. }
  144. if ( uvs !== undefined ) {
  145. tempUVs.push( new THREE.Vector2( uvs[ j ], uvs[ j + 1 ] ) );
  146. }
  147. if ( uvs2 !== undefined ) {
  148. tempUVs2.push( new THREE.Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
  149. }
  150. if ( tangents !== undefined ) {
  151. tempTangents.push( new THREE.Vector4( tangents[ k ], tangents[ k + 1 ], tangents[ k + 2 ], tangents[ k + 3 ] ) );
  152. }
  153. }
  154. var addFace = function ( a, b, c ) {
  155. var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
  156. var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
  157. var face = new THREE.Face3( a, b, c, vertexNormals, vertexColors );
  158. scope.faces.push( face );
  159. if ( uvs !== undefined ) {
  160. scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] );
  161. }
  162. if ( uvs2 !== undefined ) {
  163. scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
  164. }
  165. if ( tangents !== undefined ) {
  166. face.vertexTangents.push( tempTangents[ a ].clone(), tempTangents[ b ].clone(), tempTangents[ c ].clone() );
  167. }
  168. };
  169. if ( indices !== undefined ) {
  170. var groups = geometry.groups;
  171. if ( groups.length > 0 ) {
  172. for ( var i = 0; i < groups.length; i ++ ) {
  173. var group = groups[ i ];
  174. var start = group.start;
  175. var count = group.count;
  176. for ( var j = start, jl = start + count; j < jl; j += 3 ) {
  177. addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ] );
  178. }
  179. }
  180. } else {
  181. for ( var i = 0; i < indices.length; i += 3 ) {
  182. addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
  183. }
  184. }
  185. } else {
  186. for ( var i = 0; i < vertices.length / 3; i += 3 ) {
  187. addFace( i, i + 1, i + 2 );
  188. }
  189. }
  190. this.computeFaceNormals();
  191. if ( geometry.boundingBox !== null ) {
  192. this.boundingBox = geometry.boundingBox.clone();
  193. }
  194. if ( geometry.boundingSphere !== null ) {
  195. this.boundingSphere = geometry.boundingSphere.clone();
  196. }
  197. return this;
  198. },
  199. center: function () {
  200. this.computeBoundingBox();
  201. var offset = this.boundingBox.center().negate();
  202. this.translate( offset.x, offset.y, offset.z );
  203. return offset;
  204. },
  205. normalize: function () {
  206. this.computeBoundingSphere();
  207. var center = this.boundingSphere.center;
  208. var radius = this.boundingSphere.radius;
  209. var s = radius === 0 ? 1 : 1.0 / radius;
  210. var matrix = new THREE.Matrix4();
  211. matrix.set(
  212. s, 0, 0, - s * center.x,
  213. 0, s, 0, - s * center.y,
  214. 0, 0, s, - s * center.z,
  215. 0, 0, 0, 1
  216. );
  217. this.applyMatrix( matrix );
  218. return this;
  219. },
  220. computeFaceNormals: function () {
  221. var cb = new THREE.Vector3(), ab = new THREE.Vector3();
  222. for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
  223. var face = this.faces[ f ];
  224. var vA = this.vertices[ face.a ];
  225. var vB = this.vertices[ face.b ];
  226. var vC = this.vertices[ face.c ];
  227. cb.subVectors( vC, vB );
  228. ab.subVectors( vA, vB );
  229. cb.cross( ab );
  230. cb.normalize();
  231. face.normal.copy( cb );
  232. }
  233. },
  234. computeVertexNormals: function ( areaWeighted ) {
  235. var v, vl, f, fl, face, vertices;
  236. vertices = new Array( this.vertices.length );
  237. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  238. vertices[ v ] = new THREE.Vector3();
  239. }
  240. if ( areaWeighted ) {
  241. // vertex normals weighted by triangle areas
  242. // http://www.iquilezles.org/www/articles/normals/normals.htm
  243. var vA, vB, vC;
  244. var cb = new THREE.Vector3(), ab = new THREE.Vector3();
  245. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  246. face = this.faces[ f ];
  247. vA = this.vertices[ face.a ];
  248. vB = this.vertices[ face.b ];
  249. vC = this.vertices[ face.c ];
  250. cb.subVectors( vC, vB );
  251. ab.subVectors( vA, vB );
  252. cb.cross( ab );
  253. vertices[ face.a ].add( cb );
  254. vertices[ face.b ].add( cb );
  255. vertices[ face.c ].add( cb );
  256. }
  257. } else {
  258. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  259. face = this.faces[ f ];
  260. vertices[ face.a ].add( face.normal );
  261. vertices[ face.b ].add( face.normal );
  262. vertices[ face.c ].add( face.normal );
  263. }
  264. }
  265. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  266. vertices[ v ].normalize();
  267. }
  268. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  269. face = this.faces[ f ];
  270. var vertexNormals = face.vertexNormals;
  271. if ( vertexNormals.length === 3 ) {
  272. vertexNormals[ 0 ].copy( vertices[ face.a ] );
  273. vertexNormals[ 1 ].copy( vertices[ face.b ] );
  274. vertexNormals[ 2 ].copy( vertices[ face.c ] );
  275. } else {
  276. vertexNormals[ 0 ] = vertices[ face.a ].clone();
  277. vertexNormals[ 1 ] = vertices[ face.b ].clone();
  278. vertexNormals[ 2 ] = vertices[ face.c ].clone();
  279. }
  280. }
  281. },
  282. computeMorphNormals: function () {
  283. var i, il, f, fl, face;
  284. // save original normals
  285. // - create temp variables on first access
  286. // otherwise just copy (for faster repeated calls)
  287. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  288. face = this.faces[ f ];
  289. if ( ! face.__originalFaceNormal ) {
  290. face.__originalFaceNormal = face.normal.clone();
  291. } else {
  292. face.__originalFaceNormal.copy( face.normal );
  293. }
  294. if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
  295. for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
  296. if ( ! face.__originalVertexNormals[ i ] ) {
  297. face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
  298. } else {
  299. face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
  300. }
  301. }
  302. }
  303. // use temp geometry to compute face and vertex normals for each morph
  304. var tmpGeo = new THREE.Geometry();
  305. tmpGeo.faces = this.faces;
  306. for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
  307. // create on first access
  308. if ( ! this.morphNormals[ i ] ) {
  309. this.morphNormals[ i ] = {};
  310. this.morphNormals[ i ].faceNormals = [];
  311. this.morphNormals[ i ].vertexNormals = [];
  312. var dstNormalsFace = this.morphNormals[ i ].faceNormals;
  313. var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
  314. var faceNormal, vertexNormals;
  315. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  316. faceNormal = new THREE.Vector3();
  317. vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
  318. dstNormalsFace.push( faceNormal );
  319. dstNormalsVertex.push( vertexNormals );
  320. }
  321. }
  322. var morphNormals = this.morphNormals[ i ];
  323. // set vertices to morph target
  324. tmpGeo.vertices = this.morphTargets[ i ].vertices;
  325. // compute morph normals
  326. tmpGeo.computeFaceNormals();
  327. tmpGeo.computeVertexNormals();
  328. // store morph normals
  329. var faceNormal, vertexNormals;
  330. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  331. face = this.faces[ f ];
  332. faceNormal = morphNormals.faceNormals[ f ];
  333. vertexNormals = morphNormals.vertexNormals[ f ];
  334. faceNormal.copy( face.normal );
  335. vertexNormals.a.copy( face.vertexNormals[ 0 ] );
  336. vertexNormals.b.copy( face.vertexNormals[ 1 ] );
  337. vertexNormals.c.copy( face.vertexNormals[ 2 ] );
  338. }
  339. }
  340. // restore original normals
  341. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  342. face = this.faces[ f ];
  343. face.normal = face.__originalFaceNormal;
  344. face.vertexNormals = face.__originalVertexNormals;
  345. }
  346. },
  347. computeTangents: function () {
  348. // based on http://www.terathon.com/code/tangent.html
  349. // tangents go to vertices
  350. var f, fl, v, vl, i, vertexIndex,
  351. face, uv, vA, vB, vC, uvA, uvB, uvC,
  352. x1, x2, y1, y2, z1, z2,
  353. s1, s2, t1, t2, r, t, test,
  354. tan1 = [], tan2 = [],
  355. sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
  356. tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
  357. n = new THREE.Vector3(), w;
  358. for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
  359. tan1[ v ] = new THREE.Vector3();
  360. tan2[ v ] = new THREE.Vector3();
  361. }
  362. function handleTriangle( context, a, b, c, ua, ub, uc ) {
  363. vA = context.vertices[ a ];
  364. vB = context.vertices[ b ];
  365. vC = context.vertices[ c ];
  366. uvA = uv[ ua ];
  367. uvB = uv[ ub ];
  368. uvC = uv[ uc ];
  369. x1 = vB.x - vA.x;
  370. x2 = vC.x - vA.x;
  371. y1 = vB.y - vA.y;
  372. y2 = vC.y - vA.y;
  373. z1 = vB.z - vA.z;
  374. z2 = vC.z - vA.z;
  375. s1 = uvB.x - uvA.x;
  376. s2 = uvC.x - uvA.x;
  377. t1 = uvB.y - uvA.y;
  378. t2 = uvC.y - uvA.y;
  379. r = 1.0 / ( s1 * t2 - s2 * t1 );
  380. sdir.set( ( t2 * x1 - t1 * x2 ) * r,
  381. ( t2 * y1 - t1 * y2 ) * r,
  382. ( t2 * z1 - t1 * z2 ) * r );
  383. tdir.set( ( s1 * x2 - s2 * x1 ) * r,
  384. ( s1 * y2 - s2 * y1 ) * r,
  385. ( s1 * z2 - s2 * z1 ) * r );
  386. tan1[ a ].add( sdir );
  387. tan1[ b ].add( sdir );
  388. tan1[ c ].add( sdir );
  389. tan2[ a ].add( tdir );
  390. tan2[ b ].add( tdir );
  391. tan2[ c ].add( tdir );
  392. }
  393. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  394. face = this.faces[ f ];
  395. uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
  396. handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
  397. }
  398. var faceIndex = [ 'a', 'b', 'c', 'd' ];
  399. for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
  400. face = this.faces[ f ];
  401. for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i ++ ) {
  402. n.copy( face.vertexNormals[ i ] );
  403. vertexIndex = face[ faceIndex[ i ] ];
  404. t = tan1[ vertexIndex ];
  405. // Gram-Schmidt orthogonalize
  406. tmp.copy( t );
  407. tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
  408. // Calculate handedness
  409. tmp2.crossVectors( face.vertexNormals[ i ], t );
  410. test = tmp2.dot( tan2[ vertexIndex ] );
  411. w = ( test < 0.0 ) ? - 1.0 : 1.0;
  412. face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
  413. }
  414. }
  415. this.hasTangents = true;
  416. },
  417. computeLineDistances: function () {
  418. var d = 0;
  419. var vertices = this.vertices;
  420. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  421. if ( i > 0 ) {
  422. d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
  423. }
  424. this.lineDistances[ i ] = d;
  425. }
  426. },
  427. computeBoundingBox: function () {
  428. if ( this.boundingBox === null ) {
  429. this.boundingBox = new THREE.Box3();
  430. }
  431. this.boundingBox.setFromPoints( this.vertices );
  432. },
  433. computeBoundingSphere: function () {
  434. if ( this.boundingSphere === null ) {
  435. this.boundingSphere = new THREE.Sphere();
  436. }
  437. this.boundingSphere.setFromPoints( this.vertices );
  438. },
  439. merge: function ( geometry, matrix, materialIndexOffset ) {
  440. if ( geometry instanceof THREE.Geometry === false ) {
  441. console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
  442. return;
  443. }
  444. var normalMatrix,
  445. vertexOffset = this.vertices.length,
  446. vertices1 = this.vertices,
  447. vertices2 = geometry.vertices,
  448. faces1 = this.faces,
  449. faces2 = geometry.faces,
  450. uvs1 = this.faceVertexUvs[ 0 ],
  451. uvs2 = geometry.faceVertexUvs[ 0 ];
  452. if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
  453. if ( matrix !== undefined ) {
  454. normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
  455. }
  456. // vertices
  457. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  458. var vertex = vertices2[ i ];
  459. var vertexCopy = vertex.clone();
  460. if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
  461. vertices1.push( vertexCopy );
  462. }
  463. // faces
  464. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  465. var face = faces2[ i ], faceCopy, normal, color,
  466. faceVertexNormals = face.vertexNormals,
  467. faceVertexColors = face.vertexColors;
  468. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  469. faceCopy.normal.copy( face.normal );
  470. if ( normalMatrix !== undefined ) {
  471. faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
  472. }
  473. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  474. normal = faceVertexNormals[ j ].clone();
  475. if ( normalMatrix !== undefined ) {
  476. normal.applyMatrix3( normalMatrix ).normalize();
  477. }
  478. faceCopy.vertexNormals.push( normal );
  479. }
  480. faceCopy.color.copy( face.color );
  481. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  482. color = faceVertexColors[ j ];
  483. faceCopy.vertexColors.push( color.clone() );
  484. }
  485. faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
  486. faces1.push( faceCopy );
  487. }
  488. // uvs
  489. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  490. var uv = uvs2[ i ], uvCopy = [];
  491. if ( uv === undefined ) {
  492. continue;
  493. }
  494. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  495. uvCopy.push( uv[ j ].clone() );
  496. }
  497. uvs1.push( uvCopy );
  498. }
  499. },
  500. mergeMesh: function ( mesh ) {
  501. if ( mesh instanceof THREE.Mesh === false ) {
  502. console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
  503. return;
  504. }
  505. mesh.matrixAutoUpdate && mesh.updateMatrix();
  506. this.merge( mesh.geometry, mesh.matrix );
  507. },
  508. /*
  509. * Checks for duplicate vertices with hashmap.
  510. * Duplicated vertices are removed
  511. * and faces' vertices are updated.
  512. */
  513. mergeVertices: function () {
  514. var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
  515. var unique = [], changes = [];
  516. var v, key;
  517. var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
  518. var precision = Math.pow( 10, precisionPoints );
  519. var i, il, face;
  520. var indices, j, jl;
  521. for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
  522. v = this.vertices[ i ];
  523. key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
  524. if ( verticesMap[ key ] === undefined ) {
  525. verticesMap[ key ] = i;
  526. unique.push( this.vertices[ i ] );
  527. changes[ i ] = unique.length - 1;
  528. } else {
  529. //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
  530. changes[ i ] = changes[ verticesMap[ key ] ];
  531. }
  532. }
  533. // if faces are completely degenerate after merging vertices, we
  534. // have to remove them from the geometry.
  535. var faceIndicesToRemove = [];
  536. for ( i = 0, il = this.faces.length; i < il; i ++ ) {
  537. face = this.faces[ i ];
  538. face.a = changes[ face.a ];
  539. face.b = changes[ face.b ];
  540. face.c = changes[ face.c ];
  541. indices = [ face.a, face.b, face.c ];
  542. var dupIndex = - 1;
  543. // if any duplicate vertices are found in a Face3
  544. // we have to remove the face as nothing can be saved
  545. for ( var n = 0; n < 3; n ++ ) {
  546. if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
  547. dupIndex = n;
  548. faceIndicesToRemove.push( i );
  549. break;
  550. }
  551. }
  552. }
  553. for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
  554. var idx = faceIndicesToRemove[ i ];
  555. this.faces.splice( idx, 1 );
  556. for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
  557. this.faceVertexUvs[ j ].splice( idx, 1 );
  558. }
  559. }
  560. // Use unique set of vertices
  561. var diff = this.vertices.length - unique.length;
  562. this.vertices = unique;
  563. return diff;
  564. },
  565. toJSON: function () {
  566. var data = {
  567. metadata: {
  568. version: 4.4,
  569. type: 'Geometry',
  570. generator: 'Geometry.toJSON'
  571. }
  572. };
  573. // standard Geometry serialization
  574. data.uuid = this.uuid;
  575. data.type = this.type;
  576. if ( this.name !== '' ) data.name = this.name;
  577. if ( this.parameters !== undefined ) {
  578. var parameters = this.parameters;
  579. for ( var key in parameters ) {
  580. if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
  581. }
  582. return data;
  583. }
  584. var vertices = [];
  585. for ( var i = 0; i < this.vertices.length; i ++ ) {
  586. var vertex = this.vertices[ i ];
  587. vertices.push( vertex.x, vertex.y, vertex.z );
  588. }
  589. var faces = [];
  590. var normals = [];
  591. var normalsHash = {};
  592. var colors = [];
  593. var colorsHash = {};
  594. var uvs = [];
  595. var uvsHash = {};
  596. for ( var i = 0; i < this.faces.length; i ++ ) {
  597. var face = this.faces[ i ];
  598. var hasMaterial = false; // face.materialIndex !== undefined;
  599. var hasFaceUv = false; // deprecated
  600. var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
  601. var hasFaceNormal = face.normal.length() > 0;
  602. var hasFaceVertexNormal = face.vertexNormals.length > 0;
  603. var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
  604. var hasFaceVertexColor = face.vertexColors.length > 0;
  605. var faceType = 0;
  606. faceType = setBit( faceType, 0, 0 );
  607. faceType = setBit( faceType, 1, hasMaterial );
  608. faceType = setBit( faceType, 2, hasFaceUv );
  609. faceType = setBit( faceType, 3, hasFaceVertexUv );
  610. faceType = setBit( faceType, 4, hasFaceNormal );
  611. faceType = setBit( faceType, 5, hasFaceVertexNormal );
  612. faceType = setBit( faceType, 6, hasFaceColor );
  613. faceType = setBit( faceType, 7, hasFaceVertexColor );
  614. faces.push( faceType );
  615. faces.push( face.a, face.b, face.c );
  616. if ( hasFaceVertexUv ) {
  617. var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
  618. faces.push(
  619. getUvIndex( faceVertexUvs[ 0 ] ),
  620. getUvIndex( faceVertexUvs[ 1 ] ),
  621. getUvIndex( faceVertexUvs[ 2 ] )
  622. );
  623. }
  624. if ( hasFaceNormal ) {
  625. faces.push( getNormalIndex( face.normal ) );
  626. }
  627. if ( hasFaceVertexNormal ) {
  628. var vertexNormals = face.vertexNormals;
  629. faces.push(
  630. getNormalIndex( vertexNormals[ 0 ] ),
  631. getNormalIndex( vertexNormals[ 1 ] ),
  632. getNormalIndex( vertexNormals[ 2 ] )
  633. );
  634. }
  635. if ( hasFaceColor ) {
  636. faces.push( getColorIndex( face.color ) );
  637. }
  638. if ( hasFaceVertexColor ) {
  639. var vertexColors = face.vertexColors;
  640. faces.push(
  641. getColorIndex( vertexColors[ 0 ] ),
  642. getColorIndex( vertexColors[ 1 ] ),
  643. getColorIndex( vertexColors[ 2 ] )
  644. );
  645. }
  646. }
  647. function setBit( value, position, enabled ) {
  648. return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
  649. }
  650. function getNormalIndex( normal ) {
  651. var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
  652. if ( normalsHash[ hash ] !== undefined ) {
  653. return normalsHash[ hash ];
  654. }
  655. normalsHash[ hash ] = normals.length / 3;
  656. normals.push( normal.x, normal.y, normal.z );
  657. return normalsHash[ hash ];
  658. }
  659. function getColorIndex( color ) {
  660. var hash = color.r.toString() + color.g.toString() + color.b.toString();
  661. if ( colorsHash[ hash ] !== undefined ) {
  662. return colorsHash[ hash ];
  663. }
  664. colorsHash[ hash ] = colors.length;
  665. colors.push( color.getHex() );
  666. return colorsHash[ hash ];
  667. }
  668. function getUvIndex( uv ) {
  669. var hash = uv.x.toString() + uv.y.toString();
  670. if ( uvsHash[ hash ] !== undefined ) {
  671. return uvsHash[ hash ];
  672. }
  673. uvsHash[ hash ] = uvs.length / 2;
  674. uvs.push( uv.x, uv.y );
  675. return uvsHash[ hash ];
  676. }
  677. data.data = {};
  678. data.data.vertices = vertices;
  679. data.data.normals = normals;
  680. if ( colors.length > 0 ) data.data.colors = colors;
  681. if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
  682. data.data.faces = faces;
  683. return data;
  684. },
  685. clone: function () {
  686. return new this.constructor().copy( this );
  687. },
  688. copy: function ( source ) {
  689. this.vertices = [];
  690. this.faces = [];
  691. this.faceVertexUvs = [ [] ];
  692. var vertices = source.vertices;
  693. for ( var i = 0, il = vertices.length; i < il; i ++ ) {
  694. this.vertices.push( vertices[ i ].clone() );
  695. }
  696. var faces = source.faces;
  697. for ( var i = 0, il = faces.length; i < il; i ++ ) {
  698. this.faces.push( faces[ i ].clone() );
  699. }
  700. for ( var i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
  701. var faceVertexUvs = source.faceVertexUvs[ i ];
  702. if ( this.faceVertexUvs[ i ] === undefined ) {
  703. this.faceVertexUvs[ i ] = [];
  704. }
  705. for ( var j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
  706. var uvs = faceVertexUvs[ j ], uvsCopy = [];
  707. for ( var k = 0, kl = uvs.length; k < kl; k ++ ) {
  708. var uv = uvs[ k ];
  709. uvsCopy.push( uv.clone() );
  710. }
  711. this.faceVertexUvs[ i ].push( uvsCopy );
  712. }
  713. }
  714. return this;
  715. },
  716. dispose: function () {
  717. this.dispatchEvent( { type: 'dispose' } );
  718. }
  719. };
  720. THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
  721. THREE.GeometryIdCount = 0;