@adatechnology/game-vehicles 0.3.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 +6 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.global.js +284 -60
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +284 -60
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,9 @@ scene.remove(c.root); kit.dispose(c)
|
|
|
64
64
|
const hurt = kit.build('meteor', 'intact', state)
|
|
65
65
|
scene.add(hurt.root)
|
|
66
66
|
|
|
67
|
+
// ...or name a registered scenario and build it in one call (explicit health / flags given alongside win)
|
|
68
|
+
const wreck = kit.build('meteor', 'intact', { scenario: 'burnt' })
|
|
69
|
+
|
|
67
70
|
// 4. animate (particles, fluids, hood, rollover, explosions)
|
|
68
71
|
kit.tick(hurt, dt)
|
|
69
72
|
```
|
|
@@ -89,7 +92,7 @@ and a band decided by the health:
|
|
|
89
92
|
| 3 | `destroyed` | 1 to 25 | Heavy deformation, parts fall off |
|
|
90
93
|
| 4 | `torn_off` | 0 | The part is gone |
|
|
91
94
|
|
|
92
|
-
Bands only change the look when the band changes; `kit.build(key, state, zoneState)` rebuilds the vehicle and reapplies every zone.
|
|
95
|
+
Bands only change the look when the band changes; `kit.build(key, state, zoneState)` rebuilds the vehicle and reapplies every zone. `zoneState` may also carry `scenario: 'id or name'`: the scenario is computed on the vehicle being built (no probe build) and any `health` / `flags` given with it are merged on top. An unknown scenario damages nothing, like `zoneScenario`.
|
|
93
96
|
|
|
94
97
|
**Content packs.** A pack is a plugin: `{ name, configure, install(kit) }`. `configure` accepts everything in the configuration table below and
|
|
95
98
|
`install` can call `kit.register(...)`, `kit.scenario(...)`, `kit.defineFluid(...)`, `kit.on(...)` and so on. The engine never imports a pack.
|
|
@@ -139,7 +142,7 @@ created with, so `kit.t('mypack.some.key')` reads from it, with English as the f
|
|
|
139
142
|
| Area | Methods |
|
|
140
143
|
|---|---|
|
|
141
144
|
| Registry | `register(spec, build)`, `find(key)`, `fleet`, `configure`, `plugin`, `on`/`hook`, `scenario`, `defineFluid` |
|
|
142
|
-
| Lifecycle | `build(key, state?, zoneState?)
|
|
145
|
+
| Lifecycle | `build(key, state?, zoneState?)` (`zoneState.scenario` runs a scenario), `dispose(c)`, `tick(c, dt)`, `settle(c, seconds)`, `defaultDamage(c)` |
|
|
143
146
|
| Zones | `bandOf(health)`, `zonesOf(c)`, `applyZones(c, state)`, `zoneScenario(c, id)`, `zoneOverall(c)`, `zoneAt(c, point)`, `zoneDamageAt(c, point, dir, force)`, `zonePoint(c, zone)`, `zoneEffect(zone, health?)`, `zoneOwner` |
|
|
144
147
|
| Events | `impact(c, point, dir, force, options?)`, `zoneImpact(c, side, force)` (side: `front`, `rear`, `left`, `right` or `rolled`), `explode(c, options?)`, `blastDamage(c, amount)`, `roll(c, side?)`, `setHood(c, open)` |
|
|
145
148
|
| Fluids and particles | `splat`, `puddle`, `wipe(c, mode)` (`wiper` or `rain`), `spawn`, `burst`, `addEmitter` |
|
|
@@ -175,6 +178,7 @@ kit.scenario({
|
|
|
175
178
|
})
|
|
176
179
|
const result = kit.zoneScenario(c, 'front') // { health, flags, scenario }
|
|
177
180
|
const hurt = kit.build('meteor', 'intact', result)
|
|
181
|
+
const same = kit.build('meteor', 'intact', { scenario: 'front' }) // the two steps in one call
|
|
178
182
|
```
|
|
179
183
|
|
|
180
184
|
`x` has `c`, `meta`, `front`, `rear`, `length`, `width`, `clearance`, `top`, `rand()`, `set(zone, health)`, `flags`, `health`, `center` (of the zone
|
package/dist/index.d.ts
CHANGED
|
@@ -337,6 +337,8 @@ interface VehicleContext {
|
|
|
337
337
|
meta: VehicleMeta;
|
|
338
338
|
zones: DamageZone[];
|
|
339
339
|
zoneState: ZoneState;
|
|
340
|
+
/** The scenario the vehicle was built in (`kit.build(key, state, { scenario })`), so a rebuild keeps it. */
|
|
341
|
+
scenario?: string;
|
|
340
342
|
/** Deterministic random generator seeded from the vehicle key and state. */
|
|
341
343
|
rand: () => number;
|
|
342
344
|
parts: VehiclePart[];
|
|
@@ -418,6 +420,11 @@ interface ZoneState {
|
|
|
418
420
|
health: Record<string, number>;
|
|
419
421
|
flags: Record<string, boolean>;
|
|
420
422
|
}
|
|
423
|
+
/** The zone-state argument of `kit.build`: a `ZoneState` plus an optional scenario to compute on the vehicle being built. */
|
|
424
|
+
interface BuildZoneState extends Partial<ZoneState> {
|
|
425
|
+
/** Id or name of a registered scenario (e.g. the fleet's `burnt`); explicit `health` / `flags` override its result. */
|
|
426
|
+
scenario?: string;
|
|
427
|
+
}
|
|
421
428
|
interface ScenarioResult {
|
|
422
429
|
health: Record<string, number>;
|
|
423
430
|
flags: Record<string, boolean>;
|
|
@@ -662,7 +669,7 @@ interface VehicleKit {
|
|
|
662
669
|
defineFluid(key: string, def: FluidDefinition): FluidDefinition;
|
|
663
670
|
on(event: string, fn: (...args: any[]) => void): VehicleKit;
|
|
664
671
|
hook(event: string, ...args: any[]): void;
|
|
665
|
-
build(key: string, state?: BuildState, zoneState?:
|
|
672
|
+
build(key: string, state?: BuildState, zoneState?: BuildZoneState, options?: BuildOptions): VehicleContext;
|
|
666
673
|
/** The damageable parts of a built vehicle as boxes (optionally in the frame of `matrix`). */
|
|
667
674
|
damageables(c: VehicleContext, matrix?: ThreeObject): Damageable[];
|
|
668
675
|
dispose(c: VehicleContext): void;
|
|
@@ -894,6 +901,8 @@ interface VehicleItemOptions {
|
|
|
894
901
|
state?: BuildState;
|
|
895
902
|
/** Build in the light mode of the kit (`kit.lod`): fewer segments and no interior, for crowds and for budgets. Default off. */
|
|
896
903
|
lod?: boolean;
|
|
904
|
+
/** A registered damage scenario (id or name, e.g. the fleet's `burnt`) built into the vehicle, through `kit.build(key, state, { scenario })`. */
|
|
905
|
+
scenario?: string;
|
|
897
906
|
}
|
|
898
907
|
interface VehicleItem {
|
|
899
908
|
/** Add this to the scene: origin at the centre of the footprint on the floor, front facing +z. */
|
|
@@ -908,4 +917,4 @@ interface VehicleItem {
|
|
|
908
917
|
*/
|
|
909
918
|
declare function buildVehicleItem(kit: VehicleKit, key: string, options?: VehicleItemOptions): VehicleItem;
|
|
910
919
|
|
|
911
|
-
export { type Band, type BandId, type BandIndex, type BandOverride, type BuildFunction, type BuildOptions, type BuildState, type DamageMapOptions, type DamageZone, type Damageable, type DamageableKind, type DamageableMaterial, type DamageableSide, type ExplodeOptions, type FlagEffect, type FluidDefinition, type ImpactOptions, JOINT_RULES, type JointDef, type KitConfiguration, type KitInternals, type KitTexts, LEGACY_STATES, LEGACY_ZONE_IDS, type LocalBox, type LocaleStrings, type LodSettings, type OverallHealth, type PartDef, type PartLabel, type PartRole, type PartialLocaleStrings, type Plugin, type ResolvedConfiguration, SEED_SALTS, type ScenarioContext, type ScenarioDefinition, type ScenarioResult, type SplatOptions, type ThreeObject, type ThreeVector, type Translate, type UiHelpers, type VehicleContext, type VehicleDestructible, type VehicleDestructibleOptions, type VehicleItem, type VehicleItemOptions, type VehicleKit, type VehicleKitOptions, type VehicleMeta, type VehicleModel, type VehiclePart, type VehicleSpec, type VehicleStatus, type ZoneDamageEntry, type ZoneEffect, type ZoneState, buildVehicleItem, buildVehicleModel, clamp, createLod, createTranslate, createVehicleDestructible, createVehicleKit, defaultDamageableKinds, defaultLodSettings, format, hash, legacyGlassId, legacyLightId, legacyZoneId, listLocales, registerLegacySeeds, registerLocale, resolveStrings, rng, smooth, strHash, wrapThreeForLod };
|
|
920
|
+
export { type Band, type BandId, type BandIndex, type BandOverride, type BuildFunction, type BuildOptions, type BuildState, type BuildZoneState, type DamageMapOptions, type DamageZone, type Damageable, type DamageableKind, type DamageableMaterial, type DamageableSide, type ExplodeOptions, type FlagEffect, type FluidDefinition, type ImpactOptions, JOINT_RULES, type JointDef, type KitConfiguration, type KitInternals, type KitTexts, LEGACY_STATES, LEGACY_ZONE_IDS, type LocalBox, type LocaleStrings, type LodSettings, type OverallHealth, type PartDef, type PartLabel, type PartRole, type PartialLocaleStrings, type Plugin, type ResolvedConfiguration, SEED_SALTS, type ScenarioContext, type ScenarioDefinition, type ScenarioResult, type SplatOptions, type ThreeObject, type ThreeVector, type Translate, type UiHelpers, type VehicleContext, type VehicleDestructible, type VehicleDestructibleOptions, type VehicleItem, type VehicleItemOptions, type VehicleKit, type VehicleKitOptions, type VehicleMeta, type VehicleModel, type VehiclePart, type VehicleSpec, type VehicleStatus, type ZoneDamageEntry, type ZoneEffect, type ZoneState, buildVehicleItem, buildVehicleModel, clamp, createLod, createTranslate, createVehicleDestructible, createVehicleKit, defaultDamageableKinds, defaultLodSettings, format, hash, legacyGlassId, legacyLightId, legacyZoneId, listLocales, registerLegacySeeds, registerLocale, resolveStrings, rng, smooth, strHash, wrapThreeForLod };
|
package/dist/index.global.js
CHANGED
|
@@ -2501,46 +2501,79 @@ var GameVehicles = (() => {
|
|
|
2501
2501
|
}
|
|
2502
2502
|
const p = geo.attributes.position;
|
|
2503
2503
|
const n = p.count;
|
|
2504
|
-
const
|
|
2505
|
-
const
|
|
2506
|
-
const
|
|
2507
|
-
const
|
|
2508
|
-
const C = new V3();
|
|
2509
|
-
const e1 = new V3();
|
|
2510
|
-
const e2 = new V3();
|
|
2504
|
+
const faces = n / 3;
|
|
2505
|
+
const FN = new Float64Array(faces * 3);
|
|
2506
|
+
const map = /* @__PURE__ */ new Map();
|
|
2507
|
+
const RANGE = 65536;
|
|
2511
2508
|
function key(i) {
|
|
2512
|
-
|
|
2509
|
+
const x = Math.round(p.getX(i) * 2e3);
|
|
2510
|
+
const y = Math.round(p.getY(i) * 2e3);
|
|
2511
|
+
const z = Math.round(p.getZ(i) * 2e3);
|
|
2512
|
+
if (Math.abs(x) < RANGE && Math.abs(y) < RANGE && Math.abs(z) < RANGE) return ((x + RANGE) * 131072 + (y + RANGE)) * 131072 + (z + RANGE);
|
|
2513
|
+
return x + "," + y + "," + z;
|
|
2513
2514
|
}
|
|
2514
2515
|
const keys = new Array(n);
|
|
2515
|
-
for (let f = 0; f <
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
const
|
|
2520
|
-
|
|
2521
|
-
|
|
2516
|
+
for (let f = 0; f < faces; f++) {
|
|
2517
|
+
const ax = p.getX(3 * f);
|
|
2518
|
+
const ay = p.getY(3 * f);
|
|
2519
|
+
const az = p.getZ(3 * f);
|
|
2520
|
+
const bx = p.getX(3 * f + 1);
|
|
2521
|
+
const by = p.getY(3 * f + 1);
|
|
2522
|
+
const bz = p.getZ(3 * f + 1);
|
|
2523
|
+
const cx = p.getX(3 * f + 2);
|
|
2524
|
+
const cy = p.getY(3 * f + 2);
|
|
2525
|
+
const cz = p.getZ(3 * f + 2);
|
|
2526
|
+
const e1x = cx - bx;
|
|
2527
|
+
const e1y = cy - by;
|
|
2528
|
+
const e1z = cz - bz;
|
|
2529
|
+
const e2x = ax - bx;
|
|
2530
|
+
const e2y = ay - by;
|
|
2531
|
+
const e2z = az - bz;
|
|
2532
|
+
let nx = e1y * e2z - e1z * e2y;
|
|
2533
|
+
let ny = e1z * e2x - e1x * e2z;
|
|
2534
|
+
let nz = e1x * e2y - e1y * e2x;
|
|
2535
|
+
if (nx * nx + ny * ny + nz * nz > 1e-20) {
|
|
2536
|
+
const inv = 1 / (Math.sqrt(nx * nx + ny * ny + nz * nz) || 1);
|
|
2537
|
+
nx *= inv;
|
|
2538
|
+
ny *= inv;
|
|
2539
|
+
nz *= inv;
|
|
2540
|
+
}
|
|
2541
|
+
FN[3 * f] = nx;
|
|
2542
|
+
FN[3 * f + 1] = ny;
|
|
2543
|
+
FN[3 * f + 2] = nz;
|
|
2522
2544
|
for (let k = 0; k < 3; k++) {
|
|
2523
2545
|
const kk = key(3 * f + k);
|
|
2524
2546
|
keys[3 * f + k] = kk;
|
|
2525
|
-
|
|
2547
|
+
const list2 = map.get(kk);
|
|
2548
|
+
if (list2) list2.push(f);
|
|
2549
|
+
else map.set(kk, [f]);
|
|
2526
2550
|
}
|
|
2527
2551
|
}
|
|
2528
2552
|
const cs = Math.cos(deg * PI / 180);
|
|
2529
2553
|
const out = new Float32Array(n * 3);
|
|
2530
|
-
const s = new V3();
|
|
2531
2554
|
for (let i = 0; i < n; i++) {
|
|
2532
|
-
const fi = i / 3 | 0;
|
|
2533
|
-
const list2 = map
|
|
2534
|
-
|
|
2555
|
+
const fi = (i / 3 | 0) * 3;
|
|
2556
|
+
const list2 = map.get(keys[i]);
|
|
2557
|
+
let sx = 0;
|
|
2558
|
+
let sy = 0;
|
|
2559
|
+
let sz = 0;
|
|
2535
2560
|
for (let j = 0; j < list2.length; j++) {
|
|
2536
|
-
const g =
|
|
2537
|
-
if (g
|
|
2561
|
+
const g = list2[j] * 3;
|
|
2562
|
+
if (FN[g] * FN[fi] + FN[g + 1] * FN[fi + 1] + FN[g + 2] * FN[fi + 2] >= cs) {
|
|
2563
|
+
sx += FN[g];
|
|
2564
|
+
sy += FN[g + 1];
|
|
2565
|
+
sz += FN[g + 2];
|
|
2566
|
+
}
|
|
2538
2567
|
}
|
|
2539
|
-
if (
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2568
|
+
if (sx * sx + sy * sy + sz * sz < 1e-20) {
|
|
2569
|
+
sx = FN[fi];
|
|
2570
|
+
sy = FN[fi + 1];
|
|
2571
|
+
sz = FN[fi + 2];
|
|
2572
|
+
}
|
|
2573
|
+
const inv = 1 / (Math.sqrt(sx * sx + sy * sy + sz * sz) || 1);
|
|
2574
|
+
out[3 * i] = sx * inv;
|
|
2575
|
+
out[3 * i + 1] = sy * inv;
|
|
2576
|
+
out[3 * i + 2] = sz * inv;
|
|
2544
2577
|
}
|
|
2545
2578
|
geo.setAttribute("normal", new THREE.BufferAttribute(out, 3));
|
|
2546
2579
|
geo.userData.crease = true;
|
|
@@ -8198,6 +8231,153 @@ var GameVehicles = (() => {
|
|
|
8198
8231
|
return hole;
|
|
8199
8232
|
}
|
|
8200
8233
|
const _zr = new THREE.Raycaster();
|
|
8234
|
+
const PROXY_MIN_TRIANGLES = 500;
|
|
8235
|
+
const STROKE_REACH = 0.6;
|
|
8236
|
+
const _pv = new V3();
|
|
8237
|
+
const _pm = new THREE.Matrix4();
|
|
8238
|
+
function decalRegion(c, z) {
|
|
8239
|
+
const B = z.box;
|
|
8240
|
+
const lo = [0, 1, 2].map(function(k) {
|
|
8241
|
+
return I.boxLo(B, k) - STROKE_REACH;
|
|
8242
|
+
});
|
|
8243
|
+
const hi = [0, 1, 2].map(function(k) {
|
|
8244
|
+
return I.boxHi(B, k) + STROKE_REACH;
|
|
8245
|
+
});
|
|
8246
|
+
const a = axisOf(z.dir);
|
|
8247
|
+
const dn = z.dir.clone().normalize();
|
|
8248
|
+
const sg = z.dir.getComponent(a) > 0 ? 1 : -1;
|
|
8249
|
+
const outer = sg > 0 ? I.boxLo(B, a) - 0.6 : I.boxHi(B, a) + 0.6;
|
|
8250
|
+
const far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
8251
|
+
for (let i = 0; i < 8; i++) {
|
|
8252
|
+
const p = new V3();
|
|
8253
|
+
p.setComponent(a, outer);
|
|
8254
|
+
[0, 1, 2].filter(function(k) {
|
|
8255
|
+
return k !== a;
|
|
8256
|
+
}).forEach(function(k, j) {
|
|
8257
|
+
p.setComponent(k, i >> j & 1 ? I.boxHi(B, k) : I.boxLo(B, k));
|
|
8258
|
+
});
|
|
8259
|
+
for (let e = 0; e < 2; e++) {
|
|
8260
|
+
const q = e ? p.clone().addScaledVector(dn, far) : p;
|
|
8261
|
+
for (let k = 0; k < 3; k++) {
|
|
8262
|
+
lo[k] = Math.min(lo[k], q.getComponent(k) - 0.05);
|
|
8263
|
+
hi[k] = Math.max(hi[k], q.getComponent(k) + 0.05);
|
|
8264
|
+
}
|
|
8265
|
+
}
|
|
8266
|
+
}
|
|
8267
|
+
return { lo, hi };
|
|
8268
|
+
}
|
|
8269
|
+
function regionCands(c, z, cands) {
|
|
8270
|
+
if (!cands.some(heavy)) return cands;
|
|
8271
|
+
const R = decalRegion(c, z);
|
|
8272
|
+
const Mw = c.vehicle.matrixWorld;
|
|
8273
|
+
return cands.map(function(o) {
|
|
8274
|
+
if (!heavy(o)) return o;
|
|
8275
|
+
if (!o.geometry.boundingSphere) o.geometry.computeBoundingSphere();
|
|
8276
|
+
if (!o.geometry.boundingBox) o.geometry.computeBoundingBox();
|
|
8277
|
+
return proxyIn(o, Mw, R);
|
|
8278
|
+
});
|
|
8279
|
+
}
|
|
8280
|
+
function heavy(o) {
|
|
8281
|
+
const g = o.geometry;
|
|
8282
|
+
const pos = g && g.attributes && g.attributes.position;
|
|
8283
|
+
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;
|
|
8284
|
+
}
|
|
8285
|
+
function proxyIn(o, Mw, R) {
|
|
8286
|
+
_pm.copy(o.matrixWorld).invert().multiply(Mw);
|
|
8287
|
+
const lo = [Infinity, Infinity, Infinity];
|
|
8288
|
+
const hi = [-Infinity, -Infinity, -Infinity];
|
|
8289
|
+
for (let i = 0; i < 8; i++) {
|
|
8290
|
+
_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);
|
|
8291
|
+
for (let k = 0; k < 3; k++) {
|
|
8292
|
+
lo[k] = Math.min(lo[k], _pv.getComponent(k));
|
|
8293
|
+
hi[k] = Math.max(hi[k], _pv.getComponent(k));
|
|
8294
|
+
}
|
|
8295
|
+
}
|
|
8296
|
+
const g = o.geometry;
|
|
8297
|
+
const P = g.attributes.position.array;
|
|
8298
|
+
const ix = g.index ? g.index.array : null;
|
|
8299
|
+
const n = ix ? ix.length : P.length / 3;
|
|
8300
|
+
const keep = new Uint32Array(n - n % 3);
|
|
8301
|
+
let nk = 0;
|
|
8302
|
+
for (let t = 0; t + 2 < n; t += 3) {
|
|
8303
|
+
const a = (ix ? ix[t] : t) * 3;
|
|
8304
|
+
const b = (ix ? ix[t + 1] : t + 1) * 3;
|
|
8305
|
+
const d = (ix ? ix[t + 2] : t + 2) * 3;
|
|
8306
|
+
let out = false;
|
|
8307
|
+
for (let k = 0; k < 3 && !out; k++) {
|
|
8308
|
+
const u = P[a + k];
|
|
8309
|
+
const v = P[b + k];
|
|
8310
|
+
const w = P[d + k];
|
|
8311
|
+
out = Math.max(u, v, w) < lo[k] || Math.min(u, v, w) > hi[k];
|
|
8312
|
+
}
|
|
8313
|
+
if (!out) {
|
|
8314
|
+
keep[nk++] = ix ? ix[t] : t;
|
|
8315
|
+
keep[nk++] = ix ? ix[t + 1] : t + 1;
|
|
8316
|
+
keep[nk++] = ix ? ix[t + 2] : t + 2;
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
if (!nk) return null;
|
|
8320
|
+
const kept = keep.slice(0, nk);
|
|
8321
|
+
const box2 = new Float32Array(kept.length / 3 * 6);
|
|
8322
|
+
for (let t = 0, j = 0; t < kept.length; t += 3, j += 6) {
|
|
8323
|
+
const a = kept[t] * 3;
|
|
8324
|
+
const b = kept[t + 1] * 3;
|
|
8325
|
+
const d = kept[t + 2] * 3;
|
|
8326
|
+
for (let k = 0; k < 3; k++) {
|
|
8327
|
+
box2[j + k] = Math.min(P[a + k], P[b + k], P[d + k]);
|
|
8328
|
+
box2[j + 3 + k] = Math.max(P[a + k], P[b + k], P[d + k]);
|
|
8329
|
+
}
|
|
8330
|
+
}
|
|
8331
|
+
const pg = new THREE.BufferGeometry();
|
|
8332
|
+
pg.setAttribute("position", g.attributes.position);
|
|
8333
|
+
pg.setIndex(new THREE.BufferAttribute(new Uint32Array(kept.length), 1));
|
|
8334
|
+
pg.boundingSphere = g.boundingSphere;
|
|
8335
|
+
pg.boundingBox = g.boundingBox;
|
|
8336
|
+
const proxy = new THREE.Mesh(pg, o.material);
|
|
8337
|
+
proxy.layers.mask = o.layers.mask;
|
|
8338
|
+
proxy.proxyOf = o;
|
|
8339
|
+
proxy.kept = kept;
|
|
8340
|
+
proxy.keptBox = box2;
|
|
8341
|
+
return proxy;
|
|
8342
|
+
}
|
|
8343
|
+
function narrowTo(rc, proxy) {
|
|
8344
|
+
const o = proxy.proxyOf;
|
|
8345
|
+
const ray = rc.ray;
|
|
8346
|
+
_pm.copy(o.matrixWorld).invert();
|
|
8347
|
+
_pv.copy(ray.origin).applyMatrix4(_pm);
|
|
8348
|
+
const x0 = _pv.x;
|
|
8349
|
+
const y0 = _pv.y;
|
|
8350
|
+
const z0 = _pv.z;
|
|
8351
|
+
_pv.copy(ray.direction).multiplyScalar(rc.far).add(ray.origin).applyMatrix4(_pm);
|
|
8352
|
+
const lo0 = Math.min(x0, _pv.x) - 1e-4;
|
|
8353
|
+
const lo1 = Math.min(y0, _pv.y) - 1e-4;
|
|
8354
|
+
const lo2 = Math.min(z0, _pv.z) - 1e-4;
|
|
8355
|
+
const hi0 = Math.max(x0, _pv.x) + 1e-4;
|
|
8356
|
+
const hi1 = Math.max(y0, _pv.y) + 1e-4;
|
|
8357
|
+
const hi2 = Math.max(z0, _pv.z) + 1e-4;
|
|
8358
|
+
const K = proxy.kept;
|
|
8359
|
+
const X = proxy.keptBox;
|
|
8360
|
+
const dst = proxy.geometry.index.array;
|
|
8361
|
+
let m = 0;
|
|
8362
|
+
for (let t = 0, j = 0; t < K.length; t += 3, j += 6) {
|
|
8363
|
+
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;
|
|
8364
|
+
dst[m++] = K[t];
|
|
8365
|
+
dst[m++] = K[t + 1];
|
|
8366
|
+
dst[m++] = K[t + 2];
|
|
8367
|
+
}
|
|
8368
|
+
proxy.geometry.setDrawRange(0, m);
|
|
8369
|
+
}
|
|
8370
|
+
function castAt(rc, cands) {
|
|
8371
|
+
for (let i = 0; i < cands.length; i++) {
|
|
8372
|
+
const q = cands[i];
|
|
8373
|
+
if (!q.proxyOf) continue;
|
|
8374
|
+
q.matrixWorld.copy(q.proxyOf.matrixWorld);
|
|
8375
|
+
narrowTo(rc, q);
|
|
8376
|
+
}
|
|
8377
|
+
const hits = rc.intersectObjects(cands, false);
|
|
8378
|
+
for (let i = 0; i < hits.length; i++) if (hits[i].object.proxyOf) hits[i].object = hits[i].object.proxyOf;
|
|
8379
|
+
return hits;
|
|
8380
|
+
}
|
|
8201
8381
|
function zoneCands(c, z, inv, glassToo) {
|
|
8202
8382
|
const out = [];
|
|
8203
8383
|
c.vehicle.traverse(function(o) {
|
|
@@ -8250,7 +8430,7 @@ var GameVehicles = (() => {
|
|
|
8250
8430
|
});
|
|
8251
8431
|
_zr.set(org.clone().applyMatrix4(Mw), d.clone().transformDirection(Mw));
|
|
8252
8432
|
_zr.far = 0.6 + (I.boxHi(B, a) - I.boxLo(B, a)) + 0.05;
|
|
8253
|
-
const hits = _zr
|
|
8433
|
+
const hits = castAt(_zr, cands);
|
|
8254
8434
|
for (let i = 0; i < hits.length; i++) {
|
|
8255
8435
|
const h = hits[i];
|
|
8256
8436
|
if (!h.face) continue;
|
|
@@ -8278,7 +8458,7 @@ var GameVehicles = (() => {
|
|
|
8278
8458
|
const q = s.p.clone().addScaledVector(t, len * 0.5 * k / M);
|
|
8279
8459
|
_rt.set(q.clone().addScaledVector(n, 0.08).applyMatrix4(Mw), n.clone().negate().transformDirection(Mw));
|
|
8280
8460
|
_rt.far = 0.2;
|
|
8281
|
-
const h = _rt
|
|
8461
|
+
const h = castAt(_rt, cands).find(function(x) {
|
|
8282
8462
|
return x.face;
|
|
8283
8463
|
});
|
|
8284
8464
|
if (!h) return null;
|
|
@@ -8349,6 +8529,7 @@ var GameVehicles = (() => {
|
|
|
8349
8529
|
const R = c.rand;
|
|
8350
8530
|
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);
|
|
8351
8531
|
if (!need) return [];
|
|
8532
|
+
cands = regionCands(c, z, cands).filter(Boolean);
|
|
8352
8533
|
const S = zoneSurf(c, z, need + 2, R, cands);
|
|
8353
8534
|
let k = 0;
|
|
8354
8535
|
const ang0 = R() * PI;
|
|
@@ -8429,8 +8610,25 @@ var GameVehicles = (() => {
|
|
|
8429
8610
|
}
|
|
8430
8611
|
function subdivIn(geo, rel, B, maxLen) {
|
|
8431
8612
|
const a = geo.attributes.position.array;
|
|
8432
|
-
|
|
8433
|
-
|
|
8613
|
+
let out = new Float32Array(a.length + 4096);
|
|
8614
|
+
let used = 0;
|
|
8615
|
+
const push = function(a0, a1, a2, b0, b1, b2, c0, c1, c2) {
|
|
8616
|
+
if (used + 9 > out.length) {
|
|
8617
|
+
const bigger = new Float32Array(out.length * 2);
|
|
8618
|
+
bigger.set(out);
|
|
8619
|
+
out = bigger;
|
|
8620
|
+
}
|
|
8621
|
+
out[used] = a0;
|
|
8622
|
+
out[used + 1] = a1;
|
|
8623
|
+
out[used + 2] = a2;
|
|
8624
|
+
out[used + 3] = b0;
|
|
8625
|
+
out[used + 4] = b1;
|
|
8626
|
+
out[used + 5] = b2;
|
|
8627
|
+
out[used + 6] = c0;
|
|
8628
|
+
out[used + 7] = c1;
|
|
8629
|
+
out[used + 8] = c2;
|
|
8630
|
+
used += 9;
|
|
8631
|
+
};
|
|
8434
8632
|
const e = 0.15;
|
|
8435
8633
|
function d(p, q) {
|
|
8436
8634
|
return Math.hypot(p[0] - q[0], p[1] - q[1], p[2] - q[2]);
|
|
@@ -8444,7 +8642,7 @@ var GameVehicles = (() => {
|
|
|
8444
8642
|
const ca = d(C, A);
|
|
8445
8643
|
const mx = Math.max(ab, bc, ca);
|
|
8446
8644
|
if (mx <= maxLen || depth > 9) {
|
|
8447
|
-
|
|
8645
|
+
push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
8448
8646
|
return;
|
|
8449
8647
|
}
|
|
8450
8648
|
if (mx === ab) {
|
|
@@ -8461,31 +8659,26 @@ var GameVehicles = (() => {
|
|
|
8461
8659
|
tri(F2, Bv, C, depth + 1);
|
|
8462
8660
|
}
|
|
8463
8661
|
}
|
|
8662
|
+
const M = rel.elements;
|
|
8663
|
+
const at = function(x, y, z, k) {
|
|
8664
|
+
const w = 1 / (M[3] * x + M[7] * y + M[11] * z + M[15]);
|
|
8665
|
+
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;
|
|
8666
|
+
};
|
|
8667
|
+
const lo = [B.x0 - e, B.y0 - e, B.z0 - e];
|
|
8668
|
+
const hi = [B.x1 + e, B.y1 + e, B.z1 + e];
|
|
8464
8669
|
for (let i = 0; i < a.length; i += 9) {
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
[A, Bv, C].forEach(function(p) {
|
|
8475
|
-
v.set(p[0], p[1], p[2]).applyMatrix4(rel);
|
|
8476
|
-
x0 = Math.min(x0, v.x);
|
|
8477
|
-
x1 = Math.max(x1, v.x);
|
|
8478
|
-
y0 = Math.min(y0, v.y);
|
|
8479
|
-
y1 = Math.max(y1, v.y);
|
|
8480
|
-
z0 = Math.min(z0, v.z);
|
|
8481
|
-
z1 = Math.max(z1, v.z);
|
|
8482
|
-
});
|
|
8483
|
-
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)
|
|
8484
|
-
out.push(A[0], A[1], A[2], Bv[0], Bv[1], Bv[2], C[0], C[1], C[2]);
|
|
8485
|
-
else tri(A, Bv, C, 0);
|
|
8670
|
+
let outside = false;
|
|
8671
|
+
for (let k = 0; k < 3 && !outside; k++) {
|
|
8672
|
+
const p = at(a[i], a[i + 1], a[i + 2], k);
|
|
8673
|
+
const q = at(a[i + 3], a[i + 4], a[i + 5], k);
|
|
8674
|
+
const r = at(a[i + 6], a[i + 7], a[i + 8], k);
|
|
8675
|
+
outside = Math.max(p, q, r) < lo[k] || Math.min(p, q, r) > hi[k];
|
|
8676
|
+
}
|
|
8677
|
+
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]);
|
|
8678
|
+
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);
|
|
8486
8679
|
}
|
|
8487
8680
|
const g = new THREE.BufferGeometry();
|
|
8488
|
-
g.setAttribute("position", new THREE.
|
|
8681
|
+
g.setAttribute("position", new THREE.BufferAttribute(out.slice(0, used), 3));
|
|
8489
8682
|
g.userData.crease = true;
|
|
8490
8683
|
g.userData.p0 = null;
|
|
8491
8684
|
return g;
|
|
@@ -8508,6 +8701,17 @@ var GameVehicles = (() => {
|
|
|
8508
8701
|
});
|
|
8509
8702
|
return out;
|
|
8510
8703
|
}
|
|
8704
|
+
function boxInFrame(B, m, tmp) {
|
|
8705
|
+
const r = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
|
|
8706
|
+
for (let i = 0; i < 8; i++) {
|
|
8707
|
+
tmp.set(i & 1 ? B.x1 : B.x0, i & 2 ? B.y1 : B.y0, i & 4 ? B.z1 : B.z0).applyMatrix4(m);
|
|
8708
|
+
for (let k = 0; k < 3; k++) {
|
|
8709
|
+
r[k] = Math.min(r[k], tmp.getComponent(k) - 1e-4);
|
|
8710
|
+
r[k + 3] = Math.max(r[k + 3], tmp.getComponent(k) + 1e-4);
|
|
8711
|
+
}
|
|
8712
|
+
}
|
|
8713
|
+
return r;
|
|
8714
|
+
}
|
|
8511
8715
|
function zoneDent(c, z, dents, dirty, opt) {
|
|
8512
8716
|
opt = opt || {};
|
|
8513
8717
|
const B = z.box;
|
|
@@ -8562,6 +8766,7 @@ var GameVehicles = (() => {
|
|
|
8562
8766
|
g = msh.geometry = g.clone();
|
|
8563
8767
|
msh.userData.zCloned = true;
|
|
8564
8768
|
}
|
|
8769
|
+
let boundsDue = false;
|
|
8565
8770
|
const nonIdx = !g.index;
|
|
8566
8771
|
const onlyPos = Object.keys(g.attributes).every(function(k) {
|
|
8567
8772
|
return k === "position" || k === "normal";
|
|
@@ -8570,15 +8775,17 @@ var GameVehicles = (() => {
|
|
|
8570
8775
|
const ng = subdivIn(g, rel, B, opt.sub || 0.075);
|
|
8571
8776
|
g.dispose();
|
|
8572
8777
|
g = msh.geometry = ng;
|
|
8573
|
-
|
|
8574
|
-
ng.computeBoundingBox();
|
|
8778
|
+
boundsDue = true;
|
|
8575
8779
|
dirty.add(msh);
|
|
8576
8780
|
}
|
|
8577
8781
|
irel.copy(rel).invert();
|
|
8578
8782
|
const pos = g.attributes.position;
|
|
8579
8783
|
let changed = false;
|
|
8784
|
+
const near = boxInFrame(B, irel, v);
|
|
8580
8785
|
for (let i = 0; i < pos.count; i++) {
|
|
8581
|
-
v.fromBufferAttribute(pos, i)
|
|
8786
|
+
v.fromBufferAttribute(pos, i);
|
|
8787
|
+
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;
|
|
8788
|
+
v.applyMatrix4(rel);
|
|
8582
8789
|
const f = field(v);
|
|
8583
8790
|
if (f <= 1e-5) continue;
|
|
8584
8791
|
v.addScaledVector(d, f);
|
|
@@ -8599,9 +8806,11 @@ var GameVehicles = (() => {
|
|
|
8599
8806
|
}
|
|
8600
8807
|
if (changed) {
|
|
8601
8808
|
pos.needsUpdate = true;
|
|
8809
|
+
dirty.add(msh);
|
|
8810
|
+
}
|
|
8811
|
+
if (changed || boundsDue) {
|
|
8602
8812
|
g.computeBoundingSphere();
|
|
8603
8813
|
g.computeBoundingBox();
|
|
8604
|
-
dirty.add(msh);
|
|
8605
8814
|
}
|
|
8606
8815
|
});
|
|
8607
8816
|
const dset = new Set(c.deform);
|
|
@@ -11704,6 +11913,20 @@ var GameVehicles = (() => {
|
|
|
11704
11913
|
else kit.applyArmor(c);
|
|
11705
11914
|
}
|
|
11706
11915
|
if (zoneState == null && st === "damaged" && kit.config.damagedScenario) zoneState = kit.zoneScenario(c, kit.config.damagedScenario);
|
|
11916
|
+
else if (zoneState && zoneState.scenario != null) {
|
|
11917
|
+
c.scenario = zoneState.scenario;
|
|
11918
|
+
let fromScenario = { health: {}, flags: {} };
|
|
11919
|
+
try {
|
|
11920
|
+
fromScenario = kit.zoneScenario(c, zoneState.scenario);
|
|
11921
|
+
} catch (e) {
|
|
11922
|
+
;
|
|
11923
|
+
(c.zoneErrors = c.zoneErrors || []).push("scenario: " + (e && e.message));
|
|
11924
|
+
}
|
|
11925
|
+
zoneState = {
|
|
11926
|
+
health: Object.assign({}, fromScenario.health, zoneState.health),
|
|
11927
|
+
flags: Object.assign({}, fromScenario.flags, zoneState.flags)
|
|
11928
|
+
};
|
|
11929
|
+
}
|
|
11707
11930
|
if (zoneState) kit.applyZones(c, zoneState);
|
|
11708
11931
|
else {
|
|
11709
11932
|
c.zoneState = { health: {}, flags: {} };
|
|
@@ -13702,7 +13925,7 @@ var GameVehicles = (() => {
|
|
|
13702
13925
|
const reset = () => {
|
|
13703
13926
|
const old = c;
|
|
13704
13927
|
const parent = old.root.parent;
|
|
13705
|
-
const next = kit.build(old.key, old.state);
|
|
13928
|
+
const next = kit.build(old.key, old.state, old.scenario != null ? { scenario: old.scenario } : void 0);
|
|
13706
13929
|
if (parent) {
|
|
13707
13930
|
next.root.position.copy(old.root.position);
|
|
13708
13931
|
next.root.quaternion.copy(old.root.quaternion);
|
|
@@ -13759,7 +13982,8 @@ var GameVehicles = (() => {
|
|
|
13759
13982
|
// src/destructible/item.ts
|
|
13760
13983
|
function buildVehicleItem(kit, key, options = {}) {
|
|
13761
13984
|
const THREE = kit.THREE;
|
|
13762
|
-
const
|
|
13985
|
+
const zoneState = options.scenario != null ? { scenario: options.scenario } : void 0;
|
|
13986
|
+
const vehicle = options.lod ? kit.build(key, options.state ?? "intact", zoneState, { lod: true }) : kit.build(key, options.state ?? "intact", zoneState);
|
|
13763
13987
|
const m = vehicle.meta;
|
|
13764
13988
|
const root = new THREE.Group();
|
|
13765
13989
|
root.name = key;
|