GeometryUtils.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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. var vertexCopy = new THREE.Vertex( vertex.position.clone() );
  96. cloneGeo.vertices.push( vertexCopy );
  97. }
  98. // faces
  99. for ( i = 0, il = faces.length; i < il; i ++ ) {
  100. var face = faces[ i ], faceCopy, normal, color,
  101. faceVertexNormals = face.vertexNormals,
  102. faceVertexColors = face.vertexColors;
  103. if ( face instanceof THREE.Face3 ) {
  104. faceCopy = new THREE.Face3( face.a, face.b, face.c );
  105. } else if ( face instanceof THREE.Face4 ) {
  106. faceCopy = new THREE.Face4( face.a, face.b, face.c, face.d );
  107. }
  108. faceCopy.normal.copy( face.normal );
  109. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  110. normal = faceVertexNormals[ j ];
  111. faceCopy.vertexNormals.push( normal.clone() );
  112. }
  113. faceCopy.color.copy( face.color );
  114. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  115. color = faceVertexColors[ j ];
  116. faceCopy.vertexColors.push( color.clone() );
  117. }
  118. faceCopy.materialIndex = face.materialIndex;
  119. faceCopy.centroid.copy( face.centroid );
  120. cloneGeo.faces.push( faceCopy );
  121. }
  122. // uvs
  123. for ( i = 0, il = uvs.length; i < il; i ++ ) {
  124. var uv = uvs[ i ], uvCopy = [];
  125. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  126. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  127. }
  128. cloneGeo.faceVertexUvs[ 0 ].push( uvCopy );
  129. }
  130. return cloneGeo;
  131. },
  132. // Get random point in triangle (via barycentric coordinates)
  133. // (uniform distribution)
  134. // http://www.cgafaq.info/wiki/Random_Point_In_Triangle
  135. randomPointInTriangle: function ( vectorA, vectorB, vectorC ) {
  136. var a, b, c,
  137. point = new THREE.Vector3(),
  138. tmp = THREE.GeometryUtils.__v1;
  139. a = THREE.GeometryUtils.random();
  140. b = THREE.GeometryUtils.random();
  141. if ( ( a + b ) > 1 ) {
  142. a = 1 - a;
  143. b = 1 - b;
  144. }
  145. c = 1 - a - b;
  146. point.copy( vectorA );
  147. point.multiplyScalar( a );
  148. tmp.copy( vectorB );
  149. tmp.multiplyScalar( b );
  150. point.addSelf( tmp );
  151. tmp.copy( vectorC );
  152. tmp.multiplyScalar( c );
  153. point.addSelf( tmp );
  154. return point;
  155. },
  156. // Get random point in face (triangle / quad)
  157. // (uniform distribution)
  158. randomPointInFace: function ( face, geometry, useCachedAreas ) {
  159. var vA, vB, vC, vD;
  160. if ( face instanceof THREE.Face3 ) {
  161. vA = geometry.vertices[ face.a ].position;
  162. vB = geometry.vertices[ face.b ].position;
  163. vC = geometry.vertices[ face.c ].position;
  164. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
  165. } else if ( face instanceof THREE.Face4 ) {
  166. vA = geometry.vertices[ face.a ].position;
  167. vB = geometry.vertices[ face.b ].position;
  168. vC = geometry.vertices[ face.c ].position;
  169. vD = geometry.vertices[ face.d ].position;
  170. var area1, area2;
  171. if ( useCachedAreas ) {
  172. if ( face._area1 && face._area2 ) {
  173. area1 = face._area1;
  174. area2 = face._area2;
  175. } else {
  176. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  177. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  178. face._area1 = area1;
  179. face._area2 = area2;
  180. }
  181. } else {
  182. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
  183. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  184. }
  185. var r = THREE.GeometryUtils.random() * ( area1 + area2 );
  186. if ( r < area1 ) {
  187. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
  188. } else {
  189. return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
  190. }
  191. }
  192. },
  193. // Get uniformly distributed random points in mesh
  194. // - create array with cumulative sums of face areas
  195. // - pick random number from 0 to total area
  196. // - find corresponding place in area array by binary search
  197. // - get random point in face
  198. randomPointsInGeometry: function ( geometry, n ) {
  199. var face, i,
  200. faces = geometry.faces,
  201. vertices = geometry.vertices,
  202. il = faces.length,
  203. totalArea = 0,
  204. cumulativeAreas = [],
  205. vA, vB, vC, vD;
  206. // precompute face areas
  207. for ( i = 0; i < il; i ++ ) {
  208. face = faces[ i ];
  209. if ( face instanceof THREE.Face3 ) {
  210. vA = vertices[ face.a ].position;
  211. vB = vertices[ face.b ].position;
  212. vC = vertices[ face.c ].position;
  213. face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
  214. } else if ( face instanceof THREE.Face4 ) {
  215. vA = vertices[ face.a ].position;
  216. vB = vertices[ face.b ].position;
  217. vC = vertices[ face.c ].position;
  218. vD = vertices[ face.d ].position;
  219. face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  220. face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  221. face._area = face._area1 + face._area2;
  222. }
  223. totalArea += face._area;
  224. cumulativeAreas[ i ] = totalArea;
  225. }
  226. // binary search cumulative areas array
  227. function binarySearchIndices( value ) {
  228. function binarySearch( start, end ) {
  229. // return closest larger index
  230. // if exact number is not found
  231. if ( end < start )
  232. return start;
  233. var mid = start + Math.floor( ( end - start ) / 2 );
  234. if ( cumulativeAreas[ mid ] > value ) {
  235. return binarySearch( start, mid - 1 );
  236. } else if ( cumulativeAreas[ mid ] < value ) {
  237. return binarySearch( mid + 1, end );
  238. } else {
  239. return mid;
  240. }
  241. }
  242. var result = binarySearch( 0, cumulativeAreas.length - 1 )
  243. return result;
  244. }
  245. // pick random face weighted by face area
  246. var r, index,
  247. result = [];
  248. var stats = {};
  249. for ( i = 0; i < n; i ++ ) {
  250. r = THREE.GeometryUtils.random() * totalArea;
  251. index = binarySearchIndices( r );
  252. result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
  253. if ( ! stats[ index ] ) {
  254. stats[ index ] = 1;
  255. } else {
  256. stats[ index ] += 1;
  257. }
  258. }
  259. return result;
  260. },
  261. // Get triangle area (by Heron's formula)
  262. // http://en.wikipedia.org/wiki/Heron%27s_formula
  263. triangleArea: function ( vectorA, vectorB, vectorC ) {
  264. var s, a, b, c,
  265. tmp = THREE.GeometryUtils.__v1;
  266. tmp.sub( vectorA, vectorB );
  267. a = tmp.length();
  268. tmp.sub( vectorA, vectorC );
  269. b = tmp.length();
  270. tmp.sub( vectorB, vectorC );
  271. c = tmp.length();
  272. s = 0.5 * ( a + b + c );
  273. return Math.sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  274. },
  275. // Center geometry so that 0,0,0 is in center of bounding box
  276. center: function ( geometry ) {
  277. geometry.computeBoundingBox();
  278. var bb = geometry.boundingBox;
  279. var offset = new THREE.Vector3();
  280. offset.add( bb.min, bb.max );
  281. offset.multiplyScalar( -0.5 );
  282. geometry.applyMatrix( new THREE.Matrix4().setTranslation( offset.x, offset.y, offset.z ) );
  283. geometry.computeBoundingBox();
  284. return offset;
  285. },
  286. // Normalize UVs to be from <0,1>
  287. // (for now just the first set of UVs)
  288. normalizeUVs: function ( geometry ) {
  289. var uvSet = geometry.faceVertexUvs[ 0 ];
  290. for ( var i = 0, il = uvSet.length; i < il; i ++ ) {
  291. var uvs = uvSet[ i ];
  292. for ( var j = 0, jl = uvs.length; j < jl; j ++ ) {
  293. // texture repeat
  294. if( uvs[ j ].u !== 1.0 ) uvs[ j ].u = uvs[ j ].u - Math.floor( uvs[ j ].u );
  295. if( uvs[ j ].v !== 1.0 ) uvs[ j ].v = uvs[ j ].v - Math.floor( uvs[ j ].v );
  296. }
  297. }
  298. },
  299. triangulateQuads: function ( geometry ) {
  300. for ( var i = geometry.faces.length - 1; i >= 0; i -- ) {
  301. var face = geometry.faces[ i ];
  302. if ( face instanceof THREE.Face4 ) {
  303. var a = face.a;
  304. var b = face.b;
  305. var c = face.c;
  306. var d = face.d;
  307. var triA = new THREE.Face3( a, b, d );
  308. var triB = new THREE.Face3( b, c, d );
  309. triA.materialIndex = triB.materialIndex = face.materialIndex;
  310. triA.color.copy( face.color );
  311. triB.color.copy( face.color );
  312. if ( face.vertexColors.length === 4 ) {
  313. var cA = face.vertexColors[ 0 ];
  314. var cB = face.vertexColors[ 1 ];
  315. var cC = face.vertexColors[ 2 ];
  316. var cD = face.vertexColors[ 3 ];
  317. triA.vertexColors[ 0 ] = cA.clone();
  318. triA.vertexColors[ 1 ] = cB.clone();
  319. triA.vertexColors[ 2 ] = cD.clone();
  320. triB.vertexColors[ 0 ] = cB.clone();
  321. triB.vertexColors[ 1 ] = cC.clone();
  322. triB.vertexColors[ 2 ] = cD.clone();
  323. }
  324. geometry.faces.splice( i, 1, triA, triB );
  325. for ( var j = 0; j < geometry.faceVertexUvs.length; j ++ ) {
  326. if ( geometry.faceVertexUvs[ j ].length ) {
  327. var faceVertexUvs = geometry.faceVertexUvs[ j ][ i ];
  328. var uvA = faceVertexUvs[ 0 ];
  329. var uvB = faceVertexUvs[ 1 ];
  330. var uvC = faceVertexUvs[ 2 ];
  331. var uvD = faceVertexUvs[ 3 ];
  332. var uvsTriA = [ uvA.clone(), uvB.clone(), uvD.clone() ];
  333. var uvsTriB = [ uvB.clone(), uvC.clone(), uvD.clone() ];
  334. geometry.faceVertexUvs[ j ].splice( i, 1, uvsTriA, uvsTriB );
  335. }
  336. }
  337. for ( var j = 0; j < geometry.faceUvs.length; j ++ ) {
  338. if ( geometry.faceUvs[ j ].length ) {
  339. var faceUv = geometry.faceUvs[ j ][ i ];
  340. geometry.faceUvs[ j ].splice( i, 1, faceUv, faceUv );
  341. }
  342. }
  343. }
  344. }
  345. geometry.computeCentroids();
  346. geometry.computeFaceNormals();
  347. geometry.computeVertexNormals();
  348. if ( geometry.hasTangents ) geometry.computeTangents();
  349. },
  350. // Make all faces use unique vertices
  351. // so that each face can be separated from others
  352. explode: function( geometry ) {
  353. var vertices = [];
  354. for ( var i = geometry.faces.length - 1; i >= 0; i -- ) {
  355. var n = vertices.length;
  356. var face = geometry.faces[ i ];
  357. if ( face instanceof THREE.Face4 ) {
  358. var a = face.a;
  359. var b = face.b;
  360. var c = face.c;
  361. var d = face.d;
  362. var va = geometry.vertices[ a ];
  363. var vb = geometry.vertices[ b ];
  364. var vc = geometry.vertices[ c ];
  365. var vd = geometry.vertices[ d ];
  366. vertices.push( va.clone() );
  367. vertices.push( vb.clone() );
  368. vertices.push( vc.clone() );
  369. vertices.push( vd.clone() );
  370. face.a = n;
  371. face.b = n + 1;
  372. face.c = n + 2;
  373. face.d = n + 3;
  374. } else {
  375. var a = face.a;
  376. var b = face.b;
  377. var c = face.c;
  378. var va = geometry.vertices[ a ];
  379. var vb = geometry.vertices[ b ];
  380. var vc = geometry.vertices[ c ];
  381. vertices.push( va.clone() );
  382. vertices.push( vb.clone() );
  383. vertices.push( vc.clone() );
  384. face.a = n;
  385. face.b = n + 1;
  386. face.c = n + 2;
  387. }
  388. }
  389. geometry.vertices = vertices;
  390. }
  391. };
  392. THREE.GeometryUtils.random = THREE.Math.random16;
  393. THREE.GeometryUtils.__v1 = new THREE.Vector3();
粤ICP备19079148号