@adatechnology/game-vehicles 0.2.0 → 0.4.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 +20 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.global.js +2006 -194
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +320 -64
- package/dist/index.js.map +1 -1
- package/package.json +9 -6
package/dist/index.js
CHANGED
|
@@ -2,6 +2,9 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
|
|
5
|
+
// src/kit.ts
|
|
6
|
+
import { shapeGeometries } from "@adatechnology/game-shapes-three";
|
|
7
|
+
|
|
5
8
|
// src/locales/en.json
|
|
6
9
|
var en_default = {
|
|
7
10
|
plate: {
|
|
@@ -935,46 +938,79 @@ function installGeometry(kit) {
|
|
|
935
938
|
}
|
|
936
939
|
const p = geo.attributes.position;
|
|
937
940
|
const n = p.count;
|
|
938
|
-
const
|
|
939
|
-
const
|
|
940
|
-
const
|
|
941
|
-
const
|
|
942
|
-
const C = new V3();
|
|
943
|
-
const e1 = new V3();
|
|
944
|
-
const e2 = new V3();
|
|
941
|
+
const faces = n / 3;
|
|
942
|
+
const FN = new Float64Array(faces * 3);
|
|
943
|
+
const map = /* @__PURE__ */ new Map();
|
|
944
|
+
const RANGE = 65536;
|
|
945
945
|
function key(i) {
|
|
946
|
-
|
|
946
|
+
const x = Math.round(p.getX(i) * 2e3);
|
|
947
|
+
const y = Math.round(p.getY(i) * 2e3);
|
|
948
|
+
const z = Math.round(p.getZ(i) * 2e3);
|
|
949
|
+
if (Math.abs(x) < RANGE && Math.abs(y) < RANGE && Math.abs(z) < RANGE) return ((x + RANGE) * 131072 + (y + RANGE)) * 131072 + (z + RANGE);
|
|
950
|
+
return x + "," + y + "," + z;
|
|
947
951
|
}
|
|
948
952
|
const keys = new Array(n);
|
|
949
|
-
for (let f = 0; f <
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
const
|
|
954
|
-
|
|
955
|
-
|
|
953
|
+
for (let f = 0; f < faces; f++) {
|
|
954
|
+
const ax = p.getX(3 * f);
|
|
955
|
+
const ay = p.getY(3 * f);
|
|
956
|
+
const az = p.getZ(3 * f);
|
|
957
|
+
const bx = p.getX(3 * f + 1);
|
|
958
|
+
const by = p.getY(3 * f + 1);
|
|
959
|
+
const bz = p.getZ(3 * f + 1);
|
|
960
|
+
const cx = p.getX(3 * f + 2);
|
|
961
|
+
const cy = p.getY(3 * f + 2);
|
|
962
|
+
const cz = p.getZ(3 * f + 2);
|
|
963
|
+
const e1x = cx - bx;
|
|
964
|
+
const e1y = cy - by;
|
|
965
|
+
const e1z = cz - bz;
|
|
966
|
+
const e2x = ax - bx;
|
|
967
|
+
const e2y = ay - by;
|
|
968
|
+
const e2z = az - bz;
|
|
969
|
+
let nx = e1y * e2z - e1z * e2y;
|
|
970
|
+
let ny = e1z * e2x - e1x * e2z;
|
|
971
|
+
let nz = e1x * e2y - e1y * e2x;
|
|
972
|
+
if (nx * nx + ny * ny + nz * nz > 1e-20) {
|
|
973
|
+
const inv = 1 / (Math.sqrt(nx * nx + ny * ny + nz * nz) || 1);
|
|
974
|
+
nx *= inv;
|
|
975
|
+
ny *= inv;
|
|
976
|
+
nz *= inv;
|
|
977
|
+
}
|
|
978
|
+
FN[3 * f] = nx;
|
|
979
|
+
FN[3 * f + 1] = ny;
|
|
980
|
+
FN[3 * f + 2] = nz;
|
|
956
981
|
for (let k = 0; k < 3; k++) {
|
|
957
982
|
const kk = key(3 * f + k);
|
|
958
983
|
keys[3 * f + k] = kk;
|
|
959
|
-
|
|
984
|
+
const list = map.get(kk);
|
|
985
|
+
if (list) list.push(f);
|
|
986
|
+
else map.set(kk, [f]);
|
|
960
987
|
}
|
|
961
988
|
}
|
|
962
989
|
const cs = Math.cos(deg * PI / 180);
|
|
963
990
|
const out = new Float32Array(n * 3);
|
|
964
|
-
const s = new V3();
|
|
965
991
|
for (let i = 0; i < n; i++) {
|
|
966
|
-
const fi = i / 3 | 0;
|
|
967
|
-
const list = map
|
|
968
|
-
|
|
992
|
+
const fi = (i / 3 | 0) * 3;
|
|
993
|
+
const list = map.get(keys[i]);
|
|
994
|
+
let sx = 0;
|
|
995
|
+
let sy = 0;
|
|
996
|
+
let sz = 0;
|
|
969
997
|
for (let j = 0; j < list.length; j++) {
|
|
970
|
-
const g =
|
|
971
|
-
if (g
|
|
998
|
+
const g = list[j] * 3;
|
|
999
|
+
if (FN[g] * FN[fi] + FN[g + 1] * FN[fi + 1] + FN[g + 2] * FN[fi + 2] >= cs) {
|
|
1000
|
+
sx += FN[g];
|
|
1001
|
+
sy += FN[g + 1];
|
|
1002
|
+
sz += FN[g + 2];
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
if (sx * sx + sy * sy + sz * sz < 1e-20) {
|
|
1006
|
+
sx = FN[fi];
|
|
1007
|
+
sy = FN[fi + 1];
|
|
1008
|
+
sz = FN[fi + 2];
|
|
972
1009
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
out[3 * i] =
|
|
976
|
-
out[3 * i +
|
|
977
|
-
out[3 * i + 2] = s.z;
|
|
1010
|
+
const inv = 1 / (Math.sqrt(sx * sx + sy * sy + sz * sz) || 1);
|
|
1011
|
+
out[3 * i] = sx * inv;
|
|
1012
|
+
out[3 * i + 1] = sy * inv;
|
|
1013
|
+
out[3 * i + 2] = sz * inv;
|
|
978
1014
|
}
|
|
979
1015
|
geo.setAttribute("normal", new THREE.BufferAttribute(out, 3));
|
|
980
1016
|
geo.userData.crease = true;
|
|
@@ -6632,6 +6668,153 @@ function installZoneDecals(kit) {
|
|
|
6632
6668
|
return hole;
|
|
6633
6669
|
}
|
|
6634
6670
|
const _zr = new THREE.Raycaster();
|
|
6671
|
+
const PROXY_MIN_TRIANGLES = 500;
|
|
6672
|
+
const STROKE_REACH = 0.6;
|
|
6673
|
+
const _pv = new V3();
|
|
6674
|
+
const _pm = new THREE.Matrix4();
|
|
6675
|
+
function decalRegion(c, z) {
|
|
6676
|
+
const B = z.box;
|
|
6677
|
+
const lo = [0, 1, 2].map(function(k) {
|
|
6678
|
+
return I.boxLo(B, k) - STROKE_REACH;
|
|
6679
|
+
});
|
|
6680
|
+
const hi = [0, 1, 2].map(function(k) {
|
|
6681
|
+
return I.boxHi(B, k) + STROKE_REACH;
|
|
6682
|
+
});
|
|
6683
|
+
const a = axisOf(z.dir);
|
|
6684
|
+
const dn = z.dir.clone().normalize();
|
|
6685
|
+
const sg = z.dir.getComponent(a) > 0 ? 1 : -1;
|
|
6686
|
+
const outer = sg > 0 ? I.boxLo(B, a) - 0.6 : I.boxHi(B, a) + 0.6;
|
|
6687
|
+
const far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
6688
|
+
for (let i = 0; i < 8; i++) {
|
|
6689
|
+
const p = new V3();
|
|
6690
|
+
p.setComponent(a, outer);
|
|
6691
|
+
[0, 1, 2].filter(function(k) {
|
|
6692
|
+
return k !== a;
|
|
6693
|
+
}).forEach(function(k, j) {
|
|
6694
|
+
p.setComponent(k, i >> j & 1 ? I.boxHi(B, k) : I.boxLo(B, k));
|
|
6695
|
+
});
|
|
6696
|
+
for (let e = 0; e < 2; e++) {
|
|
6697
|
+
const q = e ? p.clone().addScaledVector(dn, far) : p;
|
|
6698
|
+
for (let k = 0; k < 3; k++) {
|
|
6699
|
+
lo[k] = Math.min(lo[k], q.getComponent(k) - 0.05);
|
|
6700
|
+
hi[k] = Math.max(hi[k], q.getComponent(k) + 0.05);
|
|
6701
|
+
}
|
|
6702
|
+
}
|
|
6703
|
+
}
|
|
6704
|
+
return { lo, hi };
|
|
6705
|
+
}
|
|
6706
|
+
function regionCands(c, z, cands) {
|
|
6707
|
+
if (!cands.some(heavy)) return cands;
|
|
6708
|
+
const R = decalRegion(c, z);
|
|
6709
|
+
const Mw = c.vehicle.matrixWorld;
|
|
6710
|
+
return cands.map(function(o) {
|
|
6711
|
+
if (!heavy(o)) return o;
|
|
6712
|
+
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
6713
|
+
if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
|
|
6714
|
+
return proxyIn(o, Mw, R);
|
|
6715
|
+
});
|
|
6716
|
+
}
|
|
6717
|
+
function heavy(o) {
|
|
6718
|
+
const g = o.geometry;
|
|
6719
|
+
const pos = g && g.attributes && g.attributes.position;
|
|
6720
|
+
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;
|
|
6721
|
+
}
|
|
6722
|
+
function proxyIn(o, Mw, R) {
|
|
6723
|
+
_pm.copy(o.matrixWorld).invert().multiply(Mw);
|
|
6724
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
6725
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
6726
|
+
for (let i = 0; i < 8; i++) {
|
|
6727
|
+
_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);
|
|
6728
|
+
for (let k = 0; k < 3; k++) {
|
|
6729
|
+
lo[k] = Math.min(lo[k], _pv.getComponent(k));
|
|
6730
|
+
hi[k] = Math.max(hi[k], _pv.getComponent(k));
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6733
|
+
const g = o.geometry;
|
|
6734
|
+
const P = g.attributes.position.array;
|
|
6735
|
+
const ix = g.index ? g.index.array : null;
|
|
6736
|
+
const n = ix ? ix.length : P.length / 3;
|
|
6737
|
+
const keep = new Uint32Array(n - n % 3);
|
|
6738
|
+
let nk = 0;
|
|
6739
|
+
for (let t = 0; t + 2 < n; t += 3) {
|
|
6740
|
+
const a = (ix ? ix[t] : t) * 3;
|
|
6741
|
+
const b = (ix ? ix[t + 1] : t + 1) * 3;
|
|
6742
|
+
const d = (ix ? ix[t + 2] : t + 2) * 3;
|
|
6743
|
+
let out = false;
|
|
6744
|
+
for (let k = 0; k < 3 && !out; k++) {
|
|
6745
|
+
const u = P[a + k];
|
|
6746
|
+
const v = P[b + k];
|
|
6747
|
+
const w = P[d + k];
|
|
6748
|
+
out = Math.max(u, v, w) < lo[k] || Math.min(u, v, w) > hi[k];
|
|
6749
|
+
}
|
|
6750
|
+
if (!out) {
|
|
6751
|
+
keep[nk++] = ix ? ix[t] : t;
|
|
6752
|
+
keep[nk++] = ix ? ix[t + 1] : t + 1;
|
|
6753
|
+
keep[nk++] = ix ? ix[t + 2] : t + 2;
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
if (!nk) return null;
|
|
6757
|
+
const kept = keep.slice(0, nk);
|
|
6758
|
+
const box = new Float32Array(kept.length / 3 * 6);
|
|
6759
|
+
for (let t = 0, j = 0; t < kept.length; t += 3, j += 6) {
|
|
6760
|
+
const a = kept[t] * 3;
|
|
6761
|
+
const b = kept[t + 1] * 3;
|
|
6762
|
+
const d = kept[t + 2] * 3;
|
|
6763
|
+
for (let k = 0; k < 3; k++) {
|
|
6764
|
+
box[j + k] = Math.min(P[a + k], P[b + k], P[d + k]);
|
|
6765
|
+
box[j + 3 + k] = Math.max(P[a + k], P[b + k], P[d + k]);
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
const pg = new THREE.BufferGeometry();
|
|
6769
|
+
pg.setAttribute("position", g.attributes.position);
|
|
6770
|
+
pg.setIndex(new THREE.BufferAttribute(new Uint32Array(kept.length), 1));
|
|
6771
|
+
pg.boundingSphere = g.boundingSphere;
|
|
6772
|
+
pg.boundingBox = g.boundingBox;
|
|
6773
|
+
const proxy = new THREE.Mesh(pg, o.material);
|
|
6774
|
+
proxy.layers.mask = o.layers.mask;
|
|
6775
|
+
proxy.proxyOf = o;
|
|
6776
|
+
proxy.kept = kept;
|
|
6777
|
+
proxy.keptBox = box;
|
|
6778
|
+
return proxy;
|
|
6779
|
+
}
|
|
6780
|
+
function narrowTo(rc, proxy) {
|
|
6781
|
+
const o = proxy.proxyOf;
|
|
6782
|
+
const ray = rc.ray;
|
|
6783
|
+
_pm.copy(o.matrixWorld).invert();
|
|
6784
|
+
_pv.copy(ray.origin).applyMatrix4(_pm);
|
|
6785
|
+
const x0 = _pv.x;
|
|
6786
|
+
const y0 = _pv.y;
|
|
6787
|
+
const z0 = _pv.z;
|
|
6788
|
+
_pv.copy(ray.direction).multiplyScalar(rc.far).add(ray.origin).applyMatrix4(_pm);
|
|
6789
|
+
const lo0 = Math.min(x0, _pv.x) - 1e-4;
|
|
6790
|
+
const lo1 = Math.min(y0, _pv.y) - 1e-4;
|
|
6791
|
+
const lo2 = Math.min(z0, _pv.z) - 1e-4;
|
|
6792
|
+
const hi0 = Math.max(x0, _pv.x) + 1e-4;
|
|
6793
|
+
const hi1 = Math.max(y0, _pv.y) + 1e-4;
|
|
6794
|
+
const hi2 = Math.max(z0, _pv.z) + 1e-4;
|
|
6795
|
+
const K = proxy.kept;
|
|
6796
|
+
const X = proxy.keptBox;
|
|
6797
|
+
const dst = proxy.geometry.index.array;
|
|
6798
|
+
let m = 0;
|
|
6799
|
+
for (let t = 0, j = 0; t < K.length; t += 3, j += 6) {
|
|
6800
|
+
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;
|
|
6801
|
+
dst[m++] = K[t];
|
|
6802
|
+
dst[m++] = K[t + 1];
|
|
6803
|
+
dst[m++] = K[t + 2];
|
|
6804
|
+
}
|
|
6805
|
+
proxy.geometry.setDrawRange(0, m);
|
|
6806
|
+
}
|
|
6807
|
+
function castAt(rc, cands) {
|
|
6808
|
+
for (let i = 0; i < cands.length; i++) {
|
|
6809
|
+
const q = cands[i];
|
|
6810
|
+
if (!q.proxyOf) continue;
|
|
6811
|
+
q.matrixWorld.copy(q.proxyOf.matrixWorld);
|
|
6812
|
+
narrowTo(rc, q);
|
|
6813
|
+
}
|
|
6814
|
+
const hits = rc.intersectObjects(cands, false);
|
|
6815
|
+
for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
|
|
6816
|
+
return hits;
|
|
6817
|
+
}
|
|
6635
6818
|
function zoneCands(c, z, inv, glassToo) {
|
|
6636
6819
|
const out = [];
|
|
6637
6820
|
c.vehicle.traverse(function(o) {
|
|
@@ -6684,7 +6867,7 @@ function installZoneDecals(kit) {
|
|
|
6684
6867
|
});
|
|
6685
6868
|
_zr.set(org.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
|
|
6686
6869
|
_zr.far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
6687
|
-
const hits = _zr
|
|
6870
|
+
const hits = castAt(_zr, cands);
|
|
6688
6871
|
for (let i = 0; i < hits.length; i++) {
|
|
6689
6872
|
const h = hits[i];
|
|
6690
6873
|
if (!h.face) continue;
|
|
@@ -6712,7 +6895,7 @@ function installZoneDecals(kit) {
|
|
|
6712
6895
|
const q = s.p.clone().addScaledVector(t, len * 0.5 * k / M);
|
|
6713
6896
|
_rt.set(q.clone().addScaledVector(n, 0.08).applyMatrix4(Mw), n.clone().negate().transformDirection(Mw));
|
|
6714
6897
|
_rt.far = 0.2;
|
|
6715
|
-
const h = _rt
|
|
6898
|
+
const h = castAt(_rt, cands).find(function(x) {
|
|
6716
6899
|
return x.face;
|
|
6717
6900
|
});
|
|
6718
6901
|
if (!h) return null;
|
|
@@ -6783,6 +6966,7 @@ function installZoneDecals(kit) {
|
|
|
6783
6966
|
const R = c.rand;
|
|
6784
6967
|
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);
|
|
6785
6968
|
if (!need) return [];
|
|
6969
|
+
cands = regionCands(c, z, cands).filter(Boolean);
|
|
6786
6970
|
const S = zoneSurf(c, z, need + 2, R, cands);
|
|
6787
6971
|
let k = 0;
|
|
6788
6972
|
const ang0 = R() * PI;
|
|
@@ -6863,8 +7047,25 @@ function installZoneDent(kit) {
|
|
|
6863
7047
|
}
|
|
6864
7048
|
function subdivIn(geo, rel, B, maxLen) {
|
|
6865
7049
|
const a = geo.attributes.position.array;
|
|
6866
|
-
|
|
6867
|
-
|
|
7050
|
+
let out = new Float32Array(a.length + 4096);
|
|
7051
|
+
let used = 0;
|
|
7052
|
+
const push = function(a0, a1, a2, b0, b1, b2, c0, c1, c2) {
|
|
7053
|
+
if (used + 9 > out.length) {
|
|
7054
|
+
const bigger = new Float32Array(out.length * 2);
|
|
7055
|
+
bigger.set(out);
|
|
7056
|
+
out = bigger;
|
|
7057
|
+
}
|
|
7058
|
+
out[used] = a0;
|
|
7059
|
+
out[used + 1] = a1;
|
|
7060
|
+
out[used + 2] = a2;
|
|
7061
|
+
out[used + 3] = b0;
|
|
7062
|
+
out[used + 4] = b1;
|
|
7063
|
+
out[used + 5] = b2;
|
|
7064
|
+
out[used + 6] = c0;
|
|
7065
|
+
out[used + 7] = c1;
|
|
7066
|
+
out[used + 8] = c2;
|
|
7067
|
+
used += 9;
|
|
7068
|
+
};
|
|
6868
7069
|
const e = 0.15;
|
|
6869
7070
|
function d(p, q) {
|
|
6870
7071
|
return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
|
|
@@ -6878,7 +7079,7 @@ function installZoneDent(kit) {
|
|
|
6878
7079
|
const ca = d(C, A);
|
|
6879
7080
|
const mx = Math.max(ab, bc, ca);
|
|
6880
7081
|
if (mx <= maxLen || depth > 9) {
|
|
6881
|
-
|
|
7082
|
+
push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
6882
7083
|
return;
|
|
6883
7084
|
}
|
|
6884
7085
|
if (mx === ab) {
|
|
@@ -6895,31 +7096,26 @@ function installZoneDent(kit) {
|
|
|
6895
7096
|
tri(F2, Bv, C, depth + 1);
|
|
6896
7097
|
}
|
|
6897
7098
|
}
|
|
7099
|
+
const M = rel.elements;
|
|
7100
|
+
const at = function(x, y, z, k) {
|
|
7101
|
+
const w = 1 / (M[3] * x + M[7] * y + M[11] * z + M[15]);
|
|
7102
|
+
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;
|
|
7103
|
+
};
|
|
7104
|
+
const lo = [B.x0 - e, B.y0 - e, B.z0 - e];
|
|
7105
|
+
const hi = [B.x1 + e, B.y1 + e, B.z1 + e];
|
|
6898
7106
|
for (let i = 0; i < a.length; i += 9) {
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
[A, Bv, C].forEach(function(p) {
|
|
6909
|
-
v.set(p[0], p[1], p[2]).applyMatrix4(rel);
|
|
6910
|
-
x0 = Math.min(x0, v.x);
|
|
6911
|
-
x1 = Math.max(x1, v.x);
|
|
6912
|
-
y0 = Math.min(y0, v.y);
|
|
6913
|
-
y1 = Math.max(y1, v.y);
|
|
6914
|
-
z0 = Math.min(z0, v.z);
|
|
6915
|
-
z1 = Math.max(z1, v.z);
|
|
6916
|
-
});
|
|
6917
|
-
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)
|
|
6918
|
-
out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
6919
|
-
else tri(A, Bv, C, 0);
|
|
7107
|
+
let outside = false;
|
|
7108
|
+
for (let k = 0; k < 3 && !outside; k++) {
|
|
7109
|
+
const p = at(a[i], a[i + 1], a[i + 2], k);
|
|
7110
|
+
const q = at(a[i + 3], a[i + 4], a[i + 5], k);
|
|
7111
|
+
const r = at(a[i + 6], a[i + 7], a[i + 8], k);
|
|
7112
|
+
outside = Math.max(p, q, r) < lo[k] || Math.min(p, q, r) > hi[k];
|
|
7113
|
+
}
|
|
7114
|
+
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]);
|
|
7115
|
+
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);
|
|
6920
7116
|
}
|
|
6921
7117
|
const g = new THREE.BufferGeometry();
|
|
6922
|
-
g.setAttribute("position", new THREE.
|
|
7118
|
+
g.setAttribute("position", new THREE.BufferAttribute(out.slice(0, used), 3));
|
|
6923
7119
|
g.userData.crease = true;
|
|
6924
7120
|
g.userData.p0 = null;
|
|
6925
7121
|
return g;
|
|
@@ -6942,6 +7138,17 @@ function installZoneDent(kit) {
|
|
|
6942
7138
|
});
|
|
6943
7139
|
return out;
|
|
6944
7140
|
}
|
|
7141
|
+
function boxInFrame(B, m, tmp) {
|
|
7142
|
+
const r = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
|
|
7143
|
+
for (let i = 0; i < 8; i++) {
|
|
7144
|
+
tmp.set(i & 1 ? B.x1 : B.x0, i & 2 ? B.y1 : B.y0, i & 4 ? B.z1 : B.z0).applyMatrix4(m);
|
|
7145
|
+
for (let k = 0; k < 3; k++) {
|
|
7146
|
+
r[k] = Math.min(r[k], tmp.getComponent(k) - 1e-4);
|
|
7147
|
+
r[k + 3] = Math.max(r[k + 3], tmp.getComponent(k) + 1e-4);
|
|
7148
|
+
}
|
|
7149
|
+
}
|
|
7150
|
+
return r;
|
|
7151
|
+
}
|
|
6945
7152
|
function zoneDent(c, z, dents, dirty, opt) {
|
|
6946
7153
|
opt = opt || {};
|
|
6947
7154
|
const B = z.box;
|
|
@@ -6996,6 +7203,7 @@ function installZoneDent(kit) {
|
|
|
6996
7203
|
g = msh.geometry = g.clone();
|
|
6997
7204
|
msh.userData.zCloned = true;
|
|
6998
7205
|
}
|
|
7206
|
+
let boundsDue = false;
|
|
6999
7207
|
const nonIdx = !g.index;
|
|
7000
7208
|
const onlyPos = Object.keys(g.attributes).every(function(k) {
|
|
7001
7209
|
return k === "position" || k === "normal";
|
|
@@ -7004,15 +7212,17 @@ function installZoneDent(kit) {
|
|
|
7004
7212
|
const ng = subdivIn(g, rel, B, opt.sub || 0.075);
|
|
7005
7213
|
g.dispose();
|
|
7006
7214
|
g = msh.geometry = ng;
|
|
7007
|
-
|
|
7008
|
-
ng.computeBoundingBox();
|
|
7215
|
+
boundsDue = true;
|
|
7009
7216
|
dirty.add(msh);
|
|
7010
7217
|
}
|
|
7011
7218
|
irel.copy(rel).invert();
|
|
7012
7219
|
const pos = g.attributes.position;
|
|
7013
7220
|
let changed = false;
|
|
7221
|
+
const near = boxInFrame(B, irel, v);
|
|
7014
7222
|
for (let i = 0; i < pos.count; i++) {
|
|
7015
|
-
v.fromBufferAttribute(pos, i)
|
|
7223
|
+
v.fromBufferAttribute(pos, i);
|
|
7224
|
+
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;
|
|
7225
|
+
v.applyMatrix4(rel);
|
|
7016
7226
|
const f = field(v);
|
|
7017
7227
|
if (f <= 1e-5) continue;
|
|
7018
7228
|
v.addScaledVector(d, f);
|
|
@@ -7033,9 +7243,11 @@ function installZoneDent(kit) {
|
|
|
7033
7243
|
}
|
|
7034
7244
|
if (changed) {
|
|
7035
7245
|
pos.needsUpdate = true;
|
|
7246
|
+
dirty.add(msh);
|
|
7247
|
+
}
|
|
7248
|
+
if (changed || boundsDue) {
|
|
7036
7249
|
g.computeBoundingSphere();
|
|
7037
7250
|
g.computeBoundingBox();
|
|
7038
|
-
dirty.add(msh);
|
|
7039
7251
|
}
|
|
7040
7252
|
});
|
|
7041
7253
|
const dset = new Set(c.deform);
|
|
@@ -9915,7 +10127,7 @@ function createVehicleKit(options) {
|
|
|
9915
10127
|
const opts = options || {};
|
|
9916
10128
|
if (!opts.THREE || !opts.THREE.Vector3) throw new Error("createVehicleKit: options.THREE (the three.js namespace) is required");
|
|
9917
10129
|
const lod = createLod(opts.lod);
|
|
9918
|
-
const THREE = wrapThreeForLod(opts.THREE, lod);
|
|
10130
|
+
const THREE = wrapThreeForLod(shapeGeometries(opts.THREE), lod);
|
|
9919
10131
|
const strings = resolveStrings(opts.locale);
|
|
9920
10132
|
const t = createTranslate(strings);
|
|
9921
10133
|
const doc = opts.document || (typeof document !== "undefined" ? document : void 0);
|
|
@@ -10138,6 +10350,20 @@ function createVehicleKit(options) {
|
|
|
10138
10350
|
else kit.applyArmor(c);
|
|
10139
10351
|
}
|
|
10140
10352
|
if (zoneState == null && st === "damaged" && kit.config.damagedScenario) zoneState = kit.zoneScenario(c, kit.config.damagedScenario);
|
|
10353
|
+
else if (zoneState && zoneState.scenario != null) {
|
|
10354
|
+
c.scenario = zoneState.scenario;
|
|
10355
|
+
let fromScenario = { health: {}, flags: {} };
|
|
10356
|
+
try {
|
|
10357
|
+
fromScenario = kit.zoneScenario(c, zoneState.scenario);
|
|
10358
|
+
} catch (e) {
|
|
10359
|
+
;
|
|
10360
|
+
(c.zoneErrors = c.zoneErrors || []).push("scenario: " + (e && e.message));
|
|
10361
|
+
}
|
|
10362
|
+
zoneState = {
|
|
10363
|
+
health: Object.assign({}, fromScenario.health, zoneState.health),
|
|
10364
|
+
flags: Object.assign({}, fromScenario.flags, zoneState.flags)
|
|
10365
|
+
};
|
|
10366
|
+
}
|
|
10141
10367
|
if (zoneState) kit.applyZones(c, zoneState);
|
|
10142
10368
|
else {
|
|
10143
10369
|
c.zoneState = { health: {}, flags: {} };
|
|
@@ -10176,6 +10402,9 @@ function createVehicleKit(options) {
|
|
|
10176
10402
|
return kit;
|
|
10177
10403
|
}
|
|
10178
10404
|
|
|
10405
|
+
// src/destructible/impl.ts
|
|
10406
|
+
import { ignitionChance, resolveIgnitionRules, sparkTargetFactor } from "@adatechnology/game-contracts";
|
|
10407
|
+
|
|
10179
10408
|
// src/destructible/model.ts
|
|
10180
10409
|
var JOINT_RULES = {
|
|
10181
10410
|
hinge: { strength: 5e3, tools: ["wrench", "screwdriver"], seconds: 3 },
|
|
@@ -11288,6 +11517,9 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11288
11517
|
const headless = !!options.headless;
|
|
11289
11518
|
const seedBase = strHash(`${c.key}|${id}|${options.seed ?? 0}`);
|
|
11290
11519
|
let rand = rng(seedBase);
|
|
11520
|
+
const ignitionRules = resolveIgnitionRules(options.ignition);
|
|
11521
|
+
const fuelFraction = clamp(options.fuel ?? 1, 0, 1);
|
|
11522
|
+
let igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
|
|
11291
11523
|
let clock = 0;
|
|
11292
11524
|
let model;
|
|
11293
11525
|
let vis = null;
|
|
@@ -11355,7 +11587,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11355
11587
|
dents: [],
|
|
11356
11588
|
holes: [],
|
|
11357
11589
|
cracks: [],
|
|
11358
|
-
liters: d.contains
|
|
11590
|
+
liters: d.contains ? d.role === "fuel_tank" ? d.contains.liters * fuelFraction : d.contains.liters : void 0,
|
|
11359
11591
|
lost: false,
|
|
11360
11592
|
status: "intact",
|
|
11361
11593
|
flat: false,
|
|
@@ -11373,6 +11605,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11373
11605
|
wasLit = true;
|
|
11374
11606
|
deadEngine = false;
|
|
11375
11607
|
rand = rng(seedBase);
|
|
11608
|
+
igniteRand = rng(strHash(`${c.key}|${id}|ignition|${options.seed ?? 0}`));
|
|
11376
11609
|
steerSign = rand() < 0.5 ? -1 : 1;
|
|
11377
11610
|
vis = headless ? null : new VehicleVisuals(kit, c, model);
|
|
11378
11611
|
recomputeGroups();
|
|
@@ -11667,8 +11900,19 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11667
11900
|
if (!p.burning && p.temp > AMBIENT) p.temp = Math.max(AMBIENT, p.temp - dt * 6);
|
|
11668
11901
|
}
|
|
11669
11902
|
for (const f of flames) heat(centreOf(f.def), 0.8, 500, dt * 0.5, out, 0);
|
|
11903
|
+
fireNearLeak(flames, dt, out);
|
|
11670
11904
|
thermal(out);
|
|
11671
11905
|
};
|
|
11906
|
+
const fireNearLeak = (flames, dt, out) => {
|
|
11907
|
+
const tank = tankPart();
|
|
11908
|
+
const leak = tank ? leaks.get(tank.def.id) : void 0;
|
|
11909
|
+
if (!tank || !leak || tank.lost || tank.burning || exploded || leak.fluid !== "fuel" && leak.fluid !== "diesel") return;
|
|
11910
|
+
if (leak.pud?.fire) return light(tank, out);
|
|
11911
|
+
const { radius, chancePerSecond } = ignitionRules.fireNear;
|
|
11912
|
+
if (chancePerSecond <= 0) return;
|
|
11913
|
+
const near = flames.some((f) => f !== tank && distToBox(tank.def, centreOf(f.def)) - Math.max(...f.def.box.size) / 2 <= radius);
|
|
11914
|
+
if (near && igniteRand() < 1 - Math.exp(-chancePerSecond * dt)) light(tank, out);
|
|
11915
|
+
};
|
|
11672
11916
|
const normalOf = (d, v) => faceNormal(d, v);
|
|
11673
11917
|
const ballistic = (h, out) => {
|
|
11674
11918
|
sync();
|
|
@@ -11736,10 +11980,21 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11736
11980
|
let amount = through ? E * 0.6 : E * 0.25;
|
|
11737
11981
|
if (through && (d.role === "battery" || d.role === "alternator")) amount = Math.max(amount, p.hp * 0.65);
|
|
11738
11982
|
damage(p, amount, "ballistic", h.source, out, worldPoint);
|
|
11739
|
-
if (d.role === "fuel_tank"
|
|
11983
|
+
if (through && d.role === "fuel_tank") rollIgnition(p, h, metal, out);
|
|
11740
11984
|
}
|
|
11741
11985
|
}
|
|
11742
11986
|
};
|
|
11987
|
+
const light = (tank, out) => {
|
|
11988
|
+
tank.temp = Math.max(tank.temp, (tank.def.ignitionC ?? 260) + 1);
|
|
11989
|
+
if ((tank.liters ?? 0) > 0.5) ignite(tank, out);
|
|
11990
|
+
};
|
|
11991
|
+
const rollIgnition = (tank, h, metal, out) => {
|
|
11992
|
+
const d = tank.def;
|
|
11993
|
+
if (!d.contains || tank.burning || (tank.liters ?? 0) <= 0.05) return;
|
|
11994
|
+
const fill = d.contains.liters > 0 ? (tank.liters ?? 0) / d.contains.liters : 0;
|
|
11995
|
+
const chance = ignitionChance(h, { sparkTarget: sparkTargetFactor(d.material, metal, ignitionRules), fill, fluid: d.contains.fluid }, ignitionRules);
|
|
11996
|
+
if (chance > 0 && igniteRand() < chance) light(tank, out);
|
|
11997
|
+
};
|
|
11743
11998
|
const blunt = (h, out) => {
|
|
11744
11999
|
sync();
|
|
11745
12000
|
const M = toFrameMatrix();
|
|
@@ -11803,7 +12058,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
11803
12058
|
const verdict = kit.blastDamage(c, E / (1 + dist * dist * 4) / 50);
|
|
11804
12059
|
if (verdict === "explosion") explode(tank, h.source, out);
|
|
11805
12060
|
else if (verdict === "fire") {
|
|
11806
|
-
|
|
12061
|
+
light(tank, out);
|
|
11807
12062
|
startLeak(tank, centreOf(tank.def).setY(tank.def.box.center[1] - tank.def.box.size[1] / 2 + 0.05), 12, out, dir);
|
|
11808
12063
|
}
|
|
11809
12064
|
}
|
|
@@ -12065,7 +12320,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
12065
12320
|
const reset = () => {
|
|
12066
12321
|
const old = c;
|
|
12067
12322
|
const parent = old.root.parent;
|
|
12068
|
-
const next = kit.build(old.key, old.state);
|
|
12323
|
+
const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
|
|
12069
12324
|
if (parent) {
|
|
12070
12325
|
next.root.position.copy(old.root.position);
|
|
12071
12326
|
next.root.quaternion.copy(old.root.quaternion);
|
|
@@ -12122,7 +12377,8 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
|
|
|
12122
12377
|
// src/destructible/item.ts
|
|
12123
12378
|
function buildVehicleItem(kit, key, options = {}) {
|
|
12124
12379
|
const THREE = kit.THREE;
|
|
12125
|
-
const
|
|
12380
|
+
const zoneState = options.scenario != null ? { scenario: options.scenario } : void 0;
|
|
12381
|
+
const vehicle = options.lod ? kit.build(key, options.state ?? "intact", zoneState, { lod: true }) : kit.build(key, options.state ?? "intact", zoneState);
|
|
12126
12382
|
const m = vehicle.meta;
|
|
12127
12383
|
const root = new THREE.Group();
|
|
12128
12384
|
root.name = key;
|