ExtrudeGeometry.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. import { BufferGeometry } from '../core/BufferGeometry';
  2. import { Float32BufferAttribute } from '../core/BufferAttribute';
  3. import { Vector2 } from '../math/Vector2';
  4. import { Vector3 } from '../math/Vector3';
  5. import { ShapeUtils } from '../extras/ShapeUtils';
  6. /**
  7. * @author zz85 / http://www.lab4games.net/zz85/blog
  8. *
  9. * Creates extruded geometry from a path shape.
  10. *
  11. * parameters = {
  12. *
  13. * curveSegments: <int>, // number of points on the curves
  14. * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
  15. * amount: <int>, // Depth to extrude the shape
  16. *
  17. * bevelEnabled: <bool>, // turn on bevel
  18. * bevelThickness: <float>, // how deep into the original shape bevel goes
  19. * bevelSize: <float>, // how far from shape outline is bevel
  20. * bevelSegments: <int>, // number of bevel layers
  21. *
  22. * extrudePath: <THREE.Curve> // curve to extrude shape along
  23. * frames: <Object> // containing arrays of tangents, normals, binormals
  24. *
  25. * UVGenerator: <Object> // object that provides UV generator functions
  26. *
  27. * }
  28. **/
  29. import { Geometry } from '../core/Geometry';
  30. function ExtrudeGeometry( shapes, options ) {
  31. Geometry.call( this );
  32. this.type = 'ExtrudeGeometry';
  33. this.parameters = {
  34. shapes: shapes,
  35. options: options
  36. };
  37. this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
  38. this.mergeVertices();
  39. }
  40. ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
  41. ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
  42. function ExtrudeBufferGeometry( shapes, options ) {
  43. if ( typeof ( shapes ) === "undefined" ) {
  44. shapes = [];
  45. return;
  46. }
  47. BufferGeometry.call( this );
  48. this.type = 'ExtrudeBufferGeometry';
  49. shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
  50. this.addShapeList( shapes, options );
  51. this.computeFaceNormals();
  52. // can't really use automatic vertex normals
  53. // as then front and back sides get smoothed too
  54. // should do separate smoothing just for sides
  55. //this.computeVertexNormals();
  56. //console.log( "took", ( Date.now() - startTime ) );
  57. }
  58. ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
  59. ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
  60. ExtrudeBufferGeometry.prototype.getArrays = function () {
  61. var positionAttribute = this.getAttribute( "position" );
  62. var verticesArray = positionAttribute ? Array.prototype.slice.call( positionAttribute.array ) : [];
  63. var uvAttribute = this.getAttribute( "uv" );
  64. var uvArray = uvAttribute ? Array.prototype.slice.call( uvAttribute.array ) : [];
  65. var IndexAttribute = this.index;
  66. var indicesArray = IndexAttribute ? Array.prototype.slice.call( IndexAttribute.array ) : [];
  67. return {
  68. position: verticesArray,
  69. uv: uvArray,
  70. index: indicesArray
  71. };
  72. };
  73. ExtrudeBufferGeometry.prototype.addShapeList = function ( shapes, options ) {
  74. var sl = shapes.length;
  75. options.arrays = this.getArrays();
  76. for ( var s = 0; s < sl; s ++ ) {
  77. var shape = shapes[ s ];
  78. this.addShape( shape, options );
  79. }
  80. this.setIndex( options.arrays.index );
  81. this.addAttribute( 'position', new Float32BufferAttribute( options.arrays.position, 3 ) );
  82. this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) );
  83. };
  84. ExtrudeBufferGeometry.prototype.addShape = function ( shape, options ) {
  85. var arrays = options.arrays ? options.arrays : this.getArrays();
  86. var verticesArray = arrays.position;
  87. var indicesArray = arrays.index;
  88. var uvArray = arrays.uv;
  89. var placeholder = [];
  90. var amount = options.amount !== undefined ? options.amount : 100;
  91. var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
  92. var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
  93. var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
  94. var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
  95. var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
  96. var steps = options.steps !== undefined ? options.steps : 1;
  97. var extrudePath = options.extrudePath;
  98. var extrudePts, extrudeByPath = false;
  99. // Use default WorldUVGenerator if no UV generators are specified.
  100. var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : ExtrudeGeometry.WorldUVGenerator;
  101. var splineTube, binormal, normal, position2;
  102. if ( extrudePath ) {
  103. extrudePts = extrudePath.getSpacedPoints( steps );
  104. extrudeByPath = true;
  105. bevelEnabled = false; // bevels not supported for path extrusion
  106. // SETUP TNB variables
  107. // TODO1 - have a .isClosed in spline?
  108. splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false );
  109. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  110. binormal = new Vector3();
  111. normal = new Vector3();
  112. position2 = new Vector3();
  113. }
  114. // Safeguards if bevels are not enabled
  115. if ( ! bevelEnabled ) {
  116. bevelSegments = 0;
  117. bevelThickness = 0;
  118. bevelSize = 0;
  119. }
  120. // Variables initialization
  121. var ahole, h, hl; // looping of holes
  122. var scope = this;
  123. var shapePoints = shape.extractPoints( curveSegments );
  124. var vertices = shapePoints.shape;
  125. var holes = shapePoints.holes;
  126. var reverse = ! ShapeUtils.isClockWise( vertices );
  127. if ( reverse ) {
  128. vertices = vertices.reverse();
  129. // Maybe we should also check if holes are in the opposite direction, just to be safe ...
  130. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  131. ahole = holes[ h ];
  132. if ( ShapeUtils.isClockWise( ahole ) ) {
  133. holes[ h ] = ahole.reverse();
  134. }
  135. }
  136. reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
  137. }
  138. var faces = ShapeUtils.triangulateShape( vertices, holes );
  139. /* Vertices */
  140. var contour = vertices; // vertices has all points but contour has only points of circumference
  141. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  142. ahole = holes[ h ];
  143. vertices = vertices.concat( ahole );
  144. }
  145. function scalePt2( pt, vec, size ) {
  146. if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
  147. return vec.clone().multiplyScalar( size ).add( pt );
  148. }
  149. var b, bs, t, z,
  150. vert, vlen = vertices.length,
  151. face, flen = faces.length;
  152. // Find directions for point movement
  153. function getBevelVec( inPt, inPrev, inNext ) {
  154. // computes for inPt the corresponding point inPt' on a new contour
  155. // shifted by 1 unit (length of normalized vector) to the left
  156. // if we walk along contour clockwise, this new contour is outside the old one
  157. //
  158. // inPt' is the intersection of the two lines parallel to the two
  159. // adjacent edges of inPt at a distance of 1 unit on the left side.
  160. var v_trans_x, v_trans_y, shrink_by = 1; // resulting translation vector for inPt
  161. // good reading for geometry algorithms (here: line-line intersection)
  162. // http://geomalgorithms.com/a05-_intersect-1.html
  163. var v_prev_x = inPt.x - inPrev.x,
  164. v_prev_y = inPt.y - inPrev.y;
  165. var v_next_x = inNext.x - inPt.x,
  166. v_next_y = inNext.y - inPt.y;
  167. var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
  168. // check for collinear edges
  169. var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  170. if ( Math.abs( collinear0 ) > Number.EPSILON ) {
  171. // not collinear
  172. // length of vectors for normalizing
  173. var v_prev_len = Math.sqrt( v_prev_lensq );
  174. var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
  175. // shift adjacent points by unit vectors to the left
  176. var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
  177. var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
  178. var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
  179. var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
  180. // scaling factor for v_prev to intersection point
  181. var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
  182. ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
  183. ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  184. // vector from inPt to intersection point
  185. v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
  186. v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
  187. // Don't normalize!, otherwise sharp corners become ugly
  188. // but prevent crazy spikes
  189. var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
  190. if ( v_trans_lensq <= 2 ) {
  191. return new Vector2( v_trans_x, v_trans_y );
  192. } else {
  193. shrink_by = Math.sqrt( v_trans_lensq / 2 );
  194. }
  195. } else {
  196. // handle special case of collinear edges
  197. var direction_eq = false; // assumes: opposite
  198. if ( v_prev_x > Number.EPSILON ) {
  199. if ( v_next_x > Number.EPSILON ) {
  200. direction_eq = true;
  201. }
  202. } else {
  203. if ( v_prev_x < - Number.EPSILON ) {
  204. if ( v_next_x < - Number.EPSILON ) {
  205. direction_eq = true;
  206. }
  207. } else {
  208. if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
  209. direction_eq = true;
  210. }
  211. }
  212. }
  213. if ( direction_eq ) {
  214. // console.log("Warning: lines are a straight sequence");
  215. v_trans_x = - v_prev_y;
  216. v_trans_y = v_prev_x;
  217. shrink_by = Math.sqrt( v_prev_lensq );
  218. } else {
  219. // console.log("Warning: lines are a straight spike");
  220. v_trans_x = v_prev_x;
  221. v_trans_y = v_prev_y;
  222. shrink_by = Math.sqrt( v_prev_lensq / 2 );
  223. }
  224. }
  225. return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
  226. }
  227. var contourMovements = [];
  228. for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  229. if ( j === il ) j = 0;
  230. if ( k === il ) k = 0;
  231. // (j)---(i)---(k)
  232. // console.log('i,j,k', i, j , k)
  233. contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
  234. }
  235. var holesMovements = [],
  236. oneHoleMovements, verticesMovements = contourMovements.concat();
  237. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  238. ahole = holes[ h ];
  239. oneHoleMovements = [];
  240. for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  241. if ( j === il ) j = 0;
  242. if ( k === il ) k = 0;
  243. // (j)---(i)---(k)
  244. oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
  245. }
  246. holesMovements.push( oneHoleMovements );
  247. verticesMovements = verticesMovements.concat( oneHoleMovements );
  248. }
  249. // Loop bevelSegments, 1 for the front, 1 for the back
  250. for ( b = 0; b < bevelSegments; b ++ ) {
  251. //for ( b = bevelSegments; b > 0; b -- ) {
  252. t = b / bevelSegments;
  253. z = bevelThickness * Math.cos( t * Math.PI / 2 );
  254. bs = bevelSize * Math.sin( t * Math.PI / 2 );
  255. // contract shape
  256. for ( i = 0, il = contour.length; i < il; i ++ ) {
  257. vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  258. v( vert.x, vert.y, - z );
  259. }
  260. // expand holes
  261. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  262. ahole = holes[ h ];
  263. oneHoleMovements = holesMovements[ h ];
  264. for ( i = 0, il = ahole.length; i < il; i ++ ) {
  265. vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  266. v( vert.x, vert.y, - z );
  267. }
  268. }
  269. }
  270. bs = bevelSize;
  271. // Back facing vertices
  272. for ( i = 0; i < vlen; i ++ ) {
  273. vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  274. if ( ! extrudeByPath ) {
  275. v( vert.x, vert.y, 0 );
  276. } else {
  277. // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  278. normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
  279. binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
  280. position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
  281. v( position2.x, position2.y, position2.z );
  282. }
  283. }
  284. // Add stepped vertices...
  285. // Including front facing vertices
  286. var s;
  287. for ( s = 1; s <= steps; s ++ ) {
  288. for ( i = 0; i < vlen; i ++ ) {
  289. vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  290. if ( ! extrudeByPath ) {
  291. v( vert.x, vert.y, amount / steps * s );
  292. } else {
  293. // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  294. normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
  295. binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
  296. position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
  297. v( position2.x, position2.y, position2.z );
  298. }
  299. }
  300. }
  301. // Add bevel segments planes
  302. //for ( b = 1; b <= bevelSegments; b ++ ) {
  303. for ( b = bevelSegments - 1; b >= 0; b -- ) {
  304. t = b / bevelSegments;
  305. z = bevelThickness * Math.cos( t * Math.PI / 2 );
  306. bs = bevelSize * Math.sin( t * Math.PI / 2 );
  307. // contract shape
  308. for ( i = 0, il = contour.length; i < il; i ++ ) {
  309. vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  310. v( vert.x, vert.y, amount + z );
  311. }
  312. // expand holes
  313. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  314. ahole = holes[ h ];
  315. oneHoleMovements = holesMovements[ h ];
  316. for ( i = 0, il = ahole.length; i < il; i ++ ) {
  317. vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  318. if ( ! extrudeByPath ) {
  319. v( vert.x, vert.y, amount + z );
  320. } else {
  321. v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
  322. }
  323. }
  324. }
  325. }
  326. /* Faces */
  327. // Top and bottom faces
  328. buildLidFaces();
  329. // Sides faces
  330. buildSideFaces();
  331. ///// Internal functions
  332. function buildLidFaces() {
  333. if ( bevelEnabled ) {
  334. var layer = 0; // steps + 1
  335. var offset = vlen * layer;
  336. // Bottom faces
  337. for ( i = 0; i < flen; i ++ ) {
  338. face = faces[ i ];
  339. f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
  340. }
  341. layer = steps + bevelSegments * 2;
  342. offset = vlen * layer;
  343. // Top faces
  344. for ( i = 0; i < flen; i ++ ) {
  345. face = faces[ i ];
  346. f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
  347. }
  348. } else {
  349. // Bottom faces
  350. for ( i = 0; i < flen; i ++ ) {
  351. face = faces[ i ];
  352. f3( face[ 2 ], face[ 1 ], face[ 0 ] );
  353. }
  354. // Top faces
  355. for ( i = 0; i < flen; i ++ ) {
  356. face = faces[ i ];
  357. f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
  358. }
  359. }
  360. }
  361. // Create faces for the z-sides of the shape
  362. function buildSideFaces() {
  363. var layeroffset = 0;
  364. sidewalls( contour, layeroffset );
  365. layeroffset += contour.length;
  366. for ( h = 0, hl = holes.length; h < hl; h ++ ) {
  367. ahole = holes[ h ];
  368. sidewalls( ahole, layeroffset );
  369. //, true
  370. layeroffset += ahole.length;
  371. }
  372. }
  373. function sidewalls( contour, layeroffset ) {
  374. var j, k;
  375. i = contour.length;
  376. while ( -- i >= 0 ) {
  377. j = i;
  378. k = i - 1;
  379. if ( k < 0 ) k = contour.length - 1;
  380. //console.log('b', i,j, i-1, k,vertices.length);
  381. var s = 0,
  382. sl = steps + bevelSegments * 2;
  383. for ( s = 0; s < sl; s ++ ) {
  384. var slen1 = vlen * s;
  385. var slen2 = vlen * ( s + 1 );
  386. var a = layeroffset + j + slen1,
  387. b = layeroffset + k + slen1,
  388. c = layeroffset + k + slen2,
  389. d = layeroffset + j + slen2;
  390. f4( a, b, c, d, contour, s, sl, j, k );
  391. }
  392. }
  393. }
  394. function v( x, y, z ) {
  395. placeholder.push( x );
  396. placeholder.push( y );
  397. placeholder.push( z );
  398. }
  399. function f3( a, b, c ) {
  400. addVertex( a );
  401. addVertex( b );
  402. addVertex( c );
  403. var nextIndex = verticesArray.length / 3;
  404. var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  405. addUV( uvs[ 0 ] );
  406. addUV( uvs[ 1 ] );
  407. addUV( uvs[ 2 ] );
  408. }
  409. function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
  410. addVertex( a );
  411. addVertex( b );
  412. addVertex( d );
  413. addVertex( b );
  414. addVertex( c );
  415. addVertex( d );
  416. var nextIndex = verticesArray.length / 3;
  417. var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  418. addUV( uvs[ 0 ] );
  419. addUV( uvs[ 1 ] );
  420. addUV( uvs[ 3 ] );
  421. addUV( uvs[ 1 ] );
  422. addUV( uvs[ 2 ] );
  423. addUV( uvs[ 3 ] );
  424. }
  425. function addVertex( index ) {
  426. indicesArray.push( verticesArray.length / 3 );
  427. verticesArray.push( placeholder[ index * 3 + 0 ] );
  428. verticesArray.push( placeholder[ index * 3 + 1 ] );
  429. verticesArray.push( placeholder[ index * 3 + 2 ] );
  430. }
  431. function addUV( vector2 ) {
  432. uvArray.push( vector2.x );
  433. uvArray.push( vector2.y );
  434. }
  435. if ( ! options.arrays ) {
  436. this.setIndex( indicesArray );
  437. this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
  438. this.addAttribute( 'uv', new Float32BufferAttribute( options.arrays.uv, 2 ) );
  439. }
  440. };
  441. ExtrudeGeometry.WorldUVGenerator = {
  442. generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
  443. var a_x = vertices[ indexA * 3 ];
  444. var a_y = vertices[ indexA * 3 + 1 ];
  445. var b_x = vertices[ indexB * 3 ];
  446. var b_y = vertices[ indexB * 3 + 1 ];
  447. var c_x = vertices[ indexC * 3 ];
  448. var c_y = vertices[ indexC * 3 + 1 ];
  449. return [
  450. new Vector2( a_x, a_y ),
  451. new Vector2( b_x, b_y ),
  452. new Vector2( c_x, c_y )
  453. ];
  454. },
  455. generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
  456. var a_x = vertices[ indexA * 3 ];
  457. var a_y = vertices[ indexA * 3 + 1 ];
  458. var a_z = vertices[ indexA * 3 + 2 ];
  459. var b_x = vertices[ indexB * 3 ];
  460. var b_y = vertices[ indexB * 3 + 1 ];
  461. var b_z = vertices[ indexB * 3 + 2 ];
  462. var c_x = vertices[ indexC * 3 ];
  463. var c_y = vertices[ indexC * 3 + 1 ];
  464. var c_z = vertices[ indexC * 3 + 2 ];
  465. var d_x = vertices[ indexD * 3 ];
  466. var d_y = vertices[ indexD * 3 + 1 ];
  467. var d_z = vertices[ indexD * 3 + 2 ];
  468. if ( Math.abs( a_y - b_y ) < 0.01 ) {
  469. return [
  470. new Vector2( a_x, 1 - a_z ),
  471. new Vector2( b_x, 1 - b_z ),
  472. new Vector2( c_x, 1 - c_z ),
  473. new Vector2( d_x, 1 - d_z )
  474. ];
  475. } else {
  476. return [
  477. new Vector2( a_y, 1 - a_z ),
  478. new Vector2( b_y, 1 - b_z ),
  479. new Vector2( c_y, 1 - c_z ),
  480. new Vector2( d_y, 1 - d_z )
  481. ];
  482. }
  483. }
  484. };
  485. export {
  486. ExtrudeGeometry,
  487. ExtrudeBufferGeometry
  488. };