GeometryUtils.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.GeometryUtils = {
  6. // Merge two geometries or geometry and geometry from object (using object's transform)
  7. merge: function ( geometry1, object2 /* mesh | geometry */ ) {
  8. var matrix, matrixRotation,
  9. vertexOffset = geometry1.vertices.length,
  10. uvPosition = geometry1.faceVertexUvs[ 0 ].length,
  11. geometry2 = object2 instanceof THREE.Mesh ? object2.geometry : object2,
  12. vertices1 = geometry1.vertices,
  13. vertices2 = geometry2.vertices,
  14. faces1 = geometry1.faces,
  15. faces2 = geometry2.faces,
  16. uvs1 = geometry1.faceVertexUvs[ 0 ],
  17. uvs2 = geometry2.faceVertexUvs[ 0 ];
  18. var geo1MaterialsMap = {};
  19. for ( var i = 0; i < geometry1.materials.length; i ++ ) {
  20. var id = geometry1.materials[ i ].id;
  21. geo1MaterialsMap[ id ] = i;
  22. }
  23. if ( object2 instanceof THREE.Mesh ) {
  24. object2.matrixAutoUpdate && object2.updateMatrix();
  25. matrix = object2.matrix;
  26. matrixRotation = new THREE.Matrix4();
  27. matrixRotation.extractRotation( matrix, object2.scale );
  28. }
  29. // vertices
  30. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  31. var vertex = vertices2[ i ];
  32. var vertexCopy = vertex.clone();
  33. if ( matrix ) matrix.multiplyVector3( vertexCopy.position );
  34. vertices1.push( vertexCopy );
  35. }
  36. // faces
  37. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  38. var face = faces2[ i ], faceCopy, normal, color,
  39. faceVertexNormals = face.vertexNormals,
  40. faceVertexColors = face.vertexColors;
  41. if ( face instanceof THREE.Face3 ) {
  42. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  43. } else if ( face instanceof THREE.Face4 ) {
  44. faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset );
  45. }
  46. faceCopy.normal.copy( face.normal );
  47. if ( matrixRotation ) matrixRotation.multiplyVector3( faceCopy.normal );
  48. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  49. normal = faceVertexNormals[ j ].clone();
  50. if ( matrixRotation ) matrixRotation.multiplyVector3( normal );
  51. faceCopy.vertexNormals.push( normal );
  52. }
  53. faceCopy.color.copy( face.color );
  54. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  55. color = faceVertexColors[ j ];
  56. faceCopy.vertexColors.push( color.clone() );
  57. }
  58. if ( face.materialIndex !== undefined ) {
  59. var material2 = geometry2.materials[ face.materialIndex ];
  60. var materialId2 = material2.id;
  61. var materialIndex = geo1MaterialsMap[ materialId2 ];
  62. if ( materialIndex === undefined ) {
  63. materialIndex = geometry1.materials.length;
  64. geo1MaterialsMap[ materialId2 ] = materialIndex;
  65. geometry1.materials.push( material2 );
  66. }
  67. faceCopy.materialIndex = materialIndex;
  68. }
  69. faceCopy.centroid.copy( face.centroid );
  70. if ( matrix ) matrix.multiplyVector3( faceCopy.centroid );
  71. faces1.push( faceCopy );
  72. }
  73. // uvs
  74. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  75. var uv = uvs2[ i ], uvCopy = [];
  76. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  77. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  78. }
  79. uvs1.push( uvCopy );
  80. }
  81. },
  82. clone: function ( geometry ) {
  83. var cloneGeo = new THREE.Geometry();
  84. var i, il;
  85. var vertices = geometry.vertices,
  86. faces = geometry.faces,
  87. uvs = geometry.faceVertexUvs[ 0 ];
  88. // materials
  89. if ( geometry.materials ) {
  90. cloneGeo.materials = geometry.materials.slice();
  91. }
  92. // vertices
  93. for ( i = 0, il = vertices.length; i < il; i ++ ) {
  94. var vertex = vertices[ i ];
  95. cloneGeo.vertices.push( vertex.clone() );
  96. }
  97. // faces
  98. for ( i = 0, il = faces.length; i < il; i ++ ) {
  99. var face = faces[ i ];
  100. cloneGeo.faces.push( face.clone() );
  101. }
  102. // uvs
  103. for ( i = 0, il = uvs.length; i < il; i ++ ) {
  104. var uv = uvs[ i ], uvCopy = [];
  105. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  106. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  107. }
  108. cloneGeo.faceVertexUvs[ 0 ].push( uvCopy );
  109. }
  110. return cloneGeo;
  111. },
  112. // Get random point in triangle (via barycentric coordinates)
  113. // (uniform distribution)
  114. // http://www.cgafaq.info/wiki/Random_Point_In_Triangle
  115. randomPointInTriangle: function ( vectorA, vectorB, vectorC ) {
  116. var a, b, c,
  117. point = new THREE.Vector3(),
  118. tmp = THREE.GeometryUtils.__v1;
  119. a = THREE.GeometryUtils.random();
  120. b = THREE.GeometryUtils.random();
  121. if ( ( a + b ) > 1 ) {
  122. a = 1 - a;
  123. b = 1 - b;
  124. }
  125. c = 1 - a - b;
  126. point.copy( vectorA );
  127. point.multiplyScalar( a );
  128. tmp.copy( vectorB );
  129. tmp.multiplyScalar( b );
  130. point.addSelf( tmp );
  131. tmp.copy( vectorC );
  132. tmp.multiplyScalar( c );
  133. point.addSelf( tmp );
  134. return point;
  135. },
  136. // Get random point in face (triangle / quad)
  137. // (uniform distribution)
  138. randomPointInFace: function ( face, geometry, useCachedAreas ) {
  139. var vA, vB, vC, vD;
  140. if ( face instanceof THREE.Face3 ) {
  141. vA = geometry.vertices[ face.a ].position;
  142. vB = geometry.vertices[ face.b ].position;
  143. vC = geometry.vertices[ face.c ].position;
  144. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
  145. } else if ( face instanceof THREE.Face4 ) {
  146. vA = geometry.vertices[ face.a ].position;
  147. vB = geometry.vertices[ face.b ].position;
  148. vC = geometry.vertices[ face.c ].position;
  149. vD = geometry.vertices[ face.d ].position;
  150. var area1, area2;
  151. if ( useCachedAreas ) {
  152. if ( face._area1 && face._area2 ) {
  153. area1 = face._area1;
  154. area2 = face._area2;
  155. } else {
  156. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  157. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  158. face._area1 = area1;
  159. face._area2 = area2;
  160. }
  161. } else {
  162. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
  163. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  164. }
  165. var r = THREE.GeometryUtils.random() * ( area1 + area2 );
  166. if ( r < area1 ) {
  167. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
  168. } else {
  169. return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
  170. }
  171. }
  172. },
  173. // Get uniformly distributed random points in mesh
  174. // - create array with cumulative sums of face areas
  175. // - pick random number from 0 to total area
  176. // - find corresponding place in area array by binary search
  177. // - get random point in face
  178. randomPointsInGeometry: function ( geometry, n ) {
  179. var face, i,
  180. faces = geometry.faces,
  181. vertices = geometry.vertices,
  182. il = faces.length,
  183. totalArea = 0,
  184. cumulativeAreas = [],
  185. vA, vB, vC, vD;
  186. // precompute face areas
  187. for ( i = 0; i < il; i ++ ) {
  188. face = faces[ i ];
  189. if ( face instanceof THREE.Face3 ) {
  190. vA = vertices[ face.a ].position;
  191. vB = vertices[ face.b ].position;
  192. vC = vertices[ face.c ].position;
  193. face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
  194. } else if ( face instanceof THREE.Face4 ) {
  195. vA = vertices[ face.a ].position;
  196. vB = vertices[ face.b ].position;
  197. vC = vertices[ face.c ].position;
  198. vD = vertices[ face.d ].position;
  199. face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  200. face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  201. face._area = face._area1 + face._area2;
  202. }
  203. totalArea += face._area;
  204. cumulativeAreas[ i ] = totalArea;
  205. }
  206. // binary search cumulative areas array
  207. function binarySearchIndices( value ) {
  208. function binarySearch( start, end ) {
  209. // return closest larger index
  210. // if exact number is not found
  211. if ( end < start )
  212. return start;
  213. var mid = start + Math.floor( ( end - start ) / 2 );
  214. if ( cumulativeAreas[ mid ] > value ) {
  215. return binarySearch( start, mid - 1 );
  216. } else if ( cumulativeAreas[ mid ] < value ) {
  217. return binarySearch( mid + 1, end );
  218. } else {
  219. return mid;
  220. }
  221. }
  222. var result = binarySearch( 0, cumulativeAreas.length - 1 )
  223. return result;
  224. }
  225. // pick random face weighted by face area
  226. var r, index,
  227. result = [];
  228. var stats = {};
  229. for ( i = 0; i < n; i ++ ) {
  230. r = THREE.GeometryUtils.random() * totalArea;
  231. index = binarySearchIndices( r );
  232. result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
  233. if ( ! stats[ index ] ) {
  234. stats[ index ] = 1;
  235. } else {
  236. stats[ index ] += 1;
  237. }
  238. }
  239. return result;
  240. },
  241. // Get triangle area (by Heron's formula)
  242. // http://en.wikipedia.org/wiki/Heron%27s_formula
  243. triangleArea: function ( vectorA, vectorB, vectorC ) {
  244. var s, a, b, c,
  245. tmp = THREE.GeometryUtils.__v1;
  246. tmp.sub( vectorA, vectorB );
  247. a = tmp.length();
  248. tmp.sub( vectorA, vectorC );
  249. b = tmp.length();
  250. tmp.sub( vectorB, vectorC );
  251. c = tmp.length();
  252. s = 0.5 * ( a + b + c );
  253. return Math.sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  254. },
  255. // Center geometry so that 0,0,0 is in center of bounding box
  256. center: function ( geometry ) {
  257. geometry.computeBoundingBox();
  258. var bb = geometry.boundingBox;
  259. var offset = new THREE.Vector3();
  260. offset.add( bb.min, bb.max );
  261. offset.multiplyScalar( -0.5 );
  262. geometry.applyMatrix( new THREE.Matrix4().setTranslation( offset.x, offset.y, offset.z ) );
  263. geometry.computeBoundingBox();
  264. return offset;
  265. },
  266. // Normalize UVs to be from <0,1>
  267. // (for now just the first set of UVs)
  268. normalizeUVs: function ( geometry ) {
  269. var uvSet = geometry.faceVertexUvs[ 0 ];
  270. for ( var i = 0, il = uvSet.length; i < il; i ++ ) {
  271. var uvs = uvSet[ i ];
  272. for ( var j = 0, jl = uvs.length; j < jl; j ++ ) {
  273. // texture repeat
  274. if( uvs[ j ].u !== 1.0 ) uvs[ j ].u = uvs[ j ].u - Math.floor( uvs[ j ].u );
  275. if( uvs[ j ].v !== 1.0 ) uvs[ j ].v = uvs[ j ].v - Math.floor( uvs[ j ].v );
  276. }
  277. }
  278. },
  279. triangulateQuads: function ( geometry ) {
  280. for ( var i = geometry.faces.length - 1; i >= 0; i -- ) {
  281. var face = geometry.faces[ i ];
  282. if ( face instanceof THREE.Face4 ) {
  283. var a = face.a;
  284. var b = face.b;
  285. var c = face.c;
  286. var d = face.d;
  287. var triA = face.clone();
  288. var triB = face.clone();
  289. triA.a = a;
  290. triA.b = b;
  291. triA.c = d;
  292. triB.a = b;
  293. triB.b = c;
  294. triB.c = d;
  295. geometry.faces.splice( i, 1, triA, triB );
  296. for ( var j = 0; j < geometry.faceVertexUvs.length; j ++ ) {
  297. if ( geometry.faceVertexUvs[ j ].length ) {
  298. var faceVertexUvs = geometry.faceVertexUvs[ j ][ i ];
  299. var uvA = faceVertexUvs[ 0 ];
  300. var uvB = faceVertexUvs[ 1 ];
  301. var uvC = faceVertexUvs[ 2 ];
  302. var uvD = faceVertexUvs[ 3 ];
  303. var uvsTriA = [ uvA.clone(), uvB.clone(), uvD.clone() ];
  304. var uvsTriB = [ uvB.clone(), uvC.clone(), uvD.clone() ];
  305. geometry.faceVertexUvs[ j ].splice( i, 1, uvsTriA, uvsTriB );
  306. }
  307. }
  308. for ( var j = 0; j < geometry.faceUvs.length; j ++ ) {
  309. if ( geometry.faceUvs[ j ].length ) {
  310. var faceUv = geometry.faceUvs[ j ][ i ];
  311. geometry.faceUvs[ j ].splice( i, 1, faceUv, faceUv );
  312. }
  313. }
  314. }
  315. }
  316. geometry.computeCentroids();
  317. geometry.computeFaceNormals();
  318. geometry.computeVertexNormals();
  319. if ( geometry.hasTangents ) geometry.computeTangents();
  320. },
  321. // Make all faces use unique vertices
  322. // so that each face can be separated from others
  323. explode: function( geometry ) {
  324. var vertices = [];
  325. for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
  326. var n = vertices.length;
  327. var face = geometry.faces[ i ];
  328. if ( face instanceof THREE.Face4 ) {
  329. var a = face.a;
  330. var b = face.b;
  331. var c = face.c;
  332. var d = face.d;
  333. var va = geometry.vertices[ a ];
  334. var vb = geometry.vertices[ b ];
  335. var vc = geometry.vertices[ c ];
  336. var vd = geometry.vertices[ d ];
  337. vertices.push( va.clone() );
  338. vertices.push( vb.clone() );
  339. vertices.push( vc.clone() );
  340. vertices.push( vd.clone() );
  341. face.a = n;
  342. face.b = n + 1;
  343. face.c = n + 2;
  344. face.d = n + 3;
  345. } else {
  346. var a = face.a;
  347. var b = face.b;
  348. var c = face.c;
  349. var va = geometry.vertices[ a ];
  350. var vb = geometry.vertices[ b ];
  351. var vc = geometry.vertices[ c ];
  352. vertices.push( va.clone() );
  353. vertices.push( vb.clone() );
  354. vertices.push( vc.clone() );
  355. face.a = n;
  356. face.b = n + 1;
  357. face.c = n + 2;
  358. }
  359. }
  360. geometry.vertices = vertices;
  361. },
  362. // Break faces with edges longer than maxEdgeLength
  363. // - not recursive
  364. // - doesn't handle yet UVs
  365. tessellate: function ( geometry, maxEdgeLength ) {
  366. var i, face,
  367. a, b, c, d,
  368. va, vb, vc, vd,
  369. dab, dbc, dac, dcd, dad,
  370. m, m1, m2,
  371. vm, vm1, vm2,
  372. triA, triB,
  373. quadA, quadB;
  374. for ( i = geometry.faces.length - 1; i >= 0; i -- ) {
  375. face = geometry.faces[ i ];
  376. if ( face instanceof THREE.Face3 ) {
  377. a = face.a;
  378. b = face.b;
  379. c = face.c;
  380. va = geometry.vertices[ a ];
  381. vb = geometry.vertices[ b ];
  382. vc = geometry.vertices[ c ];
  383. dab = va.position.distanceTo( vb.position );
  384. dbc = vb.position.distanceTo( vc.position );
  385. dac = va.position.distanceTo( vc.position );
  386. if ( dab > maxEdgeLength || dbc > maxEdgeLength || dac > maxEdgeLength ) {
  387. m = geometry.vertices.length;
  388. triA = face.clone();
  389. triB = face.clone();
  390. if ( dab >= dbc && dab >= dac ) {
  391. vm = va.clone();
  392. vm.position.addSelf( vb.position );
  393. vm.position.multiplyScalar( 0.5 );
  394. triA.a = a;
  395. triA.b = m;
  396. triA.c = c;
  397. triB.a = m;
  398. triB.b = b;
  399. triB.c = c;
  400. } else if ( dbc >= dab && dbc >= dac ) {
  401. vm = vb.clone();
  402. vm.position.addSelf( vc.position );
  403. vm.position.multiplyScalar( 0.5 );
  404. triA.a = a;
  405. triA.b = b;
  406. triA.c = m;
  407. triB.a = m;
  408. triB.b = c;
  409. triB.c = a;
  410. } else {
  411. vm = va.clone();
  412. vm.position.addSelf( vc.position );
  413. vm.position.multiplyScalar( 0.5 );
  414. triA.a = a;
  415. triA.b = b;
  416. triA.c = m;
  417. triB.a = m;
  418. triB.b = b;
  419. triB.c = c;
  420. }
  421. geometry.faces.splice( i, 1, triA, triB );
  422. geometry.vertices.push( vm );
  423. }
  424. } else {
  425. a = face.a;
  426. b = face.b;
  427. c = face.c;
  428. d = face.d;
  429. va = geometry.vertices[ a ];
  430. vb = geometry.vertices[ b ];
  431. vc = geometry.vertices[ c ];
  432. vd = geometry.vertices[ d ];
  433. dab = va.position.distanceTo( vb.position );
  434. dbc = vb.position.distanceTo( vc.position );
  435. dcd = vc.position.distanceTo( vd.position );
  436. dad = va.position.distanceTo( vd.position );
  437. if ( dab > maxEdgeLength || dbc > maxEdgeLength || dcd > maxEdgeLength || dad > maxEdgeLength ) {
  438. m1 = geometry.vertices.length;
  439. m2 = geometry.vertices.length + 1;
  440. quadA = face.clone();
  441. quadB = face.clone();
  442. if ( ( dab >= dbc && dab >= dcd && dab >= dad ) || ( dcd >= dbc && dcd >= dab && dcd >= dad ) ) {
  443. vm1 = va.clone();
  444. vm1.position.addSelf( vb.position );
  445. vm1.position.multiplyScalar( 0.5 );
  446. vm2 = vc.clone();
  447. vm2.position.addSelf( vd.position );
  448. vm2.position.multiplyScalar( 0.5 );
  449. quadA.a = a;
  450. quadA.b = m1;
  451. quadA.c = m2;
  452. quadA.d = d;
  453. quadB.a = m1;
  454. quadB.b = b;
  455. quadB.c = c;
  456. quadB.d = m2;
  457. } else {
  458. vm1 = vb.clone();
  459. vm1.position.addSelf( vc.position );
  460. vm1.position.multiplyScalar( 0.5 );
  461. vm2 = vd.clone();
  462. vm2.position.addSelf( va.position );
  463. vm2.position.multiplyScalar( 0.5 );
  464. quadA.a = a;
  465. quadA.b = b;
  466. quadA.c = m1;
  467. quadA.d = m2;
  468. quadB.a = m2;
  469. quadB.b = m1;
  470. quadB.c = c;
  471. quadB.d = d;
  472. }
  473. geometry.faces.splice( i, 1, quadA, quadB );
  474. geometry.vertices.push( vm1 );
  475. geometry.vertices.push( vm2 );
  476. }
  477. }
  478. }
  479. }
  480. };
  481. THREE.GeometryUtils.random = THREE.Math.random16;
  482. THREE.GeometryUtils.__v1 = new THREE.Vector3();