GeometryUtils.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.GeometryUtils = {
  6. merge: function ( geometry1, object2 /* mesh | geometry */ ) {
  7. var matrix, matrixRotation,
  8. vertexOffset = geometry1.vertices.length,
  9. uvPosition = geometry1.faceVertexUvs[ 0 ].length,
  10. geometry2 = object2 instanceof THREE.Mesh ? object2.geometry : object2,
  11. vertices1 = geometry1.vertices,
  12. vertices2 = geometry2.vertices,
  13. faces1 = geometry1.faces,
  14. faces2 = geometry2.faces,
  15. uvs1 = geometry1.faceVertexUvs[ 0 ],
  16. uvs2 = geometry2.faceVertexUvs[ 0 ];
  17. var geo1MaterialsMap = {};
  18. for ( var i = 0; i < geometry1.materials.length; i ++ ) {
  19. var id = geometry1.materials[ i ].id;
  20. geo1MaterialsMap[ id ] = i;
  21. }
  22. if ( object2 instanceof THREE.Mesh ) {
  23. object2.matrixAutoUpdate && object2.updateMatrix();
  24. matrix = object2.matrix;
  25. matrixRotation = new THREE.Matrix4();
  26. matrixRotation.extractRotation( matrix, object2.scale );
  27. }
  28. // vertices
  29. for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
  30. var vertex = vertices2[ i ];
  31. var vertexCopy = new THREE.Vertex( vertex.position.clone() );
  32. if ( matrix ) matrix.multiplyVector3( vertexCopy.position );
  33. vertices1.push( vertexCopy );
  34. }
  35. // faces
  36. for ( i = 0, il = faces2.length; i < il; i ++ ) {
  37. var face = faces2[ i ], faceCopy, normal, color,
  38. faceVertexNormals = face.vertexNormals,
  39. faceVertexColors = face.vertexColors;
  40. if ( face instanceof THREE.Face3 ) {
  41. faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
  42. } else if ( face instanceof THREE.Face4 ) {
  43. faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset );
  44. }
  45. faceCopy.normal.copy( face.normal );
  46. if ( matrixRotation ) matrixRotation.multiplyVector3( faceCopy.normal );
  47. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  48. normal = faceVertexNormals[ j ].clone();
  49. if ( matrixRotation ) matrixRotation.multiplyVector3( normal );
  50. faceCopy.vertexNormals.push( normal );
  51. }
  52. faceCopy.color.copy( face.color );
  53. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  54. color = faceVertexColors[ j ];
  55. faceCopy.vertexColors.push( color.clone() );
  56. }
  57. if ( face.materialIndex !== undefined ) {
  58. var material2 = geometry2.materials[ face.materialIndex ];
  59. var materialId2 = material2.id;
  60. var materialIndex = geo1MaterialsMap[ materialId2 ];
  61. if ( materialIndex === undefined ) {
  62. materialIndex = geometry1.materials.length;
  63. geometry1.materials.push( material2 );
  64. }
  65. faceCopy.materialIndex = materialIndex;
  66. }
  67. faceCopy.centroid.copy( face.centroid );
  68. if ( matrix ) matrix.multiplyVector3( faceCopy.centroid );
  69. faces1.push( faceCopy );
  70. }
  71. // uvs
  72. for ( i = 0, il = uvs2.length; i < il; i ++ ) {
  73. var uv = uvs2[ i ], uvCopy = [];
  74. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  75. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  76. }
  77. uvs1.push( uvCopy );
  78. }
  79. },
  80. clone: function ( geometry ) {
  81. var cloneGeo = new THREE.Geometry();
  82. var i, il;
  83. var vertices = geometry.vertices,
  84. faces = geometry.faces,
  85. uvs = geometry.faceVertexUvs[ 0 ];
  86. // materials
  87. if ( geometry.materials ) {
  88. cloneGeo.materials = geometry.materials.slice();
  89. }
  90. // vertices
  91. for ( i = 0, il = vertices.length; i < il; i ++ ) {
  92. var vertex = vertices[ i ];
  93. var vertexCopy = new THREE.Vertex( vertex.position.clone() );
  94. cloneGeo.vertices.push( vertexCopy );
  95. }
  96. // faces
  97. for ( i = 0, il = faces.length; i < il; i ++ ) {
  98. var face = faces[ i ], faceCopy, normal, color,
  99. faceVertexNormals = face.vertexNormals,
  100. faceVertexColors = face.vertexColors;
  101. if ( face instanceof THREE.Face3 ) {
  102. faceCopy = new THREE.Face3( face.a, face.b, face.c );
  103. } else if ( face instanceof THREE.Face4 ) {
  104. faceCopy = new THREE.Face4( face.a, face.b, face.c, face.d );
  105. }
  106. faceCopy.normal.copy( face.normal );
  107. for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
  108. normal = faceVertexNormals[ j ];
  109. faceCopy.vertexNormals.push( normal.clone() );
  110. }
  111. faceCopy.color.copy( face.color );
  112. for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
  113. color = faceVertexColors[ j ];
  114. faceCopy.vertexColors.push( color.clone() );
  115. }
  116. faceCopy.materialIndex = face.materialIndex;
  117. faceCopy.centroid.copy( face.centroid );
  118. cloneGeo.faces.push( faceCopy );
  119. }
  120. // uvs
  121. for ( i = 0, il = uvs.length; i < il; i ++ ) {
  122. var uv = uvs[ i ], uvCopy = [];
  123. for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
  124. uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
  125. }
  126. cloneGeo.faceVertexUvs[ 0 ].push( uvCopy );
  127. }
  128. return cloneGeo;
  129. },
  130. // Get random point in triangle (via barycentric coordinates)
  131. // (uniform distribution)
  132. // http://www.cgafaq.info/wiki/Random_Point_In_Triangle
  133. randomPointInTriangle: function( vectorA, vectorB, vectorC ) {
  134. var a, b, c,
  135. point = new THREE.Vector3(),
  136. tmp = THREE.GeometryUtils.__v1;
  137. a = THREE.GeometryUtils.random();
  138. b = THREE.GeometryUtils.random();
  139. if ( ( a + b ) > 1 ) {
  140. a = 1 - a;
  141. b = 1 - b;
  142. }
  143. c = 1 - a - b;
  144. point.copy( vectorA );
  145. point.multiplyScalar( a );
  146. tmp.copy( vectorB );
  147. tmp.multiplyScalar( b );
  148. point.addSelf( tmp );
  149. tmp.copy( vectorC );
  150. tmp.multiplyScalar( c );
  151. point.addSelf( tmp );
  152. return point;
  153. },
  154. // Get random point in face (triangle / quad)
  155. // (uniform distribution)
  156. randomPointInFace: function( face, geometry, useCachedAreas ) {
  157. var vA, vB, vC, vD;
  158. if ( face instanceof THREE.Face3 ) {
  159. vA = geometry.vertices[ face.a ].position;
  160. vB = geometry.vertices[ face.b ].position;
  161. vC = geometry.vertices[ face.c ].position;
  162. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
  163. } else if ( face instanceof THREE.Face4 ) {
  164. vA = geometry.vertices[ face.a ].position;
  165. vB = geometry.vertices[ face.b ].position;
  166. vC = geometry.vertices[ face.c ].position;
  167. vD = geometry.vertices[ face.d ].position;
  168. var area1, area2;
  169. if ( useCachedAreas ) {
  170. if ( face._area1 && face._area2 ) {
  171. area1 = face._area1;
  172. area2 = face._area2;
  173. } else {
  174. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  175. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  176. face._area1 = area1;
  177. face._area2 = area2;
  178. }
  179. } else {
  180. area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
  181. area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  182. }
  183. var r = THREE.GeometryUtils.random() * ( area1 + area2 );
  184. if ( r < area1 ) {
  185. return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
  186. } else {
  187. return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
  188. }
  189. }
  190. },
  191. // Get uniformly distributed random points in mesh
  192. // - create array with cumulative sums of face areas
  193. // - pick random number from 0 to total area
  194. // - find corresponding place in area array by binary search
  195. // - get random point in face
  196. randomPointsInGeometry: function( geometry, n ) {
  197. var face, i,
  198. faces = geometry.faces,
  199. vertices = geometry.vertices,
  200. il = faces.length,
  201. totalArea = 0,
  202. cumulativeAreas = [],
  203. vA, vB, vC, vD;
  204. // precompute face areas
  205. for ( i = 0; i < il; i ++ ) {
  206. face = faces[ i ];
  207. if ( face instanceof THREE.Face3 ) {
  208. vA = vertices[ face.a ].position;
  209. vB = vertices[ face.b ].position;
  210. vC = vertices[ face.c ].position;
  211. face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
  212. } else if ( face instanceof THREE.Face4 ) {
  213. vA = vertices[ face.a ].position;
  214. vB = vertices[ face.b ].position;
  215. vC = vertices[ face.c ].position;
  216. vD = vertices[ face.d ].position;
  217. face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
  218. face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
  219. face._area = face._area1 + face._area2;
  220. }
  221. totalArea += face._area;
  222. cumulativeAreas[ i ] = totalArea;
  223. }
  224. // binary search cumulative areas array
  225. function binarySearchIndices( value ) {
  226. function binarySearch( start, end ) {
  227. // return closest larger index
  228. // if exact number is not found
  229. if ( end < start )
  230. return start;
  231. var mid = start + Math.floor( ( end - start ) / 2 );
  232. if ( cumulativeAreas[ mid ] > value ) {
  233. return binarySearch( start, mid - 1 );
  234. } else if ( cumulativeAreas[ mid ] < value ) {
  235. return binarySearch( mid + 1, end );
  236. } else {
  237. return mid;
  238. }
  239. }
  240. var result = binarySearch( 0, cumulativeAreas.length - 1 )
  241. return result;
  242. }
  243. // pick random face weighted by face area
  244. var r, index,
  245. result = [];
  246. var stats = {};
  247. for ( i = 0; i < n; i ++ ) {
  248. r = THREE.GeometryUtils.random() * totalArea;
  249. index = binarySearchIndices( r );
  250. result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
  251. if ( ! stats[ index ] ) {
  252. stats[ index ] = 1;
  253. } else {
  254. stats[ index ] += 1;
  255. }
  256. }
  257. return result;
  258. },
  259. // Get triangle area (by Heron's formula)
  260. // http://en.wikipedia.org/wiki/Heron%27s_formula
  261. triangleArea: function( vectorA, vectorB, vectorC ) {
  262. var s, a, b, c,
  263. tmp = THREE.GeometryUtils.__v1;
  264. tmp.sub( vectorA, vectorB );
  265. a = tmp.length();
  266. tmp.sub( vectorA, vectorC );
  267. b = tmp.length();
  268. tmp.sub( vectorB, vectorC );
  269. c = tmp.length();
  270. s = 0.5 * ( a + b + c );
  271. return Math.sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
  272. },
  273. center: function( geometry ) {
  274. geometry.computeBoundingBox();
  275. var matrix = new THREE.Matrix4();
  276. var dx = -0.5 * ( geometry.boundingBox.x[ 1 ] + geometry.boundingBox.x[ 0 ] );
  277. var dy = -0.5 * ( geometry.boundingBox.y[ 1 ] + geometry.boundingBox.y[ 0 ] );
  278. var dz = -0.5 * ( geometry.boundingBox.z[ 1 ] + geometry.boundingBox.z[ 0 ] );
  279. matrix.setTranslation( dx, dy, dz );
  280. geometry.applyMatrix( matrix );
  281. geometry.computeBoundingBox();
  282. }
  283. };
  284. THREE.GeometryUtils.random = THREE.Math.random16;
  285. THREE.GeometryUtils.__v1 = new THREE.Vector3();
粤ICP备19079148号