Geometry.js 22 KB

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