@adatechnology/game-vehicles-three 0.1.0 → 0.3.0
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 +2 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.global.js +2184 -349
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +46 -21
- package/dist/index.js.map +1 -1
- package/package.json +11 -12
package/dist/index.global.js
CHANGED
|
@@ -22,6 +22,7 @@ var GameVehiclesThree = (() => {
|
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
DEFAULT_TEST_VEHICLES: () => DEFAULT_TEST_VEHICLES,
|
|
25
|
+
DEFAULT_TEST_WRECKS: () => DEFAULT_TEST_WRECKS,
|
|
25
26
|
LITE_CLASSES: () => LITE_CLASSES,
|
|
26
27
|
PAGE_ITEM_ALIASES: () => PAGE_ITEM_ALIASES,
|
|
27
28
|
PAGE_SCENARIO_ALIASES: () => PAGE_SCENARIO_ALIASES,
|
|
@@ -5128,8 +5129,8 @@ var GameVehiclesThree = (() => {
|
|
|
5128
5129
|
});
|
|
5129
5130
|
return GRM[kind];
|
|
5130
5131
|
}
|
|
5131
|
-
function mkSurf(
|
|
5132
|
-
const geo =
|
|
5132
|
+
function mkSurf(mesh2, W) {
|
|
5133
|
+
const geo = mesh2.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
|
|
5133
5134
|
geo.computeBoundingBox();
|
|
5134
5135
|
const bb = geo.boundingBox.clone();
|
|
5135
5136
|
const T = [], BY = {}, BX = {}, Q = 0.02;
|
|
@@ -5146,11 +5147,11 @@ var GameVehiclesThree = (() => {
|
|
|
5146
5147
|
S.hit = function(o, dd) {
|
|
5147
5148
|
const d = dd.clone().normalize();
|
|
5148
5149
|
ray.set(o, d);
|
|
5149
|
-
const
|
|
5150
|
-
if (!
|
|
5150
|
+
const list2 = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
|
|
5151
|
+
if (!list2) return null;
|
|
5151
5152
|
let best = 1e9, bt = null;
|
|
5152
|
-
for (let k = 0; k <
|
|
5153
|
-
const t = T[
|
|
5153
|
+
for (let k = 0; k < list2.length; k++) {
|
|
5154
|
+
const t = T[list2[k]];
|
|
5154
5155
|
if (!ray.intersectTriangle(t[0], t[1], t[2], false, tmp)) continue;
|
|
5155
5156
|
const dist = tmp.distanceTo(o);
|
|
5156
5157
|
if (dist < best) {
|
|
@@ -5325,8 +5326,8 @@ var GameVehiclesThree = (() => {
|
|
|
5325
5326
|
t.castShadow = false;
|
|
5326
5327
|
return t;
|
|
5327
5328
|
}
|
|
5328
|
-
function lineOn(c, Gd,
|
|
5329
|
-
const pts =
|
|
5329
|
+
function lineOn(c, Gd, list2, r, mat, off) {
|
|
5330
|
+
const pts = list2.map(function(q) {
|
|
5330
5331
|
const s = Gd.at(q[0], q[1]);
|
|
5331
5332
|
return s.p.addScaledVector(s.n, off || 3e-3);
|
|
5332
5333
|
});
|
|
@@ -5397,8 +5398,8 @@ var GameVehiclesThree = (() => {
|
|
|
5397
5398
|
const r = sh(q[0]), y = (r[0] + r[1]) / 2 + (q[1] || 0), s = Gd.at(q[0], y), rad = q[2] || Math.min(0.034, (r[1] - r[0]) * 0.4);
|
|
5398
5399
|
const cup = onSurf(c.cylinder(rad * 1.35, rad * 1.2, 0.012, LH, 0, 0, 0), s, 8e-3);
|
|
5399
5400
|
cup.castShadow = false;
|
|
5400
|
-
const
|
|
5401
|
-
|
|
5401
|
+
const ring2 = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
|
|
5402
|
+
ring2.castShadow = false;
|
|
5402
5403
|
const b = onSurf(c.sphere(rad, MT.head, 0, 0, 0, 1, 0.55, 1), s, 0.01);
|
|
5403
5404
|
b.castShadow = false;
|
|
5404
5405
|
inner.push(b);
|
|
@@ -6015,9 +6016,9 @@ var GameVehiclesThree = (() => {
|
|
|
6015
6016
|
});
|
|
6016
6017
|
})();
|
|
6017
6018
|
const REFLB = CM("#d3d7da", { metalness: 0.35, roughness: 0.28 });
|
|
6018
|
-
function dlo(
|
|
6019
|
+
function dlo(list2) {
|
|
6019
6020
|
return function(def) {
|
|
6020
|
-
return
|
|
6021
|
+
return list2.concat([def[def.length - 1]]);
|
|
6021
6022
|
};
|
|
6022
6023
|
}
|
|
6023
6024
|
function cabTaper(belt, top, x0, L, a) {
|
|
@@ -8375,7 +8376,7 @@ var GameVehiclesThree = (() => {
|
|
|
8375
8376
|
guards: [-1.1, 2],
|
|
8376
8377
|
lightsY: 0.62
|
|
8377
8378
|
});
|
|
8378
|
-
const
|
|
8379
|
+
const box2 = boxBody(c, { x0: f - len - 0.1, x1: -3.72, y0: 0.98, y1: 3.38, W: 2.42, col: "#f1f1ec" });
|
|
8379
8380
|
[1, -1].forEach(function(s) {
|
|
8380
8381
|
c.roundBox(4.6, 0.32, 0.01, 0.01, CM("#1f4fa3", { roughness: 0.5 }), -1, 1.35, s * 1.217);
|
|
8381
8382
|
c.roundBox(4.6, 0.06, 0.01, 0.01, CM("#e0a21c", { roughness: 0.5 }), -1, 1.56, s * 1.217);
|
|
@@ -8406,7 +8407,7 @@ var GameVehiclesThree = (() => {
|
|
|
8406
8407
|
c2.rod(new V3(-3.86, 0.6, z), new V3(-3.86, 3.5, z), 0.022, kit.steelMaterial);
|
|
8407
8408
|
});
|
|
8408
8409
|
});
|
|
8409
|
-
void
|
|
8410
|
+
void box2;
|
|
8410
8411
|
}
|
|
8411
8412
|
);
|
|
8412
8413
|
fx.register(
|
|
@@ -9583,9 +9584,9 @@ var GameVehiclesThree = (() => {
|
|
|
9583
9584
|
return m;
|
|
9584
9585
|
}
|
|
9585
9586
|
function fenestron(c, x, y, R, w, n, mat, bladeMat) {
|
|
9586
|
-
const
|
|
9587
|
-
|
|
9588
|
-
c.deform.push(
|
|
9587
|
+
const ring2 = c.add(new THREE.TorusGeometry(R + 0.06, 0.07, 10, 36), mat, x, y, 0);
|
|
9588
|
+
ring2.scale.z = w / 0.14;
|
|
9589
|
+
c.deform.push(ring2);
|
|
9589
9590
|
const duct = c.cylinder(R + 0.01, R + 0.01, w, MT.dark, x, y, 0, "z", { seg: 36, open: true });
|
|
9590
9591
|
duct.material = CM("#141516", { roughness: 0.8, side: THREE.DoubleSide });
|
|
9591
9592
|
const g = new THREE.Group();
|
|
@@ -9613,7 +9614,7 @@ var GameVehiclesThree = (() => {
|
|
|
9613
9614
|
);
|
|
9614
9615
|
}
|
|
9615
9616
|
c.spin.push({ o: g, axis: "z", v: 22 });
|
|
9616
|
-
return { ring, fan: g, duct };
|
|
9617
|
+
return { ring: ring2, fan: g, duct };
|
|
9617
9618
|
}
|
|
9618
9619
|
function xRotor(c, x, y, z, R, ch, mat, tip) {
|
|
9619
9620
|
const g = new THREE.Group();
|
|
@@ -11330,16 +11331,16 @@ var GameVehiclesThree = (() => {
|
|
|
11330
11331
|
function settle(c, tilt, riseOnly) {
|
|
11331
11332
|
if (tilt) c.vehicle.rotation.z += tilt;
|
|
11332
11333
|
c.root.updateMatrixWorld(true);
|
|
11333
|
-
const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert(),
|
|
11334
|
+
const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert(), box2 = new THREE.Box3(), tmp = new THREE.Box3();
|
|
11334
11335
|
c.vehicle.traverse(function(ob) {
|
|
11335
11336
|
if (!ob.isMesh) return;
|
|
11336
11337
|
for (let q = ob; q && q !== c.vehicle; q = q.parent)
|
|
11337
11338
|
if (!q.visible || q.userData.decal || q.userData.ghost || q.userData.antena) return;
|
|
11338
11339
|
if (!ob.geometry.boundingBox) ob.geometry.computeBoundingBox();
|
|
11339
11340
|
tmp.copy(ob.geometry.boundingBox).applyMatrix4(ob.matrixWorld).applyMatrix4(inv);
|
|
11340
|
-
|
|
11341
|
+
box2.union(tmp);
|
|
11341
11342
|
});
|
|
11342
|
-
if (!
|
|
11343
|
+
if (!box2.isEmpty() && (!riseOnly || box2.min.y < -5e-3)) c.vehicle.position.y -= box2.min.y;
|
|
11343
11344
|
}
|
|
11344
11345
|
function rollover(c, o) {
|
|
11345
11346
|
o = o || {};
|
|
@@ -11616,10 +11617,10 @@ var GameVehiclesThree = (() => {
|
|
|
11616
11617
|
function periscope(c, x, y, z, w, label, o) {
|
|
11617
11618
|
o = o || {};
|
|
11618
11619
|
const rot = o.rot || 0;
|
|
11619
|
-
const
|
|
11620
|
+
const box2 = c.roundBox(0.14, 0.12, w + 0.06, 0.02, o.mat || OLIVE_STEEL, x, y, z, { rot: [0, rot, 0] });
|
|
11620
11621
|
const gl = c.roundBox(0.02, 0.07, w, 0.01, MT.armorGlass, x + Math.cos(rot) * 0.07, y, z - Math.sin(rot) * 0.07, { rot: [0, rot, 0] });
|
|
11621
11622
|
if (label) kit.asGlass(c, gl, label, "laminated");
|
|
11622
|
-
return
|
|
11623
|
+
return box2;
|
|
11623
11624
|
}
|
|
11624
11625
|
function sideSeat(c, x0, x1, fl, z, dir, o) {
|
|
11625
11626
|
o = o || {};
|
|
@@ -13947,7 +13948,7 @@ var GameVehiclesThree = (() => {
|
|
|
13947
13948
|
o = o || {};
|
|
13948
13949
|
if (kit.lod.on) o = Object.assign({}, o, { seg: Math.max(kit.lod.minLoftSegments, Math.round((o.seg || 24) * kit.lod.loftSegmentFraction)) });
|
|
13949
13950
|
if (o.smooth) st = resample(st, o.smooth);
|
|
13950
|
-
const seg = o.seg || 24, pos = [], idx = [],
|
|
13951
|
+
const seg = o.seg || 24, pos = [], idx = [], ring2 = seg + 1, axisY = o.axis === "y";
|
|
13951
13952
|
st.forEach(function(s) {
|
|
13952
13953
|
const a0 = s[1], b0 = s[2], cc = (a0 + b0) / 2, hh = Math.abs(a0 - b0) / 2, w = s[3] / 2, e = 2 / (s[4] || o.p || 2.4), zc = s[5] || 0;
|
|
13953
13954
|
for (let j = 0; j <= seg; j++) {
|
|
@@ -13959,7 +13960,7 @@ var GameVehiclesThree = (() => {
|
|
|
13959
13960
|
});
|
|
13960
13961
|
for (let i = 0; i < st.length - 1; i++)
|
|
13961
13962
|
for (let k = 0; k < seg; k++) {
|
|
13962
|
-
const A = i *
|
|
13963
|
+
const A = i * ring2 + k, B = A + ring2;
|
|
13963
13964
|
if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
|
|
13964
13965
|
else idx.push(A, A + 1, B, A + 1, B + 1, B);
|
|
13965
13966
|
}
|
|
@@ -13971,7 +13972,7 @@ var GameVehiclesThree = (() => {
|
|
|
13971
13972
|
if (axisY) pos.push(cc, s[0], s[5] || 0);
|
|
13972
13973
|
else pos.push(s[0], cc, s[5] || 0);
|
|
13973
13974
|
for (let k = 0; k < seg; k++) {
|
|
13974
|
-
const a = si *
|
|
13975
|
+
const a = si * ring2 + k, flip = e === 0 !== axisY;
|
|
13975
13976
|
if (flip) idx.push(ci, a + 1, a);
|
|
13976
13977
|
else idx.push(ci, a, a + 1);
|
|
13977
13978
|
}
|
|
@@ -14158,8 +14159,8 @@ var GameVehiclesThree = (() => {
|
|
|
14158
14159
|
});
|
|
14159
14160
|
return GRM[kind];
|
|
14160
14161
|
}
|
|
14161
|
-
function mkSurf(
|
|
14162
|
-
const geo =
|
|
14162
|
+
function mkSurf(mesh2, W) {
|
|
14163
|
+
const geo = mesh2.geometry, pos = geo.attributes.position, ix = geo.index, n = ix ? ix.count : pos.count;
|
|
14163
14164
|
geo.computeBoundingBox();
|
|
14164
14165
|
const bb = geo.boundingBox.clone();
|
|
14165
14166
|
const T = [], BY = {}, BX = {}, Q = 0.02;
|
|
@@ -14176,11 +14177,11 @@ var GameVehiclesThree = (() => {
|
|
|
14176
14177
|
S.hit = function(o, dd) {
|
|
14177
14178
|
const d = dd.clone().normalize();
|
|
14178
14179
|
ray.set(o, d);
|
|
14179
|
-
const
|
|
14180
|
-
if (!
|
|
14180
|
+
const list2 = Math.abs(d.y) < 0.5 ? BY[Math.floor(o.y / Q)] : BX[Math.floor(o.x / Q)];
|
|
14181
|
+
if (!list2) return null;
|
|
14181
14182
|
let best = 1e9, bt = null;
|
|
14182
|
-
for (let k = 0; k <
|
|
14183
|
-
const t = T[
|
|
14183
|
+
for (let k = 0; k < list2.length; k++) {
|
|
14184
|
+
const t = T[list2[k]];
|
|
14184
14185
|
if (!ray.intersectTriangle(t[0], t[1], t[2], false, tmp)) continue;
|
|
14185
14186
|
const dist = tmp.distanceTo(o);
|
|
14186
14187
|
if (dist < best) {
|
|
@@ -14355,8 +14356,8 @@ var GameVehiclesThree = (() => {
|
|
|
14355
14356
|
t.castShadow = false;
|
|
14356
14357
|
return t;
|
|
14357
14358
|
}
|
|
14358
|
-
function lineOn(c, Gd,
|
|
14359
|
-
const pts =
|
|
14359
|
+
function lineOn(c, Gd, list2, r, mat, off) {
|
|
14360
|
+
const pts = list2.map(function(q) {
|
|
14360
14361
|
const s = Gd.at(q[0], q[1]);
|
|
14361
14362
|
return s.p.addScaledVector(s.n, off || 3e-3);
|
|
14362
14363
|
});
|
|
@@ -14427,8 +14428,8 @@ var GameVehiclesThree = (() => {
|
|
|
14427
14428
|
const r = sh(q[0]), y = (r[0] + r[1]) / 2 + (q[1] || 0), s = Gd.at(q[0], y), rad = q[2] || Math.min(0.034, (r[1] - r[0]) * 0.4);
|
|
14428
14429
|
const cup = onSurf(c.cylinder(rad * 1.35, rad * 1.2, 0.012, LH, 0, 0, 0), s, 8e-3);
|
|
14429
14430
|
cup.castShadow = false;
|
|
14430
|
-
const
|
|
14431
|
-
|
|
14431
|
+
const ring2 = onSurf(c.add(new THREE.TorusGeometry(rad * 1.05, 4e-3, 6, 22), MT.chrome), s, 0.012, new V3(0, 0, 1));
|
|
14432
|
+
ring2.castShadow = false;
|
|
14432
14433
|
const b = onSurf(c.sphere(rad, MT.head, 0, 0, 0, 1, 0.55, 1), s, 0.01);
|
|
14433
14434
|
b.castShadow = false;
|
|
14434
14435
|
inner.push(b);
|
|
@@ -16505,9 +16506,9 @@ var GameVehiclesThree = (() => {
|
|
|
16505
16506
|
L.inner.push(m);
|
|
16506
16507
|
return m;
|
|
16507
16508
|
}
|
|
16508
|
-
function bendSet(
|
|
16509
|
+
function bendSet(list2, piv, axis, ang) {
|
|
16509
16510
|
const q = new THREE.Quaternion().setFromAxisAngle(axis.clone().normalize(), ang);
|
|
16510
|
-
|
|
16511
|
+
list2.forEach(function(m) {
|
|
16511
16512
|
if (!m.parent) return;
|
|
16512
16513
|
m.position.sub(piv).applyQuaternion(q).add(piv);
|
|
16513
16514
|
m.quaternion.premultiply(q);
|
|
@@ -17554,7 +17555,7 @@ var GameVehiclesThree = (() => {
|
|
|
17554
17555
|
);
|
|
17555
17556
|
[1, -1].forEach(function(s) {
|
|
17556
17557
|
const z = s * (s > 0 ? 0.44 : 0.4);
|
|
17557
|
-
const
|
|
17558
|
+
const box2 = c.roundBox(0.5, 0.38, 0.2, 0.03, aluBox, -0.7, 0.8, z, { def: true }), luggageCase = [box2, c.roundBox(0.52, 0.04, 0.21, 0.015, blk, -0.7, 0.98, z)];
|
|
17558
17559
|
[-0.88, -0.52].forEach(function(x) {
|
|
17559
17560
|
luggageCase.push(c.roundBox(0.04, 0.06, 0.03, 0.01, blk, x, 0.95, z + s * 0.1));
|
|
17560
17561
|
});
|
|
@@ -17568,7 +17569,7 @@ var GameVehiclesThree = (() => {
|
|
|
17568
17569
|
blk,
|
|
17569
17570
|
{ seg: 12 }
|
|
17570
17571
|
);
|
|
17571
|
-
c.part("cargo", s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"),
|
|
17572
|
+
c.part("cargo", s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"), box2, new V3(-0.7, 0.8, z), 0.6);
|
|
17572
17573
|
c.zone(
|
|
17573
17574
|
s > 0 ? "case_right" : "case_left",
|
|
17574
17575
|
s > 0 ? trl("labels.right_pannier") : trl("labels.left_pannier"),
|
|
@@ -18216,7 +18217,7 @@ var GameVehiclesThree = (() => {
|
|
|
18216
18217
|
function sloft(st, o) {
|
|
18217
18218
|
o = o || {};
|
|
18218
18219
|
if (kit.lod.on) o = Object.assign({}, o, { seg: Math.max(kit.lod.minLoftSegments, Math.round((o.seg || 24) * kit.lod.loftSegmentFraction)) });
|
|
18219
|
-
const seg = o.seg || 24, pos = [], idx = [],
|
|
18220
|
+
const seg = o.seg || 24, pos = [], idx = [], ring2 = seg + 1, axisY = o.axis === "y";
|
|
18220
18221
|
st.forEach(function(s) {
|
|
18221
18222
|
const a0 = s[1], b0 = s[2], cc = (a0 + b0) / 2, hh = Math.abs(a0 - b0) / 2, w = s[3] / 2, e = 2 / (s[4] || o.p || 2.4), zc = s[5] || 0;
|
|
18222
18223
|
for (let j = 0; j <= seg; j++) {
|
|
@@ -18228,7 +18229,7 @@ var GameVehiclesThree = (() => {
|
|
|
18228
18229
|
});
|
|
18229
18230
|
for (let i = 0; i < st.length - 1; i++)
|
|
18230
18231
|
for (let k = 0; k < seg; k++) {
|
|
18231
|
-
const A = i *
|
|
18232
|
+
const A = i * ring2 + k, B = A + ring2;
|
|
18232
18233
|
if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
|
|
18233
18234
|
else idx.push(A, A + 1, B, A + 1, B + 1, B);
|
|
18234
18235
|
}
|
|
@@ -18240,7 +18241,7 @@ var GameVehiclesThree = (() => {
|
|
|
18240
18241
|
if (axisY) pos.push(cc, s[0], s[5] || 0);
|
|
18241
18242
|
else pos.push(s[0], cc, s[5] || 0);
|
|
18242
18243
|
for (let k = 0; k < seg; k++) {
|
|
18243
|
-
const a = si *
|
|
18244
|
+
const a = si * ring2 + k, flip = e === 0 !== axisY;
|
|
18244
18245
|
if (flip) idx.push(ci, a + 1, a);
|
|
18245
18246
|
else idx.push(ci, a, a + 1);
|
|
18246
18247
|
}
|
|
@@ -19471,12 +19472,12 @@ var GameVehiclesThree = (() => {
|
|
|
19471
19472
|
});
|
|
19472
19473
|
Z.fairing = grab(c, n0).concat([fendF]);
|
|
19473
19474
|
const HL = lamp(c, { style: "round", x: 0.72, y: 0.84, z: 0, w: 0.19, h: 0.19, d: 0.1, side: 1, label: trl("labels.headlight") });
|
|
19474
|
-
const
|
|
19475
|
-
|
|
19476
|
-
|
|
19477
|
-
|
|
19478
|
-
HL.group.add(
|
|
19479
|
-
HL.inner.push(
|
|
19475
|
+
const ring2 = new THREE.Mesh(new THREE.TorusGeometry(0.075, 7e-3, 6, 32), DRL);
|
|
19476
|
+
ring2.rotation.y = PI / 2;
|
|
19477
|
+
ring2.position.set(0.052, 0, 0);
|
|
19478
|
+
ring2.castShadow = false;
|
|
19479
|
+
HL.group.add(ring2);
|
|
19480
|
+
HL.inner.push(ring2);
|
|
19480
19481
|
n0 = c.vehicle.children.length;
|
|
19481
19482
|
const TK = [
|
|
19482
19483
|
[0.46, 0.89, 0.76, 0.18, 2.2],
|
|
@@ -22525,7 +22526,7 @@ var GameVehiclesThree = (() => {
|
|
|
22525
22526
|
});
|
|
22526
22527
|
}
|
|
22527
22528
|
function roofLining(c, extra) {
|
|
22528
|
-
const m = c.meta, yb = (m.glasshouse ? m.glasshouse.belt : m.belt) + 0.25, bb = new THREE.Box3(), sz = new V3(), ce = new V3(), gl = new Set(c.glass),
|
|
22529
|
+
const m = c.meta, yb = (m.glasshouse ? m.glasshouse.belt : m.belt) + 0.25, bb = new THREE.Box3(), sz = new V3(), ce = new V3(), gl = new Set(c.glass), list2 = [];
|
|
22529
22530
|
const cols = [m.color, m.roofCol].filter(Boolean).map(function(h) {
|
|
22530
22531
|
return new THREE.Color(h).getHex();
|
|
22531
22532
|
});
|
|
@@ -22537,14 +22538,14 @@ var GameVehiclesThree = (() => {
|
|
|
22537
22538
|
bb.copy(o.geometry.boundingBox).applyMatrix4(o.matrix);
|
|
22538
22539
|
bb.getSize(sz);
|
|
22539
22540
|
bb.getCenter(ce);
|
|
22540
|
-
if (sz.x > 0.5 && sz.z > 0.6 && sz.y < 0.08 && ce.y > yb)
|
|
22541
|
+
if (sz.x > 0.5 && sz.z > 0.6 && sz.y < 0.08 && ce.y > yb) list2.push(o);
|
|
22541
22542
|
});
|
|
22542
22543
|
extra = extra || [];
|
|
22543
|
-
if (
|
|
22544
|
+
if (list2.length || extra.length)
|
|
22544
22545
|
c.zone("roof", null, null, null, {
|
|
22545
22546
|
onBand: function(c2, b) {
|
|
22546
22547
|
if (b >= 4)
|
|
22547
|
-
|
|
22548
|
+
list2.concat(extra).forEach(function(o) {
|
|
22548
22549
|
o.visible = false;
|
|
22549
22550
|
});
|
|
22550
22551
|
}
|
|
@@ -24329,7 +24330,7 @@ var GameVehiclesThree = (() => {
|
|
|
24329
24330
|
}
|
|
24330
24331
|
return pts;
|
|
24331
24332
|
}
|
|
24332
|
-
const
|
|
24333
|
+
const ring2 = 2 * (m1 + m2) + 1;
|
|
24333
24334
|
for (let i = 0; i <= n; i++) {
|
|
24334
24335
|
const t = i / n, x = o.x0 + t * o.L, P = sec(t), row = [];
|
|
24335
24336
|
for (let k = P.length - 1; k >= 1; k--) row.push([-P[k][0], P[k][1]]);
|
|
@@ -24345,8 +24346,8 @@ var GameVehiclesThree = (() => {
|
|
|
24345
24346
|
});
|
|
24346
24347
|
}
|
|
24347
24348
|
for (let a = 0; a < n; a++)
|
|
24348
|
-
for (let k2 = 0; k2 <
|
|
24349
|
-
const p0 = a *
|
|
24349
|
+
for (let k2 = 0; k2 < ring2 - 1; k2++) {
|
|
24350
|
+
const p0 = a * ring2 + k2, p1 = p0 + ring2;
|
|
24350
24351
|
idx.push(p0, p0 + 1, p1, p0 + 1, p1 + 1, p1);
|
|
24351
24352
|
}
|
|
24352
24353
|
const ci = pos.length / 3, sh0 = o.sheer(0), ky0 = o.keel(0);
|
|
@@ -24355,7 +24356,7 @@ var GameVehiclesThree = (() => {
|
|
|
24355
24356
|
const c0 = o.col(o.x0, (sh0[1] + ky0) / 2, 0);
|
|
24356
24357
|
col.push(c0.r, c0.g, c0.b);
|
|
24357
24358
|
}
|
|
24358
|
-
for (let r = 0; r <
|
|
24359
|
+
for (let r = 0; r < ring2 - 1; r++) idx.push(ci, r + 1, r);
|
|
24359
24360
|
let g = new THREE.BufferGeometry();
|
|
24360
24361
|
g.setAttribute("position", new THREE.Float32BufferAttribute(pos, 3));
|
|
24361
24362
|
if (o.col) g.setAttribute("color", new THREE.Float32BufferAttribute(col, 3));
|
|
@@ -24428,7 +24429,7 @@ var GameVehiclesThree = (() => {
|
|
|
24428
24429
|
function foilGeo(sts, o) {
|
|
24429
24430
|
o = o || {};
|
|
24430
24431
|
const n = o.n || 12, up = o.up || "y", pos = [], idx = [];
|
|
24431
|
-
let
|
|
24432
|
+
let ring2;
|
|
24432
24433
|
const cnt = 0;
|
|
24433
24434
|
function prof(st) {
|
|
24434
24435
|
const out = [], cam = st.cam || 0;
|
|
@@ -24448,14 +24449,14 @@ var GameVehiclesThree = (() => {
|
|
|
24448
24449
|
}
|
|
24449
24450
|
sts.forEach(function(st) {
|
|
24450
24451
|
const P = prof(st);
|
|
24451
|
-
|
|
24452
|
+
ring2 = P.length;
|
|
24452
24453
|
P.forEach(function(p) {
|
|
24453
24454
|
pos.push(p[0], p[1], p[2]);
|
|
24454
24455
|
});
|
|
24455
24456
|
});
|
|
24456
24457
|
for (let a = 0; a < sts.length - 1; a++)
|
|
24457
|
-
for (let k = 0; k <
|
|
24458
|
-
const k1 = (k + 1) %
|
|
24458
|
+
for (let k = 0; k < ring2; k++) {
|
|
24459
|
+
const k1 = (k + 1) % ring2, p0 = a * ring2 + k, p1 = (a + 1) * ring2 + k, q0 = a * ring2 + k1, q1 = (a + 1) * ring2 + k1;
|
|
24459
24460
|
idx.push(p0, q0, p1, q0, q1, p1);
|
|
24460
24461
|
}
|
|
24461
24462
|
;
|
|
@@ -24463,8 +24464,8 @@ var GameVehiclesThree = (() => {
|
|
|
24463
24464
|
if (sts[si].noCap) return;
|
|
24464
24465
|
const ci = pos.length / 3, st = sts[si];
|
|
24465
24466
|
pos.push(st.p[0] - st.c * 0.35, st.p[1], st.p[2]);
|
|
24466
|
-
for (let k = 0; k <
|
|
24467
|
-
const a0 = si *
|
|
24467
|
+
for (let k = 0; k < ring2; k++) {
|
|
24468
|
+
const a0 = si * ring2 + k, a1 = si * ring2 + (k + 1) % ring2;
|
|
24468
24469
|
if (e === 0) idx.push(ci, a1, a0);
|
|
24469
24470
|
else idx.push(ci, a0, a1);
|
|
24470
24471
|
}
|
|
@@ -24692,7 +24693,7 @@ var GameVehiclesThree = (() => {
|
|
|
24692
24693
|
blue: CM("#1d4f9a", { emissive: new THREE.Color("#3a7cff"), emissiveIntensity: 1.4, roughness: 0.3 })
|
|
24693
24694
|
};
|
|
24694
24695
|
const HALO = { red: "#ff3a2a", green: "#3aff7a", white: "#fff1d0", amber: "#ffb040", blue: "#4a8cff" };
|
|
24695
|
-
function navLight(c, x, y, z,
|
|
24696
|
+
function navLight(c, x, y, z, color2, label, o) {
|
|
24696
24697
|
o = o || {};
|
|
24697
24698
|
const r = o.r || 0.045, g = new THREE.Group();
|
|
24698
24699
|
g.position.set(x, y, z);
|
|
@@ -24702,11 +24703,11 @@ var GameVehiclesThree = (() => {
|
|
|
24702
24703
|
base.position.y = -r * 0.4;
|
|
24703
24704
|
if (o.rot) base.rotation.set(o.rot[0], o.rot[1], o.rot[2]);
|
|
24704
24705
|
g.add(base);
|
|
24705
|
-
const bulb = new THREE.Mesh(new THREE.SphereGeometry(r * 0.55, 10, 8), NAV[
|
|
24706
|
+
const bulb = new THREE.Mesh(new THREE.SphereGeometry(r * 0.55, 10, 8), NAV[color2] || NAV.white);
|
|
24706
24707
|
g.add(bulb);
|
|
24707
24708
|
const lens = new THREE.Mesh(
|
|
24708
24709
|
new THREE.SphereGeometry(r, 12, 8),
|
|
24709
|
-
|
|
24710
|
+
color2 === "red" ? MT.lensRed : color2 === "amber" ? MT.lensAmber : MT.lens
|
|
24710
24711
|
);
|
|
24711
24712
|
lens.renderOrder = 3;
|
|
24712
24713
|
g.add(lens);
|
|
@@ -24715,10 +24716,10 @@ var GameVehiclesThree = (() => {
|
|
|
24715
24716
|
inner: [bulb],
|
|
24716
24717
|
lens: [lens],
|
|
24717
24718
|
kind: o.front ? "headlight" : "taillight",
|
|
24718
|
-
tint:
|
|
24719
|
+
tint: color2 === "red" ? "red" : "clear",
|
|
24719
24720
|
broken: false
|
|
24720
24721
|
};
|
|
24721
|
-
if (o.halo !== false) L.halo = [kit.halo(g, 0, 0, 0, o.hs || 0.35, HALO[
|
|
24722
|
+
if (o.halo !== false) L.halo = [kit.halo(g, 0, 0, 0, o.hs || 0.35, HALO[color2] || "#ffffff", 0.5)];
|
|
24722
24723
|
c.lights.push(L);
|
|
24723
24724
|
const pt = c.part(o.front ? "headlight" : "taillight", label, g, new V3(x, y, z), o.reach || 0.5);
|
|
24724
24725
|
pt.light = L;
|
|
@@ -24840,15 +24841,15 @@ var GameVehiclesThree = (() => {
|
|
|
24840
24841
|
c.roundBox(0.16 * r, 0.03, 0.04, 0.012, MT.chrome, x, y + 0.04, z);
|
|
24841
24842
|
c.roundBox(0.04, 0.04, 0.03, 0.01, MT.chrome, x, y + 0.02, z);
|
|
24842
24843
|
}
|
|
24843
|
-
function skinOf2(c,
|
|
24844
|
+
function skinOf2(c, mesh2, keep, mat, o) {
|
|
24844
24845
|
o = o || {};
|
|
24845
|
-
const g =
|
|
24846
|
+
const g = mesh2.geometry.clone(), p = g.attributes.position, sz = o.sz || 1.006, dy = o.dy || 0;
|
|
24846
24847
|
for (let i = 0; i < p.count; i++) {
|
|
24847
24848
|
p.setZ(i, p.getZ(i) * sz);
|
|
24848
24849
|
p.setY(i, p.getY(i) + dy * Math.sign(p.getY(i)));
|
|
24849
24850
|
}
|
|
24850
24851
|
if (g.attributes.color) g.deleteAttribute("color");
|
|
24851
|
-
const m = c.add(g, mat,
|
|
24852
|
+
const m = c.add(g, mat, mesh2.position.x, mesh2.position.y, mesh2.position.z);
|
|
24852
24853
|
m.castShadow = false;
|
|
24853
24854
|
kit.cutMesh(m, [keep], 40, o.sub ? { sub: o.sub } : void 0);
|
|
24854
24855
|
c.deform.push(m);
|
|
@@ -27604,9 +27605,9 @@ var GameVehiclesThree = (() => {
|
|
|
27604
27605
|
for (const name of LITE_CLASSES) acc[name] = { P: [], N: [], C: [], U: [], I: [], nv: 0, alpha: name === "glass", uv: name === "plate", map: null };
|
|
27605
27606
|
return acc;
|
|
27606
27607
|
};
|
|
27607
|
-
function classify(mat,
|
|
27608
|
+
function classify(mat, mesh2, c) {
|
|
27608
27609
|
if (mat.map) {
|
|
27609
|
-
if (
|
|
27610
|
+
if (mesh2.userData.plate) return "plate";
|
|
27610
27611
|
if (mat.userData && mat.userData.grille || mat.name === "grille" || mat.metalness != null && mat.roughness != null && !mat.transparent) return "trim";
|
|
27611
27612
|
return null;
|
|
27612
27613
|
}
|
|
@@ -27752,11 +27753,11 @@ var GameVehiclesThree = (() => {
|
|
|
27752
27753
|
mt.map = A.map;
|
|
27753
27754
|
if (mt.map) mt.map.needsUpdate = true;
|
|
27754
27755
|
}
|
|
27755
|
-
const
|
|
27756
|
-
|
|
27757
|
-
|
|
27758
|
-
|
|
27759
|
-
meshes.push(
|
|
27756
|
+
const mesh2 = new THREE.Mesh(g, mt);
|
|
27757
|
+
mesh2.name = name;
|
|
27758
|
+
mesh2.castShadow = name !== "glass" && name !== "light";
|
|
27759
|
+
mesh2.receiveShadow = name !== "light";
|
|
27760
|
+
meshes.push(mesh2);
|
|
27760
27761
|
}
|
|
27761
27762
|
return meshes;
|
|
27762
27763
|
}
|
|
@@ -27805,7 +27806,7 @@ var GameVehiclesThree = (() => {
|
|
|
27805
27806
|
const spec = kit.find(key);
|
|
27806
27807
|
if (!spec) throw new Error(`createVehiclesThree: unknown vehicle "${key}"`);
|
|
27807
27808
|
const seed = o.seed == null ? null : o.seed;
|
|
27808
|
-
const
|
|
27809
|
+
const color2 = o.color || (seed != null ? colorFromSeed(seed, isMilitary(key) ? paintPalettes.military : paintPalettes.civil) : null);
|
|
27809
27810
|
const c = kit.build(key, o.state || "intact", void 0, { lod: quality === "lite" });
|
|
27810
27811
|
c.root.updateMatrixWorld(true);
|
|
27811
27812
|
const primary = primaryPaint(c);
|
|
@@ -27836,9 +27837,9 @@ var GameVehiclesThree = (() => {
|
|
|
27836
27837
|
c.vehicle.matrixAutoUpdate = true;
|
|
27837
27838
|
pivot.add(c.vehicle);
|
|
27838
27839
|
group.add(pivot);
|
|
27839
|
-
if (
|
|
27840
|
+
if (color2 && primary) {
|
|
27840
27841
|
const repainted = primary.clone();
|
|
27841
|
-
repainted.color.set(
|
|
27842
|
+
repainted.color.set(color2);
|
|
27842
27843
|
c.vehicle.traverse((m) => {
|
|
27843
27844
|
if (!m.isMesh) return;
|
|
27844
27845
|
if (Array.isArray(m.material)) m.material = m.material.map((x) => x === primary ? repainted : x);
|
|
@@ -27848,8 +27849,8 @@ var GameVehiclesThree = (() => {
|
|
|
27848
27849
|
markDamageables(c, damageables);
|
|
27849
27850
|
group.updateMatrixWorld(true);
|
|
27850
27851
|
} else {
|
|
27851
|
-
const fusion = fuse(THREE, c, pivotMatrix,
|
|
27852
|
-
for (const
|
|
27852
|
+
const fusion = fuse(THREE, c, pivotMatrix, color2 ? new THREE.Color(color2) : null, primary, kit.lodHiddenMaterials());
|
|
27853
|
+
for (const mesh2 of liteMeshes(THREE, fusion, liteMaterials(THREE, kit.studioEnvironment()))) group.add(mesh2);
|
|
27853
27854
|
pruned = fusion.pruned;
|
|
27854
27855
|
}
|
|
27855
27856
|
const size = new THREE.Box3().setFromObject(group).getSize(new THREE.Vector3());
|
|
@@ -27860,7 +27861,7 @@ var GameVehiclesThree = (() => {
|
|
|
27860
27861
|
return {
|
|
27861
27862
|
key,
|
|
27862
27863
|
quality,
|
|
27863
|
-
color,
|
|
27864
|
+
color: color2,
|
|
27864
27865
|
seed,
|
|
27865
27866
|
group,
|
|
27866
27867
|
damageables,
|
|
@@ -27895,6 +27896,1594 @@ var GameVehiclesThree = (() => {
|
|
|
27895
27896
|
}
|
|
27896
27897
|
}
|
|
27897
27898
|
|
|
27899
|
+
// ../game-shapes/dist/chunk-R4RY23RH.js
|
|
27900
|
+
function canonicalJson(value) {
|
|
27901
|
+
if (value === null) return "null";
|
|
27902
|
+
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
27903
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
27904
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
27905
|
+
if (typeof value === "function") throw new Error("game-shapes: a function cannot be part of a shape (register it as a generator)");
|
|
27906
|
+
if (ArrayBuffer.isView(value)) return canonicalJson(Array.from(value));
|
|
27907
|
+
if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "null" : canonicalJson(item)).join(",")}]`;
|
|
27908
|
+
if (typeof value === "object") {
|
|
27909
|
+
const record = value;
|
|
27910
|
+
const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
|
|
27911
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
|
|
27912
|
+
}
|
|
27913
|
+
return "null";
|
|
27914
|
+
}
|
|
27915
|
+
function needsUint32(array) {
|
|
27916
|
+
for (let i = array.length - 1; i >= 0; --i) if (array[i] >= 65535) return true;
|
|
27917
|
+
return false;
|
|
27918
|
+
}
|
|
27919
|
+
var indexArray = (indices) => needsUint32(indices) ? new Uint32Array(indices) : new Uint16Array(indices);
|
|
27920
|
+
function pack(type, parameters, a) {
|
|
27921
|
+
return {
|
|
27922
|
+
type,
|
|
27923
|
+
parameters,
|
|
27924
|
+
positions: new Float32Array(a.vertices),
|
|
27925
|
+
normals: new Float32Array(a.normals),
|
|
27926
|
+
uvs: new Float32Array(a.uvs),
|
|
27927
|
+
...a.indices ? { indices: indexArray(a.indices) } : {},
|
|
27928
|
+
groups: a.groups
|
|
27929
|
+
};
|
|
27930
|
+
}
|
|
27931
|
+
var normalize3 = (x, y, z) => {
|
|
27932
|
+
const length = Math.sqrt(x * x + y * y + z * z);
|
|
27933
|
+
const s = 1 / (length || 1);
|
|
27934
|
+
return [x * s, y * s, z * s];
|
|
27935
|
+
};
|
|
27936
|
+
function box(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
|
|
27937
|
+
const parameters = { width, height, depth, widthSegments, heightSegments, depthSegments };
|
|
27938
|
+
widthSegments = Math.floor(widthSegments);
|
|
27939
|
+
heightSegments = Math.floor(heightSegments);
|
|
27940
|
+
depthSegments = Math.floor(depthSegments);
|
|
27941
|
+
const indices = [];
|
|
27942
|
+
const vertices = [];
|
|
27943
|
+
const normals = [];
|
|
27944
|
+
const uvs = [];
|
|
27945
|
+
const groups = [];
|
|
27946
|
+
let numberOfVertices = 0;
|
|
27947
|
+
let groupStart = 0;
|
|
27948
|
+
const buildPlane = (u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) => {
|
|
27949
|
+
const segmentWidth = width2 / gridX;
|
|
27950
|
+
const segmentHeight = height2 / gridY;
|
|
27951
|
+
const widthHalf = width2 / 2;
|
|
27952
|
+
const heightHalf = height2 / 2;
|
|
27953
|
+
const depthHalf = depth2 / 2;
|
|
27954
|
+
const gridX1 = gridX + 1;
|
|
27955
|
+
const gridY1 = gridY + 1;
|
|
27956
|
+
let vertexCounter = 0;
|
|
27957
|
+
let groupCount = 0;
|
|
27958
|
+
const vector = { x: 0, y: 0, z: 0 };
|
|
27959
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
27960
|
+
const y = iy * segmentHeight - heightHalf;
|
|
27961
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
27962
|
+
const x = ix * segmentWidth - widthHalf;
|
|
27963
|
+
vector[u] = x * udir;
|
|
27964
|
+
vector[v] = y * vdir;
|
|
27965
|
+
vector[w] = depthHalf;
|
|
27966
|
+
vertices.push(vector.x, vector.y, vector.z);
|
|
27967
|
+
vector[u] = 0;
|
|
27968
|
+
vector[v] = 0;
|
|
27969
|
+
vector[w] = depth2 > 0 ? 1 : -1;
|
|
27970
|
+
normals.push(vector.x, vector.y, vector.z);
|
|
27971
|
+
uvs.push(ix / gridX);
|
|
27972
|
+
uvs.push(1 - iy / gridY);
|
|
27973
|
+
vertexCounter += 1;
|
|
27974
|
+
}
|
|
27975
|
+
}
|
|
27976
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
27977
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
27978
|
+
const a = numberOfVertices + ix + gridX1 * iy;
|
|
27979
|
+
const b = numberOfVertices + ix + gridX1 * (iy + 1);
|
|
27980
|
+
const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
|
|
27981
|
+
const d = numberOfVertices + (ix + 1) + gridX1 * iy;
|
|
27982
|
+
indices.push(a, b, d);
|
|
27983
|
+
indices.push(b, c, d);
|
|
27984
|
+
groupCount += 6;
|
|
27985
|
+
}
|
|
27986
|
+
}
|
|
27987
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex });
|
|
27988
|
+
groupStart += groupCount;
|
|
27989
|
+
numberOfVertices += vertexCounter;
|
|
27990
|
+
};
|
|
27991
|
+
buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0);
|
|
27992
|
+
buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
|
|
27993
|
+
buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2);
|
|
27994
|
+
buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
|
|
27995
|
+
buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4);
|
|
27996
|
+
buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
|
|
27997
|
+
return pack("BoxGeometry", parameters, { vertices, normals, uvs, indices, groups });
|
|
27998
|
+
}
|
|
27999
|
+
function cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
|
|
28000
|
+
radialSegments = Math.floor(radialSegments);
|
|
28001
|
+
heightSegments = Math.floor(heightSegments);
|
|
28002
|
+
const indices = [];
|
|
28003
|
+
const vertices = [];
|
|
28004
|
+
const normals = [];
|
|
28005
|
+
const uvs = [];
|
|
28006
|
+
const groups = [];
|
|
28007
|
+
let index = 0;
|
|
28008
|
+
const indexArray2 = [];
|
|
28009
|
+
const halfHeight = height / 2;
|
|
28010
|
+
let groupStart = 0;
|
|
28011
|
+
const generateTorso = () => {
|
|
28012
|
+
let groupCount = 0;
|
|
28013
|
+
const slope = (radiusBottom - radiusTop) / height;
|
|
28014
|
+
for (let y = 0; y <= heightSegments; y++) {
|
|
28015
|
+
const indexRow = [];
|
|
28016
|
+
const v = y / heightSegments;
|
|
28017
|
+
const radius = v * (radiusBottom - radiusTop) + radiusTop;
|
|
28018
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
28019
|
+
const u = x / radialSegments;
|
|
28020
|
+
const theta = u * thetaLength + thetaStart;
|
|
28021
|
+
const sinTheta = Math.sin(theta);
|
|
28022
|
+
const cosTheta = Math.cos(theta);
|
|
28023
|
+
vertices.push(radius * sinTheta, -v * height + halfHeight, radius * cosTheta);
|
|
28024
|
+
const n = normalize3(sinTheta, slope, cosTheta);
|
|
28025
|
+
normals.push(n[0], n[1], n[2]);
|
|
28026
|
+
uvs.push(u, 1 - v);
|
|
28027
|
+
indexRow.push(index++);
|
|
28028
|
+
}
|
|
28029
|
+
indexArray2.push(indexRow);
|
|
28030
|
+
}
|
|
28031
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
28032
|
+
for (let y = 0; y < heightSegments; y++) {
|
|
28033
|
+
const a = indexArray2[y][x];
|
|
28034
|
+
const b = indexArray2[y + 1][x];
|
|
28035
|
+
const c = indexArray2[y + 1][x + 1];
|
|
28036
|
+
const d = indexArray2[y][x + 1];
|
|
28037
|
+
indices.push(a, b, d);
|
|
28038
|
+
indices.push(b, c, d);
|
|
28039
|
+
groupCount += 6;
|
|
28040
|
+
}
|
|
28041
|
+
}
|
|
28042
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: 0 });
|
|
28043
|
+
groupStart += groupCount;
|
|
28044
|
+
};
|
|
28045
|
+
const generateCap = (top) => {
|
|
28046
|
+
const centerIndexStart = index;
|
|
28047
|
+
let groupCount = 0;
|
|
28048
|
+
const radius = top === true ? radiusTop : radiusBottom;
|
|
28049
|
+
const sign2 = top === true ? 1 : -1;
|
|
28050
|
+
for (let x = 1; x <= radialSegments; x++) {
|
|
28051
|
+
vertices.push(0, halfHeight * sign2, 0);
|
|
28052
|
+
normals.push(0, sign2, 0);
|
|
28053
|
+
uvs.push(0.5, 0.5);
|
|
28054
|
+
index++;
|
|
28055
|
+
}
|
|
28056
|
+
const centerIndexEnd = index;
|
|
28057
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
28058
|
+
const u = x / radialSegments;
|
|
28059
|
+
const theta = u * thetaLength + thetaStart;
|
|
28060
|
+
const cosTheta = Math.cos(theta);
|
|
28061
|
+
const sinTheta = Math.sin(theta);
|
|
28062
|
+
vertices.push(radius * sinTheta, halfHeight * sign2, radius * cosTheta);
|
|
28063
|
+
normals.push(0, sign2, 0);
|
|
28064
|
+
uvs.push(cosTheta * 0.5 + 0.5, sinTheta * 0.5 * sign2 + 0.5);
|
|
28065
|
+
index++;
|
|
28066
|
+
}
|
|
28067
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
28068
|
+
const c = centerIndexStart + x;
|
|
28069
|
+
const i = centerIndexEnd + x;
|
|
28070
|
+
if (top === true) indices.push(i, i + 1, c);
|
|
28071
|
+
else indices.push(i + 1, i, c);
|
|
28072
|
+
groupCount += 3;
|
|
28073
|
+
}
|
|
28074
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: top === true ? 1 : 2 });
|
|
28075
|
+
groupStart += groupCount;
|
|
28076
|
+
};
|
|
28077
|
+
generateTorso();
|
|
28078
|
+
if (openEnded === false) {
|
|
28079
|
+
if (radiusTop > 0) generateCap(true);
|
|
28080
|
+
if (radiusBottom > 0) generateCap(false);
|
|
28081
|
+
}
|
|
28082
|
+
return { vertices, normals, uvs, indices, groups };
|
|
28083
|
+
}
|
|
28084
|
+
function cylinder(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
28085
|
+
const parameters = { radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
28086
|
+
return pack("CylinderGeometry", parameters, cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
28087
|
+
}
|
|
28088
|
+
function cone(radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
28089
|
+
const parameters = { radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
28090
|
+
return pack("ConeGeometry", parameters, cylinderArrays(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
28091
|
+
}
|
|
28092
|
+
function sphere(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
|
|
28093
|
+
const parameters = { radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength };
|
|
28094
|
+
widthSegments = Math.max(3, Math.floor(widthSegments));
|
|
28095
|
+
heightSegments = Math.max(2, Math.floor(heightSegments));
|
|
28096
|
+
const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI);
|
|
28097
|
+
let index = 0;
|
|
28098
|
+
const grid = [];
|
|
28099
|
+
const indices = [];
|
|
28100
|
+
const vertices = [];
|
|
28101
|
+
const normals = [];
|
|
28102
|
+
const uvs = [];
|
|
28103
|
+
for (let iy = 0; iy <= heightSegments; iy++) {
|
|
28104
|
+
const verticesRow = [];
|
|
28105
|
+
const v = iy / heightSegments;
|
|
28106
|
+
let uOffset = 0;
|
|
28107
|
+
if (iy === 0 && thetaStart === 0) uOffset = 0.5 / widthSegments;
|
|
28108
|
+
else if (iy === heightSegments && thetaEnd === Math.PI) uOffset = -0.5 / widthSegments;
|
|
28109
|
+
for (let ix = 0; ix <= widthSegments; ix++) {
|
|
28110
|
+
const u = ix / widthSegments;
|
|
28111
|
+
const x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
28112
|
+
const y = radius * Math.cos(thetaStart + v * thetaLength);
|
|
28113
|
+
const z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
28114
|
+
vertices.push(x, y, z);
|
|
28115
|
+
const n = normalize3(x, y, z);
|
|
28116
|
+
normals.push(n[0], n[1], n[2]);
|
|
28117
|
+
uvs.push(u + uOffset, 1 - v);
|
|
28118
|
+
verticesRow.push(index++);
|
|
28119
|
+
}
|
|
28120
|
+
grid.push(verticesRow);
|
|
28121
|
+
}
|
|
28122
|
+
for (let iy = 0; iy < heightSegments; iy++) {
|
|
28123
|
+
for (let ix = 0; ix < widthSegments; ix++) {
|
|
28124
|
+
const a = grid[iy][ix + 1];
|
|
28125
|
+
const b = grid[iy][ix];
|
|
28126
|
+
const c = grid[iy + 1][ix];
|
|
28127
|
+
const d = grid[iy + 1][ix + 1];
|
|
28128
|
+
if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
|
|
28129
|
+
if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
|
|
28130
|
+
}
|
|
28131
|
+
}
|
|
28132
|
+
return pack("SphereGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28133
|
+
}
|
|
28134
|
+
function plane(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
|
|
28135
|
+
const parameters = { width, height, widthSegments, heightSegments };
|
|
28136
|
+
const widthHalf = width / 2;
|
|
28137
|
+
const heightHalf = height / 2;
|
|
28138
|
+
const gridX = Math.floor(widthSegments);
|
|
28139
|
+
const gridY = Math.floor(heightSegments);
|
|
28140
|
+
const gridX1 = gridX + 1;
|
|
28141
|
+
const gridY1 = gridY + 1;
|
|
28142
|
+
const segmentWidth = width / gridX;
|
|
28143
|
+
const segmentHeight = height / gridY;
|
|
28144
|
+
const indices = [];
|
|
28145
|
+
const vertices = [];
|
|
28146
|
+
const normals = [];
|
|
28147
|
+
const uvs = [];
|
|
28148
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
28149
|
+
const y = iy * segmentHeight - heightHalf;
|
|
28150
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
28151
|
+
const x = ix * segmentWidth - widthHalf;
|
|
28152
|
+
vertices.push(x, -y, 0);
|
|
28153
|
+
normals.push(0, 0, 1);
|
|
28154
|
+
uvs.push(ix / gridX);
|
|
28155
|
+
uvs.push(1 - iy / gridY);
|
|
28156
|
+
}
|
|
28157
|
+
}
|
|
28158
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
28159
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
28160
|
+
const a = ix + gridX1 * iy;
|
|
28161
|
+
const b = ix + gridX1 * (iy + 1);
|
|
28162
|
+
const c = ix + 1 + gridX1 * (iy + 1);
|
|
28163
|
+
const d = ix + 1 + gridX1 * iy;
|
|
28164
|
+
indices.push(a, b, d);
|
|
28165
|
+
indices.push(b, c, d);
|
|
28166
|
+
}
|
|
28167
|
+
}
|
|
28168
|
+
return pack("PlaneGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28169
|
+
}
|
|
28170
|
+
function circle(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
28171
|
+
const parameters = { radius, segments, thetaStart, thetaLength };
|
|
28172
|
+
segments = Math.max(3, segments);
|
|
28173
|
+
const indices = [];
|
|
28174
|
+
const vertices = [];
|
|
28175
|
+
const normals = [];
|
|
28176
|
+
const uvs = [];
|
|
28177
|
+
vertices.push(0, 0, 0);
|
|
28178
|
+
normals.push(0, 0, 1);
|
|
28179
|
+
uvs.push(0.5, 0.5);
|
|
28180
|
+
for (let s = 0, i = 3; s <= segments; s++, i += 3) {
|
|
28181
|
+
const segment = thetaStart + s / segments * thetaLength;
|
|
28182
|
+
vertices.push(radius * Math.cos(segment), radius * Math.sin(segment), 0);
|
|
28183
|
+
normals.push(0, 0, 1);
|
|
28184
|
+
uvs.push((vertices[i] / radius + 1) / 2, (vertices[i + 1] / radius + 1) / 2);
|
|
28185
|
+
}
|
|
28186
|
+
for (let i = 1; i <= segments; i++) indices.push(i, i + 1, 0);
|
|
28187
|
+
return pack("CircleGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28188
|
+
}
|
|
28189
|
+
function ring(innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
28190
|
+
const parameters = { innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength };
|
|
28191
|
+
thetaSegments = Math.max(3, thetaSegments);
|
|
28192
|
+
phiSegments = Math.max(1, phiSegments);
|
|
28193
|
+
const indices = [];
|
|
28194
|
+
const vertices = [];
|
|
28195
|
+
const normals = [];
|
|
28196
|
+
const uvs = [];
|
|
28197
|
+
let radius = innerRadius;
|
|
28198
|
+
const radiusStep = (outerRadius - innerRadius) / phiSegments;
|
|
28199
|
+
for (let j = 0; j <= phiSegments; j++) {
|
|
28200
|
+
for (let i = 0; i <= thetaSegments; i++) {
|
|
28201
|
+
const segment = thetaStart + i / thetaSegments * thetaLength;
|
|
28202
|
+
const x = radius * Math.cos(segment);
|
|
28203
|
+
const y = radius * Math.sin(segment);
|
|
28204
|
+
vertices.push(x, y, 0);
|
|
28205
|
+
normals.push(0, 0, 1);
|
|
28206
|
+
uvs.push((x / outerRadius + 1) / 2, (y / outerRadius + 1) / 2);
|
|
28207
|
+
}
|
|
28208
|
+
radius += radiusStep;
|
|
28209
|
+
}
|
|
28210
|
+
for (let j = 0; j < phiSegments; j++) {
|
|
28211
|
+
const thetaSegmentLevel = j * (thetaSegments + 1);
|
|
28212
|
+
for (let i = 0; i < thetaSegments; i++) {
|
|
28213
|
+
const segment = i + thetaSegmentLevel;
|
|
28214
|
+
const a = segment;
|
|
28215
|
+
const b = segment + thetaSegments + 1;
|
|
28216
|
+
const c = segment + thetaSegments + 2;
|
|
28217
|
+
const d = segment + 1;
|
|
28218
|
+
indices.push(a, b, d);
|
|
28219
|
+
indices.push(b, c, d);
|
|
28220
|
+
}
|
|
28221
|
+
}
|
|
28222
|
+
return pack("RingGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28223
|
+
}
|
|
28224
|
+
function lathe(points, segments = 12, phiStart = 0, phiLength = Math.PI * 2) {
|
|
28225
|
+
const parameters = { points: points.map(([x, y]) => ({ x, y })), segments, phiStart, phiLength };
|
|
28226
|
+
segments = Math.floor(segments);
|
|
28227
|
+
phiLength = Math.max(0, Math.min(Math.PI * 2, phiLength));
|
|
28228
|
+
const indices = [];
|
|
28229
|
+
const vertices = [];
|
|
28230
|
+
const uvs = [];
|
|
28231
|
+
const initNormals = [];
|
|
28232
|
+
const normals = [];
|
|
28233
|
+
const inverseSegments = 1 / segments;
|
|
28234
|
+
const normal = { x: 0, y: 0, z: 0 };
|
|
28235
|
+
const curNormal = { x: 0, y: 0, z: 0 };
|
|
28236
|
+
const prevNormal = { x: 0, y: 0, z: 0 };
|
|
28237
|
+
let dx = 0;
|
|
28238
|
+
let dy = 0;
|
|
28239
|
+
const last = points.length - 1;
|
|
28240
|
+
const px = (j) => points[j][0];
|
|
28241
|
+
const py = (j) => points[j][1];
|
|
28242
|
+
const setNormalized = () => {
|
|
28243
|
+
const n = normalize3(normal.x, normal.y, normal.z);
|
|
28244
|
+
normal.x = n[0];
|
|
28245
|
+
normal.y = n[1];
|
|
28246
|
+
normal.z = n[2];
|
|
28247
|
+
};
|
|
28248
|
+
for (let j = 0; j <= last; j++) {
|
|
28249
|
+
if (j === 0) {
|
|
28250
|
+
dx = px(j + 1) - px(j);
|
|
28251
|
+
dy = py(j + 1) - py(j);
|
|
28252
|
+
normal.x = dy * 1;
|
|
28253
|
+
normal.y = -dx;
|
|
28254
|
+
normal.z = dy * 0;
|
|
28255
|
+
prevNormal.x = normal.x;
|
|
28256
|
+
prevNormal.y = normal.y;
|
|
28257
|
+
prevNormal.z = normal.z;
|
|
28258
|
+
setNormalized();
|
|
28259
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
28260
|
+
} else if (j === last) {
|
|
28261
|
+
initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z);
|
|
28262
|
+
} else {
|
|
28263
|
+
dx = px(j + 1) - px(j);
|
|
28264
|
+
dy = py(j + 1) - py(j);
|
|
28265
|
+
normal.x = dy * 1;
|
|
28266
|
+
normal.y = -dx;
|
|
28267
|
+
normal.z = dy * 0;
|
|
28268
|
+
curNormal.x = normal.x;
|
|
28269
|
+
curNormal.y = normal.y;
|
|
28270
|
+
curNormal.z = normal.z;
|
|
28271
|
+
normal.x += prevNormal.x;
|
|
28272
|
+
normal.y += prevNormal.y;
|
|
28273
|
+
normal.z += prevNormal.z;
|
|
28274
|
+
setNormalized();
|
|
28275
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
28276
|
+
prevNormal.x = curNormal.x;
|
|
28277
|
+
prevNormal.y = curNormal.y;
|
|
28278
|
+
prevNormal.z = curNormal.z;
|
|
28279
|
+
}
|
|
28280
|
+
}
|
|
28281
|
+
for (let i = 0; i <= segments; i++) {
|
|
28282
|
+
const phi = phiStart + i * inverseSegments * phiLength;
|
|
28283
|
+
const sin = Math.sin(phi);
|
|
28284
|
+
const cos = Math.cos(phi);
|
|
28285
|
+
for (let j = 0; j <= last; j++) {
|
|
28286
|
+
vertices.push(px(j) * sin, py(j), px(j) * cos);
|
|
28287
|
+
uvs.push(i / segments, j / (points.length - 1));
|
|
28288
|
+
const x = initNormals[3 * j + 0] * sin;
|
|
28289
|
+
const y = initNormals[3 * j + 1];
|
|
28290
|
+
const z = initNormals[3 * j + 0] * cos;
|
|
28291
|
+
normals.push(x, y, z);
|
|
28292
|
+
}
|
|
28293
|
+
}
|
|
28294
|
+
for (let i = 0; i < segments; i++) {
|
|
28295
|
+
for (let j = 0; j < points.length - 1; j++) {
|
|
28296
|
+
const base = j + i * points.length;
|
|
28297
|
+
const a = base;
|
|
28298
|
+
const b = base + points.length;
|
|
28299
|
+
const c = base + points.length + 1;
|
|
28300
|
+
const d = base + 1;
|
|
28301
|
+
indices.push(a, b, d);
|
|
28302
|
+
indices.push(c, d, b);
|
|
28303
|
+
}
|
|
28304
|
+
}
|
|
28305
|
+
return pack("LatheGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28306
|
+
}
|
|
28307
|
+
function torus(radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2) {
|
|
28308
|
+
const parameters = { radius, tube, radialSegments, tubularSegments, arc };
|
|
28309
|
+
radialSegments = Math.floor(radialSegments);
|
|
28310
|
+
tubularSegments = Math.floor(tubularSegments);
|
|
28311
|
+
const indices = [];
|
|
28312
|
+
const vertices = [];
|
|
28313
|
+
const normals = [];
|
|
28314
|
+
const uvs = [];
|
|
28315
|
+
for (let j = 0; j <= radialSegments; j++) {
|
|
28316
|
+
for (let i = 0; i <= tubularSegments; i++) {
|
|
28317
|
+
const u = i / tubularSegments * arc;
|
|
28318
|
+
const v = j / radialSegments * Math.PI * 2;
|
|
28319
|
+
const x = (radius + tube * Math.cos(v)) * Math.cos(u);
|
|
28320
|
+
const y = (radius + tube * Math.cos(v)) * Math.sin(u);
|
|
28321
|
+
const z = tube * Math.sin(v);
|
|
28322
|
+
vertices.push(x, y, z);
|
|
28323
|
+
const cx = radius * Math.cos(u);
|
|
28324
|
+
const cy = radius * Math.sin(u);
|
|
28325
|
+
const n = normalize3(x - cx, y - cy, z - 0);
|
|
28326
|
+
normals.push(n[0], n[1], n[2]);
|
|
28327
|
+
uvs.push(i / tubularSegments);
|
|
28328
|
+
uvs.push(j / radialSegments);
|
|
28329
|
+
}
|
|
28330
|
+
}
|
|
28331
|
+
for (let j = 1; j <= radialSegments; j++) {
|
|
28332
|
+
for (let i = 1; i <= tubularSegments; i++) {
|
|
28333
|
+
const a = (tubularSegments + 1) * j + i - 1;
|
|
28334
|
+
const b = (tubularSegments + 1) * (j - 1) + i - 1;
|
|
28335
|
+
const c = (tubularSegments + 1) * (j - 1) + i;
|
|
28336
|
+
const d = (tubularSegments + 1) * j + i;
|
|
28337
|
+
indices.push(a, b, d);
|
|
28338
|
+
indices.push(b, c, d);
|
|
28339
|
+
}
|
|
28340
|
+
}
|
|
28341
|
+
return pack("TorusGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
28342
|
+
}
|
|
28343
|
+
function difference(size, subtract) {
|
|
28344
|
+
const [w, h, d] = size;
|
|
28345
|
+
const hw = w / 2;
|
|
28346
|
+
const hh = h / 2;
|
|
28347
|
+
const hd = d / 2;
|
|
28348
|
+
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);
|
|
28349
|
+
const cuts = (lo, hi, values) => [.../* @__PURE__ */ new Set([lo, hi, ...values.filter((v) => v > lo && v < hi)])].sort((a, b) => a - b);
|
|
28350
|
+
const xs = cuts(-hw, hw, holes.flatMap((hole) => [hole.x0, hole.x1]));
|
|
28351
|
+
const ys = cuts(-hh, hh, holes.flatMap((hole) => [hole.y0, hole.y1]));
|
|
28352
|
+
const nx = xs.length - 1;
|
|
28353
|
+
const ny = ys.length - 1;
|
|
28354
|
+
const solid = (i, j) => {
|
|
28355
|
+
if (i < 0 || j < 0 || i >= nx || j >= ny) return false;
|
|
28356
|
+
const cx = (xs[i] + xs[i + 1]) / 2;
|
|
28357
|
+
const cy = (ys[j] + ys[j + 1]) / 2;
|
|
28358
|
+
return !holes.some((hole) => cx > hole.x0 && cx < hole.x1 && cy > hole.y0 && cy < hole.y1);
|
|
28359
|
+
};
|
|
28360
|
+
const positions = [];
|
|
28361
|
+
const normals = [];
|
|
28362
|
+
const uvs = [];
|
|
28363
|
+
const indices = [];
|
|
28364
|
+
const quad = (corners, normal, uv) => {
|
|
28365
|
+
const base = positions.length / 3;
|
|
28366
|
+
for (let k = 0; k < 4; k++) {
|
|
28367
|
+
positions.push(...corners[k]);
|
|
28368
|
+
normals.push(...normal);
|
|
28369
|
+
uvs.push(...uv[k]);
|
|
28370
|
+
}
|
|
28371
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
28372
|
+
};
|
|
28373
|
+
const fu = (x) => (x + hw) / w;
|
|
28374
|
+
const fv = (y) => (y + hh) / h;
|
|
28375
|
+
for (let j = 0; j < ny; j++) {
|
|
28376
|
+
for (let i = 0; i < nx; i++) {
|
|
28377
|
+
if (!solid(i, j)) continue;
|
|
28378
|
+
const x0 = xs[i];
|
|
28379
|
+
const x1 = xs[i + 1];
|
|
28380
|
+
const y0 = ys[j];
|
|
28381
|
+
const y1 = ys[j + 1];
|
|
28382
|
+
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)]]);
|
|
28383
|
+
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)]]);
|
|
28384
|
+
const zu = (z) => (z + hd) / d;
|
|
28385
|
+
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)]]);
|
|
28386
|
+
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)]]);
|
|
28387
|
+
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)]]);
|
|
28388
|
+
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)]]);
|
|
28389
|
+
}
|
|
28390
|
+
}
|
|
28391
|
+
return {
|
|
28392
|
+
type: "BufferGeometry",
|
|
28393
|
+
parameters: { size: [w, h, d], subtract: holes.map((hole) => ({ min: [hole.x0, hole.y0], max: [hole.x1, hole.y1] })) },
|
|
28394
|
+
positions: new Float32Array(positions),
|
|
28395
|
+
normals: new Float32Array(normals),
|
|
28396
|
+
uvs: new Float32Array(uvs),
|
|
28397
|
+
indices: indexArray(indices),
|
|
28398
|
+
groups: []
|
|
28399
|
+
};
|
|
28400
|
+
}
|
|
28401
|
+
var Earcut = {
|
|
28402
|
+
triangulate: function(data, holeIndices, dim = 2) {
|
|
28403
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
28404
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
28405
|
+
let outerNode = linkedList(data, 0, outerLen, dim, true);
|
|
28406
|
+
const triangles = [];
|
|
28407
|
+
if (!outerNode || outerNode.next === outerNode.prev) return triangles;
|
|
28408
|
+
let minX, minY, maxX, maxY, x, y, invSize;
|
|
28409
|
+
if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
|
|
28410
|
+
if (data.length > 80 * dim) {
|
|
28411
|
+
minX = maxX = data[0];
|
|
28412
|
+
minY = maxY = data[1];
|
|
28413
|
+
for (let i = dim; i < outerLen; i += dim) {
|
|
28414
|
+
x = data[i];
|
|
28415
|
+
y = data[i + 1];
|
|
28416
|
+
if (x < minX) minX = x;
|
|
28417
|
+
if (y < minY) minY = y;
|
|
28418
|
+
if (x > maxX) maxX = x;
|
|
28419
|
+
if (y > maxY) maxY = y;
|
|
28420
|
+
}
|
|
28421
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
28422
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
|
28423
|
+
}
|
|
28424
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
|
28425
|
+
return triangles;
|
|
28426
|
+
}
|
|
28427
|
+
};
|
|
28428
|
+
function linkedList(data, start, end, dim, clockwise) {
|
|
28429
|
+
let i, last;
|
|
28430
|
+
if (clockwise === signedArea(data, start, end, dim) > 0) {
|
|
28431
|
+
for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
28432
|
+
} else {
|
|
28433
|
+
for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
28434
|
+
}
|
|
28435
|
+
if (last && equals(last, last.next)) {
|
|
28436
|
+
removeNode(last);
|
|
28437
|
+
last = last.next;
|
|
28438
|
+
}
|
|
28439
|
+
return last;
|
|
28440
|
+
}
|
|
28441
|
+
function filterPoints(start, end) {
|
|
28442
|
+
if (!start) return start;
|
|
28443
|
+
if (!end) end = start;
|
|
28444
|
+
let p = start, again;
|
|
28445
|
+
do {
|
|
28446
|
+
again = false;
|
|
28447
|
+
if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
|
|
28448
|
+
removeNode(p);
|
|
28449
|
+
p = end = p.prev;
|
|
28450
|
+
if (p === p.next) break;
|
|
28451
|
+
again = true;
|
|
28452
|
+
} else {
|
|
28453
|
+
p = p.next;
|
|
28454
|
+
}
|
|
28455
|
+
} while (again || p !== end);
|
|
28456
|
+
return end;
|
|
28457
|
+
}
|
|
28458
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
28459
|
+
if (!ear) return;
|
|
28460
|
+
if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
|
|
28461
|
+
let stop = ear, prev, next;
|
|
28462
|
+
while (ear.prev !== ear.next) {
|
|
28463
|
+
prev = ear.prev;
|
|
28464
|
+
next = ear.next;
|
|
28465
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
28466
|
+
triangles.push(prev.i / dim | 0);
|
|
28467
|
+
triangles.push(ear.i / dim | 0);
|
|
28468
|
+
triangles.push(next.i / dim | 0);
|
|
28469
|
+
removeNode(ear);
|
|
28470
|
+
ear = next.next;
|
|
28471
|
+
stop = next.next;
|
|
28472
|
+
continue;
|
|
28473
|
+
}
|
|
28474
|
+
ear = next;
|
|
28475
|
+
if (ear === stop) {
|
|
28476
|
+
if (!pass) {
|
|
28477
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
28478
|
+
} else if (pass === 1) {
|
|
28479
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
28480
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
28481
|
+
} else if (pass === 2) {
|
|
28482
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
28483
|
+
}
|
|
28484
|
+
break;
|
|
28485
|
+
}
|
|
28486
|
+
}
|
|
28487
|
+
}
|
|
28488
|
+
function isEar(ear) {
|
|
28489
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
28490
|
+
if (area(a, b, c) >= 0) return false;
|
|
28491
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
28492
|
+
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;
|
|
28493
|
+
let p = c.next;
|
|
28494
|
+
while (p !== a) {
|
|
28495
|
+
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;
|
|
28496
|
+
p = p.next;
|
|
28497
|
+
}
|
|
28498
|
+
return true;
|
|
28499
|
+
}
|
|
28500
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
28501
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
28502
|
+
if (area(a, b, c) >= 0) return false;
|
|
28503
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
28504
|
+
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;
|
|
28505
|
+
const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
28506
|
+
let p = ear.prevZ, n = ear.nextZ;
|
|
28507
|
+
while (p && p.z >= minZ && n && n.z <= maxZ) {
|
|
28508
|
+
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;
|
|
28509
|
+
p = p.prevZ;
|
|
28510
|
+
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;
|
|
28511
|
+
n = n.nextZ;
|
|
28512
|
+
}
|
|
28513
|
+
while (p && p.z >= minZ) {
|
|
28514
|
+
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;
|
|
28515
|
+
p = p.prevZ;
|
|
28516
|
+
}
|
|
28517
|
+
while (n && n.z <= maxZ) {
|
|
28518
|
+
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;
|
|
28519
|
+
n = n.nextZ;
|
|
28520
|
+
}
|
|
28521
|
+
return true;
|
|
28522
|
+
}
|
|
28523
|
+
function cureLocalIntersections(start, triangles, dim) {
|
|
28524
|
+
let p = start;
|
|
28525
|
+
do {
|
|
28526
|
+
const a = p.prev, b = p.next.next;
|
|
28527
|
+
if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
28528
|
+
triangles.push(a.i / dim | 0);
|
|
28529
|
+
triangles.push(p.i / dim | 0);
|
|
28530
|
+
triangles.push(b.i / dim | 0);
|
|
28531
|
+
removeNode(p);
|
|
28532
|
+
removeNode(p.next);
|
|
28533
|
+
p = start = b;
|
|
28534
|
+
}
|
|
28535
|
+
p = p.next;
|
|
28536
|
+
} while (p !== start);
|
|
28537
|
+
return filterPoints(p);
|
|
28538
|
+
}
|
|
28539
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
28540
|
+
let a = start;
|
|
28541
|
+
do {
|
|
28542
|
+
let b = a.next.next;
|
|
28543
|
+
while (b !== a.prev) {
|
|
28544
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
28545
|
+
let c = splitPolygon(a, b);
|
|
28546
|
+
a = filterPoints(a, a.next);
|
|
28547
|
+
c = filterPoints(c, c.next);
|
|
28548
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
28549
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
28550
|
+
return;
|
|
28551
|
+
}
|
|
28552
|
+
b = b.next;
|
|
28553
|
+
}
|
|
28554
|
+
a = a.next;
|
|
28555
|
+
} while (a !== start);
|
|
28556
|
+
}
|
|
28557
|
+
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
28558
|
+
const queue = [];
|
|
28559
|
+
let i, len, start, end, list2;
|
|
28560
|
+
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
28561
|
+
start = holeIndices[i] * dim;
|
|
28562
|
+
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
28563
|
+
list2 = linkedList(data, start, end, dim, false);
|
|
28564
|
+
if (list2 === list2.next) list2.steiner = true;
|
|
28565
|
+
queue.push(getLeftmost(list2));
|
|
28566
|
+
}
|
|
28567
|
+
queue.sort(compareX);
|
|
28568
|
+
for (i = 0; i < queue.length; i++) {
|
|
28569
|
+
outerNode = eliminateHole(queue[i], outerNode);
|
|
28570
|
+
}
|
|
28571
|
+
return outerNode;
|
|
28572
|
+
}
|
|
28573
|
+
function compareX(a, b) {
|
|
28574
|
+
return a.x - b.x;
|
|
28575
|
+
}
|
|
28576
|
+
function eliminateHole(hole, outerNode) {
|
|
28577
|
+
const bridge = findHoleBridge(hole, outerNode);
|
|
28578
|
+
if (!bridge) {
|
|
28579
|
+
return outerNode;
|
|
28580
|
+
}
|
|
28581
|
+
const bridgeReverse = splitPolygon(bridge, hole);
|
|
28582
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
|
28583
|
+
return filterPoints(bridge, bridge.next);
|
|
28584
|
+
}
|
|
28585
|
+
function findHoleBridge(hole, outerNode) {
|
|
28586
|
+
let p = outerNode, qx = -Infinity, m;
|
|
28587
|
+
const hx = hole.x, hy = hole.y;
|
|
28588
|
+
do {
|
|
28589
|
+
if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
|
|
28590
|
+
const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
|
|
28591
|
+
if (x <= hx && x > qx) {
|
|
28592
|
+
qx = x;
|
|
28593
|
+
m = p.x < p.next.x ? p : p.next;
|
|
28594
|
+
if (x === hx) return m;
|
|
28595
|
+
}
|
|
28596
|
+
}
|
|
28597
|
+
p = p.next;
|
|
28598
|
+
} while (p !== outerNode);
|
|
28599
|
+
if (!m) return null;
|
|
28600
|
+
const stop = m, mx = m.x, my = m.y;
|
|
28601
|
+
let tanMin = Infinity, tan;
|
|
28602
|
+
p = m;
|
|
28603
|
+
do {
|
|
28604
|
+
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)) {
|
|
28605
|
+
tan = Math.abs(hy - p.y) / (hx - p.x);
|
|
28606
|
+
if (locallyInside(p, hole) && (tan < tanMin || tan === tanMin && (p.x > m.x || p.x === m.x && sectorContainsSector(m, p)))) {
|
|
28607
|
+
m = p;
|
|
28608
|
+
tanMin = tan;
|
|
28609
|
+
}
|
|
28610
|
+
}
|
|
28611
|
+
p = p.next;
|
|
28612
|
+
} while (p !== stop);
|
|
28613
|
+
return m;
|
|
28614
|
+
}
|
|
28615
|
+
function sectorContainsSector(m, p) {
|
|
28616
|
+
return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
|
|
28617
|
+
}
|
|
28618
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
28619
|
+
let p = start;
|
|
28620
|
+
do {
|
|
28621
|
+
if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
|
|
28622
|
+
p.prevZ = p.prev;
|
|
28623
|
+
p.nextZ = p.next;
|
|
28624
|
+
p = p.next;
|
|
28625
|
+
} while (p !== start);
|
|
28626
|
+
p.prevZ.nextZ = null;
|
|
28627
|
+
p.prevZ = null;
|
|
28628
|
+
sortLinked(p);
|
|
28629
|
+
}
|
|
28630
|
+
function sortLinked(list2) {
|
|
28631
|
+
let i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1;
|
|
28632
|
+
do {
|
|
28633
|
+
p = list2;
|
|
28634
|
+
list2 = null;
|
|
28635
|
+
tail = null;
|
|
28636
|
+
numMerges = 0;
|
|
28637
|
+
while (p) {
|
|
28638
|
+
numMerges++;
|
|
28639
|
+
q = p;
|
|
28640
|
+
pSize = 0;
|
|
28641
|
+
for (i = 0; i < inSize; i++) {
|
|
28642
|
+
pSize++;
|
|
28643
|
+
q = q.nextZ;
|
|
28644
|
+
if (!q) break;
|
|
28645
|
+
}
|
|
28646
|
+
qSize = inSize;
|
|
28647
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
28648
|
+
if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
|
|
28649
|
+
e = p;
|
|
28650
|
+
p = p.nextZ;
|
|
28651
|
+
pSize--;
|
|
28652
|
+
} else {
|
|
28653
|
+
e = q;
|
|
28654
|
+
q = q.nextZ;
|
|
28655
|
+
qSize--;
|
|
28656
|
+
}
|
|
28657
|
+
if (tail) tail.nextZ = e;
|
|
28658
|
+
else list2 = e;
|
|
28659
|
+
e.prevZ = tail;
|
|
28660
|
+
tail = e;
|
|
28661
|
+
}
|
|
28662
|
+
p = q;
|
|
28663
|
+
}
|
|
28664
|
+
tail.nextZ = null;
|
|
28665
|
+
inSize *= 2;
|
|
28666
|
+
} while (numMerges > 1);
|
|
28667
|
+
return list2;
|
|
28668
|
+
}
|
|
28669
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
28670
|
+
x = (x - minX) * invSize | 0;
|
|
28671
|
+
y = (y - minY) * invSize | 0;
|
|
28672
|
+
x = (x | x << 8) & 16711935;
|
|
28673
|
+
x = (x | x << 4) & 252645135;
|
|
28674
|
+
x = (x | x << 2) & 858993459;
|
|
28675
|
+
x = (x | x << 1) & 1431655765;
|
|
28676
|
+
y = (y | y << 8) & 16711935;
|
|
28677
|
+
y = (y | y << 4) & 252645135;
|
|
28678
|
+
y = (y | y << 2) & 858993459;
|
|
28679
|
+
y = (y | y << 1) & 1431655765;
|
|
28680
|
+
return x | y << 1;
|
|
28681
|
+
}
|
|
28682
|
+
function getLeftmost(start) {
|
|
28683
|
+
let p = start, leftmost = start;
|
|
28684
|
+
do {
|
|
28685
|
+
if (p.x < leftmost.x || p.x === leftmost.x && p.y < leftmost.y) leftmost = p;
|
|
28686
|
+
p = p.next;
|
|
28687
|
+
} while (p !== start);
|
|
28688
|
+
return leftmost;
|
|
28689
|
+
}
|
|
28690
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
28691
|
+
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);
|
|
28692
|
+
}
|
|
28693
|
+
function isValidDiagonal(a, b) {
|
|
28694
|
+
return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
|
|
28695
|
+
(locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
|
|
28696
|
+
(area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
|
|
28697
|
+
equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
|
|
28698
|
+
}
|
|
28699
|
+
function area(p, q, r) {
|
|
28700
|
+
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
28701
|
+
}
|
|
28702
|
+
function equals(p1, p2) {
|
|
28703
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
28704
|
+
}
|
|
28705
|
+
function intersects(p1, q1, p2, q2) {
|
|
28706
|
+
const o1 = sign(area(p1, q1, p2));
|
|
28707
|
+
const o2 = sign(area(p1, q1, q2));
|
|
28708
|
+
const o3 = sign(area(p2, q2, p1));
|
|
28709
|
+
const o4 = sign(area(p2, q2, q1));
|
|
28710
|
+
if (o1 !== o2 && o3 !== o4) return true;
|
|
28711
|
+
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
28712
|
+
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
28713
|
+
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
28714
|
+
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
28715
|
+
return false;
|
|
28716
|
+
}
|
|
28717
|
+
function onSegment(p, q, r) {
|
|
28718
|
+
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);
|
|
28719
|
+
}
|
|
28720
|
+
function sign(num2) {
|
|
28721
|
+
return num2 > 0 ? 1 : num2 < 0 ? -1 : 0;
|
|
28722
|
+
}
|
|
28723
|
+
function intersectsPolygon(a, b) {
|
|
28724
|
+
let p = a;
|
|
28725
|
+
do {
|
|
28726
|
+
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;
|
|
28727
|
+
p = p.next;
|
|
28728
|
+
} while (p !== a);
|
|
28729
|
+
return false;
|
|
28730
|
+
}
|
|
28731
|
+
function locallyInside(a, b) {
|
|
28732
|
+
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;
|
|
28733
|
+
}
|
|
28734
|
+
function middleInside(a, b) {
|
|
28735
|
+
let p = a, inside = false;
|
|
28736
|
+
const px = (a.x + b.x) / 2, py = (a.y + b.y) / 2;
|
|
28737
|
+
do {
|
|
28738
|
+
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)
|
|
28739
|
+
inside = !inside;
|
|
28740
|
+
p = p.next;
|
|
28741
|
+
} while (p !== a);
|
|
28742
|
+
return inside;
|
|
28743
|
+
}
|
|
28744
|
+
function splitPolygon(a, b) {
|
|
28745
|
+
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;
|
|
28746
|
+
a.next = b;
|
|
28747
|
+
b.prev = a;
|
|
28748
|
+
a2.next = an;
|
|
28749
|
+
an.prev = a2;
|
|
28750
|
+
b2.next = a2;
|
|
28751
|
+
a2.prev = b2;
|
|
28752
|
+
bp.next = b2;
|
|
28753
|
+
b2.prev = bp;
|
|
28754
|
+
return b2;
|
|
28755
|
+
}
|
|
28756
|
+
function insertNode(i, x, y, last) {
|
|
28757
|
+
const p = new Node(i, x, y);
|
|
28758
|
+
if (!last) {
|
|
28759
|
+
p.prev = p;
|
|
28760
|
+
p.next = p;
|
|
28761
|
+
} else {
|
|
28762
|
+
p.next = last.next;
|
|
28763
|
+
p.prev = last;
|
|
28764
|
+
last.next.prev = p;
|
|
28765
|
+
last.next = p;
|
|
28766
|
+
}
|
|
28767
|
+
return p;
|
|
28768
|
+
}
|
|
28769
|
+
function removeNode(p) {
|
|
28770
|
+
p.next.prev = p.prev;
|
|
28771
|
+
p.prev.next = p.next;
|
|
28772
|
+
if (p.prevZ) p.prevZ.nextZ = p.nextZ;
|
|
28773
|
+
if (p.nextZ) p.nextZ.prevZ = p.prevZ;
|
|
28774
|
+
}
|
|
28775
|
+
function Node(i, x, y) {
|
|
28776
|
+
this.i = i;
|
|
28777
|
+
this.x = x;
|
|
28778
|
+
this.y = y;
|
|
28779
|
+
this.prev = null;
|
|
28780
|
+
this.next = null;
|
|
28781
|
+
this.z = 0;
|
|
28782
|
+
this.prevZ = null;
|
|
28783
|
+
this.nextZ = null;
|
|
28784
|
+
this.steiner = false;
|
|
28785
|
+
}
|
|
28786
|
+
function signedArea(data, start, end, dim) {
|
|
28787
|
+
let sum = 0;
|
|
28788
|
+
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
28789
|
+
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
28790
|
+
j = i;
|
|
28791
|
+
}
|
|
28792
|
+
return sum;
|
|
28793
|
+
}
|
|
28794
|
+
var equals2 = (a, b) => a.x === b.x && a.y === b.y;
|
|
28795
|
+
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 };
|
|
28796
|
+
function pathPoints(points) {
|
|
28797
|
+
const out = [];
|
|
28798
|
+
let last;
|
|
28799
|
+
for (let i = 1; i < points.length; i++) {
|
|
28800
|
+
const v1 = { x: points[i - 1][0], y: points[i - 1][1] };
|
|
28801
|
+
const v2 = { x: points[i][0], y: points[i][1] };
|
|
28802
|
+
for (let d = 0; d <= 1; d++) {
|
|
28803
|
+
const point = linePoint(v1, v2, d / 1);
|
|
28804
|
+
if (last && equals2(last, point)) continue;
|
|
28805
|
+
out.push(point);
|
|
28806
|
+
last = point;
|
|
28807
|
+
}
|
|
28808
|
+
}
|
|
28809
|
+
return out;
|
|
28810
|
+
}
|
|
28811
|
+
function area2(contour) {
|
|
28812
|
+
const n = contour.length;
|
|
28813
|
+
let a = 0;
|
|
28814
|
+
for (let p = n - 1, q = 0; q < n; p = q++) a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
|
|
28815
|
+
return a * 0.5;
|
|
28816
|
+
}
|
|
28817
|
+
var isClockWise = (pts) => area2(pts) < 0;
|
|
28818
|
+
function removeDupEndPts(points) {
|
|
28819
|
+
const l = points.length;
|
|
28820
|
+
if (l > 2 && equals2(points[l - 1], points[0])) points.pop();
|
|
28821
|
+
}
|
|
28822
|
+
function triangulateShape(contour, holes) {
|
|
28823
|
+
const vertices = [];
|
|
28824
|
+
const holeIndices = [];
|
|
28825
|
+
const faces = [];
|
|
28826
|
+
removeDupEndPts(contour);
|
|
28827
|
+
for (const p of contour) vertices.push(p.x, p.y);
|
|
28828
|
+
let holeIndex = contour.length;
|
|
28829
|
+
holes.forEach(removeDupEndPts);
|
|
28830
|
+
for (let i = 0; i < holes.length; i++) {
|
|
28831
|
+
holeIndices.push(holeIndex);
|
|
28832
|
+
holeIndex += holes[i].length;
|
|
28833
|
+
for (const p of holes[i]) vertices.push(p.x, p.y);
|
|
28834
|
+
}
|
|
28835
|
+
const triangles = Earcut.triangulate(vertices, holeIndices);
|
|
28836
|
+
for (let i = 0; i < triangles.length; i += 3) faces.push(triangles.slice(i, i + 3));
|
|
28837
|
+
return faces;
|
|
28838
|
+
}
|
|
28839
|
+
function computeVertexNormals(positions, indices) {
|
|
28840
|
+
const normals = new Float32Array(positions.length);
|
|
28841
|
+
const get = (array, i) => [array[i * 3], array[i * 3 + 1], array[i * 3 + 2]];
|
|
28842
|
+
const face = (vA, vB, vC) => {
|
|
28843
|
+
const pA = get(positions, vA);
|
|
28844
|
+
const pB = get(positions, vB);
|
|
28845
|
+
const pC = get(positions, vC);
|
|
28846
|
+
const cb = [pC[0] - pB[0], pC[1] - pB[1], pC[2] - pB[2]];
|
|
28847
|
+
const ab = [pA[0] - pB[0], pA[1] - pB[1], pA[2] - pB[2]];
|
|
28848
|
+
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]];
|
|
28849
|
+
};
|
|
28850
|
+
const set = (i, x, y, z) => {
|
|
28851
|
+
normals[i * 3] = x;
|
|
28852
|
+
normals[i * 3 + 1] = y;
|
|
28853
|
+
normals[i * 3 + 2] = z;
|
|
28854
|
+
};
|
|
28855
|
+
if (indices) {
|
|
28856
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
28857
|
+
const vA = indices[i];
|
|
28858
|
+
const vB = indices[i + 1];
|
|
28859
|
+
const vC = indices[i + 2];
|
|
28860
|
+
const cb = face(vA, vB, vC);
|
|
28861
|
+
for (const v of [vA, vB, vC]) {
|
|
28862
|
+
const n = get(normals, v);
|
|
28863
|
+
set(v, n[0] + cb[0], n[1] + cb[1], n[2] + cb[2]);
|
|
28864
|
+
}
|
|
28865
|
+
}
|
|
28866
|
+
} else {
|
|
28867
|
+
for (let i = 0; i < positions.length / 3; i += 3) {
|
|
28868
|
+
const cb = face(i, i + 1, i + 2);
|
|
28869
|
+
set(i, cb[0], cb[1], cb[2]);
|
|
28870
|
+
set(i + 1, cb[0], cb[1], cb[2]);
|
|
28871
|
+
set(i + 2, cb[0], cb[1], cb[2]);
|
|
28872
|
+
}
|
|
28873
|
+
}
|
|
28874
|
+
for (let i = 0; i < normals.length / 3; i++) {
|
|
28875
|
+
const [x, y, z] = get(normals, i);
|
|
28876
|
+
const s = 1 / (Math.sqrt(x * x + y * y + z * z) || 1);
|
|
28877
|
+
set(i, x * s, y * s, z * s);
|
|
28878
|
+
}
|
|
28879
|
+
return normals;
|
|
28880
|
+
}
|
|
28881
|
+
function extrude(outline, depth = 1, steps = 1, bevel = void 0) {
|
|
28882
|
+
const parameters = { shape: outline, depth, steps, bevel: bevel ?? {} };
|
|
28883
|
+
const verticesArray = [];
|
|
28884
|
+
const uvArray = [];
|
|
28885
|
+
const groups = [];
|
|
28886
|
+
const placeholder = [];
|
|
28887
|
+
const bevelEnabled = bevel !== false;
|
|
28888
|
+
const spec = bevel === false || bevel === void 0 ? {} : bevel;
|
|
28889
|
+
let bevelThickness = spec.thickness !== void 0 ? spec.thickness : 0.2;
|
|
28890
|
+
let bevelSize = spec.size !== void 0 ? spec.size : bevelThickness - 0.1;
|
|
28891
|
+
let bevelOffset = spec.offset !== void 0 ? spec.offset : 0;
|
|
28892
|
+
let bevelSegments = spec.segments !== void 0 ? spec.segments : 3;
|
|
28893
|
+
if (!bevelEnabled) {
|
|
28894
|
+
bevelSegments = 0;
|
|
28895
|
+
bevelThickness = 0;
|
|
28896
|
+
bevelSize = 0;
|
|
28897
|
+
bevelOffset = 0;
|
|
28898
|
+
}
|
|
28899
|
+
let vertices = pathPoints(outline.outer);
|
|
28900
|
+
const holes = (outline.holes ?? []).map(pathPoints);
|
|
28901
|
+
const reverse = !isClockWise(vertices);
|
|
28902
|
+
if (reverse) {
|
|
28903
|
+
vertices = vertices.reverse();
|
|
28904
|
+
for (let h = 0; h < holes.length; h++) {
|
|
28905
|
+
const ahole = holes[h];
|
|
28906
|
+
if (isClockWise(ahole)) holes[h] = ahole.reverse();
|
|
28907
|
+
}
|
|
28908
|
+
}
|
|
28909
|
+
const faces = triangulateShape(vertices, holes);
|
|
28910
|
+
const contour = vertices;
|
|
28911
|
+
for (const ahole of holes) vertices = vertices.concat(ahole);
|
|
28912
|
+
const scalePt2 = (pt, vec, size) => ({ x: pt.x + vec.x * size, y: pt.y + vec.y * size });
|
|
28913
|
+
const vlen = vertices.length;
|
|
28914
|
+
const flen = faces.length;
|
|
28915
|
+
const getBevelVec = (inPt, inPrev, inNext) => {
|
|
28916
|
+
let vTransX;
|
|
28917
|
+
let vTransY;
|
|
28918
|
+
let shrinkBy;
|
|
28919
|
+
const vPrevX = inPt.x - inPrev.x;
|
|
28920
|
+
const vPrevY = inPt.y - inPrev.y;
|
|
28921
|
+
const vNextX = inNext.x - inPt.x;
|
|
28922
|
+
const vNextY = inNext.y - inPt.y;
|
|
28923
|
+
const vPrevLensq = vPrevX * vPrevX + vPrevY * vPrevY;
|
|
28924
|
+
const collinear0 = vPrevX * vNextY - vPrevY * vNextX;
|
|
28925
|
+
if (Math.abs(collinear0) > Number.EPSILON) {
|
|
28926
|
+
const vPrevLen = Math.sqrt(vPrevLensq);
|
|
28927
|
+
const vNextLen = Math.sqrt(vNextX * vNextX + vNextY * vNextY);
|
|
28928
|
+
const ptPrevShiftX = inPrev.x - vPrevY / vPrevLen;
|
|
28929
|
+
const ptPrevShiftY = inPrev.y + vPrevX / vPrevLen;
|
|
28930
|
+
const ptNextShiftX = inNext.x - vNextY / vNextLen;
|
|
28931
|
+
const ptNextShiftY = inNext.y + vNextX / vNextLen;
|
|
28932
|
+
const sf = ((ptNextShiftX - ptPrevShiftX) * vNextY - (ptNextShiftY - ptPrevShiftY) * vNextX) / (vPrevX * vNextY - vPrevY * vNextX);
|
|
28933
|
+
vTransX = ptPrevShiftX + vPrevX * sf - inPt.x;
|
|
28934
|
+
vTransY = ptPrevShiftY + vPrevY * sf - inPt.y;
|
|
28935
|
+
const vTransLensq = vTransX * vTransX + vTransY * vTransY;
|
|
28936
|
+
if (vTransLensq <= 2) return { x: vTransX, y: vTransY };
|
|
28937
|
+
shrinkBy = Math.sqrt(vTransLensq / 2);
|
|
28938
|
+
} else {
|
|
28939
|
+
let directionEq = false;
|
|
28940
|
+
if (vPrevX > Number.EPSILON) {
|
|
28941
|
+
if (vNextX > Number.EPSILON) directionEq = true;
|
|
28942
|
+
} else if (vPrevX < -Number.EPSILON) {
|
|
28943
|
+
if (vNextX < -Number.EPSILON) directionEq = true;
|
|
28944
|
+
} else if (Math.sign(vPrevY) === Math.sign(vNextY)) {
|
|
28945
|
+
directionEq = true;
|
|
28946
|
+
}
|
|
28947
|
+
if (directionEq) {
|
|
28948
|
+
vTransX = -vPrevY;
|
|
28949
|
+
vTransY = vPrevX;
|
|
28950
|
+
shrinkBy = Math.sqrt(vPrevLensq);
|
|
28951
|
+
} else {
|
|
28952
|
+
vTransX = vPrevX;
|
|
28953
|
+
vTransY = vPrevY;
|
|
28954
|
+
shrinkBy = Math.sqrt(vPrevLensq / 2);
|
|
28955
|
+
}
|
|
28956
|
+
}
|
|
28957
|
+
return { x: vTransX / shrinkBy, y: vTransY / shrinkBy };
|
|
28958
|
+
};
|
|
28959
|
+
const movements = (ring2) => {
|
|
28960
|
+
const out = [];
|
|
28961
|
+
for (let i = 0, il = ring2.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
|
|
28962
|
+
if (j === il) j = 0;
|
|
28963
|
+
if (k === il) k = 0;
|
|
28964
|
+
out[i] = getBevelVec(ring2[i], ring2[j], ring2[k]);
|
|
28965
|
+
}
|
|
28966
|
+
return out;
|
|
28967
|
+
};
|
|
28968
|
+
const contourMovements = movements(contour);
|
|
28969
|
+
const holesMovements = [];
|
|
28970
|
+
let verticesMovements = contourMovements.concat();
|
|
28971
|
+
for (const ahole of holes) {
|
|
28972
|
+
const oneHoleMovements = movements(ahole);
|
|
28973
|
+
holesMovements.push(oneHoleMovements);
|
|
28974
|
+
verticesMovements = verticesMovements.concat(oneHoleMovements);
|
|
28975
|
+
}
|
|
28976
|
+
const v = (x, y, z) => {
|
|
28977
|
+
placeholder.push(x);
|
|
28978
|
+
placeholder.push(y);
|
|
28979
|
+
placeholder.push(z);
|
|
28980
|
+
};
|
|
28981
|
+
const bevelLayer = (b, zOf) => {
|
|
28982
|
+
const t = b / bevelSegments;
|
|
28983
|
+
const z = bevelThickness * Math.cos(t * Math.PI / 2);
|
|
28984
|
+
const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
|
|
28985
|
+
for (let i = 0; i < contour.length; i++) {
|
|
28986
|
+
const vert = scalePt2(contour[i], contourMovements[i], bs2);
|
|
28987
|
+
v(vert.x, vert.y, zOf(z));
|
|
28988
|
+
}
|
|
28989
|
+
for (let h = 0; h < holes.length; h++) {
|
|
28990
|
+
const ahole = holes[h];
|
|
28991
|
+
const oneHoleMovements = holesMovements[h];
|
|
28992
|
+
for (let i = 0; i < ahole.length; i++) {
|
|
28993
|
+
const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
|
|
28994
|
+
v(vert.x, vert.y, zOf(z));
|
|
28995
|
+
}
|
|
28996
|
+
}
|
|
28997
|
+
};
|
|
28998
|
+
for (let b = 0; b < bevelSegments; b++) bevelLayer(b, (z) => -z);
|
|
28999
|
+
const bs = bevelSize + bevelOffset;
|
|
29000
|
+
for (let i = 0; i < vlen; i++) {
|
|
29001
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
29002
|
+
v(vert.x, vert.y, 0);
|
|
29003
|
+
}
|
|
29004
|
+
for (let s = 1; s <= steps; s++) {
|
|
29005
|
+
for (let i = 0; i < vlen; i++) {
|
|
29006
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
29007
|
+
v(vert.x, vert.y, depth / steps * s);
|
|
29008
|
+
}
|
|
29009
|
+
}
|
|
29010
|
+
for (let b = bevelSegments - 1; b >= 0; b--) bevelLayer(b, (z) => depth + z);
|
|
29011
|
+
const addVertex = (index) => {
|
|
29012
|
+
verticesArray.push(placeholder[index * 3 + 0]);
|
|
29013
|
+
verticesArray.push(placeholder[index * 3 + 1]);
|
|
29014
|
+
verticesArray.push(placeholder[index * 3 + 2]);
|
|
29015
|
+
};
|
|
29016
|
+
const addUV = (x, y) => {
|
|
29017
|
+
uvArray.push(x);
|
|
29018
|
+
uvArray.push(y);
|
|
29019
|
+
};
|
|
29020
|
+
const at = (index, axis) => verticesArray[index * 3 + axis];
|
|
29021
|
+
const f3 = (a, b, c) => {
|
|
29022
|
+
addVertex(a);
|
|
29023
|
+
addVertex(b);
|
|
29024
|
+
addVertex(c);
|
|
29025
|
+
const nextIndex = verticesArray.length / 3;
|
|
29026
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at(index, 0), at(index, 1));
|
|
29027
|
+
};
|
|
29028
|
+
const f4 = (a, b, c, d) => {
|
|
29029
|
+
addVertex(a);
|
|
29030
|
+
addVertex(b);
|
|
29031
|
+
addVertex(d);
|
|
29032
|
+
addVertex(b);
|
|
29033
|
+
addVertex(c);
|
|
29034
|
+
addVertex(d);
|
|
29035
|
+
const nextIndex = verticesArray.length / 3;
|
|
29036
|
+
const iA = nextIndex - 6;
|
|
29037
|
+
const iB = nextIndex - 3;
|
|
29038
|
+
const iC = nextIndex - 2;
|
|
29039
|
+
const iD = nextIndex - 1;
|
|
29040
|
+
const byX = Math.abs(at(iA, 1) - at(iB, 1)) < Math.abs(at(iA, 0) - at(iB, 0));
|
|
29041
|
+
const uv = (index) => [byX ? at(index, 0) : at(index, 1), 1 - at(index, 2)];
|
|
29042
|
+
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
29043
|
+
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
29044
|
+
};
|
|
29045
|
+
let start = verticesArray.length / 3;
|
|
29046
|
+
if (bevelEnabled) {
|
|
29047
|
+
let offset = 0;
|
|
29048
|
+
for (let i = 0; i < flen; i++) {
|
|
29049
|
+
const face = faces[i];
|
|
29050
|
+
f3(face[2] + offset, face[1] + offset, face[0] + offset);
|
|
29051
|
+
}
|
|
29052
|
+
const layer = steps + bevelSegments * 2;
|
|
29053
|
+
offset = vlen * layer;
|
|
29054
|
+
for (let i = 0; i < flen; i++) {
|
|
29055
|
+
const face = faces[i];
|
|
29056
|
+
f3(face[0] + offset, face[1] + offset, face[2] + offset);
|
|
29057
|
+
}
|
|
29058
|
+
} else {
|
|
29059
|
+
for (let i = 0; i < flen; i++) {
|
|
29060
|
+
const face = faces[i];
|
|
29061
|
+
f3(face[2], face[1], face[0]);
|
|
29062
|
+
}
|
|
29063
|
+
for (let i = 0; i < flen; i++) {
|
|
29064
|
+
const face = faces[i];
|
|
29065
|
+
f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
|
|
29066
|
+
}
|
|
29067
|
+
}
|
|
29068
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 0 });
|
|
29069
|
+
start = verticesArray.length / 3;
|
|
29070
|
+
const sidewalls = (ring2, layeroffset2) => {
|
|
29071
|
+
let i = ring2.length;
|
|
29072
|
+
while (--i >= 0) {
|
|
29073
|
+
const j = i;
|
|
29074
|
+
let k = i - 1;
|
|
29075
|
+
if (k < 0) k = ring2.length - 1;
|
|
29076
|
+
for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
|
|
29077
|
+
const slen1 = vlen * s;
|
|
29078
|
+
const slen2 = vlen * (s + 1);
|
|
29079
|
+
f4(layeroffset2 + j + slen1, layeroffset2 + k + slen1, layeroffset2 + k + slen2, layeroffset2 + j + slen2);
|
|
29080
|
+
}
|
|
29081
|
+
}
|
|
29082
|
+
};
|
|
29083
|
+
let layeroffset = 0;
|
|
29084
|
+
sidewalls(contour, layeroffset);
|
|
29085
|
+
layeroffset += contour.length;
|
|
29086
|
+
for (const ahole of holes) {
|
|
29087
|
+
sidewalls(ahole, layeroffset);
|
|
29088
|
+
layeroffset += ahole.length;
|
|
29089
|
+
}
|
|
29090
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 1 });
|
|
29091
|
+
const positions = new Float32Array(verticesArray);
|
|
29092
|
+
return { type: "ExtrudeGeometry", parameters, positions, normals: computeVertexNormals(positions), uvs: new Float32Array(uvArray), groups };
|
|
29093
|
+
}
|
|
29094
|
+
var PARAMETER_KEYS = {
|
|
29095
|
+
box: ["size", "segments"],
|
|
29096
|
+
cylinder: ["radiusTop", "radiusBottom", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
29097
|
+
cone: ["radius", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
29098
|
+
sphere: ["radius", "widthSegments", "heightSegments", "phiStart", "phiLength", "thetaStart", "thetaLength"],
|
|
29099
|
+
plane: ["width", "height", "widthSegments", "heightSegments"],
|
|
29100
|
+
circle: ["radius", "segments", "thetaStart", "thetaLength"],
|
|
29101
|
+
ring: ["innerRadius", "outerRadius", "thetaSegments", "phiSegments", "thetaStart", "thetaLength"],
|
|
29102
|
+
lathe: ["points", "segments", "phiStart", "phiLength"],
|
|
29103
|
+
torus: ["radius", "tube", "radialSegments", "tubularSegments", "arc"],
|
|
29104
|
+
extrude: ["shape", "depth", "steps", "bevel"],
|
|
29105
|
+
difference: ["size", "subtract"],
|
|
29106
|
+
mesh: ["positions", "normals", "uvs", "indices"]
|
|
29107
|
+
};
|
|
29108
|
+
var SEGMENT_KEYS = {
|
|
29109
|
+
cylinder: ["radialSegments"],
|
|
29110
|
+
cone: ["radialSegments"],
|
|
29111
|
+
sphere: ["widthSegments", "heightSegments"],
|
|
29112
|
+
circle: ["segments"],
|
|
29113
|
+
ring: ["thetaSegments"],
|
|
29114
|
+
lathe: ["segments"],
|
|
29115
|
+
torus: ["radialSegments", "tubularSegments"]
|
|
29116
|
+
};
|
|
29117
|
+
var SEGMENT_DEFAULTS = { radialSegments: 32, widthSegments: 32, heightSegments: 16, segments: 12, thetaSegments: 32, tubularSegments: 48 };
|
|
29118
|
+
var segmentDefault = (kind, key) => kind === "circle" && key === "segments" ? 32 : kind === "torus" && key === "radialSegments" ? 12 : SEGMENT_DEFAULTS[key];
|
|
29119
|
+
function primitiveParameters(node, options = {}) {
|
|
29120
|
+
const out = {};
|
|
29121
|
+
const source = node;
|
|
29122
|
+
for (const key of PARAMETER_KEYS[node.kind]) if (source[key] !== void 0) out[key] = source[key];
|
|
29123
|
+
const detail = options.detail ?? 1;
|
|
29124
|
+
if (detail !== 1) {
|
|
29125
|
+
const floor = options.minSegments ?? 3;
|
|
29126
|
+
for (const key of SEGMENT_KEYS[node.kind] ?? []) {
|
|
29127
|
+
const given = out[key] ?? segmentDefault(node.kind, key);
|
|
29128
|
+
out[key] = Math.max(floor, Math.round(given * detail));
|
|
29129
|
+
}
|
|
29130
|
+
}
|
|
29131
|
+
return out;
|
|
29132
|
+
}
|
|
29133
|
+
function mesh(p) {
|
|
29134
|
+
const positions = new Float32Array(p.positions);
|
|
29135
|
+
const indices = p.indices ? indexArray(p.indices) : void 0;
|
|
29136
|
+
return {
|
|
29137
|
+
type: "BufferGeometry",
|
|
29138
|
+
parameters: {},
|
|
29139
|
+
positions,
|
|
29140
|
+
normals: p.normals ? new Float32Array(p.normals) : computeVertexNormals(positions, indices),
|
|
29141
|
+
uvs: p.uvs ? new Float32Array(p.uvs) : new Float32Array(positions.length / 3 * 2),
|
|
29142
|
+
...indices ? { indices } : {},
|
|
29143
|
+
groups: []
|
|
29144
|
+
};
|
|
29145
|
+
}
|
|
29146
|
+
function make(kind, p) {
|
|
29147
|
+
switch (kind) {
|
|
29148
|
+
case "box": {
|
|
29149
|
+
const size = p.size ?? [1, 1, 1];
|
|
29150
|
+
const segments = p.segments ?? [1, 1, 1];
|
|
29151
|
+
return box(size[0], size[1], size[2], segments[0], segments[1], segments[2]);
|
|
29152
|
+
}
|
|
29153
|
+
case "cylinder":
|
|
29154
|
+
return cylinder(p.radiusTop, p.radiusBottom, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
|
|
29155
|
+
case "cone":
|
|
29156
|
+
return cone(p.radius, p.height, p.radialSegments, p.heightSegments, p.openEnded, p.thetaStart, p.thetaLength);
|
|
29157
|
+
case "sphere":
|
|
29158
|
+
return sphere(p.radius, p.widthSegments, p.heightSegments, p.phiStart, p.phiLength, p.thetaStart, p.thetaLength);
|
|
29159
|
+
case "plane":
|
|
29160
|
+
return plane(p.width, p.height, p.widthSegments, p.heightSegments);
|
|
29161
|
+
case "circle":
|
|
29162
|
+
return circle(p.radius, p.segments, p.thetaStart, p.thetaLength);
|
|
29163
|
+
case "ring":
|
|
29164
|
+
return ring(p.innerRadius, p.outerRadius, p.thetaSegments, p.phiSegments, p.thetaStart, p.thetaLength);
|
|
29165
|
+
case "lathe":
|
|
29166
|
+
return lathe(p.points, p.segments, p.phiStart, p.phiLength);
|
|
29167
|
+
case "torus":
|
|
29168
|
+
return torus(p.radius, p.tube, p.radialSegments, p.tubularSegments, p.arc);
|
|
29169
|
+
case "extrude":
|
|
29170
|
+
return extrude(p.shape, p.depth, p.steps, p.bevel);
|
|
29171
|
+
case "difference":
|
|
29172
|
+
return difference(p.size, p.subtract ?? []);
|
|
29173
|
+
case "mesh":
|
|
29174
|
+
return mesh(p);
|
|
29175
|
+
default:
|
|
29176
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
29177
|
+
}
|
|
29178
|
+
}
|
|
29179
|
+
var templates = /* @__PURE__ */ new Map();
|
|
29180
|
+
var templateLimit = 4096;
|
|
29181
|
+
var stats = { hits: 0, misses: 0 };
|
|
29182
|
+
function buildPrimitive(node, options = {}) {
|
|
29183
|
+
const parameters = primitiveParameters(node, options);
|
|
29184
|
+
if (node.kind === "mesh" || templateLimit === 0) return make(node.kind, parameters);
|
|
29185
|
+
const key = `${node.kind}:${canonicalJson(parameters)}`;
|
|
29186
|
+
const cached = templates.get(key);
|
|
29187
|
+
if (cached) {
|
|
29188
|
+
stats.hits++;
|
|
29189
|
+
templates.delete(key);
|
|
29190
|
+
templates.set(key, cached);
|
|
29191
|
+
return cached;
|
|
29192
|
+
}
|
|
29193
|
+
stats.misses++;
|
|
29194
|
+
const built = make(node.kind, parameters);
|
|
29195
|
+
templates.set(key, built);
|
|
29196
|
+
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
29197
|
+
return built;
|
|
29198
|
+
}
|
|
29199
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
|
|
29200
|
+
var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
|
|
29201
|
+
var str = (v) => typeof v === "string" ? null : "expected a string";
|
|
29202
|
+
var int = (min) => (v) => typeof v === "number" && Number.isInteger(v) && v >= min ? null : `expected an integer >= ${min}`;
|
|
29203
|
+
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}]`;
|
|
29204
|
+
var tuple = (n, item = num) => (v) => {
|
|
29205
|
+
if (!Array.isArray(v) || v.length !== n) return `expected an array of ${n}`;
|
|
29206
|
+
for (const x of v) if (item(x)) return `expected an array of ${n} numbers`;
|
|
29207
|
+
return null;
|
|
29208
|
+
};
|
|
29209
|
+
var list = (item, min = 0) => (v) => {
|
|
29210
|
+
if (!Array.isArray(v)) return "expected an array";
|
|
29211
|
+
if (v.length < min) return `expected at least ${min} items`;
|
|
29212
|
+
for (let i = 0; i < v.length; i++) {
|
|
29213
|
+
const e = item(v[i]);
|
|
29214
|
+
if (e) return `[${i}]: ${e}`;
|
|
29215
|
+
}
|
|
29216
|
+
return null;
|
|
29217
|
+
};
|
|
29218
|
+
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"';
|
|
29219
|
+
var oneOf = (values) => (v) => values.includes(v) ? null : `expected one of ${values.map((x) => JSON.stringify(x)).join(", ")}`;
|
|
29220
|
+
var object = (fields, required = []) => (v) => {
|
|
29221
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return "expected an object";
|
|
29222
|
+
const record = v;
|
|
29223
|
+
for (const key of required) if (record[key] === void 0) return `${key}: required`;
|
|
29224
|
+
for (const key of Object.keys(record)) {
|
|
29225
|
+
if (record[key] === void 0) continue;
|
|
29226
|
+
const check = fields[key];
|
|
29227
|
+
if (!check) return `${key}: unknown field`;
|
|
29228
|
+
const e = check(record[key]);
|
|
29229
|
+
if (e) return `${key}: ${e}`;
|
|
29230
|
+
}
|
|
29231
|
+
return null;
|
|
29232
|
+
};
|
|
29233
|
+
var ORDERS = ["XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"];
|
|
29234
|
+
var TRANSFORM = {
|
|
29235
|
+
position: tuple(3),
|
|
29236
|
+
rotation: tuple(3),
|
|
29237
|
+
rotationOrder: oneOf(ORDERS),
|
|
29238
|
+
scale: (v) => typeof v === "number" ? num(v) : tuple(3)(v),
|
|
29239
|
+
heading: num,
|
|
29240
|
+
matrix: tuple(16)
|
|
29241
|
+
};
|
|
29242
|
+
var UV = object({ u0: num, v0: num, u1: num, v1: num }, ["u0", "v0", "u1", "v1"]);
|
|
29243
|
+
var INSTANCE = object({ ...TRANSFORM, color });
|
|
29244
|
+
var COMMON = {
|
|
29245
|
+
...TRANSFORM,
|
|
29246
|
+
kind: str,
|
|
29247
|
+
name: str,
|
|
29248
|
+
part: str,
|
|
29249
|
+
material: str,
|
|
29250
|
+
color,
|
|
29251
|
+
uv: UV,
|
|
29252
|
+
instances: list(INSTANCE),
|
|
29253
|
+
minDetail: range(0, 1, true),
|
|
29254
|
+
tags: list(str)
|
|
29255
|
+
};
|
|
29256
|
+
var vec2 = tuple(2);
|
|
29257
|
+
var BEVEL = (v) => v === false ? null : object({ thickness: num, size: num, offset: num, segments: int(1) })(v);
|
|
29258
|
+
var KINDS = {
|
|
29259
|
+
group: { fields: {} },
|
|
29260
|
+
box: { fields: { size: tuple(3), segments: tuple(3, int(1)) } },
|
|
29261
|
+
cylinder: { fields: { radiusTop: num, radiusBottom: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
29262
|
+
cone: { fields: { radius: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
29263
|
+
sphere: { fields: { radius: num, widthSegments: int(3), heightSegments: int(2), phiStart: num, phiLength: num, thetaStart: num, thetaLength: num } },
|
|
29264
|
+
plane: { fields: { width: num, height: num, widthSegments: int(1), heightSegments: int(1) } },
|
|
29265
|
+
circle: { fields: { radius: num, segments: int(3), thetaStart: num, thetaLength: num } },
|
|
29266
|
+
ring: { fields: { innerRadius: num, outerRadius: num, thetaSegments: int(3), phiSegments: int(1), thetaStart: num, thetaLength: num } },
|
|
29267
|
+
lathe: { fields: { points: list(vec2, 2), segments: int(1), phiStart: num, phiLength: num }, required: ["points"] },
|
|
29268
|
+
torus: { fields: { radius: num, tube: num, radialSegments: int(1), tubularSegments: int(1), arc: num } },
|
|
29269
|
+
extrude: {
|
|
29270
|
+
fields: { shape: object({ outer: list(vec2, 3), holes: list(list(vec2, 3)) }, ["outer"]), depth: num, steps: int(1), bevel: BEVEL },
|
|
29271
|
+
required: ["shape"]
|
|
29272
|
+
},
|
|
29273
|
+
difference: { fields: { size: tuple(3), subtract: list(object({ min: vec2, max: vec2 }, ["min", "max"])) }, required: ["size", "subtract"] },
|
|
29274
|
+
mesh: {
|
|
29275
|
+
fields: {
|
|
29276
|
+
positions: (v) => list(num)(v) ?? (v.length % 3 === 0 ? null : "expected a multiple of 3 numbers"),
|
|
29277
|
+
normals: list(num),
|
|
29278
|
+
uvs: list(num),
|
|
29279
|
+
indices: list(int(0))
|
|
29280
|
+
},
|
|
29281
|
+
required: ["positions"]
|
|
29282
|
+
},
|
|
29283
|
+
point: { fields: { data: () => null } },
|
|
29284
|
+
custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
|
|
29285
|
+
};
|
|
29286
|
+
|
|
29287
|
+
// ../game-shapes-three/dist/index.js
|
|
29288
|
+
var UV_BEFORE_NORMAL = /* @__PURE__ */ new Set(["LatheGeometry", "ExtrudeGeometry"]);
|
|
29289
|
+
var INDEX_FIRST = /* @__PURE__ */ new Set(["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry"]);
|
|
29290
|
+
var isPrimitive = (value) => typeof value.type === "string";
|
|
29291
|
+
function threeParameters(THREE, p) {
|
|
29292
|
+
if (p.type === "LatheGeometry") {
|
|
29293
|
+
const points = p.parameters.points.map(({ x, y }) => new THREE.Vector2(x, y));
|
|
29294
|
+
return { ...p.parameters, points };
|
|
29295
|
+
}
|
|
29296
|
+
return { ...p.parameters };
|
|
29297
|
+
}
|
|
29298
|
+
function toGeometry(THREE, source, options = {}) {
|
|
29299
|
+
const copy = options.copy !== false;
|
|
29300
|
+
const primitive = isPrimitive(source) ? source : null;
|
|
29301
|
+
const ThreeClass = primitive && primitive.type !== "BufferGeometry" ? THREE[primitive.type] : void 0;
|
|
29302
|
+
const geometry = ThreeClass ? Reflect.construct(THREE.BufferGeometry, [], ThreeClass) : new THREE.BufferGeometry();
|
|
29303
|
+
if (primitive && ThreeClass) {
|
|
29304
|
+
Object.assign(geometry, { type: primitive.type, parameters: threeParameters(THREE, primitive) });
|
|
29305
|
+
}
|
|
29306
|
+
const attribute = (array, size) => copy ? new THREE.Float32BufferAttribute(array, size) : new THREE.BufferAttribute(array, size);
|
|
29307
|
+
const index = source.indices;
|
|
29308
|
+
const setIndex = () => {
|
|
29309
|
+
if (!index) return;
|
|
29310
|
+
geometry.setIndex(copy ? index instanceof Uint32Array ? new THREE.Uint32BufferAttribute(index, 1) : new THREE.Uint16BufferAttribute(index, 1) : new THREE.BufferAttribute(index, 1));
|
|
29311
|
+
};
|
|
29312
|
+
const type = primitive?.type ?? "BufferGeometry";
|
|
29313
|
+
if (INDEX_FIRST.has(type)) setIndex();
|
|
29314
|
+
geometry.setAttribute("position", attribute(source.positions, 3));
|
|
29315
|
+
if (UV_BEFORE_NORMAL.has(type)) {
|
|
29316
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
29317
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
29318
|
+
} else {
|
|
29319
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
29320
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
29321
|
+
}
|
|
29322
|
+
if (!primitive && source.colors) geometry.setAttribute("color", attribute(source.colors, 3));
|
|
29323
|
+
if (!INDEX_FIRST.has(type)) setIndex();
|
|
29324
|
+
if (primitive) for (const group of primitive.groups) geometry.addGroup(group.start, group.count, group.materialIndex);
|
|
29325
|
+
return geometry;
|
|
29326
|
+
}
|
|
29327
|
+
var SHAPE_GEOMETRY_TYPES = ["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry", "ExtrudeGeometry"];
|
|
29328
|
+
function linePoints(path) {
|
|
29329
|
+
if (path.autoClose || path.curves.length === 0) return null;
|
|
29330
|
+
const points = [];
|
|
29331
|
+
for (const [index, curve] of path.curves.entries()) {
|
|
29332
|
+
if (!curve.isLineCurve || !curve.v1 || !curve.v2) return null;
|
|
29333
|
+
if (index === 0) points.push([curve.v1.x, curve.v1.y]);
|
|
29334
|
+
else {
|
|
29335
|
+
const last = points[points.length - 1];
|
|
29336
|
+
if (last[0] !== curve.v1.x || last[1] !== curve.v1.y) return null;
|
|
29337
|
+
}
|
|
29338
|
+
points.push([curve.v2.x, curve.v2.y]);
|
|
29339
|
+
}
|
|
29340
|
+
return points;
|
|
29341
|
+
}
|
|
29342
|
+
function extrudeOf(shapes, options = {}) {
|
|
29343
|
+
if (Array.isArray(shapes) || !shapes || options.extrudePath !== void 0 || options.UVGenerator !== void 0) return null;
|
|
29344
|
+
const shape = shapes;
|
|
29345
|
+
const outer = linePoints(shape);
|
|
29346
|
+
if (!outer) return null;
|
|
29347
|
+
const holes = [];
|
|
29348
|
+
for (const hole of shape.holes ?? []) {
|
|
29349
|
+
const points = linePoints(hole);
|
|
29350
|
+
if (!points) return null;
|
|
29351
|
+
holes.push(points);
|
|
29352
|
+
}
|
|
29353
|
+
const outline = holes.length ? { outer, holes } : { outer };
|
|
29354
|
+
const bevel = options.bevelEnabled === false ? false : {
|
|
29355
|
+
...options.bevelThickness !== void 0 ? { thickness: options.bevelThickness } : {},
|
|
29356
|
+
...options.bevelSize !== void 0 ? { size: options.bevelSize } : {},
|
|
29357
|
+
...options.bevelOffset !== void 0 ? { offset: options.bevelOffset } : {},
|
|
29358
|
+
...options.bevelSegments !== void 0 ? { segments: options.bevelSegments } : {}
|
|
29359
|
+
};
|
|
29360
|
+
return extrude(outline, options.depth, options.steps, bevel);
|
|
29361
|
+
}
|
|
29362
|
+
var namespaces = /* @__PURE__ */ new WeakMap();
|
|
29363
|
+
var shims = /* @__PURE__ */ new WeakSet();
|
|
29364
|
+
function shapeGeometries(THREE, options = {}) {
|
|
29365
|
+
if (shims.has(THREE)) return THREE;
|
|
29366
|
+
const cache = options.cache !== false;
|
|
29367
|
+
const key = cache ? "cache" : "nocache";
|
|
29368
|
+
let byKey = namespaces.get(THREE);
|
|
29369
|
+
if (!byKey) {
|
|
29370
|
+
byKey = /* @__PURE__ */ new Map();
|
|
29371
|
+
namespaces.set(THREE, byKey);
|
|
29372
|
+
}
|
|
29373
|
+
const existing = byKey.get(key);
|
|
29374
|
+
if (existing) return existing;
|
|
29375
|
+
const made = (p) => toGeometry(THREE, p);
|
|
29376
|
+
const viaCache = (node, direct) => cache ? buildPrimitive(node) : direct();
|
|
29377
|
+
const defined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
29378
|
+
const constructors = {
|
|
29379
|
+
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))),
|
|
29380
|
+
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))),
|
|
29381
|
+
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))),
|
|
29382
|
+
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))),
|
|
29383
|
+
PlaneGeometry: (width, height, widthSegments, heightSegments) => made(viaCache({ kind: "plane", ...defined({ width, height, widthSegments, heightSegments }) }, () => plane(width, height, widthSegments, heightSegments))),
|
|
29384
|
+
CircleGeometry: (radius, segments, thetaStart, thetaLength) => made(viaCache({ kind: "circle", ...defined({ radius, segments, thetaStart, thetaLength }) }, () => circle(radius, segments, thetaStart, thetaLength))),
|
|
29385
|
+
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))),
|
|
29386
|
+
LatheGeometry: (points, segments, phiStart, phiLength) => {
|
|
29387
|
+
if (!points) return new THREE.LatheGeometry(void 0, segments, phiStart, phiLength);
|
|
29388
|
+
const profile = points.map((p) => [p.x, p.y]);
|
|
29389
|
+
return made(viaCache({ kind: "lathe", points: profile, ...defined({ segments, phiStart, phiLength }) }, () => lathe(profile, segments, phiStart, phiLength)));
|
|
29390
|
+
},
|
|
29391
|
+
TorusGeometry: (radius, tube, radialSegments, tubularSegments, arc) => made(viaCache({ kind: "torus", ...defined({ radius, tube, radialSegments, tubularSegments, arc }) }, () => torus(radius, tube, radialSegments, tubularSegments, arc))),
|
|
29392
|
+
ExtrudeGeometry: (shapes, extrudeOptions) => {
|
|
29393
|
+
const buffers = shapes === void 0 ? null : extrudeOf(shapes, extrudeOptions);
|
|
29394
|
+
if (!buffers) return new THREE.ExtrudeGeometry(shapes, extrudeOptions);
|
|
29395
|
+
const geometry = toGeometry(THREE, buffers);
|
|
29396
|
+
geometry.parameters = { shapes, options: extrudeOptions ?? {} };
|
|
29397
|
+
return geometry;
|
|
29398
|
+
}
|
|
29399
|
+
};
|
|
29400
|
+
const namespace = { ...THREE };
|
|
29401
|
+
for (const type of SHAPE_GEOMETRY_TYPES) {
|
|
29402
|
+
const make2 = constructors[type];
|
|
29403
|
+
const Constructor = function(...args) {
|
|
29404
|
+
return make2(...args);
|
|
29405
|
+
};
|
|
29406
|
+
Constructor.prototype = THREE[type].prototype;
|
|
29407
|
+
Object.defineProperty(Constructor, "name", { value: type });
|
|
29408
|
+
namespace[type] = Constructor;
|
|
29409
|
+
}
|
|
29410
|
+
const result = namespace;
|
|
29411
|
+
byKey.set(key, result);
|
|
29412
|
+
shims.add(result);
|
|
29413
|
+
return result;
|
|
29414
|
+
}
|
|
29415
|
+
|
|
29416
|
+
// ../game-contracts/dist/index.js
|
|
29417
|
+
var DEFAULT_IGNITION_RULES = {
|
|
29418
|
+
fillCurve: [
|
|
29419
|
+
[0, 0.6],
|
|
29420
|
+
[0.1, 1],
|
|
29421
|
+
[0.35, 0.6],
|
|
29422
|
+
[0.65, 0.3],
|
|
29423
|
+
[0.9, 0.15],
|
|
29424
|
+
[1, 0.12]
|
|
29425
|
+
],
|
|
29426
|
+
flameFillInfluence: 0.5,
|
|
29427
|
+
flameDefaults: { incendiary: 0.7, tracer: 0.2 },
|
|
29428
|
+
sparkTarget: { steel: 1, iron: 1, aluminium: 0.25 },
|
|
29429
|
+
sparkMetalDefault: 0.5,
|
|
29430
|
+
sparkFluid: { diesel: 0.15 },
|
|
29431
|
+
fireNear: { radius: 1.5, chancePerSecond: 0.5 }
|
|
29432
|
+
};
|
|
29433
|
+
var resolveIgnitionRules = (rules) => ({
|
|
29434
|
+
...DEFAULT_IGNITION_RULES,
|
|
29435
|
+
...rules,
|
|
29436
|
+
flameDefaults: { ...DEFAULT_IGNITION_RULES.flameDefaults, ...rules?.flameDefaults },
|
|
29437
|
+
sparkTarget: { ...DEFAULT_IGNITION_RULES.sparkTarget, ...rules?.sparkTarget },
|
|
29438
|
+
sparkFluid: { ...DEFAULT_IGNITION_RULES.sparkFluid, ...rules?.sparkFluid },
|
|
29439
|
+
fireNear: { ...DEFAULT_IGNITION_RULES.fireNear, ...rules?.fireNear }
|
|
29440
|
+
});
|
|
29441
|
+
var fillFactor = (fill2, curve = DEFAULT_IGNITION_RULES.fillCurve) => {
|
|
29442
|
+
if (curve.length === 0) return 1;
|
|
29443
|
+
const f = Math.min(1, Math.max(0, fill2));
|
|
29444
|
+
if (f <= curve[0][0]) return curve[0][1];
|
|
29445
|
+
for (let i = 1; i < curve.length; i++) {
|
|
29446
|
+
const [x1, y1] = curve[i];
|
|
29447
|
+
const [x0, y0] = curve[i - 1];
|
|
29448
|
+
if (f <= x1) return x1 === x0 ? y1 : y0 + (y1 - y0) * (f - x0) / (x1 - x0);
|
|
29449
|
+
}
|
|
29450
|
+
return curve[curve.length - 1][1];
|
|
29451
|
+
};
|
|
29452
|
+
var sparkTargetFactor = (materialId, metal, rules = DEFAULT_IGNITION_RULES) => !metal ? 0 : rules.sparkTarget[materialId] ?? rules.sparkMetalDefault;
|
|
29453
|
+
var ignitionChance = (hit, target, rules = DEFAULT_IGNITION_RULES) => {
|
|
29454
|
+
const k = fillFactor(target.fill, rules.fillCurve);
|
|
29455
|
+
const spark = (hit.ignition?.spark ?? 0) * target.sparkTarget * (target.fluid === void 0 ? 1 : rules.sparkFluid[target.fluid] ?? 1) * k;
|
|
29456
|
+
const flameBase = hit.ignition?.flame ?? Math.max(hit.incendiary ? rules.flameDefaults.incendiary : 0, hit.tracer ? rules.flameDefaults.tracer : 0);
|
|
29457
|
+
const flame = flameBase * (1 - rules.flameFillInfluence * (1 - k));
|
|
29458
|
+
return 1 - (1 - Math.min(1, Math.max(0, spark))) * (1 - Math.min(1, Math.max(0, flame)));
|
|
29459
|
+
};
|
|
29460
|
+
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
29461
|
+
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
29462
|
+
var deepMerge = (base, patch) => {
|
|
29463
|
+
if (!patch) return base;
|
|
29464
|
+
const result = { ...base };
|
|
29465
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
29466
|
+
if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
|
|
29467
|
+
const current = result[key];
|
|
29468
|
+
result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
|
|
29469
|
+
}
|
|
29470
|
+
return result;
|
|
29471
|
+
};
|
|
29472
|
+
var mergeById = (shipped, extra) => {
|
|
29473
|
+
const entries = /* @__PURE__ */ new Map();
|
|
29474
|
+
for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
|
|
29475
|
+
return entries;
|
|
29476
|
+
};
|
|
29477
|
+
var applyPatches = (entries, patches) => {
|
|
29478
|
+
for (const [id, patch] of Object.entries(patches ?? {})) {
|
|
29479
|
+
const entry = entries.get(id);
|
|
29480
|
+
if (entry) entries.set(id, deepMerge(entry, patch));
|
|
29481
|
+
}
|
|
29482
|
+
};
|
|
29483
|
+
var removeIds = (entries, ids) => {
|
|
29484
|
+
for (const id of ids ?? []) entries.delete(id);
|
|
29485
|
+
};
|
|
29486
|
+
|
|
27898
29487
|
// ../game-vehicles/dist/index.js
|
|
27899
29488
|
var __defProp2 = Object.defineProperty;
|
|
27900
29489
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -28580,9 +30169,9 @@ var GameVehiclesThree = (() => {
|
|
|
28580
30169
|
return envTex;
|
|
28581
30170
|
}
|
|
28582
30171
|
kit.studioEnvironment = studioEnvironment;
|
|
28583
|
-
function makeMaterial(
|
|
30172
|
+
function makeMaterial(color2, o) {
|
|
28584
30173
|
o = o || {};
|
|
28585
|
-
const c =
|
|
30174
|
+
const c = color2 instanceof THREE.Color ? color2 : new THREE.Color(color2);
|
|
28586
30175
|
const key = "s" + c.getHexString() + JSON.stringify(o, function(k, v) {
|
|
28587
30176
|
return v && v.isColor ? "#" + v.getHexString() : v && v.isTexture ? v.uuid : v;
|
|
28588
30177
|
});
|
|
@@ -28598,8 +30187,8 @@ var GameVehiclesThree = (() => {
|
|
|
28598
30187
|
}
|
|
28599
30188
|
return cache[key];
|
|
28600
30189
|
}
|
|
28601
|
-
function makeFlatMaterial(
|
|
28602
|
-
return makeMaterial(
|
|
30190
|
+
function makeFlatMaterial(color2, o) {
|
|
30191
|
+
return makeMaterial(color2, Object.assign({ flatShading: true, roughness: 0.92 }, o || {}));
|
|
28603
30192
|
}
|
|
28604
30193
|
const DOUBLE_SIDE = THREE.DoubleSide;
|
|
28605
30194
|
function toColor(hex) {
|
|
@@ -28816,46 +30405,79 @@ var GameVehiclesThree = (() => {
|
|
|
28816
30405
|
}
|
|
28817
30406
|
const p = geo.attributes.position;
|
|
28818
30407
|
const n = p.count;
|
|
28819
|
-
const
|
|
28820
|
-
const
|
|
28821
|
-
const
|
|
28822
|
-
const
|
|
28823
|
-
const C = new V3();
|
|
28824
|
-
const e1 = new V3();
|
|
28825
|
-
const e2 = new V3();
|
|
30408
|
+
const faces = n / 3;
|
|
30409
|
+
const FN = new Float64Array(faces * 3);
|
|
30410
|
+
const map = /* @__PURE__ */ new Map();
|
|
30411
|
+
const RANGE = 65536;
|
|
28826
30412
|
function key(i) {
|
|
28827
|
-
|
|
30413
|
+
const x = Math.round(p.getX(i) * 2e3);
|
|
30414
|
+
const y = Math.round(p.getY(i) * 2e3);
|
|
30415
|
+
const z = Math.round(p.getZ(i) * 2e3);
|
|
30416
|
+
if (Math.abs(x) < RANGE && Math.abs(y) < RANGE && Math.abs(z) < RANGE) return ((x + RANGE) * 131072 + (y + RANGE)) * 131072 + (z + RANGE);
|
|
30417
|
+
return x + "," + y + "," + z;
|
|
28828
30418
|
}
|
|
28829
30419
|
const keys = new Array(n);
|
|
28830
|
-
for (let f = 0; f <
|
|
28831
|
-
|
|
28832
|
-
|
|
28833
|
-
|
|
28834
|
-
const
|
|
28835
|
-
|
|
28836
|
-
|
|
30420
|
+
for (let f = 0; f < faces; f++) {
|
|
30421
|
+
const ax = p.getX(3 * f);
|
|
30422
|
+
const ay = p.getY(3 * f);
|
|
30423
|
+
const az = p.getZ(3 * f);
|
|
30424
|
+
const bx = p.getX(3 * f + 1);
|
|
30425
|
+
const by = p.getY(3 * f + 1);
|
|
30426
|
+
const bz = p.getZ(3 * f + 1);
|
|
30427
|
+
const cx = p.getX(3 * f + 2);
|
|
30428
|
+
const cy = p.getY(3 * f + 2);
|
|
30429
|
+
const cz = p.getZ(3 * f + 2);
|
|
30430
|
+
const e1x = cx - bx;
|
|
30431
|
+
const e1y = cy - by;
|
|
30432
|
+
const e1z = cz - bz;
|
|
30433
|
+
const e2x = ax - bx;
|
|
30434
|
+
const e2y = ay - by;
|
|
30435
|
+
const e2z = az - bz;
|
|
30436
|
+
let nx = e1y * e2z - e1z * e2y;
|
|
30437
|
+
let ny = e1z * e2x - e1x * e2z;
|
|
30438
|
+
let nz = e1x * e2y - e1y * e2x;
|
|
30439
|
+
if (nx * nx + ny * ny + nz * nz > 1e-20) {
|
|
30440
|
+
const inv = 1 / (Math.sqrt(nx * nx + ny * ny + nz * nz) || 1);
|
|
30441
|
+
nx *= inv;
|
|
30442
|
+
ny *= inv;
|
|
30443
|
+
nz *= inv;
|
|
30444
|
+
}
|
|
30445
|
+
FN[3 * f] = nx;
|
|
30446
|
+
FN[3 * f + 1] = ny;
|
|
30447
|
+
FN[3 * f + 2] = nz;
|
|
28837
30448
|
for (let k = 0; k < 3; k++) {
|
|
28838
30449
|
const kk = key(3 * f + k);
|
|
28839
30450
|
keys[3 * f + k] = kk;
|
|
28840
|
-
|
|
30451
|
+
const list2 = map.get(kk);
|
|
30452
|
+
if (list2) list2.push(f);
|
|
30453
|
+
else map.set(kk, [f]);
|
|
28841
30454
|
}
|
|
28842
30455
|
}
|
|
28843
30456
|
const cs = Math.cos(deg * PI / 180);
|
|
28844
30457
|
const out = new Float32Array(n * 3);
|
|
28845
|
-
const s = new V3();
|
|
28846
30458
|
for (let i = 0; i < n; i++) {
|
|
28847
|
-
const fi = i / 3 | 0;
|
|
28848
|
-
const
|
|
28849
|
-
|
|
28850
|
-
|
|
28851
|
-
|
|
28852
|
-
|
|
28853
|
-
|
|
28854
|
-
|
|
28855
|
-
|
|
28856
|
-
|
|
28857
|
-
|
|
28858
|
-
|
|
30459
|
+
const fi = (i / 3 | 0) * 3;
|
|
30460
|
+
const list2 = map.get(keys[i]);
|
|
30461
|
+
let sx = 0;
|
|
30462
|
+
let sy = 0;
|
|
30463
|
+
let sz = 0;
|
|
30464
|
+
for (let j = 0; j < list2.length; j++) {
|
|
30465
|
+
const g = list2[j] * 3;
|
|
30466
|
+
if (FN[g] * FN[fi] + FN[g + 1] * FN[fi + 1] + FN[g + 2] * FN[fi + 2] >= cs) {
|
|
30467
|
+
sx += FN[g];
|
|
30468
|
+
sy += FN[g + 1];
|
|
30469
|
+
sz += FN[g + 2];
|
|
30470
|
+
}
|
|
30471
|
+
}
|
|
30472
|
+
if (sx * sx + sy * sy + sz * sz < 1e-20) {
|
|
30473
|
+
sx = FN[fi];
|
|
30474
|
+
sy = FN[fi + 1];
|
|
30475
|
+
sz = FN[fi + 2];
|
|
30476
|
+
}
|
|
30477
|
+
const inv = 1 / (Math.sqrt(sx * sx + sy * sy + sz * sz) || 1);
|
|
30478
|
+
out[3 * i] = sx * inv;
|
|
30479
|
+
out[3 * i + 1] = sy * inv;
|
|
30480
|
+
out[3 * i + 2] = sz * inv;
|
|
28859
30481
|
}
|
|
28860
30482
|
geo.setAttribute("normal", new THREE.BufferAttribute(out, 3));
|
|
28861
30483
|
geo.userData.crease = true;
|
|
@@ -28914,7 +30536,7 @@ var GameVehiclesThree = (() => {
|
|
|
28914
30536
|
const pos = [];
|
|
28915
30537
|
const col = [];
|
|
28916
30538
|
const idx = [];
|
|
28917
|
-
const
|
|
30539
|
+
const ring2 = seg + 1;
|
|
28918
30540
|
st.forEach(function(s) {
|
|
28919
30541
|
for (let j = 0; j <= seg; j++) {
|
|
28920
30542
|
const a = j / seg * PI * 2;
|
|
@@ -28932,8 +30554,8 @@ var GameVehiclesThree = (() => {
|
|
|
28932
30554
|
});
|
|
28933
30555
|
for (let i = 0; i < st.length - 1; i++)
|
|
28934
30556
|
for (let k = 0; k < seg; k++) {
|
|
28935
|
-
const a0 = i *
|
|
28936
|
-
const b0 = a0 +
|
|
30557
|
+
const a0 = i * ring2 + k;
|
|
30558
|
+
const b0 = a0 + ring2;
|
|
28937
30559
|
idx.push(a0, a0 + 1, b0, a0 + 1, b0 + 1, b0);
|
|
28938
30560
|
}
|
|
28939
30561
|
;
|
|
@@ -28947,7 +30569,7 @@ var GameVehiclesThree = (() => {
|
|
|
28947
30569
|
col.push(cc.r, cc.g, cc.b);
|
|
28948
30570
|
}
|
|
28949
30571
|
for (let k = 0; k < seg; k++) {
|
|
28950
|
-
const a = si *
|
|
30572
|
+
const a = si * ring2 + k;
|
|
28951
30573
|
if (e === 0) idx.push(ci, a + 1, a);
|
|
28952
30574
|
else idx.push(ci, a, a + 1);
|
|
28953
30575
|
}
|
|
@@ -29085,13 +30707,13 @@ var GameVehiclesThree = (() => {
|
|
|
29085
30707
|
});
|
|
29086
30708
|
tris = next;
|
|
29087
30709
|
});
|
|
29088
|
-
function build(
|
|
30710
|
+
function build(list2) {
|
|
29089
30711
|
const g = new THREE.BufferGeometry();
|
|
29090
30712
|
let off = 0;
|
|
29091
30713
|
names.forEach(function(nm, a) {
|
|
29092
|
-
const arr = new Float32Array(
|
|
30714
|
+
const arr = new Float32Array(list2.length * 3 * sizes[a]);
|
|
29093
30715
|
let w = 0;
|
|
29094
|
-
|
|
30716
|
+
list2.forEach(function(t) {
|
|
29095
30717
|
for (let k = 0; k < 3; k++) for (let q = 0; q < sizes[a]; q++) arr[w++] = t[k][off + q];
|
|
29096
30718
|
});
|
|
29097
30719
|
g.setAttribute(nm, new THREE.BufferAttribute(arr, sizes[a]));
|
|
@@ -29106,10 +30728,10 @@ var GameVehiclesThree = (() => {
|
|
|
29106
30728
|
});
|
|
29107
30729
|
return out;
|
|
29108
30730
|
}
|
|
29109
|
-
function mergeGeometries(
|
|
30731
|
+
function mergeGeometries(list2) {
|
|
29110
30732
|
const pos = [];
|
|
29111
30733
|
const nor = [];
|
|
29112
|
-
|
|
30734
|
+
list2.forEach(function(g2) {
|
|
29113
30735
|
const n = g2.index ? g2.toNonIndexed() : g2;
|
|
29114
30736
|
if (!n.attributes.normal) n.computeVertexNormals();
|
|
29115
30737
|
const pa = n.attributes.position.array;
|
|
@@ -29168,13 +30790,13 @@ var GameVehiclesThree = (() => {
|
|
|
29168
30790
|
};
|
|
29169
30791
|
kit.holeSide = function(poly, o) {
|
|
29170
30792
|
o = o || {};
|
|
29171
|
-
let
|
|
30793
|
+
let area3 = 0;
|
|
29172
30794
|
for (let i = 0; i < poly.length; i++) {
|
|
29173
30795
|
const a = poly[i];
|
|
29174
30796
|
const b = poly[(i + 1) % poly.length];
|
|
29175
|
-
|
|
30797
|
+
area3 += a[0] * b[1] - b[0] * a[1];
|
|
29176
30798
|
}
|
|
29177
|
-
const sg =
|
|
30799
|
+
const sg = area3 > 0 ? 1 : -1;
|
|
29178
30800
|
const E2 = poly.map(function(a, i) {
|
|
29179
30801
|
const b = poly[(i + 1) % poly.length];
|
|
29180
30802
|
const dx = b[0] - a[0];
|
|
@@ -29475,11 +31097,11 @@ var GameVehiclesThree = (() => {
|
|
|
29475
31097
|
return d.clone().applyQuaternion(this.vehicle.quaternion);
|
|
29476
31098
|
}
|
|
29477
31099
|
/** Declares or refines a damage zone: `c.zone(id, label, box, parts, options)`. Pass `label === false` to remove an auto-derived zone. */
|
|
29478
|
-
zone(id, label,
|
|
31100
|
+
zone(id, label, box2, parts, o) {
|
|
29479
31101
|
const d = Object.assign({ id }, o || {});
|
|
29480
31102
|
if (label === false) d.remove = true;
|
|
29481
31103
|
else if (label) d.name = label;
|
|
29482
|
-
if (
|
|
31104
|
+
if (box2) d.box = I.normalizeBox(box2);
|
|
29483
31105
|
if (parts) d.objs = Array.isArray(parts) ? parts.slice() : [parts];
|
|
29484
31106
|
this.zoneDefs.push(d);
|
|
29485
31107
|
return d;
|
|
@@ -29628,7 +31250,7 @@ var GameVehiclesThree = (() => {
|
|
|
29628
31250
|
const seg = o.seg || 24;
|
|
29629
31251
|
const pos = [];
|
|
29630
31252
|
const idx = [];
|
|
29631
|
-
const
|
|
31253
|
+
const ring2 = seg + 1;
|
|
29632
31254
|
const axisY = o.axis === "y";
|
|
29633
31255
|
st.forEach(function(s) {
|
|
29634
31256
|
const a0 = s[1];
|
|
@@ -29650,8 +31272,8 @@ var GameVehiclesThree = (() => {
|
|
|
29650
31272
|
});
|
|
29651
31273
|
for (let i = 0; i < st.length - 1; i++)
|
|
29652
31274
|
for (let k = 0; k < seg; k++) {
|
|
29653
|
-
const A = i *
|
|
29654
|
-
const B = A +
|
|
31275
|
+
const A = i * ring2 + k;
|
|
31276
|
+
const B = A + ring2;
|
|
29655
31277
|
if (axisY) idx.push(A, B, A + 1, A + 1, B, B + 1);
|
|
29656
31278
|
else idx.push(A, A + 1, B, A + 1, B + 1, B);
|
|
29657
31279
|
}
|
|
@@ -29664,7 +31286,7 @@ var GameVehiclesThree = (() => {
|
|
|
29664
31286
|
if (axisY) pos.push(cc, s[0], s[5] || 0);
|
|
29665
31287
|
else pos.push(s[0], cc, s[5] || 0);
|
|
29666
31288
|
for (let k = 0; k < seg; k++) {
|
|
29667
|
-
const a = si *
|
|
31289
|
+
const a = si * ring2 + k;
|
|
29668
31290
|
const flip = e === 0 !== axisY;
|
|
29669
31291
|
if (flip) idx.push(ci, a + 1, a);
|
|
29670
31292
|
else idx.push(ci, a, a + 1);
|
|
@@ -29892,15 +31514,15 @@ var GameVehiclesThree = (() => {
|
|
|
29892
31514
|
c.part("glass", L, m, pos, o.reach || 0.9);
|
|
29893
31515
|
return m;
|
|
29894
31516
|
};
|
|
29895
|
-
kit.asGlass = function(c,
|
|
31517
|
+
kit.asGlass = function(c, mesh2, label, type, o) {
|
|
29896
31518
|
o = o || {};
|
|
29897
|
-
const i = c.deform.indexOf(
|
|
31519
|
+
const i = c.deform.indexOf(mesh2);
|
|
29898
31520
|
if (i >= 0) c.deform.splice(i, 1);
|
|
29899
|
-
if (
|
|
29900
|
-
const geo =
|
|
29901
|
-
geo.applyMatrix4(new THREE.Matrix4().compose(
|
|
31521
|
+
if (mesh2.parent) mesh2.parent.remove(mesh2);
|
|
31522
|
+
const geo = mesh2.geometry;
|
|
31523
|
+
geo.applyMatrix4(new THREE.Matrix4().compose(mesh2.position, mesh2.quaternion, mesh2.scale));
|
|
29902
31524
|
if (o.reuv !== false) o.reuv = true;
|
|
29903
|
-
return kit.addGlass(c, geo, label, type, Object.assign({ mat:
|
|
31525
|
+
return kit.addGlass(c, geo, label, type, Object.assign({ mat: mesh2.material }, o));
|
|
29904
31526
|
};
|
|
29905
31527
|
kit.sideWindows = function(c, polys, Wg, T, label, o) {
|
|
29906
31528
|
o = o || {};
|
|
@@ -29946,12 +31568,12 @@ var GameVehiclesThree = (() => {
|
|
|
29946
31568
|
});
|
|
29947
31569
|
});
|
|
29948
31570
|
};
|
|
29949
|
-
kit.cutMesh = function(
|
|
29950
|
-
const src = o && o.sub ? subdivide(
|
|
31571
|
+
kit.cutMesh = function(mesh2, tests, deg, o) {
|
|
31572
|
+
const src = o && o.sub ? subdivide(mesh2.geometry, o.sub) : mesh2.geometry;
|
|
29951
31573
|
const r = cutGeometry(src, tests);
|
|
29952
31574
|
crease(r.geo, deg || 42);
|
|
29953
|
-
|
|
29954
|
-
|
|
31575
|
+
mesh2.geometry.dispose();
|
|
31576
|
+
mesh2.geometry = r.geo;
|
|
29955
31577
|
return r.cut;
|
|
29956
31578
|
};
|
|
29957
31579
|
kit.quadDef = function(pb, pt, Wg, T, which, bev, o) {
|
|
@@ -30149,8 +31771,8 @@ var GameVehiclesThree = (() => {
|
|
|
30149
31771
|
const pz = nR === 1 ? 0 : (i ? 1 : -1) * w / 4;
|
|
30150
31772
|
const back = gm(g, new THREE.CylinderGeometry(r * 1.06, r * 1.06, d * 0.8, 22), MATERIALS.housing, 0, 0, pz);
|
|
30151
31773
|
back.rotation.z = PI / 2;
|
|
30152
|
-
const
|
|
30153
|
-
|
|
31774
|
+
const ring2 = gm(g, new THREE.TorusGeometry(r * 1.02, 0.013, 8, 30), MATERIALS.chrome, d / 2 - 6e-3, 0, pz);
|
|
31775
|
+
ring2.rotation.y = PI / 2;
|
|
30154
31776
|
const bowl = gm(g, new THREE.SphereGeometry(r * 0.96, 18, 10, 0, PI * 2, 0, PI / 2), MATERIALS.reflectorLit, d / 2 - 0.012, 0, pz);
|
|
30155
31777
|
bowl.rotation.z = PI / 2;
|
|
30156
31778
|
bowl.scale.y = 0.55;
|
|
@@ -30227,8 +31849,8 @@ var GameVehiclesThree = (() => {
|
|
|
30227
31849
|
const e = gm(g, new THREE.CylinderGeometry(r * 0.9, r * 0.9, 0.012, 20), q * ls > 0 ? MATERIALS.tail : MATERIALS.tail, d / 2 - 0.02, 0, pz);
|
|
30228
31850
|
e.rotation.z = PI / 2;
|
|
30229
31851
|
inner.push(e);
|
|
30230
|
-
const
|
|
30231
|
-
|
|
31852
|
+
const ring2 = gm(g, new THREE.TorusGeometry(r, 0.01, 6, 24), MATERIALS.chrome, d / 2 - 4e-3, 0, pz);
|
|
31853
|
+
ring2.rotation.y = PI / 2;
|
|
30232
31854
|
const ln = gm(g, new THREE.SphereGeometry(r, 16, 8, 0, PI * 2, 0, PI / 2), MATERIALS.lensRed, d / 2 - 0.01, 0, pz);
|
|
30233
31855
|
ln.rotation.z = -PI / 2;
|
|
30234
31856
|
ln.scale.y = 0.25;
|
|
@@ -30321,7 +31943,7 @@ var GameVehiclesThree = (() => {
|
|
|
30321
31943
|
} else if (st === "mesh") {
|
|
30322
31944
|
gm(g, roundedBoxGeometry(0.05, h, w, Math.min(0.03, h * 0.3)), MATERIALS.housing);
|
|
30323
31945
|
const cell = 0.026;
|
|
30324
|
-
const
|
|
31946
|
+
const list2 = [];
|
|
30325
31947
|
const rows = Math.floor(h * 0.85 / (cell * 1.6));
|
|
30326
31948
|
const cols = Math.floor(w * 0.9 / (cell * 1.8));
|
|
30327
31949
|
for (let rI = 0; rI < rows; rI++)
|
|
@@ -30330,9 +31952,9 @@ var GameVehiclesThree = (() => {
|
|
|
30330
31952
|
hg.rotateZ(PI / 2);
|
|
30331
31953
|
hg.rotateX(PI / 6);
|
|
30332
31954
|
hg.translate(0.026, -h * 0.42 + (rI + 0.5) * h * 0.85 / rows, -w * 0.45 + (cI + 0.5 + rI % 2 * 0.5 - 0.25) * w * 0.9 / cols);
|
|
30333
|
-
|
|
31955
|
+
list2.push(hg);
|
|
30334
31956
|
}
|
|
30335
|
-
if (
|
|
31957
|
+
if (list2.length) gm(g, mergeGeometries(list2), MATERIALS.trim);
|
|
30336
31958
|
gm(g, roundedBoxGeometry(0.022, 0.014, w, 6e-3), MATERIALS.chrome, 0.03, h / 2 - 8e-3, 0);
|
|
30337
31959
|
} else if (st === "big") {
|
|
30338
31960
|
const fr = roundedBoxGeometry(0.06, h, w, 0.03);
|
|
@@ -31167,7 +32789,7 @@ var GameVehiclesThree = (() => {
|
|
|
31167
32789
|
m.underbodyGroup = ug;
|
|
31168
32790
|
const DK = makeMaterial("#1a1b1c", { roughness: 0.75, metalness: 0.3 });
|
|
31169
32791
|
const ST = MATERIALS.steel;
|
|
31170
|
-
function
|
|
32792
|
+
function box2(w, h, d, mat, x, y, z) {
|
|
31171
32793
|
return c.roundBox(w, h, d, Math.min(0.02, h * 0.4), mat, x, y, z, { parent: ug });
|
|
31172
32794
|
}
|
|
31173
32795
|
function rod(a, b, r, mat) {
|
|
@@ -31184,9 +32806,9 @@ var GameVehiclesThree = (() => {
|
|
|
31184
32806
|
rod(new V3(rx, rr, -zW), new V3(rx, rr, zW), 0.045, ST);
|
|
31185
32807
|
c.sphere(0.13, ST, rx, rr, 0, 1, 0.85, 1, { parent: ug });
|
|
31186
32808
|
rod(new V3(rx + 0.1, rr, 0), new V3(fx - 0.6, yU + 0.04, 0), 0.035, ST);
|
|
31187
|
-
} else
|
|
32809
|
+
} else box2(0.09, 0.08, zW * 2, DK, rx + 0.08, Math.max(yU, rr - 0.12), 0);
|
|
31188
32810
|
if (!ev) {
|
|
31189
|
-
|
|
32811
|
+
box2(Math.min(0.5, (fx - rx) * 0.2), 0.1, 0.38, DK, fx - 0.25, yU + 0.01, -0.05);
|
|
31190
32812
|
const tz = W * 0.3;
|
|
31191
32813
|
const mx = rx - 0.15;
|
|
31192
32814
|
const ty = Math.max(0.14, by - 0.06);
|
|
@@ -31203,10 +32825,10 @@ var GameVehiclesThree = (() => {
|
|
|
31203
32825
|
{ parent: ug, seg: 30, rs: 6 }
|
|
31204
32826
|
);
|
|
31205
32827
|
c.cylinder(0.1, 0.1, 0.42, ST, mx, ty + 0.02, tz, "x", { parent: ug });
|
|
31206
|
-
|
|
31207
|
-
|
|
32828
|
+
box2(0.24, 0.06, 0.2, DK, (fx + rx) / 2 + 0.1, ty, 0.16);
|
|
32829
|
+
box2(0.55, 0.18, W * 0.5, makeMaterial("#232527", { roughness: 0.7 }), rx + 0.62, Math.max(0.16, by - 0.02), -W * 0.1);
|
|
31208
32830
|
} else {
|
|
31209
|
-
|
|
32831
|
+
box2(
|
|
31210
32832
|
(fx - rx) * 0.72,
|
|
31211
32833
|
0.1,
|
|
31212
32834
|
W - 0.4,
|
|
@@ -31215,7 +32837,7 @@ var GameVehiclesThree = (() => {
|
|
|
31215
32837
|
Math.max(0.14, by - 0.03),
|
|
31216
32838
|
0
|
|
31217
32839
|
);
|
|
31218
|
-
for (let k = 0; k < 6; k++)
|
|
32840
|
+
for (let k = 0; k < 6; k++) box2(0.03, 0.02, W - 0.45, ST, rx + 0.4 + k * (fx - rx - 0.8) / 5, Math.max(0.14, by - 0.03) - 0.06, 0);
|
|
31219
32841
|
}
|
|
31220
32842
|
if (o.spare && m.rear < rx - 0.7) {
|
|
31221
32843
|
c.cylinder(0.32, 0.32, 0.2, MATERIALS.rubber, rx - 0.55, Math.max(0.2, by - 0.05), 0, null, { parent: ug });
|
|
@@ -31539,16 +33161,16 @@ var GameVehiclesThree = (() => {
|
|
|
31539
33161
|
}
|
|
31540
33162
|
} else {
|
|
31541
33163
|
const ns = o.spokes || 28;
|
|
31542
|
-
const
|
|
33164
|
+
const list2 = [];
|
|
31543
33165
|
for (let jj = 0; jj < ns; jj++) {
|
|
31544
33166
|
const a2 = jj / ns * PI * 2;
|
|
31545
33167
|
const cg = new THREE.CylinderGeometry(25e-4, 25e-4, sl, 4);
|
|
31546
33168
|
cg.applyMatrix4(
|
|
31547
33169
|
new THREE.Matrix4().makeRotationZ(a2 - PI / 2).setPosition(Math.cos(a2) * sl / 2, Math.sin(a2) * sl / 2, (jj % 2 ? 1 : -1) * 0.012)
|
|
31548
33170
|
);
|
|
31549
|
-
|
|
33171
|
+
list2.push(cg);
|
|
31550
33172
|
}
|
|
31551
|
-
g.add(new THREE.Mesh(mergeGeometries(
|
|
33173
|
+
g.add(new THREE.Mesh(mergeGeometries(list2), MATERIALS.chrome));
|
|
31552
33174
|
}
|
|
31553
33175
|
const hub = new THREE.Mesh(new THREE.CylinderGeometry(0.035, 0.035, 0.1, 12), MATERIALS.steel);
|
|
31554
33176
|
hub.rotation.x = PI / 2;
|
|
@@ -31728,9 +33350,9 @@ var GameVehiclesThree = (() => {
|
|
|
31728
33350
|
return puffTexture(k * 17, true);
|
|
31729
33351
|
});
|
|
31730
33352
|
}
|
|
31731
|
-
const
|
|
33353
|
+
const list2 = fire ? FIRE_TEXTURES : SMOKE_TEXTURES;
|
|
31732
33354
|
const mat = new THREE.SpriteMaterial({
|
|
31733
|
-
map:
|
|
33355
|
+
map: list2[Math.floor(Math.random() * list2.length)],
|
|
31734
33356
|
color: new THREE.Color(col),
|
|
31735
33357
|
transparent: true,
|
|
31736
33358
|
depthWrite: false,
|
|
@@ -33033,7 +34655,7 @@ var GameVehiclesThree = (() => {
|
|
|
33033
34655
|
}
|
|
33034
34656
|
});
|
|
33035
34657
|
const dset = new Set(c.deform);
|
|
33036
|
-
const
|
|
34658
|
+
const box2 = new THREE.Box3();
|
|
33037
34659
|
c.vehicle.children.forEach(function(o) {
|
|
33038
34660
|
if (dset.has(o) || o.userData.noFollow) return;
|
|
33039
34661
|
if (!(o.isMesh || o.isGroup && o.userData.rigid)) return;
|
|
@@ -33044,10 +34666,10 @@ var GameVehiclesThree = (() => {
|
|
|
33044
34666
|
if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
|
|
33045
34667
|
o.userData.bb0 = o.geometry.boundingBox.clone().applyMatrix4(o.matrix);
|
|
33046
34668
|
} else {
|
|
33047
|
-
|
|
33048
|
-
|
|
33049
|
-
o.userData.c0 =
|
|
33050
|
-
o.userData.bb0 =
|
|
34669
|
+
box2.setFromObject(o);
|
|
34670
|
+
box2.applyMatrix4(gInv);
|
|
34671
|
+
o.userData.c0 = box2.getCenter(new V3());
|
|
34672
|
+
o.userData.bb0 = box2.clone();
|
|
33051
34673
|
}
|
|
33052
34674
|
o.userData.pos0 = o.position.clone();
|
|
33053
34675
|
}
|
|
@@ -33341,11 +34963,11 @@ var GameVehiclesThree = (() => {
|
|
|
33341
34963
|
[12, "#d8322a", kit.t("blast.lethal", { m: 12 })],
|
|
33342
34964
|
[30, "#e0a548", kit.t("blast.injury", { m: 30 })]
|
|
33343
34965
|
].forEach(function(r) {
|
|
33344
|
-
const
|
|
33345
|
-
|
|
33346
|
-
|
|
33347
|
-
|
|
33348
|
-
g.add(
|
|
34966
|
+
const ring2 = new THREE.Mesh(new THREE.RingGeometry(r[0] - 0.25, r[0], 96), boomMat(r[1], 0.85));
|
|
34967
|
+
ring2.rotation.x = -PI / 2;
|
|
34968
|
+
ring2.position.y = 0.06;
|
|
34969
|
+
ring2.renderOrder = 5;
|
|
34970
|
+
g.add(ring2);
|
|
33349
34971
|
const fill2 = new THREE.Mesh(new THREE.CircleGeometry(r[0], 96), boomMat(r[1], 0.07));
|
|
33350
34972
|
fill2.rotation.x = -PI / 2;
|
|
33351
34973
|
fill2.position.y = 0.05;
|
|
@@ -33362,7 +34984,7 @@ var GameVehiclesThree = (() => {
|
|
|
33362
34984
|
lb.rotation.x = -PI / 2;
|
|
33363
34985
|
lb.position.set(0, 0.08, r[0] + r[0] * 0.06);
|
|
33364
34986
|
g.add(lb);
|
|
33365
|
-
c.bigFx.rings.push(
|
|
34987
|
+
c.bigFx.rings.push(ring2, fill2, lb);
|
|
33366
34988
|
});
|
|
33367
34989
|
}
|
|
33368
34990
|
function detonate(c) {
|
|
@@ -33635,7 +35257,7 @@ var GameVehiclesThree = (() => {
|
|
|
33635
35257
|
const I = kit._;
|
|
33636
35258
|
const { MATERIALS } = I;
|
|
33637
35259
|
function rollMeshes(c) {
|
|
33638
|
-
const
|
|
35260
|
+
const list2 = [];
|
|
33639
35261
|
const thin = [];
|
|
33640
35262
|
c.root.updateMatrixWorld(true);
|
|
33641
35263
|
const inv = new THREE.Matrix4().copy(c.vehicle.matrixWorld).invert();
|
|
@@ -33653,9 +35275,9 @@ var GameVehiclesThree = (() => {
|
|
|
33653
35275
|
thin.push({ o: ob, M });
|
|
33654
35276
|
return;
|
|
33655
35277
|
}
|
|
33656
|
-
|
|
35278
|
+
list2.push({ o: ob, M });
|
|
33657
35279
|
});
|
|
33658
|
-
return { list, thin };
|
|
35280
|
+
return { list: list2, thin };
|
|
33659
35281
|
}
|
|
33660
35282
|
function convexHull(pts) {
|
|
33661
35283
|
pts.sort(function(a, b) {
|
|
@@ -33738,7 +35360,7 @@ var GameVehiclesThree = (() => {
|
|
|
33738
35360
|
};
|
|
33739
35361
|
function rollContact(c, A, q) {
|
|
33740
35362
|
const m = c.meta;
|
|
33741
|
-
const
|
|
35363
|
+
const list2 = [];
|
|
33742
35364
|
const dy = A.cen[0] - q[0];
|
|
33743
35365
|
const dz = A.cen[1] - q[1];
|
|
33744
35366
|
const dl = Math.hypot(dy, dz) || 1;
|
|
@@ -33746,17 +35368,17 @@ var GameVehiclesThree = (() => {
|
|
|
33746
35368
|
const f = 0.75;
|
|
33747
35369
|
const bike = m.kind === "bike";
|
|
33748
35370
|
(bike ? [0] : [-0.28, 0, 0.28]).forEach(function(k) {
|
|
33749
|
-
|
|
35371
|
+
list2.push([new V3(A.x + k * A.L, q[0], q[1]), dir]);
|
|
33750
35372
|
});
|
|
33751
35373
|
if (!bike && Math.abs(dir.z) > 0.75 && m.top - m.belt > 0.25 && A.hits < 3) {
|
|
33752
35374
|
const sd = -Math.sign(dir.z);
|
|
33753
35375
|
const yw = m.belt + (m.top - m.belt) * 0.45;
|
|
33754
35376
|
[-0.25, 0.2].forEach(function(k) {
|
|
33755
35377
|
const h = I.probe(c, new V3(A.x + k * A.L, yw, sd * (m.width / 2 + 2)), new V3(0, 0, -sd), 2 + m.width);
|
|
33756
|
-
if (h)
|
|
35378
|
+
if (h) list2.push([h.p, new V3(0, 0, -sd)]);
|
|
33757
35379
|
});
|
|
33758
35380
|
}
|
|
33759
|
-
|
|
35381
|
+
list2.forEach(function(e) {
|
|
33760
35382
|
I.impact(c, e[0], e[1], f, { noStain: true, maxDepth: 0.1 });
|
|
33761
35383
|
const pf = c.toEffects(e[0]);
|
|
33762
35384
|
pf.y = Math.max(0.03, pf.y);
|
|
@@ -33766,15 +35388,15 @@ var GameVehiclesThree = (() => {
|
|
|
33766
35388
|
});
|
|
33767
35389
|
A.hits++;
|
|
33768
35390
|
A.bounce = A.hits === 1 ? 0.06 : 0.1;
|
|
33769
|
-
if (m.kind === "boat") I.burst(c, "water", c.toEffects(
|
|
35391
|
+
if (m.kind === "boat") I.burst(c, "water", c.toEffects(list2[0][0]).setY(0.05), 30, { speed: 3 });
|
|
33770
35392
|
}
|
|
33771
|
-
function exactMinY(c,
|
|
35393
|
+
function exactMinY(c, list2) {
|
|
33772
35394
|
c.root.updateMatrixWorld(true);
|
|
33773
35395
|
const inv = new THREE.Matrix4().copy(c.root.matrixWorld).invert();
|
|
33774
35396
|
const M = new THREE.Matrix4();
|
|
33775
35397
|
const v = new V3();
|
|
33776
35398
|
let mn = 1e9;
|
|
33777
|
-
|
|
35399
|
+
list2.forEach(function(e) {
|
|
33778
35400
|
const ob = e.o;
|
|
33779
35401
|
if (!ob.parent || !I.shown(c, ob)) return;
|
|
33780
35402
|
M.multiplyMatrices(inv, ob.matrixWorld);
|
|
@@ -34473,6 +36095,153 @@ var GameVehiclesThree = (() => {
|
|
|
34473
36095
|
return hole;
|
|
34474
36096
|
}
|
|
34475
36097
|
const _zr = new THREE.Raycaster();
|
|
36098
|
+
const PROXY_MIN_TRIANGLES = 500;
|
|
36099
|
+
const STROKE_REACH = 0.6;
|
|
36100
|
+
const _pv = new V3();
|
|
36101
|
+
const _pm = new THREE.Matrix4();
|
|
36102
|
+
function decalRegion(c, z) {
|
|
36103
|
+
const B = z.box;
|
|
36104
|
+
const lo = [0, 1, 2].map(function(k) {
|
|
36105
|
+
return I.boxLo(B, k) - STROKE_REACH;
|
|
36106
|
+
});
|
|
36107
|
+
const hi = [0, 1, 2].map(function(k) {
|
|
36108
|
+
return I.boxHi(B, k) + STROKE_REACH;
|
|
36109
|
+
});
|
|
36110
|
+
const a = axisOf(z.dir);
|
|
36111
|
+
const dn = z.dir.clone().normalize();
|
|
36112
|
+
const sg = z.dir.getComponent(a) > 0 ? 1 : -1;
|
|
36113
|
+
const outer = sg > 0 ? I.boxLo(B, a) - 0.6 : I.boxHi(B, a) + 0.6;
|
|
36114
|
+
const far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
36115
|
+
for (let i = 0; i < 8; i++) {
|
|
36116
|
+
const p = new V3();
|
|
36117
|
+
p.setComponent(a, outer);
|
|
36118
|
+
[0, 1, 2].filter(function(k) {
|
|
36119
|
+
return k !== a;
|
|
36120
|
+
}).forEach(function(k, j) {
|
|
36121
|
+
p.setComponent(k, i >> j & 1 ? I.boxHi(B, k) : I.boxLo(B, k));
|
|
36122
|
+
});
|
|
36123
|
+
for (let e = 0; e < 2; e++) {
|
|
36124
|
+
const q = e ? p.clone().addScaledVector(dn, far) : p;
|
|
36125
|
+
for (let k = 0; k < 3; k++) {
|
|
36126
|
+
lo[k] = Math.min(lo[k], q.getComponent(k) - 0.05);
|
|
36127
|
+
hi[k] = Math.max(hi[k], q.getComponent(k) + 0.05);
|
|
36128
|
+
}
|
|
36129
|
+
}
|
|
36130
|
+
}
|
|
36131
|
+
return { lo, hi };
|
|
36132
|
+
}
|
|
36133
|
+
function regionCands(c, z, cands) {
|
|
36134
|
+
if (!cands.some(heavy)) return cands;
|
|
36135
|
+
const R = decalRegion(c, z);
|
|
36136
|
+
const Mw = c.vehicle.matrixWorld;
|
|
36137
|
+
return cands.map(function(o) {
|
|
36138
|
+
if (!heavy(o)) return o;
|
|
36139
|
+
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
36140
|
+
if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
|
|
36141
|
+
return proxyIn(o, Mw, R);
|
|
36142
|
+
});
|
|
36143
|
+
}
|
|
36144
|
+
function heavy(o) {
|
|
36145
|
+
const g = o.geometry;
|
|
36146
|
+
const pos = g && g.attributes && g.attributes.position;
|
|
36147
|
+
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;
|
|
36148
|
+
}
|
|
36149
|
+
function proxyIn(o, Mw, R) {
|
|
36150
|
+
_pm.copy(o.matrixWorld).invert().multiply(Mw);
|
|
36151
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
36152
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
36153
|
+
for (let i = 0; i < 8; i++) {
|
|
36154
|
+
_pv.set(i & 1 ? R.hi[0] : R.lo[0], i & 2 ? R.hi[1] : R.lo[1], i & 4 ? R.hi[2] : R.lo[2]).applyMatrix4(_pm);
|
|
36155
|
+
for (let k = 0; k < 3; k++) {
|
|
36156
|
+
lo[k] = Math.min(lo[k], _pv.getComponent(k));
|
|
36157
|
+
hi[k] = Math.max(hi[k], _pv.getComponent(k));
|
|
36158
|
+
}
|
|
36159
|
+
}
|
|
36160
|
+
const g = o.geometry;
|
|
36161
|
+
const P = g.attributes.position.array;
|
|
36162
|
+
const ix = g.index ? g.index.array : null;
|
|
36163
|
+
const n = ix ? ix.length : P.length / 3;
|
|
36164
|
+
const keep = new Uint32Array(n - n % 3);
|
|
36165
|
+
let nk = 0;
|
|
36166
|
+
for (let t = 0; t + 2 < n; t += 3) {
|
|
36167
|
+
const a = (ix ? ix[t] : t) * 3;
|
|
36168
|
+
const b = (ix ? ix[t + 1] : t + 1) * 3;
|
|
36169
|
+
const d = (ix ? ix[t + 2] : t + 2) * 3;
|
|
36170
|
+
let out = false;
|
|
36171
|
+
for (let k = 0; k < 3 && !out; k++) {
|
|
36172
|
+
const u = P[a + k];
|
|
36173
|
+
const v = P[b + k];
|
|
36174
|
+
const w = P[d + k];
|
|
36175
|
+
out = Math.max(u, v, w) < lo[k] || Math.min(u, v, w) > hi[k];
|
|
36176
|
+
}
|
|
36177
|
+
if (!out) {
|
|
36178
|
+
keep[nk++] = ix ? ix[t] : t;
|
|
36179
|
+
keep[nk++] = ix ? ix[t + 1] : t + 1;
|
|
36180
|
+
keep[nk++] = ix ? ix[t + 2] : t + 2;
|
|
36181
|
+
}
|
|
36182
|
+
}
|
|
36183
|
+
if (!nk) return null;
|
|
36184
|
+
const kept = keep.slice(0, nk);
|
|
36185
|
+
const box2 = new Float32Array(kept.length / 3 * 6);
|
|
36186
|
+
for (let t = 0, j = 0; t < kept.length; t += 3, j += 6) {
|
|
36187
|
+
const a = kept[t] * 3;
|
|
36188
|
+
const b = kept[t + 1] * 3;
|
|
36189
|
+
const d = kept[t + 2] * 3;
|
|
36190
|
+
for (let k = 0; k < 3; k++) {
|
|
36191
|
+
box2[j + k] = Math.min(P[a + k], P[b + k], P[d + k]);
|
|
36192
|
+
box2[j + 3 + k] = Math.max(P[a + k], P[b + k], P[d + k]);
|
|
36193
|
+
}
|
|
36194
|
+
}
|
|
36195
|
+
const pg = new THREE.BufferGeometry();
|
|
36196
|
+
pg.setAttribute("position", g.attributes.position);
|
|
36197
|
+
pg.setIndex(new THREE.BufferAttribute(new Uint32Array(kept.length), 1));
|
|
36198
|
+
pg.boundingSphere = g.boundingSphere;
|
|
36199
|
+
pg.boundingBox = g.boundingBox;
|
|
36200
|
+
const proxy = new THREE.Mesh(pg, o.material);
|
|
36201
|
+
proxy.layers.mask = o.layers.mask;
|
|
36202
|
+
proxy.proxyOf = o;
|
|
36203
|
+
proxy.kept = kept;
|
|
36204
|
+
proxy.keptBox = box2;
|
|
36205
|
+
return proxy;
|
|
36206
|
+
}
|
|
36207
|
+
function narrowTo(rc, proxy) {
|
|
36208
|
+
const o = proxy.proxyOf;
|
|
36209
|
+
const ray = rc.ray;
|
|
36210
|
+
_pm.copy(o.matrixWorld).invert();
|
|
36211
|
+
_pv.copy(ray.origin).applyMatrix4(_pm);
|
|
36212
|
+
const x0 = _pv.x;
|
|
36213
|
+
const y0 = _pv.y;
|
|
36214
|
+
const z0 = _pv.z;
|
|
36215
|
+
_pv.copy(ray.direction).multiplyScalar(rc.far).add(ray.origin).applyMatrix4(_pm);
|
|
36216
|
+
const lo0 = Math.min(x0, _pv.x) - 1e-4;
|
|
36217
|
+
const lo1 = Math.min(y0, _pv.y) - 1e-4;
|
|
36218
|
+
const lo2 = Math.min(z0, _pv.z) - 1e-4;
|
|
36219
|
+
const hi0 = Math.max(x0, _pv.x) + 1e-4;
|
|
36220
|
+
const hi1 = Math.max(y0, _pv.y) + 1e-4;
|
|
36221
|
+
const hi2 = Math.max(z0, _pv.z) + 1e-4;
|
|
36222
|
+
const K = proxy.kept;
|
|
36223
|
+
const X = proxy.keptBox;
|
|
36224
|
+
const dst = proxy.geometry.index.array;
|
|
36225
|
+
let m = 0;
|
|
36226
|
+
for (let t = 0, j = 0; t < K.length; t += 3, j += 6) {
|
|
36227
|
+
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;
|
|
36228
|
+
dst[m++] = K[t];
|
|
36229
|
+
dst[m++] = K[t + 1];
|
|
36230
|
+
dst[m++] = K[t + 2];
|
|
36231
|
+
}
|
|
36232
|
+
proxy.geometry.setDrawRange(0, m);
|
|
36233
|
+
}
|
|
36234
|
+
function castAt(rc, cands) {
|
|
36235
|
+
for (let i = 0; i < cands.length; i++) {
|
|
36236
|
+
const q = cands[i];
|
|
36237
|
+
if (!q.proxyOf) continue;
|
|
36238
|
+
q.matrixWorld.copy(q.proxyOf.matrixWorld);
|
|
36239
|
+
narrowTo(rc, q);
|
|
36240
|
+
}
|
|
36241
|
+
const hits = rc.intersectObjects(cands, false);
|
|
36242
|
+
for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
|
|
36243
|
+
return hits;
|
|
36244
|
+
}
|
|
34476
36245
|
function zoneCands(c, z, inv, glassToo) {
|
|
34477
36246
|
const out = [];
|
|
34478
36247
|
c.vehicle.traverse(function(o) {
|
|
@@ -34525,7 +36294,7 @@ var GameVehiclesThree = (() => {
|
|
|
34525
36294
|
});
|
|
34526
36295
|
_zr.set(org.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
|
|
34527
36296
|
_zr.far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
34528
|
-
const hits = _zr
|
|
36297
|
+
const hits = castAt(_zr, cands);
|
|
34529
36298
|
for (let i = 0; i < hits.length; i++) {
|
|
34530
36299
|
const h = hits[i];
|
|
34531
36300
|
if (!h.face) continue;
|
|
@@ -34553,7 +36322,7 @@ var GameVehiclesThree = (() => {
|
|
|
34553
36322
|
const q = s.p.clone().addScaledVector(t, len * 0.5 * k / M);
|
|
34554
36323
|
_rt.set(q.clone().addScaledVector(n, 0.08).applyMatrix4(Mw), n.clone().negate().transformDirection(Mw));
|
|
34555
36324
|
_rt.far = 0.2;
|
|
34556
|
-
const h = _rt
|
|
36325
|
+
const h = castAt(_rt, cands).find(function(x) {
|
|
34557
36326
|
return x.face;
|
|
34558
36327
|
});
|
|
34559
36328
|
if (!h) return null;
|
|
@@ -34624,6 +36393,7 @@ var GameVehiclesThree = (() => {
|
|
|
34624
36393
|
const R = c.rand;
|
|
34625
36394
|
const need = (spec.fine || 0) + (spec.deep || 0) + (spec.chip || 0) + (spec.rust || 0) + (spec.tear || 0) + (spec.ding || 0) + (spec.soot || 0) + (spec.crater || 0);
|
|
34626
36395
|
if (!need) return [];
|
|
36396
|
+
cands = regionCands(c, z, cands).filter(Boolean);
|
|
34627
36397
|
const S = zoneSurf(c, z, need + 2, R, cands);
|
|
34628
36398
|
let k = 0;
|
|
34629
36399
|
const ang0 = R() * PI;
|
|
@@ -34702,8 +36472,25 @@ var GameVehiclesThree = (() => {
|
|
|
34702
36472
|
}
|
|
34703
36473
|
function subdivIn(geo, rel, B, maxLen) {
|
|
34704
36474
|
const a = geo.attributes.position.array;
|
|
34705
|
-
|
|
34706
|
-
|
|
36475
|
+
let out = new Float32Array(a.length + 4096);
|
|
36476
|
+
let used = 0;
|
|
36477
|
+
const push = function(a0, a1, a2, b0, b1, b2, c0, c1, c2) {
|
|
36478
|
+
if (used + 9 > out.length) {
|
|
36479
|
+
const bigger = new Float32Array(out.length * 2);
|
|
36480
|
+
bigger.set(out);
|
|
36481
|
+
out = bigger;
|
|
36482
|
+
}
|
|
36483
|
+
out[used] = a0;
|
|
36484
|
+
out[used + 1] = a1;
|
|
36485
|
+
out[used + 2] = a2;
|
|
36486
|
+
out[used + 3] = b0;
|
|
36487
|
+
out[used + 4] = b1;
|
|
36488
|
+
out[used + 5] = b2;
|
|
36489
|
+
out[used + 6] = c0;
|
|
36490
|
+
out[used + 7] = c1;
|
|
36491
|
+
out[used + 8] = c2;
|
|
36492
|
+
used += 9;
|
|
36493
|
+
};
|
|
34707
36494
|
const e = 0.15;
|
|
34708
36495
|
function d(p, q) {
|
|
34709
36496
|
return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
|
|
@@ -34717,7 +36504,7 @@ var GameVehiclesThree = (() => {
|
|
|
34717
36504
|
const ca = d(C, A);
|
|
34718
36505
|
const mx = Math.max(ab, bc, ca);
|
|
34719
36506
|
if (mx <= maxLen || depth > 9) {
|
|
34720
|
-
|
|
36507
|
+
push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
34721
36508
|
return;
|
|
34722
36509
|
}
|
|
34723
36510
|
if (mx === ab) {
|
|
@@ -34734,31 +36521,26 @@ var GameVehiclesThree = (() => {
|
|
|
34734
36521
|
tri(F2, Bv, C, depth + 1);
|
|
34735
36522
|
}
|
|
34736
36523
|
}
|
|
36524
|
+
const M = rel.elements;
|
|
36525
|
+
const at = function(x, y, z, k) {
|
|
36526
|
+
const w = 1 / (M[3] * x + M[7] * y + M[11] * z + M[15]);
|
|
36527
|
+
return k === 0 ? (M[0] * x + M[4] * y + M[8] * z + M[12]) * w : k === 1 ? (M[1] * x + M[5] * y + M[9] * z + M[13]) * w : (M[2] * x + M[6] * y + M[10] * z + M[14]) * w;
|
|
36528
|
+
};
|
|
36529
|
+
const lo = [B.x0 - e, B.y0 - e, B.z0 - e];
|
|
36530
|
+
const hi = [B.x1 + e, B.y1 + e, B.z1 + e];
|
|
34737
36531
|
for (let i = 0; i < a.length; i += 9) {
|
|
34738
|
-
|
|
34739
|
-
|
|
34740
|
-
|
|
34741
|
-
|
|
34742
|
-
|
|
34743
|
-
|
|
34744
|
-
|
|
34745
|
-
|
|
34746
|
-
|
|
34747
|
-
[A, Bv, C].forEach(function(p) {
|
|
34748
|
-
v.set(p[0], p[1], p[2]).applyMatrix4(rel);
|
|
34749
|
-
x0 = Math.min(x0, v.x);
|
|
34750
|
-
x1 = Math.max(x1, v.x);
|
|
34751
|
-
y0 = Math.min(y0, v.y);
|
|
34752
|
-
y1 = Math.max(y1, v.y);
|
|
34753
|
-
z0 = Math.min(z0, v.z);
|
|
34754
|
-
z1 = Math.max(z1, v.z);
|
|
34755
|
-
});
|
|
34756
|
-
if (x1 < B.x0 - e || x0 > B.x1 + e || y1 < B.y0 - e || y0 > B.y1 + e || z1 < B.z0 - e || z0 > B.z1 + e)
|
|
34757
|
-
out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
34758
|
-
else tri(A, Bv, C, 0);
|
|
36532
|
+
let outside = false;
|
|
36533
|
+
for (let k = 0; k < 3 && !outside; k++) {
|
|
36534
|
+
const p = at(a[i], a[i + 1], a[i + 2], k);
|
|
36535
|
+
const q = at(a[i + 3], a[i + 4], a[i + 5], k);
|
|
36536
|
+
const r = at(a[i + 6], a[i + 7], a[i + 8], k);
|
|
36537
|
+
outside = Math.max(p, q, r) < lo[k] || Math.min(p, q, r) > hi[k];
|
|
36538
|
+
}
|
|
36539
|
+
if (outside) push(a[i], a[i + 1], a[i + 2], a[i + 3], a[i + 4], a[i + 5], a[i + 6], a[i + 7], a[i + 8]);
|
|
36540
|
+
else tri([a[i], a[i + 1], a[i + 2]], [a[i + 3], a[i + 4], a[i + 5]], [a[i + 6], a[i + 7], a[i + 8]], 0);
|
|
34759
36541
|
}
|
|
34760
36542
|
const g = new THREE.BufferGeometry();
|
|
34761
|
-
g.setAttribute("position", new THREE.
|
|
36543
|
+
g.setAttribute("position", new THREE.BufferAttribute(out.slice(0, used), 3));
|
|
34762
36544
|
g.userData.crease = true;
|
|
34763
36545
|
g.userData.p0 = null;
|
|
34764
36546
|
return g;
|
|
@@ -34781,6 +36563,17 @@ var GameVehiclesThree = (() => {
|
|
|
34781
36563
|
});
|
|
34782
36564
|
return out;
|
|
34783
36565
|
}
|
|
36566
|
+
function boxInFrame(B, m, tmp) {
|
|
36567
|
+
const r = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
|
|
36568
|
+
for (let i = 0; i < 8; i++) {
|
|
36569
|
+
tmp.set(i & 1 ? B.x1 : B.x0, i & 2 ? B.y1 : B.y0, i & 4 ? B.z1 : B.z0).applyMatrix4(m);
|
|
36570
|
+
for (let k = 0; k < 3; k++) {
|
|
36571
|
+
r[k] = Math.min(r[k], tmp.getComponent(k) - 1e-4);
|
|
36572
|
+
r[k + 3] = Math.max(r[k + 3], tmp.getComponent(k) + 1e-4);
|
|
36573
|
+
}
|
|
36574
|
+
}
|
|
36575
|
+
return r;
|
|
36576
|
+
}
|
|
34784
36577
|
function zoneDent(c, z, dents, dirty, opt) {
|
|
34785
36578
|
opt = opt || {};
|
|
34786
36579
|
const B = z.box;
|
|
@@ -34835,6 +36628,7 @@ var GameVehiclesThree = (() => {
|
|
|
34835
36628
|
g = msh.geometry = g.clone();
|
|
34836
36629
|
msh.userData.zCloned = true;
|
|
34837
36630
|
}
|
|
36631
|
+
let boundsDue = false;
|
|
34838
36632
|
const nonIdx = !g.index;
|
|
34839
36633
|
const onlyPos = Object.keys(g.attributes).every(function(k) {
|
|
34840
36634
|
return k === "position" || k === "normal";
|
|
@@ -34843,15 +36637,17 @@ var GameVehiclesThree = (() => {
|
|
|
34843
36637
|
const ng = subdivIn(g, rel, B, opt.sub || 0.075);
|
|
34844
36638
|
g.dispose();
|
|
34845
36639
|
g = msh.geometry = ng;
|
|
34846
|
-
|
|
34847
|
-
ng.computeBoundingBox();
|
|
36640
|
+
boundsDue = true;
|
|
34848
36641
|
dirty.add(msh);
|
|
34849
36642
|
}
|
|
34850
36643
|
irel.copy(rel).invert();
|
|
34851
36644
|
const pos = g.attributes.position;
|
|
34852
36645
|
let changed = false;
|
|
36646
|
+
const near = boxInFrame(B, irel, v);
|
|
34853
36647
|
for (let i = 0; i < pos.count; i++) {
|
|
34854
|
-
v.fromBufferAttribute(pos, i)
|
|
36648
|
+
v.fromBufferAttribute(pos, i);
|
|
36649
|
+
if (v.x < near[0] || v.x > near[3] || v.y < near[1] || v.y > near[4] || v.z < near[2] || v.z > near[5]) continue;
|
|
36650
|
+
v.applyMatrix4(rel);
|
|
34855
36651
|
const f = field(v);
|
|
34856
36652
|
if (f <= 1e-5) continue;
|
|
34857
36653
|
v.addScaledVector(d, f);
|
|
@@ -34872,9 +36668,11 @@ var GameVehiclesThree = (() => {
|
|
|
34872
36668
|
}
|
|
34873
36669
|
if (changed) {
|
|
34874
36670
|
pos.needsUpdate = true;
|
|
36671
|
+
dirty.add(msh);
|
|
36672
|
+
}
|
|
36673
|
+
if (changed || boundsDue) {
|
|
34875
36674
|
g.computeBoundingSphere();
|
|
34876
36675
|
g.computeBoundingBox();
|
|
34877
|
-
dirty.add(msh);
|
|
34878
36676
|
}
|
|
34879
36677
|
});
|
|
34880
36678
|
const dset = new Set(c.deform);
|
|
@@ -35954,9 +37752,9 @@ var GameVehiclesThree = (() => {
|
|
|
35954
37752
|
down: new V3(0, 1, 0)
|
|
35955
37753
|
}[d] || null;
|
|
35956
37754
|
}
|
|
35957
|
-
function resolveObjs(c,
|
|
37755
|
+
function resolveObjs(c, list2, z) {
|
|
35958
37756
|
const out = [];
|
|
35959
|
-
(
|
|
37757
|
+
(list2 || []).forEach(function(o) {
|
|
35960
37758
|
if (!o) return;
|
|
35961
37759
|
if (typeof o === "string") {
|
|
35962
37760
|
c.parts.forEach(function(p) {
|
|
@@ -35984,22 +37782,22 @@ var GameVehiclesThree = (() => {
|
|
|
35984
37782
|
}
|
|
35985
37783
|
function deriveZones(c) {
|
|
35986
37784
|
const m = c.meta;
|
|
35987
|
-
let
|
|
37785
|
+
let list2 = [];
|
|
35988
37786
|
const byId = {};
|
|
35989
37787
|
(m.zones === false ? [] : I.autoZones(c)).forEach(function(z) {
|
|
35990
37788
|
byId[z.id] = z;
|
|
35991
|
-
|
|
37789
|
+
list2.push(z);
|
|
35992
37790
|
});
|
|
35993
37791
|
(c.zoneDefs || []).forEach(function(d) {
|
|
35994
37792
|
let z = byId[d.id];
|
|
35995
37793
|
if (d.remove) {
|
|
35996
37794
|
if (z) {
|
|
35997
|
-
|
|
37795
|
+
list2.splice(list2.indexOf(z), 1);
|
|
35998
37796
|
delete byId[d.id];
|
|
35999
37797
|
}
|
|
36000
|
-
|
|
37798
|
+
list2.slice().forEach(function(q) {
|
|
36001
37799
|
if (q.id.indexOf(d.id + "_") === 0 && /^\d+$/.test(q.id.slice(d.id.length + 1))) {
|
|
36002
|
-
|
|
37800
|
+
list2.splice(list2.indexOf(q), 1);
|
|
36003
37801
|
delete byId[q.id];
|
|
36004
37802
|
}
|
|
36005
37803
|
});
|
|
@@ -36012,7 +37810,7 @@ var GameVehiclesThree = (() => {
|
|
|
36012
37810
|
} else {
|
|
36013
37811
|
z = Object.assign({ type: "panel" }, d);
|
|
36014
37812
|
byId[d.id] = z;
|
|
36015
|
-
|
|
37813
|
+
list2.push(z);
|
|
36016
37814
|
}
|
|
36017
37815
|
});
|
|
36018
37816
|
const inv = I.worldInverseOf(c);
|
|
@@ -36045,10 +37843,10 @@ var GameVehiclesThree = (() => {
|
|
|
36045
37843
|
}
|
|
36046
37844
|
z.box = I.normalizeBox(bb);
|
|
36047
37845
|
});
|
|
36048
|
-
|
|
37846
|
+
list2 = list2.filter(function(z) {
|
|
36049
37847
|
return z.box && z.name;
|
|
36050
37848
|
});
|
|
36051
|
-
|
|
37849
|
+
list2.forEach(function(z) {
|
|
36052
37850
|
z.glass = (z.glass || []).slice();
|
|
36053
37851
|
z.lights = (z.lights || []).slice();
|
|
36054
37852
|
z.wheels = (z.wheels || []).slice();
|
|
@@ -36085,7 +37883,7 @@ var GameVehiclesThree = (() => {
|
|
|
36085
37883
|
if (owner.has(g) || !g.parent || !g.userData.glass || g.userData.ghost) return;
|
|
36086
37884
|
const cg = I.localBox(c, g, inv).getCenter(new V3());
|
|
36087
37885
|
let best = null;
|
|
36088
|
-
|
|
37886
|
+
list2.forEach(function(z) {
|
|
36089
37887
|
if (z.internal || z.type === "wheel" || z.type === "light") return;
|
|
36090
37888
|
if (I.boxContains(z.box, cg.x, cg.y, cg.z, 0.05) && (!best || I.boxVolume(z.box) < I.boxVolume(best.box))) best = z;
|
|
36091
37889
|
});
|
|
@@ -36094,7 +37892,7 @@ var GameVehiclesThree = (() => {
|
|
|
36094
37892
|
owner.set(g, best);
|
|
36095
37893
|
}
|
|
36096
37894
|
});
|
|
36097
|
-
const looseParts =
|
|
37895
|
+
const looseParts = list2.filter(function(z) {
|
|
36098
37896
|
return z.type === "part";
|
|
36099
37897
|
});
|
|
36100
37898
|
if (looseParts.length)
|
|
@@ -36119,7 +37917,7 @@ var GameVehiclesThree = (() => {
|
|
|
36119
37917
|
});
|
|
36120
37918
|
}
|
|
36121
37919
|
});
|
|
36122
|
-
|
|
37920
|
+
list2.forEach(function(z) {
|
|
36123
37921
|
if (!z.mirror) return;
|
|
36124
37922
|
z.mirrors = [];
|
|
36125
37923
|
const B = z.box;
|
|
@@ -36151,21 +37949,21 @@ var GameVehiclesThree = (() => {
|
|
|
36151
37949
|
});
|
|
36152
37950
|
}
|
|
36153
37951
|
});
|
|
36154
|
-
|
|
37952
|
+
list2.forEach(function(z) {
|
|
36155
37953
|
const B = z.box;
|
|
36156
37954
|
z.map = z.map || [Math.max(B.x0, R - 0.3), Math.min(B.x1, F + 0.3), Math.max(B.z0, -W / 2 - 0.35), Math.min(B.z1, W / 2 + 0.35)];
|
|
36157
37955
|
});
|
|
36158
|
-
carMap(c,
|
|
37956
|
+
carMap(c, list2);
|
|
36159
37957
|
c.zoneOwners = owner;
|
|
36160
|
-
return
|
|
37958
|
+
return list2;
|
|
36161
37959
|
}
|
|
36162
|
-
function carMap(c,
|
|
37960
|
+
function carMap(c, list2) {
|
|
36163
37961
|
const m = c.meta;
|
|
36164
37962
|
const W = m.width || 1.7;
|
|
36165
37963
|
const hw = W / 2;
|
|
36166
37964
|
const gh = m.glasshouse;
|
|
36167
37965
|
if ((m.kind || "car") !== "car" || !gh || gh.fb == null) return;
|
|
36168
|
-
|
|
37966
|
+
list2.forEach(function(z) {
|
|
36169
37967
|
if (z.mapSet) return;
|
|
36170
37968
|
const B = z.box;
|
|
36171
37969
|
const s = z.side;
|
|
@@ -36228,8 +38026,8 @@ var GameVehiclesThree = (() => {
|
|
|
36228
38026
|
const top = m.top || belt + 0.5;
|
|
36229
38027
|
const hw = W / 2;
|
|
36230
38028
|
const WH = I.wheelInfo(c);
|
|
36231
|
-
function add2(id, name, type,
|
|
36232
|
-
const z = Object.assign({ id, name, type, box: I.normalizeBox(
|
|
38029
|
+
function add2(id, name, type, box2, o) {
|
|
38030
|
+
const z = Object.assign({ id, name, type, box: I.normalizeBox(box2) }, o || {});
|
|
36233
38031
|
Z.push(z);
|
|
36234
38032
|
return z;
|
|
36235
38033
|
}
|
|
@@ -37723,9 +39521,9 @@ var GameVehiclesThree = (() => {
|
|
|
37723
39521
|
const kind = kindOf2(zone);
|
|
37724
39522
|
if (!kind || !zone.box) continue;
|
|
37725
39523
|
const b = zone.box;
|
|
37726
|
-
const
|
|
37727
|
-
if (matrix)
|
|
37728
|
-
out.push({ material: kind.material, zone: zone.id, part: kind.part, side: zone.side === 0 ? "center" : zone.side < 0 ? "left" : "right", box });
|
|
39524
|
+
const box2 = new THREE.Box3(new THREE.Vector3(b.x0, b.y0, b.z0), new THREE.Vector3(b.x1, b.y1, b.z1));
|
|
39525
|
+
if (matrix) box2.applyMatrix4(matrix);
|
|
39526
|
+
out.push({ material: kind.material, zone: zone.id, part: kind.part, side: zone.side === 0 ? "center" : zone.side < 0 ? "left" : "right", box: box2 });
|
|
37729
39527
|
}
|
|
37730
39528
|
return out;
|
|
37731
39529
|
};
|
|
@@ -37734,7 +39532,7 @@ var GameVehiclesThree = (() => {
|
|
|
37734
39532
|
const opts = options || {};
|
|
37735
39533
|
if (!opts.THREE || !opts.THREE.Vector3) throw new Error("createVehicleKit: options.THREE (the three.js namespace) is required");
|
|
37736
39534
|
const lod = createLod(opts.lod);
|
|
37737
|
-
const THREE = wrapThreeForLod(opts.THREE, lod);
|
|
39535
|
+
const THREE = wrapThreeForLod(shapeGeometries(opts.THREE), lod);
|
|
37738
39536
|
const strings = resolveStrings(opts.locale);
|
|
37739
39537
|
const t = createTranslate(strings);
|
|
37740
39538
|
const doc = opts.document || (typeof document !== "undefined" ? document : void 0);
|
|
@@ -37957,6 +39755,20 @@ var GameVehiclesThree = (() => {
|
|
|
37957
39755
|
else kit.applyArmor(c);
|
|
37958
39756
|
}
|
|
37959
39757
|
if (zoneState == null && st === "damaged" && kit.config.damagedScenario) zoneState = kit.zoneScenario(c, kit.config.damagedScenario);
|
|
39758
|
+
else if (zoneState && zoneState.scenario != null) {
|
|
39759
|
+
c.scenario = zoneState.scenario;
|
|
39760
|
+
let fromScenario = { health: {}, flags: {} };
|
|
39761
|
+
try {
|
|
39762
|
+
fromScenario = kit.zoneScenario(c, zoneState.scenario);
|
|
39763
|
+
} catch (e) {
|
|
39764
|
+
;
|
|
39765
|
+
(c.zoneErrors = c.zoneErrors || []).push("scenario: " + (e && e.message));
|
|
39766
|
+
}
|
|
39767
|
+
zoneState = {
|
|
39768
|
+
health: Object.assign({}, fromScenario.health, zoneState.health),
|
|
39769
|
+
flags: Object.assign({}, fromScenario.flags, zoneState.flags)
|
|
39770
|
+
};
|
|
39771
|
+
}
|
|
37960
39772
|
if (zoneState) kit.applyZones(c, zoneState);
|
|
37961
39773
|
else {
|
|
37962
39774
|
c.zoneState = { health: {}, flags: {} };
|
|
@@ -38120,19 +39932,19 @@ var GameVehiclesThree = (() => {
|
|
|
38120
39932
|
for (const z of zones) {
|
|
38121
39933
|
let role = roleOfZone(z);
|
|
38122
39934
|
if (z === hubZone) role = "frame";
|
|
38123
|
-
const
|
|
38124
|
-
const
|
|
39935
|
+
const box2 = boxOf(z);
|
|
39936
|
+
const area3 = areaOf(box2.size);
|
|
38125
39937
|
const id = z.id;
|
|
38126
39938
|
const label = String(z.name ?? id);
|
|
38127
39939
|
const tags = [...z.tags ?? []];
|
|
38128
39940
|
if (role === "rim") {
|
|
38129
39941
|
const wheels = z.wheels ?? [];
|
|
38130
39942
|
const r = Math.max(0.2, ...wheels.map((w) => w.userData?.r ?? 0.3));
|
|
38131
|
-
const sz = Math.sign(
|
|
38132
|
-
const rimBox = { center: [
|
|
39943
|
+
const sz = Math.sign(box2.center[2]) || 1;
|
|
39944
|
+
const rimBox = { center: [box2.center[0], box2.center[1], box2.center[2] - sz * box2.size[2] * 0.25], size: [box2.size[0] * 0.7, box2.size[1] * 0.7, box2.size[2] * 0.5] };
|
|
38133
39945
|
add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box: rimBox, mass: 22 * r * Math.max(1, wheels.length), hp: 12e3 * armour, zoneId: id, visual: kind !== "plane" && !/landing/.test(id), tags: ["wheel", ...tags] });
|
|
38134
39946
|
const tyreId = id.replace(/^wheels?/, "tyre").replace(/^(?!tyre)/, "tyre_");
|
|
38135
|
-
const tyreBox = { center:
|
|
39947
|
+
const tyreBox = { center: box2.center, size: [box2.size[0] * 0.98, box2.size[1] * 0.98, box2.size[2]] };
|
|
38136
39948
|
add2({
|
|
38137
39949
|
id: tyreId,
|
|
38138
39950
|
role: "tyre",
|
|
@@ -38152,29 +39964,29 @@ var GameVehiclesThree = (() => {
|
|
|
38152
39964
|
if (role === "glass") {
|
|
38153
39965
|
const glass = (z.glass ?? [])[0];
|
|
38154
39966
|
const laminated = glass?.userData?.glass?.type === "laminated" || m.bullet;
|
|
38155
|
-
add2({ id, role, name: label, material: "glass", box, mass: 10 *
|
|
39967
|
+
add2({ id, role, name: label, material: "glass", box: box2, mass: 10 * area3, hp: laminated ? 4e3 : 450, zoneId: id, visual: false, tags: ["glass", ...tags] });
|
|
38156
39968
|
continue;
|
|
38157
39969
|
}
|
|
38158
39970
|
if (role === "light") {
|
|
38159
|
-
add2({ id, role, name: label, material: "glass", box, mass: 1.2 + 4 *
|
|
39971
|
+
add2({ id, role, name: label, material: "glass", box: box2, mass: 1.2 + 4 * area3, hp: 320, zoneId: id, visual: true, tags: ["light", ...tags] });
|
|
38160
39972
|
continue;
|
|
38161
39973
|
}
|
|
38162
39974
|
if (role === "bumper") {
|
|
38163
|
-
add2({ id, role, name: label, material: "plastic", box, mass: 6 + 5 *
|
|
39975
|
+
add2({ id, role, name: label, material: "plastic", box: box2, mass: 6 + 5 * area3, hp: 9e3, ignitionC: 400, zoneId: id, visual: true, tags: ["bumper", ...tags] });
|
|
38164
39976
|
continue;
|
|
38165
39977
|
}
|
|
38166
39978
|
if (role === "engine") {
|
|
38167
39979
|
const kg2 = { bike: 55, quad: 90, car: 150, tractor: 450, truck: 600, bus: 450, tank: 900, boat: 90, plane: 160, heli: 150 }[kind];
|
|
38168
|
-
add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box, mass: kg2, hp: 6e4 * armour, ignitionC: 260, zoneId: id, visual: false, tags: ["engine", ...tags] });
|
|
39980
|
+
add2({ id, role, name: label, material: kind === "plane" || kind === "heli" ? "aluminium" : "steel", box: box2, mass: kg2, hp: 6e4 * armour, ignitionC: 260, zoneId: id, visual: false, tags: ["engine", ...tags] });
|
|
38169
39981
|
continue;
|
|
38170
39982
|
}
|
|
38171
39983
|
if (role === "radiator") {
|
|
38172
|
-
add2({ id, role, name: label, material: "aluminium", box, mass: 8, hp: 3e3, zoneId: id, visual: false, contains: { fluid: "coolant", liters: kind === "truck" || kind === "bus" ? 18 : 7, pressurized: true }, tags: ["radiator", ...tags] });
|
|
39984
|
+
add2({ id, role, name: label, material: "aluminium", box: box2, mass: 8, hp: 3e3, zoneId: id, visual: false, contains: { fluid: "coolant", liters: kind === "truck" || kind === "bus" ? 18 : 7, pressurized: true }, tags: ["radiator", ...tags] });
|
|
38173
39985
|
continue;
|
|
38174
39986
|
}
|
|
38175
39987
|
if (role === "fuel_tank") {
|
|
38176
39988
|
if (fuelless) {
|
|
38177
|
-
add2({ id, role: "other", name: label, material: "steel", box, mass: 20, hp: 25e3, zoneId: id, visual: false, tags });
|
|
39989
|
+
add2({ id, role: "other", name: label, material: "steel", box: box2, mass: 20, hp: 25e3, zoneId: id, visual: false, tags });
|
|
38178
39990
|
continue;
|
|
38179
39991
|
}
|
|
38180
39992
|
const liters = { bike: 14, quad: 16, car: 55, tractor: 150, truck: 300, bus: 200, tank: 600, boat: 90, plane: 120, heli: 300 }[kind];
|
|
@@ -38184,7 +39996,7 @@ var GameVehiclesThree = (() => {
|
|
|
38184
39996
|
role,
|
|
38185
39997
|
name: label,
|
|
38186
39998
|
material: "steel",
|
|
38187
|
-
box,
|
|
39999
|
+
box: box2,
|
|
38188
40000
|
mass: 14 + liters * 0.8,
|
|
38189
40001
|
hp: 25e3 * armour,
|
|
38190
40002
|
zoneId: id,
|
|
@@ -38197,21 +40009,21 @@ var GameVehiclesThree = (() => {
|
|
|
38197
40009
|
continue;
|
|
38198
40010
|
}
|
|
38199
40011
|
if (role === "battery") {
|
|
38200
|
-
add2({ id, role, name: label, material: "plastic", box, mass: 14, hp: 1500, zoneId: id, visual: true, ignitionC: 200, tags: ["battery", ...tags] });
|
|
40012
|
+
add2({ id, role, name: label, material: "plastic", box: box2, mass: 14, hp: 1500, zoneId: id, visual: true, ignitionC: 200, tags: ["battery", ...tags] });
|
|
38201
40013
|
continue;
|
|
38202
40014
|
}
|
|
38203
40015
|
if (role === "frame") {
|
|
38204
|
-
add2({ id, role, name: label, material: "steel", box: floorPan(
|
|
40016
|
+
add2({ id, role, name: label, material: "steel", box: floorPan(box2), mass: mass * 0.25, hp: 15e4 * armour, zoneId: id, visual: false, tags: ["frame", ...tags] });
|
|
38205
40017
|
continue;
|
|
38206
40018
|
}
|
|
38207
40019
|
const roofLike = role === "roof";
|
|
38208
|
-
const kg = (skin === "steel" ? STEEL_KG_M2 : ALU_KG_M2) *
|
|
40020
|
+
const kg = (skin === "steel" ? STEEL_KG_M2 : ALU_KG_M2) * area3 * (role === "door" ? 1.6 : 1);
|
|
38209
40021
|
add2({
|
|
38210
40022
|
id,
|
|
38211
40023
|
role,
|
|
38212
40024
|
name: label,
|
|
38213
40025
|
material: skin,
|
|
38214
|
-
box,
|
|
40026
|
+
box: box2,
|
|
38215
40027
|
mass: Math.max(2, kg),
|
|
38216
40028
|
hp: (roofLike ? 3e4 : 2e4) * armour,
|
|
38217
40029
|
zoneId: id,
|
|
@@ -38433,7 +40245,7 @@ var GameVehiclesThree = (() => {
|
|
|
38433
40245
|
const my = kind === "bike" || kind === "quad" ? (m.top ?? belt + 0.25) - 0.1 : belt + 0.12;
|
|
38434
40246
|
for (const s of [-1, 1]) {
|
|
38435
40247
|
const door = zones.find((z) => z.type === "door" && z.side === s && (z.mirrors ?? []).length);
|
|
38436
|
-
let
|
|
40248
|
+
let box2 = { center: [mx, my, s * half], size: [0.14, 0.12, 0.2] };
|
|
38437
40249
|
if (door) {
|
|
38438
40250
|
const bb = door.mirrors.reduce(
|
|
38439
40251
|
(acc, o) => {
|
|
@@ -38446,14 +40258,14 @@ var GameVehiclesThree = (() => {
|
|
|
38446
40258
|
},
|
|
38447
40259
|
null
|
|
38448
40260
|
);
|
|
38449
|
-
if (bb)
|
|
40261
|
+
if (bb) box2 = { center: [(bb[0] + bb[1]) / 2, (bb[2] + bb[3]) / 2, (bb[4] + bb[5]) / 2], size: [Math.max(0.06, bb[1] - bb[0]), Math.max(0.06, bb[3] - bb[2]), Math.max(0.06, bb[5] - bb[4])] };
|
|
38450
40262
|
}
|
|
38451
40263
|
add2({
|
|
38452
40264
|
id: `mirror_${side(s)}`,
|
|
38453
40265
|
role: "mirror",
|
|
38454
40266
|
name: t("mechanics.mirror", { side: t(`sides.${side(s)}`), sideM: t(`sides.${side(s)}M`) }),
|
|
38455
40267
|
material: "plastic",
|
|
38456
|
-
box,
|
|
40268
|
+
box: box2,
|
|
38457
40269
|
mass: 1.1,
|
|
38458
40270
|
hp: 1500,
|
|
38459
40271
|
ignitionC: 400,
|
|
@@ -38639,13 +40451,13 @@ var GameVehiclesThree = (() => {
|
|
|
38639
40451
|
(parent ?? this.c.vehicle).add(m);
|
|
38640
40452
|
return m;
|
|
38641
40453
|
}
|
|
38642
|
-
surface(axis,
|
|
40454
|
+
surface(axis, sign2, B, samples) {
|
|
38643
40455
|
const V3 = this.THREE.Vector3;
|
|
38644
40456
|
const hits = [];
|
|
38645
40457
|
const far = 3;
|
|
38646
40458
|
for (const [u, v] of samples) {
|
|
38647
|
-
const o = axis === "z" ? new V3(u, v,
|
|
38648
|
-
const d = axis === "z" ? new V3(0, 0, -
|
|
40459
|
+
const o = axis === "z" ? new V3(u, v, sign2 * (Math.max(Math.abs(B.z0), Math.abs(B.z1)) + 1)) : new V3(sign2 * (Math.max(Math.abs(B.x0), Math.abs(B.x1)) + 1), u, v);
|
|
40460
|
+
const d = axis === "z" ? new V3(0, 0, -sign2) : new V3(-sign2, 0, 0);
|
|
38649
40461
|
const h = this.I.probe(this.c, o, d, far);
|
|
38650
40462
|
if (h) hits.push(axis === "z" ? h.p.z : h.p.x);
|
|
38651
40463
|
}
|
|
@@ -38795,12 +40607,12 @@ var GameVehiclesThree = (() => {
|
|
|
38795
40607
|
const z = this.zone(p);
|
|
38796
40608
|
if (!z) return false;
|
|
38797
40609
|
const V3 = this.THREE.Vector3;
|
|
38798
|
-
const
|
|
38799
|
-
if (!
|
|
40610
|
+
const list2 = z.glass.filter((g) => g.parent && g.visible);
|
|
40611
|
+
if (!list2.length) return false;
|
|
38800
40612
|
const pt = new V3(...point);
|
|
38801
|
-
let best =
|
|
40613
|
+
let best = list2[0];
|
|
38802
40614
|
let bd = Infinity;
|
|
38803
|
-
for (const g of
|
|
40615
|
+
for (const g of list2) {
|
|
38804
40616
|
g.geometry.computeBoundingBox();
|
|
38805
40617
|
const bb = g.geometry.boundingBox.clone().applyMatrix4(g.matrix);
|
|
38806
40618
|
const d = bb.distanceToPoint(pt);
|
|
@@ -39097,6 +40909,9 @@ var GameVehiclesThree = (() => {
|
|
|
39097
40909
|
const headless = !!options.headless;
|
|
39098
40910
|
const seedBase = strHash(`${c.key}|${id}|${options.seed ?? 0}`);
|
|
39099
40911
|
let rand = rng(seedBase);
|
|
40912
|
+
const ignitionRules = resolveIgnitionRules(options.ignition);
|
|
40913
|
+
const fuelFraction = clamp(options.fuel ?? 1, 0, 1);
|
|
40914
|
+
let igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
|
|
39100
40915
|
let clock = 0;
|
|
39101
40916
|
let model;
|
|
39102
40917
|
let vis = null;
|
|
@@ -39164,7 +40979,7 @@ var GameVehiclesThree = (() => {
|
|
|
39164
40979
|
dents: [],
|
|
39165
40980
|
holes: [],
|
|
39166
40981
|
cracks: [],
|
|
39167
|
-
liters: d.contains
|
|
40982
|
+
liters: d.contains ? d.role === "fuel_tank" ? d.contains.liters * fuelFraction : d.contains.liters : void 0,
|
|
39168
40983
|
lost: false,
|
|
39169
40984
|
status: "intact",
|
|
39170
40985
|
flat: false,
|
|
@@ -39182,6 +40997,7 @@ var GameVehiclesThree = (() => {
|
|
|
39182
40997
|
wasLit = true;
|
|
39183
40998
|
deadEngine = false;
|
|
39184
40999
|
rand = rng(seedBase);
|
|
41000
|
+
igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
|
|
39185
41001
|
steerSign = rand() < 0.5 ? -1 : 1;
|
|
39186
41002
|
vis = headless ? null : new VehicleVisuals(kit, c, model);
|
|
39187
41003
|
recomputeGroups();
|
|
@@ -39203,8 +41019,8 @@ var GameVehiclesThree = (() => {
|
|
|
39203
41019
|
comps.get(r).push(p);
|
|
39204
41020
|
}
|
|
39205
41021
|
const hubRoot = parent.has(model.hub) ? find(model.hub) : "";
|
|
39206
|
-
const
|
|
39207
|
-
groupsCache =
|
|
41022
|
+
const list2 = [...comps.entries()].sort((a, b) => a[0] === hubRoot ? -1 : b[0] === hubRoot ? 1 : 0);
|
|
41023
|
+
groupsCache = list2.map(([, v]) => v);
|
|
39208
41024
|
groupOf = /* @__PURE__ */ new Map();
|
|
39209
41025
|
groupsCache.forEach((g, i) => g.forEach((p) => groupOf.set(p, i)));
|
|
39210
41026
|
return groupsCache;
|
|
@@ -39476,8 +41292,19 @@ var GameVehiclesThree = (() => {
|
|
|
39476
41292
|
if (!p.burning && p.temp > AMBIENT) p.temp = Math.max(AMBIENT, p.temp - dt * 6);
|
|
39477
41293
|
}
|
|
39478
41294
|
for (const f of flames) heat(centreOf(f.def), 0.8, 500, dt * 0.5, out, 0);
|
|
41295
|
+
fireNearLeak(flames, dt, out);
|
|
39479
41296
|
thermal(out);
|
|
39480
41297
|
};
|
|
41298
|
+
const fireNearLeak = (flames, dt, out) => {
|
|
41299
|
+
const tank = tankPart();
|
|
41300
|
+
const leak = tank ? leaks.get(tank.def.id) : void 0;
|
|
41301
|
+
if (!tank || !leak || tank.lost || tank.burning || exploded || leak.fluid !== "fuel" && leak.fluid !== "diesel") return;
|
|
41302
|
+
if (leak.pud?.fire) return light(tank, out);
|
|
41303
|
+
const { radius, chancePerSecond } = ignitionRules.fireNear;
|
|
41304
|
+
if (chancePerSecond <= 0) return;
|
|
41305
|
+
const near = flames.some((f) => f !== tank && distToBox(tank.def, centreOf(f.def)) - Math.max(...f.def.box.size) / 2 <= radius);
|
|
41306
|
+
if (near && igniteRand() < 1 - Math.exp(-chancePerSecond * dt)) light(tank, out);
|
|
41307
|
+
};
|
|
39481
41308
|
const normalOf = (d, v) => faceNormal(d, v);
|
|
39482
41309
|
const ballistic = (h, out) => {
|
|
39483
41310
|
sync();
|
|
@@ -39545,10 +41372,21 @@ var GameVehiclesThree = (() => {
|
|
|
39545
41372
|
let amount = through ? E * 0.6 : E * 0.25;
|
|
39546
41373
|
if (through && (d.role === "battery" || d.role === "alternator")) amount = Math.max(amount, p.hp * 0.65);
|
|
39547
41374
|
damage(p, amount, "ballistic", h.source, out, worldPoint);
|
|
39548
|
-
if (d.role === "fuel_tank"
|
|
41375
|
+
if (through && d.role === "fuel_tank") rollIgnition(p, h, metal, out);
|
|
39549
41376
|
}
|
|
39550
41377
|
}
|
|
39551
41378
|
};
|
|
41379
|
+
const light = (tank, out) => {
|
|
41380
|
+
tank.temp = Math.max(tank.temp, (tank.def.ignitionC ?? 260) + 1);
|
|
41381
|
+
if ((tank.liters ?? 0) > 0.5) ignite(tank, out);
|
|
41382
|
+
};
|
|
41383
|
+
const rollIgnition = (tank, h, metal, out) => {
|
|
41384
|
+
const d = tank.def;
|
|
41385
|
+
if (!d.contains || tank.burning || (tank.liters ?? 0) <= 0.05) return;
|
|
41386
|
+
const fill2 = d.contains.liters > 0 ? (tank.liters ?? 0) / d.contains.liters : 0;
|
|
41387
|
+
const chance = ignitionChance(h, { sparkTarget: sparkTargetFactor(d.material, metal, ignitionRules), fill: fill2, fluid: d.contains.fluid }, ignitionRules);
|
|
41388
|
+
if (chance > 0 && igniteRand() < chance) light(tank, out);
|
|
41389
|
+
};
|
|
39552
41390
|
const blunt = (h, out) => {
|
|
39553
41391
|
sync();
|
|
39554
41392
|
const M = toFrameMatrix();
|
|
@@ -39612,7 +41450,7 @@ var GameVehiclesThree = (() => {
|
|
|
39612
41450
|
const verdict = kit.blastDamage(c, E / (1 + dist * dist * 4) / 50);
|
|
39613
41451
|
if (verdict === "explosion") explode(tank, h.source, out);
|
|
39614
41452
|
else if (verdict === "fire") {
|
|
39615
|
-
|
|
41453
|
+
light(tank, out);
|
|
39616
41454
|
startLeak(tank, centreOf(tank.def).setY(tank.def.box.center[1] - tank.def.box.size[1] / 2 + 0.05), 12, out, dir);
|
|
39617
41455
|
}
|
|
39618
41456
|
}
|
|
@@ -39626,9 +41464,9 @@ var GameVehiclesThree = (() => {
|
|
|
39626
41464
|
thermal(out);
|
|
39627
41465
|
};
|
|
39628
41466
|
const sound = (role) => {
|
|
39629
|
-
const
|
|
39630
|
-
if (!
|
|
39631
|
-
return
|
|
41467
|
+
const list2 = [...ps.values()].filter((p) => p.def.role === role);
|
|
41468
|
+
if (!list2.length) return true;
|
|
41469
|
+
return list2.every((p) => !p.lost && attached(p.def.id) && p.hp >= p.def.hp * 0.5);
|
|
39632
41470
|
};
|
|
39633
41471
|
const tankPart = () => [...ps.values()].find((p) => p.def.role === "fuel_tank" && p.def.contains);
|
|
39634
41472
|
const computeStatus = () => {
|
|
@@ -39820,8 +41658,8 @@ var GameVehiclesThree = (() => {
|
|
|
39820
41658
|
queue = [];
|
|
39821
41659
|
const hood = c.hood;
|
|
39822
41660
|
if (hood) {
|
|
39823
|
-
const
|
|
39824
|
-
const cur = hood.piv.rotation.z /
|
|
41661
|
+
const sign2 = hood.sign || 1;
|
|
41662
|
+
const cur = hood.piv.rotation.z / sign2;
|
|
39825
41663
|
if (Math.abs(cur - hood.ang) > 1e-4) {
|
|
39826
41664
|
hood.ang = cur;
|
|
39827
41665
|
hood.target = cur;
|
|
@@ -39874,7 +41712,7 @@ var GameVehiclesThree = (() => {
|
|
|
39874
41712
|
const reset = () => {
|
|
39875
41713
|
const old = c;
|
|
39876
41714
|
const parent = old.root.parent;
|
|
39877
|
-
const next = kit.build(old.key, old.state);
|
|
41715
|
+
const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
|
|
39878
41716
|
if (parent) {
|
|
39879
41717
|
next.root.position.copy(old.root.position);
|
|
39880
41718
|
next.root.quaternion.copy(old.root.quaternion);
|
|
@@ -39929,7 +41767,8 @@ var GameVehiclesThree = (() => {
|
|
|
39929
41767
|
}
|
|
39930
41768
|
function buildVehicleItem(kit, key, options = {}) {
|
|
39931
41769
|
const THREE = kit.THREE;
|
|
39932
|
-
const
|
|
41770
|
+
const zoneState = options.scenario != null ? { scenario: options.scenario } : void 0;
|
|
41771
|
+
const vehicle = options.lod ? kit.build(key, options.state ?? "intact", zoneState, { lod: true }) : kit.build(key, options.state ?? "intact", zoneState);
|
|
39933
41772
|
const m = vehicle.meta;
|
|
39934
41773
|
const root = new THREE.Group();
|
|
39935
41774
|
root.name = key;
|
|
@@ -39942,34 +41781,6 @@ var GameVehiclesThree = (() => {
|
|
|
39942
41781
|
return { root, vehicle };
|
|
39943
41782
|
}
|
|
39944
41783
|
|
|
39945
|
-
// ../game-contracts/dist/index.js
|
|
39946
|
-
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
39947
|
-
var isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
39948
|
-
var deepMerge = (base, patch) => {
|
|
39949
|
-
if (!patch) return base;
|
|
39950
|
-
const result = { ...base };
|
|
39951
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
39952
|
-
if (value === void 0 || UNSAFE_KEYS.has(key)) continue;
|
|
39953
|
-
const current = result[key];
|
|
39954
|
-
result[key] = isPlainObject(current) && isPlainObject(value) ? deepMerge(current, value) : value;
|
|
39955
|
-
}
|
|
39956
|
-
return result;
|
|
39957
|
-
};
|
|
39958
|
-
var mergeById = (shipped, extra) => {
|
|
39959
|
-
const entries = /* @__PURE__ */ new Map();
|
|
39960
|
-
for (const entry of [...shipped, ...extra ?? []]) entries.set(entry.id, entry);
|
|
39961
|
-
return entries;
|
|
39962
|
-
};
|
|
39963
|
-
var applyPatches = (entries, patches) => {
|
|
39964
|
-
for (const [id, patch] of Object.entries(patches ?? {})) {
|
|
39965
|
-
const entry = entries.get(id);
|
|
39966
|
-
if (entry) entries.set(id, deepMerge(entry, patch));
|
|
39967
|
-
}
|
|
39968
|
-
};
|
|
39969
|
-
var removeIds = (entries, ids) => {
|
|
39970
|
-
for (const id of ids ?? []) entries.delete(id);
|
|
39971
|
-
};
|
|
39972
|
-
|
|
39973
41784
|
// ../game-vehicles-driving/dist/index.js
|
|
39974
41785
|
var defaultArcadeSpec = {
|
|
39975
41786
|
length: 4.3,
|
|
@@ -40105,7 +41916,7 @@ var GameVehiclesThree = (() => {
|
|
|
40105
41916
|
{ id: "blood", grip: 0.5 }
|
|
40106
41917
|
];
|
|
40107
41918
|
function createSurfaces(options = {}) {
|
|
40108
|
-
const entries = mergeById(defaultSurfaces, options.packs?.flatMap((
|
|
41919
|
+
const entries = mergeById(defaultSurfaces, options.packs?.flatMap((pack2) => pack2.surfaces ?? []));
|
|
40109
41920
|
applyPatches(entries, options.patch);
|
|
40110
41921
|
removeIds(entries, options.remove);
|
|
40111
41922
|
const fallback = entries.get("dry_asphalt") ?? { id: "dry_asphalt", grip: 1 };
|
|
@@ -40398,6 +42209,7 @@ var GameVehiclesThree = (() => {
|
|
|
40398
42209
|
"vehicles_kill_battery",
|
|
40399
42210
|
"vehicles_rollover",
|
|
40400
42211
|
"vehicles_melt",
|
|
42212
|
+
"vehicles_burnt_wreck",
|
|
40401
42213
|
"vehicles_drive_arcade",
|
|
40402
42214
|
"vehicles_drive_semi"
|
|
40403
42215
|
];
|
|
@@ -40429,7 +42241,7 @@ var GameVehiclesThree = (() => {
|
|
|
40429
42241
|
en: {
|
|
40430
42242
|
group: "Vehicles",
|
|
40431
42243
|
name: "Vehicles area",
|
|
40432
|
-
items: { hatch: "Compact hatch", sedan: "Midsize sedan", pickup: "Midsize pickup", sport_bike: "Sport bike", box_truck: "Box truck", city_bus: "City bus", battle_tank: "Battle tank", attack_helicopter: "Attack helicopter" },
|
|
42244
|
+
items: { hatch: "Compact hatch", sedan: "Midsize sedan", pickup: "Midsize pickup", sport_bike: "Sport bike", box_truck: "Box truck", city_bus: "City bus", battle_tank: "Battle tank", attack_helicopter: "Attack helicopter", sedan_burnt: "Burnt sedan", hatch_burnt: "Burnt hatch" },
|
|
40433
42245
|
controls: { quality: "Quality", paint_by_seed: "Paint by seed", color_seed: "Colour seed", palette: "Palette", driving: "Driving", surface: "Surface" },
|
|
40434
42246
|
hints: {
|
|
40435
42247
|
quality: "High: the kit at full detail. Light: fewer segments and no interior (the light mode of the fleet); applies to the vehicles placed from now on",
|
|
@@ -40462,7 +42274,8 @@ var GameVehiclesThree = (() => {
|
|
|
40462
42274
|
vehicles_rollover: "Vehicles: roll over",
|
|
40463
42275
|
vehicles_melt: "Vehicles: melt (long fire burns the tyres)",
|
|
40464
42276
|
vehicles_drive_arcade: "Vehicles: arcade driving down a lane that ends in a wall",
|
|
40465
|
-
vehicles_drive_semi: "Vehicles: semi-simulation braking on dry, wet and mud"
|
|
42277
|
+
vehicles_drive_semi: "Vehicles: semi-simulation braking on dry, wet and mud",
|
|
42278
|
+
vehicles_burnt_wreck: "Vehicles: the burnt sedan comes out of the kit burnt, with the glass gone"
|
|
40466
42279
|
},
|
|
40467
42280
|
checks: {
|
|
40468
42281
|
windshield_holes: "Windshield: {0} hole(s), went through {1:b} (expected: 1, true)",
|
|
@@ -40487,13 +42300,15 @@ var GameVehiclesThree = (() => {
|
|
|
40487
42300
|
arcade_bounce: "Arcade: the car bounces back at {0} m/s (expected: below 0)",
|
|
40488
42301
|
arcade_noise: "Arcade: {0} engine noise(s) and {1} crash noise(s) (expected: 1 or more each)",
|
|
40489
42302
|
semi_order: "Semi: braking from 80 km/h takes dry {0} m, wet {1} m, mud {2} m (expected: dry shorter than wet shorter than mud)",
|
|
40490
|
-
semi_mud: "Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)"
|
|
42303
|
+
semi_mud: "Semi: a 2WD car on mud {0:on} (expected: bogged on, a bog event)",
|
|
42304
|
+
wreck_burnt: "Burnt sedan: burnt flag {0:b} (expected: yes)",
|
|
42305
|
+
wreck_glass: "Burnt sedan: {0} glass zone(s), {1} still above 0 (expected: 1 or more, none above 0)"
|
|
40491
42306
|
}
|
|
40492
42307
|
},
|
|
40493
42308
|
"pt-BR": {
|
|
40494
42309
|
group: "Ve\xEDculos",
|
|
40495
42310
|
name: "\xC1rea de ve\xEDculos",
|
|
40496
|
-
items: { hatch: "Hatch compacto", sedan: "Sed\xE3 m\xE9dio", pickup: "Picape m\xE9dia", sport_bike: "Moto esportiva", box_truck: "Caminh\xE3o ba\xFA", city_bus: "\xD4nibus urbano", battle_tank: "Tanque de guerra", attack_helicopter: "Helic\xF3ptero de ataque" },
|
|
42311
|
+
items: { hatch: "Hatch compacto", sedan: "Sed\xE3 m\xE9dio", pickup: "Picape m\xE9dia", sport_bike: "Moto esportiva", box_truck: "Caminh\xE3o ba\xFA", city_bus: "\xD4nibus urbano", battle_tank: "Tanque de guerra", attack_helicopter: "Helic\xF3ptero de ataque", sedan_burnt: "Sed\xE3 queimado", hatch_burnt: "Hatch queimado" },
|
|
40497
42312
|
controls: { quality: "Qualidade", paint_by_seed: "Pintar pela semente", color_seed: "Semente da cor", palette: "Paleta", driving: "Dire\xE7\xE3o", surface: "Piso" },
|
|
40498
42313
|
hints: {
|
|
40499
42314
|
quality: "Alta: o kit com todo o detalhe. Leve: menos segmentos e sem interior (o modo leve da frota); vale para os ve\xEDculos postos daqui em diante",
|
|
@@ -40526,7 +42341,8 @@ var GameVehiclesThree = (() => {
|
|
|
40526
42341
|
vehicles_rollover: "Ve\xEDculos: capotar",
|
|
40527
42342
|
vehicles_melt: "Ve\xEDculos: derreter (fogo longo queima os pneus)",
|
|
40528
42343
|
vehicles_drive_arcade: "Ve\xEDculos: dire\xE7\xE3o arcade numa pista que acaba num muro",
|
|
40529
|
-
vehicles_drive_semi: "Ve\xEDculos: frenagem da semissimula\xE7\xE3o no seco, no molhado e na lama"
|
|
42344
|
+
vehicles_drive_semi: "Ve\xEDculos: frenagem da semissimula\xE7\xE3o no seco, no molhado e na lama",
|
|
42345
|
+
vehicles_burnt_wreck: "Ve\xEDculos: o sed\xE3 queimado sai do kit queimado, sem os vidros"
|
|
40530
42346
|
},
|
|
40531
42347
|
checks: {
|
|
40532
42348
|
windshield_holes: "Para-brisa: {0} furo(s), atravessou {1:b} (esperado: 1, sim)",
|
|
@@ -40551,7 +42367,9 @@ var GameVehiclesThree = (() => {
|
|
|
40551
42367
|
arcade_bounce: "Arcade: o carro volta a {0} m/s (esperado: abaixo de 0)",
|
|
40552
42368
|
arcade_noise: "Arcade: {0} ru\xEDdo(s) de motor e {1} de batida (esperado: 1 ou mais de cada)",
|
|
40553
42369
|
semi_order: "Semi: frear de 80 km/h leva no seco {0} m, no molhado {1} m, na lama {2} m (esperado: seco menor que molhado menor que lama)",
|
|
40554
|
-
semi_mud: "Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)"
|
|
42370
|
+
semi_mud: "Semi: um carro 2WD na lama {0:on} (esperado: atolado, com evento de atolamento)",
|
|
42371
|
+
wreck_burnt: "Sed\xE3 queimado: marca de queimado {0:b} (esperado: sim)",
|
|
42372
|
+
wreck_glass: "Sed\xE3 queimado: {0} zona(s) de vidro, {1} ainda acima de 0 (esperado: 1 ou mais, nenhuma acima de 0)"
|
|
40555
42373
|
}
|
|
40556
42374
|
}
|
|
40557
42375
|
};
|
|
@@ -40710,6 +42528,14 @@ var GameVehiclesThree = (() => {
|
|
|
40710
42528
|
const t = part(room, v, "tyre_front_left");
|
|
40711
42529
|
expect(events(room, "melt", v) >= 1 && (t.status === "melted" || t.melt > 0.5), say("tyre_melt", t.status, Math.round(t.melt * 100), events(room, "melt", v)));
|
|
40712
42530
|
}),
|
|
42531
|
+
// new in the kit: the burnt wreck comes ready from the kit (the fleet's `burnt` scenario built into the vehicle), no damage applied by the area
|
|
42532
|
+
scenario("vehicles_burnt_wreck", ({ room, expect }) => {
|
|
42533
|
+
const c = room.spawn("sedan_burnt", [0, 0, -7], 0).root.userData.vehicle;
|
|
42534
|
+
expect(c.zoneState.flags.burnt === true, say("wreck_burnt", c.zoneState.flags.burnt === true));
|
|
42535
|
+
const glass = c.zones.filter((z) => z.type === "glass");
|
|
42536
|
+
const up = glass.filter((z) => (c.zoneState.health[z.id] ?? 100) > 0);
|
|
42537
|
+
expect(glass.length >= 1 && up.length === 0, say("wreck_glass", glass.length, up.length));
|
|
42538
|
+
}),
|
|
40713
42539
|
// new in the kit: the drivers, headless (no vehicle is spawned)
|
|
40714
42540
|
scenario("vehicles_drive_arcade", ({ expect }) => {
|
|
40715
42541
|
const driver = createArcadeDriver();
|
|
@@ -40986,9 +42812,14 @@ var GameVehiclesThree = (() => {
|
|
|
40986
42812
|
glass: "glass_burst",
|
|
40987
42813
|
sparks: "impact_metal",
|
|
40988
42814
|
leak: "vehicle_leak",
|
|
42815
|
+
leakIgnited: "vehicle_leak_ignited",
|
|
40989
42816
|
exhaust: "vehicle_exhaust"
|
|
40990
42817
|
};
|
|
40991
42818
|
var defaultSoundIds = { engine: "engine_saw", horn: "horn", crash: "sfx_impact" };
|
|
42819
|
+
var DEFAULT_TEST_WRECKS = [
|
|
42820
|
+
{ key: "sedan_burnt", vehicle: "midsize_sedan", scenario: "burnt" },
|
|
42821
|
+
{ key: "hatch_burnt", vehicle: "compact_hatch", scenario: "burnt" }
|
|
42822
|
+
];
|
|
40992
42823
|
|
|
40993
42824
|
// src/test-area/module.ts
|
|
40994
42825
|
var VEHICLES_AREA_ID = "vehicles_area";
|
|
@@ -41002,6 +42833,8 @@ var GameVehiclesThree = (() => {
|
|
|
41002
42833
|
const locale = options.locale ?? "pt-BR";
|
|
41003
42834
|
const text = TEXT[locale] ?? TEXT["pt-BR"];
|
|
41004
42835
|
const keys = options.vehicles ?? DEFAULT_TEST_VEHICLES;
|
|
42836
|
+
const wrecks = options.wrecks ?? DEFAULT_TEST_WRECKS;
|
|
42837
|
+
const entries = [...keys.map((key) => ({ key, id: itemId(key) })), ...wrecks.map((w) => ({ key: w.vehicle, id: w.key, scenario: w.scenario }))];
|
|
41005
42838
|
const effectIds = { ...defaultEffectIds, ...options.effects };
|
|
41006
42839
|
const soundIds = { ...defaultSoundIds, ...options.sounds };
|
|
41007
42840
|
const settings = { quality: "high", paint: false, seed: 1, palette: "auto", driving: "arcade", surface: "dry_asphalt" };
|
|
@@ -41036,29 +42869,31 @@ var GameVehiclesThree = (() => {
|
|
|
41036
42869
|
const paletteFor = (key) => settings.palette === "civil" ? paintPalettes.civil : settings.palette === "military" ? paintPalettes.military : paletteOf(key);
|
|
41037
42870
|
const paintOf = (entry) => {
|
|
41038
42871
|
if (!settings.paint) return;
|
|
41039
|
-
const
|
|
42872
|
+
const color2 = colorFromSeed(settings.seed + entry.index, paletteFor(entry.key));
|
|
41040
42873
|
if (!entry.paint) {
|
|
41041
42874
|
const vehicle = entry.item.vehicle;
|
|
41042
42875
|
const primary = primaryPaint(entry.item.vehicle);
|
|
41043
42876
|
if (!primary) return;
|
|
41044
42877
|
entry.paint = primary.clone();
|
|
41045
|
-
vehicle.vehicle.traverse((
|
|
41046
|
-
if (!
|
|
41047
|
-
if (Array.isArray(
|
|
41048
|
-
else if (
|
|
42878
|
+
vehicle.vehicle.traverse((mesh2) => {
|
|
42879
|
+
if (!mesh2.isMesh) return;
|
|
42880
|
+
if (Array.isArray(mesh2.material)) mesh2.material = mesh2.material.map((m) => m === primary ? entry.paint : m);
|
|
42881
|
+
else if (mesh2.material === primary) mesh2.material = entry.paint;
|
|
41049
42882
|
});
|
|
41050
42883
|
}
|
|
41051
|
-
entry.paint.color.set(
|
|
42884
|
+
entry.paint.color.set(color2);
|
|
41052
42885
|
};
|
|
41053
|
-
const item = (key) => ({
|
|
41054
|
-
id:
|
|
41055
|
-
name: text.items[
|
|
42886
|
+
const item = ({ key, id: itemKey, scenario }) => ({
|
|
42887
|
+
id: itemKey,
|
|
42888
|
+
name: text.items[itemKey] ?? key,
|
|
41056
42889
|
movable: false,
|
|
42890
|
+
// the first build of a vehicle takes most of a second
|
|
42891
|
+
slow: true,
|
|
41057
42892
|
build: (THREE) => {
|
|
41058
42893
|
const kit = kitFor(THREE);
|
|
41059
|
-
const built = buildVehicleItem(kit, key, { lod: settings.quality === "lite" });
|
|
42894
|
+
const built = buildVehicleItem(kit, key, { lod: settings.quality === "lite", ...scenario ? { scenario } : {} });
|
|
41060
42895
|
built.root.userData.kit = kit;
|
|
41061
|
-
const entry = { root: built.root, key, item: built, index: counter++, helpers: [] };
|
|
42896
|
+
const entry = { root: built.root, key, ...scenario ? { scenario } : {}, item: built, index: counter++, helpers: [] };
|
|
41062
42897
|
placed.set(built.root.uuid, entry);
|
|
41063
42898
|
measure(entry);
|
|
41064
42899
|
paintOf(entry);
|
|
@@ -41067,7 +42902,7 @@ var GameVehiclesThree = (() => {
|
|
|
41067
42902
|
impl: (root, id) => {
|
|
41068
42903
|
const r = root;
|
|
41069
42904
|
const kit = r.userData.kit;
|
|
41070
|
-
const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[
|
|
42905
|
+
const d = createVehicleDestructible(kit, r.userData.vehicle, { id, frame: root, name: text.items[itemKey] ?? key });
|
|
41071
42906
|
tapEffects(d);
|
|
41072
42907
|
r.userData.destructible = d;
|
|
41073
42908
|
return d;
|
|
@@ -41094,7 +42929,7 @@ var GameVehiclesThree = (() => {
|
|
|
41094
42929
|
for (const e of events) {
|
|
41095
42930
|
const position = e.point ?? e.worldPoint;
|
|
41096
42931
|
if (!position) continue;
|
|
41097
|
-
if (e.type === "ignite") fx.play({ effect: effectIds.ignite, point: position });
|
|
42932
|
+
if (e.type === "ignite") fx.play({ effect: /fuel_tank|tank/.test(e.part ?? "") ? effectIds.leakIgnited : effectIds.ignite, point: position });
|
|
41098
42933
|
else if (e.type === "explode") fx.play({ effect: effectIds.explode, point: position });
|
|
41099
42934
|
else if (e.type === "leak") fx.play({ effect: effectIds.leak, point: position });
|
|
41100
42935
|
else if (e.type === "fracture" && /glass|window|windshield/.test(e.part ?? "")) fx.play({ effect: effectIds.glass, point: position });
|
|
@@ -41127,12 +42962,12 @@ var GameVehiclesThree = (() => {
|
|
|
41127
42962
|
const bounds = new three.Box3();
|
|
41128
42963
|
const piece = new three.Box3();
|
|
41129
42964
|
const matrix = new three.Matrix4();
|
|
41130
|
-
entry.root.traverse((
|
|
41131
|
-
if (!
|
|
41132
|
-
for (let p =
|
|
41133
|
-
if (
|
|
41134
|
-
|
|
41135
|
-
piece.copy(
|
|
42965
|
+
entry.root.traverse((mesh2) => {
|
|
42966
|
+
if (!mesh2.isMesh || !mesh2.geometry || mesh2.userData.ghost) return;
|
|
42967
|
+
for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
|
|
42968
|
+
if (mesh2.userData.helper) return;
|
|
42969
|
+
mesh2.geometry.computeBoundingBox();
|
|
42970
|
+
piece.copy(mesh2.geometry.boundingBox).applyMatrix4(matrix.multiplyMatrices(inverse, mesh2.matrixWorld));
|
|
41136
42971
|
bounds.union(piece);
|
|
41137
42972
|
});
|
|
41138
42973
|
const size = bounds.getSize(new three.Vector3());
|
|
@@ -41153,8 +42988,8 @@ var GameVehiclesThree = (() => {
|
|
|
41153
42988
|
if (!host?.bench || !three) return;
|
|
41154
42989
|
clearHelpers();
|
|
41155
42990
|
const kit = [...placed.values()][0] && ([...placed.values()][0].root.userData.kit ?? void 0);
|
|
41156
|
-
const mark = (entry,
|
|
41157
|
-
const helper = new three.Box3Helper(
|
|
42991
|
+
const mark = (entry, box2, color2) => {
|
|
42992
|
+
const helper = new three.Box3Helper(box2, color2);
|
|
41158
42993
|
helper.userData.helper = true;
|
|
41159
42994
|
entry.root.add(helper);
|
|
41160
42995
|
entry.helpers.push(helper);
|
|
@@ -41168,8 +43003,8 @@ var GameVehiclesThree = (() => {
|
|
|
41168
43003
|
if (host.bench.layer("zones")) {
|
|
41169
43004
|
for (const zone of entry.item.vehicle.zones ?? []) {
|
|
41170
43005
|
if (!zone.box || zone.type === "internal") continue;
|
|
41171
|
-
const
|
|
41172
|
-
mark(entry,
|
|
43006
|
+
const box2 = new three.Box3(new three.Vector3(zone.box.x0, zone.box.y0, zone.box.z0), new three.Vector3(zone.box.x1, zone.box.y1, zone.box.z1)).applyMatrix4(matrix);
|
|
43007
|
+
mark(entry, box2, ZONE_COLOURS[zone.type] ?? 16777215);
|
|
41173
43008
|
}
|
|
41174
43009
|
}
|
|
41175
43010
|
}
|
|
@@ -41318,11 +43153,11 @@ var GameVehiclesThree = (() => {
|
|
|
41318
43153
|
let drawCalls = 0;
|
|
41319
43154
|
let triangles = 0;
|
|
41320
43155
|
for (const entry of placed.values()) {
|
|
41321
|
-
entry.root.traverse((
|
|
41322
|
-
if (!
|
|
41323
|
-
for (let p =
|
|
43156
|
+
entry.root.traverse((mesh2) => {
|
|
43157
|
+
if (!mesh2.isMesh || mesh2.userData.helper) return;
|
|
43158
|
+
for (let p = mesh2; p; p = p.parent) if (p.visible === false) return;
|
|
41324
43159
|
drawCalls += 1;
|
|
41325
|
-
const g =
|
|
43160
|
+
const g = mesh2.geometry;
|
|
41326
43161
|
triangles += (g.index ? g.index.count : g.attributes.position.count) / 3;
|
|
41327
43162
|
});
|
|
41328
43163
|
}
|
|
@@ -41341,7 +43176,7 @@ var GameVehiclesThree = (() => {
|
|
|
41341
43176
|
for (const entry of placed.values()) {
|
|
41342
43177
|
const want = fleetDims(entry.key);
|
|
41343
43178
|
const got = entry.size;
|
|
41344
|
-
if (!want || !got) continue;
|
|
43179
|
+
if (!want || !got || entry.scenario) continue;
|
|
41345
43180
|
worst = Math.max(worst, Math.abs(got.length - want.length), Math.abs(got.width - want.width), Math.abs(got.height - want.height));
|
|
41346
43181
|
}
|
|
41347
43182
|
return Math.round(worst * 1e3);
|
|
@@ -41353,23 +43188,23 @@ var GameVehiclesThree = (() => {
|
|
|
41353
43188
|
get placed() {
|
|
41354
43189
|
return placed;
|
|
41355
43190
|
},
|
|
41356
|
-
items: () =>
|
|
43191
|
+
items: () => entries.map(item),
|
|
41357
43192
|
area: () => {
|
|
41358
43193
|
const gap = 1.6;
|
|
41359
43194
|
const WIDE = 6;
|
|
41360
|
-
const rowOf = (
|
|
43195
|
+
const rowOf = (list2, z) => {
|
|
41361
43196
|
let cursor = 0;
|
|
41362
|
-
const spots =
|
|
41363
|
-
const width = fleetDims(key)?.width ?? 2;
|
|
43197
|
+
const spots = list2.map((entry) => {
|
|
43198
|
+
const width = fleetDims(entry.key)?.width ?? 2;
|
|
41364
43199
|
const x = cursor + width / 2;
|
|
41365
43200
|
cursor += width + gap;
|
|
41366
|
-
return {
|
|
43201
|
+
return { id: entry.id, x };
|
|
41367
43202
|
});
|
|
41368
43203
|
return { spots, z, width: Math.max(0, cursor - gap) };
|
|
41369
43204
|
};
|
|
41370
|
-
const front = rowOf(
|
|
41371
|
-
const back = rowOf(
|
|
41372
|
-
const placements = [front, back].flatMap((row) => row.spots.map(({
|
|
43205
|
+
const front = rowOf(entries.filter((e) => (fleetDims(e.key)?.width ?? 2) <= WIDE), 0);
|
|
43206
|
+
const back = rowOf(entries.filter((e) => (fleetDims(e.key)?.width ?? 2) > WIDE), -16);
|
|
43207
|
+
const placements = [front, back].flatMap((row) => row.spots.map(({ id, x }) => ({ item: id, position: [x - row.width / 2, 0, row.z], rotationY: 0 })));
|
|
41373
43208
|
return { placements, view: { eye: [0, 5, Math.max(14, front.width * 0.6)], target: [0, 1, -2] } };
|
|
41374
43209
|
},
|
|
41375
43210
|
controls: () => {
|