@adatechnology/game-items-three 0.1.5 → 0.1.6
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/README.md +5 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.global.js +1820 -288
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.global.js
CHANGED
|
@@ -72,52 +72,1696 @@ var GameItemsThree = (() => {
|
|
|
72
72
|
wearableMaterials: () => wearableMaterials
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
// ../game-shapes/dist/chunk-R4RY23RH.js
|
|
76
|
+
function canonicalJson(value) {
|
|
77
|
+
if (value === null) return "null";
|
|
78
|
+
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
79
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
80
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
81
|
+
if (typeof value === "function") throw new Error("game-shapes: a function cannot be part of a shape (register it as a generator)");
|
|
82
|
+
if (ArrayBuffer.isView(value)) return canonicalJson(Array.from(value));
|
|
83
|
+
if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "null" : canonicalJson(item)).join(",")}]`;
|
|
84
|
+
if (typeof value === "object") {
|
|
85
|
+
const record = value;
|
|
86
|
+
const keys = Object.keys(record).filter((key2) => record[key2] !== void 0).sort();
|
|
87
|
+
return `{${keys.map((key2) => `${JSON.stringify(key2)}:${canonicalJson(record[key2])}`).join(",")}}`;
|
|
88
|
+
}
|
|
89
|
+
return "null";
|
|
90
|
+
}
|
|
91
|
+
function normalMatrix(me) {
|
|
92
|
+
const n11 = me[0], n21 = me[1], n31 = me[2];
|
|
93
|
+
const n12 = me[4], n22 = me[5], n32 = me[6];
|
|
94
|
+
const n13 = me[8], n23 = me[9], n33 = me[10];
|
|
95
|
+
const t11 = n33 * n22 - n32 * n23;
|
|
96
|
+
const t12 = n32 * n13 - n33 * n12;
|
|
97
|
+
const t13 = n23 * n12 - n22 * n13;
|
|
98
|
+
const det = n11 * t11 + n21 * t12 + n31 * t13;
|
|
99
|
+
if (det === 0) return [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
100
|
+
const detInv = 1 / det;
|
|
101
|
+
const te = [
|
|
102
|
+
t11 * detInv,
|
|
103
|
+
(n31 * n23 - n33 * n21) * detInv,
|
|
104
|
+
(n32 * n21 - n31 * n22) * detInv,
|
|
105
|
+
t12 * detInv,
|
|
106
|
+
(n33 * n11 - n31 * n13) * detInv,
|
|
107
|
+
(n31 * n12 - n32 * n11) * detInv,
|
|
108
|
+
t13 * detInv,
|
|
109
|
+
(n21 * n13 - n23 * n11) * detInv,
|
|
110
|
+
(n22 * n11 - n21 * n12) * detInv
|
|
111
|
+
];
|
|
112
|
+
let tmp = te[1];
|
|
113
|
+
te[1] = te[3];
|
|
114
|
+
te[3] = tmp;
|
|
115
|
+
tmp = te[2];
|
|
116
|
+
te[2] = te[6];
|
|
117
|
+
te[6] = tmp;
|
|
118
|
+
tmp = te[5];
|
|
119
|
+
te[5] = te[7];
|
|
120
|
+
te[7] = tmp;
|
|
121
|
+
return te;
|
|
122
|
+
}
|
|
123
|
+
function transformPoint(e, x, y, z) {
|
|
124
|
+
const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
|
|
125
|
+
return [(e[0] * x + e[4] * y + e[8] * z + e[12]) * w, (e[1] * x + e[5] * y + e[9] * z + e[13]) * w, (e[2] * x + e[6] * y + e[10] * z + e[14]) * w];
|
|
126
|
+
}
|
|
127
|
+
function needsUint32(array) {
|
|
128
|
+
for (let i = array.length - 1; i >= 0; --i) if (array[i] >= 65535) return true;
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
var indexArray = (indices) => needsUint32(indices) ? new Uint32Array(indices) : new Uint16Array(indices);
|
|
132
|
+
function pack(type, parameters, a) {
|
|
133
|
+
return {
|
|
134
|
+
type,
|
|
135
|
+
parameters,
|
|
136
|
+
positions: new Float32Array(a.vertices),
|
|
137
|
+
normals: new Float32Array(a.normals),
|
|
138
|
+
uvs: new Float32Array(a.uvs),
|
|
139
|
+
...a.indices ? { indices: indexArray(a.indices) } : {},
|
|
140
|
+
groups: a.groups
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
var normalize3 = (x, y, z) => {
|
|
144
|
+
const length = Math.sqrt(x * x + y * y + z * z);
|
|
145
|
+
const s = 1 / (length || 1);
|
|
146
|
+
return [x * s, y * s, z * s];
|
|
147
|
+
};
|
|
148
|
+
function box(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
|
|
149
|
+
const parameters = { width, height, depth, widthSegments, heightSegments, depthSegments };
|
|
150
|
+
widthSegments = Math.floor(widthSegments);
|
|
151
|
+
heightSegments = Math.floor(heightSegments);
|
|
152
|
+
depthSegments = Math.floor(depthSegments);
|
|
153
|
+
const indices = [];
|
|
154
|
+
const vertices = [];
|
|
155
|
+
const normals = [];
|
|
156
|
+
const uvs = [];
|
|
157
|
+
const groups = [];
|
|
158
|
+
let numberOfVertices = 0;
|
|
159
|
+
let groupStart = 0;
|
|
160
|
+
const buildPlane = (u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) => {
|
|
161
|
+
const segmentWidth = width2 / gridX;
|
|
162
|
+
const segmentHeight = height2 / gridY;
|
|
163
|
+
const widthHalf = width2 / 2;
|
|
164
|
+
const heightHalf = height2 / 2;
|
|
165
|
+
const depthHalf = depth2 / 2;
|
|
166
|
+
const gridX1 = gridX + 1;
|
|
167
|
+
const gridY1 = gridY + 1;
|
|
168
|
+
let vertexCounter = 0;
|
|
169
|
+
let groupCount = 0;
|
|
170
|
+
const vector = { x: 0, y: 0, z: 0 };
|
|
171
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
172
|
+
const y = iy * segmentHeight - heightHalf;
|
|
173
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
174
|
+
const x = ix * segmentWidth - widthHalf;
|
|
175
|
+
vector[u] = x * udir;
|
|
176
|
+
vector[v] = y * vdir;
|
|
177
|
+
vector[w] = depthHalf;
|
|
178
|
+
vertices.push(vector.x, vector.y, vector.z);
|
|
179
|
+
vector[u] = 0;
|
|
180
|
+
vector[v] = 0;
|
|
181
|
+
vector[w] = depth2 > 0 ? 1 : -1;
|
|
182
|
+
normals.push(vector.x, vector.y, vector.z);
|
|
183
|
+
uvs.push(ix / gridX);
|
|
184
|
+
uvs.push(1 - iy / gridY);
|
|
185
|
+
vertexCounter += 1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
189
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
190
|
+
const a = numberOfVertices + ix + gridX1 * iy;
|
|
191
|
+
const b = numberOfVertices + ix + gridX1 * (iy + 1);
|
|
192
|
+
const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
|
|
193
|
+
const d = numberOfVertices + (ix + 1) + gridX1 * iy;
|
|
194
|
+
indices.push(a, b, d);
|
|
195
|
+
indices.push(b, c, d);
|
|
196
|
+
groupCount += 6;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex });
|
|
200
|
+
groupStart += groupCount;
|
|
201
|
+
numberOfVertices += vertexCounter;
|
|
202
|
+
};
|
|
203
|
+
buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0);
|
|
204
|
+
buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
|
|
205
|
+
buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2);
|
|
206
|
+
buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
|
|
207
|
+
buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4);
|
|
208
|
+
buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
|
|
209
|
+
return pack("BoxGeometry", parameters, { vertices, normals, uvs, indices, groups });
|
|
210
|
+
}
|
|
211
|
+
function cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
|
|
212
|
+
radialSegments = Math.floor(radialSegments);
|
|
213
|
+
heightSegments = Math.floor(heightSegments);
|
|
214
|
+
const indices = [];
|
|
215
|
+
const vertices = [];
|
|
216
|
+
const normals = [];
|
|
217
|
+
const uvs = [];
|
|
218
|
+
const groups = [];
|
|
219
|
+
let index = 0;
|
|
220
|
+
const indexArray2 = [];
|
|
221
|
+
const halfHeight = height / 2;
|
|
222
|
+
let groupStart = 0;
|
|
223
|
+
const generateTorso = () => {
|
|
224
|
+
let groupCount = 0;
|
|
225
|
+
const slope = (radiusBottom - radiusTop) / height;
|
|
226
|
+
for (let y = 0; y <= heightSegments; y++) {
|
|
227
|
+
const indexRow = [];
|
|
228
|
+
const v = y / heightSegments;
|
|
229
|
+
const radius = v * (radiusBottom - radiusTop) + radiusTop;
|
|
230
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
231
|
+
const u = x / radialSegments;
|
|
232
|
+
const theta = u * thetaLength + thetaStart;
|
|
233
|
+
const sinTheta = Math.sin(theta);
|
|
234
|
+
const cosTheta = Math.cos(theta);
|
|
235
|
+
vertices.push(radius * sinTheta, -v * height + halfHeight, radius * cosTheta);
|
|
236
|
+
const n = normalize3(sinTheta, slope, cosTheta);
|
|
237
|
+
normals.push(n[0], n[1], n[2]);
|
|
238
|
+
uvs.push(u, 1 - v);
|
|
239
|
+
indexRow.push(index++);
|
|
240
|
+
}
|
|
241
|
+
indexArray2.push(indexRow);
|
|
242
|
+
}
|
|
243
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
244
|
+
for (let y = 0; y < heightSegments; y++) {
|
|
245
|
+
const a = indexArray2[y][x];
|
|
246
|
+
const b = indexArray2[y + 1][x];
|
|
247
|
+
const c = indexArray2[y + 1][x + 1];
|
|
248
|
+
const d = indexArray2[y][x + 1];
|
|
249
|
+
indices.push(a, b, d);
|
|
250
|
+
indices.push(b, c, d);
|
|
251
|
+
groupCount += 6;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: 0 });
|
|
255
|
+
groupStart += groupCount;
|
|
256
|
+
};
|
|
257
|
+
const generateCap = (top) => {
|
|
258
|
+
const centerIndexStart = index;
|
|
259
|
+
let groupCount = 0;
|
|
260
|
+
const radius = top === true ? radiusTop : radiusBottom;
|
|
261
|
+
const sign2 = top === true ? 1 : -1;
|
|
262
|
+
for (let x = 1; x <= radialSegments; x++) {
|
|
263
|
+
vertices.push(0, halfHeight * sign2, 0);
|
|
264
|
+
normals.push(0, sign2, 0);
|
|
265
|
+
uvs.push(0.5, 0.5);
|
|
266
|
+
index++;
|
|
267
|
+
}
|
|
268
|
+
const centerIndexEnd = index;
|
|
269
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
270
|
+
const u = x / radialSegments;
|
|
271
|
+
const theta = u * thetaLength + thetaStart;
|
|
272
|
+
const cosTheta = Math.cos(theta);
|
|
273
|
+
const sinTheta = Math.sin(theta);
|
|
274
|
+
vertices.push(radius * sinTheta, halfHeight * sign2, radius * cosTheta);
|
|
275
|
+
normals.push(0, sign2, 0);
|
|
276
|
+
uvs.push(cosTheta * 0.5 + 0.5, sinTheta * 0.5 * sign2 + 0.5);
|
|
277
|
+
index++;
|
|
278
|
+
}
|
|
279
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
280
|
+
const c = centerIndexStart + x;
|
|
281
|
+
const i = centerIndexEnd + x;
|
|
282
|
+
if (top === true) indices.push(i, i + 1, c);
|
|
283
|
+
else indices.push(i + 1, i, c);
|
|
284
|
+
groupCount += 3;
|
|
285
|
+
}
|
|
286
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: top === true ? 1 : 2 });
|
|
287
|
+
groupStart += groupCount;
|
|
288
|
+
};
|
|
289
|
+
generateTorso();
|
|
290
|
+
if (openEnded === false) {
|
|
291
|
+
if (radiusTop > 0) generateCap(true);
|
|
292
|
+
if (radiusBottom > 0) generateCap(false);
|
|
293
|
+
}
|
|
294
|
+
return { vertices, normals, uvs, indices, groups };
|
|
295
|
+
}
|
|
296
|
+
function cylinder(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
297
|
+
const parameters = { radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
298
|
+
return pack("CylinderGeometry", parameters, cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
299
|
+
}
|
|
300
|
+
function cone(radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
301
|
+
const parameters = { radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
302
|
+
return pack("ConeGeometry", parameters, cylinderArrays(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
303
|
+
}
|
|
304
|
+
function sphere(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
|
|
305
|
+
const parameters = { radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength };
|
|
306
|
+
widthSegments = Math.max(3, Math.floor(widthSegments));
|
|
307
|
+
heightSegments = Math.max(2, Math.floor(heightSegments));
|
|
308
|
+
const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI);
|
|
309
|
+
let index = 0;
|
|
310
|
+
const grid = [];
|
|
311
|
+
const indices = [];
|
|
312
|
+
const vertices = [];
|
|
313
|
+
const normals = [];
|
|
314
|
+
const uvs = [];
|
|
315
|
+
for (let iy = 0; iy <= heightSegments; iy++) {
|
|
316
|
+
const verticesRow = [];
|
|
317
|
+
const v = iy / heightSegments;
|
|
318
|
+
let uOffset = 0;
|
|
319
|
+
if (iy === 0 && thetaStart === 0) uOffset = 0.5 / widthSegments;
|
|
320
|
+
else if (iy === heightSegments && thetaEnd === Math.PI) uOffset = -0.5 / widthSegments;
|
|
321
|
+
for (let ix = 0; ix <= widthSegments; ix++) {
|
|
322
|
+
const u = ix / widthSegments;
|
|
323
|
+
const x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
324
|
+
const y = radius * Math.cos(thetaStart + v * thetaLength);
|
|
325
|
+
const z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
326
|
+
vertices.push(x, y, z);
|
|
327
|
+
const n = normalize3(x, y, z);
|
|
328
|
+
normals.push(n[0], n[1], n[2]);
|
|
329
|
+
uvs.push(u + uOffset, 1 - v);
|
|
330
|
+
verticesRow.push(index++);
|
|
331
|
+
}
|
|
332
|
+
grid.push(verticesRow);
|
|
333
|
+
}
|
|
334
|
+
for (let iy = 0; iy < heightSegments; iy++) {
|
|
335
|
+
for (let ix = 0; ix < widthSegments; ix++) {
|
|
336
|
+
const a = grid[iy][ix + 1];
|
|
337
|
+
const b = grid[iy][ix];
|
|
338
|
+
const c = grid[iy + 1][ix];
|
|
339
|
+
const d = grid[iy + 1][ix + 1];
|
|
340
|
+
if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
|
|
341
|
+
if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return pack("SphereGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
345
|
+
}
|
|
346
|
+
function plane(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
|
|
347
|
+
const parameters = { width, height, widthSegments, heightSegments };
|
|
348
|
+
const widthHalf = width / 2;
|
|
349
|
+
const heightHalf = height / 2;
|
|
350
|
+
const gridX = Math.floor(widthSegments);
|
|
351
|
+
const gridY = Math.floor(heightSegments);
|
|
352
|
+
const gridX1 = gridX + 1;
|
|
353
|
+
const gridY1 = gridY + 1;
|
|
354
|
+
const segmentWidth = width / gridX;
|
|
355
|
+
const segmentHeight = height / gridY;
|
|
356
|
+
const indices = [];
|
|
357
|
+
const vertices = [];
|
|
358
|
+
const normals = [];
|
|
359
|
+
const uvs = [];
|
|
360
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
361
|
+
const y = iy * segmentHeight - heightHalf;
|
|
362
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
363
|
+
const x = ix * segmentWidth - widthHalf;
|
|
364
|
+
vertices.push(x, -y, 0);
|
|
365
|
+
normals.push(0, 0, 1);
|
|
366
|
+
uvs.push(ix / gridX);
|
|
367
|
+
uvs.push(1 - iy / gridY);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
371
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
372
|
+
const a = ix + gridX1 * iy;
|
|
373
|
+
const b = ix + gridX1 * (iy + 1);
|
|
374
|
+
const c = ix + 1 + gridX1 * (iy + 1);
|
|
375
|
+
const d = ix + 1 + gridX1 * iy;
|
|
376
|
+
indices.push(a, b, d);
|
|
377
|
+
indices.push(b, c, d);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return pack("PlaneGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
381
|
+
}
|
|
382
|
+
function circle(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
383
|
+
const parameters = { radius, segments, thetaStart, thetaLength };
|
|
384
|
+
segments = Math.max(3, segments);
|
|
385
|
+
const indices = [];
|
|
386
|
+
const vertices = [];
|
|
387
|
+
const normals = [];
|
|
388
|
+
const uvs = [];
|
|
389
|
+
vertices.push(0, 0, 0);
|
|
390
|
+
normals.push(0, 0, 1);
|
|
391
|
+
uvs.push(0.5, 0.5);
|
|
392
|
+
for (let s = 0, i = 3; s <= segments; s++, i += 3) {
|
|
393
|
+
const segment = thetaStart + s / segments * thetaLength;
|
|
394
|
+
vertices.push(radius * Math.cos(segment), radius * Math.sin(segment), 0);
|
|
395
|
+
normals.push(0, 0, 1);
|
|
396
|
+
uvs.push((vertices[i] / radius + 1) / 2, (vertices[i + 1] / radius + 1) / 2);
|
|
397
|
+
}
|
|
398
|
+
for (let i = 1; i <= segments; i++) indices.push(i, i + 1, 0);
|
|
399
|
+
return pack("CircleGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
400
|
+
}
|
|
401
|
+
function ring(innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
402
|
+
const parameters = { innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength };
|
|
403
|
+
thetaSegments = Math.max(3, thetaSegments);
|
|
404
|
+
phiSegments = Math.max(1, phiSegments);
|
|
405
|
+
const indices = [];
|
|
406
|
+
const vertices = [];
|
|
407
|
+
const normals = [];
|
|
408
|
+
const uvs = [];
|
|
409
|
+
let radius = innerRadius;
|
|
410
|
+
const radiusStep = (outerRadius - innerRadius) / phiSegments;
|
|
411
|
+
for (let j = 0; j <= phiSegments; j++) {
|
|
412
|
+
for (let i = 0; i <= thetaSegments; i++) {
|
|
413
|
+
const segment = thetaStart + i / thetaSegments * thetaLength;
|
|
414
|
+
const x = radius * Math.cos(segment);
|
|
415
|
+
const y = radius * Math.sin(segment);
|
|
416
|
+
vertices.push(x, y, 0);
|
|
417
|
+
normals.push(0, 0, 1);
|
|
418
|
+
uvs.push((x / outerRadius + 1) / 2, (y / outerRadius + 1) / 2);
|
|
419
|
+
}
|
|
420
|
+
radius += radiusStep;
|
|
421
|
+
}
|
|
422
|
+
for (let j = 0; j < phiSegments; j++) {
|
|
423
|
+
const thetaSegmentLevel = j * (thetaSegments + 1);
|
|
424
|
+
for (let i = 0; i < thetaSegments; i++) {
|
|
425
|
+
const segment = i + thetaSegmentLevel;
|
|
426
|
+
const a = segment;
|
|
427
|
+
const b = segment + thetaSegments + 1;
|
|
428
|
+
const c = segment + thetaSegments + 2;
|
|
429
|
+
const d = segment + 1;
|
|
430
|
+
indices.push(a, b, d);
|
|
431
|
+
indices.push(b, c, d);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return pack("RingGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
435
|
+
}
|
|
436
|
+
function lathe(points, segments = 12, phiStart = 0, phiLength = Math.PI * 2) {
|
|
437
|
+
const parameters = { points: points.map(([x, y]) => ({ x, y })), segments, phiStart, phiLength };
|
|
438
|
+
segments = Math.floor(segments);
|
|
439
|
+
phiLength = Math.max(0, Math.min(Math.PI * 2, phiLength));
|
|
440
|
+
const indices = [];
|
|
441
|
+
const vertices = [];
|
|
442
|
+
const uvs = [];
|
|
443
|
+
const initNormals = [];
|
|
444
|
+
const normals = [];
|
|
445
|
+
const inverseSegments = 1 / segments;
|
|
446
|
+
const normal = { x: 0, y: 0, z: 0 };
|
|
447
|
+
const curNormal = { x: 0, y: 0, z: 0 };
|
|
448
|
+
const prevNormal = { x: 0, y: 0, z: 0 };
|
|
449
|
+
let dx = 0;
|
|
450
|
+
let dy = 0;
|
|
451
|
+
const last = points.length - 1;
|
|
452
|
+
const px = (j) => points[j][0];
|
|
453
|
+
const py = (j) => points[j][1];
|
|
454
|
+
const setNormalized = () => {
|
|
455
|
+
const n = normalize3(normal.x, normal.y, normal.z);
|
|
456
|
+
normal.x = n[0];
|
|
457
|
+
normal.y = n[1];
|
|
458
|
+
normal.z = n[2];
|
|
459
|
+
};
|
|
460
|
+
for (let j = 0; j <= last; j++) {
|
|
461
|
+
if (j === 0) {
|
|
462
|
+
dx = px(j + 1) - px(j);
|
|
463
|
+
dy = py(j + 1) - py(j);
|
|
464
|
+
normal.x = dy * 1;
|
|
465
|
+
normal.y = -dx;
|
|
466
|
+
normal.z = dy * 0;
|
|
467
|
+
prevNormal.x = normal.x;
|
|
468
|
+
prevNormal.y = normal.y;
|
|
469
|
+
prevNormal.z = normal.z;
|
|
470
|
+
setNormalized();
|
|
471
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
472
|
+
} else if (j === last) {
|
|
473
|
+
initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z);
|
|
474
|
+
} else {
|
|
475
|
+
dx = px(j + 1) - px(j);
|
|
476
|
+
dy = py(j + 1) - py(j);
|
|
477
|
+
normal.x = dy * 1;
|
|
478
|
+
normal.y = -dx;
|
|
479
|
+
normal.z = dy * 0;
|
|
480
|
+
curNormal.x = normal.x;
|
|
481
|
+
curNormal.y = normal.y;
|
|
482
|
+
curNormal.z = normal.z;
|
|
483
|
+
normal.x += prevNormal.x;
|
|
484
|
+
normal.y += prevNormal.y;
|
|
485
|
+
normal.z += prevNormal.z;
|
|
486
|
+
setNormalized();
|
|
487
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
488
|
+
prevNormal.x = curNormal.x;
|
|
489
|
+
prevNormal.y = curNormal.y;
|
|
490
|
+
prevNormal.z = curNormal.z;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
for (let i = 0; i <= segments; i++) {
|
|
494
|
+
const phi = phiStart + i * inverseSegments * phiLength;
|
|
495
|
+
const sin = Math.sin(phi);
|
|
496
|
+
const cos = Math.cos(phi);
|
|
497
|
+
for (let j = 0; j <= last; j++) {
|
|
498
|
+
vertices.push(px(j) * sin, py(j), px(j) * cos);
|
|
499
|
+
uvs.push(i / segments, j / (points.length - 1));
|
|
500
|
+
const x = initNormals[3 * j + 0] * sin;
|
|
501
|
+
const y = initNormals[3 * j + 1];
|
|
502
|
+
const z = initNormals[3 * j + 0] * cos;
|
|
503
|
+
normals.push(x, y, z);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
for (let i = 0; i < segments; i++) {
|
|
507
|
+
for (let j = 0; j < points.length - 1; j++) {
|
|
508
|
+
const base = j + i * points.length;
|
|
509
|
+
const a = base;
|
|
510
|
+
const b = base + points.length;
|
|
511
|
+
const c = base + points.length + 1;
|
|
512
|
+
const d = base + 1;
|
|
513
|
+
indices.push(a, b, d);
|
|
514
|
+
indices.push(c, d, b);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return pack("LatheGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
518
|
+
}
|
|
519
|
+
function torus(radius = 1, tube2 = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2) {
|
|
520
|
+
const parameters = { radius, tube: tube2, radialSegments, tubularSegments, arc };
|
|
521
|
+
radialSegments = Math.floor(radialSegments);
|
|
522
|
+
tubularSegments = Math.floor(tubularSegments);
|
|
523
|
+
const indices = [];
|
|
524
|
+
const vertices = [];
|
|
525
|
+
const normals = [];
|
|
526
|
+
const uvs = [];
|
|
527
|
+
for (let j = 0; j <= radialSegments; j++) {
|
|
528
|
+
for (let i = 0; i <= tubularSegments; i++) {
|
|
529
|
+
const u = i / tubularSegments * arc;
|
|
530
|
+
const v = j / radialSegments * Math.PI * 2;
|
|
531
|
+
const x = (radius + tube2 * Math.cos(v)) * Math.cos(u);
|
|
532
|
+
const y = (radius + tube2 * Math.cos(v)) * Math.sin(u);
|
|
533
|
+
const z = tube2 * Math.sin(v);
|
|
534
|
+
vertices.push(x, y, z);
|
|
535
|
+
const cx = radius * Math.cos(u);
|
|
536
|
+
const cy = radius * Math.sin(u);
|
|
537
|
+
const n = normalize3(x - cx, y - cy, z - 0);
|
|
538
|
+
normals.push(n[0], n[1], n[2]);
|
|
539
|
+
uvs.push(i / tubularSegments);
|
|
540
|
+
uvs.push(j / radialSegments);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
for (let j = 1; j <= radialSegments; j++) {
|
|
544
|
+
for (let i = 1; i <= tubularSegments; i++) {
|
|
545
|
+
const a = (tubularSegments + 1) * j + i - 1;
|
|
546
|
+
const b = (tubularSegments + 1) * (j - 1) + i - 1;
|
|
547
|
+
const c = (tubularSegments + 1) * (j - 1) + i;
|
|
548
|
+
const d = (tubularSegments + 1) * j + i;
|
|
549
|
+
indices.push(a, b, d);
|
|
550
|
+
indices.push(b, c, d);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return pack("TorusGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
554
|
+
}
|
|
555
|
+
function difference(size, subtract) {
|
|
556
|
+
const [w, h, d] = size;
|
|
557
|
+
const hw = w / 2;
|
|
558
|
+
const hh = h / 2;
|
|
559
|
+
const hd = d / 2;
|
|
560
|
+
const holes = subtract.map((hole) => ({ x0: Math.max(-hw, Math.min(hole.min[0], hole.max[0])), x1: Math.min(hw, Math.max(hole.min[0], hole.max[0])), y0: Math.max(-hh, Math.min(hole.min[1], hole.max[1])), y1: Math.min(hh, Math.max(hole.min[1], hole.max[1])) })).filter((hole) => hole.x1 > hole.x0 && hole.y1 > hole.y0);
|
|
561
|
+
const cuts = (lo, hi, values) => [.../* @__PURE__ */ new Set([lo, hi, ...values.filter((v) => v > lo && v < hi)])].sort((a, b) => a - b);
|
|
562
|
+
const xs = cuts(-hw, hw, holes.flatMap((hole) => [hole.x0, hole.x1]));
|
|
563
|
+
const ys = cuts(-hh, hh, holes.flatMap((hole) => [hole.y0, hole.y1]));
|
|
564
|
+
const nx = xs.length - 1;
|
|
565
|
+
const ny = ys.length - 1;
|
|
566
|
+
const solid = (i, j) => {
|
|
567
|
+
if (i < 0 || j < 0 || i >= nx || j >= ny) return false;
|
|
568
|
+
const cx = (xs[i] + xs[i + 1]) / 2;
|
|
569
|
+
const cy = (ys[j] + ys[j + 1]) / 2;
|
|
570
|
+
return !holes.some((hole) => cx > hole.x0 && cx < hole.x1 && cy > hole.y0 && cy < hole.y1);
|
|
571
|
+
};
|
|
572
|
+
const positions = [];
|
|
573
|
+
const normals = [];
|
|
574
|
+
const uvs = [];
|
|
575
|
+
const indices = [];
|
|
576
|
+
const quad = (corners, normal, uv) => {
|
|
577
|
+
const base = positions.length / 3;
|
|
578
|
+
for (let k = 0; k < 4; k++) {
|
|
579
|
+
positions.push(...corners[k]);
|
|
580
|
+
normals.push(...normal);
|
|
581
|
+
uvs.push(...uv[k]);
|
|
582
|
+
}
|
|
583
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
584
|
+
};
|
|
585
|
+
const fu = (x) => (x + hw) / w;
|
|
586
|
+
const fv = (y) => (y + hh) / h;
|
|
587
|
+
for (let j = 0; j < ny; j++) {
|
|
588
|
+
for (let i = 0; i < nx; i++) {
|
|
589
|
+
if (!solid(i, j)) continue;
|
|
590
|
+
const x0 = xs[i];
|
|
591
|
+
const x1 = xs[i + 1];
|
|
592
|
+
const y0 = ys[j];
|
|
593
|
+
const y1 = ys[j + 1];
|
|
594
|
+
quad([[x0, y0, hd], [x1, y0, hd], [x1, y1, hd], [x0, y1, hd]], [0, 0, 1], [[fu(x0), fv(y0)], [fu(x1), fv(y0)], [fu(x1), fv(y1)], [fu(x0), fv(y1)]]);
|
|
595
|
+
quad([[x1, y0, -hd], [x0, y0, -hd], [x0, y1, -hd], [x1, y1, -hd]], [0, 0, -1], [[1 - fu(x1), fv(y0)], [1 - fu(x0), fv(y0)], [1 - fu(x0), fv(y1)], [1 - fu(x1), fv(y1)]]);
|
|
596
|
+
const zu = (z) => (z + hd) / d;
|
|
597
|
+
if (!solid(i - 1, j)) quad([[x0, y0, -hd], [x0, y0, hd], [x0, y1, hd], [x0, y1, -hd]], [-1, 0, 0], [[zu(-hd), fv(y0)], [zu(hd), fv(y0)], [zu(hd), fv(y1)], [zu(-hd), fv(y1)]]);
|
|
598
|
+
if (!solid(i + 1, j)) quad([[x1, y0, hd], [x1, y0, -hd], [x1, y1, -hd], [x1, y1, hd]], [1, 0, 0], [[zu(hd), fv(y0)], [zu(-hd), fv(y0)], [zu(-hd), fv(y1)], [zu(hd), fv(y1)]]);
|
|
599
|
+
if (!solid(i, j - 1)) quad([[x0, y0, -hd], [x1, y0, -hd], [x1, y0, hd], [x0, y0, hd]], [0, -1, 0], [[fu(x0), zu(-hd)], [fu(x1), zu(-hd)], [fu(x1), zu(hd)], [fu(x0), zu(hd)]]);
|
|
600
|
+
if (!solid(i, j + 1)) quad([[x0, y1, hd], [x1, y1, hd], [x1, y1, -hd], [x0, y1, -hd]], [0, 1, 0], [[fu(x0), zu(hd)], [fu(x1), zu(hd)], [fu(x1), zu(-hd)], [fu(x0), zu(-hd)]]);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return {
|
|
604
|
+
type: "BufferGeometry",
|
|
605
|
+
parameters: { size: [w, h, d], subtract: holes.map((hole) => ({ min: [hole.x0, hole.y0], max: [hole.x1, hole.y1] })) },
|
|
606
|
+
positions: new Float32Array(positions),
|
|
607
|
+
normals: new Float32Array(normals),
|
|
608
|
+
uvs: new Float32Array(uvs),
|
|
609
|
+
indices: indexArray(indices),
|
|
610
|
+
groups: []
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
var Earcut = {
|
|
614
|
+
triangulate: function(data, holeIndices, dim = 2) {
|
|
615
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
616
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
617
|
+
let outerNode = linkedList(data, 0, outerLen, dim, true);
|
|
618
|
+
const triangles = [];
|
|
619
|
+
if (!outerNode || outerNode.next === outerNode.prev) return triangles;
|
|
620
|
+
let minX, minY, maxX, maxY, x, y, invSize;
|
|
621
|
+
if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
|
|
622
|
+
if (data.length > 80 * dim) {
|
|
623
|
+
minX = maxX = data[0];
|
|
624
|
+
minY = maxY = data[1];
|
|
625
|
+
for (let i = dim; i < outerLen; i += dim) {
|
|
626
|
+
x = data[i];
|
|
627
|
+
y = data[i + 1];
|
|
628
|
+
if (x < minX) minX = x;
|
|
629
|
+
if (y < minY) minY = y;
|
|
630
|
+
if (x > maxX) maxX = x;
|
|
631
|
+
if (y > maxY) maxY = y;
|
|
632
|
+
}
|
|
633
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
634
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
|
635
|
+
}
|
|
636
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
|
637
|
+
return triangles;
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
function linkedList(data, start, end, dim, clockwise) {
|
|
641
|
+
let i, last;
|
|
642
|
+
if (clockwise === signedArea(data, start, end, dim) > 0) {
|
|
643
|
+
for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
644
|
+
} else {
|
|
645
|
+
for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
646
|
+
}
|
|
647
|
+
if (last && equals(last, last.next)) {
|
|
648
|
+
removeNode(last);
|
|
649
|
+
last = last.next;
|
|
650
|
+
}
|
|
651
|
+
return last;
|
|
652
|
+
}
|
|
653
|
+
function filterPoints(start, end) {
|
|
654
|
+
if (!start) return start;
|
|
655
|
+
if (!end) end = start;
|
|
656
|
+
let p = start, again;
|
|
657
|
+
do {
|
|
658
|
+
again = false;
|
|
659
|
+
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
660
|
+
removeNode(p);
|
|
661
|
+
p = end = p.prev;
|
|
662
|
+
if (p === p.next) break;
|
|
663
|
+
again = true;
|
|
664
|
+
} else {
|
|
665
|
+
p = p.next;
|
|
666
|
+
}
|
|
667
|
+
} while (again || p !== end);
|
|
668
|
+
return end;
|
|
669
|
+
}
|
|
670
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
671
|
+
if (!ear) return;
|
|
672
|
+
if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
|
|
673
|
+
let stop = ear, prev, next;
|
|
674
|
+
while (ear.prev !== ear.next) {
|
|
675
|
+
prev = ear.prev;
|
|
676
|
+
next = ear.next;
|
|
677
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
678
|
+
triangles.push(prev.i / dim | 0);
|
|
679
|
+
triangles.push(ear.i / dim | 0);
|
|
680
|
+
triangles.push(next.i / dim | 0);
|
|
681
|
+
removeNode(ear);
|
|
682
|
+
ear = next.next;
|
|
683
|
+
stop = next.next;
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
ear = next;
|
|
687
|
+
if (ear === stop) {
|
|
688
|
+
if (!pass) {
|
|
689
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
690
|
+
} else if (pass === 1) {
|
|
691
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
692
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
693
|
+
} else if (pass === 2) {
|
|
694
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
695
|
+
}
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
function isEar(ear) {
|
|
701
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
702
|
+
if (area(a, b, c) >= 0) return false;
|
|
703
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
704
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
705
|
+
let p = c.next;
|
|
706
|
+
while (p !== a) {
|
|
707
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
|
708
|
+
p = p.next;
|
|
709
|
+
}
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
713
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
714
|
+
if (area(a, b, c) >= 0) return false;
|
|
715
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
716
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
717
|
+
const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
718
|
+
let p = ear.prevZ, n = ear.nextZ;
|
|
719
|
+
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
720
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
|
721
|
+
p = p.prevZ;
|
|
722
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
|
723
|
+
n = n.nextZ;
|
|
724
|
+
}
|
|
725
|
+
while (p && p.z >= minZ) {
|
|
726
|
+
if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
|
|
727
|
+
p = p.prevZ;
|
|
728
|
+
}
|
|
729
|
+
while (n && n.z <= maxZ) {
|
|
730
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
|
731
|
+
n = n.nextZ;
|
|
732
|
+
}
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
735
|
+
function cureLocalIntersections(start, triangles, dim) {
|
|
736
|
+
let p = start;
|
|
737
|
+
do {
|
|
738
|
+
const a = p.prev, b = p.next.next;
|
|
739
|
+
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
740
|
+
triangles.push(a.i / dim | 0);
|
|
741
|
+
triangles.push(p.i / dim | 0);
|
|
742
|
+
triangles.push(b.i / dim | 0);
|
|
743
|
+
removeNode(p);
|
|
744
|
+
removeNode(p.next);
|
|
745
|
+
p = start = b;
|
|
746
|
+
}
|
|
747
|
+
p = p.next;
|
|
748
|
+
} while (p !== start);
|
|
749
|
+
return filterPoints(p);
|
|
750
|
+
}
|
|
751
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
752
|
+
let a = start;
|
|
753
|
+
do {
|
|
754
|
+
let b = a.next.next;
|
|
755
|
+
while (b !== a.prev) {
|
|
756
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
757
|
+
let c = splitPolygon(a, b);
|
|
758
|
+
a = filterPoints(a, a.next);
|
|
759
|
+
c = filterPoints(c, c.next);
|
|
760
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
761
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
b = b.next;
|
|
765
|
+
}
|
|
766
|
+
a = a.next;
|
|
767
|
+
} while (a !== start);
|
|
768
|
+
}
|
|
769
|
+
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
770
|
+
const queue = [];
|
|
771
|
+
let i, len, start, end, list2;
|
|
772
|
+
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
773
|
+
start = holeIndices[i] * dim;
|
|
774
|
+
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
775
|
+
list2 = linkedList(data, start, end, dim, false);
|
|
776
|
+
if (list2 === list2.next) list2.steiner = true;
|
|
777
|
+
queue.push(getLeftmost(list2));
|
|
778
|
+
}
|
|
779
|
+
queue.sort(compareX);
|
|
780
|
+
for (i = 0; i < queue.length; i++) {
|
|
781
|
+
outerNode = eliminateHole(queue[i], outerNode);
|
|
782
|
+
}
|
|
783
|
+
return outerNode;
|
|
784
|
+
}
|
|
785
|
+
function compareX(a, b) {
|
|
786
|
+
return a.x - b.x;
|
|
787
|
+
}
|
|
788
|
+
function eliminateHole(hole, outerNode) {
|
|
789
|
+
const bridge = findHoleBridge(hole, outerNode);
|
|
790
|
+
if (!bridge) {
|
|
791
|
+
return outerNode;
|
|
792
|
+
}
|
|
793
|
+
const bridgeReverse = splitPolygon(bridge, hole);
|
|
794
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
|
795
|
+
return filterPoints(bridge, bridge.next);
|
|
796
|
+
}
|
|
797
|
+
function findHoleBridge(hole, outerNode) {
|
|
798
|
+
let p = outerNode, qx = -Infinity, m;
|
|
799
|
+
const hx = hole.x, hy = hole.y;
|
|
800
|
+
do {
|
|
801
|
+
if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
|
|
802
|
+
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
|
|
803
|
+
if (x <= hx && x > qx) {
|
|
804
|
+
qx = x;
|
|
805
|
+
m = p.x < p.next.x ? p : p.next;
|
|
806
|
+
if (x === hx) return m;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
p = p.next;
|
|
810
|
+
} while (p !== outerNode);
|
|
811
|
+
if (!m) return null;
|
|
812
|
+
const stop = m, mx = m.x, my = m.y;
|
|
813
|
+
let tanMin = Infinity, tan;
|
|
814
|
+
p = m;
|
|
815
|
+
do {
|
|
816
|
+
if (hx >= p.x && p.x >= mx && hx !== p.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
|
|
817
|
+
tan = Math.abs(hy - p.y) / (hx - p.x);
|
|
818
|
+
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
|
|
819
|
+
m = p;
|
|
820
|
+
tanMin = tan;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
p = p.next;
|
|
824
|
+
} while (p !== stop);
|
|
825
|
+
return m;
|
|
826
|
+
}
|
|
827
|
+
function sectorContainsSector(m, p) {
|
|
828
|
+
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
829
|
+
}
|
|
830
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
831
|
+
let p = start;
|
|
832
|
+
do {
|
|
833
|
+
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
834
|
+
p.prevZ = p.prev;
|
|
835
|
+
p.nextZ = p.next;
|
|
836
|
+
p = p.next;
|
|
837
|
+
} while (p !== start);
|
|
838
|
+
p.prevZ.nextZ = null;
|
|
839
|
+
p.prevZ = null;
|
|
840
|
+
sortLinked(p);
|
|
841
|
+
}
|
|
842
|
+
function sortLinked(list2) {
|
|
843
|
+
let i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
|
|
844
|
+
do {
|
|
845
|
+
p = list2;
|
|
846
|
+
list2 = null;
|
|
847
|
+
tail = null;
|
|
848
|
+
numMerges = 0;
|
|
849
|
+
while (p) {
|
|
850
|
+
numMerges++;
|
|
851
|
+
q = p;
|
|
852
|
+
pSize = 0;
|
|
853
|
+
for (i = 0; i < inSize; i++) {
|
|
854
|
+
pSize++;
|
|
855
|
+
q = q.nextZ;
|
|
856
|
+
if (!q) break;
|
|
857
|
+
}
|
|
858
|
+
qSize = inSize;
|
|
859
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
860
|
+
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
|
|
861
|
+
e = p;
|
|
862
|
+
p = p.nextZ;
|
|
863
|
+
pSize--;
|
|
864
|
+
} else {
|
|
865
|
+
e = q;
|
|
866
|
+
q = q.nextZ;
|
|
867
|
+
qSize--;
|
|
868
|
+
}
|
|
869
|
+
if (tail) tail.nextZ = e;
|
|
870
|
+
else list2 = e;
|
|
871
|
+
e.prevZ = tail;
|
|
872
|
+
tail = e;
|
|
873
|
+
}
|
|
874
|
+
p = q;
|
|
875
|
+
}
|
|
876
|
+
tail.nextZ = null;
|
|
877
|
+
inSize *= 2;
|
|
878
|
+
} while (numMerges > 1);
|
|
879
|
+
return list2;
|
|
880
|
+
}
|
|
881
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
882
|
+
x = (x - minX) * invSize | 0;
|
|
883
|
+
y = (y - minY) * invSize | 0;
|
|
884
|
+
x = (x | x << 8) & 16711935;
|
|
885
|
+
x = (x | x << 4) & 252645135;
|
|
886
|
+
x = (x | x << 2) & 858993459;
|
|
887
|
+
x = (x | x << 1) & 1431655765;
|
|
888
|
+
y = (y | y << 8) & 16711935;
|
|
889
|
+
y = (y | y << 4) & 252645135;
|
|
890
|
+
y = (y | y << 2) & 858993459;
|
|
891
|
+
y = (y | y << 1) & 1431655765;
|
|
892
|
+
return x | y << 1;
|
|
893
|
+
}
|
|
894
|
+
function getLeftmost(start) {
|
|
895
|
+
let p = start, leftmost = start;
|
|
896
|
+
do {
|
|
897
|
+
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
|
|
898
|
+
p = p.next;
|
|
899
|
+
} while (p !== start);
|
|
900
|
+
return leftmost;
|
|
901
|
+
}
|
|
902
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
903
|
+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
|
904
|
+
}
|
|
905
|
+
function isValidDiagonal(a, b) {
|
|
906
|
+
return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
|
|
907
|
+
(locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
|
|
908
|
+
(area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
|
|
909
|
+
equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
|
|
910
|
+
}
|
|
911
|
+
function area(p, q, r) {
|
|
912
|
+
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
913
|
+
}
|
|
914
|
+
function equals(p1, p2) {
|
|
915
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
916
|
+
}
|
|
917
|
+
function intersects(p1, q1, p2, q2) {
|
|
918
|
+
const o1 = sign(area(p1, q1, p2));
|
|
919
|
+
const o2 = sign(area(p1, q1, q2));
|
|
920
|
+
const o3 = sign(area(p2, q2, p1));
|
|
921
|
+
const o4 = sign(area(p2, q2, q1));
|
|
922
|
+
if (o1 !== o2 && o3 !== o4) return true;
|
|
923
|
+
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
924
|
+
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
925
|
+
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
926
|
+
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
function onSegment(p, q, r) {
|
|
930
|
+
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
931
|
+
}
|
|
932
|
+
function sign(num2) {
|
|
933
|
+
return num2 > 0 ? 1 : num2 < 0 ? -1 : 0;
|
|
934
|
+
}
|
|
935
|
+
function intersectsPolygon(a, b) {
|
|
936
|
+
let p = a;
|
|
937
|
+
do {
|
|
938
|
+
if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && intersects(p, p.next, a, b)) return true;
|
|
939
|
+
p = p.next;
|
|
940
|
+
} while (p !== a);
|
|
941
|
+
return false;
|
|
942
|
+
}
|
|
943
|
+
function locallyInside(a, b) {
|
|
944
|
+
return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
|
|
945
|
+
}
|
|
946
|
+
function middleInside(a, b) {
|
|
947
|
+
let p = a, inside = false;
|
|
948
|
+
const px = (a.x + b.x) / 2, py = (a.y + b.y) / 2;
|
|
949
|
+
do {
|
|
950
|
+
if (p.y > py !== p.next.y > py && p.next.y !== p.y && px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)
|
|
951
|
+
inside = !inside;
|
|
952
|
+
p = p.next;
|
|
953
|
+
} while (p !== a);
|
|
954
|
+
return inside;
|
|
955
|
+
}
|
|
956
|
+
function splitPolygon(a, b) {
|
|
957
|
+
const a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev;
|
|
958
|
+
a.next = b;
|
|
959
|
+
b.prev = a;
|
|
960
|
+
a2.next = an;
|
|
961
|
+
an.prev = a2;
|
|
962
|
+
b2.next = a2;
|
|
963
|
+
a2.prev = b2;
|
|
964
|
+
bp.next = b2;
|
|
965
|
+
b2.prev = bp;
|
|
966
|
+
return b2;
|
|
967
|
+
}
|
|
968
|
+
function insertNode(i, x, y, last) {
|
|
969
|
+
const p = new Node(i, x, y);
|
|
970
|
+
if (!last) {
|
|
971
|
+
p.prev = p;
|
|
972
|
+
p.next = p;
|
|
973
|
+
} else {
|
|
974
|
+
p.next = last.next;
|
|
975
|
+
p.prev = last;
|
|
976
|
+
last.next.prev = p;
|
|
977
|
+
last.next = p;
|
|
978
|
+
}
|
|
979
|
+
return p;
|
|
980
|
+
}
|
|
981
|
+
function removeNode(p) {
|
|
982
|
+
p.next.prev = p.prev;
|
|
983
|
+
p.prev.next = p.next;
|
|
984
|
+
if (p.prevZ) p.prevZ.nextZ = p.nextZ;
|
|
985
|
+
if (p.nextZ) p.nextZ.prevZ = p.prevZ;
|
|
986
|
+
}
|
|
987
|
+
function Node(i, x, y) {
|
|
988
|
+
this.i = i;
|
|
989
|
+
this.x = x;
|
|
990
|
+
this.y = y;
|
|
991
|
+
this.prev = null;
|
|
992
|
+
this.next = null;
|
|
993
|
+
this.z = 0;
|
|
994
|
+
this.prevZ = null;
|
|
995
|
+
this.nextZ = null;
|
|
996
|
+
this.steiner = false;
|
|
997
|
+
}
|
|
998
|
+
function signedArea(data, start, end, dim) {
|
|
999
|
+
let sum = 0;
|
|
1000
|
+
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
1001
|
+
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
1002
|
+
j = i;
|
|
1003
|
+
}
|
|
1004
|
+
return sum;
|
|
1005
|
+
}
|
|
1006
|
+
var equals2 = (a, b) => a.x === b.x && a.y === b.y;
|
|
1007
|
+
var linePoint = (v1, v2, t) => t === 1 ? { x: v2.x, y: v2.y } : { x: (v2.x - v1.x) * t + v1.x, y: (v2.y - v1.y) * t + v1.y };
|
|
1008
|
+
function pathPoints(points) {
|
|
1009
|
+
const out = [];
|
|
1010
|
+
let last;
|
|
1011
|
+
for (let i = 1; i < points.length; i++) {
|
|
1012
|
+
const v1 = { x: points[i - 1][0], y: points[i - 1][1] };
|
|
1013
|
+
const v2 = { x: points[i][0], y: points[i][1] };
|
|
1014
|
+
for (let d = 0; d <= 1; d++) {
|
|
1015
|
+
const point = linePoint(v1, v2, d / 1);
|
|
1016
|
+
if (last && equals2(last, point)) continue;
|
|
1017
|
+
out.push(point);
|
|
1018
|
+
last = point;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
return out;
|
|
1022
|
+
}
|
|
1023
|
+
function area2(contour) {
|
|
1024
|
+
const n = contour.length;
|
|
1025
|
+
let a = 0;
|
|
1026
|
+
for (let p = n - 1, q = 0; q < n; p = q++) a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
|
|
1027
|
+
return a * 0.5;
|
|
1028
|
+
}
|
|
1029
|
+
var isClockWise = (pts) => area2(pts) < 0;
|
|
1030
|
+
function removeDupEndPts(points) {
|
|
1031
|
+
const l = points.length;
|
|
1032
|
+
if (l > 2 && equals2(points[l - 1], points[0])) points.pop();
|
|
1033
|
+
}
|
|
1034
|
+
function triangulateShape(contour, holes) {
|
|
1035
|
+
const vertices = [];
|
|
1036
|
+
const holeIndices = [];
|
|
1037
|
+
const faces = [];
|
|
1038
|
+
removeDupEndPts(contour);
|
|
1039
|
+
for (const p of contour) vertices.push(p.x, p.y);
|
|
1040
|
+
let holeIndex = contour.length;
|
|
1041
|
+
holes.forEach(removeDupEndPts);
|
|
1042
|
+
for (let i = 0; i < holes.length; i++) {
|
|
1043
|
+
holeIndices.push(holeIndex);
|
|
1044
|
+
holeIndex += holes[i].length;
|
|
1045
|
+
for (const p of holes[i]) vertices.push(p.x, p.y);
|
|
1046
|
+
}
|
|
1047
|
+
const triangles = Earcut.triangulate(vertices, holeIndices);
|
|
1048
|
+
for (let i = 0; i < triangles.length; i += 3) faces.push(triangles.slice(i, i + 3));
|
|
1049
|
+
return faces;
|
|
1050
|
+
}
|
|
1051
|
+
function computeVertexNormals(positions, indices) {
|
|
1052
|
+
const normals = new Float32Array(positions.length);
|
|
1053
|
+
const get = (array, i) => [array[i * 3], array[i * 3 + 1], array[i * 3 + 2]];
|
|
1054
|
+
const face = (vA, vB, vC) => {
|
|
1055
|
+
const pA = get(positions, vA);
|
|
1056
|
+
const pB = get(positions, vB);
|
|
1057
|
+
const pC = get(positions, vC);
|
|
1058
|
+
const cb = [pC[0] - pB[0], pC[1] - pB[1], pC[2] - pB[2]];
|
|
1059
|
+
const ab = [pA[0] - pB[0], pA[1] - pB[1], pA[2] - pB[2]];
|
|
1060
|
+
return [cb[1] * ab[2] - cb[2] * ab[1], cb[2] * ab[0] - cb[0] * ab[2], cb[0] * ab[1] - cb[1] * ab[0]];
|
|
1061
|
+
};
|
|
1062
|
+
const set = (i, x, y, z) => {
|
|
1063
|
+
normals[i * 3] = x;
|
|
1064
|
+
normals[i * 3 + 1] = y;
|
|
1065
|
+
normals[i * 3 + 2] = z;
|
|
1066
|
+
};
|
|
1067
|
+
if (indices) {
|
|
1068
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
1069
|
+
const vA = indices[i];
|
|
1070
|
+
const vB = indices[i + 1];
|
|
1071
|
+
const vC = indices[i + 2];
|
|
1072
|
+
const cb = face(vA, vB, vC);
|
|
1073
|
+
for (const v of [vA, vB, vC]) {
|
|
1074
|
+
const n = get(normals, v);
|
|
1075
|
+
set(v, n[0] + cb[0], n[1] + cb[1], n[2] + cb[2]);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
} else {
|
|
1079
|
+
for (let i = 0; i < positions.length / 3; i += 3) {
|
|
1080
|
+
const cb = face(i, i + 1, i + 2);
|
|
1081
|
+
set(i, cb[0], cb[1], cb[2]);
|
|
1082
|
+
set(i + 1, cb[0], cb[1], cb[2]);
|
|
1083
|
+
set(i + 2, cb[0], cb[1], cb[2]);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
for (let i = 0; i < normals.length / 3; i++) {
|
|
1087
|
+
const [x, y, z] = get(normals, i);
|
|
1088
|
+
const s = 1 / (Math.sqrt(x * x + y * y + z * z) || 1);
|
|
1089
|
+
set(i, x * s, y * s, z * s);
|
|
1090
|
+
}
|
|
1091
|
+
return normals;
|
|
1092
|
+
}
|
|
1093
|
+
function extrude(outline, depth = 1, steps = 1, bevel = void 0) {
|
|
1094
|
+
const parameters = { shape: outline, depth, steps, bevel: bevel ?? {} };
|
|
1095
|
+
const verticesArray = [];
|
|
1096
|
+
const uvArray = [];
|
|
1097
|
+
const groups = [];
|
|
1098
|
+
const placeholder = [];
|
|
1099
|
+
const bevelEnabled = bevel !== false;
|
|
1100
|
+
const spec = bevel === false || bevel === void 0 ? {} : bevel;
|
|
1101
|
+
let bevelThickness = spec.thickness !== void 0 ? spec.thickness : 0.2;
|
|
1102
|
+
let bevelSize = spec.size !== void 0 ? spec.size : bevelThickness - 0.1;
|
|
1103
|
+
let bevelOffset = spec.offset !== void 0 ? spec.offset : 0;
|
|
1104
|
+
let bevelSegments = spec.segments !== void 0 ? spec.segments : 3;
|
|
1105
|
+
if (!bevelEnabled) {
|
|
1106
|
+
bevelSegments = 0;
|
|
1107
|
+
bevelThickness = 0;
|
|
1108
|
+
bevelSize = 0;
|
|
1109
|
+
bevelOffset = 0;
|
|
1110
|
+
}
|
|
1111
|
+
let vertices = pathPoints(outline.outer);
|
|
1112
|
+
const holes = (outline.holes ?? []).map(pathPoints);
|
|
1113
|
+
const reverse = !isClockWise(vertices);
|
|
1114
|
+
if (reverse) {
|
|
1115
|
+
vertices = vertices.reverse();
|
|
1116
|
+
for (let h = 0; h < holes.length; h++) {
|
|
1117
|
+
const ahole = holes[h];
|
|
1118
|
+
if (isClockWise(ahole)) holes[h] = ahole.reverse();
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
const faces = triangulateShape(vertices, holes);
|
|
1122
|
+
const contour = vertices;
|
|
1123
|
+
for (const ahole of holes) vertices = vertices.concat(ahole);
|
|
1124
|
+
const scalePt2 = (pt, vec, size) => ({ x: pt.x + vec.x * size, y: pt.y + vec.y * size });
|
|
1125
|
+
const vlen = vertices.length;
|
|
1126
|
+
const flen = faces.length;
|
|
1127
|
+
const getBevelVec = (inPt, inPrev, inNext) => {
|
|
1128
|
+
let vTransX;
|
|
1129
|
+
let vTransY;
|
|
1130
|
+
let shrinkBy;
|
|
1131
|
+
const vPrevX = inPt.x - inPrev.x;
|
|
1132
|
+
const vPrevY = inPt.y - inPrev.y;
|
|
1133
|
+
const vNextX = inNext.x - inPt.x;
|
|
1134
|
+
const vNextY = inNext.y - inPt.y;
|
|
1135
|
+
const vPrevLensq = vPrevX * vPrevX + vPrevY * vPrevY;
|
|
1136
|
+
const collinear0 = vPrevX * vNextY - vPrevY * vNextX;
|
|
1137
|
+
if (Math.abs(collinear0) > Number.EPSILON) {
|
|
1138
|
+
const vPrevLen = Math.sqrt(vPrevLensq);
|
|
1139
|
+
const vNextLen = Math.sqrt(vNextX * vNextX + vNextY * vNextY);
|
|
1140
|
+
const ptPrevShiftX = inPrev.x - vPrevY / vPrevLen;
|
|
1141
|
+
const ptPrevShiftY = inPrev.y + vPrevX / vPrevLen;
|
|
1142
|
+
const ptNextShiftX = inNext.x - vNextY / vNextLen;
|
|
1143
|
+
const ptNextShiftY = inNext.y + vNextX / vNextLen;
|
|
1144
|
+
const sf = ((ptNextShiftX - ptPrevShiftX) * vNextY - (ptNextShiftY - ptPrevShiftY) * vNextX) / (vPrevX * vNextY - vPrevY * vNextX);
|
|
1145
|
+
vTransX = ptPrevShiftX + vPrevX * sf - inPt.x;
|
|
1146
|
+
vTransY = ptPrevShiftY + vPrevY * sf - inPt.y;
|
|
1147
|
+
const vTransLensq = vTransX * vTransX + vTransY * vTransY;
|
|
1148
|
+
if (vTransLensq <= 2) return { x: vTransX, y: vTransY };
|
|
1149
|
+
shrinkBy = Math.sqrt(vTransLensq / 2);
|
|
1150
|
+
} else {
|
|
1151
|
+
let directionEq = false;
|
|
1152
|
+
if (vPrevX > Number.EPSILON) {
|
|
1153
|
+
if (vNextX > Number.EPSILON) directionEq = true;
|
|
1154
|
+
} else if (vPrevX < -Number.EPSILON) {
|
|
1155
|
+
if (vNextX < -Number.EPSILON) directionEq = true;
|
|
1156
|
+
} else if (Math.sign(vPrevY) === Math.sign(vNextY)) {
|
|
1157
|
+
directionEq = true;
|
|
1158
|
+
}
|
|
1159
|
+
if (directionEq) {
|
|
1160
|
+
vTransX = -vPrevY;
|
|
1161
|
+
vTransY = vPrevX;
|
|
1162
|
+
shrinkBy = Math.sqrt(vPrevLensq);
|
|
1163
|
+
} else {
|
|
1164
|
+
vTransX = vPrevX;
|
|
1165
|
+
vTransY = vPrevY;
|
|
1166
|
+
shrinkBy = Math.sqrt(vPrevLensq / 2);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return { x: vTransX / shrinkBy, y: vTransY / shrinkBy };
|
|
1170
|
+
};
|
|
1171
|
+
const movements = (ring2) => {
|
|
1172
|
+
const out = [];
|
|
1173
|
+
for (let i = 0, il = ring2.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
|
|
1174
|
+
if (j === il) j = 0;
|
|
1175
|
+
if (k === il) k = 0;
|
|
1176
|
+
out[i] = getBevelVec(ring2[i], ring2[j], ring2[k]);
|
|
1177
|
+
}
|
|
1178
|
+
return out;
|
|
1179
|
+
};
|
|
1180
|
+
const contourMovements = movements(contour);
|
|
1181
|
+
const holesMovements = [];
|
|
1182
|
+
let verticesMovements = contourMovements.concat();
|
|
1183
|
+
for (const ahole of holes) {
|
|
1184
|
+
const oneHoleMovements = movements(ahole);
|
|
1185
|
+
holesMovements.push(oneHoleMovements);
|
|
1186
|
+
verticesMovements = verticesMovements.concat(oneHoleMovements);
|
|
1187
|
+
}
|
|
1188
|
+
const v = (x, y, z) => {
|
|
1189
|
+
placeholder.push(x);
|
|
1190
|
+
placeholder.push(y);
|
|
1191
|
+
placeholder.push(z);
|
|
1192
|
+
};
|
|
1193
|
+
const bevelLayer = (b, zOf) => {
|
|
1194
|
+
const t = b / bevelSegments;
|
|
1195
|
+
const z = bevelThickness * Math.cos(t * Math.PI / 2);
|
|
1196
|
+
const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
|
|
1197
|
+
for (let i = 0; i < contour.length; i++) {
|
|
1198
|
+
const vert = scalePt2(contour[i], contourMovements[i], bs2);
|
|
1199
|
+
v(vert.x, vert.y, zOf(z));
|
|
1200
|
+
}
|
|
1201
|
+
for (let h = 0; h < holes.length; h++) {
|
|
1202
|
+
const ahole = holes[h];
|
|
1203
|
+
const oneHoleMovements = holesMovements[h];
|
|
1204
|
+
for (let i = 0; i < ahole.length; i++) {
|
|
1205
|
+
const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
|
|
1206
|
+
v(vert.x, vert.y, zOf(z));
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
};
|
|
1210
|
+
for (let b = 0; b < bevelSegments; b++) bevelLayer(b, (z) => -z);
|
|
1211
|
+
const bs = bevelSize + bevelOffset;
|
|
1212
|
+
for (let i = 0; i < vlen; i++) {
|
|
1213
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
1214
|
+
v(vert.x, vert.y, 0);
|
|
1215
|
+
}
|
|
1216
|
+
for (let s = 1; s <= steps; s++) {
|
|
1217
|
+
for (let i = 0; i < vlen; i++) {
|
|
1218
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
1219
|
+
v(vert.x, vert.y, depth / steps * s);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
for (let b = bevelSegments - 1; b >= 0; b--) bevelLayer(b, (z) => depth + z);
|
|
1223
|
+
const addVertex = (index) => {
|
|
1224
|
+
verticesArray.push(placeholder[index * 3 + 0]);
|
|
1225
|
+
verticesArray.push(placeholder[index * 3 + 1]);
|
|
1226
|
+
verticesArray.push(placeholder[index * 3 + 2]);
|
|
1227
|
+
};
|
|
1228
|
+
const addUV = (x, y) => {
|
|
1229
|
+
uvArray.push(x);
|
|
1230
|
+
uvArray.push(y);
|
|
1231
|
+
};
|
|
1232
|
+
const at = (index, axis) => verticesArray[index * 3 + axis];
|
|
1233
|
+
const f3 = (a, b, c) => {
|
|
1234
|
+
addVertex(a);
|
|
1235
|
+
addVertex(b);
|
|
1236
|
+
addVertex(c);
|
|
1237
|
+
const nextIndex = verticesArray.length / 3;
|
|
1238
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at(index, 0), at(index, 1));
|
|
1239
|
+
};
|
|
1240
|
+
const f4 = (a, b, c, d) => {
|
|
1241
|
+
addVertex(a);
|
|
1242
|
+
addVertex(b);
|
|
1243
|
+
addVertex(d);
|
|
1244
|
+
addVertex(b);
|
|
1245
|
+
addVertex(c);
|
|
1246
|
+
addVertex(d);
|
|
1247
|
+
const nextIndex = verticesArray.length / 3;
|
|
1248
|
+
const iA = nextIndex - 6;
|
|
1249
|
+
const iB = nextIndex - 3;
|
|
1250
|
+
const iC = nextIndex - 2;
|
|
1251
|
+
const iD = nextIndex - 1;
|
|
1252
|
+
const byX = Math.abs(at(iA, 1) - at(iB, 1)) < Math.abs(at(iA, 0) - at(iB, 0));
|
|
1253
|
+
const uv = (index) => [byX ? at(index, 0) : at(index, 1), 1 - at(index, 2)];
|
|
1254
|
+
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
1255
|
+
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
1256
|
+
};
|
|
1257
|
+
let start = verticesArray.length / 3;
|
|
1258
|
+
if (bevelEnabled) {
|
|
1259
|
+
let offset = 0;
|
|
1260
|
+
for (let i = 0; i < flen; i++) {
|
|
1261
|
+
const face = faces[i];
|
|
1262
|
+
f3(face[2] + offset, face[1] + offset, face[0] + offset);
|
|
1263
|
+
}
|
|
1264
|
+
const layer = steps + bevelSegments * 2;
|
|
1265
|
+
offset = vlen * layer;
|
|
1266
|
+
for (let i = 0; i < flen; i++) {
|
|
1267
|
+
const face = faces[i];
|
|
1268
|
+
f3(face[0] + offset, face[1] + offset, face[2] + offset);
|
|
1269
|
+
}
|
|
1270
|
+
} else {
|
|
1271
|
+
for (let i = 0; i < flen; i++) {
|
|
1272
|
+
const face = faces[i];
|
|
1273
|
+
f3(face[2], face[1], face[0]);
|
|
1274
|
+
}
|
|
1275
|
+
for (let i = 0; i < flen; i++) {
|
|
1276
|
+
const face = faces[i];
|
|
1277
|
+
f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 0 });
|
|
1281
|
+
start = verticesArray.length / 3;
|
|
1282
|
+
const sidewalls = (ring2, layeroffset2) => {
|
|
1283
|
+
let i = ring2.length;
|
|
1284
|
+
while (--i >= 0) {
|
|
1285
|
+
const j = i;
|
|
1286
|
+
let k = i - 1;
|
|
1287
|
+
if (k < 0) k = ring2.length - 1;
|
|
1288
|
+
for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
|
|
1289
|
+
const slen1 = vlen * s;
|
|
1290
|
+
const slen2 = vlen * (s + 1);
|
|
1291
|
+
f4(layeroffset2 + j + slen1, layeroffset2 + k + slen1, layeroffset2 + k + slen2, layeroffset2 + j + slen2);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
let layeroffset = 0;
|
|
1296
|
+
sidewalls(contour, layeroffset);
|
|
1297
|
+
layeroffset += contour.length;
|
|
1298
|
+
for (const ahole of holes) {
|
|
1299
|
+
sidewalls(ahole, layeroffset);
|
|
1300
|
+
layeroffset += ahole.length;
|
|
1301
|
+
}
|
|
1302
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 1 });
|
|
1303
|
+
const positions = new Float32Array(verticesArray);
|
|
1304
|
+
return { type: "ExtrudeGeometry", parameters, positions, normals: computeVertexNormals(positions), uvs: new Float32Array(uvArray), groups };
|
|
1305
|
+
}
|
|
1306
|
+
var PARAMETER_KEYS = {
|
|
1307
|
+
box: ["size", "segments"],
|
|
1308
|
+
cylinder: ["radiusTop", "radiusBottom", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
1309
|
+
cone: ["radius", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
1310
|
+
sphere: ["radius", "widthSegments", "heightSegments", "phiStart", "phiLength", "thetaStart", "thetaLength"],
|
|
1311
|
+
plane: ["width", "height", "widthSegments", "heightSegments"],
|
|
1312
|
+
circle: ["radius", "segments", "thetaStart", "thetaLength"],
|
|
1313
|
+
ring: ["innerRadius", "outerRadius", "thetaSegments", "phiSegments", "thetaStart", "thetaLength"],
|
|
1314
|
+
lathe: ["points", "segments", "phiStart", "phiLength"],
|
|
1315
|
+
torus: ["radius", "tube", "radialSegments", "tubularSegments", "arc"],
|
|
1316
|
+
extrude: ["shape", "depth", "steps", "bevel"],
|
|
1317
|
+
difference: ["size", "subtract"],
|
|
1318
|
+
mesh: ["positions", "normals", "uvs", "indices"]
|
|
1319
|
+
};
|
|
1320
|
+
var SEGMENT_KEYS = {
|
|
1321
|
+
cylinder: ["radialSegments"],
|
|
1322
|
+
cone: ["radialSegments"],
|
|
1323
|
+
sphere: ["widthSegments", "heightSegments"],
|
|
1324
|
+
circle: ["segments"],
|
|
1325
|
+
ring: ["thetaSegments"],
|
|
1326
|
+
lathe: ["segments"],
|
|
1327
|
+
torus: ["radialSegments", "tubularSegments"]
|
|
1328
|
+
};
|
|
1329
|
+
var SEGMENT_DEFAULTS = { radialSegments: 32, widthSegments: 32, heightSegments: 16, segments: 12, thetaSegments: 32, tubularSegments: 48 };
|
|
1330
|
+
var segmentDefault = (kind, key2) => kind === "circle" && key2 === "segments" ? 32 : kind === "torus" && key2 === "radialSegments" ? 12 : SEGMENT_DEFAULTS[key2];
|
|
1331
|
+
function primitiveParameters(node, options = {}) {
|
|
1332
|
+
const out = {};
|
|
1333
|
+
const source = node;
|
|
1334
|
+
for (const key2 of PARAMETER_KEYS[node.kind]) if (source[key2] !== void 0) out[key2] = source[key2];
|
|
1335
|
+
const detail = options.detail ?? 1;
|
|
1336
|
+
if (detail !== 1) {
|
|
1337
|
+
const floor = options.minSegments ?? 3;
|
|
1338
|
+
for (const key2 of SEGMENT_KEYS[node.kind] ?? []) {
|
|
1339
|
+
const given = out[key2] ?? segmentDefault(node.kind, key2);
|
|
1340
|
+
out[key2] = Math.max(floor, Math.round(given * detail));
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return out;
|
|
1344
|
+
}
|
|
1345
|
+
function mesh(p) {
|
|
1346
|
+
const positions = new Float32Array(p.positions);
|
|
1347
|
+
const indices = p.indices ? indexArray(p.indices) : void 0;
|
|
1348
|
+
return {
|
|
1349
|
+
type: "BufferGeometry",
|
|
1350
|
+
parameters: {},
|
|
1351
|
+
positions,
|
|
1352
|
+
normals: p.normals ? new Float32Array(p.normals) : computeVertexNormals(positions, indices),
|
|
1353
|
+
uvs: p.uvs ? new Float32Array(p.uvs) : new Float32Array(positions.length / 3 * 2),
|
|
1354
|
+
...indices ? { indices } : {},
|
|
1355
|
+
groups: []
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
function make(kind, p) {
|
|
1359
|
+
switch (kind) {
|
|
1360
|
+
case "box": {
|
|
1361
|
+
const size = p.size ?? [1, 1, 1];
|
|
1362
|
+
const segments = p.segments ?? [1, 1, 1];
|
|
1363
|
+
return box(size[0], size[1], size[2], segments[0], segments[1], segments[2]);
|
|
1364
|
+
}
|
|
1365
|
+
case "cylinder":
|
|
1366
|
+
return cylinder(p.radiusTop, p.radiusBottom, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
|
|
1367
|
+
case "cone":
|
|
1368
|
+
return cone(p.radius, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
|
|
1369
|
+
case "sphere":
|
|
1370
|
+
return sphere(p.radius, p.widthSegments, p.heightSegments, p.phiStart, p.phiLength, p.thetaStart, p.thetaLength);
|
|
1371
|
+
case "plane":
|
|
1372
|
+
return plane(p.width, p.height, p.widthSegments, p.heightSegments);
|
|
1373
|
+
case "circle":
|
|
1374
|
+
return circle(p.radius, p.segments, p.thetaStart, p.thetaLength);
|
|
1375
|
+
case "ring":
|
|
1376
|
+
return ring(p.innerRadius, p.outerRadius, p.thetaSegments, p.phiSegments, p.thetaStart, p.thetaLength);
|
|
1377
|
+
case "lathe":
|
|
1378
|
+
return lathe(p.points, p.segments, p.phiStart, p.phiLength);
|
|
1379
|
+
case "torus":
|
|
1380
|
+
return torus(p.radius, p.tube, p.radialSegments, p.tubularSegments, p.arc);
|
|
1381
|
+
case "extrude":
|
|
1382
|
+
return extrude(p.shape, p.depth, p.steps, p.bevel);
|
|
1383
|
+
case "difference":
|
|
1384
|
+
return difference(p.size, p.subtract ?? []);
|
|
1385
|
+
case "mesh":
|
|
1386
|
+
return mesh(p);
|
|
1387
|
+
default:
|
|
1388
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
var templates = /* @__PURE__ */ new Map();
|
|
1392
|
+
var templateLimit = 4096;
|
|
1393
|
+
var stats = { hits: 0, misses: 0 };
|
|
1394
|
+
function buildPrimitive(node, options = {}) {
|
|
1395
|
+
const parameters = primitiveParameters(node, options);
|
|
1396
|
+
if (node.kind === "mesh" || templateLimit === 0) return make(node.kind, parameters);
|
|
1397
|
+
const key2 = `${node.kind}:${canonicalJson(parameters)}`;
|
|
1398
|
+
const cached = templates.get(key2);
|
|
1399
|
+
if (cached) {
|
|
1400
|
+
stats.hits++;
|
|
1401
|
+
templates.delete(key2);
|
|
1402
|
+
templates.set(key2, cached);
|
|
1403
|
+
return cached;
|
|
1404
|
+
}
|
|
1405
|
+
stats.misses++;
|
|
1406
|
+
const built = make(node.kind, parameters);
|
|
1407
|
+
templates.set(key2, built);
|
|
1408
|
+
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
1409
|
+
return built;
|
|
1410
|
+
}
|
|
1411
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
|
|
1412
|
+
var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
|
|
1413
|
+
var str = (v) => typeof v === "string" ? null : "expected a string";
|
|
1414
|
+
var int = (min) => (v) => typeof v === "number" && Number.isInteger(v) && v >= min ? null : `expected an integer >= ${min}`;
|
|
1415
|
+
var range = (lo, hi, loOpen = false) => (v) => typeof v === "number" && (loOpen ? v > lo : v >= lo) && v <= hi ? null : `expected a number in ${loOpen ? "(" : "["}${lo}, ${hi}]`;
|
|
1416
|
+
var tuple = (n, item = num) => (v) => {
|
|
1417
|
+
if (!Array.isArray(v) || v.length !== n) return `expected an array of ${n}`;
|
|
1418
|
+
for (const x of v) if (item(x)) return `expected an array of ${n} numbers`;
|
|
1419
|
+
return null;
|
|
1420
|
+
};
|
|
1421
|
+
var list = (item, min = 0) => (v) => {
|
|
1422
|
+
if (!Array.isArray(v)) return "expected an array";
|
|
1423
|
+
if (v.length < min) return `expected at least ${min} items`;
|
|
1424
|
+
for (let i = 0; i < v.length; i++) {
|
|
1425
|
+
const e = item(v[i]);
|
|
1426
|
+
if (e) return `[${i}]: ${e}`;
|
|
1427
|
+
}
|
|
1428
|
+
return null;
|
|
1429
|
+
};
|
|
1430
|
+
var color = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= 16777215 || typeof v === "string" && /^#[0-9a-fA-F]{6}$/.test(v) ? null : 'expected 0xRRGGBB or "#rrggbb"';
|
|
1431
|
+
var oneOf = (values) => (v) => values.includes(v) ? null : `expected one of ${values.map((x) => JSON.stringify(x)).join(", ")}`;
|
|
1432
|
+
var object = (fields, required = []) => (v) => {
|
|
1433
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return "expected an object";
|
|
1434
|
+
const record = v;
|
|
1435
|
+
for (const key2 of required) if (record[key2] === void 0) return `${key2}: required`;
|
|
1436
|
+
for (const key2 of Object.keys(record)) {
|
|
1437
|
+
if (record[key2] === void 0) continue;
|
|
1438
|
+
const check = fields[key2];
|
|
1439
|
+
if (!check) return `${key2}: unknown field`;
|
|
1440
|
+
const e = check(record[key2]);
|
|
1441
|
+
if (e) return `${key2}: ${e}`;
|
|
1442
|
+
}
|
|
1443
|
+
return null;
|
|
1444
|
+
};
|
|
1445
|
+
var ORDERS = ["XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"];
|
|
1446
|
+
var TRANSFORM = {
|
|
1447
|
+
position: tuple(3),
|
|
1448
|
+
rotation: tuple(3),
|
|
1449
|
+
rotationOrder: oneOf(ORDERS),
|
|
1450
|
+
scale: (v) => typeof v === "number" ? num(v) : tuple(3)(v),
|
|
1451
|
+
heading: num,
|
|
1452
|
+
matrix: tuple(16)
|
|
1453
|
+
};
|
|
1454
|
+
var UV = object({ u0: num, v0: num, u1: num, v1: num }, ["u0", "v0", "u1", "v1"]);
|
|
1455
|
+
var INSTANCE = object({ ...TRANSFORM, color });
|
|
1456
|
+
var COMMON = {
|
|
1457
|
+
...TRANSFORM,
|
|
1458
|
+
kind: str,
|
|
1459
|
+
name: str,
|
|
1460
|
+
part: str,
|
|
1461
|
+
material: str,
|
|
1462
|
+
color,
|
|
1463
|
+
uv: UV,
|
|
1464
|
+
instances: list(INSTANCE),
|
|
1465
|
+
minDetail: range(0, 1, true),
|
|
1466
|
+
tags: list(str)
|
|
1467
|
+
};
|
|
1468
|
+
var vec2 = tuple(2);
|
|
1469
|
+
var BEVEL = (v) => v === false ? null : object({ thickness: num, size: num, offset: num, segments: int(1) })(v);
|
|
1470
|
+
var KINDS = {
|
|
1471
|
+
group: { fields: {} },
|
|
1472
|
+
box: { fields: { size: tuple(3), segments: tuple(3, int(1)) } },
|
|
1473
|
+
cylinder: { fields: { radiusTop: num, radiusBottom: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
1474
|
+
cone: { fields: { radius: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
1475
|
+
sphere: { fields: { radius: num, widthSegments: int(3), heightSegments: int(2), phiStart: num, phiLength: num, thetaStart: num, thetaLength: num } },
|
|
1476
|
+
plane: { fields: { width: num, height: num, widthSegments: int(1), heightSegments: int(1) } },
|
|
1477
|
+
circle: { fields: { radius: num, segments: int(3), thetaStart: num, thetaLength: num } },
|
|
1478
|
+
ring: { fields: { innerRadius: num, outerRadius: num, thetaSegments: int(3), phiSegments: int(1), thetaStart: num, thetaLength: num } },
|
|
1479
|
+
lathe: { fields: { points: list(vec2, 2), segments: int(1), phiStart: num, phiLength: num }, required: ["points"] },
|
|
1480
|
+
torus: { fields: { radius: num, tube: num, radialSegments: int(1), tubularSegments: int(1), arc: num } },
|
|
1481
|
+
extrude: {
|
|
1482
|
+
fields: { shape: object({ outer: list(vec2, 3), holes: list(list(vec2, 3)) }, ["outer"]), depth: num, steps: int(1), bevel: BEVEL },
|
|
1483
|
+
required: ["shape"]
|
|
1484
|
+
},
|
|
1485
|
+
difference: { fields: { size: tuple(3), subtract: list(object({ min: vec2, max: vec2 }, ["min", "max"])) }, required: ["size", "subtract"] },
|
|
1486
|
+
mesh: {
|
|
1487
|
+
fields: {
|
|
1488
|
+
positions: (v) => list(num)(v) ?? (v.length % 3 === 0 ? null : "expected a multiple of 3 numbers"),
|
|
1489
|
+
normals: list(num),
|
|
1490
|
+
uvs: list(num),
|
|
1491
|
+
indices: list(int(0))
|
|
1492
|
+
},
|
|
1493
|
+
required: ["positions"]
|
|
1494
|
+
},
|
|
1495
|
+
point: { fields: { data: () => null } },
|
|
1496
|
+
custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
|
|
1497
|
+
};
|
|
1498
|
+
function mergeTransformed(pieces) {
|
|
1499
|
+
let total = 0;
|
|
1500
|
+
for (const piece2 of pieces) total += piece2.indices ? piece2.indices.length : piece2.positions.length / 3;
|
|
1501
|
+
const positions = new Float32Array(total * 3);
|
|
1502
|
+
const normals = new Float32Array(total * 3);
|
|
1503
|
+
const uvs = new Float32Array(total * 2);
|
|
1504
|
+
let at = 0;
|
|
1505
|
+
for (const piece2 of pieces) {
|
|
1506
|
+
const e = piece2.matrix;
|
|
1507
|
+
const nm = normalMatrix(e);
|
|
1508
|
+
const count = piece2.indices ? piece2.indices.length : piece2.positions.length / 3;
|
|
1509
|
+
const p = new Float32Array(count * 3);
|
|
1510
|
+
const n = new Float32Array(count * 3);
|
|
1511
|
+
for (let k = 0; k < count; k++) {
|
|
1512
|
+
const i = piece2.indices ? piece2.indices[k] : k;
|
|
1513
|
+
for (let c = 0; c < 3; c++) {
|
|
1514
|
+
p[k * 3 + c] = piece2.positions[i * 3 + c];
|
|
1515
|
+
if (piece2.normals) n[k * 3 + c] = piece2.normals[i * 3 + c];
|
|
1516
|
+
}
|
|
1517
|
+
if (piece2.uvs) {
|
|
1518
|
+
uvs[(at + k) * 2] = piece2.uvs[i * 2];
|
|
1519
|
+
uvs[(at + k) * 2 + 1] = piece2.uvs[i * 2 + 1];
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
for (let k = 0; k < count; k++) {
|
|
1523
|
+
const q = transformPoint(e, p[k * 3], p[k * 3 + 1], p[k * 3 + 2]);
|
|
1524
|
+
positions[(at + k) * 3] = q[0];
|
|
1525
|
+
positions[(at + k) * 3 + 1] = q[1];
|
|
1526
|
+
positions[(at + k) * 3 + 2] = q[2];
|
|
1527
|
+
const x = n[k * 3];
|
|
1528
|
+
const y = n[k * 3 + 1];
|
|
1529
|
+
const z = n[k * 3 + 2];
|
|
1530
|
+
const vx = nm[0] * x + nm[3] * y + nm[6] * z;
|
|
1531
|
+
const vy = nm[1] * x + nm[4] * y + nm[7] * z;
|
|
1532
|
+
const vz = nm[2] * x + nm[5] * y + nm[8] * z;
|
|
1533
|
+
const s = 1 / (Math.sqrt(vx * vx + vy * vy + vz * vz) || 1);
|
|
1534
|
+
normals[(at + k) * 3] = vx * s;
|
|
1535
|
+
normals[(at + k) * 3 + 1] = vy * s;
|
|
1536
|
+
normals[(at + k) * 3 + 2] = vz * s;
|
|
1537
|
+
}
|
|
1538
|
+
at += count;
|
|
1539
|
+
}
|
|
1540
|
+
return { positions, normals, uvs };
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
// ../game-shapes-three/dist/index.js
|
|
1544
|
+
var UV_BEFORE_NORMAL = /* @__PURE__ */ new Set(["LatheGeometry", "ExtrudeGeometry"]);
|
|
1545
|
+
var INDEX_FIRST = /* @__PURE__ */ new Set(["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry"]);
|
|
1546
|
+
var isPrimitive = (value) => typeof value.type === "string";
|
|
1547
|
+
function threeParameters(THREE, p) {
|
|
1548
|
+
if (p.type === "LatheGeometry") {
|
|
1549
|
+
const points = p.parameters.points.map(({ x, y }) => new THREE.Vector2(x, y));
|
|
1550
|
+
return { ...p.parameters, points };
|
|
1551
|
+
}
|
|
1552
|
+
return { ...p.parameters };
|
|
1553
|
+
}
|
|
1554
|
+
function toGeometry(THREE, source, options = {}) {
|
|
1555
|
+
const copy = options.copy !== false;
|
|
1556
|
+
const primitive = isPrimitive(source) ? source : null;
|
|
1557
|
+
const ThreeClass = primitive && primitive.type !== "BufferGeometry" ? THREE[primitive.type] : void 0;
|
|
1558
|
+
const geometry = ThreeClass ? Reflect.construct(THREE.BufferGeometry, [], ThreeClass) : new THREE.BufferGeometry();
|
|
1559
|
+
if (primitive && ThreeClass) {
|
|
1560
|
+
Object.assign(geometry, { type: primitive.type, parameters: threeParameters(THREE, primitive) });
|
|
1561
|
+
}
|
|
1562
|
+
const attribute = (array, size) => copy ? new THREE.Float32BufferAttribute(array, size) : new THREE.BufferAttribute(array, size);
|
|
1563
|
+
const index = source.indices;
|
|
1564
|
+
const setIndex = () => {
|
|
1565
|
+
if (!index) return;
|
|
1566
|
+
geometry.setIndex(copy ? index instanceof Uint32Array ? new THREE.Uint32BufferAttribute(index, 1) : new THREE.Uint16BufferAttribute(index, 1) : new THREE.BufferAttribute(index, 1));
|
|
1567
|
+
};
|
|
1568
|
+
const type = primitive?.type ?? "BufferGeometry";
|
|
1569
|
+
if (INDEX_FIRST.has(type)) setIndex();
|
|
1570
|
+
geometry.setAttribute("position", attribute(source.positions, 3));
|
|
1571
|
+
if (UV_BEFORE_NORMAL.has(type)) {
|
|
1572
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
1573
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
1574
|
+
} else {
|
|
1575
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
1576
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
1577
|
+
}
|
|
1578
|
+
if (!primitive && source.colors) geometry.setAttribute("color", attribute(source.colors, 3));
|
|
1579
|
+
if (!INDEX_FIRST.has(type)) setIndex();
|
|
1580
|
+
if (primitive) for (const group of primitive.groups) geometry.addGroup(group.start, group.count, group.materialIndex);
|
|
1581
|
+
return geometry;
|
|
1582
|
+
}
|
|
1583
|
+
var SHAPE_GEOMETRY_TYPES = ["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry", "ExtrudeGeometry"];
|
|
1584
|
+
function linePoints(path) {
|
|
1585
|
+
if (path.autoClose || path.curves.length === 0) return null;
|
|
1586
|
+
const points = [];
|
|
1587
|
+
for (const [index, curve] of path.curves.entries()) {
|
|
1588
|
+
if (!curve.isLineCurve || !curve.v1 || !curve.v2) return null;
|
|
1589
|
+
if (index === 0) points.push([curve.v1.x, curve.v1.y]);
|
|
1590
|
+
else {
|
|
1591
|
+
const last = points[points.length - 1];
|
|
1592
|
+
if (last[0] !== curve.v1.x || last[1] !== curve.v1.y) return null;
|
|
1593
|
+
}
|
|
1594
|
+
points.push([curve.v2.x, curve.v2.y]);
|
|
1595
|
+
}
|
|
1596
|
+
return points;
|
|
1597
|
+
}
|
|
1598
|
+
function extrudeOf(shapes, options = {}) {
|
|
1599
|
+
if (Array.isArray(shapes) || !shapes || options.extrudePath !== void 0 || options.UVGenerator !== void 0) return null;
|
|
1600
|
+
const shape = shapes;
|
|
1601
|
+
const outer = linePoints(shape);
|
|
1602
|
+
if (!outer) return null;
|
|
1603
|
+
const holes = [];
|
|
1604
|
+
for (const hole of shape.holes ?? []) {
|
|
1605
|
+
const points = linePoints(hole);
|
|
1606
|
+
if (!points) return null;
|
|
1607
|
+
holes.push(points);
|
|
1608
|
+
}
|
|
1609
|
+
const outline = holes.length ? { outer, holes } : { outer };
|
|
1610
|
+
const bevel = options.bevelEnabled === false ? false : {
|
|
1611
|
+
...options.bevelThickness !== void 0 ? { thickness: options.bevelThickness } : {},
|
|
1612
|
+
...options.bevelSize !== void 0 ? { size: options.bevelSize } : {},
|
|
1613
|
+
...options.bevelOffset !== void 0 ? { offset: options.bevelOffset } : {},
|
|
1614
|
+
...options.bevelSegments !== void 0 ? { segments: options.bevelSegments } : {}
|
|
1615
|
+
};
|
|
1616
|
+
return extrude(outline, options.depth, options.steps, bevel);
|
|
1617
|
+
}
|
|
1618
|
+
var namespaces = /* @__PURE__ */ new WeakMap();
|
|
1619
|
+
function shapeGeometries(THREE, options = {}) {
|
|
1620
|
+
const cache = options.cache !== false;
|
|
1621
|
+
const key2 = cache ? "cache" : "nocache";
|
|
1622
|
+
let byKey = namespaces.get(THREE);
|
|
1623
|
+
if (!byKey) {
|
|
1624
|
+
byKey = /* @__PURE__ */ new Map();
|
|
1625
|
+
namespaces.set(THREE, byKey);
|
|
1626
|
+
}
|
|
1627
|
+
const existing = byKey.get(key2);
|
|
1628
|
+
if (existing) return existing;
|
|
1629
|
+
const made = (p) => toGeometry(THREE, p);
|
|
1630
|
+
const viaCache = (node, direct) => cache ? buildPrimitive(node) : direct();
|
|
1631
|
+
const defined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
1632
|
+
const constructors = {
|
|
1633
|
+
BoxGeometry: (width, height, depth, ws = 1, hs = 1, ds = 1) => made(viaCache({ kind: "box", size: [width ?? 1, height ?? 1, depth ?? 1], segments: [ws, hs, ds] }, () => box(width, height, depth, ws, hs, ds))),
|
|
1634
|
+
CylinderGeometry: (radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cylinder", ...defined({ radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cylinder(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
|
|
1635
|
+
ConeGeometry: (radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cone", ...defined({ radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cone(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
|
|
1636
|
+
SphereGeometry: (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) => made(viaCache({ kind: "sphere", ...defined({ radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength }) }, () => sphere(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength))),
|
|
1637
|
+
PlaneGeometry: (width, height, widthSegments, heightSegments) => made(viaCache({ kind: "plane", ...defined({ width, height, widthSegments, heightSegments }) }, () => plane(width, height, widthSegments, heightSegments))),
|
|
1638
|
+
CircleGeometry: (radius, segments, thetaStart, thetaLength) => made(viaCache({ kind: "circle", ...defined({ radius, segments, thetaStart, thetaLength }) }, () => circle(radius, segments, thetaStart, thetaLength))),
|
|
1639
|
+
RingGeometry: (innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) => made(viaCache({ kind: "ring", ...defined({ innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength }) }, () => ring(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength))),
|
|
1640
|
+
LatheGeometry: (points, segments, phiStart, phiLength) => {
|
|
1641
|
+
if (!points) return new THREE.LatheGeometry(void 0, segments, phiStart, phiLength);
|
|
1642
|
+
const profile = points.map((p) => [p.x, p.y]);
|
|
1643
|
+
return made(viaCache({ kind: "lathe", points: profile, ...defined({ segments, phiStart, phiLength }) }, () => lathe(profile, segments, phiStart, phiLength)));
|
|
1644
|
+
},
|
|
1645
|
+
TorusGeometry: (radius, tube2, radialSegments, tubularSegments, arc) => made(viaCache({ kind: "torus", ...defined({ radius, tube: tube2, radialSegments, tubularSegments, arc }) }, () => torus(radius, tube2, radialSegments, tubularSegments, arc))),
|
|
1646
|
+
ExtrudeGeometry: (shapes, extrudeOptions) => {
|
|
1647
|
+
const buffers = shapes === void 0 ? null : extrudeOf(shapes, extrudeOptions);
|
|
1648
|
+
if (!buffers) return new THREE.ExtrudeGeometry(shapes, extrudeOptions);
|
|
1649
|
+
const geometry = toGeometry(THREE, buffers);
|
|
1650
|
+
geometry.parameters = { shapes, options: extrudeOptions ?? {} };
|
|
1651
|
+
return geometry;
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
const namespace = { ...THREE };
|
|
1655
|
+
for (const type of SHAPE_GEOMETRY_TYPES) {
|
|
1656
|
+
const make2 = constructors[type];
|
|
1657
|
+
const Constructor = function(...args) {
|
|
1658
|
+
return make2(...args);
|
|
1659
|
+
};
|
|
1660
|
+
Constructor.prototype = THREE[type].prototype;
|
|
1661
|
+
Object.defineProperty(Constructor, "name", { value: type });
|
|
1662
|
+
namespace[type] = Constructor;
|
|
1663
|
+
}
|
|
1664
|
+
const result = namespace;
|
|
1665
|
+
byKey.set(key2, result);
|
|
1666
|
+
return result;
|
|
1667
|
+
}
|
|
1668
|
+
var isVisible = (object2) => {
|
|
1669
|
+
for (let node = object2; node; node = node.parent) if (!node.visible) return false;
|
|
1670
|
+
return true;
|
|
1671
|
+
};
|
|
1672
|
+
var plain = (attribute) => attribute !== void 0 && !attribute.isInterleavedBufferAttribute && attribute.array instanceof Float32Array && !attribute.normalized;
|
|
1673
|
+
function piece(geometry, matrix) {
|
|
1674
|
+
const position = geometry.getAttribute("position");
|
|
1675
|
+
const normal = geometry.getAttribute("normal");
|
|
1676
|
+
const uv = geometry.getAttribute("uv");
|
|
1677
|
+
const ok = plain(position) && (normal === void 0 || plain(normal)) && (uv === void 0 || plain(uv)) && position.itemSize === 3 && (uv === void 0 || uv.itemSize === 2);
|
|
1678
|
+
if (ok) {
|
|
1679
|
+
return { positions: position.array, ...normal ? { normals: normal.array } : {}, ...uv ? { uvs: uv.array } : {}, indices: geometry.index ? geometry.index.array : null, matrix: matrix.elements };
|
|
1680
|
+
}
|
|
1681
|
+
const flat = geometry.index ? geometry.toNonIndexed() : geometry;
|
|
1682
|
+
const read = (name, size) => {
|
|
1683
|
+
const attribute = flat.getAttribute(name);
|
|
1684
|
+
if (!attribute) return void 0;
|
|
1685
|
+
const out = new Float32Array(attribute.count * size);
|
|
1686
|
+
for (let i = 0; i < attribute.count; i++) for (let c = 0; c < size; c++) out[i * size + c] = c === 0 ? attribute.getX(i) : c === 1 ? attribute.getY(i) : attribute.getZ(i);
|
|
1687
|
+
return out;
|
|
1688
|
+
};
|
|
1689
|
+
const positions = read("position", 3);
|
|
1690
|
+
const normals = read("normal", 3);
|
|
1691
|
+
const uvs = read("uv", 2);
|
|
1692
|
+
if (flat !== geometry) flat.dispose();
|
|
1693
|
+
return { positions, ...normals ? { normals } : {}, ...uvs ? { uvs } : {}, indices: null, matrix: matrix.elements };
|
|
1694
|
+
}
|
|
1695
|
+
function mergeByMaterial(THREE, root, space) {
|
|
1696
|
+
const toSpace = space.matrixWorld.clone().invert();
|
|
1697
|
+
const byMaterial = /* @__PURE__ */ new Map();
|
|
1698
|
+
root.traverse((object2) => {
|
|
1699
|
+
const mesh2 = object2;
|
|
1700
|
+
if (!mesh2.isMesh || Array.isArray(mesh2.material) || !isVisible(mesh2)) return;
|
|
1701
|
+
const list2 = byMaterial.get(mesh2.material) ?? [];
|
|
1702
|
+
list2.push(piece(mesh2.geometry, new THREE.Matrix4().multiplyMatrices(toSpace, mesh2.matrixWorld)));
|
|
1703
|
+
byMaterial.set(mesh2.material, list2);
|
|
1704
|
+
});
|
|
1705
|
+
return [...byMaterial].map(([material, pieces]) => {
|
|
1706
|
+
const merged = mergeTransformed(pieces);
|
|
1707
|
+
const geometry = new THREE.BufferGeometry();
|
|
1708
|
+
geometry.setAttribute("position", new THREE.BufferAttribute(merged.positions, 3));
|
|
1709
|
+
geometry.setAttribute("normal", new THREE.BufferAttribute(merged.normals, 3));
|
|
1710
|
+
geometry.setAttribute("uv", new THREE.BufferAttribute(merged.uvs, 2));
|
|
1711
|
+
const mesh2 = new THREE.Mesh(geometry, material);
|
|
1712
|
+
mesh2.castShadow = false;
|
|
1713
|
+
mesh2.receiveShadow = true;
|
|
1714
|
+
return mesh2;
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
|
|
75
1718
|
// src/kit.ts
|
|
76
1719
|
var WEAR_TAGS = ["metal", "wood", "cloth", "plastic", "paper", "food", "glass"];
|
|
77
1720
|
var channelsOf = (hex2) => [(hex2 >> 16 & 255) / 255, (hex2 >> 8 & 255) / 255, (hex2 & 255) / 255];
|
|
78
|
-
function createItemKit(
|
|
1721
|
+
function createItemKit(three) {
|
|
1722
|
+
const T = shapeGeometries(three);
|
|
79
1723
|
const materials = [];
|
|
80
|
-
const M = (
|
|
81
|
-
const material = new
|
|
82
|
-
const base = new
|
|
83
|
-
const data = { base, baseRgb: channelsOf(
|
|
1724
|
+
const M = (color2, tag, options = {}) => {
|
|
1725
|
+
const material = new T.MeshStandardMaterial(Object.assign({ color: color2, roughness: 0.78, metalness: 0 }, options));
|
|
1726
|
+
const base = new T.Color(color2);
|
|
1727
|
+
const data = { base, baseRgb: channelsOf(color2), tag, rough: material.roughness };
|
|
84
1728
|
material.userData = data;
|
|
85
1729
|
materials.push(material);
|
|
86
1730
|
return material;
|
|
87
1731
|
};
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (scale)
|
|
93
|
-
return
|
|
1732
|
+
const mesh2 = (geometry, material, position = [0, 0, 0], rotation = [0, 0, 0], scale) => {
|
|
1733
|
+
const object2 = new T.Mesh(geometry, material);
|
|
1734
|
+
object2.position.set(...position);
|
|
1735
|
+
object2.rotation.set(...rotation);
|
|
1736
|
+
if (scale) object2.scale.set(...scale);
|
|
1737
|
+
return object2;
|
|
94
1738
|
};
|
|
95
1739
|
return {
|
|
96
|
-
T
|
|
1740
|
+
T,
|
|
97
1741
|
materials,
|
|
98
1742
|
M,
|
|
99
|
-
mesh,
|
|
100
|
-
cyl: (radiusTop, radiusBottom, height, segments = 14) => new
|
|
101
|
-
bx: (width, height, depth) => new
|
|
102
|
-
lathe: (points, segments = 16) => new
|
|
103
|
-
torus: (radius, tube2, arc = Math.PI * 2) => new
|
|
1743
|
+
mesh: mesh2,
|
|
1744
|
+
cyl: (radiusTop, radiusBottom, height, segments = 14) => new T.CylinderGeometry(radiusTop, radiusBottom, height, segments),
|
|
1745
|
+
bx: (width, height, depth) => new T.BoxGeometry(width, height, depth),
|
|
1746
|
+
lathe: (points, segments = 16) => new T.LatheGeometry(points.map(([x, y]) => new T.Vector2(x, y)), segments),
|
|
1747
|
+
torus: (radius, tube2, arc = Math.PI * 2) => new T.TorusGeometry(radius, tube2, 8, 18, arc),
|
|
104
1748
|
extrude: (points, depth, bevel = 0.015) => {
|
|
105
|
-
const shape = new
|
|
1749
|
+
const shape = new T.Shape();
|
|
106
1750
|
points.forEach(([x, y], index) => index ? shape.lineTo(x, y) : shape.moveTo(x, y));
|
|
107
|
-
return new
|
|
1751
|
+
return new T.ExtrudeGeometry(shape, { depth, bevelEnabled: true, bevelThickness: bevel, bevelSize: bevel, bevelSegments: 2 });
|
|
108
1752
|
},
|
|
109
1753
|
G: (...children) => {
|
|
110
|
-
const group = new
|
|
1754
|
+
const group = new T.Group();
|
|
111
1755
|
children.forEach((child) => group.add(child));
|
|
112
1756
|
return group;
|
|
113
1757
|
},
|
|
114
|
-
metal: (
|
|
115
|
-
wood: (
|
|
116
|
-
cloth: (
|
|
117
|
-
plastic: (
|
|
118
|
-
paper: (
|
|
119
|
-
food: (
|
|
120
|
-
glass: (
|
|
1758
|
+
metal: (color2) => M(color2, "metal", { metalness: 0.55, roughness: 0.45 }),
|
|
1759
|
+
wood: (color2) => M(color2, "wood"),
|
|
1760
|
+
cloth: (color2) => M(color2, "cloth", { roughness: 0.95 }),
|
|
1761
|
+
plastic: (color2) => M(color2, "plastic", { roughness: 0.6 }),
|
|
1762
|
+
paper: (color2) => M(color2, "paper", { roughness: 0.9 }),
|
|
1763
|
+
food: (color2) => M(color2, "food", { roughness: 0.85 }),
|
|
1764
|
+
glass: (color2, opacity) => M(color2, "glass", { roughness: 0.15, metalness: 0.1, transparent: true, opacity })
|
|
121
1765
|
};
|
|
122
1766
|
}
|
|
123
1767
|
|
|
@@ -131,10 +1775,10 @@ var GameItemsThree = (() => {
|
|
|
131
1775
|
};
|
|
132
1776
|
function wearableMaterials(root) {
|
|
133
1777
|
const found = /* @__PURE__ */ new Set();
|
|
134
|
-
root.traverse((
|
|
135
|
-
const
|
|
136
|
-
if (!
|
|
137
|
-
for (const material of Array.isArray(
|
|
1778
|
+
root.traverse((object2) => {
|
|
1779
|
+
const mesh2 = object2;
|
|
1780
|
+
if (!mesh2.isMesh) return;
|
|
1781
|
+
for (const material of Array.isArray(mesh2.material) ? mesh2.material : [mesh2.material]) if (dataOf(material)) found.add(material);
|
|
138
1782
|
});
|
|
139
1783
|
return [...found];
|
|
140
1784
|
}
|
|
@@ -185,8 +1829,8 @@ var GameItemsThree = (() => {
|
|
|
185
1829
|
];
|
|
186
1830
|
var DEFAULT_COLOR = 9080724;
|
|
187
1831
|
var PI = Math.PI;
|
|
188
|
-
function shade(
|
|
189
|
-
const channel = (shift) => Math.max(0, Math.min(255, Math.round((
|
|
1832
|
+
function shade(color2, factor) {
|
|
1833
|
+
const channel = (shift) => Math.max(0, Math.min(255, Math.round((color2 >> shift & 255) * factor)));
|
|
190
1834
|
return channel(16) << 16 | channel(8) << 8 | channel(0);
|
|
191
1835
|
}
|
|
192
1836
|
var seg = (c, n) => Math.max(5, Math.round(n * c.detail));
|
|
@@ -230,7 +1874,7 @@ var GameItemsThree = (() => {
|
|
|
230
1874
|
const { k, w, h, d } = c;
|
|
231
1875
|
return k.G(k.mesh(k.bx(w, h * 0.88, d), k.paper(c.color), [0, -h * 0.06, 0]), k.mesh(k.bx(w * 1, h * 0.12, d * 0.5), k.paper(shade(c.color, 0.85)), [0, h * 0.44, 0]), k.mesh(k.bx(w * 0.7, h * 0.3, d * 1), k.paper(shade(c.color, 1.2)), [0, 0, 0]));
|
|
232
1876
|
};
|
|
233
|
-
var
|
|
1877
|
+
var box2 = (c) => {
|
|
234
1878
|
const { k, w, h, d } = c;
|
|
235
1879
|
return k.G(k.mesh(k.bx(w, h, d), k.paper(c.color)), k.mesh(k.bx(w, h * 0.12, d), k.paper(shade(c.color, 0.8)), [0, h * 0.44, 0]), k.mesh(k.bx(w * 0.62, h * 0.4, d), k.paper(shade(c.color, 1.25)), [0, -h * 0.02, 0]));
|
|
236
1880
|
};
|
|
@@ -246,8 +1890,8 @@ var GameItemsThree = (() => {
|
|
|
246
1890
|
};
|
|
247
1891
|
var fruit = (c) => {
|
|
248
1892
|
const { k, w, h, d } = c;
|
|
249
|
-
const
|
|
250
|
-
return k.G(k.mesh(
|
|
1893
|
+
const sphere2 = new k.T.SphereGeometry(0.5, seg(c, 12), seg(c, 8));
|
|
1894
|
+
return k.G(k.mesh(sphere2, k.food(c.color), [0, -h * 0.04, 0], [0, 0, 0], [w, h * 0.92, d]), k.mesh(k.cyl(h * 0.02, h * 0.02, h * 0.1, 6), k.wood(5913122), [0, h * 0.45, 0]));
|
|
251
1895
|
};
|
|
252
1896
|
var dish = (c) => {
|
|
253
1897
|
const { k, w, h, d } = c;
|
|
@@ -329,9 +1973,9 @@ var GameItemsThree = (() => {
|
|
|
329
1973
|
var key = alongLong((c, L, a, b) => {
|
|
330
1974
|
const { k } = c;
|
|
331
1975
|
const metal = k.metal(12095802);
|
|
332
|
-
const
|
|
333
|
-
const tube2 = Math.min(b * 0.4,
|
|
334
|
-
return k.G(k.mesh(new c.k.T.TorusGeometry(
|
|
1976
|
+
const ring2 = a * 0.5;
|
|
1977
|
+
const tube2 = Math.min(b * 0.4, ring2 * 0.2);
|
|
1978
|
+
return k.G(k.mesh(new c.k.T.TorusGeometry(ring2 * 0.8, tube2, 5, seg(c, 10)), k.metal(10132896), [-L / 2 + ring2 * 0.8 + tube2, 0, 0]), k.mesh(k.bx(L * 0.62, a * 0.28, b), metal, [L * 0.12, 0, 0]), k.mesh(k.bx(L * 0.08, a * 0.22, b), metal, [L * 0.36, -a * 0.2, 0]), k.mesh(k.bx(L * 0.06, a * 0.22, b), metal, [L * 0.2, -a * 0.2, 0]));
|
|
335
1979
|
});
|
|
336
1980
|
var battery = alongLong((c, L, a, b) => {
|
|
337
1981
|
const { k } = c;
|
|
@@ -351,7 +1995,7 @@ var GameItemsThree = (() => {
|
|
|
351
1995
|
var DRAWERS = {
|
|
352
1996
|
can,
|
|
353
1997
|
bag,
|
|
354
|
-
box,
|
|
1998
|
+
box: box2,
|
|
355
1999
|
bottle,
|
|
356
2000
|
tool,
|
|
357
2001
|
roll,
|
|
@@ -654,60 +2298,60 @@ var GameItemsThree = (() => {
|
|
|
654
2298
|
];
|
|
655
2299
|
|
|
656
2300
|
// src/models/canned-beans.ts
|
|
657
|
-
var cannedBeans = ({ mesh, cyl, torus, G, metal, paper: paper2, food }) => {
|
|
2301
|
+
var cannedBeans = ({ mesh: mesh2, cyl, torus: torus2, G, metal, paper: paper2, food }) => {
|
|
658
2302
|
const m = metal(9277590);
|
|
659
|
-
return G(
|
|
2303
|
+
return G(mesh2(cyl(0.32, 0.32, 0.52), m), mesh2(cyl(0.326, 0.326, 0.34, 14), food(10172964)), mesh2(cyl(0.33, 0.33, 0.06), paper2(14861162), [0, 0.02, 0]), mesh2(torus2(0.31, 0.025), m, [0, 0.26, 0], [Math.PI / 2, 0, 0]), mesh2(torus2(0.31, 0.025), m, [0, -0.26, 0], [Math.PI / 2, 0, 0]));
|
|
660
2304
|
};
|
|
661
2305
|
|
|
662
2306
|
// src/models/water-bottle.ts
|
|
663
|
-
var waterBottle = ({ mesh, cyl, lathe, G, plastic, paper: paper2, glass }) => G(
|
|
2307
|
+
var waterBottle = ({ mesh: mesh2, cyl, lathe: lathe2, G, plastic, paper: paper2, glass }) => G(mesh2(lathe2([[0, -0.6], [0.2, -0.6], [0.22, -0.5], [0.22, 0.2], [0.19, 0.32], [0.09, 0.45], [0.08, 0.55], [0, 0.55]]), glass(9421788, 0.55)), mesh2(cyl(0.085, 0.085, 0.1, 12), plastic(2907530), [0, 0.6, 0]), mesh2(cyl(0.225, 0.225, 0.22, 16), paper2(15330543), [0, -0.15, 0]), mesh2(cyl(0.226, 0.226, 0.05, 16), plastic(3831976), [0, -0.12, 0]));
|
|
664
2308
|
|
|
665
2309
|
// src/models/rice.ts
|
|
666
|
-
var rice = ({ mesh, bx, G, paper: paper2, food }) => G(
|
|
2310
|
+
var rice = ({ mesh: mesh2, bx, G, paper: paper2, food }) => G(mesh2(bx(0.7, 0.95, 0.28), paper2(15129792)), mesh2(bx(0.72, 0.12, 0.1), paper2(14010792), [0, 0.52, 0]), mesh2(bx(0.5, 0.3, 0.02), food(11883039), [0, 0.05, 0.15]), mesh2(bx(0.3, 0.1, 0.02), paper2(4160069), [0, -0.25, 0.15]));
|
|
667
2311
|
|
|
668
2312
|
// src/models/military-ration.ts
|
|
669
|
-
var militaryRation = ({ mesh, bx, G, plastic, paper: paper2 }) => G(
|
|
2313
|
+
var militaryRation = ({ mesh: mesh2, bx, G, plastic, paper: paper2 }) => G(mesh2(bx(0.75, 1, 0.22), plastic(5923142)), mesh2(bx(0.77, 0.1, 0.23), plastic(4672823), [0, 0.48, 0]), mesh2(bx(0.5, 0.14, 0.01), paper2(2237727), [0, 0.18, 0.115]), mesh2(bx(0.36, 0.06, 0.01), paper2(2237727), [0, -0.02, 0.115]));
|
|
670
2314
|
|
|
671
2315
|
// src/models/cachaca.ts
|
|
672
|
-
var cachaca = ({ mesh, cyl, lathe, G, wood, paper: paper2, food, glass }) => G(
|
|
2316
|
+
var cachaca = ({ mesh: mesh2, cyl, lathe: lathe2, G, wood, paper: paper2, food, glass }) => G(mesh2(lathe2([[0, -0.6], [0.25, -0.6], [0.27, -0.52], [0.27, 0.1], [0.2, 0.25], [0.09, 0.35], [0.09, 0.58], [0, 0.58]]), glass(12749354, 0.78)), mesh2(cyl(0.08, 0.07, 0.14, 10), wood(9071172), [0, 0.64, 0]), mesh2(cyl(0.275, 0.275, 0.34, 16), paper2(15327692), [0, -0.25, 0]), mesh2(cyl(0.276, 0.276, 0.06, 16), food(8007455), [0, -0.15, 0]));
|
|
673
2317
|
|
|
674
2318
|
// src/models/first-aid-kit.ts
|
|
675
|
-
var firstAidKit = ({ mesh, bx, torus, G, plastic }) => {
|
|
2319
|
+
var firstAidKit = ({ mesh: mesh2, bx, torus: torus2, G, plastic }) => {
|
|
676
2320
|
const r = plastic(11680300);
|
|
677
|
-
return G(
|
|
2321
|
+
return G(mesh2(bx(1.05, 0.72, 0.38), plastic(15131608)), mesh2(bx(1.07, 0.06, 0.4), plastic(12433578), [0, 0, 0]), mesh2(bx(0.36, 0.1, 0.02), r, [0, 0.1, 0.2]), mesh2(bx(0.1, 0.36, 0.02), r, [0, 0.1, 0.2]), mesh2(torus2(0.16, 0.035, Math.PI), plastic(5591884), [0, 0.36, 0]));
|
|
678
2322
|
};
|
|
679
2323
|
|
|
680
2324
|
// src/models/bandage.ts
|
|
681
|
-
var bandage = ({ mesh, cyl, bx, G, cloth: cloth2 }) => {
|
|
2325
|
+
var bandage = ({ mesh: mesh2, cyl, bx, G, cloth: cloth2 }) => {
|
|
682
2326
|
const c = cloth2(15525330);
|
|
683
|
-
return G(
|
|
2327
|
+
return G(mesh2(cyl(0.34, 0.34, 0.38, 18), c, [0, 0, 0], [Math.PI / 2, 0, 0]), mesh2(cyl(0.1, 0.1, 0.4, 12), cloth2(9078135), [0, 0, 0], [Math.PI / 2, 0, 0]), mesh2(bx(0.36, 0.02, 0.36), c, [0.2, -0.33, 0.05], [0, 0, -0.25]), mesh2(bx(0.3, 0.02, 0.36), c, [0.5, -0.4, 0.05], [0, 0, -0.05]));
|
|
684
2328
|
};
|
|
685
2329
|
|
|
686
2330
|
// src/models/amoxicillin.ts
|
|
687
|
-
var amoxicillin = ({ T
|
|
2331
|
+
var amoxicillin = ({ T, mesh: mesh2, bx, G, metal, plastic, paper: paper2 }) => G(mesh2(bx(0.8, 0.42, 0.24), paper2(15789798)), mesh2(bx(0.81, 0.1, 0.25), plastic(5141127), [0, 0.1, 0]), mesh2(bx(0.6, 0.04, 0.3), metal(12172736), [0.15, -0.24, 0.25], [0, 0.3, 0]), ...[0, 1, 2, 3].map((k) => mesh2(new T.SphereGeometry(0.05, 10, 8), plastic(14263361), [-0.05 + k * 0.14, -0.21, 0.3], [0, 0, 0], [1, 0.6, 1])));
|
|
688
2332
|
|
|
689
2333
|
// src/models/crowbar.ts
|
|
690
|
-
var crowbar = ({ T
|
|
691
|
-
const c = new
|
|
692
|
-
return G(
|
|
2334
|
+
var crowbar = ({ T, mesh: mesh2, cyl, G, metal }) => {
|
|
2335
|
+
const c = new T.CatmullRomCurve3([[0, -0.8, 0], [0, 0.45, 0], [0.02, 0.62, 0], [0.12, 0.72, 0], [0.26, 0.7, 0], [0.32, 0.6, 0]].map((p) => new T.Vector3(...p)));
|
|
2336
|
+
return G(mesh2(new T.TubeGeometry(c, 30, 0.055, 8), metal(10168863)), mesh2(cyl(0.02, 0.055, 0.14, 8), metal(3816510), [0, -0.86, 0]));
|
|
693
2337
|
};
|
|
694
2338
|
|
|
695
2339
|
// src/models/hammer.ts
|
|
696
|
-
var hammer = ({ T
|
|
2340
|
+
var hammer = ({ T, mesh: mesh2, cyl, bx, G, metal, wood, plastic }) => G(mesh2(cyl(0.05, 0.065, 1.1, 10), wood(9069628), [0, -0.15, 0]), mesh2(cyl(0.07, 0.07, 0.3, 10), plastic(2237727), [0, -0.6, 0]), mesh2(bx(0.28, 0.15, 0.15), metal(5593437), [0.05, 0.45, 0]), mesh2(cyl(0.08, 0.08, 0.1, 12), metal(5593437), [0.22, 0.45, 0], [0, 0, Math.PI / 2]), mesh2(new T.ConeGeometry(0.06, 0.3, 6), metal(5593437), [-0.22, 0.5, 0.035], [0, 0, 1.9]), mesh2(new T.ConeGeometry(0.06, 0.3, 6), metal(5593437), [-0.22, 0.5, -0.035], [0, 0, 1.9]));
|
|
697
2341
|
|
|
698
2342
|
// src/models/machete.ts
|
|
699
|
-
var machete = ({ mesh, cyl, bx, extrude, G, metal, wood }) => G(
|
|
2343
|
+
var machete = ({ mesh: mesh2, cyl, bx, extrude: extrude2, G, metal, wood }) => G(mesh2(extrude2([[0, 0], [1.25, 0.05], [1.4, 0.14], [1.3, 0.26], [0, 0.2]], 0.03), metal(11120048), [-0.55, 0, 0]), mesh2(bx(0.45, 0.2, 0.1), wood(3877408), [-0.78, 0.1, 0.015]), ...[-0.9, -0.68].map((x) => mesh2(cyl(0.025, 0.025, 0.12, 8), metal(12095802), [x, 0.1, 0.015], [Math.PI / 2, 0, 0])));
|
|
700
2344
|
|
|
701
2345
|
// src/models/axe.ts
|
|
702
|
-
var axe = ({ M, mesh, cyl, bx, extrude, G, metal, wood }) => G(
|
|
2346
|
+
var axe = ({ M, mesh: mesh2, cyl, bx, extrude: extrude2, G, metal, wood }) => G(mesh2(cyl(0.05, 0.06, 1.5, 10), wood(10122312), [0, -0.1, 0]), mesh2(extrude2([[0, 0], [0.42, -0.16], [0.5, 0.05], [0.48, 0.3], [0.4, 0.42], [0, 0.22]], 0.07), metal(7106677), [0.02, 0.38, -0.05]), mesh2(bx(0.12, 0.26, 0.14), metal(4869456), [0, 0.5, 0]), mesh2(bx(0.1, 0.2, 0.08), M(10168863, "plastic"), [0, 0.55, 0]));
|
|
703
2347
|
|
|
704
2348
|
// src/models/nail-bat.ts
|
|
705
|
-
var nailBat = ({ mesh, cyl, lathe, G, metal, wood }) => {
|
|
706
|
-
const g = G(
|
|
2349
|
+
var nailBat = ({ mesh: mesh2, cyl, lathe: lathe2, G, metal, wood }) => {
|
|
2350
|
+
const g = G(mesh2(lathe2([[0, -0.85], [0.05, -0.85], [0.05, -0.8], [0.035, -0.75], [0.04, -0.2], [0.09, 0.3], [0.11, 0.7], [0.09, 0.82], [0, 0.84]], 14), wood(11569754)));
|
|
707
2351
|
const nm = metal(8225158);
|
|
708
2352
|
for (let k = 0; k < 9; k++) {
|
|
709
2353
|
const a = k * 2.4, y = 0.25 + k % 5 * 0.12;
|
|
710
|
-
const n =
|
|
2354
|
+
const n = mesh2(cyl(0.012, 0.012, 0.2, 6), nm, [Math.cos(a) * 0.12, y, Math.sin(a) * 0.12], [0, 0, 0]);
|
|
711
2355
|
n.lookAt(Math.cos(a) * 2, y, Math.sin(a) * 2);
|
|
712
2356
|
n.rotateX(Math.PI / 2);
|
|
713
2357
|
g.add(n);
|
|
@@ -716,56 +2360,56 @@ var GameItemsThree = (() => {
|
|
|
716
2360
|
};
|
|
717
2361
|
|
|
718
2362
|
// src/models/hiking-backpack-40l.ts
|
|
719
|
-
var hikingBackpack40L = ({ T
|
|
2363
|
+
var hikingBackpack40L = ({ T, mesh: mesh2, bx, G, cloth: cloth2, plastic }) => {
|
|
720
2364
|
const c = cloth2(5204794), d = cloth2(3557162);
|
|
721
|
-
return G(
|
|
2365
|
+
return G(mesh2(bx(0.78, 0.9, 0.42), c), mesh2(new T.SphereGeometry(0.4, 14, 8, 0, Math.PI * 2, 0, Math.PI / 2), c, [0, 0.44, 0], [0, 0, 0], [0.98, 0.45, 0.53]), mesh2(bx(0.56, 0.4, 0.16), d, [0, -0.15, 0.27]), mesh2(bx(0.8, 0.12, 0.46), d, [0, 0.2, 0]), mesh2(bx(0.06, 0.9, 0.06), cloth2(2237727), [-0.22, 0, -0.24]), mesh2(bx(0.06, 0.9, 0.06), cloth2(2237727), [0.22, 0, -0.24]), mesh2(bx(0.1, 0.08, 0.04), plastic(14263361), [0, 0.2, 0.24]));
|
|
722
2366
|
};
|
|
723
2367
|
|
|
724
2368
|
// src/models/flashlight.ts
|
|
725
|
-
var flashlight = ({ M, mesh, cyl, bx, torus, G, metal, plastic }) => G(
|
|
2369
|
+
var flashlight = ({ M, mesh: mesh2, cyl, bx, torus: torus2, G, metal, plastic }) => G(mesh2(cyl(0.11, 0.11, 0.8, 14), metal(2763822), [0, -0.15, 0]), mesh2(cyl(0.19, 0.12, 0.28, 16), metal(3816768), [0, 0.37, 0]), mesh2(cyl(0.17, 0.17, 0.02, 16), M(16773568, "glass", { emissive: 16769162, emissiveIntensity: 0.9 }), [0, 0.52, 0]), mesh2(bx(0.06, 0.1, 0.05), plastic(11883039), [0, 0.05, 0.11]), ...[-0.4, -0.3, -0.2].map((y) => mesh2(torus2(0.112, 0.012), plastic(1776669), [0, y, 0], [Math.PI / 2, 0, 0])));
|
|
726
2370
|
|
|
727
2371
|
// src/models/portable-radio.ts
|
|
728
|
-
var portableRadio = ({ M, mesh, cyl, bx, torus, G, metal, plastic }) => {
|
|
729
|
-
const g = G(
|
|
730
|
-
const a =
|
|
2372
|
+
var portableRadio = ({ M, mesh: mesh2, cyl, bx, torus: torus2, G, metal, plastic }) => {
|
|
2373
|
+
const g = G(mesh2(bx(1.05, 0.62, 0.3), plastic(3816757)), mesh2(cyl(0.2, 0.2, 0.02, 18), plastic(1974043), [-0.24, -0.04, 0.16], [Math.PI / 2, 0, 0]), mesh2(bx(0.36, 0.14, 0.02), M(14263361, "glass", { emissive: 6965776, emissiveIntensity: 0.6 }), [0.26, 0.1, 0.16]), mesh2(cyl(0.06, 0.06, 0.06, 12), plastic(9276032), [0.18, -0.15, 0.17], [Math.PI / 2, 0, 0]), mesh2(cyl(0.06, 0.06, 0.06, 12), plastic(9276032), [0.36, -0.15, 0.17], [Math.PI / 2, 0, 0]), mesh2(torus2(0.24, 0.03, Math.PI), plastic(2237727), [0, 0.3, 0]));
|
|
2374
|
+
const a = mesh2(cyl(0.012, 0.02, 0.95, 6), metal(12172736), [0.4, 0.72, 0], [0, 0, -0.35]);
|
|
731
2375
|
g.add(a);
|
|
732
2376
|
return g;
|
|
733
2377
|
};
|
|
734
2378
|
|
|
735
2379
|
// src/models/house-key.ts
|
|
736
|
-
var houseKey = ({ mesh, bx, torus, extrude, G, metal, plastic }) => {
|
|
2380
|
+
var houseKey = ({ mesh: mesh2, bx, torus: torus2, extrude: extrude2, G, metal, plastic }) => {
|
|
737
2381
|
const b = metal(12095802);
|
|
738
|
-
return G(
|
|
2382
|
+
return G(mesh2(torus2(0.22, 0.04), metal(10132896), [-0.55, 0.1, 0]), mesh2(extrude2([[0, -0.2], [0.25, -0.22], [0.3, -0.1], [0.3, 0.1], [0.25, 0.22], [0, 0.2]], 0.05), b, [-0.38, 0.02, -0.025]), mesh2(extrude2([[0, 0], [0.75, 0], [0.75, -0.08], [0.66, -0.08], [0.66, -0.14], [0.56, -0.08], [0.46, -0.14], [0.4, -0.08], [0, -0.08]], 0.035), b, [-0.1, 0.06, -0.017]), mesh2(bx(0.24, 0.34, 0.03), plastic(11883039), [-0.72, -0.28, 0], [0, 0, 0.25]));
|
|
739
2383
|
};
|
|
740
2384
|
|
|
741
2385
|
// src/models/survivor-diary.ts
|
|
742
|
-
var survivorDiary = ({ mesh, bx, G, cloth: cloth2, paper: paper2 }) => G(
|
|
2386
|
+
var survivorDiary = ({ mesh: mesh2, bx, G, cloth: cloth2, paper: paper2 }) => G(mesh2(bx(0.78, 1.02, 0.05), paper2(7028522), [0, 0, 0.1]), mesh2(bx(0.78, 1.02, 0.05), paper2(7028522), [0, 0, -0.1]), mesh2(bx(0.74, 0.98, 0.16), paper2(15327692), [0.01, 0, 0]), mesh2(bx(0.06, 1.02, 0.25), paper2(5911330), [-0.38, 0, 0]), mesh2(bx(0.03, 1.04, 0.27), cloth2(2237727), [0.25, 0, 0]), mesh2(bx(0.18, 0.3, 2e-3), paper2(14010792), [0.05, 0.2, 0.126], [0, 0, 0.08]));
|
|
743
2387
|
|
|
744
2388
|
// src/models/motorcycle-helmet.ts
|
|
745
|
-
var motorcycleHelmet = ({ T
|
|
2389
|
+
var motorcycleHelmet = ({ T, M, mesh: mesh2, cyl, bx, G, plastic }) => G(mesh2(new T.SphereGeometry(0.55, 18, 12), plastic(2830138), [0, 0, 0], [0, 0, 0], [1, 0.95, 1.08]), mesh2(new T.SphereGeometry(0.56, 18, 10, -0.9, 1.8, 1.05, 0.75), M(1316636, "glass", { roughness: 0.15, metalness: 0.4 }), [0, 0.02, 0.02], [0, 0, 0], [1, 0.95, 1.08]), mesh2(bx(0.2, 0.12, 0.02), plastic(14710591), [0.42, 0.2, 0.22], [0, 0.95, 0]), mesh2(cyl(0.5, 0.55, 0.12, 18), plastic(1908776), [0, -0.5, 0]));
|
|
746
2390
|
|
|
747
2391
|
// src/models/lpg-cylinder-13kg.ts
|
|
748
|
-
var lpgCylinder13Kg = ({ mesh, cyl, bx, lathe, torus, G, metal }) => G(
|
|
2392
|
+
var lpgCylinder13Kg = ({ mesh: mesh2, cyl, bx, lathe: lathe2, torus: torus2, G, metal }) => G(mesh2(lathe2([[0, -0.6], [0.38, -0.6], [0.42, -0.55], [0.45, -0.3], [0.45, 0.15], [0.4, 0.32], [0.28, 0.42], [0.12, 0.46], [0, 0.46]], 18), metal(3497862)), mesh2(cyl(0.47, 0.47, 0.1, 18), metal(2705514), [0, -0.62, 0]), mesh2(torus2(0.24, 0.035), metal(2705514), [0, 0.58, 0], [Math.PI / 2, 0, 0]), mesh2(cyl(0.07, 0.07, 0.14, 10), metal(12095802), [0, 0.5, 0]), mesh2(bx(0.04, 0.2, 0.04), metal(2705514), [0.22, 0.5, 0]), mesh2(bx(0.04, 0.2, 0.04), metal(2705514), [-0.22, 0.5, 0]));
|
|
749
2393
|
|
|
750
2394
|
// src/models/fuel-jerrycan.ts
|
|
751
|
-
var fuelJerrycan = ({ mesh, cyl, bx, G, plastic }) => G(
|
|
2395
|
+
var fuelJerrycan = ({ mesh: mesh2, cyl, bx, G, plastic }) => G(mesh2(bx(0.85, 1, 0.42), plastic(10695210)), mesh2(bx(0.6, 0.1, 0.3), plastic(8267296), [0, 0.45, 0]), mesh2(bx(0.36, 0.2, 0.1), plastic(10695210), [-0.12, 0.62, 0]), mesh2(cyl(0.05, 0.07, 0.35, 10), plastic(14263361), [0.3, 0.66, 0], [0, 0, -0.6]), mesh2(bx(0.6, 0.5, 0.02), plastic(9054754), [0, -0.1, 0.22]));
|
|
752
2396
|
|
|
753
2397
|
// src/models/walkie-talkies.ts
|
|
754
|
-
var walkieTalkies = ({ M, mesh, cyl, bx, G, plastic }) => G(
|
|
2398
|
+
var walkieTalkies = ({ M, mesh: mesh2, cyl, bx, G, plastic }) => G(mesh2(bx(0.42, 0.9, 0.2), plastic(2764071)), mesh2(bx(0.34, 0.3, 0.02), plastic(1447956), [0, -0.12, 0.11]), mesh2(bx(0.24, 0.12, 0.02), M(10469258, "glass", { emissive: 3099170, emissiveIntensity: 0.7 }), [0, 0.22, 0.11]), mesh2(cyl(0.035, 0.045, 0.6, 8), plastic(1776666), [0.12, 0.72, 0]), mesh2(cyl(0.04, 0.04, 0.08, 10), plastic(11883039), [-0.12, 0.48, 0]), mesh2(bx(0.05, 0.2, 0.1), plastic(3816757), [-0.23, 0.05, 0]));
|
|
755
2399
|
|
|
756
2400
|
// src/models/batteries.ts
|
|
757
|
-
var batteries = ({ mesh, cyl, G, metal }) => {
|
|
2401
|
+
var batteries = ({ mesh: mesh2, cyl, G, metal }) => {
|
|
758
2402
|
const g = G();
|
|
759
|
-
[-0.2, 0.2].forEach((x, k) => g.add(
|
|
2403
|
+
[-0.2, 0.2].forEach((x, k) => g.add(mesh2(cyl(0.17, 0.17, 0.95, 16), metal(k ? 11883039 : 2763822), [x, 0, 0]), mesh2(cyl(0.172, 0.172, 0.3, 16), metal(13214247), [x, 0.33, 0]), mesh2(cyl(0.06, 0.06, 0.06, 10), metal(12172736), [x, 0.5, 0])));
|
|
760
2404
|
return g;
|
|
761
2405
|
};
|
|
762
2406
|
|
|
763
2407
|
// src/models/wooden-plank.ts
|
|
764
|
-
var woodenPlank = ({ mesh, cyl, bx, G, metal, wood }) => {
|
|
2408
|
+
var woodenPlank = ({ mesh: mesh2, cyl, bx, G, metal, wood }) => {
|
|
765
2409
|
const g = G();
|
|
766
|
-
[11043929, 9333829, 11833960].forEach((c, k) => g.add(
|
|
2410
|
+
[11043929, 9333829, 11833960].forEach((c, k) => g.add(mesh2(bx(1.5, 0.07, 0.26), wood(c), [0, -0.15 + k * 0.12, (k - 1) * 0.05], [0, (k - 1) * 0.12, 0])));
|
|
767
2411
|
const nm = metal(8225158);
|
|
768
|
-
[-0.5, -0.3, 0.4].forEach((x, k) => g.add(
|
|
2412
|
+
[-0.5, -0.3, 0.4].forEach((x, k) => g.add(mesh2(cyl(0.012, 0.012, 0.18, 6), nm, [x, 0.18 + k * 0.01, 0.2], [0, 0, (k - 1) * 0.3])));
|
|
769
2413
|
return g;
|
|
770
2414
|
};
|
|
771
2415
|
|
|
@@ -819,15 +2463,15 @@ var GameItemsThree = (() => {
|
|
|
819
2463
|
var listItemModels = () => [...entries.keys()];
|
|
820
2464
|
|
|
821
2465
|
// src/build-item.ts
|
|
822
|
-
function restOnBase(
|
|
823
|
-
const
|
|
824
|
-
const centre =
|
|
825
|
-
inner.position.set(-centre.x, -
|
|
2466
|
+
function restOnBase(T, inner) {
|
|
2467
|
+
const box3 = new T.Box3().setFromObject(inner);
|
|
2468
|
+
const centre = box3.getCenter(new T.Vector3());
|
|
2469
|
+
inner.position.set(-centre.x, -box3.min.y, -centre.z);
|
|
826
2470
|
}
|
|
827
|
-
function buildItem(
|
|
828
|
-
const kit = options.kit ?? createItemKit(
|
|
2471
|
+
function buildItem(T, item, options = {}) {
|
|
2472
|
+
const kit = options.kit ?? createItemKit(T);
|
|
829
2473
|
const first = kit.materials.length;
|
|
830
|
-
const root = new
|
|
2474
|
+
const root = new T.Group();
|
|
831
2475
|
root.name = item.id;
|
|
832
2476
|
const entry = item.model === void 0 ? void 0 : itemModelEntry(item.model);
|
|
833
2477
|
const builder = item.model === void 0 ? void 0 : itemModelBuilder(item.model);
|
|
@@ -839,13 +2483,13 @@ var GameItemsThree = (() => {
|
|
|
839
2483
|
inner.name = entry.teamId;
|
|
840
2484
|
root.scale.setScalar(entry.scale);
|
|
841
2485
|
root.add(inner);
|
|
842
|
-
restOnBase(
|
|
2486
|
+
restOnBase(T, inner);
|
|
843
2487
|
} else {
|
|
844
2488
|
shape = shapeOf(item);
|
|
845
2489
|
const inner = drawShape(kit, shape, item.size, { ...item.color === void 0 ? {} : { color: item.color }, ...options.detail === void 0 ? {} : { detail: options.detail } });
|
|
846
2490
|
inner.name = shape;
|
|
847
2491
|
root.add(inner);
|
|
848
|
-
restOnBase(
|
|
2492
|
+
restOnBase(T, inner);
|
|
849
2493
|
}
|
|
850
2494
|
const materials = kit.materials.slice(first);
|
|
851
2495
|
if (options.wear) setWear(materials, options.wear);
|
|
@@ -853,126 +2497,14 @@ var GameItemsThree = (() => {
|
|
|
853
2497
|
return { root, kind, ...shape ? { shape } : {}, size: item.size, materials };
|
|
854
2498
|
}
|
|
855
2499
|
|
|
856
|
-
// ../game-props3d/dist/index.js
|
|
857
|
-
var T = (id, interior, w, d, h, y, solid, group) => ({ id, interior, w, d, h, y, solid, group });
|
|
858
|
-
var TYPE_DEFS = [
|
|
859
|
-
T("ceiling_light", true, 0.4, 0.4, 0.07, 0, false, "ceiling"),
|
|
860
|
-
T("pendant", true, 0.34, 0.34, 1, 0, false, "ceiling"),
|
|
861
|
-
T("track_spot", true, 1.2, 0.1, 0.2, 0, false, "ceiling"),
|
|
862
|
-
T("chandelier", true, 0.7, 0.7, 0.7, 0, false, "ceiling"),
|
|
863
|
-
T("wall_ac", true, 0.9, 0.2, 0.28, 2.15, false, "wall"),
|
|
864
|
-
T("picture_small", true, 0.35, 0.03, 0.45, 1.3, false, "wall"),
|
|
865
|
-
T("picture_large", true, 1, 0.04, 0.7, 1.2, false, "wall"),
|
|
866
|
-
T("mirror", true, 0.6, 0.03, 1.2, 0.9, false, "wall"),
|
|
867
|
-
T("curtain", true, 1.6, 0.12, 2.3, 0.1, false, "wall"),
|
|
868
|
-
T("blinds", true, 1.2, 0.08, 1.3, 1, false, "wall"),
|
|
869
|
-
T("flat_tv", true, 1.2, 0.06, 0.7, 1, false, "wall"),
|
|
870
|
-
T("floor_plant", true, 0.5, 0.5, 1.1, 0, true, "plants"),
|
|
871
|
-
T("table_plant", true, 0.2, 0.2, 0.3, 0, false, "plants"),
|
|
872
|
-
T("hanging_plant", true, 0.5, 0.5, 1, 0, false, "plants"),
|
|
873
|
-
T("tv_stand", true, 1.6, 0.42, 1.05, 0, true, "furniture"),
|
|
874
|
-
T("breakfast_bar", true, 2, 1.6, 0.95, 0, true, "furniture"),
|
|
875
|
-
T("sofa_l", true, 2.8, 1.7, 0.85, 0, true, "furniture"),
|
|
876
|
-
T("double_bed_modern", true, 1.6, 2.1, 1.2, 0, true, "furniture"),
|
|
877
|
-
T("home_office", true, 1.4, 0.75, 1.2, 0, true, "furniture"),
|
|
878
|
-
T("closet", true, 2.2, 0.6, 2.3, 0, true, "furniture"),
|
|
879
|
-
T("vanity", true, 0.6, 0.45, 1.5, 0, true, "furniture"),
|
|
880
|
-
T("ac_condenser", false, 0.8, 0.3, 0.55, 0.5, true, "yard"),
|
|
881
|
-
T("lawn", false, 4, 4, 0.02, 0, false, "floor"),
|
|
882
|
-
T("tile_floor", false, 4, 3, 0.03, 0, false, "floor"),
|
|
883
|
-
T("concrete", false, 4, 4, 0.03, 0, false, "floor"),
|
|
884
|
-
T("deck_floor", false, 4, 3, 0.04, 0, false, "floor"),
|
|
885
|
-
T("dirt", false, 4, 4, 0.02, 0, false, "floor"),
|
|
886
|
-
T("gourmet_counter", false, 4.2, 3, 2.9, 0, true, "yard"),
|
|
887
|
-
T("sauna", false, 2, 1.8, 2.1, 0, true, "yard"),
|
|
888
|
-
T("soaking_tub", false, 1.3, 1.3, 0.8, 0, true, "yard"),
|
|
889
|
-
T("pool", false, 4.5, 2.8, 0.1, 0, true, "yard"),
|
|
890
|
-
T("deck", false, 3.5, 3, 0.22, 0, true, "yard"),
|
|
891
|
-
T("sun_lounger", false, 0.62, 1.9, 0.5, 0, true, "yard"),
|
|
892
|
-
T("garden_bed", false, 2, 1, 0.9, 0, true, "yard"),
|
|
893
|
-
T("fruit_tree", false, 2.4, 2.4, 3.2, 0, true, "yard"),
|
|
894
|
-
T("palm_tree", false, 2, 2, 4.5, 0, true, "yard"),
|
|
895
|
-
T("pergola", false, 3.5, 3, 2.4, 0, true, "yard"),
|
|
896
|
-
T("slide", false, 0.8, 2.6, 1.5, 0, true, "yard"),
|
|
897
|
-
T("swing", false, 2.2, 1.7, 2.2, 0, true, "yard"),
|
|
898
|
-
T("bbq_simple", false, 0.9, 0.6, 1, 0, true, "yard"),
|
|
899
|
-
T("garage_car", false, 1.8, 4.2, 1.45, 0, true, "yard"),
|
|
900
|
-
T("window_boards", true, 1.2, 0.06, 1.15, 1, false, "house_state"),
|
|
901
|
-
T("barricade", true, 1.5, 0.7, 1.8, 0, true, "house_state"),
|
|
902
|
-
T("sandbags", false, 1.6, 0.5, 0.6, 0, true, "house_state"),
|
|
903
|
-
T("barbed_wire", false, 4, 0.2, 0.6, 0, false, "house_state"),
|
|
904
|
-
T("razor_wire", false, 4, 0.6, 0.6, 0, false, "house_state"),
|
|
905
|
-
T("water_bottle_crates", true, 0.9, 0.6, 0.65, 0, true, "house_state"),
|
|
906
|
-
T("canned_food", true, 0.4, 0.3, 0.3, 0, false, "house_state"),
|
|
907
|
-
T("water_jug", true, 0.3, 0.3, 0.5, 0, true, "house_state"),
|
|
908
|
-
T("floor_mattress", true, 0.9, 1.9, 0.3, 0, false, "house_state"),
|
|
909
|
-
T("lantern", true, 0.16, 0.16, 0.3, 0, false, "house_state"),
|
|
910
|
-
T("candles", true, 0.25, 0.25, 0.2, 0, false, "house_state"),
|
|
911
|
-
T("open_suitcases", true, 1.5, 0.7, 0.6, 0, false, "house_state"),
|
|
912
|
-
T("clothes_on_floor", true, 1.2, 1, 0.05, 0, false, "house_state"),
|
|
913
|
-
T("fallen_chair", true, 0.5, 0.5, 0.5, 0, false, "house_state"),
|
|
914
|
-
T("blood_stains", true, 1.2, 1.2, 0.01, 0, false, "house_state"),
|
|
915
|
-
T("open_door", true, 0.9, 0.15, 2.15, 0, false, "house_state")
|
|
916
|
-
];
|
|
917
|
-
var DEFS = Object.fromEntries(TYPE_DEFS.map((t) => [t.id, t]));
|
|
918
|
-
var ATTRIBUTES = ["position", "normal", "uv"];
|
|
919
|
-
var isVisible = (object) => {
|
|
920
|
-
for (let node = object; node; node = node.parent) if (!node.visible) return false;
|
|
921
|
-
return true;
|
|
922
|
-
};
|
|
923
|
-
var bake = (THREE, mesh, matrix) => {
|
|
924
|
-
const source = mesh.geometry.index ? mesh.geometry.toNonIndexed() : mesh.geometry.clone();
|
|
925
|
-
const baked = new THREE.BufferGeometry();
|
|
926
|
-
const count = source.getAttribute("position").count;
|
|
927
|
-
for (const name of ATTRIBUTES) {
|
|
928
|
-
const attribute = source.getAttribute(name);
|
|
929
|
-
baked.setAttribute(name, attribute ?? new THREE.BufferAttribute(new Float32Array(count * (name === "uv" ? 2 : 3)), name === "uv" ? 2 : 3));
|
|
930
|
-
}
|
|
931
|
-
source.dispose();
|
|
932
|
-
return baked.applyMatrix4(matrix);
|
|
933
|
-
};
|
|
934
|
-
var join = (THREE, geometries) => {
|
|
935
|
-
const merged = new THREE.BufferGeometry();
|
|
936
|
-
for (const name of ATTRIBUTES) {
|
|
937
|
-
const size = (geometries[0]?.getAttribute(name)).itemSize;
|
|
938
|
-
const total = geometries.reduce((sum, geometry) => sum + geometry.getAttribute(name).count, 0);
|
|
939
|
-
const array = new Float32Array(total * size);
|
|
940
|
-
let offset = 0;
|
|
941
|
-
for (const geometry of geometries) {
|
|
942
|
-
array.set(geometry.getAttribute(name).array, offset);
|
|
943
|
-
offset += geometry.getAttribute(name).count * size;
|
|
944
|
-
}
|
|
945
|
-
merged.setAttribute(name, new THREE.BufferAttribute(array, size));
|
|
946
|
-
}
|
|
947
|
-
return merged;
|
|
948
|
-
};
|
|
949
|
-
function mergeByMaterial(THREE, root, space) {
|
|
950
|
-
const toSpace = space.matrixWorld.clone().invert();
|
|
951
|
-
const byMaterial = /* @__PURE__ */ new Map();
|
|
952
|
-
root.traverse((object) => {
|
|
953
|
-
const mesh = object;
|
|
954
|
-
if (!mesh.isMesh || Array.isArray(mesh.material) || !isVisible(mesh)) return;
|
|
955
|
-
const list = byMaterial.get(mesh.material) ?? [];
|
|
956
|
-
list.push(bake(THREE, mesh, new THREE.Matrix4().multiplyMatrices(toSpace, mesh.matrixWorld)));
|
|
957
|
-
byMaterial.set(mesh.material, list);
|
|
958
|
-
});
|
|
959
|
-
return [...byMaterial].map(([material, geometries]) => {
|
|
960
|
-
const merged = new THREE.Mesh(join(THREE, geometries), material);
|
|
961
|
-
for (const geometry of geometries) geometry.dispose();
|
|
962
|
-
merged.castShadow = false;
|
|
963
|
-
merged.receiveShadow = true;
|
|
964
|
-
return merged;
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
|
|
968
2500
|
// src/merge.ts
|
|
969
|
-
function mergeItem(
|
|
2501
|
+
function mergeItem(T, model) {
|
|
970
2502
|
model.root.updateMatrixWorld(true);
|
|
971
|
-
const merged = new
|
|
2503
|
+
const merged = new T.Group();
|
|
972
2504
|
merged.name = model.root.name;
|
|
973
2505
|
merged.scale.copy(model.root.scale);
|
|
974
2506
|
merged.userData = { ...model.root.userData };
|
|
975
|
-
merged.add(...mergeByMaterial(
|
|
2507
|
+
merged.add(...mergeByMaterial(T, model.root, model.root));
|
|
976
2508
|
return { ...model, root: merged };
|
|
977
2509
|
}
|
|
978
2510
|
|
|
@@ -989,20 +2521,20 @@ var GameItemsThree = (() => {
|
|
|
989
2521
|
var cullDistanceOf = (size, budgets = ITEM_BUDGETS) => budgets[sizeClassOf(size, budgets)].cullDistance;
|
|
990
2522
|
function countTriangles(root) {
|
|
991
2523
|
let total = 0;
|
|
992
|
-
root.traverse((
|
|
993
|
-
const
|
|
994
|
-
if (!
|
|
995
|
-
const geometry =
|
|
2524
|
+
root.traverse((object2) => {
|
|
2525
|
+
const mesh2 = object2;
|
|
2526
|
+
if (!mesh2.isMesh || !mesh2.visible) return;
|
|
2527
|
+
const geometry = mesh2.geometry;
|
|
996
2528
|
total += geometry.index ? geometry.index.count / 3 : geometry.getAttribute("position").count / 3;
|
|
997
2529
|
});
|
|
998
2530
|
return Math.round(total);
|
|
999
2531
|
}
|
|
1000
2532
|
function countDrawCalls(root) {
|
|
1001
2533
|
let total = 0;
|
|
1002
|
-
root.traverse((
|
|
1003
|
-
const
|
|
1004
|
-
if (!
|
|
1005
|
-
total += Array.isArray(
|
|
2534
|
+
root.traverse((object2) => {
|
|
2535
|
+
const mesh2 = object2;
|
|
2536
|
+
if (!mesh2.isMesh || !mesh2.visible) return;
|
|
2537
|
+
total += Array.isArray(mesh2.material) ? Math.max(1, mesh2.geometry.groups.length) : 1;
|
|
1006
2538
|
});
|
|
1007
2539
|
return total;
|
|
1008
2540
|
}
|
|
@@ -1013,19 +2545,19 @@ var GameItemsThree = (() => {
|
|
|
1013
2545
|
}
|
|
1014
2546
|
|
|
1015
2547
|
// src/lod.ts
|
|
1016
|
-
function buildItemLod(
|
|
2548
|
+
function buildItemLod(T, item, options = {}) {
|
|
1017
2549
|
const budgets = options.budgets ?? ITEM_BUDGETS;
|
|
1018
2550
|
const cullDistance = cullDistanceOf(item.size, budgets);
|
|
1019
2551
|
const lod1Distance = options.lod1Distance ?? cullDistance / 3;
|
|
1020
|
-
const joined = (model) => options.merge === false ? model : mergeItem(
|
|
2552
|
+
const joined = (model) => options.merge === false ? model : mergeItem(T, model);
|
|
1021
2553
|
const wear = options.wear === void 0 ? {} : { wear: options.wear };
|
|
1022
|
-
const near = joined(buildItem(
|
|
1023
|
-
const far = joined(buildItem(
|
|
1024
|
-
const root = new
|
|
2554
|
+
const near = joined(buildItem(T, item, { ...wear, kit: createItemKit(T) }));
|
|
2555
|
+
const far = joined(buildItem(T, item, { ...wear, simple: true, detail: budgets.lod1Ratio, kit: createItemKit(T) }));
|
|
2556
|
+
const root = new T.LOD();
|
|
1025
2557
|
root.name = item.id;
|
|
1026
2558
|
root.addLevel(near.root, 0);
|
|
1027
2559
|
root.addLevel(far.root, lod1Distance);
|
|
1028
|
-
root.addLevel(new
|
|
2560
|
+
root.addLevel(new T.Group(), cullDistance);
|
|
1029
2561
|
root.userData.wear = options.wear ?? 0;
|
|
1030
2562
|
return { root, near, far, cullDistance, lod1Distance };
|
|
1031
2563
|
}
|
|
@@ -1042,7 +2574,7 @@ var GameItemsThree = (() => {
|
|
|
1042
2574
|
};
|
|
1043
2575
|
|
|
1044
2576
|
// src/thumbnails.ts
|
|
1045
|
-
var hex = (
|
|
2577
|
+
var hex = (color2) => `#${(color2 & 16777215).toString(16).padStart(6, "0")}`;
|
|
1046
2578
|
var DEFAULT_COLOR2 = 9080724;
|
|
1047
2579
|
var STEEL = "#9aa0a6";
|
|
1048
2580
|
var BRASS = "#b8913a";
|
|
@@ -1075,9 +2607,9 @@ var GameItemsThree = (() => {
|
|
|
1075
2607
|
plank: (c) => `<rect x="5" y="26" width="54" height="13" fill="${WOOD}"/><rect x="5" y="30" width="54" height="2" fill="${c === "#808080" ? "#6b4a2c" : c}" fill-opacity=".5"/><circle cx="12" cy="32" r="2" fill="#7d8186"/><circle cx="52" cy="32" r="2" fill="#7d8186"/>`,
|
|
1076
2608
|
device: (c) => `<rect x="15" y="7" width="34" height="50" rx="5" fill="${c}"/><rect x="20" y="13" width="24" height="18" rx="2" fill="#9fbf8a"/><circle cx="26" cy="43" r="4" fill="#b9bdc0"/><rect x="35" y="40" width="9" height="6" rx="1" fill="#b9bdc0"/>`
|
|
1077
2609
|
};
|
|
1078
|
-
function shapeThumbnailSvg(shape,
|
|
2610
|
+
function shapeThumbnailSvg(shape, color2 = DEFAULT_COLOR2) {
|
|
1079
2611
|
const art = ART[shape];
|
|
1080
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">${art(hex(
|
|
2612
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">${art(hex(color2), hex(shade(color2, 0.7)), hex(shade(color2, 1.3)))}</svg>`;
|
|
1081
2613
|
}
|
|
1082
2614
|
function itemThumbnail(item) {
|
|
1083
2615
|
if (item.model !== void 0 && hasItemModel(item.model)) return { render: true };
|
|
@@ -1091,23 +2623,23 @@ var GameItemsThree = (() => {
|
|
|
1091
2623
|
}
|
|
1092
2624
|
var FIT_MARGIN = 1.15;
|
|
1093
2625
|
var FIELD_OF_VIEW = 30;
|
|
1094
|
-
function composeThumbnailScene(
|
|
2626
|
+
function composeThumbnailScene(T, item, options = {}) {
|
|
1095
2627
|
const { yaw = -0.6, pitch = 0.45, distance = 1, wear = 0 } = options;
|
|
1096
|
-
const scene = new
|
|
1097
|
-
const model = buildItem(
|
|
2628
|
+
const scene = new T.Scene();
|
|
2629
|
+
const model = buildItem(T, item);
|
|
1098
2630
|
if (wear) setWear(model.root, wear);
|
|
1099
2631
|
scene.add(model.root);
|
|
1100
|
-
scene.add(new
|
|
1101
|
-
const sun = new
|
|
2632
|
+
scene.add(new T.HemisphereLight(14673646, 3814440, 0.85));
|
|
2633
|
+
const sun = new T.DirectionalLight(16769727, 1.1);
|
|
1102
2634
|
sun.position.set(2.5, 3.5, 2.5);
|
|
1103
2635
|
scene.add(sun);
|
|
1104
|
-
const rim = new
|
|
2636
|
+
const rim = new T.DirectionalLight(9417430, 0.45);
|
|
1105
2637
|
rim.position.set(-3, 1, -2.5);
|
|
1106
2638
|
scene.add(rim);
|
|
1107
|
-
const
|
|
1108
|
-
const centre =
|
|
1109
|
-
const radius =
|
|
1110
|
-
const camera = new
|
|
2639
|
+
const box3 = new T.Box3().setFromObject(model.root);
|
|
2640
|
+
const centre = box3.getCenter(new T.Vector3());
|
|
2641
|
+
const radius = box3.getSize(new T.Vector3()).length() / 2;
|
|
2642
|
+
const camera = new T.PerspectiveCamera(FIELD_OF_VIEW, 1, radius / 50, radius * 40);
|
|
1111
2643
|
const fit = radius * FIT_MARGIN / Math.sin(FIELD_OF_VIEW * Math.PI / 360);
|
|
1112
2644
|
const away = fit * distance;
|
|
1113
2645
|
camera.position.set(centre.x + away * Math.cos(pitch) * Math.sin(yaw), centre.y + away * Math.sin(pitch), centre.z + away * Math.cos(pitch) * Math.cos(yaw));
|
|
@@ -1115,8 +2647,8 @@ var GameItemsThree = (() => {
|
|
|
1115
2647
|
camera.updateMatrixWorld(true);
|
|
1116
2648
|
return { scene, camera };
|
|
1117
2649
|
}
|
|
1118
|
-
function renderItemThumbnail(
|
|
1119
|
-
const { scene, camera } = composeThumbnailScene(
|
|
2650
|
+
function renderItemThumbnail(T, renderer, item, options = {}) {
|
|
2651
|
+
const { scene, camera } = composeThumbnailScene(T, item, options);
|
|
1120
2652
|
const size = options.size ?? 128;
|
|
1121
2653
|
renderer.setSize(size, size);
|
|
1122
2654
|
renderer.setClearColor?.(0, 0);
|
|
@@ -1440,7 +2972,7 @@ var GameItemsThree = (() => {
|
|
|
1440
2972
|
};
|
|
1441
2973
|
var WEARING_DURABILITY = ["condition", "hits", "cuts"];
|
|
1442
2974
|
var hasCondition = (item) => item.protection !== void 0 || item.weapon !== void 0 || WEARING_DURABILITY.includes(item.durability?.kind ?? "");
|
|
1443
|
-
var between = (
|
|
2975
|
+
var between = (range2, random) => range2[0] + random() * (range2[1] - range2[0]);
|
|
1444
2976
|
var spawnAgeDays = (item, outbreakDays, random, catalog) => item.shelfLife === void 0 ? void 0 : outbreakDays + between(catalog.rules.spawn.ageShare, random) * item.shelfLife;
|
|
1445
2977
|
var isRetailStock = (query, catalog) => {
|
|
1446
2978
|
const { spawn } = catalog.rules;
|
|
@@ -1728,15 +3260,15 @@ var GameItemsThree = (() => {
|
|
|
1728
3260
|
name: fill(text.shelf, { category: categoryName(plan.category) }),
|
|
1729
3261
|
movable: false,
|
|
1730
3262
|
build: (THREE) => {
|
|
1731
|
-
const
|
|
1732
|
-
const group = new
|
|
1733
|
-
const wood = new
|
|
1734
|
-
const frame = new
|
|
1735
|
-
const top = new
|
|
3263
|
+
const T = THREE;
|
|
3264
|
+
const group = new T.Group();
|
|
3265
|
+
const wood = new T.MeshStandardMaterial({ color: 9071173, roughness: 0.85 });
|
|
3266
|
+
const frame = new T.MeshStandardMaterial({ color: 4869458, roughness: 0.7, metalness: 0.3 });
|
|
3267
|
+
const top = new T.Mesh(new T.BoxGeometry(plan.length, 0.04, plan.depth), wood);
|
|
1736
3268
|
top.position.y = SHELF_HEIGHT - 0.02;
|
|
1737
3269
|
group.add(top);
|
|
1738
3270
|
for (const sx of [-1, 1]) for (const sz of [-1, 1]) {
|
|
1739
|
-
const leg = new
|
|
3271
|
+
const leg = new T.Mesh(new T.BoxGeometry(0.05, SHELF_HEIGHT - 0.04, 0.05), frame);
|
|
1740
3272
|
leg.position.set(sx * (plan.length - 0.1) / 2, (SHELF_HEIGHT - 0.04) / 2, sz * (plan.depth - 0.1) / 2);
|
|
1741
3273
|
group.add(leg);
|
|
1742
3274
|
}
|
|
@@ -1753,9 +3285,9 @@ var GameItemsThree = (() => {
|
|
|
1753
3285
|
movable: true,
|
|
1754
3286
|
thumbnail: itemThumbnailSvg(drawable(def)),
|
|
1755
3287
|
build: (THREE) => {
|
|
1756
|
-
const
|
|
1757
|
-
latestTHREE =
|
|
1758
|
-
const model = buildItem(
|
|
3288
|
+
const T = THREE;
|
|
3289
|
+
latestTHREE = T;
|
|
3290
|
+
const model = buildItem(T, drawable(def), { wear: stageFor(def) });
|
|
1759
3291
|
register({ id: `${ITEM_PREFIX}${def.id}`, itemId: def.id, group: "shelf", category: def.category, def, kind: model.kind, size: def.size, root: model.root });
|
|
1760
3292
|
return model.root;
|
|
1761
3293
|
}
|
|
@@ -1765,9 +3297,9 @@ var GameItemsThree = (() => {
|
|
|
1765
3297
|
name: model.def ? nameOf(model.def) : label(`item.${model.id}`, humanize(model.id)),
|
|
1766
3298
|
movable: false,
|
|
1767
3299
|
build: (THREE) => {
|
|
1768
|
-
const
|
|
3300
|
+
const T = THREE;
|
|
1769
3301
|
const subject = { id: model.id, category: model.def?.category ?? "", size: model.size, model: model.id };
|
|
1770
|
-
const built = buildItem(
|
|
3302
|
+
const built = buildItem(T, subject, { wear: stageFor(model.def) });
|
|
1771
3303
|
register({ id: `${SHOWCASE_PREFIX}${model.id}`, itemId: model.id, group: "showcase", category: model.def?.category ?? "", def: model.def, kind: built.kind, size: model.size, root: built.root });
|
|
1772
3304
|
return built.root;
|
|
1773
3305
|
}
|
|
@@ -1777,11 +3309,11 @@ var GameItemsThree = (() => {
|
|
|
1777
3309
|
name: text.stand,
|
|
1778
3310
|
movable: false,
|
|
1779
3311
|
build: (THREE) => {
|
|
1780
|
-
const
|
|
1781
|
-
const group = new
|
|
1782
|
-
const base = new
|
|
3312
|
+
const T = THREE;
|
|
3313
|
+
const group = new T.Group();
|
|
3314
|
+
const base = new T.Mesh(new T.CylinderGeometry(STAND.radius, STAND.radius + 0.1, STAND.height - 0.04, 40), new T.MeshStandardMaterial({ color: 3816772, roughness: 0.8 }));
|
|
1783
3315
|
base.position.y = (STAND.height - 0.04) / 2;
|
|
1784
|
-
const top = new
|
|
3316
|
+
const top = new T.Mesh(new T.CylinderGeometry(STAND.radius, STAND.radius, 0.04, 40), new T.MeshStandardMaterial({ color: 13617848, roughness: 0.6 }));
|
|
1785
3317
|
top.position.y = STAND.height - 0.02;
|
|
1786
3318
|
group.add(base, top);
|
|
1787
3319
|
return group;
|
|
@@ -1792,19 +3324,19 @@ var GameItemsThree = (() => {
|
|
|
1792
3324
|
name: text.ruler,
|
|
1793
3325
|
movable: false,
|
|
1794
3326
|
build: (THREE) => {
|
|
1795
|
-
const
|
|
1796
|
-
const group = new
|
|
1797
|
-
const post = new
|
|
3327
|
+
const T = THREE;
|
|
3328
|
+
const group = new T.Group();
|
|
3329
|
+
const post = new T.Mesh(new T.BoxGeometry(0.06, RULER_HEIGHT, 0.02), new T.MeshStandardMaterial({ color: 15262408, roughness: 0.7 }));
|
|
1798
3330
|
post.position.y = RULER_HEIGHT / 2;
|
|
1799
3331
|
group.add(post);
|
|
1800
|
-
const tick = new
|
|
3332
|
+
const tick = new T.MeshStandardMaterial({ color: 1776411 });
|
|
1801
3333
|
for (let cm = 0; cm <= 155; cm += 5) {
|
|
1802
3334
|
const long = cm % 10 === 0;
|
|
1803
|
-
const mark = new
|
|
3335
|
+
const mark = new T.Mesh(new T.BoxGeometry(long ? 0.05 : 0.03, 4e-3, 0.024), tick);
|
|
1804
3336
|
mark.position.set(0.03 + (long ? 0.025 : 0.015), cm / 100, 0);
|
|
1805
3337
|
group.add(mark);
|
|
1806
3338
|
}
|
|
1807
|
-
const base = new
|
|
3339
|
+
const base = new T.Mesh(new T.BoxGeometry(0.3, 0.03, 0.3), new T.MeshStandardMaterial({ color: 5593180 }));
|
|
1808
3340
|
base.position.y = 0.015;
|
|
1809
3341
|
group.add(base);
|
|
1810
3342
|
group.userData.height = RULER_HEIGHT;
|
|
@@ -1816,19 +3348,19 @@ var GameItemsThree = (() => {
|
|
|
1816
3348
|
name: text.human,
|
|
1817
3349
|
movable: false,
|
|
1818
3350
|
build: (THREE) => {
|
|
1819
|
-
const
|
|
1820
|
-
const group = new
|
|
1821
|
-
const skin = new
|
|
3351
|
+
const T = THREE;
|
|
3352
|
+
const group = new T.Group();
|
|
3353
|
+
const skin = new T.MeshStandardMaterial({ color: 10134445, roughness: 0.9 });
|
|
1822
3354
|
const part = (geometry, x, y) => {
|
|
1823
|
-
const
|
|
1824
|
-
|
|
1825
|
-
group.add(
|
|
3355
|
+
const mesh2 = new T.Mesh(geometry, skin);
|
|
3356
|
+
mesh2.position.set(x, y, 0);
|
|
3357
|
+
group.add(mesh2);
|
|
1826
3358
|
};
|
|
1827
|
-
for (const x of [-0.09, 0.09]) part(new
|
|
1828
|
-
part(new
|
|
1829
|
-
for (const x of [-0.26, 0.26]) part(new
|
|
1830
|
-
part(new
|
|
1831
|
-
part(new
|
|
3359
|
+
for (const x of [-0.09, 0.09]) part(new T.CylinderGeometry(0.075, 0.06, 0.88, 10), x, 0.44);
|
|
3360
|
+
part(new T.BoxGeometry(0.4, 0.62, 0.22), 0, 0.88 + 0.31);
|
|
3361
|
+
for (const x of [-0.26, 0.26]) part(new T.CylinderGeometry(0.045, 0.04, 0.6, 8), x, 1.2);
|
|
3362
|
+
part(new T.CylinderGeometry(0.05, 0.055, 0.07, 8), 0, 1.535);
|
|
3363
|
+
part(new T.SphereGeometry(0.115, 14, 10), 0, 1.685);
|
|
1832
3364
|
group.userData.height = HUMAN_HEIGHT;
|
|
1833
3365
|
return group;
|
|
1834
3366
|
}
|
|
@@ -1838,14 +3370,14 @@ var GameItemsThree = (() => {
|
|
|
1838
3370
|
name: text.table,
|
|
1839
3371
|
movable: false,
|
|
1840
3372
|
build: (THREE) => {
|
|
1841
|
-
const
|
|
1842
|
-
const group = new
|
|
1843
|
-
const top = new
|
|
3373
|
+
const T = THREE;
|
|
3374
|
+
const group = new T.Group();
|
|
3375
|
+
const top = new T.Mesh(new T.BoxGeometry(TABLE.length, 0.05, TABLE.depth), new T.MeshStandardMaterial({ color: 8022613, roughness: 0.8 }));
|
|
1844
3376
|
top.position.y = TABLE.height - 0.025;
|
|
1845
3377
|
group.add(top);
|
|
1846
|
-
const frame = new
|
|
3378
|
+
const frame = new T.MeshStandardMaterial({ color: 4013892 });
|
|
1847
3379
|
for (const sx of [-1, 1]) for (const sz of [-1, 1]) {
|
|
1848
|
-
const leg = new
|
|
3380
|
+
const leg = new T.Mesh(new T.BoxGeometry(0.06, TABLE.height - 0.05, 0.06), frame);
|
|
1849
3381
|
leg.position.set(sx * (TABLE.length - 0.12) / 2, (TABLE.height - 0.05) / 2, sz * (TABLE.depth - 0.12) / 2);
|
|
1850
3382
|
group.add(leg);
|
|
1851
3383
|
}
|
|
@@ -1863,10 +3395,10 @@ var GameItemsThree = (() => {
|
|
|
1863
3395
|
};
|
|
1864
3396
|
const applyHighlight = () => {
|
|
1865
3397
|
for (const entry of entries2) {
|
|
1866
|
-
entry.root.traverse((
|
|
1867
|
-
const
|
|
1868
|
-
if (!
|
|
1869
|
-
for (const material of Array.isArray(
|
|
3398
|
+
entry.root.traverse((object2) => {
|
|
3399
|
+
const mesh2 = object2;
|
|
3400
|
+
if (!mesh2.isMesh) return;
|
|
3401
|
+
for (const material of Array.isArray(mesh2.material) ? mesh2.material : [mesh2.material]) {
|
|
1870
3402
|
const standard = material;
|
|
1871
3403
|
if (standard.emissive) standard.emissive.setHex(layers.simple_shapes && entry.kind === "shape" ? HIGHLIGHT : 0);
|
|
1872
3404
|
}
|
|
@@ -1874,21 +3406,21 @@ var GameItemsThree = (() => {
|
|
|
1874
3406
|
}
|
|
1875
3407
|
};
|
|
1876
3408
|
const clearBoxes = () => {
|
|
1877
|
-
for (const
|
|
1878
|
-
|
|
3409
|
+
for (const box3 of boxes) {
|
|
3410
|
+
box3.parent?.remove(box3);
|
|
1879
3411
|
}
|
|
1880
3412
|
boxes = [];
|
|
1881
3413
|
};
|
|
1882
3414
|
const applyBoxes = () => {
|
|
1883
3415
|
clearBoxes();
|
|
1884
3416
|
if (!layers.boxes || !host || !latestTHREE) return;
|
|
1885
|
-
const
|
|
3417
|
+
const T = latestTHREE;
|
|
1886
3418
|
const scene = host.scene;
|
|
1887
3419
|
for (const entry of liveEntries()) {
|
|
1888
3420
|
if (!entry.root.visible) continue;
|
|
1889
|
-
const
|
|
1890
|
-
if (
|
|
1891
|
-
const helper = new
|
|
3421
|
+
const box3 = new T.Box3().setFromObject(entry.root);
|
|
3422
|
+
if (box3.isEmpty()) continue;
|
|
3423
|
+
const helper = new T.Box3Helper(box3, BOX_COLOR);
|
|
1892
3424
|
scene.add(helper);
|
|
1893
3425
|
boxes.push(helper);
|
|
1894
3426
|
}
|
|
@@ -1899,7 +3431,7 @@ var GameItemsThree = (() => {
|
|
|
1899
3431
|
findsGroup = null;
|
|
1900
3432
|
}
|
|
1901
3433
|
};
|
|
1902
|
-
const labelSprite = (
|
|
3434
|
+
const labelSprite = (T, content) => {
|
|
1903
3435
|
if (typeof document === "undefined") return null;
|
|
1904
3436
|
const canvas = document.createElement("canvas");
|
|
1905
3437
|
const context = canvas.getContext("2d");
|
|
@@ -1913,8 +3445,8 @@ var GameItemsThree = (() => {
|
|
|
1913
3445
|
context.textAlign = "center";
|
|
1914
3446
|
context.textBaseline = "middle";
|
|
1915
3447
|
context.fillText(content.length > 22 ? `${content.slice(0, 21)}\u2026` : content, 128, 32);
|
|
1916
|
-
const texture = new
|
|
1917
|
-
const sprite = new
|
|
3448
|
+
const texture = new T.CanvasTexture(canvas);
|
|
3449
|
+
const sprite = new T.Sprite(new T.SpriteMaterial({ map: texture, depthTest: false, transparent: true }));
|
|
1918
3450
|
sprite.scale.set(0.5, 0.125, 1);
|
|
1919
3451
|
sprite.renderOrder = 10;
|
|
1920
3452
|
return sprite;
|
|
@@ -1922,8 +3454,8 @@ var GameItemsThree = (() => {
|
|
|
1922
3454
|
const showFinds = () => {
|
|
1923
3455
|
clearFinds();
|
|
1924
3456
|
if (!host || !latestTHREE) return;
|
|
1925
|
-
const
|
|
1926
|
-
const group = new
|
|
3457
|
+
const T = latestTHREE;
|
|
3458
|
+
const group = new T.Group();
|
|
1927
3459
|
group.position.set(TABLE.at[0], TABLE.height + 5e-3, TABLE.at[2]);
|
|
1928
3460
|
let cursor = -TABLE.length / 2 + 0.1;
|
|
1929
3461
|
const scale = 1;
|
|
@@ -1932,12 +3464,12 @@ var GameItemsThree = (() => {
|
|
|
1932
3464
|
const copies = Math.min(found.count, MAX_COPIES);
|
|
1933
3465
|
const start = cursor;
|
|
1934
3466
|
for (let i = 0; i < copies; i++) {
|
|
1935
|
-
const model = buildItem(
|
|
3467
|
+
const model = buildItem(T, drawable(def), { wear: stageFor(def) });
|
|
1936
3468
|
model.root.position.set(cursor + def.size[0] * scale / 2, 0, 0);
|
|
1937
3469
|
group.add(model.root);
|
|
1938
3470
|
cursor += def.size[0] + 0.03;
|
|
1939
3471
|
}
|
|
1940
|
-
const sprite = labelSprite(
|
|
3472
|
+
const sprite = labelSprite(T, `${nameOf(def)} x${found.count}`);
|
|
1941
3473
|
if (sprite) {
|
|
1942
3474
|
sprite.position.set((start + cursor) / 2, Math.max(def.size[1], 0.1) + 0.12, 0);
|
|
1943
3475
|
sprite.visible = layers.labels;
|
|
@@ -1951,8 +3483,8 @@ var GameItemsThree = (() => {
|
|
|
1951
3483
|
findsGroup = group;
|
|
1952
3484
|
};
|
|
1953
3485
|
const applyLabels = () => {
|
|
1954
|
-
findsGroup?.traverse((
|
|
1955
|
-
if (
|
|
3486
|
+
findsGroup?.traverse((object2) => {
|
|
3487
|
+
if (object2.userData.label) object2.visible = layers.labels;
|
|
1956
3488
|
});
|
|
1957
3489
|
};
|
|
1958
3490
|
const rollFinds = () => {
|