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.
- package/index.d.ts +52 -0
- package/index.js +2 -1
- package/package.json +4 -2
- package/src/threeFont/Curve/Curve.js +349 -0
- package/src/threeFont/Curve/CurvePath.js +202 -0
- package/src/threeFont/Curve/Interpolations.js +57 -0
- package/src/threeFont/Curve/Shape.js +77 -0
- package/src/threeFont/Math/MathUtils.js +526 -0
- package/src/threeFont/Math/Matrix4.js +863 -0
- package/src/threeFont/Math/Quaternion.js +584 -0
- package/src/threeFont/Math/Vector2.js +373 -0
- package/src/threeFont/Math/Vector3.js +617 -0
- package/src/threeFont/TextGeometry/Earcut.js +634 -0
- package/src/threeFont/TextGeometry/ExtrudeGeometry.js +647 -0
- package/src/threeFont/TextGeometry/FontLoader.js +114 -0
- package/src/threeFont/TextGeometry/Path.js +146 -0
- package/src/threeFont/TextGeometry/ShapePath.js +222 -0
- package/src/threeFont/TextGeometry/ShapeUtils.js +70 -0
- package/src/threeFont/curves/CubicBezierCurve.js +66 -0
- package/src/threeFont/curves/Curves.js +10 -0
- package/src/threeFont/curves/EllipseCurve.js +130 -0
- package/src/threeFont/curves/LineCurve.js +70 -0
- package/src/threeFont/curves/QuadraticBezierCurve.js +61 -0
- package/src/threeFont/curves/SplineCurve.js +76 -0
- package/src/threeFont/index.js +166 -0
- package/src/vtkUtils.js +55 -28
- package/tsconfig.json +1 -1
|
@@ -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 };
|