SubdivisionModifier.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
  3. *
  4. * Subdivision Geometry Modifier
  5. * using Catmull-Clark Subdivision Surfaces
  6. * for creating smooth geometry meshes
  7. *
  8. * Note: a modifier modifies vertices and faces of geometry,
  9. * so use THREE.GeometryUtils.clone() if orignal geoemtry needs to be retained
  10. *
  11. * Readings:
  12. * http://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
  13. * http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/
  14. */
  15. THREE.SubdivisionModifier = function( subdivisions ) {
  16. this.subdivisions = (subdivisions === undefined ) ? 1 : subdivisions;
  17. // Settings
  18. this.useOldVertexColors = false;
  19. this.supportUVs = true;
  20. };
  21. //THREE.SubdivisionModifier.prototype = new THREE.Modifier();
  22. THREE.SubdivisionModifier.prototype.constructor = THREE.SubdivisionModifier;
  23. // Applies the "modify" pattern
  24. THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
  25. var repeats = this.subdivisions;
  26. while ( repeats-- > 0 ) {
  27. this.smooth( geometry );
  28. }
  29. };
  30. // Performs an iteration of Catmull-Clark Subdivision
  31. THREE.SubdivisionModifier.prototype.smooth = function ( oldGeometry ) {
  32. //console.log( 'running smooth' );
  33. // New set of vertices, faces and uvs
  34. var newVertices = [], newFaces = [], newUVs = [];
  35. function v( x, y, z ) {
  36. newVertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
  37. }
  38. var scope = this;
  39. function f4( a, b, c, d, oldFace, orders ) {
  40. // TODO move vertex selection over here!
  41. var newFace = new THREE.Face4( a, b, c, d, null, oldFace.color, oldFace.material );
  42. if (scope.useOldVertexColors) {
  43. newFace.vertexColors = [];
  44. var color, tmpColor, order;
  45. for (var i=0;i<4;i++) {
  46. order = orders[i];
  47. color = new THREE.Color(),
  48. color.setRGB(0,0,0);
  49. for (var j=0, jl=0; j<order.length;j++) {
  50. tmpColor = oldFace.vertexColors[order[j]-1];
  51. color.r += tmpColor.r;
  52. color.g += tmpColor.g;
  53. color.b += tmpColor.b;
  54. }
  55. color.r /= order.length;
  56. color.g /= order.length;
  57. color.b /= order.length;
  58. newFace.vertexColors[i] = color;
  59. }
  60. }
  61. newFaces.push( newFace );
  62. if (!scope.supportUVs || uvForVertices.length!=0) {
  63. newUVs.push( [
  64. uvForVertices[a],
  65. uvForVertices[b],
  66. uvForVertices[c],
  67. uvForVertices[d]
  68. ] );
  69. }
  70. }
  71. function edge_hash( a, b ) {
  72. return Math.min( a, b ) + "_" + Math.max( a, b );
  73. };
  74. function computeEdgeFaces( geometry ) {
  75. function addToMap( map, hash, i ) {
  76. if ( map[ hash ] === undefined ) {
  77. map[ hash ] = [];
  78. }
  79. map[ hash ].push( i );
  80. };
  81. var i, il, v1, v2, j, k,
  82. face, faceIndices, faceIndex,
  83. edge,
  84. hash,
  85. vfMap = {};
  86. // construct vertex -> face map
  87. for( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  88. face = geometry.faces[ i ];
  89. if ( face instanceof THREE.Face3 ) {
  90. hash = edge_hash( face.a, face.b );
  91. addToMap( vfMap, hash, i );
  92. hash = edge_hash( face.b, face.c );
  93. addToMap( vfMap, hash, i );
  94. hash = edge_hash( face.c, face.a );
  95. addToMap( vfMap, hash, i );
  96. } else if ( face instanceof THREE.Face4 ) {
  97. hash = edge_hash( face.a, face.b );
  98. addToMap( vfMap, hash, i );
  99. hash = edge_hash( face.b, face.c );
  100. addToMap( vfMap, hash, i );
  101. hash = edge_hash( face.c, face.d );
  102. addToMap( vfMap, hash, i );
  103. hash = edge_hash( face.d, face.a );
  104. addToMap( vfMap, hash, i );
  105. }
  106. }
  107. // extract faces
  108. // var edges = [];
  109. //
  110. // var numOfEdges = 0;
  111. // for (i in vfMap) {
  112. // numOfEdges++;
  113. //
  114. // edge = vfMap[i];
  115. // edges.push(edge);
  116. //
  117. // }
  118. //console.log('vfMap', vfMap, 'geometry.edges',geometry.edges, 'numOfEdges', numOfEdges);
  119. return vfMap;
  120. };
  121. var originalPoints = oldGeometry.vertices;
  122. var originalFaces = oldGeometry.faces;
  123. var newPoints = originalPoints.concat(); // Vertices
  124. var facePoints = [], edgePoints = {};
  125. var uvForVertices = [];
  126. // Step 1
  127. // For each face, add a face point
  128. // Set each face point to be the centroid of all original points for the respective face.
  129. var i, il, j, jl, face;
  130. // For Uvs
  131. var uvs = oldGeometry.faceVertexUvs[0];
  132. var abcd = 'abcd', vertice;
  133. for (i=0, il = uvs.length; i<il; i++ ) {
  134. for (j=0,jl=uvs[i].length;j<jl;j++) {
  135. vertice = originalFaces[i][abcd.charAt(j)];
  136. if (!uvForVertices[vertice]) {
  137. uvForVertices[vertice] = uvs[i][j];
  138. } else {
  139. //console.log('dup', uvForVertices[vertice]);
  140. }
  141. }
  142. }
  143. var avgUv ;
  144. for (i=0, il = originalFaces.length; i<il ;i++) {
  145. face = originalFaces[i];
  146. facePoints.push(face.centroid);
  147. newPoints.push( new THREE.Vertex(face.centroid) );
  148. if (!scope.supportUVs || uvForVertices.length==0) continue;
  149. // Prepare subdivided uv
  150. avgUv = new THREE.UV();
  151. if ( face instanceof THREE.Face3 ) {
  152. avgUv.u = uvForVertices[face.a].u + uvForVertices[face.b].u + uvForVertices[face.c].u;
  153. avgUv.v = uvForVertices[face.a].v + uvForVertices[face.b].v + uvForVertices[face.c].v;
  154. avgUv.u /= 3;
  155. avgUv.v /= 3;
  156. } else if ( face instanceof THREE.Face4 ) {
  157. avgUv.u = uvForVertices[face.a].u + uvForVertices[face.b].u + uvForVertices[face.c].u + uvForVertices[face.d].u;
  158. avgUv.v = uvForVertices[face.a].v + uvForVertices[face.b].v + uvForVertices[face.c].v + uvForVertices[face.d].v;
  159. avgUv.u /= 4;
  160. avgUv.v /= 4;
  161. }
  162. uvForVertices.push(avgUv);
  163. }
  164. // Step 2
  165. // For each edge, add an edge point.
  166. // Set each edge point to be the average of the two neighbouring face points and its two original endpoints.
  167. var vfMap = computeEdgeFaces ( oldGeometry );
  168. var edge, faceIndexA, faceIndexB, avg;
  169. //console.log('vfMap', vfMap);
  170. var edgeCount = 0;
  171. var originalVerticesLength = originalPoints.length;
  172. var edgeVertex, edgeVertexA, edgeVertexB;
  173. for (i in vfMap) {
  174. edge = vfMap[i];
  175. faceIndexA = edge[0]; // face index a
  176. faceIndexB = edge[1]; // face index b
  177. edgeVertex = i.split('_');
  178. edgeVertexA = edgeVertex[0];
  179. edgeVertexB = edgeVertex[1];
  180. avg = new THREE.Vector3();
  181. //console.log(i, faceIndexB,facePoints[faceIndexB]);
  182. if (edge.length!=2) {
  183. //console.log('warning, ', i, 'edge has only 1 connecting face', edge);
  184. avg.addSelf(originalPoints[edgeVertexA].position);
  185. avg.addSelf(originalPoints[edgeVertexB].position);
  186. avg.multiplyScalar(0.5);
  187. } else {
  188. avg.addSelf(facePoints[faceIndexA]);
  189. avg.addSelf(facePoints[faceIndexB]);
  190. avg.addSelf(originalPoints[edgeVertexA].position);
  191. avg.addSelf(originalPoints[edgeVertexB].position);
  192. avg.multiplyScalar(0.25);
  193. }
  194. edgePoints[i] = originalVerticesLength + originalFaces.length + edgeCount;
  195. newPoints.push( new THREE.Vertex(avg) );
  196. edgeCount ++;
  197. if (!scope.supportUVs || uvForVertices.length==0) continue;
  198. // Prepare subdivided uv
  199. avgUv = new THREE.UV();
  200. avgUv.u = uvForVertices[edgeVertexA].u + uvForVertices[edgeVertexB].u;
  201. avgUv.v = uvForVertices[edgeVertexA].v + uvForVertices[edgeVertexB].v;
  202. avgUv.u /= 2;
  203. avgUv.v /= 2;
  204. uvForVertices.push(avgUv);
  205. }
  206. // Step 3
  207. // For each face point, add an edge for every edge of the face,
  208. // connecting the face point to each edge point for the face.
  209. var facePt, currentVerticeIndex;
  210. var hashAB, hashBC, hashCD, hashDA, hashCA;
  211. for (i=0, il = facePoints.length; i<il ;i++) { // for every face
  212. facePt = facePoints[i];
  213. face = originalFaces[i];
  214. currentVerticeIndex = originalVerticesLength+ i;
  215. if ( face instanceof THREE.Face3 ) {
  216. // create 3 face4s
  217. hashAB = edge_hash( face.a, face.b );
  218. hashBC = edge_hash( face.b, face.c );
  219. hashCA = edge_hash( face.c, face.a );
  220. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, ['123', '12', '2', '23'] );
  221. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCA], face, ['123', '23', '3', '31'] );
  222. f4( currentVerticeIndex, edgePoints[hashCA], face.a, edgePoints[hashAB], face, ['123', '31', '1', '12'] );
  223. } else if ( face instanceof THREE.Face4 ) {
  224. // create 4 face4s
  225. hashAB = edge_hash( face.a, face.b );
  226. hashBC = edge_hash( face.b, face.c );
  227. hashCD = edge_hash( face.c, face.d );
  228. hashDA = edge_hash( face.d, face.a );
  229. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, ['1234', '12', '2', '23'] );
  230. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCD], face, ['1234', '23', '3', '34'] );
  231. f4( currentVerticeIndex, edgePoints[hashCD], face.d, edgePoints[hashDA], face, ['1234', '34', '4', '41'] );
  232. f4( currentVerticeIndex, edgePoints[hashDA], face.a, edgePoints[hashAB], face, ['1234', '41', '1', '12'] );
  233. } else {
  234. console.log('face should be a face!', face);
  235. }
  236. }
  237. newVertices = newPoints;
  238. // console.log('original ', oldGeometry.vertices.length, oldGeometry.faces.length );
  239. // console.log('new points', newPoints.length, 'faces', newFaces.length );
  240. // Step 4
  241. // For each original point P,
  242. // take the average F of all n face points for faces touching P,
  243. // and take the average R of all n edge midpoints for edges touching P,
  244. // where each edge midpoint is the average of its two endpoint vertices.
  245. // Move each original point to the point
  246. var vertexEdgeMap = {};
  247. var vertexFaceMap = {};
  248. var addVertexEdgeMap = function(vertex, edge) {
  249. if (vertexEdgeMap[vertex]===undefined) {
  250. vertexEdgeMap[vertex] = [];
  251. }
  252. vertexEdgeMap[vertex].push(edge);
  253. };
  254. var addVertexFaceMap = function(vertex, face) {
  255. if (vertexFaceMap[vertex]===undefined) {
  256. vertexFaceMap[vertex] = {};
  257. }
  258. vertexFaceMap[vertex][face] = null;
  259. };
  260. // Prepares vertexEdgeMap and vertexFaceMap
  261. for (i in vfMap) { // This is for every edge
  262. edge = vfMap[i];
  263. edgeVertex = i.split('_');
  264. edgeVertexA = edgeVertex[0];
  265. edgeVertexB = edgeVertex[1];
  266. addVertexEdgeMap(edgeVertexA, [edgeVertexA, edgeVertexB] );
  267. addVertexEdgeMap(edgeVertexB, [edgeVertexA, edgeVertexB] );
  268. faceIndexA = edge[0]; // face index a
  269. faceIndexB = edge[1]; // face index b
  270. addVertexFaceMap(edgeVertexA, faceIndexA);
  271. if (faceIndexB) addVertexFaceMap(edgeVertexA, faceIndexB);
  272. else addVertexFaceMap(edgeVertexA, faceIndexA);
  273. addVertexFaceMap(edgeVertexB, faceIndexA);
  274. if (faceIndexB) addVertexFaceMap(edgeVertexB, faceIndexB);
  275. else addVertexFaceMap(edgeVertexB, faceIndexA);
  276. }
  277. //console.log('vertexEdgeMap',vertexEdgeMap, 'vertexFaceMap', vertexFaceMap);
  278. var F = new THREE.Vector3();
  279. var R = new THREE.Vector3();
  280. var n;
  281. for (i=0, il = originalPoints.length; i<il; i++) {
  282. // (F + 2R + (n-3)P) / n
  283. if (vertexEdgeMap[i]===undefined) continue;
  284. F.set(0,0,0);
  285. R.set(0,0,0);
  286. var newPos = new THREE.Vector3(0,0,0);
  287. var f =0;
  288. for (j in vertexFaceMap[i]) {
  289. F.addSelf(facePoints[j]);
  290. f++;
  291. }
  292. F.divideScalar(f);
  293. n = vertexEdgeMap[i].length;
  294. for (j=0; j<n;j++) {
  295. edge = vertexEdgeMap[i][j];
  296. var midPt = originalPoints[edge[0]].position.clone().addSelf(originalPoints[edge[1]].position).divideScalar(2);
  297. R.addSelf(midPt);
  298. // R.addSelf(originalPoints[edge[0]].position);
  299. // R.addSelf(originalPoints[edge[1]].position);
  300. }
  301. R.divideScalar(n)
  302. newPos.addSelf(originalPoints[i].position);
  303. newPos.multiplyScalar(n - 3);
  304. newPos.addSelf(F);
  305. newPos.addSelf(R.multiplyScalar(2));
  306. newPos.divideScalar(n);
  307. newVertices[i].position = newPos;
  308. }
  309. var newGeometry = oldGeometry; // Let's pretend the old geometry is now new :P
  310. newGeometry.vertices = newVertices;
  311. newGeometry.faces = newFaces;
  312. newGeometry.faceVertexUvs[ 0 ] = newUVs;
  313. delete newGeometry.__tmpVertices; // makes __tmpVertices undefined :P
  314. newGeometry.computeCentroids();
  315. newGeometry.computeFaceNormals();
  316. newGeometry.computeVertexNormals();
  317. };
粤ICP备19079148号