@adatechnology/game-vehicles 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -938,46 +938,79 @@ function installGeometry(kit) {
938
938
  }
939
939
  const p = geo.attributes.position;
940
940
  const n = p.count;
941
- const FN = [];
942
- const map = {};
943
- const A = new V3();
944
- const B = new V3();
945
- const C = new V3();
946
- const e1 = new V3();
947
- 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;
948
945
  function key(i) {
949
- return Math.round(p.getX(i) * 2e3) + "," + Math.round(p.getY(i) * 2e3) + "," + Math.round(p.getZ(i) * 2e3);
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;
950
951
  }
951
952
  const keys = new Array(n);
952
- for (let f = 0; f < n / 3; f++) {
953
- A.fromBufferAttribute(p, 3 * f);
954
- B.fromBufferAttribute(p, 3 * f + 1);
955
- C.fromBufferAttribute(p, 3 * f + 2);
956
- const nn = new V3().crossVectors(e1.subVectors(C, B), e2.subVectors(A, B));
957
- if (nn.lengthSq() > 1e-20) nn.normalize();
958
- FN.push(nn);
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;
959
981
  for (let k = 0; k < 3; k++) {
960
982
  const kk = key(3 * f + k);
961
983
  keys[3 * f + k] = kk;
962
- (map[kk] || (map[kk] = [])).push(f);
984
+ const list = map.get(kk);
985
+ if (list) list.push(f);
986
+ else map.set(kk, [f]);
963
987
  }
964
988
  }
965
989
  const cs = Math.cos(deg * PI / 180);
966
990
  const out = new Float32Array(n * 3);
967
- const s = new V3();
968
991
  for (let i = 0; i < n; i++) {
969
- const fi = i / 3 | 0;
970
- const list = map[keys[i]];
971
- s.set(0, 0, 0);
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;
972
997
  for (let j = 0; j < list.length; j++) {
973
- const g = FN[list[j]];
974
- if (g.dot(FN[fi]) >= cs) s.add(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
+ }
975
1004
  }
976
- if (s.lengthSq() < 1e-20) s.copy(FN[fi]);
977
- s.normalize();
978
- out[3 * i] = s.x;
979
- out[3 * i + 1] = s.y;
980
- out[3 * i + 2] = s.z;
1005
+ if (sx * sx + sy * sy + sz * sz < 1e-20) {
1006
+ sx = FN[fi];
1007
+ sy = FN[fi + 1];
1008
+ sz = FN[fi + 2];
1009
+ }
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;
981
1014
  }
982
1015
  geo.setAttribute("normal", new THREE.BufferAttribute(out, 3));
983
1016
  geo.userData.crease = true;
@@ -1362,6 +1395,7 @@ function installGeometry(kit) {
1362
1395
  }
1363
1396
 
1364
1397
  // src/context.ts
