SubdivisionModifier.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  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. * http://xrt.wikidot.com/blog:31
  15. * "Subdivision Surfaces in Character Animation"
  16. *
  17. * Supports:
  18. * Closed and Open geometries.
  19. *
  20. * TODO:
  21. * crease vertex and "semi-sharp" features
  22. * selective subdivision
  23. */
  24. THREE.SubdivisionModifier = function( subdivisions ) {
  25. this.subdivisions = (subdivisions === undefined ) ? 1 : subdivisions;
  26. // Settings
  27. this.useOldVertexColors = false;
  28. this.supportUVs = true;
  29. this.debug = false;
  30. };
  31. // Applies the "modify" pattern
  32. THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
  33. var repeats = this.subdivisions;
  34. while ( repeats-- > 0 ) {
  35. this.smooth( geometry );
  36. }
  37. };
  38. // Performs an iteration of Catmull-Clark Subdivision
  39. THREE.SubdivisionModifier.prototype.smooth = function ( oldGeometry ) {
  40. //debug( 'running smooth' );
  41. // New set of vertices, faces and uvs
  42. var newVertices = [], newFaces = [], newUVs = [];
  43. function v( x, y, z ) {
  44. newVertices.push( new THREE.Vector3( x, y, z ) );
  45. }
  46. var scope = this;
  47. function debug() {
  48. if (scope.debug) console.log.apply(console, arguments);
  49. }
  50. function warn() {
  51. if (console)
  52. console.log.apply(console, arguments);
  53. }
  54. function f4( a, b, c, d, oldFace, orders, facei ) {
  55. // TODO move vertex selection over here!
  56. var newFace = new THREE.Face4( a, b, c, d, null, oldFace.color, oldFace.materialIndex );
  57. if (scope.useOldVertexColors) {
  58. newFace.vertexColors = [];
  59. var color, tmpColor, order;
  60. for (var i=0;i<4;i++) {
  61. order = orders[i];
  62. color = new THREE.Color(),
  63. color.setRGB(0,0,0);
  64. for (var j=0, jl=0; j<order.length;j++) {
  65. tmpColor = oldFace.vertexColors[order[j]-1];
  66. color.r += tmpColor.r;
  67. color.g += tmpColor.g;
  68. color.b += tmpColor.b;
  69. }
  70. color.r /= order.length;
  71. color.g /= order.length;
  72. color.b /= order.length;
  73. newFace.vertexColors[i] = color;
  74. }
  75. }
  76. newFaces.push( newFace );
  77. if (scope.supportUVs) {
  78. var aUv = [
  79. getUV(a, ''),
  80. getUV(b, facei),
  81. getUV(c, facei),
  82. getUV(d, facei)
  83. ];
  84. if (!aUv[0]) debug('a :( ', a+':'+facei);
  85. else if (!aUv[1]) debug('b :( ', b+':'+facei);
  86. else if (!aUv[2]) debug('c :( ', c+':'+facei);
  87. else if (!aUv[3]) debug('d :( ', d+':'+facei);
  88. else
  89. newUVs.push( aUv );
  90. }
  91. }
  92. function edge_hash( a, b ) {
  93. return Math.min( a, b ) + "_" + Math.max( a, b );
  94. }
  95. function computeEdgeFaces( geometry ) {
  96. var i, il, v1, v2, j, k,
  97. face, faceIndices, faceIndex,
  98. edge,
  99. hash,
  100. edgeFaceMap = {};
  101. function mapEdgeHash( hash, i ) {
  102. if ( edgeFaceMap[ hash ] === undefined ) {
  103. edgeFaceMap[ hash ] = [];
  104. }
  105. edgeFaceMap[ hash ].push( i );
  106. }
  107. // construct vertex -> face map
  108. for( i = 0, il = geometry.faces.length; i < il; i ++ ) {
  109. face = geometry.faces[ i ];
  110. if ( face instanceof THREE.Face3 ) {
  111. hash = edge_hash( face.a, face.b );
  112. mapEdgeHash( hash, i );
  113. hash = edge_hash( face.b, face.c );
  114. mapEdgeHash( hash, i );
  115. hash = edge_hash( face.c, face.a );
  116. mapEdgeHash( hash, i );
  117. } else if ( face instanceof THREE.Face4 ) {
  118. hash = edge_hash( face.a, face.b );
  119. mapEdgeHash( hash, i );
  120. hash = edge_hash( face.b, face.c );
  121. mapEdgeHash( hash, i );
  122. hash = edge_hash( face.c, face.d );
  123. mapEdgeHash( hash, i );
  124. hash = edge_hash( face.d, face.a );
  125. mapEdgeHash( hash, i );
  126. }
  127. }
  128. // extract faces
  129. // var edges = [];
  130. //
  131. // var numOfEdges = 0;
  132. // for (i in edgeFaceMap) {
  133. // numOfEdges++;
  134. //
  135. // edge = edgeFaceMap[i];
  136. // edges.push(edge);
  137. //
  138. // }
  139. //debug('edgeFaceMap', edgeFaceMap, 'geometry.edges',geometry.edges, 'numOfEdges', numOfEdges);
  140. return edgeFaceMap;
  141. }
  142. var originalPoints = oldGeometry.vertices;
  143. var originalFaces = oldGeometry.faces;
  144. var newPoints = originalPoints.concat(); // Vertices
  145. var facePoints = [], edgePoints = {};
  146. var sharpEdges = {}, sharpVertices = [], sharpFaces = [];
  147. var uvForVertices = {}; // Stored in {vertex}:{old face} format
  148. var originalVerticesLength = originalPoints.length;
  149. function getUV(vertexNo, oldFaceNo) {
  150. var j,jl;
  151. var key = vertexNo+':'+oldFaceNo;
  152. var theUV = uvForVertices[key];
  153. if (!theUV) {
  154. if (vertexNo>=originalVerticesLength && vertexNo < (originalVerticesLength + originalFaces.length)) {
  155. debug('face pt');
  156. } else {
  157. debug('edge pt');
  158. }
  159. warn('warning, UV not found for', key);
  160. return null;
  161. }
  162. return theUV;
  163. // Original faces -> Vertex Nos.
  164. // new Facepoint -> Vertex Nos.
  165. // edge Points
  166. }
  167. function addUV(vertexNo, oldFaceNo, value) {
  168. var key = vertexNo+':'+oldFaceNo;
  169. if (!(key in uvForVertices)) {
  170. uvForVertices[key] = value;
  171. } else {
  172. warn('dup vertexNo', vertexNo, 'oldFaceNo', oldFaceNo, 'value', value, 'key', key, uvForVertices[key]);
  173. }
  174. }
  175. // Step 1
  176. // For each face, add a face point
  177. // Set each face point to be the centroid of all original points for the respective face.
  178. // debug(oldGeometry);
  179. var i, il, j, jl, face;
  180. // For Uvs
  181. var uvs = oldGeometry.faceVertexUvs[0];
  182. var abcd = 'abcd', vertice;
  183. debug('originalFaces, uvs, originalVerticesLength', originalFaces.length, uvs.length, originalVerticesLength);
  184. if (scope.supportUVs)
  185. for (i=0, il = uvs.length; i<il; i++ ) {
  186. for (j=0,jl=uvs[i].length;j<jl;j++) {
  187. vertice = originalFaces[i][abcd.charAt(j)];
  188. addUV(vertice, i, uvs[i][j]);
  189. }
  190. }
  191. if (uvs.length == 0) scope.supportUVs = false;
  192. // Additional UVs check, if we index original
  193. var uvCount = 0;
  194. for (var u in uvForVertices) {
  195. uvCount++;
  196. }
  197. if (!uvCount) {
  198. scope.supportUVs = false;
  199. debug('no uvs');
  200. }
  201. debug('-- Original Faces + Vertices UVs completed', uvForVertices, 'vs', uvs.length);
  202. var avgUv ;
  203. for (i=0, il = originalFaces.length; i<il ;i++) {
  204. face = originalFaces[ i ];
  205. facePoints.push( face.centroid );
  206. newPoints.push( face.centroid );
  207. if (!scope.supportUVs) continue;
  208. // Prepare subdivided uv
  209. avgUv = new THREE.UV();
  210. if ( face instanceof THREE.Face3 ) {
  211. avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u;
  212. avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v;
  213. avgUv.u /= 3;
  214. avgUv.v /= 3;
  215. } else if ( face instanceof THREE.Face4 ) {
  216. avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u + getUV( face.d, i ).u;
  217. avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v + getUV( face.d, i ).v;
  218. avgUv.u /= 4;
  219. avgUv.v /= 4;
  220. }
  221. addUV(originalVerticesLength + i, '', avgUv);
  222. }
  223. debug('-- added UVs for new Faces', uvForVertices);
  224. // Step 2
  225. // For each edge, add an edge point.
  226. // Set each edge point to be the average of the two neighbouring face points and its two original endpoints.
  227. var edgeFaceMap = computeEdgeFaces ( oldGeometry ); // Edge Hash -> Faces Index
  228. var edge, faceIndexA, faceIndexB, avg;
  229. // debug('edgeFaceMap', edgeFaceMap);
  230. var edgeCount = 0;
  231. var edgeVertex, edgeVertexA, edgeVertexB;
  232. ////
  233. var vertexEdgeMap = {}; // Gives edges connecting from each vertex
  234. var vertexFaceMap = {}; // Gives faces connecting from each vertex
  235. function addVertexEdgeMap(vertex, edge) {
  236. if (vertexEdgeMap[vertex]===undefined) {
  237. vertexEdgeMap[vertex] = [];
  238. }
  239. vertexEdgeMap[vertex].push(edge);
  240. }
  241. function addVertexFaceMap(vertex, face, edge) {
  242. if (vertexFaceMap[vertex]===undefined) {
  243. vertexFaceMap[vertex] = {};
  244. }
  245. vertexFaceMap[vertex][face] = edge;
  246. // vertexFaceMap[vertex][face] = null;
  247. }
  248. // Prepares vertexEdgeMap and vertexFaceMap
  249. for (i in edgeFaceMap) { // This is for every edge
  250. edge = edgeFaceMap[i];
  251. edgeVertex = i.split('_');
  252. edgeVertexA = edgeVertex[0];
  253. edgeVertexB = edgeVertex[1];
  254. // Maps an edgeVertex to connecting edges
  255. addVertexEdgeMap(edgeVertexA, [edgeVertexA, edgeVertexB] );
  256. addVertexEdgeMap(edgeVertexB, [edgeVertexA, edgeVertexB] );
  257. for (j=0,jl=edge.length;j<jl;j++) {
  258. face = edge[j];
  259. addVertexFaceMap(edgeVertexA, face, i);
  260. addVertexFaceMap(edgeVertexB, face, i);
  261. }
  262. if (edge.length < 2) {
  263. // edge is "sharp";
  264. sharpEdges[i] = true;
  265. sharpVertices[edgeVertexA] = true;
  266. sharpVertices[edgeVertexB] = true;
  267. }
  268. }
  269. debug('vertexEdgeMap',vertexEdgeMap, 'vertexFaceMap', vertexFaceMap);
  270. for (i in edgeFaceMap) {
  271. edge = edgeFaceMap[i];
  272. faceIndexA = edge[0]; // face index a
  273. faceIndexB = edge[1]; // face index b
  274. edgeVertex = i.split('_');
  275. edgeVertexA = edgeVertex[0];
  276. edgeVertexB = edgeVertex[1];
  277. avg = new THREE.Vector3();
  278. //debug(i, faceIndexB,facePoints[faceIndexB]);
  279. if (sharpEdges[i]) {
  280. //debug('warning, ', i, 'edge has only 1 connecting face', edge);
  281. // For a sharp edge, average the edge end points.
  282. avg.addSelf(originalPoints[edgeVertexA]);
  283. avg.addSelf(originalPoints[edgeVertexB]);
  284. avg.multiplyScalar(0.5);
  285. sharpVertices[newPoints.length] = true;
  286. } else {
  287. avg.addSelf(facePoints[faceIndexA]);
  288. avg.addSelf(facePoints[faceIndexB]);
  289. avg.addSelf(originalPoints[edgeVertexA]);
  290. avg.addSelf(originalPoints[edgeVertexB]);
  291. avg.multiplyScalar(0.25);
  292. }
  293. edgePoints[i] = originalVerticesLength + originalFaces.length + edgeCount;
  294. newPoints.push( avg );
  295. edgeCount ++;
  296. if (!scope.supportUVs) {
  297. continue;
  298. }
  299. // debug('faceIndexAB', faceIndexA, faceIndexB, sharpEdges[i]);
  300. // Prepare subdivided uv
  301. avgUv = new THREE.UV();
  302. avgUv.u = getUV(edgeVertexA, faceIndexA).u + getUV(edgeVertexB, faceIndexA).u;
  303. avgUv.v = getUV(edgeVertexA, faceIndexA).v + getUV(edgeVertexB, faceIndexA).v;
  304. avgUv.u /= 2;
  305. avgUv.v /= 2;
  306. addUV(edgePoints[i], faceIndexA, avgUv);
  307. if (!sharpEdges[i]) {
  308. avgUv = new THREE.UV();
  309. avgUv.u = getUV(edgeVertexA, faceIndexB).u + getUV(edgeVertexB, faceIndexB).u;
  310. avgUv.v = getUV(edgeVertexA, faceIndexB).v + getUV(edgeVertexB, faceIndexB).v;
  311. avgUv.u /= 2;
  312. avgUv.v /= 2;
  313. addUV(edgePoints[i], faceIndexB, avgUv);
  314. }
  315. }
  316. debug('-- Step 2 done');
  317. // Step 3
  318. // For each face point, add an edge for every edge of the face,
  319. // connecting the face point to each edge point for the face.
  320. var facePt, currentVerticeIndex;
  321. var hashAB, hashBC, hashCD, hashDA, hashCA;
  322. var abc123 = ['123', '12', '2', '23'];
  323. var bca123 = ['123', '23', '3', '31'];
  324. var cab123 = ['123', '31', '1', '12'];
  325. var abc1234 = ['1234', '12', '2', '23'];
  326. var bcd1234 = ['1234', '23', '3', '34'];
  327. var cda1234 = ['1234', '34', '4', '41'];
  328. var dab1234 = ['1234', '41', '1', '12'];
  329. for (i=0, il = facePoints.length; i<il ;i++) { // for every face
  330. facePt = facePoints[i];
  331. face = originalFaces[i];
  332. currentVerticeIndex = originalVerticesLength+ i;
  333. if ( face instanceof THREE.Face3 ) {
  334. // create 3 face4s
  335. hashAB = edge_hash( face.a, face.b );
  336. hashBC = edge_hash( face.b, face.c );
  337. hashCA = edge_hash( face.c, face.a );
  338. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc123, i );
  339. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCA], face, bca123, i );
  340. f4( currentVerticeIndex, edgePoints[hashCA], face.a, edgePoints[hashAB], face, cab123, i );
  341. } else if ( face instanceof THREE.Face4 ) {
  342. // create 4 face4s
  343. hashAB = edge_hash( face.a, face.b );
  344. hashBC = edge_hash( face.b, face.c );
  345. hashCD = edge_hash( face.c, face.d );
  346. hashDA = edge_hash( face.d, face.a );
  347. f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc1234, i );
  348. f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCD], face, bcd1234, i );
  349. f4( currentVerticeIndex, edgePoints[hashCD], face.d, edgePoints[hashDA], face, cda1234, i );
  350. f4( currentVerticeIndex, edgePoints[hashDA], face.a, edgePoints[hashAB], face, dab1234, i );
  351. } else {
  352. debug('face should be a face!', face);
  353. }
  354. }
  355. newVertices = newPoints;
  356. // debug('original ', oldGeometry.vertices.length, oldGeometry.faces.length );
  357. // debug('new points', newPoints.length, 'faces', newFaces.length );
  358. // Step 4
  359. // For each original point P,
  360. // take the average F of all n face points for faces touching P,
  361. // and take the average R of all n edge midpoints for edges touching P,
  362. // where each edge midpoint is the average of its two endpoint vertices.
  363. // Move each original point to the point
  364. var F = new THREE.Vector3();
  365. var R = new THREE.Vector3();
  366. var n;
  367. for (i=0, il = originalPoints.length; i<il; i++) {
  368. // (F + 2R + (n-3)P) / n
  369. if (vertexEdgeMap[i]===undefined) continue;
  370. F.set(0,0,0);
  371. R.set(0,0,0);
  372. var newPos = new THREE.Vector3(0,0,0);
  373. var f =0;
  374. for (j in vertexFaceMap[i]) {
  375. F.addSelf(facePoints[j]);
  376. f++;
  377. }
  378. var sharpEdgeCount = 0;
  379. n = vertexEdgeMap[i].length;
  380. for (j=0;j<n;j++) {
  381. if (
  382. sharpEdges[
  383. edge_hash(vertexEdgeMap[i][j][0],vertexEdgeMap[i][j][1])
  384. ]) {
  385. sharpEdgeCount++;
  386. }
  387. }
  388. if ( sharpEdgeCount==2 ) {
  389. continue;
  390. // Do not move vertex if there's 2 connecting sharp edges.
  391. }
  392. /*
  393. if (sharpEdgeCount>2) {
  394. // TODO
  395. }
  396. */
  397. F.divideScalar(f);
  398. for (j=0; j<n;j++) {
  399. edge = vertexEdgeMap[i][j];
  400. var midPt = originalPoints[edge[0]].clone().addSelf(originalPoints[edge[1]]).divideScalar(2);
  401. R.addSelf(midPt);
  402. // R.addSelf(originalPoints[edge[0]]);
  403. // R.addSelf(originalPoints[edge[1]]);
  404. }
  405. R.divideScalar(n);
  406. newPos.addSelf(originalPoints[i]);
  407. newPos.multiplyScalar(n - 3);
  408. newPos.addSelf(F);
  409. newPos.addSelf(R.multiplyScalar(2));
  410. newPos.divideScalar(n);
  411. newVertices[i] = newPos;
  412. }
  413. var newGeometry = oldGeometry; // Let's pretend the old geometry is now new :P
  414. newGeometry.vertices = newVertices;
  415. newGeometry.faces = newFaces;
  416. newGeometry.faceVertexUvs[ 0 ] = newUVs;
  417. delete newGeometry.__tmpVertices; // makes __tmpVertices undefined :P
  418. newGeometry.computeCentroids();
  419. newGeometry.computeFaceNormals();
  420. newGeometry.computeVertexNormals();
  421. };
粤ICP备19079148号