ExtrudeGeometry.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. import { BufferGeometry } from '../core/BufferGeometry.js';
  2. import { Float32BufferAttribute } from '../core/BufferAttribute.js';
  3. import * as Curves from '../extras/curves/Curves.js';
  4. import { Vector2 } from '../math/Vector2.js';
  5. import { Vector3 } from '../math/Vector3.js';
  6. import { Shape } from '../extras/core/Shape.js';
  7. import { ShapeUtils } from '../extras/ShapeUtils.js';
  8. /**
  9. * Creates extruded geometry from a path shape.
  10. *
  11. * ```js
  12. * const length = 12, width = 8;
  13. *
  14. * const shape = new THREE.Shape();
  15. * shape.moveTo( 0,0 );
  16. * shape.lineTo( 0, width );
  17. * shape.lineTo( length, width );
  18. * shape.lineTo( length, 0 );
  19. * shape.lineTo( 0, 0 );
  20. *
  21. * const geometry = new THREE.ExtrudeGeometry( shape );
  22. * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
  23. * const mesh = new THREE.Mesh( geometry, material ) ;
  24. * scene.add( mesh );
  25. * ```
  26. *
  27. * @augments BufferGeometry
  28. */
  29. class ExtrudeGeometry extends BufferGeometry {
  30. /**
  31. * Constructs a new extrude geometry.
  32. *
  33. * @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
  34. * @param {ExtrudeGeometry~Options} [options] - The extrude settings.
  35. */
  36. constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) {
  37. super();
  38. this.type = 'ExtrudeGeometry';
  39. /**
  40. * Holds the constructor parameters that have been
  41. * used to generate the geometry. Any modification
  42. * after instantiation does not change the geometry.
  43. *
  44. * @type {Object}
  45. */
  46. this.parameters = {
  47. shapes: shapes,
  48. options: options
  49. };
  50. shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
  51. const scope = this;
  52. const verticesArray = [];
  53. const uvArray = [];
  54. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  55. const shape = shapes[ i ];
  56. addShape( shape );
  57. }
  58. // build geometry
  59. this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
  60. this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
  61. this.computeVertexNormals();
  62. // functions
  63. function addShape( shape ) {
  64. const placeholder = [];
  65. // options
  66. const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
  67. const steps = options.steps !== undefined ? options.steps : 1;
  68. const depth = options.depth !== undefined ? options.depth : 1;
  69. let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
  70. let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
  71. let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
  72. let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
  73. let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
  74. const extrudePath = options.extrudePath;
  75. const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
  76. //
  77. let extrudePts, extrudeByPath = false;
  78. let splineTube, binormal, normal, position2;
  79. if ( extrudePath ) {
  80. extrudePts = extrudePath.getSpacedPoints( steps );
  81. extrudeByPath = true;
  82. bevelEnabled = false; // bevels not supported for path extrusion
  83. // SETUP TNB variables
  84. // TODO1 - have a .isClosed in spline?
  85. splineTube = extrudePath.computeFrenetFrames( steps, false );
  86. // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
  87. binormal = new Vector3();
  88. normal = new Vector3();
  89. position2 = new Vector3();
  90. }
  91. // Safeguards if bevels are not enabled
  92. if ( ! bevelEnabled ) {
  93. bevelSegments = 0;
  94. bevelThickness = 0;
  95. bevelSize = 0;
  96. bevelOffset = 0;
  97. }
  98. // Variables initialization
  99. const shapePoints = shape.extractPoints( curveSegments );
  100. let vertices = shapePoints.shape;
  101. const holes = shapePoints.holes;
  102. const reverse = ! ShapeUtils.isClockWise( vertices );
  103. if ( reverse ) {
  104. vertices = vertices.reverse();
  105. // Maybe we should also check if holes are in the opposite direction, just to be safe ...
  106. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  107. const ahole = holes[ h ];
  108. if ( ShapeUtils.isClockWise( ahole ) ) {
  109. holes[ h ] = ahole.reverse();
  110. }
  111. }
  112. }
  113. const faces = ShapeUtils.triangulateShape( vertices, holes );
  114. /* Vertices */
  115. const contour = vertices; // vertices has all points but contour has only points of circumference
  116. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  117. const ahole = holes[ h ];
  118. vertices = vertices.concat( ahole );
  119. }
  120. function scalePt2( pt, vec, size ) {
  121. if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
  122. return pt.clone().addScaledVector( vec, size );
  123. }
  124. const vlen = vertices.length, flen = faces.length;
  125. // Find directions for point movement
  126. function getBevelVec( inPt, inPrev, inNext ) {
  127. // computes for inPt the corresponding point inPt' on a new contour
  128. // shifted by 1 unit (length of normalized vector) to the left
  129. // if we walk along contour clockwise, this new contour is outside the old one
  130. //
  131. // inPt' is the intersection of the two lines parallel to the two
  132. // adjacent edges of inPt at a distance of 1 unit on the left side.
  133. let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
  134. // good reading for geometry algorithms (here: line-line intersection)
  135. // http://geomalgorithms.com/a05-_intersect-1.html
  136. const v_prev_x = inPt.x - inPrev.x,
  137. v_prev_y = inPt.y - inPrev.y;
  138. const v_next_x = inNext.x - inPt.x,
  139. v_next_y = inNext.y - inPt.y;
  140. const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
  141. // check for collinear edges
  142. const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  143. if ( Math.abs( collinear0 ) > Number.EPSILON ) {
  144. // not collinear
  145. // length of vectors for normalizing
  146. const v_prev_len = Math.sqrt( v_prev_lensq );
  147. const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
  148. // shift adjacent points by unit vectors to the left
  149. const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
  150. const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
  151. const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
  152. const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
  153. // scaling factor for v_prev to intersection point
  154. const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
  155. ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
  156. ( v_prev_x * v_next_y - v_prev_y * v_next_x );
  157. // vector from inPt to intersection point
  158. v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
  159. v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
  160. // Don't normalize!, otherwise sharp corners become ugly
  161. // but prevent crazy spikes
  162. const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
  163. if ( v_trans_lensq <= 2 ) {
  164. return new Vector2( v_trans_x, v_trans_y );
  165. } else {
  166. shrink_by = Math.sqrt( v_trans_lensq / 2 );
  167. }
  168. } else {
  169. // handle special case of collinear edges
  170. let direction_eq = false; // assumes: opposite
  171. if ( v_prev_x > Number.EPSILON ) {
  172. if ( v_next_x > Number.EPSILON ) {
  173. direction_eq = true;
  174. }
  175. } else {
  176. if ( v_prev_x < - Number.EPSILON ) {
  177. if ( v_next_x < - Number.EPSILON ) {
  178. direction_eq = true;
  179. }
  180. } else {
  181. if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
  182. direction_eq = true;
  183. }
  184. }
  185. }
  186. if ( direction_eq ) {
  187. // console.log("Warning: lines are a straight sequence");
  188. v_trans_x = - v_prev_y;
  189. v_trans_y = v_prev_x;
  190. shrink_by = Math.sqrt( v_prev_lensq );
  191. } else {
  192. // console.log("Warning: lines are a straight spike");
  193. v_trans_x = v_prev_x;
  194. v_trans_y = v_prev_y;
  195. shrink_by = Math.sqrt( v_prev_lensq / 2 );
  196. }
  197. }
  198. return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
  199. }
  200. const contourMovements = [];
  201. for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  202. if ( j === il ) j = 0;
  203. if ( k === il ) k = 0;
  204. // (j)---(i)---(k)
  205. // console.log('i,j,k', i, j , k)
  206. contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
  207. }
  208. const holesMovements = [];
  209. let oneHoleMovements, verticesMovements = contourMovements.concat();
  210. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  211. const ahole = holes[ h ];
  212. oneHoleMovements = [];
  213. for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
  214. if ( j === il ) j = 0;
  215. if ( k === il ) k = 0;
  216. // (j)---(i)---(k)
  217. oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
  218. }
  219. holesMovements.push( oneHoleMovements );
  220. verticesMovements = verticesMovements.concat( oneHoleMovements );
  221. }
  222. // Loop bevelSegments, 1 for the front, 1 for the back
  223. for ( let b = 0; b < bevelSegments; b ++ ) {
  224. //for ( b = bevelSegments; b > 0; b -- ) {
  225. const t = b / bevelSegments;
  226. const z = bevelThickness * Math.cos( t * Math.PI / 2 );
  227. const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
  228. // contract shape
  229. for ( let i = 0, il = contour.length; i < il; i ++ ) {
  230. const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  231. v( vert.x, vert.y, - z );
  232. }
  233. // expand holes
  234. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  235. const ahole = holes[ h ];
  236. oneHoleMovements = holesMovements[ h ];
  237. for ( let i = 0, il = ahole.length; i < il; i ++ ) {
  238. const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  239. v( vert.x, vert.y, - z );
  240. }
  241. }
  242. }
  243. const bs = bevelSize + bevelOffset;
  244. // Back facing vertices
  245. for ( let i = 0; i < vlen; i ++ ) {
  246. const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  247. if ( ! extrudeByPath ) {
  248. v( vert.x, vert.y, 0 );
  249. } else {
  250. // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
  251. normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
  252. binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
  253. position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
  254. v( position2.x, position2.y, position2.z );
  255. }
  256. }
  257. // Add stepped vertices...
  258. // Including front facing vertices
  259. for ( let s = 1; s <= steps; s ++ ) {
  260. for ( let i = 0; i < vlen; i ++ ) {
  261. const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
  262. if ( ! extrudeByPath ) {
  263. v( vert.x, vert.y, depth / steps * s );
  264. } else {
  265. // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
  266. normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
  267. binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
  268. position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
  269. v( position2.x, position2.y, position2.z );
  270. }
  271. }
  272. }
  273. // Add bevel segments planes
  274. //for ( b = 1; b <= bevelSegments; b ++ ) {
  275. for ( let b = bevelSegments - 1; b >= 0; b -- ) {
  276. const t = b / bevelSegments;
  277. const z = bevelThickness * Math.cos( t * Math.PI / 2 );
  278. const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
  279. // contract shape
  280. for ( let i = 0, il = contour.length; i < il; i ++ ) {
  281. const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
  282. v( vert.x, vert.y, depth + z );
  283. }
  284. // expand holes
  285. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  286. const ahole = holes[ h ];
  287. oneHoleMovements = holesMovements[ h ];
  288. for ( let i = 0, il = ahole.length; i < il; i ++ ) {
  289. const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
  290. if ( ! extrudeByPath ) {
  291. v( vert.x, vert.y, depth + z );
  292. } else {
  293. v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
  294. }
  295. }
  296. }
  297. }
  298. /* Faces */
  299. // Top and bottom faces
  300. buildLidFaces();
  301. // Sides faces
  302. buildSideFaces();
  303. ///// Internal functions
  304. function buildLidFaces() {
  305. const start = verticesArray.length / 3;
  306. if ( bevelEnabled ) {
  307. let layer = 0; // steps + 1
  308. let offset = vlen * layer;
  309. // Bottom faces
  310. for ( let i = 0; i < flen; i ++ ) {
  311. const face = faces[ i ];
  312. f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
  313. }
  314. layer = steps + bevelSegments * 2;
  315. offset = vlen * layer;
  316. // Top faces
  317. for ( let i = 0; i < flen; i ++ ) {
  318. const face = faces[ i ];
  319. f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
  320. }
  321. } else {
  322. // Bottom faces
  323. for ( let i = 0; i < flen; i ++ ) {
  324. const face = faces[ i ];
  325. f3( face[ 2 ], face[ 1 ], face[ 0 ] );
  326. }
  327. // Top faces
  328. for ( let i = 0; i < flen; i ++ ) {
  329. const face = faces[ i ];
  330. f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
  331. }
  332. }
  333. scope.addGroup( start, verticesArray.length / 3 - start, 0 );
  334. }
  335. // Create faces for the z-sides of the shape
  336. function buildSideFaces() {
  337. const start = verticesArray.length / 3;
  338. let layeroffset = 0;
  339. sidewalls( contour, layeroffset );
  340. layeroffset += contour.length;
  341. for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
  342. const ahole = holes[ h ];
  343. sidewalls( ahole, layeroffset );
  344. //, true
  345. layeroffset += ahole.length;
  346. }
  347. scope.addGroup( start, verticesArray.length / 3 - start, 1 );
  348. }
  349. function sidewalls( contour, layeroffset ) {
  350. let i = contour.length;
  351. while ( -- i >= 0 ) {
  352. const j = i;
  353. let k = i - 1;
  354. if ( k < 0 ) k = contour.length - 1;
  355. //console.log('b', i,j, i-1, k,vertices.length);
  356. for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
  357. const slen1 = vlen * s;
  358. const slen2 = vlen * ( s + 1 );
  359. const a = layeroffset + j + slen1,
  360. b = layeroffset + k + slen1,
  361. c = layeroffset + k + slen2,
  362. d = layeroffset + j + slen2;
  363. f4( a, b, c, d );
  364. }
  365. }
  366. }
  367. function v( x, y, z ) {
  368. placeholder.push( x );
  369. placeholder.push( y );
  370. placeholder.push( z );
  371. }
  372. function f3( a, b, c ) {
  373. addVertex( a );
  374. addVertex( b );
  375. addVertex( c );
  376. const nextIndex = verticesArray.length / 3;
  377. const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  378. addUV( uvs[ 0 ] );
  379. addUV( uvs[ 1 ] );
  380. addUV( uvs[ 2 ] );
  381. }
  382. function f4( a, b, c, d ) {
  383. addVertex( a );
  384. addVertex( b );
  385. addVertex( d );
  386. addVertex( b );
  387. addVertex( c );
  388. addVertex( d );
  389. const nextIndex = verticesArray.length / 3;
  390. const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
  391. addUV( uvs[ 0 ] );
  392. addUV( uvs[ 1 ] );
  393. addUV( uvs[ 3 ] );
  394. addUV( uvs[ 1 ] );
  395. addUV( uvs[ 2 ] );
  396. addUV( uvs[ 3 ] );
  397. }
  398. function addVertex( index ) {
  399. verticesArray.push( placeholder[ index * 3 + 0 ] );
  400. verticesArray.push( placeholder[ index * 3 + 1 ] );
  401. verticesArray.push( placeholder[ index * 3 + 2 ] );
  402. }
  403. function addUV( vector2 ) {
  404. uvArray.push( vector2.x );
  405. uvArray.push( vector2.y );
  406. }
  407. }
  408. }
  409. copy( source ) {
  410. super.copy( source );
  411. this.parameters = Object.assign( {}, source.parameters );
  412. return this;
  413. }
  414. toJSON() {
  415. const data = super.toJSON();
  416. const shapes = this.parameters.shapes;
  417. const options = this.parameters.options;
  418. return toJSON( shapes, options, data );
  419. }
  420. /**
  421. * Factory method for creating an instance of this class from the given
  422. * JSON object.
  423. *
  424. * @param {Object} data - A JSON object representing the serialized geometry.
  425. * @param {Array<Shape>} shapes - An array of shapes.
  426. * @return {ExtrudeGeometry} A new instance.
  427. */
  428. static fromJSON( data, shapes ) {
  429. const geometryShapes = [];
  430. for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
  431. const shape = shapes[ data.shapes[ j ] ];
  432. geometryShapes.push( shape );
  433. }
  434. const extrudePath = data.options.extrudePath;
  435. if ( extrudePath !== undefined ) {
  436. data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
  437. }
  438. return new ExtrudeGeometry( geometryShapes, data.options );
  439. }
  440. }
  441. const WorldUVGenerator = {
  442. generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
  443. const a_x = vertices[ indexA * 3 ];
  444. const a_y = vertices[ indexA * 3 + 1 ];
  445. const b_x = vertices[ indexB * 3 ];
  446. const b_y = vertices[ indexB * 3 + 1 ];
  447. const c_x = vertices[ indexC * 3 ];
  448. const 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. const a_x = vertices[ indexA * 3 ];
  457. const a_y = vertices[ indexA * 3 + 1 ];
  458. const a_z = vertices[ indexA * 3 + 2 ];
  459. const b_x = vertices[ indexB * 3 ];
  460. const b_y = vertices[ indexB * 3 + 1 ];
  461. const b_z = vertices[ indexB * 3 + 2 ];
  462. const c_x = vertices[ indexC * 3 ];
  463. const c_y = vertices[ indexC * 3 + 1 ];
  464. const c_z = vertices[ indexC * 3 + 2 ];
  465. const d_x = vertices[ indexD * 3 ];
  466. const d_y = vertices[ indexD * 3 + 1 ];
  467. const d_z = vertices[ indexD * 3 + 2 ];
  468. if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
  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. function toJSON( shapes, options, data ) {
  486. data.shapes = [];
  487. if ( Array.isArray( shapes ) ) {
  488. for ( let i = 0, l = shapes.length; i < l; i ++ ) {
  489. const shape = shapes[ i ];
  490. data.shapes.push( shape.uuid );
  491. }
  492. } else {
  493. data.shapes.push( shapes.uuid );
  494. }
  495. data.options = Object.assign( {}, options );
  496. if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
  497. return data;
  498. }
  499. /**
  500. * Represents the `options` type of the geometry's constructor.
  501. *
  502. * @typedef {Object} ExtrudeGeometry~Options
  503. * @property {number} [curveSegments=12] - Number of points on the curves.
  504. * @property {number} [steps=1] - Number of points used for subdividing segments along the depth of the extruded spline.
  505. * @property {number} [depth=1] - Depth to extrude the shape.
  506. * @property {boolean} [bevelEnabled=true] - Whether to beveling to the shape or not.
  507. * @property {number} [bevelThickness=0.2] - How deep into the original shape the bevel goes.
  508. * @property {number} [bevelSize=bevelThickness-0.1] - Distance from the shape outline that the bevel extends.
  509. * @property {number} [bevelOffset=0] - Distance from the shape outline that the bevel starts.
  510. * @property {number} [bevelSegments=3] - Number of bevel layers.
  511. * @property {?Curve} [extrudePath=null] - A 3D spline path along which the shape should be extruded. Bevels not supported for path extrusion.
  512. * @property {Object} [UVGenerator] - An object that provides UV generator functions for custom UV generation.
  513. **/
  514. export { ExtrudeGeometry };
粤ICP备19079148号