GeometryUtils.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  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 */, materialOffset ) {
  8. var matrix, normalMatrix,
  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. materialOffset = materialOffset !== undefined ? materialOffset : 0;
  19. if ( object2 instanceof THREE.Mesh ) {
  20. object2.matrixAutoUpdate && object2.updateMatrix();
  21. matrix = object2.matrix;
  22. normalMatrix = new THREE.Matrix3();
  23. normalMatrix.getInverse( matrix );
  24. normalMatrix.transpose();
  25. }
  26. // vertices
  27. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  28. var vertex = vertices2[ i ];
  29. var vertexCopy = vertex.clone();
  30. if ( matrix ) vertexCopy.applyMatrix4( matrix );
  31. vertices1.push( vertexCopy );
  32. }
  33. // faces
  34. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  35. var face = faces2[ i ], faceCopy, normal, color,
  36. faceVertexNormals = face.vertexNormals,
  37. faceVertexColors = face.vertexColors;
  38. if ( face instanceof THREE.Face3 ) {
  39. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  40. } else if ( face instanceof THREE.Face4 ) {
  41. faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset );
  42. }
  43. faceCopy.normal.copy( face.normal );
  44. if ( normalMatrix ) {
  45. faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
  46. }
  47. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  48. normal = faceVertexNormals[ j ].clone();
  49. if ( normalMatrix ) {
  50. normal.applyMatrix3( normalMatrix ).normalize();
  51. }
  52. faceCopy.vertexNormals.push( normal );
  53. }
  54. faceCopy.color.copy( face.color );
  55. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  56. color = faceVertexColors[ j ];
  57. faceCopy.vertexColors.push( color.clone() );
  58. }
  59. faceCopy.materialIndex = face.materialIndex + materialOffset;
  60. faceCopy.centroid.copy( face.centroid );
  61. if ( matrix ) {
  62. faceCopy.centroid.applyMatrix4( matrix );
  63. }
  64. faces1.push( faceCopy );
  65. }
  66. // uvs
  67. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  68. var uv = uvs2[ i ], uvCopy = [];
  69. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  70. uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
  71. }
  72. uvs1.push( uvCopy );
  73. }
  74. },
  75. removeMaterials: function ( geometry, materialIndexArray ) {
  76. var materialIndexMap = {};
  77. for ( var i = 0, il = materialIndexArray.length; i < il; i ++ ) {
  78. materialIndexMap[ materialIndexArray[i] ] = true;
  79. }
  80. var face, newFaces = [];
  81. for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
  82. face = geometry.faces[ i ];
  83. if ( ! ( face.materialIndex in materialIndexMap ) ) newFaces.push( face );
  84. }
  85. geometry.faces = newFaces;
  86. },
  87. // Get random point in triangle (via barycentric coordinates)
  88. // (uniform distribution)
  89. // http://www.cgafaq.info/wiki/Random_Point_In_Triangle
  90. randomPointInTriangle: function ( vectorA, vectorB, vectorC ) {
  91. var a, b, c,
  92. point = new THREE.Vector3(),
  93. tmp = THREE.GeometryUtils.__v1;
  94. a = THREE.GeometryUtils.random();
  95. b = THREE.GeometryUtils.random();
  96. if ( ( a + b ) > 1 ) {
  97. a = 1 - a;
  98. b = 1 - b;
  99. }
  100. c = 1 - a - b;
  101. point.copy( vectorA );
  102. point.multiplyScalar( a );
  103. tmp.copy( vectorB );
  104. tmp.multiplyScalar( b );
  105. point.add( tmp );
  106. tmp.copy( vectorC );
  107. tmp.multiplyScalar( c );
  108. point.add( tmp );
  109. return point;
  110. },
  111. // Get random point in face (triangle / quad)
  112. // (uniform distribution)
  113. randomPointInFace: function ( face, geometry, useCachedAreas ) {
  114. var vA, vB, vC, vD;
  115. if ( face instanceof THREE.Face3 ) {
  116. vA = geometry.vertices[ face.a ];
  117. vB = geometry.vertices[ face.b ];
  118. vC = geometry.vertices[ face.c ];
  119. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
  120. } else if ( face instanceof THREE.Face4 ) {
  121. vA = geometry.vertices[ face.a ];
  122. vB = geometry.vertices[ face.b ];
  123. vC = geometry.vertices[ face.c ];
  124. vD = geometry.vertices[ face.d ];
  125. var area1, area2;
  126. if ( useCachedAreas ) {
  127. if ( face._area1 && face._area2 ) {
  128. area1 = face._area1;
  129. area2 = face._area2;
  130. } else {
  131. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  132. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  133. face._area1 = area1;
  134. face._area2 = area2;
  135. }
  136. } else {
  137. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
  138. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  139. }
  140. var r = THREE.GeometryUtils.random() * ( area1 + area2 );
  141. if ( r < area1 ) {
  142. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
  143. } else {
  144. return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
  145. }
  146. }
  147. },
  148. // Get uniformly distributed random points in mesh
  149. // - create array with cumulative sums of face areas
  150. // - pick random number from 0 to total area
  151. // - find corresponding place in area array by binary search
  152. // - get random point in face
  153. randomPointsInGeometry: function ( geometry, n ) {
  154. var face, i,
  155. faces = geometry.faces,
  156. vertices = geometry.vertices,
  157. il = faces.length,
  158. totalArea = 0,
  159. cumulativeAreas = [],
  160. vA, vB, vC, vD;
  161. // precompute face areas
  162. for ( i = 0; i < il; i ++ ) {
  163. face = faces[ i ];
  164. if ( face instanceof THREE.Face3 ) {
  165. vA = vertices[ face.a ];
  166. vB = vertices[ face.b ];
  167. vC = vertices[ face.c ];
  168. face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
  169. } else if ( face instanceof THREE.Face4 ) {
  170. vA = vertices[ face.a ];
  171. vB = vertices[ face.b ];
  172. vC = vertices[ face.c ];
  173. vD = vertices[ face.d ];
  174. face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  175. face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  176. face._area = face._area1 + face._area2;
  177. }
  178. totalArea += face._area;
  179. cumulativeAreas[ i ] = totalArea;
  180. }
  181. // binary search cumulative areas array
  182. function binarySearchIndices( value ) {
  183. function binarySearch( start, end ) {
  184. // return closest larger index
  185. // if exact number is not found
  186. if ( end < start )
  187. return start;
  188. var mid = start + Math.floor( ( end - start ) / 2 );
  189. if ( cumulativeAreas[ mid ] > value ) {
  190. return binarySearch( start, mid - 1 );
  191. } else if ( cumulativeAreas[ mid ] < value ) {
  192. return binarySearch( mid + 1, end );
  193. } else {
  194. return mid;
  195. }
  196. }
  197. var result = binarySearch( 0, cumulativeAreas.length - 1 )
  198. return result;
  199. }
  200. // pick random face weighted by face area
  201. var r, index,
  202. result = [];
  203. var stats = {};
  204. for ( i = 0; i < n; i ++ ) {
  205. r = THREE.GeometryUtils.random() * totalArea;
  206. index = binarySearchIndices( r );
  207. result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
  208. if ( ! stats[ index ] ) {
  209. stats[ index ] = 1;
  210. } else {
  211. stats[ index ] += 1;
  212. }
  213. }
  214. return result;
  215. },
  216. // Get triangle area (half of parallelogram)
  217. // http://mathworld.wolfram.com/TriangleArea.html
  218. triangleArea: function ( vectorA, vectorB, vectorC ) {
  219. var tmp1 = THREE.GeometryUtils.__v1,
  220. tmp2 = THREE.GeometryUtils.__v2;
  221. tmp1.subVectors( vectorB, vectorA );
  222. tmp2.subVectors( vectorC, vectorA );
  223. tmp1.cross( tmp2 );
  224. return 0.5 * tmp1.length();
  225. },
  226. // Center geometry so that 0,0,0 is in center of bounding box
  227. center: function ( geometry ) {
  228. geometry.computeBoundingBox();
  229. var bb = geometry.boundingBox;
  230. var offset = new THREE.Vector3();
  231. offset.addVectors( bb.min, bb.max );
  232. offset.multiplyScalar( -0.5 );
  233. geometry.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
  234. geometry.computeBoundingBox();
  235. return offset;
  236. },
  237. // Normalize UVs to be from <0,1>
  238. // (for now just the first set of UVs)
  239. normalizeUVs: function ( geometry ) {
  240. var uvSet = geometry.faceVertexUvs[ 0 ];
  241. for ( var i = 0, il = uvSet.length; i < il; i ++ ) {
  242. var uvs = uvSet[ i ];
  243. for ( var j = 0, jl = uvs.length; j < jl; j ++ ) {
  244. // texture repeat
  245. if( uvs[ j ].x !== 1.0 ) uvs[ j ].x = uvs[ j ].x - Math.floor( uvs[ j ].x );
  246. if( uvs[ j ].y !== 1.0 ) uvs[ j ].y = uvs[ j ].y - Math.floor( uvs[ j ].y );
  247. }
  248. }
  249. },
  250. triangulateQuads: function ( geometry ) {
  251. var i, il, j, jl;
  252. var faces = [];
  253. var faceUvs = [];
  254. var faceVertexUvs = [];
  255. for ( i = 0, il = geometry.faceUvs.length; i < il; i ++ ) {
  256. faceUvs[ i ] = [];
  257. }
  258. for ( i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
  259. faceVertexUvs[ i ] = [];
  260. }
  261. for ( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  262. var face = geometry.faces[ i ];
  263. if ( face instanceof THREE.Face4 ) {
  264. var a = face.a;
  265. var b = face.b;
  266. var c = face.c;
  267. var d = face.d;
  268. var triA = new THREE.Face3();
  269. var triB = new THREE.Face3();
  270. triA.color.copy( face.color );
  271. triB.color.copy( face.color );
  272. triA.materialIndex = face.materialIndex;
  273. triB.materialIndex = face.materialIndex;
  274. triA.a = a;
  275. triA.b = b;
  276. triA.c = d;
  277. triB.a = b;
  278. triB.b = c;
  279. triB.c = d;
  280. if ( face.vertexColors.length === 4 ) {
  281. triA.vertexColors[ 0 ] = face.vertexColors[ 0 ].clone();
  282. triA.vertexColors[ 1 ] = face.vertexColors[ 1 ].clone();
  283. triA.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
  284. triB.vertexColors[ 0 ] = face.vertexColors[ 1 ].clone();
  285. triB.vertexColors[ 1 ] = face.vertexColors[ 2 ].clone();
  286. triB.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
  287. }
  288. faces.push( triA, triB );
  289. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  290. if ( geometry.faceVertexUvs[ j ].length ) {
  291. var uvs = geometry.faceVertexUvs[ j ][ i ];
  292. var uvA = uvs[ 0 ];
  293. var uvB = uvs[ 1 ];
  294. var uvC = uvs[ 2 ];
  295. var uvD = uvs[ 3 ];
  296. var uvsTriA = [ uvA.clone(), uvB.clone(), uvD.clone() ];
  297. var uvsTriB = [ uvB.clone(), uvC.clone(), uvD.clone() ];
  298. faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
  299. }
  300. }
  301. for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
  302. if ( geometry.faceUvs[ j ].length ) {
  303. var faceUv = geometry.faceUvs[ j ][ i ];
  304. faceUvs[ j ].push( faceUv, faceUv );
  305. }
  306. }
  307. } else {
  308. faces.push( face );
  309. for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
  310. faceUvs[ j ].push( geometry.faceUvs[ j ][ i ] );
  311. }
  312. for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
  313. faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
  314. }
  315. }
  316. }
  317. geometry.faces = faces;
  318. geometry.faceUvs = faceUvs;
  319. geometry.faceVertexUvs = faceVertexUvs;
  320. geometry.computeCentroids();
  321. geometry.computeFaceNormals();
  322. geometry.computeVertexNormals();
  323. if ( geometry.hasTangents ) geometry.computeTangents();
  324. },
  325. setMaterialIndex: function ( geometry, index, startFace, endFace ){
  326. var faces = geometry.faces;
  327. var start = startFace || 0;
  328. var end = endFace || faces.length - 1;
  329. for ( var i = start; i <= end; i ++ ) {
  330. faces[i].materialIndex = index;
  331. }
  332. }
  333. };
  334. THREE.GeometryUtils.random = THREE.Math.random16;
  335. THREE.GeometryUtils.__v1 = new THREE.Vector3();
  336. THREE.GeometryUtils.__v2 = new THREE.Vector3();
粤ICP备19079148号