1398
+ import { markKitOrigin } from "@adatechnology/game-contracts";
1365
1399
  function installContext(kit) {
1366
1400
  const THREE = kit.THREE;
1367
1401
  const V3 = THREE.Vector3;
@@ -1381,6 +1415,7 @@ function installContext(kit) {
1381
1415
  this.effects = new THREE.Group();
1382
1416
  this.root.add(this.vehicle);
1383
1417
  this.root.add(this.effects);
1418
+ markKitOrigin(this.root, { owner: "game-vehicles", kind: "vehicle" });
1384
1419
  this.state = state;
1385
1420
  this.glass = [];
1386
1421
  this.quads = [];
@@ -6635,6 +6670,153 @@ function installZoneDecals(kit) {
6635
6670
  return hole;
6636
6671
  }
6637
6672
  const _zr = new THREE.Raycaster();
6673
+ const PROXY_MIN_TRIANGLES = 500;
6674
+ const STROKE_REACH = 0.6;
6675
+ const _pv = new V3();
6676
+ const _pm = new THREE.Matrix4();
6677
+ function decalRegion(c, z) {
6678
+ const B = z.box;
6679
+ const lo = [0, 1, 2].map(function(k) {
6680
+ return I.boxLo(B, k) - STROKE_REACH;
6681
+ });
6682
+ const hi = [0, 1, 2].map(function(k) {
6683
+ return I.boxHi(B, k) + STROKE_REACH;
6684
+ });
6685
+ const a = axisOf(z.dir);
6686
+ const dn = z.dir.clone().normalize();
6687
+ const sg = z.dir.getComponent(a) > 0 ? 1 : -1;
6688
+ const outer = sg > 0 ? I.boxLo(B, a) - 0.6 : I.boxHi(B, a) + 0.6;
6689
+ const far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
6690
+ for (let i = 0; i < 8; i++) {
6691
+ const p = new V3();
6692
+ p.setComponent(a, outer);
6693
+ [0, 1, 2].filter(function(k) {
6694
+ return k !== a;
6695
+ }).forEach(function(k, j) {
6696
+ p.setComponent(k, i >> j & 1 ? I.boxHi(B, k) : I.boxLo(B, k));
6697
+ });
6698
+ for (let e = 0; e < 2; e++) {
6699
+ const q = e ? p.clone().addScaledVector(dn, far) : p;
6700
+ for (let k = 0; k < 3; k++) {
6701
+ lo[k] = Math.min(lo[k], q.getComponent(k) - 0.05);
6702
+ hi[k] = Math.max(hi[k], q.getComponent(k) + 0.05);
6703
+ }
6704
+ }
6705
+ }
6706
+ return { lo, hi };
6707
+ }
6708
+ function regionCands(c, z, cands) {
6709
+ if (!cands.some(heavy)) return cands;
6710
+ const R = decalRegion(c, z);
6711
+ const Mw = c.vehicle.matrixWorld;
6712
+ return cands.map(function(o) {
6713
+ if (!heavy(o)) return o;
6714
+ if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
6715
+ if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
6716
+ return proxyIn(o, Mw, R);
6717
+ });
6718
+ }
6719
+ function heavy(o) {
6720
+ const g = o.geometry;
6721
+ const pos = g && g.attributes && g.attributes.position;
6722
+ 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;
6723
+ }
6724
+ function proxyIn(o, Mw, R) {
6725
+ _pm.copy(o.matrixWorld).invert().multiply(Mw);
6726
+ const lo = [Infinity, Infinity, Infinity];
6727
+ const hi = [-Infinity, -Infinity, -Infinity];
6728
+ for (let i = 0; i < 8; i++) {
6729
+ _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);
6730
+ for (let k = 0; k < 3; k++) {
6731
+ lo[k] = Math.min(lo[k], _pv.getComponent(k));
6732
+ hi[k] = Math.max(hi[k], _pv.getComponent(k));
6733
+ }
6734
+ }
6735
+ const g = o.geometry;
6736
+ const P = g.attributes.position.array;
6737
+ const ix = g.index ? g.index.array : null;
6738
+ const n = ix ? ix.length : P.length / 3;
6739
+ const keep = new Uint32Array(n - n % 3);
6740
+ let nk = 0;
6741
+ for (let t = 0; t + 2 < n; t += 3) {
6742
+ const a = (ix ? ix[t] : t) * 3;
6743
+ const b = (ix ? ix[t + 1] : t + 1) * 3;
6744
+ const d = (ix ? ix[t + 2] : t + 2) * 3;
6745
+ let out = false;
6746
+ for (let k = 0; k < 3 && !out; k++) {
6747
+ const u = P[a + k];
6748
+ const v = P[b + k];
6749
+ const w = P[d + k];
6750
+ out = Math.max(u, v, w) < lo[k] || Math.min(u, v, w) > hi[k];
6751
+ }
6752
+ if (!out) {
6753
+ keep[nk++] = ix ? ix[t] : t;
6754
+ keep[nk++] = ix ? ix[t + 1] : t + 1;
6755
+ keep[nk++] = ix ? ix[t + 2] : t + 2;
6756
+ }
6757
+ }
6758
+ if (!nk) return null;
6759
+ const kept = keep.slice(0, nk);
6760
+ const box = new Float32Array(kept.length / 3 * 6);
6761
+ for (let t = 0, j = 0; t < kept.length; t += 3, j += 6) {
6762
+ const a = kept[t] * 3;
6763
+ const b = kept[t + 1] * 3;
6764
+ const d = kept[t + 2] * 3;
6765
+ for (let k = 0; k < 3; k++) {
6766
+ box[j + k] = Math.min(P[a + k], P[b + k], P[d + k]);
6767
+ box[j + 3 + k] = Math.max(P[a + k], P[b + k], P[d + k]);
6768
+ }
6769
+ }
6770
+ const pg = new THREE.BufferGeometry();
6771
+ pg.setAttribute("position", g.attributes.position);
6772
+ pg.setIndex(new THREE.BufferAttribute(new Uint32Array(kept.length), 1));
6773
+ pg.boundingSphere = g.boundingSphere;
6774
+ pg.boundingBox = g.boundingBox;
6775
+ const proxy = new THREE.Mesh(pg, o.material);
6776
+ proxy.layers.mask = o.layers.mask;
6777
+ proxy.proxyOf = o;
6778
+ proxy.kept = kept;
6779
+ proxy.keptBox = box;
6780
+ return proxy;
6781
+ }
6782
+ function narrowTo(rc, proxy) {
6783
+ const o = proxy.proxyOf;
6784
+ const ray = rc.ray;
6785
+ _pm.copy(o.matrixWorld).invert();
6786
+ _pv.copy(ray.origin).applyMatrix4(_pm);
6787
+ const x0 = _pv.x;
6788
+ const y0 = _pv.y;
6789
+ const z0 = _pv.z;
6790
+ _pv.copy(ray.direction).multiplyScalar(rc.far).add(ray.origin).applyMatrix4(_pm);
6791
+ const lo0 = Math.min(x0, _pv.x) - 1e-4;
6792
+ const lo1 = Math.min(y0, _pv.y) - 1e-4;
6793
+ const lo2 = Math.min(z0, _pv.z) - 1e-4;
6794
+ const hi0 = Math.max(x0, _pv.x) + 1e-4;
6795
+ const hi1 = Math.max(y0, _pv.y) + 1e-4;
6796
+ const hi2 = Math.max(z0, _pv.z) + 1e-4;
6797
+ const K = proxy.kept;
6798
+ const X = proxy.keptBox;
6799
+ const dst = proxy.geometry.index.array;
6800
+ let m = 0;
6801
+ for (let t = 0, j = 0; t < K.length; t += 3, j += 6) {
6802
+ 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;
6803
+ dst[m++] = K[t];
6804
+ dst[m++] = K[t + 1];
6805
+ dst[m++] = K[t + 2];
6806
+ }
6807
+ proxy.geometry.setDrawRange(0, m);
6808
+ }
6809
+ function castAt(rc, cands) {
6810
+ for (let i = 0; i < cands.length; i++) {
6811
+ const q = cands[i];
6812
+ if (!q.proxyOf) continue;
6813
+ q.matrixWorld.copy(q.proxyOf.matrixWorld);
6814
+ narrowTo(rc, q);
6815
+ }
6816
+ const hits = rc.intersectObjects(cands, false);
6817
+ for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
6818
+ return hits;
6819
+ }
6638
6820
  function zoneCands(c, z, inv, glassToo) {
6639
6821
  const out = [];
6640
6822
  c.vehicle.traverse(function(o) {
@@ -6687,7 +6869,7 @@ function installZoneDecals(kit) {
6687
6869
  });
6688
6870
  _zr.set(org.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
6689
6871
  _zr.far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
6690
- const hits = _zr.intersectObjects(cands, false);
6872
+ const hits = castAt(_zr, cands);
6691
6873
  for (let i = 0; i < hits.length; i++) {
6692
6874
  const h = hits[i];
6693
6875
  if (!h.face) continue;
@@ -6715,7 +6897,7 @@ function installZoneDecals(kit) {
6715
6897
  const q = s.p.clone().addScaledVector(t, len * 0.5 * k / M);
6716
6898
  _rt.set(q.clone().addScaledVector(n, 0.08).applyMatrix4(Mw), n.clone().negate().transformDirection(Mw));
6717
6899
  _rt.far = 0.2;
6718
- const h = _rt.intersectObjects(cands, false).find(function(x) {
6900
+ const h = castAt(_rt, cands).find(function(x) {
6719
6901
  return x.face;
6720
6902
  });
6721
6903
  if (!h) return null;
@@ -6786,6 +6968,7 @@ function installZoneDecals(kit) {
6786
6968
  const R = c.rand;
6787
6969
  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);
6788
6970
  if (!need) return [];
6971
+ cands = regionCands(c, z, cands).filter(Boolean);
6789
6972
  const S = zoneSurf(c, z, need + 2, R, cands);
6790
6973
  let k = 0;
6791
6974
  const ang0 = R() * PI;
@@ -6866,8 +7049,25 @@ function installZoneDent(kit) {
6866
7049
  }
6867
7050
  function subdivIn(geo, rel, B, maxLen) {
6868
7051
  const a = geo.attributes.position.array;
6869
- const out = [];
6870
- const v = new V3();
7052
+ let out = new Float32Array(a.length + 4096);
7053
+ let used = 0;
7054
+ const push = function(a0, a1, a2, b0, b1, b2, c0, c1, c2) {
7055
+ if (used + 9 > out.length) {
7056
+ const bigger = new Float32Array(out.length * 2);
7057
+ bigger.set(out);
7058
+ out = bigger;
7059
+ }
7060
+ out[used] = a0;
7061
+ out[used + 1] = a1;
7062
+ out[used + 2] = a2;
7063
+ out[used + 3] = b0;
7064
+ out[used + 4] = b1;
7065
+ out[used + 5] = b2;
7066
+ out[used + 6] = c0;
7067
+ out[used + 7] = c1;
7068
+ out[used + 8] = c2;
7069
+ used += 9;
7070
+ };
6871
7071
  const e = 0.15;
6872
7072
  function d(p, q) {
6873
7073
  return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
@@ -6881,7 +7081,7 @@ function installZoneDent(kit) {
6881
7081
  const ca = d(C, A);
6882
7082
  const mx = Math.max(ab, bc, ca);
6883
7083
  if (mx <= maxLen || depth > 9) {
6884
- out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
7084
+ push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
6885
7085
  return;
6886
7086
  }
6887
7087
  if (mx === ab) {
@@ -6898,31 +7098,26 @@ function installZoneDent(kit) {
6898
7098
  tri(F2, Bv, C, depth + 1);
6899
7099
  }
6900
7100
  }
7101
+ const M = rel.elements;
7102
+ const at = function(x, y, z, k) {
7103
+ const w = 1 / (M[3] * x + M[7] * y + M[11] * z + M[15]);
7104
+ 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;
7105
+ };
7106
+ const lo = [B.x0 - e, B.y0 - e, B.z0 - e];
7107
+ const hi = [B.x1 + e, B.y1 + e, B.z1 + e];
6901
7108
  for (let i = 0; i < a.length; i += 9) {
6902
- const A = [a[i], a[i + 1], a[i + 2]];
6903
- const Bv = [a[i + 3], a[i + 4], a[i + 5]];
6904
- const C = [a[i + 6], a[i + 7], a[i + 8]];
6905
- let x0 = 1e9;
6906
- let x1 = -1e9;
6907
- let y0 = 1e9;
6908
- let y1 = -1e9;
6909
- let z0 = 1e9;
6910
- let z1 = -1e9;
6911
- [A, Bv, C].forEach(function(p) {
6912
- v.set(p[0], p[1], p[2]).applyMatrix4(rel);
6913
- x0 = Math.min(x0, v.x);
6914
- x1 = Math.max(x1, v.x);
6915
- y0 = Math.min(y0, v.y);
6916
- y1 = Math.max(y1, v.y);
6917
- z0 = Math.min(z0, v.z);
6918
- z1 = Math.max(z1, v.z);
6919
- });
6920
- 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)
6921
- out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
6922
- else tri(A, Bv, C, 0);
7109
+ let outside = false;
7110
+ for (let k = 0; k < 3 && !outside; k++) {
7111
+ const p = at(a[i], a[i + 1], a[i + 2], k);
7112
+ const q = at(a[i + 3], a[i + 4], a[i + 5], k);
7113
+ const r = at(a[i + 6], a[i + 7], a[i + 8], k);
7114
+ outside = Math.max(p, q, r) < lo[k] || Math.min(p, q, r) > hi[k];
7115
+ }
7116
+ 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]);
7117
+ 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);
6923
7118
  }
6924
7119
  const g = new THREE.BufferGeometry();
6925
- g.setAttribute("position", new THREE.Float32BufferAttribute(out, 3));
7120
+ g.setAttribute("position", new THREE.BufferAttribute(out.slice(0, used), 3));
6926
7121
  g.userData.crease = true;
6927
7122
  g.userData.p0 = null;
6928
7123
  return g;
@@ -6945,6 +7140,17 @@ function installZoneDent(kit) {
6945
7140
  });
6946
7141
  return out;
6947
7142
  }
7143
+ function boxInFrame(B, m, tmp) {
7144
+ const r = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
7145
+ for (let i = 0; i < 8; i++) {
7146
+ tmp.set(i & 1 ? B.x1 : B.x0, i & 2 ? B.y1 : B.y0, i & 4 ? B.z1 : B.z0).applyMatrix4(m);
7147
+ for (let k = 0; k < 3; k++) {
7148
+ r[k] = Math.min(r[k], tmp.getComponent(k) - 1e-4);
7149
+ r[k + 3] = Math.max(r[k + 3], tmp.getComponent(k) + 1e-4);
7150
+ }
7151
+ }
7152
+ return r;
7153
+ }
6948
7154
  function zoneDent(c, z, dents, dirty, opt) {
6949
7155
  opt = opt || {};
6950
7156
  const B = z.box;
@@ -6999,6 +7205,7 @@ function installZoneDent(kit) {
6999
7205
  g = msh.geometry = g.clone();
7000
7206
  msh.userData.zCloned = true;
7001
7207
  }
7208
+ let boundsDue = false;
7002
7209
  const nonIdx = !g.index;
7003
7210
  const onlyPos = Object.keys(g.attributes).every(function(k) {
7004
7211
  return k === "position" || k === "normal";
@@ -7007,15 +7214,17 @@ function installZoneDent(kit) {
7007
7214
  const ng = subdivIn(g, rel, B, opt.sub || 0.075);
7008
7215
  g.dispose();
7009
7216
  g = msh.geometry = ng;
7010
- ng.computeBoundingSphere();
7011
- ng.computeBoundingBox();
7217
+ boundsDue = true;
7012
7218
  dirty.add(msh);
7013
7219
  }
7014
7220
  irel.copy(rel).invert();
7015
7221
  const pos = g.attributes.position;
7016
7222
  let changed = false;
7223
+ const near = boxInFrame(B, irel, v);
7017
7224
  for (let i = 0; i < pos.count; i++) {
7018
- v.fromBufferAttribute(pos, i).applyMatrix4(rel);
7225
+ v.fromBufferAttribute(pos, i);
7226
+ 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;
7227
+ v.applyMatrix4(rel);
7019
7228
  const f = field(v);
7020
7229
  if (f <= 1e-5) continue;
7021
7230
  v.addScaledVector(d, f);
@@ -7036,9 +7245,11 @@ function installZoneDent(kit) {
7036
7245
  }
7037
7246
  if (changed) {
7038
7247
  pos.needsUpdate = true;
7248
+ dirty.add(msh);
7249
+ }
7250
+ if (changed || boundsDue) {
7039
7251
  g.computeBoundingSphere();
7040
7252
  g.computeBoundingBox();
7041
- dirty.add(msh);
7042
7253
  }
7043
7254
  });
7044
7255
  const dset = new Set(c.deform);
@@ -10141,6 +10352,20 @@ function createVehicleKit(options) {
10141
10352
  else kit.applyArmor(c);
10142
10353
  }
10143
10354
  if (zoneState == null && st === "damaged" && kit.config.damagedScenario) zoneState = kit.zoneScenario(c, kit.config.damagedScenario);
10355
+ else if (zoneState && zoneState.scenario != null) {
10356
+ c.scenario = zoneState.scenario;
10357
+ let fromScenario = { health: {}, flags: {} };
10358
+ try {
10359
+ fromScenario = kit.zoneScenario(c, zoneState.scenario);
10360
+ } catch (e) {
10361
+ ;
10362
+ (c.zoneErrors = c.zoneErrors || []).push("scenario: " + (e && e.message));
10363
+ }
10364
+ zoneState = {
10365
+ health: Object.assign({}, fromScenario.health, zoneState.health),
10366
+ flags: Object.assign({}, fromScenario.flags, zoneState.flags)
10367
+ };
10368
+ }
10144
10369
  if (zoneState) kit.applyZones(c, zoneState);
10145
10370
  else {
10146
10371
  c.zoneState = { health: {}, flags: {} };
@@ -12097,7 +12322,7 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
12097
12322
  const reset = () => {
12098
12323
  const old = c;
12099
12324
  const parent = old.root.parent;
12100
- const next = kit.build(old.key, old.state);
12325
+ const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
12101
12326
  if (parent) {
12102
12327
  next.root.position.copy(old.root.position);
12103
12328
  next.root.quaternion.copy(old.root.quaternion);
@@ -12154,7 +12379,8 @@ function createVehicleDestructible(kit, vehicleCtx, options = {}) {
12154
12379
  // src/destructible/item.ts
12155
12380
  function buildVehicleItem(kit, key, options = {}) {
12156
12381
  const THREE = kit.THREE;
12157
- const vehicle = options.lod ? kit.build(key, options.state ?? "intact", void 0, { lod: true }) : kit.build(key, options.state ?? "intact");
12382
+ const zoneState = options.scenario != null ? { scenario: options.scenario } : void 0;
12383
+ const vehicle = options.lod ? kit.build(key, options.state ?? "intact", zoneState, { lod: true }) : kit.build(key, options.state ?? "intact", zoneState);
12158
12384
  const m = vehicle.meta;
12159
12385
  const root = new THREE.Group();
12160
12386
  root.name = key;