@adatechnology/game-vehicles 0.4.5 → 0.4.7
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/dist/index.global.js +666 -184
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +633 -151
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.global.js
CHANGED
|
@@ -580,12 +580,12 @@ var GameVehicles = (() => {
|
|
|
580
580
|
return triangles;
|
|
581
581
|
}
|
|
582
582
|
};
|
|
583
|
-
function linkedList(data,
|
|
583
|
+
function linkedList(data, start2, end, dim, clockwise) {
|
|
584
584
|
let i, last;
|
|
585
|
-
if (clockwise === signedArea(data,
|
|
586
|
-
for (i =
|
|
585
|
+
if (clockwise === signedArea(data, start2, end, dim) > 0) {
|
|
586
|
+
for (i = start2; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
587
587
|
} else {
|
|
588
|
-
for (i = end - dim; i >=
|
|
588
|
+
for (i = end - dim; i >= start2; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
589
589
|
}
|
|
590
590
|
if (last && equals(last, last.next)) {
|
|
591
591
|
removeNode(last);
|
|
@@ -593,10 +593,10 @@ var GameVehicles = (() => {
|
|
|
593
593
|
}
|
|
594
594
|
return last;
|
|
595
595
|
}
|
|
596
|
-
function filterPoints(
|
|
597
|
-
if (!
|
|
598
|
-
if (!end) end =
|
|
599
|
-
let p =
|
|
596
|
+
function filterPoints(start2, end) {
|
|
597
|
+
if (!start2) return start2;
|
|
598
|
+
if (!end) end = start2;
|
|
599
|
+
let p = start2, again;
|
|
600
600
|
do {
|
|
601
601
|
again = false;
|
|
602
602
|
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
@@ -675,8 +675,8 @@ var GameVehicles = (() => {
|
|
|
675
675
|
}
|
|
676
676
|
return true;
|
|
677
677
|
}
|
|
678
|
-
function cureLocalIntersections(
|
|
679
|
-
let p =
|
|
678
|
+
function cureLocalIntersections(start2, triangles, dim) {
|
|
679
|
+
let p = start2;
|
|
680
680
|
do {
|
|
681
681
|
const a = p.prev, b = p.next.next;
|
|
682
682
|
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
@@ -685,14 +685,14 @@ var GameVehicles = (() => {
|
|
|
685
685
|
triangles.push(b.i / dim | 0);
|
|
686
686
|
removeNode(p);
|
|
687
687
|
removeNode(p.next);
|
|
688
|
-
p =
|
|
688
|
+
p = start2 = b;
|
|
689
689
|
}
|
|
690
690
|
p = p.next;
|
|
691
|
-
} while (p !==
|
|
691
|
+
} while (p !== start2);
|
|
692
692
|
return filterPoints(p);
|
|
693
693
|
}
|
|
694
|
-
function splitEarcut(
|
|
695
|
-
let a =
|
|
694
|
+
function splitEarcut(start2, triangles, dim, minX, minY, invSize) {
|
|
695
|
+
let a = start2;
|
|
696
696
|
do {
|
|
697
697
|
let b = a.next.next;
|
|
698
698
|
while (b !== a.prev) {
|
|
@@ -707,15 +707,15 @@ var GameVehicles = (() => {
|
|
|
707
707
|
b = b.next;
|
|
708
708
|
}
|
|
709
709
|
a = a.next;
|
|
710
|
-
} while (a !==
|
|
710
|
+
} while (a !== start2);
|
|
711
711
|
}
|
|
712
712
|
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
713
713
|
const queue = [];
|
|
714
|
-
let i, len,
|
|
714
|
+
let i, len, start2, end, list2;
|
|
715
715
|
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
716
|
-
|
|
716
|
+
start2 = holeIndices[i] * dim;
|
|
717
717
|
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
718
|
-
list2 = linkedList(data,
|
|
718
|
+
list2 = linkedList(data, start2, end, dim, false);
|
|
719
719
|
if (list2 === list2.next) list2.steiner = true;
|
|
720
720
|
queue.push(getLeftmost(list2));
|
|
721
721
|
}
|
|
@@ -770,14 +770,14 @@ var GameVehicles = (() => {
|
|
|
770
770
|
function sectorContainsSector(m, p) {
|
|
771
771
|
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
772
772
|
}
|
|
773
|
-
function indexCurve(
|
|
774
|
-
let p =
|
|
773
|
+
function indexCurve(start2, minX, minY, invSize) {
|
|
774
|
+
let p = start2;
|
|
775
775
|
do {
|
|
776
776
|
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
777
777
|
p.prevZ = p.prev;
|
|
778
778
|
p.nextZ = p.next;
|
|
779
779
|
p = p.next;
|
|
780
|
-
} while (p !==
|
|
780
|
+
} while (p !== start2);
|
|
781
781
|
p.prevZ.nextZ = null;
|
|
782
782
|
p.prevZ = null;
|
|
783
783
|
sortLinked(p);
|
|
@@ -834,12 +834,12 @@ var GameVehicles = (() => {
|
|
|
834
834
|
y = (y | y << 1) & 1431655765;
|
|
835
835
|
return x | y << 1;
|
|
836
836
|
}
|
|
837
|
-
function getLeftmost(
|
|
838
|
-
let p =
|
|
837
|
+
function getLeftmost(start2) {
|
|
838
|
+
let p = start2, leftmost = start2;
|
|
839
839
|
do {
|
|
840
840
|
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
|
|
841
841
|
p = p.next;
|
|
842
|
-
} while (p !==
|
|
842
|
+
} while (p !== start2);
|
|
843
843
|
return leftmost;
|
|
844
844
|
}
|
|
845
845
|
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
@@ -938,9 +938,9 @@ var GameVehicles = (() => {
|
|
|
938
938
|
this.nextZ = null;
|
|
939
939
|
this.steiner = false;
|
|
940
940
|
}
|
|
941
|
-
function signedArea(data,
|
|
941
|
+
function signedArea(data, start2, end, dim) {
|
|
942
942
|
let sum = 0;
|
|
943
|
-
for (let i =
|
|
943
|
+
for (let i = start2, j = end - dim; i < end; i += dim) {
|
|
944
944
|
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
945
945
|
j = i;
|
|
946
946
|
}
|
|
@@ -1197,7 +1197,7 @@ var GameVehicles = (() => {
|
|
|
1197
1197
|
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
1198
1198
|
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
1199
1199
|
};
|
|
1200
|
-
let
|
|
1200
|
+
let start2 = verticesArray.length / 3;
|
|
1201
1201
|
if (bevelEnabled) {
|
|
1202
1202
|
let offset = 0;
|
|
1203
1203
|
for (let i = 0; i < flen; i++) {
|
|
@@ -1220,8 +1220,8 @@ var GameVehicles = (() => {
|
|
|
1220
1220
|
f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
|
|
1221
1221
|
}
|
|
1222
1222
|
}
|
|
1223
|
-
groups.push({ start, count: verticesArray.length / 3 -
|
|
1224
|
-
|
|
1223
|
+
groups.push({ start: start2, count: verticesArray.length / 3 - start2, materialIndex: 0 });
|
|
1224
|
+
start2 = verticesArray.length / 3;
|
|
1225
1225
|
const sidewalls = (ring2, layeroffset2) => {
|
|
1226
1226
|
let i = ring2.length;
|
|
1227
1227
|
while (--i >= 0) {
|
|
@@ -1242,7 +1242,7 @@ var GameVehicles = (() => {
|
|
|
1242
1242
|
sidewalls(ahole, layeroffset);
|
|
1243
1243
|
layeroffset += ahole.length;
|
|
1244
1244
|
}
|
|
1245
|
-
groups.push({ start, count: verticesArray.length / 3 -
|
|
1245
|
+
groups.push({ start: start2, count: verticesArray.length / 3 - start2, materialIndex: 1 });
|
|
1246
1246
|
const positions = new Float32Array(verticesArray);
|
|
1247
1247
|
return { type: "ExtrudeGeometry", parameters, positions, normals: computeVertexNormals(positions), uvs: new Float32Array(uvArray), groups };
|
|
1248
1248
|
}
|
|
@@ -1518,8 +1518,8 @@ var GameVehicles = (() => {
|
|
|
1518
1518
|
var shims = /* @__PURE__ */ new WeakSet();
|
|
1519
1519
|
function shapeGeometries(THREE, options = {}) {
|
|
1520
1520
|
if (shims.has(THREE)) return THREE;
|
|
1521
|
-
const
|
|
1522
|
-
const key =
|
|
1521
|
+
const cache2 = options.cache !== false;
|
|
1522
|
+
const key = cache2 ? "cache" : "nocache";
|
|
1523
1523
|
let byKey = namespaces.get(THREE);
|
|
1524
1524
|
if (!byKey) {
|
|
1525
1525
|
byKey = /* @__PURE__ */ new Map();
|
|
@@ -1528,7 +1528,7 @@ var GameVehicles = (() => {
|
|
|
1528
1528
|
const existing = byKey.get(key);
|
|
1529
1529
|
if (existing) return existing;
|
|
1530
1530
|
const made = (p) => toGeometry(THREE, p);
|
|
1531
|
-
const viaCache = (node, direct) =>
|
|
1531
|
+
const viaCache = (node, direct) => cache2 ? buildPrimitive(node) : direct();
|
|
1532
1532
|
const defined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
1533
1533
|
const constructors = {
|
|
1534
1534
|
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))),
|
|
@@ -2224,7 +2224,7 @@ var GameVehicles = (() => {
|
|
|
2224
2224
|
const I = kit._;
|
|
2225
2225
|
const document2 = kit.document;
|
|
2226
2226
|
const RUST = new THREE.Color("#5e3220");
|
|
2227
|
-
const
|
|
2227
|
+
const cache2 = {};
|
|
2228
2228
|
let envTex = null;
|
|
2229
2229
|
function studioEnvironment() {
|
|
2230
2230
|
if (envTex) return envTex;
|
|
@@ -2269,7 +2269,7 @@ var GameVehicles = (() => {
|
|
|
2269
2269
|
const key = "s" + c.getHexString() + JSON.stringify(o, function(k, v) {
|
|
2270
2270
|
return v && v.isColor ? "#" + v.getHexString() : v && v.isTexture ? v.uuid : v;
|
|
2271
2271
|
});
|
|
2272
|
-
if (!
|
|
2272
|
+
if (!cache2[key]) {
|
|
2273
2273
|
const o2 = Object.assign({}, o);
|
|
2274
2274
|
delete o2.noEnv;
|
|
2275
2275
|
const mt = new THREE.MeshStandardMaterial(Object.assign({ color: c, roughness: 0.8, metalness: 0, flatShading: false }, o2));
|
|
@@ -2277,9 +2277,9 @@ var GameVehicles = (() => {
|
|
|
2277
2277
|
mt.envMap = studioEnvironment();
|
|
2278
2278
|
if (o.envMapIntensity == null) mt.envMapIntensity = 0.55 + (mt.metalness - 0.6) * 1.6;
|
|
2279
2279
|
}
|
|
2280
|
-
|
|
2280
|
+
cache2[key] = mt;
|
|
2281
2281
|
}
|
|
2282
|
-
return
|
|
2282
|
+
return cache2[key];
|
|
2283
2283
|
}
|
|
2284
2284
|
function makeFlatMaterial(color2, o) {
|
|
2285
2285
|
return makeMaterial(color2, Object.assign({ flatShading: true, roughness: 0.92 }, o || {}));
|
|
@@ -2394,7 +2394,131 @@ var GameVehicles = (() => {
|
|
|
2394
2394
|
return t;
|
|
2395
2395
|
}
|
|
2396
2396
|
kit.textTexture = textTexture;
|
|
2397
|
-
Object.assign(I, { RUST, cache, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE, toColor, MATERIALS, paintColor, texCache, textTexture });
|
|
2397
|
+
Object.assign(I, { RUST, cache: cache2, studioEnvironment, makeMaterial, makeFlatMaterial, DOUBLE_SIDE, toColor, MATERIALS, paintColor, texCache, textTexture });
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
// src/tri-index.ts
|
|
2401
|
+
var TRI_BLOCK = 32;
|
|
2402
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
2403
|
+
function trianglesOf(geo) {
|
|
2404
|
+
return Math.floor((geo.index ? geo.index.count : geo.attributes.position.count) / 3);
|
|
2405
|
+
}
|
|
2406
|
+
function supports(geo) {
|
|
2407
|
+
const pos = geo.attributes && geo.attributes.position;
|
|
2408
|
+
return !!pos && !pos.isInterleavedBufferAttribute && pos.itemSize === 3;
|
|
2409
|
+
}
|
|
2410
|
+
function isCurrent(geo, ti) {
|
|
2411
|
+
const pos = geo.attributes.position;
|
|
2412
|
+
return ti.position === pos && ti.positionVersion === pos.version && ti.index === (geo.index || null) && ti.indexVersion === (geo.index ? geo.index.version : 0) && ti.triangles === trianglesOf(geo);
|
|
2413
|
+
}
|
|
2414
|
+
function blockCount(triangles) {
|
|
2415
|
+
return Math.ceil(triangles / TRI_BLOCK);
|
|
2416
|
+
}
|
|
2417
|
+
function boxBlock(ti, block) {
|
|
2418
|
+
const B = ti.boxes;
|
|
2419
|
+
const t0 = block * TRI_BLOCK;
|
|
2420
|
+
const t1 = Math.min(ti.triangles, t0 + TRI_BLOCK);
|
|
2421
|
+
const o = block * 6;
|
|
2422
|
+
for (let k = 0; k < 3; k++) {
|
|
2423
|
+
ti.blocks[o + k] = Infinity;
|
|
2424
|
+
ti.blocks[o + 3 + k] = -Infinity;
|
|
2425
|
+
}
|
|
2426
|
+
for (let t = t0; t < t1; t++) {
|
|
2427
|
+
const j = t * 6;
|
|
2428
|
+
for (let k = 0; k < 3; k++) {
|
|
2429
|
+
if (B[j + k] < ti.blocks[o + k]) ti.blocks[o + k] = B[j + k];
|
|
2430
|
+
if (B[j + 3 + k] > ti.blocks[o + 3 + k]) ti.blocks[o + 3 + k] = B[j + 3 + k];
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
function boxTriangle(geo, ti, t) {
|
|
2435
|
+
const P = geo.attributes.position.array;
|
|
2436
|
+
const ix = geo.index ? geo.index.array : null;
|
|
2437
|
+
const a = (ix ? ix[t * 3] : t * 3) * 3;
|
|
2438
|
+
const b = (ix ? ix[t * 3 + 1] : t * 3 + 1) * 3;
|
|
2439
|
+
const c = (ix ? ix[t * 3 + 2] : t * 3 + 2) * 3;
|
|
2440
|
+
const j = t * 6;
|
|
2441
|
+
for (let k = 0; k < 3; k++) {
|
|
2442
|
+
ti.boxes[j + k] = Math.min(P[a + k], P[b + k], P[c + k]);
|
|
2443
|
+
ti.boxes[j + 3 + k] = Math.max(P[a + k], P[b + k], P[c + k]);
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
function advance(geo, ti, deadline) {
|
|
2447
|
+
const total = blockCount(ti.triangles);
|
|
2448
|
+
while (ti.builtBlocks < total) {
|
|
2449
|
+
const block = ti.builtBlocks;
|
|
2450
|
+
const t1 = Math.min(ti.triangles, (block + 1) * TRI_BLOCK);
|
|
2451
|
+
for (let t = block * TRI_BLOCK; t < t1; t++) boxTriangle(geo, ti, t);
|
|
2452
|
+
boxBlock(ti, block);
|
|
2453
|
+
ti.builtBlocks++;
|
|
2454
|
+
if (deadline !== Infinity && performance.now() >= deadline) break;
|
|
2455
|
+
}
|
|
2456
|
+
return ti.builtBlocks === total;
|
|
2457
|
+
}
|
|
2458
|
+
function start(geo) {
|
|
2459
|
+
const pos = geo.attributes.position;
|
|
2460
|
+
const triangles = trianglesOf(geo);
|
|
2461
|
+
const ti = {
|
|
2462
|
+
position: pos,
|
|
2463
|
+
positionVersion: pos.version,
|
|
2464
|
+
index: geo.index || null,
|
|
2465
|
+
indexVersion: geo.index ? geo.index.version : 0,
|
|
2466
|
+
triangles,
|
|
2467
|
+
boxes: new Float64Array(triangles * 6),
|
|
2468
|
+
blocks: new Float64Array(blockCount(triangles) * 6),
|
|
2469
|
+
builtBlocks: 0
|
|
2470
|
+
};
|
|
2471
|
+
cache.set(geo, ti);
|
|
2472
|
+
return ti;
|
|
2473
|
+
}
|
|
2474
|
+
function triIndexOf(geo) {
|
|
2475
|
+
if (!supports(geo)) return void 0;
|
|
2476
|
+
let ti = cache.get(geo);
|
|
2477
|
+
if (!ti || !isCurrent(geo, ti)) ti = start(geo);
|
|
2478
|
+
advance(geo, ti, Infinity);
|
|
2479
|
+
return ti;
|
|
2480
|
+
}
|
|
2481
|
+
function warmTriIndex(geo, deadline) {
|
|
2482
|
+
if (!supports(geo)) return true;
|
|
2483
|
+
let ti = cache.get(geo);
|
|
2484
|
+
if (!ti || !isCurrent(geo, ti)) ti = start(geo);
|
|
2485
|
+
return advance(geo, ti, deadline);
|
|
2486
|
+
}
|
|
2487
|
+
function storeTriIndex(geo, boxes) {
|
|
2488
|
+
const ti = start(geo);
|
|
2489
|
+
ti.boxes = boxes;
|
|
2490
|
+
const total = blockCount(ti.triangles);
|
|
2491
|
+
for (let b = 0; b < total; b++) boxBlock(ti, b);
|
|
2492
|
+
ti.builtBlocks = total;
|
|
2493
|
+
}
|
|
2494
|
+
function liveTriIndex(geo) {
|
|
2495
|
+
if (geo.index || !supports(geo)) return void 0;
|
|
2496
|
+
const ti = cache.get(geo);
|
|
2497
|
+
return ti && isCurrent(geo, ti) && ti.builtBlocks === blockCount(ti.triangles) ? ti : void 0;
|
|
2498
|
+
}
|
|
2499
|
+
function touchTriIndex(geo, ti, vertices) {
|
|
2500
|
+
if (ti.positionVersion + 1 !== geo.attributes.position.version) return;
|
|
2501
|
+
const blocks = /* @__PURE__ */ new Set();
|
|
2502
|
+
for (const v of vertices) {
|
|
2503
|
+
const t = Math.floor(v / 3);
|
|
2504
|
+
if (t >= ti.triangles) continue;
|
|
2505
|
+
boxTriangle(geo, ti, t);
|
|
2506
|
+
blocks.add(Math.floor(t / TRI_BLOCK));
|
|
2507
|
+
}
|
|
2508
|
+
blocks.forEach((b) => boxBlock(ti, b));
|
|
2509
|
+
ti.positionVersion = geo.attributes.position.version;
|
|
2510
|
+
}
|
|
2511
|
+
function boundsFromIndex(geo) {
|
|
2512
|
+
if (geo.index || !supports(geo)) return void 0;
|
|
2513
|
+
const ti = cache.get(geo);
|
|
2514
|
+
if (!ti || !isCurrent(geo, ti) || ti.builtBlocks !== blockCount(ti.triangles) || !ti.triangles || geo.attributes.position.count !== ti.triangles * 3) return void 0;
|
|
2515
|
+
const box2 = new Float64Array([Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity]);
|
|
2516
|
+
for (let b = 0, n = blockCount(ti.triangles); b < n; b++)
|
|
2517
|
+
for (let k = 0; k < 3; k++) {
|
|
2518
|
+
box2[k] = Math.min(box2[k], ti.blocks[b * 6 + k]);
|
|
2519
|
+
box2[3 + k] = Math.max(box2[3 + k], ti.blocks[b * 6 + 3 + k]);
|
|
2520
|
+
}
|
|
2521
|
+
return { box: box2, version: ti.positionVersion };
|
|
2398
2522
|
}
|
|
2399
2523
|
|
|
2400
2524
|
// src/geometry.ts
|
|
@@ -2491,7 +2615,8 @@ var GameVehicles = (() => {
|
|
|
2491
2615
|
g.userData.crease = true;
|
|
2492
2616
|
return g;
|
|
2493
2617
|
}
|
|
2494
|
-
|
|
2618
|
+
const latestCrease = /* @__PURE__ */ new WeakMap();
|
|
2619
|
+
function creaseTask(geo, deg) {
|
|
2495
2620
|
if (geo.index) {
|
|
2496
2621
|
const ni = geo.toNonIndexed();
|
|
2497
2622
|
Object.keys(ni.attributes).forEach(function(k) {
|
|
@@ -2499,30 +2624,22 @@ var GameVehicles = (() => {
|
|
|
2499
2624
|
});
|
|
2500
2625
|
geo.setIndex(null);
|
|
2501
2626
|
}
|
|
2502
|
-
const
|
|
2503
|
-
const n =
|
|
2627
|
+
const P = geo.attributes.position.array;
|
|
2628
|
+
const n = geo.attributes.position.count;
|
|
2504
2629
|
const faces = n / 3;
|
|
2505
2630
|
const FN = new Float64Array(faces * 3);
|
|
2506
|
-
const
|
|
2507
|
-
const RANGE = 65536;
|
|
2508
|
-
function key(i) {
|
|
2509
|
-
const x = Math.round(p.getX(i) * 2e3);
|
|
2510
|
-
const y = Math.round(p.getY(i) * 2e3);
|
|
2511
|
-
const z = Math.round(p.getZ(i) * 2e3);
|
|
2512
|
-
if (Math.abs(x) < RANGE && Math.abs(y) < RANGE && Math.abs(z) < RANGE) return ((x + RANGE) * 131072 + (y + RANGE)) * 131072 + (z + RANGE);
|
|
2513
|
-
return x + "," + y + "," + z;
|
|
2514
|
-
}
|
|
2515
|
-
const keys = new Array(n);
|
|
2631
|
+
const out = new Float32Array(n * 3);
|
|
2516
2632
|
for (let f = 0; f < faces; f++) {
|
|
2517
|
-
const
|
|
2518
|
-
const
|
|
2519
|
-
const
|
|
2520
|
-
const
|
|
2521
|
-
const
|
|
2522
|
-
const
|
|
2523
|
-
const
|
|
2524
|
-
const
|
|
2525
|
-
const
|
|
2633
|
+
const o = 9 * f;
|
|
2634
|
+
const ax = P[o];
|
|
2635
|
+
const ay = P[o + 1];
|
|
2636
|
+
const az = P[o + 2];
|
|
2637
|
+
const bx = P[o + 3];
|
|
2638
|
+
const by = P[o + 4];
|
|
2639
|
+
const bz = P[o + 5];
|
|
2640
|
+
const cx = P[o + 6];
|
|
2641
|
+
const cy = P[o + 7];
|
|
2642
|
+
const cz = P[o + 8];
|
|
2526
2643
|
const e1x = cx - bx;
|
|
2527
2644
|
const e1y = cy - by;
|
|
2528
2645
|
const e1z = cz - bz;
|
|
@@ -2542,41 +2659,109 @@ var GameVehicles = (() => {
|
|
|
2542
2659
|
FN[3 * f + 1] = ny;
|
|
2543
2660
|
FN[3 * f + 2] = nz;
|
|
2544
2661
|
for (let k = 0; k < 3; k++) {
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2662
|
+
out[9 * f + 3 * k] = nx;
|
|
2663
|
+
out[9 * f + 3 * k + 1] = ny;
|
|
2664
|
+
out[9 * f + 3 * k + 2] = nz;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
const normal = new THREE.BufferAttribute(out, 3);
|
|
2668
|
+
geo.setAttribute("normal", normal);
|
|
2669
|
+
const token = {};
|
|
2670
|
+
latestCrease.set(geo, token);
|
|
2671
|
+
let size = 16;
|
|
2672
|
+
while (size < n * 2) size *= 2;
|
|
2673
|
+
const mask = size - 1;
|
|
2674
|
+
const slot = new Int32Array(size).fill(-1);
|
|
2675
|
+
const gx = new Int32Array(n);
|
|
2676
|
+
const gy = new Int32Array(n);
|
|
2677
|
+
const gz = new Int32Array(n);
|
|
2678
|
+
const groupOf = new Int32Array(n);
|
|
2679
|
+
let groups = 0;
|
|
2680
|
+
let start2;
|
|
2681
|
+
let members;
|
|
2682
|
+
const cs = Math.cos(deg * PI / 180);
|
|
2683
|
+
let phase = 0;
|
|
2684
|
+
let at = 0;
|
|
2685
|
+
function hashSlice(deadline) {
|
|
2686
|
+
for (; at < n; at++) {
|
|
2687
|
+
if ((at & 1023) === 0 && performance.now() > deadline) return false;
|
|
2688
|
+
const x = Math.round(P[3 * at] * 2e3) | 0;
|
|
2689
|
+
const y = Math.round(P[3 * at + 1] * 2e3) | 0;
|
|
2690
|
+
const z = Math.round(P[3 * at + 2] * 2e3) | 0;
|
|
2691
|
+
let h = (Math.imul(x, 73856093) ^ Math.imul(y, 19349663) ^ Math.imul(z, 83492791)) & mask;
|
|
2692
|
+
let g = slot[h];
|
|
2693
|
+
while (g >= 0 && (gx[g] !== x || gy[g] !== y || gz[g] !== z)) {
|
|
2694
|
+
h = h + 1 & mask;
|
|
2695
|
+
g = slot[h];
|
|
2696
|
+
}
|
|
2697
|
+
if (g < 0) {
|
|
2698
|
+
g = groups++;
|
|
2699
|
+
slot[h] = g;
|
|
2700
|
+
gx[g] = x;
|
|
2701
|
+
gy[g] = y;
|
|
2702
|
+
gz[g] = z;
|
|
2703
|
+
}
|
|
2704
|
+
groupOf[at] = g;
|
|
2550
2705
|
}
|
|
2706
|
+
return true;
|
|
2551
2707
|
}
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2558
|
-
let
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
if (
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2708
|
+
function gather() {
|
|
2709
|
+
start2 = new Int32Array(groups + 1);
|
|
2710
|
+
for (let i = 0; i < n; i++) start2[groupOf[i] + 1]++;
|
|
2711
|
+
for (let g = 0; g < groups; g++) start2[g + 1] += start2[g];
|
|
2712
|
+
const fill = start2.slice(0, groups);
|
|
2713
|
+
members = new Int32Array(n);
|
|
2714
|
+
for (let i = 0; i < n; i++) members[fill[groupOf[i]]++] = i / 3 | 0;
|
|
2715
|
+
}
|
|
2716
|
+
function smoothSlice(deadline) {
|
|
2717
|
+
for (; at < n; at++) {
|
|
2718
|
+
if ((at & 1023) === 0 && performance.now() > deadline) return false;
|
|
2719
|
+
const fi = (at / 3 | 0) * 3;
|
|
2720
|
+
const g = groupOf[at];
|
|
2721
|
+
let sx = 0;
|
|
2722
|
+
let sy = 0;
|
|
2723
|
+
let sz = 0;
|
|
2724
|
+
for (let j = start2[g], end = start2[g + 1]; j < end; j++) {
|
|
2725
|
+
const o = members[j] * 3;
|
|
2726
|
+
if (FN[o] * FN[fi] + FN[o + 1] * FN[fi + 1] + FN[o + 2] * FN[fi + 2] >= cs) {
|
|
2727
|
+
sx += FN[o];
|
|
2728
|
+
sy += FN[o + 1];
|
|
2729
|
+
sz += FN[o + 2];
|
|
2730
|
+
}
|
|
2566
2731
|
}
|
|
2732
|
+
if (sx * sx + sy * sy + sz * sz < 1e-20) {
|
|
2733
|
+
sx = FN[fi];
|
|
2734
|
+
sy = FN[fi + 1];
|
|
2735
|
+
sz = FN[fi + 2];
|
|
2736
|
+
}
|
|
2737
|
+
const inv = 1 / (Math.sqrt(sx * sx + sy * sy + sz * sz) || 1);
|
|
2738
|
+
out[3 * at] = sx * inv;
|
|
2739
|
+
out[3 * at + 1] = sy * inv;
|
|
2740
|
+
out[3 * at + 2] = sz * inv;
|
|
2567
2741
|
}
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2742
|
+
return true;
|
|
2743
|
+
}
|
|
2744
|
+
function step(deadline) {
|
|
2745
|
+
if (latestCrease.get(geo) !== token) return true;
|
|
2746
|
+
if (phase === 0) {
|
|
2747
|
+
if (!hashSlice(deadline)) return false;
|
|
2748
|
+
gather();
|
|
2749
|
+
phase = 1;
|
|
2750
|
+
at = 0;
|
|
2751
|
+
}
|
|
2752
|
+
if (phase === 1) {
|
|
2753
|
+
const done = smoothSlice(deadline);
|
|
2754
|
+
if (deadline !== Infinity) normal.needsUpdate = true;
|
|
2755
|
+
if (!done) return false;
|
|
2756
|
+
phase = 2;
|
|
2757
|
+
geo.userData.crease = true;
|
|
2572
2758
|
}
|
|
2573
|
-
|
|
2574
|
-
out[3 * i] = sx * inv;
|
|
2575
|
-
out[3 * i + 1] = sy * inv;
|
|
2576
|
-
out[3 * i + 2] = sz * inv;
|
|
2759
|
+
return true;
|
|
2577
2760
|
}
|
|
2578
|
-
geo
|
|
2579
|
-
|
|
2761
|
+
return { geo, step };
|
|
2762
|
+
}
|
|
2763
|
+
function crease(geo, deg) {
|
|
2764
|
+
creaseTask(geo, deg).step(Infinity);
|
|
2580
2765
|
return geo;
|
|
2581
2766
|
}
|
|
2582
2767
|
function pathShape(items) {
|
|
@@ -2723,28 +2908,28 @@ var GameVehicles = (() => {
|
|
|
2723
2908
|
return g;
|
|
2724
2909
|
}
|
|
2725
2910
|
function cutGeometry(geo, tests) {
|
|
2726
|
-
const
|
|
2911
|
+
const idx = geo.index ? geo.index.array : null;
|
|
2727
2912
|
const names = ["position"].concat(
|
|
2728
2913
|
["color", "uv"].filter(function(n2) {
|
|
2729
|
-
return !!
|
|
2914
|
+
return !!geo.attributes[n2];
|
|
2730
2915
|
})
|
|
2731
2916
|
);
|
|
2732
2917
|
const sizes = names.map(function(n2) {
|
|
2733
|
-
return
|
|
2918
|
+
return geo.attributes[n2].itemSize;
|
|
2734
2919
|
});
|
|
2735
2920
|
const arrs = names.map(function(n2) {
|
|
2736
|
-
return
|
|
2921
|
+
return geo.attributes[n2].array;
|
|
2737
2922
|
});
|
|
2738
|
-
const nv =
|
|
2739
|
-
|
|
2740
|
-
for (let f = 0; f < nv; f += 3) {
|
|
2923
|
+
const nv = idx ? idx.length : geo.attributes.position.count;
|
|
2924
|
+
function readTri(f) {
|
|
2741
2925
|
const t = [];
|
|
2742
2926
|
for (let k = 0; k < 3; k++) {
|
|
2927
|
+
const vi = idx ? idx[f + k] : f + k;
|
|
2743
2928
|
const v = [];
|
|
2744
|
-
for (let a = 0; a < names.length; a++) for (let q = 0; q < sizes[a]; q++) v.push(arrs[a][
|
|
2929
|
+
for (let a = 0; a < names.length; a++) for (let q = 0; q < sizes[a]; q++) v.push(arrs[a][vi * sizes[a] + q]);
|
|
2745
2930
|
t.push(v);
|
|
2746
2931
|
}
|
|
2747
|
-
|
|
2932
|
+
return t;
|
|
2748
2933
|
}
|
|
2749
2934
|
const cut = {};
|
|
2750
2935
|
const n = new V3();
|
|
@@ -2770,60 +2955,177 @@ var GameVehicles = (() => {
|
|
|
2770
2955
|
function fan(poly, arr) {
|
|
2771
2956
|
for (let i = 1; i < poly.length - 1; i++) arr.push([poly[0], poly[i], poly[i + 1]]);
|
|
2772
2957
|
}
|
|
2773
|
-
|
|
2774
|
-
const
|
|
2958
|
+
function testTri(T, t, next, rem) {
|
|
2959
|
+
const A = t[0];
|
|
2960
|
+
const B = t[1];
|
|
2961
|
+
const C = t[2];
|
|
2962
|
+
e1.set(B[0] - A[0], B[1] - A[1], B[2] - A[2]);
|
|
2963
|
+
e2.set(C[0] - A[0], C[1] - A[1], C[2] - A[2]);
|
|
2964
|
+
n.crossVectors(e1, e2);
|
|
2965
|
+
const len = n.length();
|
|
2966
|
+
if (len < 1e-12) {
|
|
2967
|
+
next.push(t);
|
|
2968
|
+
return;
|
|
2969
|
+
}
|
|
2970
|
+
n.multiplyScalar(1 / len);
|
|
2971
|
+
ce.set((A[0] + B[0] + C[0]) / 3, (A[1] + B[1] + C[1]) / 3, (A[2] + B[2] + C[2]) / 3);
|
|
2972
|
+
if (T.sel && !T.sel(n, ce)) {
|
|
2973
|
+
next.push(t);
|
|
2974
|
+
return;
|
|
2975
|
+
}
|
|
2976
|
+
const d = [T.sdf(A[0], A[1], A[2]), T.sdf(B[0], B[1], B[2]), T.sdf(C[0], C[1], C[2])];
|
|
2977
|
+
const ins = (d[0] < 0 ? 1 : 0) + (d[1] < 0 ? 1 : 0) + (d[2] < 0 ? 1 : 0);
|
|
2978
|
+
if (ins === 0) next.push(t);
|
|
2979
|
+
else if (ins === 3) {
|
|
2980
|
+
if (rem) rem.push(t);
|
|
2981
|
+
} else {
|
|
2982
|
+
fan(clip(t, d, 1), next);
|
|
2983
|
+
if (rem) fan(clip(t, d, -1), rem);
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
const segments = [];
|
|
2987
|
+
let total = 0;
|
|
2988
|
+
const ti = tests.length === 1 && tests[0].bounds ? triIndexOf(geo) : void 0;
|
|
2989
|
+
if (ti) {
|
|
2990
|
+
const T = tests[0];
|
|
2991
|
+
const lo = T.bounds.lo;
|
|
2992
|
+
const hi = T.bounds.hi;
|
|
2775
2993
|
const rem = T.tag ? cut[T.tag] = cut[T.tag] || [] : null;
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
if (T.sel && !T.sel(n, ce)) {
|
|
2791
|
-
next.push(t);
|
|
2792
|
-
return;
|
|
2994
|
+
const boxes = ti.boxes;
|
|
2995
|
+
const blocks = ti.blocks;
|
|
2996
|
+
let runFrom = -1;
|
|
2997
|
+
const closeRun = function(end) {
|
|
2998
|
+
if (runFrom < 0) return;
|
|
2999
|
+
segments.push([runFrom, end]);
|
|
3000
|
+
total += end - runFrom;
|
|
3001
|
+
runFrom = -1;
|
|
3002
|
+
};
|
|
3003
|
+
for (let blk = 0, t0 = 0; t0 < ti.triangles; blk++, t0 += TRI_BLOCK) {
|
|
3004
|
+
const j = blk * 6;
|
|
3005
|
+
if (blocks[j + 3] < lo[0] || blocks[j] > hi[0] || blocks[j + 4] < lo[1] || blocks[j + 1] > hi[1] || blocks[j + 5] < lo[2] || blocks[j + 2] > hi[2]) {
|
|
3006
|
+
if (runFrom < 0) runFrom = t0;
|
|
3007
|
+
continue;
|
|
2793
3008
|
}
|
|
2794
|
-
const
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
3009
|
+
const t1 = Math.min(ti.triangles, t0 + TRI_BLOCK);
|
|
3010
|
+
for (let t = t0; t < t1; t++) {
|
|
3011
|
+
const q = t * 6;
|
|
3012
|
+
if (boxes[q + 3] < lo[0] || boxes[q] > hi[0] || boxes[q + 4] < lo[1] || boxes[q + 1] > hi[1] || boxes[q + 5] < lo[2] || boxes[q + 2] > hi[2]) {
|
|
3013
|
+
if (runFrom < 0) runFrom = t;
|
|
3014
|
+
continue;
|
|
3015
|
+
}
|
|
3016
|
+
closeRun(t);
|
|
3017
|
+
const next = [];
|
|
3018
|
+
testTri(T, readTri(t * 3), next, rem);
|
|
3019
|
+
if (next.length) {
|
|
3020
|
+
segments.push(next);
|
|
3021
|
+
total += next.length;
|
|
3022
|
+
}
|
|
2802
3023
|
}
|
|
3024
|
+
}
|
|
3025
|
+
closeRun(ti.triangles);
|
|
3026
|
+
} else {
|
|
3027
|
+
let tris = [];
|
|
3028
|
+
for (let f = 0; f < nv; f += 3) tris.push(readTri(f));
|
|
3029
|
+
tests.forEach(function(T) {
|
|
3030
|
+
const next = [];
|
|
3031
|
+
const rem = T.tag ? cut[T.tag] = cut[T.tag] || [] : null;
|
|
3032
|
+
tris.forEach(function(t) {
|
|
3033
|
+
testTri(T, t, next, rem);
|
|
3034
|
+
});
|
|
3035
|
+
tris = next;
|
|
2803
3036
|
});
|
|
2804
|
-
tris
|
|
2805
|
-
|
|
2806
|
-
|
|
3037
|
+
segments.push(tris);
|
|
3038
|
+
total = tris.length;
|
|
3039
|
+
}
|
|
3040
|
+
function fill(segs, count, boxesOut2) {
|
|
2807
3041
|
const g = new THREE.BufferGeometry();
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
3042
|
+
const dst = names.map(function(_nm, a) {
|
|
3043
|
+
return new Float32Array(count * 3 * sizes[a]);
|
|
3044
|
+
});
|
|
3045
|
+
const w = names.map(function() {
|
|
3046
|
+
return 0;
|
|
3047
|
+
});
|
|
3048
|
+
let wb = 0;
|
|
3049
|
+
segs.forEach(function(seg) {
|
|
3050
|
+
if (typeof seg[0] === "number") {
|
|
3051
|
+
for (let a = 0; a < names.length; a++) {
|
|
3052
|
+
const size = sizes[a];
|
|
3053
|
+
if (!idx) {
|
|
3054
|
+
dst[a].set(arrs[a].subarray(seg[0] * 3 * size, seg[1] * 3 * size), w[a]);
|
|
3055
|
+
w[a] += (seg[1] - seg[0]) * 3 * size;
|
|
3056
|
+
continue;
|
|
3057
|
+
}
|
|
3058
|
+
for (let f = seg[0] * 3; f < seg[1] * 3; f++) for (let q = 0; q < size; q++) dst[a][w[a]++] = arrs[a][idx[f] * size + q];
|
|
3059
|
+
}
|
|
3060
|
+
if (boxesOut2 && ti) {
|
|
3061
|
+
boxesOut2.set(ti.boxes.subarray(seg[0] * 6, seg[1] * 6), wb);
|
|
3062
|
+
wb += (seg[1] - seg[0]) * 6;
|
|
3063
|
+
}
|
|
3064
|
+
return;
|
|
3065
|
+
}
|
|
3066
|
+
seg.forEach(function(t) {
|
|
3067
|
+
if (boxesOut2) {
|
|
3068
|
+
for (let k = 0; k < 3; k++) {
|
|
3069
|
+
boxesOut2[wb + k] = Math.fround(Math.min(t[0][k], t[1][k], t[2][k]));
|
|
3070
|
+
boxesOut2[wb + 3 + k] = Math.fround(Math.max(t[0][k], t[1][k], t[2][k]));
|
|
3071
|
+
}
|
|
3072
|
+
wb += 6;
|
|
3073
|
+
}
|
|
3074
|
+
let off = 0;
|
|
3075
|
+
for (let a = 0; a < names.length; a++) {
|
|
3076
|
+
for (let k = 0; k < 3; k++) for (let q = 0; q < sizes[a]; q++) dst[a][w[a]++] = t[k][off + q];
|
|
3077
|
+
off += sizes[a];
|
|
3078
|
+
}
|
|
2814
3079
|
});
|
|
2815
|
-
|
|
2816
|
-
|
|
3080
|
+
});
|
|
3081
|
+
names.forEach(function(nm, a) {
|
|
3082
|
+
g.setAttribute(nm, new THREE.BufferAttribute(dst[a], sizes[a]));
|
|
2817
3083
|
});
|
|
2818
3084
|
g.userData.crease = true;
|
|
2819
3085
|
return g;
|
|
2820
3086
|
}
|
|
2821
|
-
const
|
|
3087
|
+
const boxesOut = ti ? new Float64Array(total * 6) : void 0;
|
|
3088
|
+
const out = { geo: fill(segments, total, boxesOut), cut: {}, tasks: {} };
|
|
3089
|
+
if (boxesOut) storeTriIndex(out.geo, boxesOut);
|
|
2822
3090
|
Object.keys(cut).forEach(function(k) {
|
|
2823
|
-
|
|
3091
|
+
const piece = fill([cut[k]], cut[k].length);
|
|
3092
|
+
const mode = tests.find(function(T) {
|
|
3093
|
+
return T.tag === k;
|
|
3094
|
+
}).pieces;
|
|
3095
|
+
if (mode === "none") out.cut[k] = piece;
|
|
3096
|
+
else if (mode === "later") {
|
|
3097
|
+
out.cut[k] = piece;
|
|
3098
|
+
out.tasks[k] = creaseTask(piece, 42);
|
|
3099
|
+
} else out.cut[k] = crease(piece, 42);
|
|
2824
3100
|
});
|
|
2825
3101
|
return out;
|
|
2826
3102
|
}
|
|
3103
|
+
function refreshBounds(geo) {
|
|
3104
|
+
const found = boundsFromIndex(geo);
|
|
3105
|
+
if (!found) {
|
|
3106
|
+
geo.computeBoundingSphere();
|
|
3107
|
+
geo.computeBoundingBox();
|
|
3108
|
+
return;
|
|
3109
|
+
}
|
|
3110
|
+
if (geo.boundingBox && geo.boundingSphere && boundsDone.get(geo) === found.version) return;
|
|
3111
|
+
const b = found.box;
|
|
3112
|
+
if (!geo.boundingBox) geo.boundingBox = new THREE.Box3();
|
|
3113
|
+
geo.boundingBox.min.set(b[0], b[1], b[2]);
|
|
3114
|
+
geo.boundingBox.max.set(b[3], b[4], b[5]);
|
|
3115
|
+
if (!geo.boundingSphere) geo.boundingSphere = new THREE.Sphere();
|
|
3116
|
+
const center = geo.boundingBox.getCenter(geo.boundingSphere.center);
|
|
3117
|
+
const P = geo.attributes.position.array;
|
|
3118
|
+
let maxRadiusSq = 0;
|
|
3119
|
+
for (let i = 0; i < P.length; i += 3) {
|
|
3120
|
+
const dx = center.x - P[i];
|
|
3121
|
+
const dy = center.y - P[i + 1];
|
|
3122
|
+
const dz = center.z - P[i + 2];
|
|
3123
|
+
maxRadiusSq = Math.max(maxRadiusSq, dx * dx + dy * dy + dz * dz);
|
|
3124
|
+
}
|
|
3125
|
+
geo.boundingSphere.radius = Math.sqrt(maxRadiusSq);
|
|
3126
|
+
boundsDone.set(geo, found.version);
|
|
3127
|
+
}
|
|
3128
|
+
const boundsDone = /* @__PURE__ */ new WeakMap();
|
|
2827
3129
|
function mergeGeometries(list2) {
|
|
2828
3130
|
const pos = [];
|
|
2829
3131
|
const nor = [];
|
|
@@ -2954,7 +3256,7 @@ var GameVehicles = (() => {
|
|
|
2954
3256
|
}
|
|
2955
3257
|
};
|
|
2956
3258
|
};
|
|
2957
|
-
Object.assign(I, { roundedBoxGeometry, taper, subdivide, crease, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject });
|
|
3259
|
+
Object.assign(I, { roundedBoxGeometry, taper, subdivide, crease, creaseTask, refreshBounds, pathShape, tumble, loftGeometry, hullGeometry, cutGeometry, mergeGeometries, uvProject });
|
|
2958
3260
|
}
|
|
2959
3261
|
|
|
2960
3262
|
// ../game-contracts/dist/index.js
|
|
@@ -6359,8 +6661,15 @@ var GameVehicles = (() => {
|
|
|
6359
6661
|
x.arc(cx, cy, 26 * s, 0, PI * 2);
|
|
6360
6662
|
x.fill();
|
|
6361
6663
|
}
|
|
6664
|
+
const NO_CANVAS = new Proxy(function() {
|
|
6665
|
+
}, { get: () => NO_CANVAS, apply: () => NO_CANVAS, set: () => true });
|
|
6362
6666
|
function crackGlass(c, msh, p, force, sc) {
|
|
6363
6667
|
const G = msh.userData.glass;
|
|
6668
|
+
if (G.cracksFreed) {
|
|
6669
|
+
drawWeb(NO_CANVAS, 0, 0, sc != null ? sc : 0.6 + force * 0.5, Math.max(0.4, G.aspect || 1), c.rand);
|
|
6670
|
+
G.hits++;
|
|
6671
|
+
return;
|
|
6672
|
+
}
|
|
6364
6673
|
if (!G.cv) {
|
|
6365
6674
|
G.cv = document2.createElement("canvas");
|
|
6366
6675
|
G.cv.width = G.cv.height = 256;
|
|
@@ -6443,6 +6752,14 @@ var GameVehicles = (() => {
|
|
|
6443
6752
|
const G = msh.userData.glass;
|
|
6444
6753
|
if (G.broken) return;
|
|
6445
6754
|
G.broken = true;
|
|
6755
|
+
const freeCracks = function() {
|
|
6756
|
+
if (!G.tex) return;
|
|
6757
|
+
if (msh.material !== MATERIALS.glassEdge && msh.material?.map === G.tex) msh.material.dispose();
|
|
6758
|
+
G.tex.dispose();
|
|
6759
|
+
G.tex = null;
|
|
6760
|
+
G.cv = null;
|
|
6761
|
+
G.cracksFreed = true;
|
|
6762
|
+
};
|
|
6446
6763
|
const cubesAt = [];
|
|
6447
6764
|
if (G.outline && G.T !== void 0) {
|
|
6448
6765
|
const out = G.outline;
|
|
@@ -6476,6 +6793,7 @@ var GameVehicles = (() => {
|
|
|
6476
6793
|
geo.computeVertexNormals();
|
|
6477
6794
|
msh.geometry.dispose();
|
|
6478
6795
|
msh.geometry = geo;
|
|
6796
|
+
freeCracks();
|
|
6479
6797
|
msh.material = MATERIALS.glassEdge;
|
|
6480
6798
|
let minx = 1e9;
|
|
6481
6799
|
let maxx = -1e9;
|
|
@@ -6499,8 +6817,12 @@ var GameVehicles = (() => {
|
|
|
6499
6817
|
if (rim) {
|
|
6500
6818
|
msh.geometry.dispose();
|
|
6501
6819
|
msh.geometry = rim;
|
|
6820
|
+
freeCracks();
|
|
6502
6821
|
msh.material = MATERIALS.glassEdge;
|
|
6503
|
-
} else
|
|
6822
|
+
} else {
|
|
6823
|
+
freeCracks();
|
|
6824
|
+
msh.visible = false;
|
|
6825
|
+
}
|
|
6504
6826
|
for (let j = 0; j < 36; j++)
|
|
6505
6827
|
cubesAt.push(
|
|
6506
6828
|
new V3(
|
|
@@ -8335,6 +8657,8 @@ var GameVehicles = (() => {
|
|
|
8335
8657
|
const pos = g && g.attributes && g.attributes.position;
|
|
8336
8658
|
return o.raycast === THREE.Mesh.prototype.raycast && !o.isSkinnedMesh && !Array.isArray(o.material) && pos && !pos.isInterleavedBufferAttribute && pos.itemSize === 3 && !g.groups.length && !(g.morphAttributes && g.morphAttributes.position) && (g.index ? g.index.count : pos.count) / 3 >= PROXY_MIN_TRIANGLES;
|
|
8337
8659
|
}
|
|
8660
|
+
let _keep = new Uint32Array(0);
|
|
8661
|
+
let _box = new Float32Array(0);
|
|
8338
8662
|
function proxyIn(o, Mw, R) {
|
|
8339
8663
|
_pm.copy(o.matrixWorld).invert().multiply(Mw);
|
|
8340
8664
|
const lo = [Infinity, Infinity, Infinity];
|
|
@@ -8347,39 +8671,48 @@ var GameVehicles = (() => {
|
|
|
8347
8671
|
}
|
|
8348
8672
|
}
|
|
8349
8673
|
const g = o.geometry;
|
|
8350
|
-
const
|
|
8674
|
+
const ti = triIndexOf(g);
|
|
8675
|
+
if (!ti) return null;
|
|
8351
8676
|
const ix = g.index ? g.index.array : null;
|
|
8352
|
-
const
|
|
8353
|
-
const
|
|
8677
|
+
const boxes = ti.boxes;
|
|
8678
|
+
const blocks = ti.blocks;
|
|
8679
|
+
if (_keep.length < ti.triangles * 3) {
|
|
8680
|
+
_keep = new Uint32Array(ti.triangles * 3);
|
|
8681
|
+
_box = new Float32Array(ti.triangles * 6);
|
|
8682
|
+
}
|
|
8683
|
+
const keep = _keep;
|
|
8684
|
+
const box2 = _box;
|
|
8354
8685
|
let nk = 0;
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
const
|
|
8358
|
-
|
|
8359
|
-
|
|
8360
|
-
for (let
|
|
8361
|
-
const
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
keep[nk++] = ix ? ix[t + 1] : t + 1;
|
|
8369
|
-
keep[nk++] = ix ? ix[t + 2] : t + 2;
|
|
8686
|
+
let nt = 0;
|
|
8687
|
+
for (let blk = 0, t0 = 0; t0 < ti.triangles; blk++, t0 += TRI_BLOCK) {
|
|
8688
|
+
const j = blk * 6;
|
|
8689
|
+
if (blocks[j + 3] < lo[0] || blocks[j] > hi[0] || blocks[j + 4] < lo[1] || blocks[j + 1] > hi[1] || blocks[j + 5] < lo[2] || blocks[j + 2] > hi[2]) continue;
|
|
8690
|
+
const t1 = Math.min(ti.triangles, t0 + TRI_BLOCK);
|
|
8691
|
+
for (let t = t0; t < t1; t++) {
|
|
8692
|
+
const q = t * 6;
|
|
8693
|
+
if (boxes[q + 3] < lo[0] || boxes[q] > hi[0] || boxes[q + 4] < lo[1] || boxes[q + 1] > hi[1] || boxes[q + 5] < lo[2] || boxes[q + 2] > hi[2]) continue;
|
|
8694
|
+
keep[nk++] = ix ? ix[t * 3] : t * 3;
|
|
8695
|
+
keep[nk++] = ix ? ix[t * 3 + 1] : t * 3 + 1;
|
|
8696
|
+
keep[nk++] = ix ? ix[t * 3 + 2] : t * 3 + 2;
|
|
8697
|
+
for (let k = 0; k < 6; k++) box2[nt * 6 + k] = boxes[q + k];
|
|
8698
|
+
nt++;
|
|
8370
8699
|
}
|
|
8371
8700
|
}
|
|
8372
8701
|
if (!nk) return null;
|
|
8373
8702
|
const kept = keep.slice(0, nk);
|
|
8374
|
-
const
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
const b =
|
|
8378
|
-
const d = kept[t + 2] * 3;
|
|
8703
|
+
const keptBox = box2.slice(0, nt * 6);
|
|
8704
|
+
const keptBlocks = new Float32Array(Math.ceil(nt / TRI_BLOCK) * 6);
|
|
8705
|
+
for (let blk = 0; blk * TRI_BLOCK < nt; blk++) {
|
|
8706
|
+
const b = blk * 6;
|
|
8379
8707
|
for (let k = 0; k < 3; k++) {
|
|
8380
|
-
|
|
8381
|
-
|
|
8708
|
+
keptBlocks[b + k] = Infinity;
|
|
8709
|
+
keptBlocks[b + 3 + k] = -Infinity;
|
|
8382
8710
|
}
|
|
8711
|
+
for (let t = blk * TRI_BLOCK, t1 = Math.min(nt, t + TRI_BLOCK); t < t1; t++)
|
|
8712
|
+
for (let k = 0; k < 3; k++) {
|
|
8713
|
+
if (keptBox[t * 6 + k] < keptBlocks[b + k]) keptBlocks[b + k] = keptBox[t * 6 + k];
|
|
8714
|
+
if (keptBox[t * 6 + 3 + k] > keptBlocks[b + 3 + k]) keptBlocks[b + 3 + k] = keptBox[t * 6 + 3 + k];
|
|
8715
|
+
}
|
|
8383
8716
|
}
|
|
8384
8717
|
const pg = new THREE.BufferGeometry();
|
|
8385
8718
|
pg.setAttribute("position", g.attributes.position);
|
|
@@ -8390,7 +8723,8 @@ var GameVehicles = (() => {
|
|
|
8390
8723
|
proxy.layers.mask = o.layers.mask;
|
|
8391
8724
|
proxy.proxyOf = o;
|
|
8392
8725
|
proxy.kept = kept;
|
|
8393
|
-
proxy.keptBox =
|
|
8726
|
+
proxy.keptBox = keptBox;
|
|
8727
|
+
proxy.keptBlocks = keptBlocks;
|
|
8394
8728
|
return proxy;
|
|
8395
8729
|
}
|
|
8396
8730
|
function narrowTo(rc, proxy) {
|
|
@@ -8410,13 +8744,21 @@ var GameVehicles = (() => {
|
|
|
8410
8744
|
const hi2 = Math.max(z0, _pv.z) + 1e-4;
|
|
8411
8745
|
const K = proxy.kept;
|
|
8412
8746
|
const X = proxy.keptBox;
|
|
8747
|
+
const KB = proxy.keptBlocks;
|
|
8748
|
+
const nt = K.length / 3;
|
|
8413
8749
|
const dst = proxy.geometry.index.array;
|
|
8414
8750
|
let m = 0;
|
|
8415
|
-
for (let
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8751
|
+
for (let blk = 0, t0 = 0; t0 < nt; blk++, t0 += TRI_BLOCK) {
|
|
8752
|
+
const b = blk * 6;
|
|
8753
|
+
if (KB[b + 3] < lo0 || KB[b] > hi0 || KB[b + 4] < lo1 || KB[b + 1] > hi1 || KB[b + 5] < lo2 || KB[b + 2] > hi2) continue;
|
|
8754
|
+
const t1 = Math.min(nt, t0 + TRI_BLOCK);
|
|
8755
|
+
for (let t = t0; t < t1; t++) {
|
|
8756
|
+
const j = t * 6;
|
|
8757
|
+
if (X[j + 3] < lo0 || X[j] > hi0 || X[j + 4] < lo1 || X[j + 1] > hi1 || X[j + 5] < lo2 || X[j + 2] > hi2) continue;
|
|
8758
|
+
dst[m++] = K[t * 3];
|
|
8759
|
+
dst[m++] = K[t * 3 + 1];
|
|
8760
|
+
dst[m++] = K[t * 3 + 2];
|
|
8761
|
+
}
|
|
8420
8762
|
}
|
|
8421
8763
|
proxy.geometry.setDrawRange(0, m);
|
|
8422
8764
|
}
|
|
@@ -8834,6 +9176,8 @@ var GameVehicles = (() => {
|
|
|
8834
9176
|
irel.copy(rel).invert();
|
|
8835
9177
|
const pos = g.attributes.position;
|
|
8836
9178
|
let changed = false;
|
|
9179
|
+
const liveIndex = liveTriIndex(g);
|
|
9180
|
+
const movedVertices = [];
|
|
8837
9181
|
const near = boxInFrame(B, irel, v);
|
|
8838
9182
|
for (let i = 0; i < pos.count; i++) {
|
|
8839
9183
|
v.fromBufferAttribute(pos, i);
|
|
@@ -8845,6 +9189,7 @@ var GameVehicles = (() => {
|
|
|
8845
9189
|
if (opt.extra) opt.extra(v, f);
|
|
8846
9190
|
v.applyMatrix4(irel);
|
|
8847
9191
|
pos.setXYZ(i, v.x, v.y, v.z);
|
|
9192
|
+
movedVertices.push(i);
|
|
8848
9193
|
changed = true;
|
|
8849
9194
|
}
|
|
8850
9195
|
if (opt.extraAll) {
|
|
@@ -8853,12 +9198,14 @@ var GameVehicles = (() => {
|
|
|
8853
9198
|
if (opt.extraAll(v)) {
|
|
8854
9199
|
v.applyMatrix4(irel);
|
|
8855
9200
|
pos.setXYZ(j, v.x, v.y, v.z);
|
|
9201
|
+
movedVertices.push(j);
|
|
8856
9202
|
changed = true;
|
|
8857
9203
|
}
|
|
8858
9204
|
}
|
|
8859
9205
|
}
|
|
8860
9206
|
if (changed) {
|
|
8861
9207
|
pos.needsUpdate = true;
|
|
9208
|
+
if (liveIndex) touchTriIndex(g, liveIndex, movedVertices);
|
|
8862
9209
|
dirty.add(msh);
|
|
8863
9210
|
}
|
|
8864
9211
|
if (changed || boundsDue) {
|
|
@@ -8889,6 +9236,26 @@ var GameVehicles = (() => {
|
|
|
8889
9236
|
});
|
|
8890
9237
|
return { field, moved, ax, a, cu, cv, hu, hv, outer };
|
|
8891
9238
|
}
|
|
9239
|
+
function panelBoundsIn(rel, rect, B, a, ax) {
|
|
9240
|
+
const det = rel.determinant();
|
|
9241
|
+
if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return void 0;
|
|
9242
|
+
const back = rel.clone().invert();
|
|
9243
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
9244
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
9245
|
+
const q = new V3();
|
|
9246
|
+
for (let i = 0; i < 8; i++) {
|
|
9247
|
+
q.setComponent(ax[0], i & 1 ? rect[1] : rect[0]);
|
|
9248
|
+
q.setComponent(ax[1], i & 2 ? rect[3] : rect[2]);
|
|
9249
|
+
q.setComponent(a, i & 4 ? I.boxHi(B, a) : I.boxLo(B, a));
|
|
9250
|
+
q.applyMatrix4(back);
|
|
9251
|
+
for (let k = 0; k < 3; k++) {
|
|
9252
|
+
lo[k] = Math.min(lo[k], q.getComponent(k));
|
|
9253
|
+
hi[k] = Math.max(hi[k], q.getComponent(k));
|
|
9254
|
+
}
|
|
9255
|
+
}
|
|
9256
|
+
const pad = 1e-3;
|
|
9257
|
+
return { lo: lo.map((x) => x - pad), hi: hi.map((x) => x + pad) };
|
|
9258
|
+
}
|
|
8892
9259
|
function cutPanel(c, z, rect, keep, dirty, o) {
|
|
8893
9260
|
o = o || {};
|
|
8894
9261
|
const B = z.box;
|
|
@@ -8921,6 +9288,7 @@ var GameVehicles = (() => {
|
|
|
8921
9288
|
}
|
|
8922
9289
|
const test = {
|
|
8923
9290
|
tag: "part",
|
|
9291
|
+
pieces: keep ? o.pieceTasks ? "later" : "crease" : "none",
|
|
8924
9292
|
sel: o.anyN || z.cutAll ? null : function(n) {
|
|
8925
9293
|
nv.copy(n).applyMatrix3(nm).normalize();
|
|
8926
9294
|
return nv.dot(outN) > 0.3;
|
|
@@ -8939,13 +9307,12 @@ var GameVehicles = (() => {
|
|
|
8939
9307
|
return q;
|
|
8940
9308
|
}
|
|
8941
9309
|
};
|
|
8942
|
-
const r = cutGeometry(g, [test]);
|
|
9310
|
+
const r = cutGeometry(g, [{ ...test, bounds: panelBoundsIn(rel, rect, B, a, ax) }]);
|
|
8943
9311
|
const cg = r.cut.part;
|
|
8944
9312
|
if (!cg || !cg.attributes.position.count) return;
|
|
8945
9313
|
g.dispose();
|
|
8946
9314
|
msh.geometry = r.geo;
|
|
8947
|
-
r.geo
|
|
8948
|
-
r.geo.computeBoundingBox();
|
|
9315
|
+
I.refreshBounds(r.geo);
|
|
8949
9316
|
dirty.add(msh);
|
|
8950
9317
|
if (!keep) {
|
|
8951
9318
|
cg.dispose();
|
|
@@ -8958,6 +9325,7 @@ var GameVehicles = (() => {
|
|
|
8958
9325
|
rel.decompose(pm.position, pm.quaternion, pm.scale);
|
|
8959
9326
|
c.vehicle.add(pm);
|
|
8960
9327
|
pm.updateMatrixWorld(true);
|
|
9328
|
+
if (o.pieceTasks) o.pieceTasks.set(pm, r.tasks.part);
|
|
8961
9329
|
pieces.push({ mesh: pm, cut: true });
|
|
8962
9330
|
});
|
|
8963
9331
|
return pieces;
|
|
@@ -12594,7 +12962,15 @@ var GameVehicles = (() => {
|
|
|
12594
12962
|
__publicField(this, "gone", /* @__PURE__ */ new Set());
|
|
12595
12963
|
/** Shows or hides the plate and the recess of a door or lid by its state (see `showWhenOpen`). */
|
|
12596
12964
|
__publicField(this, "syncPlates", /* @__PURE__ */ new Map());
|
|
12965
|
+
/** Doors and lids whose own skin was cut from the body and hung on the hinge (true), or that had none to take and keep the plate (false). */
|
|
12966
|
+
__publicField(this, "skins", /* @__PURE__ */ new Map());
|
|
12597
12967
|
__publicField(this, "lightsOn", true);
|
|
12968
|
+
/** Heavy body meshes whose triangle index is still to build (null once done). */
|
|
12969
|
+
__publicField(this, "warming");
|
|
12970
|
+
/** A panel was torn off since the last `pump`: that frame already paid for the cut, the smoothing starts on the next one. */
|
|
12971
|
+
__publicField(this, "tornThisFrame", false);
|
|
12972
|
+
/** Normal smoothing still running, by mesh: a mesh cut again gets a new task and the old one is dropped. */
|
|
12973
|
+
__publicField(this, "smoothing", /* @__PURE__ */ new Map());
|
|
12598
12974
|
__publicField(this, "hood");
|
|
12599
12975
|
this.kit = kit;
|
|
12600
12976
|
this.c = c;
|
|
@@ -12604,6 +12980,8 @@ var GameVehicles = (() => {
|
|
|
12604
12980
|
for (const p of model.parts) this.byId.set(p.id, p);
|
|
12605
12981
|
c.root.updateMatrixWorld(true);
|
|
12606
12982
|
this.hood = this.nameHood();
|
|
12983
|
+
this.warming = c.deform.filter((msh) => msh.geometry && msh.geometry.attributes.position && msh.geometry.attributes.position.count >= 1500);
|
|
12984
|
+
if (!this.warming.length) this.warming = null;
|
|
12607
12985
|
for (const p of model.parts) {
|
|
12608
12986
|
if (p.role === "door" || p.role === "lid") this.makePlate(p);
|
|
12609
12987
|
else if (p.role === "mirror" && !this.mirrorObjects(p).length) this.makeMirror(p);
|
|
@@ -12739,11 +13117,21 @@ var GameVehicles = (() => {
|
|
|
12739
13117
|
* keeps the shape of its model instead of flat panels over its curved sides. Follows the hinge's rotation, whoever turns it (the clips of a host, `detach`).
|
|
12740
13118
|
*/
|
|
12741
13119
|
showWhenOpen(id, piv, panel, recess) {
|
|
13120
|
+
let busy = false;
|
|
12742
13121
|
const sync = () => {
|
|
13122
|
+
if (busy) return;
|
|
12743
13123
|
const r = piv.rotation;
|
|
12744
13124
|
const open = Math.abs(r.x) + Math.abs(r.y) + Math.abs(r.z) > 1e-3 || this.gone.has(id) || piv.parent !== this.c.vehicle;
|
|
12745
|
-
|
|
12746
|
-
|
|
13125
|
+
if (open && !this.gone.has(id) && piv.parent === this.c.vehicle && !this.skins.has(id)) {
|
|
13126
|
+
busy = true;
|
|
13127
|
+
try {
|
|
13128
|
+
this.skins.set(id, this.takeSkin(id, piv));
|
|
13129
|
+
} finally {
|
|
13130
|
+
busy = false;
|
|
13131
|
+
}
|
|
13132
|
+
}
|
|
13133
|
+
panel.visible = open && !this.skins.get(id);
|
|
13134
|
+
recess.visible = open && !this.skins.get(id);
|
|
12747
13135
|
};
|
|
12748
13136
|
const euler = piv.rotation;
|
|
12749
13137
|
const quaternion = piv.quaternion;
|
|
@@ -12760,6 +13148,58 @@ var GameVehicles = (() => {
|
|
|
12760
13148
|
this.syncPlates.set(id, sync);
|
|
12761
13149
|
sync();
|
|
12762
13150
|
}
|
|
13151
|
+
/**
|
|
13152
|
+
* Cuts the skin of a door or lid zone out of the body (as the damage's hanging door does) and hangs it, with the thin parts on it (trim, handle) and, for a door, the side
|
|
13153
|
+
* window over it, on the hinge. Done with the hinge closed, so every piece keeps its place; answers whether there was skin to take.
|
|
13154
|
+
*/
|
|
13155
|
+
takeSkin(id, piv) {
|
|
13156
|
+
const p = this.byId.get(id);
|
|
13157
|
+
const z = p && this.zone(p);
|
|
13158
|
+
if (!p || !z) return false;
|
|
13159
|
+
const I = this.I;
|
|
13160
|
+
const B = z.box;
|
|
13161
|
+
const q = piv.quaternion.clone();
|
|
13162
|
+
piv.quaternion.identity();
|
|
13163
|
+
this.c.root.updateMatrixWorld(true);
|
|
13164
|
+
const inv = I.worldInverseOf(this.c);
|
|
13165
|
+
let objs = [];
|
|
13166
|
+
try {
|
|
13167
|
+
if (p.role === "door") {
|
|
13168
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
13169
|
+
const rect = [B.x0 + 0.03, B.x1 - 0.03, B.y0 + Math.min(0.08, (B.y1 - B.y0) * 0.1), B.y1 - 0.02];
|
|
13170
|
+
const pcs = I.cutPanel(this.c, z, rect, true, dirty).map((x) => x.mesh).filter((m) => !!m);
|
|
13171
|
+
this.mend(dirty);
|
|
13172
|
+
if (pcs.length) objs = [...pcs, ...I.followersIn(this.c, z, inv), ...I.windowsOver(this.c, z, inv)];
|
|
13173
|
+
} else {
|
|
13174
|
+
const pcs = this.cutZone(z);
|
|
13175
|
+
if (pcs.length) objs = [...pcs, ...I.followersIn(this.c, z, inv)];
|
|
13176
|
+
}
|
|
13177
|
+
} catch {
|
|
13178
|
+
objs = [];
|
|
13179
|
+
}
|
|
13180
|
+
const deform = this.c.deform ?? [];
|
|
13181
|
+
for (const o of objs) {
|
|
13182
|
+
if (!o.parent || o === piv) continue;
|
|
13183
|
+
piv.attach(o);
|
|
13184
|
+
o.traverse((x) => {
|
|
13185
|
+
x.userData.noFollow = true;
|
|
13186
|
+
});
|
|
13187
|
+
const di = deform.indexOf(o);
|
|
13188
|
+
if (di >= 0) deform.splice(di, 1);
|
|
13189
|
+
}
|
|
13190
|
+
piv.quaternion.copy(q);
|
|
13191
|
+
this.c.root.updateMatrixWorld(true);
|
|
13192
|
+
return objs.length > 0;
|
|
13193
|
+
}
|
|
13194
|
+
mend(dirty) {
|
|
13195
|
+
dirty.forEach((msh) => {
|
|
13196
|
+
const g = msh.geometry;
|
|
13197
|
+
if (g.userData.crease || !g.index) this.I.crease(g, 42);
|
|
13198
|
+
else g.computeVertexNormals();
|
|
13199
|
+
g.computeBoundingSphere();
|
|
13200
|
+
g.computeBoundingBox();
|
|
13201
|
+
});
|
|
13202
|
+
}
|
|
12763
13203
|
makeMirror(p) {
|
|
12764
13204
|
const [cx, cy, cz] = p.box.center;
|
|
12765
13205
|
const s = cz < 0 ? -1 : 1;
|
|
@@ -12897,6 +13337,31 @@ var GameVehicles = (() => {
|
|
|
12897
13337
|
this.I.flattenTire(w, Math.min(0.5, 0.12 + 0.38 * melt));
|
|
12898
13338
|
}
|
|
12899
13339
|
}
|
|
13340
|
+
/** Smooths the normals of a cut mesh a slice per frame (see `pump`); until then it draws with flat face normals. */
|
|
13341
|
+
smoothLater(msh) {
|
|
13342
|
+
this.smoothing.set(msh, this.I.creaseTask(msh.geometry, 42));
|
|
13343
|
+
this.tornThisFrame = true;
|
|
13344
|
+
}
|
|
13345
|
+
/** Spends at most `budgetMs` finishing the pending normal smoothing. Call once per frame. */
|
|
13346
|
+
pump(budgetMs = 2.5) {
|
|
13347
|
+
if (this.tornThisFrame) {
|
|
13348
|
+
this.tornThisFrame = false;
|
|
13349
|
+
return;
|
|
13350
|
+
}
|
|
13351
|
+
if (!this.smoothing.size && !this.warming) return;
|
|
13352
|
+
const deadline = performance.now() + budgetMs;
|
|
13353
|
+
for (const [msh, task] of this.smoothing) {
|
|
13354
|
+
if (msh.geometry !== task.geo || task.step(deadline)) this.smoothing.delete(msh);
|
|
13355
|
+
if (performance.now() >= deadline) return;
|
|
13356
|
+
}
|
|
13357
|
+
this.warmIndexes(deadline);
|
|
13358
|
+
}
|
|
13359
|
+
/** Measures the triangles of the heavy body meshes once, a slice per frame, so the first panel torn off finds them ready (see `triIndexOf`). */
|
|
13360
|
+
warmIndexes(deadline) {
|
|
13361
|
+
if (!this.warming) return;
|
|
13362
|
+
this.warming = this.warming.filter((msh) => !warmTriIndex(msh.geometry, deadline));
|
|
13363
|
+
if (!this.warming.length) this.warming = null;
|
|
13364
|
+
}
|
|
12900
13365
|
/** Moves the panel of a lost zone out of the body (the kit's torn-off look). */
|
|
12901
13366
|
tearOff(p) {
|
|
12902
13367
|
const z = this.zone(p);
|
|
@@ -12909,10 +13374,9 @@ var GameVehicles = (() => {
|
|
|
12909
13374
|
}
|
|
12910
13375
|
dirty.forEach((msh) => {
|
|
12911
13376
|
const g = msh.geometry;
|
|
12912
|
-
if (g.userData.crease || !g.index) this.
|
|
13377
|
+
if (g.userData.crease || !g.index) this.smoothLater(msh);
|
|
12913
13378
|
else g.computeVertexNormals();
|
|
12914
|
-
|
|
12915
|
-
g.computeBoundingBox();
|
|
13379
|
+
this.I.refreshBounds(g);
|
|
12916
13380
|
});
|
|
12917
13381
|
this.gone.add(p.id);
|
|
12918
13382
|
}
|
|
@@ -13055,17 +13519,19 @@ var GameVehicles = (() => {
|
|
|
13055
13519
|
const mg = Math.min(0.05, (u1 - u0) * 0.08, (v1 - v0) * 0.08);
|
|
13056
13520
|
const dirty = /* @__PURE__ */ new Set();
|
|
13057
13521
|
let pcs = [];
|
|
13522
|
+
const pieceTasks = /* @__PURE__ */ new Map();
|
|
13058
13523
|
try {
|
|
13059
|
-
pcs = I.cutPanel(this.c, z, [u0 + mg, u1 - mg, v0 + mg, v1 - mg], true, dirty);
|
|
13524
|
+
pcs = I.cutPanel(this.c, z, [u0 + mg, u1 - mg, v0 + mg, v1 - mg], true, dirty, { pieceTasks });
|
|
13060
13525
|
} catch {
|
|
13061
13526
|
pcs = [];
|
|
13062
13527
|
}
|
|
13528
|
+
pieceTasks.forEach((task, mesh2) => this.smoothing.set(mesh2, task));
|
|
13529
|
+
this.tornThisFrame = true;
|
|
13063
13530
|
dirty.forEach((msh) => {
|
|
13064
13531
|
const g = msh.geometry;
|
|
13065
|
-
if (g.userData.crease || !g.index)
|
|
13532
|
+
if (g.userData.crease || !g.index) this.smoothLater(msh);
|
|
13066
13533
|
else g.computeVertexNormals();
|
|
13067
|
-
|
|
13068
|
-
g.computeBoundingBox();
|
|
13534
|
+
I.refreshBounds(g);
|
|
13069
13535
|
});
|
|
13070
13536
|
return pcs.map((q) => q.mesh).filter((m) => !!m);
|
|
13071
13537
|
}
|
|
@@ -13844,7 +14310,7 @@ var GameVehicles = (() => {
|
|
|
13844
14310
|
specCache = { name: options.name ?? c.spec.name ?? c.key, parts, joints, tags: ["vehicle", kindOf(c)] };
|
|
13845
14311
|
return specCache;
|
|
13846
14312
|
};
|
|
13847
|
-
const
|
|
14313
|
+
const buildState = () => {
|
|
13848
14314
|
const parts = model.parts.map((d) => {
|
|
13849
14315
|
const p = ps.get(d.id);
|
|
13850
14316
|
const marked = p.dents.length > 0 || p.holes.length > 0 || p.cracks.length > 0;
|
|
@@ -13881,7 +14347,15 @@ var GameVehicles = (() => {
|
|
|
13881
14347
|
}));
|
|
13882
14348
|
return { id, name: options.name ?? c.spec.name ?? c.key, position: [0, 0, 0], rotation: [0, 0, 0, 1], parts, joints, groups: groupsCache.map((g) => [...g]), destroyed: parts.every((p) => p.status === "broken" || p.status === "melted" || p.status === "ashes") };
|
|
13883
14349
|
};
|
|
14350
|
+
let stateCache;
|
|
14351
|
+
const state = () => stateCache ?? (stateCache = buildState());
|
|
14352
|
+
const isSimulating = () => {
|
|
14353
|
+
if (leaks.size > 0) return true;
|
|
14354
|
+
for (const p of ps.values()) if (!p.lost && (p.burning || p.temp > AMBIENT)) return true;
|
|
14355
|
+
return false;
|
|
14356
|
+
};
|
|
13884
14357
|
const hit = (h) => {
|
|
14358
|
+
stateCache = void 0;
|
|
13885
14359
|
const out = [];
|
|
13886
14360
|
const hh = h.space === "local" ? { ...h, space: "world", point: toWorld(h.point) } : h;
|
|
13887
14361
|
if (hh.space === "local" || !hh.point) return out;
|
|
@@ -13908,6 +14382,8 @@ var GameVehicles = (() => {
|
|
|
13908
14382
|
clock += dt;
|
|
13909
14383
|
const out = queue;
|
|
13910
14384
|
queue = [];
|
|
14385
|
+
const wasSimulating = isSimulating();
|
|
14386
|
+
const handledBefore = (blastHandled ? 1 : 0) + (rollHandled ? 2 : 0);
|
|
13911
14387
|
const hood = c.hood;
|
|
13912
14388
|
if (hood) {
|
|
13913
14389
|
const sign2 = hood.sign || 1;
|
|
@@ -13928,12 +14404,15 @@ var GameVehicles = (() => {
|
|
|
13928
14404
|
afterBlast(out);
|
|
13929
14405
|
afterRoll(out);
|
|
13930
14406
|
applyEffects();
|
|
14407
|
+
vis?.pump();
|
|
14408
|
+
if (wasSimulating || out.length > 0 || handledBefore !== (blastHandled ? 1 : 0) + (rollHandled ? 2 : 0)) stateCache = void 0;
|
|
13931
14409
|
return out;
|
|
13932
14410
|
};
|
|
13933
14411
|
const disassemble = (jointId, tool, dt) => {
|
|
13934
14412
|
const j = js.find((x) => x.def.id === jointId);
|
|
13935
14413
|
if (!j || !j.def.tools.includes(tool)) return -1;
|
|
13936
14414
|
if (j.open) return 1;
|
|
14415
|
+
stateCache = void 0;
|
|
13937
14416
|
j.progress = Math.min(1, j.progress + dt / j.def.seconds);
|
|
13938
14417
|
const step = Math.floor(j.progress * 4) / 4;
|
|
13939
14418
|
if (step > j.reported && j.progress < 1) {
|
|
@@ -13949,6 +14428,7 @@ var GameVehicles = (() => {
|
|
|
13949
14428
|
return j.progress;
|
|
13950
14429
|
};
|
|
13951
14430
|
const extinguish = (partId) => {
|
|
14431
|
+
stateCache = void 0;
|
|
13952
14432
|
for (const p of ps.values()) {
|
|
13953
14433
|
if (partId && p.def.id !== partId) continue;
|
|
13954
14434
|
if (p.burning) {
|
|
@@ -13962,6 +14442,7 @@ var GameVehicles = (() => {
|
|
|
13962
14442
|
}
|
|
13963
14443
|
};
|
|
13964
14444
|
const reset = () => {
|
|
14445
|
+
stateCache = void 0;
|
|
13965
14446
|
const old = c;
|
|
13966
14447
|
const parent = old.root.parent;
|
|
13967
14448
|
const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
|
|
@@ -13979,6 +14460,7 @@ var GameVehicles = (() => {
|
|
|
13979
14460
|
setup();
|
|
13980
14461
|
};
|
|
13981
14462
|
const rollover = (side2 = 1) => {
|
|
14463
|
+
stateCache = void 0;
|
|
13982
14464
|
if (kit.roll(c, side2)) rolled = true;
|
|
13983
14465
|
void rolled;
|
|
13984
14466
|
};
|