ExtrudeGeometry.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**
  2. * @author zz85 / http://www.lab4games.net/zz85/blog
  3. * Creates extruded geometry from a path shape.
  4. **/
  5. THREE.ExtrudeGeometry = function( shapes, options ) {
  6. THREE.Geometry.call( this );
  7. shapes = shapes instanceof Array ? shapes : [ shapes ];
  8. var s=0, sl = shapes.length, shape;
  9. for (;s<sl;s++) {
  10. shape = shapes[s];
  11. console.log(shape);
  12. this.addShape( shape, options );
  13. }
  14. };
  15. THREE.ExtrudeGeometry.prototype = new THREE.Geometry();
  16. THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry;
  17. THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
  18. var amount = options.amount !== undefined ? options.amount : 100;
  19. var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
  20. var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness; // 8
  21. var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
  22. var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
  23. // We should set bevel segments to 0 if bevel is not enabled.
  24. if (!bevelEnabled) bevelSegments = 0 ;
  25. var steps = options.steps !== undefined ? options.steps : 1;
  26. var extrudePath = options.path !== undefined ? options.path : null;
  27. var extrudePts, extrudeByPath = false;
  28. if ( extrudePath ) {
  29. extrudePts = extrudePath.getPoints();
  30. steps = extrudePts.length;
  31. extrudeByPath = true;
  32. }
  33. // TODO, extrude by path's tangents? also via 3d path?
  34. // Variables initalization
  35. var ahole, h, hl; // looping of holes
  36. var scope = this;
  37. var bevelPoints = [];
  38. var shapesOffset = this.vertices.length;
  39. // getPoints
  40. var shapePoints = shape.extractAllPoints(false, 8);
  41. // false for getPoints | true for getSpacedPoints() for points with equal divisions
  42. var vertices = shapePoints.shape;
  43. var holes = shapePoints.holes;
  44. var reverse = !THREE.Shape.Utils.isClockWise( vertices ) ;
  45. if (reverse) {
  46. vertices = vertices.reverse();
  47. // Maybe we should also check if holes are in the opposite direction, just to be safe...
  48. for (h = 0, hl = holes.length; h < hl; h++ ) {
  49. ahole = holes[h];
  50. if (THREE.Shape.Utils.isClockWise(ahole)) {
  51. holes[h] = ahole.reverse();
  52. }
  53. }
  54. reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
  55. }
  56. var faces = THREE.Shape.Utils.triangulateShape(vertices, holes);
  57. //var faces = THREE.Shape.Utils.triangulate2(vertices, holes);
  58. //console.log(faces);
  59. ////
  60. /// Handle Vertices
  61. ////
  62. var contour = vertices; // vertices has all points but contour has only points of circumference
  63. for (h = 0, hl = holes.length; h < hl; h++ ) {
  64. ahole = holes[h];
  65. vertices = vertices.concat(ahole);
  66. }
  67. // Find all centroids of shapes and holes
  68. var b;
  69. var sum = new THREE.Vector2();
  70. var contourCentroid, holesCentroids;
  71. for (i=0, il = contour.length; i<il; i++) {
  72. sum.addSelf(contour[i]);
  73. }
  74. contourCentroid = sum.divideScalar( contour.length ) ;
  75. holesCentroids = [];
  76. for (h=0, hl = holes.length; h<hl; h++) {
  77. sum = new THREE.Vector2();
  78. ahole = holes[h];
  79. for (i=0, il = ahole.length; i<il; i++) {
  80. sum.addSelf(ahole[i]);
  81. }
  82. holesCentroids[h] = sum.divideScalar( ahole.length ) ;
  83. }
  84. function scalePt (pt, centroid, size, expandOutwards /* Boolean */ ) {
  85. vectorFromCentroid = pt.clone().subSelf( centroid );
  86. adj = size / vectorFromCentroid.length();
  87. if ( expandOutwards ) {
  88. adj += 1;
  89. } else {
  90. adj = 1 - adj;
  91. }
  92. return vectorFromCentroid.multiplyScalar( adj ).addSelf( centroid );
  93. }
  94. function scalePt2 (pt, vec, size ) {
  95. //return vec.clone().multiplyScalar( size ).addSelf( pt );
  96. return pt.clone().addSelf(vec.clone().multiplyScalar( size ));
  97. }
  98. var i,
  99. vert, vlen = vertices.length,
  100. face, flen = faces.length,
  101. cont, clen = contour.length,
  102. hol, hlen;
  103. var bs;
  104. //------
  105. // Find directions for point movement
  106. //
  107. var RAD_TO_DEGREES = 180 / Math.PI;
  108. function getBevelVec(pt_i, pt_j, pt_k) {
  109. var anglea = Math.atan2(pt_j.y - pt_i.y, pt_j.x - pt_i.x);
  110. var angleb = Math.atan2(pt_k.y - pt_i.y, pt_k.x - pt_i.x);
  111. if ( anglea > angleb) {
  112. angleb += Math.PI*2;
  113. }
  114. // var anglea = Math.atan2(pt_i.y - pt_j.y, pt_i.x - pt_j.x);
  115. // var angleb = Math.atan2(pt_i.y - pt_k.y, pt_i.x - pt_k.x);
  116. //
  117. // console.log('>?', anglea > angleb);
  118. //
  119. // if ( anglea < angleb) {
  120. // angleb += Math.PI*2;
  121. // }
  122. //x = Math.cos(anglea) + Math.cos(angleb);
  123. //y = Math.sin(anglea) + Math.sin(angleb);
  124. //anglec = Math.atan2(y,x);
  125. anglec = (anglea + angleb ) / 2;
  126. //console.log('angle1', anglea * RAD_TO_DEGREES,'angle2', angleb * RAD_TO_DEGREES, 'anglec', anglec *RAD_TO_DEGREES);
  127. var x = Math.cos(anglec);
  128. var y = Math.sin(anglec);
  129. var vec = new THREE.Vector2(x,y).normalize();
  130. return vec;
  131. }
  132. var contourMovements = [];
  133. for ( i = 0, il = contour.length, j = il-1, k = i + 1; i < il; i++,j++,k++ ) {
  134. if (j==il) j = 0;
  135. if (k==il) k = 0;
  136. // (j)---(i)---(k)
  137. // console.log('i,j,k', i, j , k)
  138. var pt_i = contour[ i ];
  139. var pt_j = contour[ j ];
  140. var pt_k = contour[ k ];
  141. contourMovements[i]= getBevelVec(contour[ i ], contour[ j ], contour[ k ] );
  142. }
  143. var holesMovements = [], oneHoleMovements;
  144. for ( h = 0, hl = holes.length; h < hl; h++ ) {
  145. ahole = holes[h];
  146. oneHoleMovements = [];
  147. for ( i = 0, il = ahole.length, j = il-1, k = i + 1; i < il; i++,j++,k++ ) {
  148. if (j==il) j = 0;
  149. if (k==il) k = 0;
  150. // (j)---(i)---(k)
  151. oneHoleMovements[i]= getBevelVec(ahole[ i ], ahole[ j ], ahole[ k ] );
  152. }
  153. holesMovements.push(oneHoleMovements);
  154. }
  155. // Loop bevelSegments, 1 for the front, 1 for the back
  156. for (b=bevelSegments; b > 0; b--) {
  157. t = b / bevelSegments;
  158. z = bevelThickness * t;
  159. // Formula could probably be simplified
  160. //bs = bevelSize * (1-Math.sin ((1-t) * Math.PI/2 )) ; //bevelSize * t ;
  161. bs = bevelSize * t ;
  162. // contract shape
  163. for ( i = 0, il = contour.length; i < il; i++ ) {
  164. vert = scalePt2(contour[i], contourMovements[i], bs);
  165. v( vert.x, vert.y, - z);
  166. }
  167. // expand holes
  168. for ( h = 0, hl = holes.length; h < hl; h++ ) {
  169. ahole = holes[h];
  170. oneHoleMovements = holesMovements[h];
  171. for ( i = 0, il = ahole.length; i < il; i++ ) {
  172. vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
  173. v( vert.x, vert.y, -z );
  174. }
  175. }
  176. }
  177. // Back facing vertices
  178. for ( i = 0; i < vlen; i++ ) {
  179. vert = vertices[ i ];
  180. //v( vert.x, vert.y, 0 );
  181. if ( !extrudeByPath ) {
  182. v( vert.x, vert.y, 0 );
  183. } else {
  184. v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  185. }
  186. }
  187. // Add steped vertices...
  188. // Including front facing vertices
  189. var s = 1;
  190. for ( ; s <= steps; s++ ) {
  191. for ( i = 0; i < vlen; i ++ ) {
  192. vert = vertices[ i ];
  193. if ( !extrudeByPath ) {
  194. v( vert.x, vert.y, amount/steps * s );
  195. } else {
  196. v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  197. }
  198. }
  199. }
  200. // Add Bevel Segments planes
  201. for (b=1; b <= bevelSegments; b++) {
  202. t = b / bevelSegments;
  203. z = bevelThickness * t;
  204. bs = bevelSize * (1-Math.sin ((1-t) * Math.PI/2 ));
  205. // contract shape
  206. for ( i = 0, il = contour.length; i < il; i++ ) {
  207. vert = scalePt(contour[i], contourCentroid, bs , false);
  208. v( vert.x, vert.y, amount + z);
  209. }
  210. // expand holes
  211. for ( h = 0, hl = holes.length; h < hl; h++ ) {
  212. ahole = holes[h];
  213. for ( i = 0, il = ahole.length; i < il; i++ ) {
  214. vert = scalePt(ahole[i], holesCentroids[h] , bs , true);
  215. if ( !extrudeByPath ) {
  216. v( vert.x, vert.y, amount + z);
  217. } else {
  218. v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x +z);
  219. }
  220. }
  221. }
  222. }
  223. ////
  224. /// Handle Faces
  225. ////
  226. // Bottom faces
  227. if (bevelEnabled ) {
  228. var layer = 0 ; //steps + 1
  229. var offset = vlen * layer;
  230. for ( i = 0; i < flen; i++ ) {
  231. face = faces[ i ];
  232. f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset);
  233. }
  234. layer = steps + bevelSegments* 2;
  235. offset = vlen * layer;
  236. // Top faces
  237. var layers = (steps + bevelSegments * 2) * vlen;
  238. for ( i = 0; i < flen; i++ ) {
  239. face = faces[ i ];
  240. f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
  241. }
  242. } else {
  243. for ( i = 0; i < flen; i++ ) {
  244. face = faces[ i ];
  245. f3( face[ 2 ], face[ 1 ], face[ 0 ] );
  246. }
  247. // Top faces
  248. var layers = (steps + bevelSegments * 2) * vlen;
  249. for ( i = 0; i < flen; i++ ) {
  250. face = faces[ i ];
  251. f3( face[ 0 ] + vlen* steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
  252. }
  253. }
  254. var tmpPt;
  255. var j, k, l, m;
  256. var layeroffset = 0;
  257. // Sides faces
  258. sidewalls(contour);
  259. layeroffset += contour.length;
  260. for (h = 0, hl = holes.length; h < hl; h++ ) {
  261. ahole = holes[h];
  262. sidewalls(ahole);
  263. //, true
  264. layeroffset += ahole.length;
  265. }
  266. // Create faces for the z-sides of the shape
  267. function sidewalls(contour) {
  268. i = contour.length;
  269. while ( --i >= 0 ) {
  270. tmpPt = contour[ i ];
  271. j = i;
  272. k = i - 1;
  273. if ( k < 0 ) k = contour.length - 1;
  274. //console.log('b', i,j, i-1, k,vertices.length);
  275. var s = 0;
  276. for ( ; s < (steps + bevelSegments * 2) ; s++ ) {
  277. var slen1 = vlen * s;
  278. var slen2 = vlen * ( s + 1 );
  279. f4( layeroffset + j + slen1, layeroffset + k + slen1, layeroffset + k + slen2, layeroffset + j + slen2 );
  280. }
  281. }
  282. }
  283. // UVs to be added
  284. this.computeCentroids();
  285. this.computeFaceNormals();
  286. //this.computeVertexNormals();
  287. function v( x, y, z ) {
  288. scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
  289. }
  290. function f3( a, b, c ) {
  291. a += shapesOffset;
  292. b += shapesOffset;
  293. c += shapesOffset;
  294. scope.faces.push( new THREE.Face3( a, b, c ) );
  295. }
  296. function f4( a, b, c, d ) {
  297. a += shapesOffset;
  298. b += shapesOffset;
  299. c += shapesOffset;
  300. d += shapesOffset;
  301. scope.faces.push( new THREE.Face4( a, b, c, d ) );
  302. }
  303. };
粤ICP备19079148号