xl-public-utils 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,647 @@
1
+ /**
2
+ * Creates extruded geometry from a path shape.
3
+ *
4
+ * parameters = {
5
+ *
6
+ * curveSegments: <int>, // number of points on the curves
7
+ * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
8
+ * depth: <float>, // Depth to extrude the shape
9
+ *
10
+ * bevelEnabled: <bool>, // turn on bevel
11
+ * bevelThickness: <float>, // how deep into the original shape bevel goes
12
+ * bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
13
+ * bevelOffset: <float>, // how far from shape outline does bevel start
14
+ * bevelSegments: <int>, // number of bevel layers
15
+ *
16
+ * extrudePath: <THREE.Curve> // curve to extrude shape along
17
+ *
18
+ * UVGenerator: <Object> // object that provides UV generator functions
19
+ *
20
+ * }
21
+ */
22
+
23
+ import * as Curves from '../curves/Curves.js';
24
+ import { Vector2 } from '../Math/Vector2.js';
25
+ import { Vector3 } from '../Math/Vector3.js';
26
+ import { Shape } from '../Curve/Shape.js';
27
+ import { ShapeUtils } from './ShapeUtils.js';
28
+
29
+ class ExtrudeGeometry {
30
+ 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 = {}) {
31
+ this.type = 'ExtrudeGeometry';
32
+
33
+ this.parameters = {
34
+ shapes: shapes,
35
+ options: options,
36
+ };
37
+ this.groups = [];
38
+
39
+ shapes = Array.isArray(shapes) ? shapes : [shapes];
40
+
41
+ const scope = this;
42
+
43
+ const verticesArray = [];
44
+ let faceArray = [];
45
+ const uvArray = [];
46
+
47
+ for (let i = 0, l = shapes.length; i < l; i++) {
48
+ const shape = shapes[i];
49
+ addShape(shape);
50
+ }
51
+
52
+ // build geometry
53
+ this.vertices = verticesArray;
54
+ // this.faces = [];
55
+ for (let i = 0; i < this.vertices.length / 3; i += 3) {
56
+ faceArray.push(3, i, i + 1, i + 2);
57
+ }
58
+ this.faces = faceArray;
59
+
60
+ // this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3));
61
+ // this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2));
62
+
63
+ // this.computeVertexNormals();
64
+
65
+ // functions
66
+
67
+ function addShape(shape) {
68
+ const placeholder = [];
69
+
70
+ // options
71
+
72
+ const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
73
+ const steps = options.steps !== undefined ? options.steps : 1;
74
+ let depth = options.depth !== undefined ? options.depth : 1;
75
+
76
+ let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
77
+ let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
78
+ let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
79
+ let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
80
+ let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
81
+
82
+ const extrudePath = options.extrudePath;
83
+
84
+ const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
85
+
86
+ // deprecated options
87
+
88
+ if (options.amount !== undefined) {
89
+ console.warn('THREE.ExtrudeBufferGeometry: amount has been renamed to depth.');
90
+ depth = options.amount;
91
+ }
92
+
93
+ //
94
+
95
+ let extrudePts,
96
+ extrudeByPath = false;
97
+ let splineTube, binormal, normal, position2;
98
+
99
+ if (extrudePath) {
100
+ extrudePts = extrudePath.getSpacedPoints(steps);
101
+
102
+ extrudeByPath = true;
103
+ bevelEnabled = false; // bevels not supported for path extrusion
104
+
105
+ // SETUP TNB variables
106
+
107
+ // TODO1 - have a .isClosed in spline?
108
+
109
+ splineTube = extrudePath.computeFrenetFrames(steps, false);
110
+
111
+ // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
112
+
113
+ binormal = new Vector3();
114
+ normal = new Vector3();
115
+ position2 = new Vector3();
116
+ }
117
+
118
+ // Safeguards if bevels are not enabled
119
+
120
+ if (!bevelEnabled) {
121
+ bevelSegments = 0;
122
+ bevelThickness = 0;
123
+ bevelSize = 0;
124
+ bevelOffset = 0;
125
+ }
126
+
127
+ // Variables initialization
128
+
129
+ const shapePoints = shape.extractPoints(curveSegments);
130
+
131
+ let vertices = shapePoints.shape;
132
+ const holes = shapePoints.holes;
133
+
134
+ const reverse = !ShapeUtils.isClockWise(vertices);
135
+
136
+ if (reverse) {
137
+ vertices = vertices.reverse();
138
+
139
+ // Maybe we should also check if holes are in the opposite direction, just to be safe ...
140
+
141
+ for (let h = 0, hl = holes.length; h < hl; h++) {
142
+ const ahole = holes[h];
143
+
144
+ if (ShapeUtils.isClockWise(ahole)) {
145
+ holes[h] = ahole.reverse();
146
+ }
147
+ }
148
+ }
149
+
150
+ const faces = ShapeUtils.triangulateShape(vertices, holes);
151
+
152
+ /* Vertices */
153
+
154
+ const contour = vertices; // vertices has all points but contour has only points of circumference
155
+
156
+ for (let h = 0, hl = holes.length; h < hl; h++) {
157
+ const ahole = holes[h];
158
+
159
+ vertices = vertices.concat(ahole);
160
+ }
161
+
162
+ function scalePt2(pt, vec, size) {
163
+ if (!vec) console.error('THREE.ExtrudeGeometry: vec does not exist');
164
+
165
+ return vec.clone().multiplyScalar(size).add(pt);
166
+ }
167
+
168
+ const vlen = vertices.length,
169
+ flen = faces.length;
170
+
171
+ // Find directions for point movement
172
+
173
+ function getBevelVec(inPt, inPrev, inNext) {
174
+ // computes for inPt the corresponding point inPt' on a new contour
175
+ // shifted by 1 unit (length of normalized vector) to the left
176
+ // if we walk along contour clockwise, this new contour is outside the old one
177
+ //
178
+ // inPt' is the intersection of the two lines parallel to the two
179
+ // adjacent edges of inPt at a distance of 1 unit on the left side.
180
+
181
+ let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
182
+
183
+ // good reading for geometry algorithms (here: line-line intersection)
184
+ // http://geomalgorithms.com/a05-_intersect-1.html
185
+
186
+ const v_prev_x = inPt.x - inPrev.x,
187
+ v_prev_y = inPt.y - inPrev.y;
188
+ const v_next_x = inNext.x - inPt.x,
189
+ v_next_y = inNext.y - inPt.y;
190
+
191
+ const v_prev_lensq = v_prev_x * v_prev_x + v_prev_y * v_prev_y;
192
+
193
+ // check for collinear edges
194
+ const collinear0 = v_prev_x * v_next_y - v_prev_y * v_next_x;
195
+
196
+ if (Math.abs(collinear0) > Number.EPSILON) {
197
+ // not collinear
198
+
199
+ // length of vectors for normalizing
200
+
201
+ const v_prev_len = Math.sqrt(v_prev_lensq);
202
+ const v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y);
203
+
204
+ // shift adjacent points by unit vectors to the left
205
+
206
+ const ptPrevShift_x = inPrev.x - v_prev_y / v_prev_len;
207
+ const ptPrevShift_y = inPrev.y + v_prev_x / v_prev_len;
208
+
209
+ const ptNextShift_x = inNext.x - v_next_y / v_next_len;
210
+ const ptNextShift_y = inNext.y + v_next_x / v_next_len;
211
+
212
+ // scaling factor for v_prev to intersection point
213
+
214
+ const sf =
215
+ ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x);
216
+
217
+ // vector from inPt to intersection point
218
+
219
+ v_trans_x = ptPrevShift_x + v_prev_x * sf - inPt.x;
220
+ v_trans_y = ptPrevShift_y + v_prev_y * sf - inPt.y;
221
+
222
+ // Don't normalize!, otherwise sharp corners become ugly
223
+ // but prevent crazy spikes
224
+ const v_trans_lensq = v_trans_x * v_trans_x + v_trans_y * v_trans_y;
225
+ if (v_trans_lensq <= 2) {
226
+ return new Vector2(v_trans_x, v_trans_y);
227
+ } else {
228
+ shrink_by = Math.sqrt(v_trans_lensq / 2);
229
+ }
230
+ } else {
231
+ // handle special case of collinear edges
232
+
233
+ let direction_eq = false; // assumes: opposite
234
+
235
+ if (v_prev_x > Number.EPSILON) {
236
+ if (v_next_x > Number.EPSILON) {
237
+ direction_eq = true;
238
+ }
239
+ } else {
240
+ if (v_prev_x < -Number.EPSILON) {
241
+ if (v_next_x < -Number.EPSILON) {
242
+ direction_eq = true;
243
+ }
244
+ } else {
245
+ if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
246
+ direction_eq = true;
247
+ }
248
+ }
249
+ }
250
+
251
+ if (direction_eq) {
252
+ // console.log("Warning: lines are a straight sequence");
253
+ v_trans_x = -v_prev_y;
254
+ v_trans_y = v_prev_x;
255
+ shrink_by = Math.sqrt(v_prev_lensq);
256
+ } else {
257
+ // console.log("Warning: lines are a straight spike");
258
+ v_trans_x = v_prev_x;
259
+ v_trans_y = v_prev_y;
260
+ shrink_by = Math.sqrt(v_prev_lensq / 2);
261
+ }
262
+ }
263
+
264
+ return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by);
265
+ }
266
+
267
+ const contourMovements = [];
268
+
269
+ for (let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
270
+ if (j === il) j = 0;
271
+ if (k === il) k = 0;
272
+
273
+ // (j)---(i)---(k)
274
+ // console.log('i,j,k', i, j , k)
275
+
276
+ contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]);
277
+ }
278
+
279
+ const holesMovements = [];
280
+ let oneHoleMovements,
281
+ verticesMovements = contourMovements.concat();
282
+
283
+ for (let h = 0, hl = holes.length; h < hl; h++) {
284
+ const ahole = holes[h];
285
+
286
+ oneHoleMovements = [];
287
+
288
+ for (let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
289
+ if (j === il) j = 0;
290
+ if (k === il) k = 0;
291
+
292
+ // (j)---(i)---(k)
293
+ oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]);
294
+ }
295
+
296
+ holesMovements.push(oneHoleMovements);
297
+ verticesMovements = verticesMovements.concat(oneHoleMovements);
298
+ }
299
+
300
+ // Loop bevelSegments, 1 for the front, 1 for the back
301
+
302
+ for (let b = 0; b < bevelSegments; b++) {
303
+ //for ( b = bevelSegments; b > 0; b -- ) {
304
+
305
+ const t = b / bevelSegments;
306
+ const z = bevelThickness * Math.cos((t * Math.PI) / 2);
307
+ const bs = bevelSize * Math.sin((t * Math.PI) / 2) + bevelOffset;
308
+
309
+ // contract shape
310
+
311
+ for (let i = 0, il = contour.length; i < il; i++) {
312
+ const vert = scalePt2(contour[i], contourMovements[i], bs);
313
+
314
+ v(vert.x, vert.y, -z);
315
+ }
316
+
317
+ // expand holes
318
+
319
+ for (let h = 0, hl = holes.length; h < hl; h++) {
320
+ const ahole = holes[h];
321
+ oneHoleMovements = holesMovements[h];
322
+
323
+ for (let i = 0, il = ahole.length; i < il; i++) {
324
+ const vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
325
+
326
+ v(vert.x, vert.y, -z);
327
+ }
328
+ }
329
+ }
330
+
331
+ const bs = bevelSize + bevelOffset;
332
+
333
+ // Back facing vertices
334
+
335
+ for (let i = 0; i < vlen; i++) {
336
+ const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
337
+
338
+ if (!extrudeByPath) {
339
+ v(vert.x, vert.y, 0);
340
+ } else {
341
+ // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
342
+
343
+ normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
344
+ binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
345
+
346
+ position2.copy(extrudePts[0]).add(normal).add(binormal);
347
+
348
+ v(position2.x, position2.y, position2.z);
349
+ }
350
+ }
351
+
352
+ // Add stepped vertices...
353
+ // Including front facing vertices
354
+
355
+ for (let s = 1; s <= steps; s++) {
356
+ for (let i = 0; i < vlen; i++) {
357
+ const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
358
+
359
+ if (!extrudeByPath) {
360
+ v(vert.x, vert.y, (depth / steps) * s);
361
+ } else {
362
+ // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
363
+
364
+ normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
365
+ binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
366
+
367
+ position2.copy(extrudePts[s]).add(normal).add(binormal);
368
+
369
+ v(position2.x, position2.y, position2.z);
370
+ }
371
+ }
372
+ }
373
+
374
+ // Add bevel segments planes
375
+
376
+ //for ( b = 1; b <= bevelSegments; b ++ ) {
377
+ for (let b = bevelSegments - 1; b >= 0; b--) {
378
+ const t = b / bevelSegments;
379
+ const z = bevelThickness * Math.cos((t * Math.PI) / 2);
380
+ const bs = bevelSize * Math.sin((t * Math.PI) / 2) + bevelOffset;
381
+
382
+ // contract shape
383
+
384
+ for (let i = 0, il = contour.length; i < il; i++) {
385
+ const vert = scalePt2(contour[i], contourMovements[i], bs);
386
+ v(vert.x, vert.y, depth + z);
387
+ }
388
+
389
+ // expand holes
390
+
391
+ for (let h = 0, hl = holes.length; h < hl; h++) {
392
+ const ahole = holes[h];
393
+ oneHoleMovements = holesMovements[h];
394
+
395
+ for (let i = 0, il = ahole.length; i < il; i++) {
396
+ const vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
397
+
398
+ if (!extrudeByPath) {
399
+ v(vert.x, vert.y, depth + z);
400
+ } else {
401
+ v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z);
402
+ }
403
+ }
404
+ }
405
+ }
406
+
407
+ /* Faces */
408
+
409
+ // Top and bottom faces
410
+
411
+ buildLidFaces();
412
+
413
+ // Sides faces
414
+
415
+ buildSideFaces();
416
+
417
+ ///// Internal functions
418
+
419
+ function buildLidFaces() {
420
+ const start = verticesArray.length / 3;
421
+
422
+ if (bevelEnabled) {
423
+ let layer = 0; // steps + 1
424
+ let offset = vlen * layer;
425
+
426
+ // Bottom faces
427
+
428
+ for (let i = 0; i < flen; i++) {
429
+ const face = faces[i];
430
+ f3(face[2] + offset, face[1] + offset, face[0] + offset);
431
+ }
432
+
433
+ layer = steps + bevelSegments * 2;
434
+ offset = vlen * layer;
435
+
436
+ // Top faces
437
+
438
+ for (let i = 0; i < flen; i++) {
439
+ const face = faces[i];
440
+ f3(face[0] + offset, face[1] + offset, face[2] + offset);
441
+ }
442
+ } else {
443
+ // Bottom faces
444
+
445
+ for (let i = 0; i < flen; i++) {
446
+ const face = faces[i];
447
+ f3(face[2], face[1], face[0]);
448
+ }
449
+
450
+ // Top faces
451
+
452
+ for (let i = 0; i < flen; i++) {
453
+ const face = faces[i];
454
+ f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
455
+ }
456
+ }
457
+
458
+ scope.addGroup(start, verticesArray.length / 3 - start, 0);
459
+ }
460
+
461
+ // Create faces for the z-sides of the shape
462
+
463
+ function buildSideFaces() {
464
+ const start = verticesArray.length / 3;
465
+ let layeroffset = 0;
466
+ sidewalls(contour, layeroffset);
467
+ layeroffset += contour.length;
468
+
469
+ for (let h = 0, hl = holes.length; h < hl; h++) {
470
+ const ahole = holes[h];
471
+ sidewalls(ahole, layeroffset);
472
+
473
+ //, true
474
+ layeroffset += ahole.length;
475
+ }
476
+
477
+ scope.addGroup(start, verticesArray.length / 3 - start, 1);
478
+ }
479
+
480
+ function sidewalls(contour, layeroffset) {
481
+ let i = contour.length;
482
+
483
+ while (--i >= 0) {
484
+ const j = i;
485
+ let k = i - 1;
486
+ if (k < 0) k = contour.length - 1;
487
+
488
+ //console.log('b', i,j, i-1, k,vertices.length);
489
+
490
+ for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
491
+ const slen1 = vlen * s;
492
+ const slen2 = vlen * (s + 1);
493
+
494
+ const a = layeroffset + j + slen1,
495
+ b = layeroffset + k + slen1,
496
+ c = layeroffset + k + slen2,
497
+ d = layeroffset + j + slen2;
498
+
499
+ f4(a, b, c, d);
500
+ }
501
+ }
502
+ }
503
+
504
+ function v(x, y, z) {
505
+ placeholder.push(x);
506
+ placeholder.push(y);
507
+ placeholder.push(z);
508
+ }
509
+
510
+ function f3(a, b, c) {
511
+ addVertex(a);
512
+ addVertex(b);
513
+ addVertex(c);
514
+
515
+ const nextIndex = verticesArray.length / 3;
516
+ const uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1);
517
+
518
+ addUV(uvs[0]);
519
+ addUV(uvs[1]);
520
+ addUV(uvs[2]);
521
+ }
522
+
523
+ function f4(a, b, c, d) {
524
+ addVertex(a);
525
+ addVertex(b);
526
+ addVertex(d);
527
+
528
+ addVertex(b);
529
+ addVertex(c);
530
+ addVertex(d);
531
+
532
+ const nextIndex = verticesArray.length / 3;
533
+ const uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1);
534
+
535
+ addUV(uvs[0]);
536
+ addUV(uvs[1]);
537
+ addUV(uvs[3]);
538
+
539
+ addUV(uvs[1]);
540
+ addUV(uvs[2]);
541
+ addUV(uvs[3]);
542
+ }
543
+
544
+ function addVertex(index) {
545
+ verticesArray.push(placeholder[index * 3 + 0]);
546
+ verticesArray.push(placeholder[index * 3 + 1]);
547
+ verticesArray.push(placeholder[index * 3 + 2]);
548
+ }
549
+
550
+ function addUV(vector2) {
551
+ uvArray.push(vector2.x);
552
+ uvArray.push(vector2.y);
553
+ }
554
+ }
555
+ }
556
+
557
+ addGroup(start, count, materialIndex = 0) {
558
+ this.groups.push({
559
+ start: start,
560
+ count: count,
561
+ materialIndex: materialIndex,
562
+ });
563
+ }
564
+
565
+ toJSON() {
566
+ const data = super.toJSON();
567
+
568
+ const shapes = this.parameters.shapes;
569
+ const options = this.parameters.options;
570
+
571
+ return toJSON(shapes, options, data);
572
+ }
573
+
574
+ static fromJSON(data, shapes) {
575
+ const geometryShapes = [];
576
+
577
+ for (let j = 0, jl = data.shapes.length; j < jl; j++) {
578
+ const shape = shapes[data.shapes[j]];
579
+
580
+ geometryShapes.push(shape);
581
+ }
582
+
583
+ const extrudePath = data.options.extrudePath;
584
+
585
+ if (extrudePath !== undefined) {
586
+ data.options.extrudePath = new Curves[extrudePath.type]().fromJSON(extrudePath);
587
+ }
588
+
589
+ return new ExtrudeGeometry(geometryShapes, data.options);
590
+ }
591
+ }
592
+
593
+ const WorldUVGenerator = {
594
+ generateTopUV: function (geometry, vertices, indexA, indexB, indexC) {
595
+ const a_x = vertices[indexA * 3];
596
+ const a_y = vertices[indexA * 3 + 1];
597
+ const b_x = vertices[indexB * 3];
598
+ const b_y = vertices[indexB * 3 + 1];
599
+ const c_x = vertices[indexC * 3];
600
+ const c_y = vertices[indexC * 3 + 1];
601
+
602
+ return [new Vector2(a_x, a_y), new Vector2(b_x, b_y), new Vector2(c_x, c_y)];
603
+ },
604
+
605
+ generateSideWallUV: function (geometry, vertices, indexA, indexB, indexC, indexD) {
606
+ const a_x = vertices[indexA * 3];
607
+ const a_y = vertices[indexA * 3 + 1];
608
+ const a_z = vertices[indexA * 3 + 2];
609
+ const b_x = vertices[indexB * 3];
610
+ const b_y = vertices[indexB * 3 + 1];
611
+ const b_z = vertices[indexB * 3 + 2];
612
+ const c_x = vertices[indexC * 3];
613
+ const c_y = vertices[indexC * 3 + 1];
614
+ const c_z = vertices[indexC * 3 + 2];
615
+ const d_x = vertices[indexD * 3];
616
+ const d_y = vertices[indexD * 3 + 1];
617
+ const d_z = vertices[indexD * 3 + 2];
618
+
619
+ if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) {
620
+ return [new Vector2(a_x, 1 - a_z), new Vector2(b_x, 1 - b_z), new Vector2(c_x, 1 - c_z), new Vector2(d_x, 1 - d_z)];
621
+ } else {
622
+ return [new Vector2(a_y, 1 - a_z), new Vector2(b_y, 1 - b_z), new Vector2(c_y, 1 - c_z), new Vector2(d_y, 1 - d_z)];
623
+ }
624
+ },
625
+ };
626
+
627
+ function toJSON(shapes, options, data) {
628
+ data.shapes = [];
629
+
630
+ if (Array.isArray(shapes)) {
631
+ for (let i = 0, l = shapes.length; i < l; i++) {
632
+ const shape = shapes[i];
633
+
634
+ data.shapes.push(shape.uuid);
635
+ }
636
+ } else {
637
+ data.shapes.push(shapes.uuid);
638
+ }
639
+
640
+ data.options = Object.assign({}, options);
641
+
642
+ if (options.extrudePath !== undefined) data.options.extrudePath = options.extrudePath.toJSON();
643
+
644
+ return data;
645
+ }
646
+
647
+ export { ExtrudeGeometry, ExtrudeGeometry as ExtrudeBufferGeometry };