@vgai/engine 0.5.22 → 0.5.23
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 -3
- package/dist/adapter/adapter-module.d.ts.map +1 -1
- package/dist/adapter/adapter-module.js +2 -4
- package/dist/adapter/adapter-surface.d.ts +1 -1
- package/dist/adapter/adapter-surface.js +1 -1
- package/dist/adapter/authoring.d.ts +19 -21
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/authoring.js +2 -2
- package/dist/adapter/binding.d.ts +341 -0
- package/dist/adapter/binding.d.ts.map +1 -0
- package/dist/adapter/binding.js +148 -0
- package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -1
- package/dist/adapter/colyseus-networking-adapter.js +23 -4
- package/dist/adapter/entrypoint-selection-readers.d.ts +24 -0
- package/dist/adapter/entrypoint-selection-readers.d.ts.map +1 -0
- package/dist/adapter/entrypoint-selection-readers.js +63 -0
- package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -1
- package/dist/adapter/entrypoint-selection-source.js +1 -44
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
- package/dist/adapter/finders/scenes-from-entrypoint-selection.js +1 -52
- package/dist/adapter/host-context.d.ts +46 -15
- package/dist/adapter/host-context.d.ts.map +1 -1
- package/dist/adapter/host-context.js +2 -9
- package/dist/adapter/index.d.ts +11 -12
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/index.js +9 -10
- package/dist/adapter/ingest/game-contract.d.ts +0 -3
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +0 -3
- package/dist/adapter/ingest/scene-capture.d.ts +19 -23
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +143 -17
- package/dist/adapter/ingest/visible-capture-window.d.ts +34 -0
- package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
- package/dist/adapter/native-debug-module.d.ts +31 -5
- package/dist/adapter/native-debug-module.d.ts.map +1 -1
- package/dist/adapter/native-debug-module.js +25 -7
- package/dist/adapter/rapier-physics-adapter.d.ts +31 -1
- package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -1
- package/dist/adapter/rapier-physics-adapter.js +50 -36
- package/dist/adapter/renderer-config.d.ts +2 -2
- package/dist/adapter/renderer-config.js +2 -2
- package/dist/adapter/root-adapter.d.ts +7 -7
- package/dist/adapter/root-adapter.js +4 -4
- package/dist/adapter/system-adapter.d.ts +45 -7
- package/dist/adapter/system-adapter.d.ts.map +1 -1
- package/dist/adapter/system-seam-contract.d.ts +3 -3
- package/dist/adapter/system-seam-contract.js +3 -3
- package/dist/adapter/system-slot.d.ts +168 -0
- package/dist/adapter/system-slot.d.ts.map +1 -0
- package/dist/adapter/system-slot.js +229 -0
- package/dist/adapter/transform.d.ts +11 -1
- package/dist/adapter/transform.d.ts.map +1 -1
- package/dist/ai/navigation.d.ts +17 -1
- package/dist/ai/navigation.d.ts.map +1 -1
- package/dist/ai/navigation.js +26 -5
- package/dist/animation/anim-graph-types.d.ts +11 -3
- package/dist/animation/anim-graph-types.d.ts.map +1 -1
- package/dist/animation/theatre-clock-binding.d.ts +4 -4
- package/dist/animation/theatre-clock-binding.js +4 -4
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
- package/dist/animation/xstate-animation-binding.js +2 -2
- package/dist/animation/xstate-animation-meta.d.ts +13 -0
- package/dist/animation/xstate-animation-meta.d.ts.map +1 -1
- package/dist/animation/xstate-animation-meta.js +14 -0
- package/dist/asset-formats/index.d.ts +4 -7
- package/dist/asset-formats/index.d.ts.map +1 -1
- package/dist/asset-formats/index.js +4 -7
- package/dist/asset-formats/render-env.d.ts +5 -8
- package/dist/asset-formats/render-env.d.ts.map +1 -1
- package/dist/asset-formats/render-env.js +3 -6
- package/dist/asset-parse-error.d.ts +2 -5
- package/dist/asset-parse-error.d.ts.map +1 -1
- package/dist/asset-parse-error.js +2 -5
- package/dist/audio/bus-mixer.d.ts +101 -0
- package/dist/audio/bus-mixer.d.ts.map +1 -0
- package/dist/audio/bus-mixer.js +115 -0
- package/dist/core/frame-pacing.d.ts +1 -1
- package/dist/core/frame-pacing.js +2 -2
- package/dist/core/game-loop.d.ts +1 -3
- package/dist/core/game-loop.d.ts.map +1 -1
- package/dist/core/game-loop.js +1 -3
- package/dist/core/seeded-random.d.ts +1 -1
- package/dist/core/sim-clock.d.ts +5 -6
- package/dist/core/sim-clock.d.ts.map +1 -1
- package/dist/core/sim-clock.js +4 -5
- package/dist/core/types.d.ts +1 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/defaults.d.ts +6 -14
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +6 -14
- package/dist/dev/register-render-vitals.d.ts +1 -4
- package/dist/dev/register-render-vitals.d.ts.map +1 -1
- package/dist/dev/register-render-vitals.js +1 -4
- package/dist/dev/render-debug-adapter.d.ts +2 -3
- package/dist/dev/render-debug-adapter.d.ts.map +1 -1
- package/dist/dev/render-debug-adapter.js +2 -3
- package/dist/dev/render-vitals.d.ts +3 -3
- package/dist/dev/render-vitals.js +3 -3
- package/dist/dev/webgl-frame-capture.d.ts +1 -1
- package/dist/dev/webgl-frame-capture.js +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/input/host-pointer.d.ts +122 -0
- package/dist/input/host-pointer.d.ts.map +1 -0
- package/dist/input/host-pointer.js +160 -0
- package/dist/input/input-manager.d.ts +18 -5
- package/dist/input/input-manager.d.ts.map +1 -1
- package/dist/input/input-manager.js +33 -13
- package/dist/input/rebind-controller.d.ts.map +1 -1
- package/dist/input/rebind-controller.js +6 -8
- package/dist/input/schema.d.ts.map +1 -1
- package/dist/input/schema.js +56 -28
- package/dist/manifest/filename.d.ts.map +1 -1
- package/dist/manifest/filename.js +8 -12
- package/dist/manifest/load.d.ts +10 -10
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +9 -6
- package/dist/manifest/schema.d.ts +17 -21
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +45 -35
- package/dist/physics/collider-dimensions.d.ts +8 -12
- package/dist/physics/collider-dimensions.d.ts.map +1 -1
- package/dist/physics/collider-dimensions.js +8 -12
- package/dist/pixi/scene-capture.d.ts +11 -13
- package/dist/pixi/scene-capture.d.ts.map +1 -1
- package/dist/react/world-state.d.ts +1 -1
- package/dist/react/world-state.d.ts.map +1 -1
- package/dist/render/light-camera-factory.d.ts +5 -7
- package/dist/render/light-camera-factory.d.ts.map +1 -1
- package/dist/render/light-camera-factory.js +8 -11
- package/dist/render/material-factory.js +1 -1
- package/dist/render/render-batch-system.d.ts.map +1 -1
- package/dist/render/render-features.d.ts +17 -6
- package/dist/render/render-features.d.ts.map +1 -1
- package/dist/render/render-features.js +0 -28
- package/dist/runtime/create-runtime.d.ts +34 -25
- package/dist/runtime/create-runtime.d.ts.map +1 -1
- package/dist/runtime/create-runtime.js +218 -93
- package/dist/runtime/debug-registry.d.ts +77 -8
- package/dist/runtime/debug-registry.d.ts.map +1 -1
- package/dist/runtime/debug-registry.js +3 -3
- package/dist/runtime/dev-build.d.ts +2 -2
- package/dist/runtime/dev-build.js +2 -2
- package/dist/runtime/game-input-seams.d.ts +2 -2
- package/dist/runtime/game-input-seams.d.ts.map +1 -1
- package/dist/runtime/game.d.ts +90 -41
- package/dist/runtime/game.d.ts.map +1 -1
- package/dist/runtime/game.js +80 -54
- package/dist/runtime/mount-game.d.ts +0 -16
- package/dist/runtime/mount-game.d.ts.map +1 -1
- package/dist/runtime/mount-game.js +8 -39
- package/dist/runtime/mount-manifest.d.ts +22 -14
- package/dist/runtime/mount-manifest.d.ts.map +1 -1
- package/dist/runtime/mount-manifest.js +18 -18
- package/dist/runtime/playtest.d.ts +22 -0
- package/dist/runtime/playtest.d.ts.map +1 -0
- package/dist/runtime/playtest.js +12 -0
- package/dist/runtime/state-bridge.d.ts +2 -3
- package/dist/runtime/state-bridge.d.ts.map +1 -1
- package/dist/runtime/state-bridge.js +1 -0
- package/dist/setup/setup-audio.d.ts +12 -0
- package/dist/setup/setup-audio.d.ts.map +1 -1
- package/dist/setup/setup-audio.js +9 -10
- package/dist/setup/setup-renderer.d.ts +2 -25
- package/dist/setup/setup-renderer.d.ts.map +1 -1
- package/dist/setup/setup-renderer.js +2 -31
- package/dist/world3d-react/r3f-root-factory.d.ts +7 -7
- package/dist/world3d-react/r3f-root-factory.js +7 -7
- package/dist/world3d-react/rapier-physics-bridge.d.ts +9 -8
- package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
- package/dist/world3d-react/rapier-physics-bridge.js +100 -48
- package/package.json +1 -1
- package/schemas/engine-capabilities.json +16 -14
- package/schemas/vgai-project.schema.json +35 -26
- package/src/adapter/adapter-module.ts +2 -4
- package/src/adapter/adapter-surface.ts +1 -1
- package/src/adapter/authoring.ts +19 -21
- package/src/adapter/binding.ts +468 -0
- package/src/adapter/colyseus-networking-adapter.ts +20 -5
- package/src/adapter/entrypoint-selection-readers.ts +66 -0
- package/src/adapter/entrypoint-selection-source.ts +1 -40
- package/src/adapter/finders/scenes-from-entrypoint-selection.ts +1 -48
- package/src/adapter/host-context.ts +45 -15
- package/src/adapter/index.ts +23 -11
- package/src/adapter/ingest/game-contract.ts +0 -3
- package/src/adapter/ingest/scene-capture.ts +190 -39
- package/src/adapter/ingest/visible-capture-window.ts +35 -0
- package/src/adapter/native-debug-module.ts +43 -7
- package/src/adapter/rapier-physics-adapter.ts +76 -20
- package/src/adapter/renderer-config.ts +2 -2
- package/src/adapter/root-adapter.ts +7 -7
- package/src/adapter/system-adapter.ts +43 -8
- package/src/adapter/system-seam-contract.ts +3 -3
- package/src/adapter/system-slot.ts +291 -0
- package/src/adapter/transform.ts +18 -1
- package/src/ai/navigation.ts +30 -3
- package/src/animation/anim-graph-types.ts +11 -3
- package/src/animation/theatre-clock-binding.ts +4 -4
- package/src/animation/xstate-animation-binding.ts +2 -2
- package/src/animation/xstate-animation-meta.ts +16 -0
- package/src/asset-formats/index.ts +4 -7
- package/src/asset-formats/render-env.ts +3 -6
- package/src/asset-parse-error.ts +2 -5
- package/src/audio/bus-mixer.ts +161 -0
- package/src/core/frame-pacing.ts +2 -2
- package/src/core/game-loop.ts +1 -3
- package/src/core/seeded-random.ts +1 -1
- package/src/core/sim-clock.ts +5 -6
- package/src/core/types.ts +1 -3
- package/src/defaults.ts +6 -14
- package/src/dev/register-render-vitals.ts +1 -4
- package/src/dev/render-debug-adapter.ts +2 -3
- package/src/dev/render-vitals.ts +3 -3
- package/src/dev/webgl-frame-capture.ts +1 -1
- package/src/index.ts +2 -5
- package/src/input/host-pointer.ts +230 -0
- package/src/input/input-manager.ts +34 -13
- package/src/input/input-types.ts +1 -1
- package/src/input/rebind-controller.ts +6 -8
- package/src/input/schema.ts +216 -188
- package/src/manifest/filename.ts +8 -12
- package/src/manifest/load.ts +17 -13
- package/src/manifest/schema.ts +55 -47
- package/src/physics/collider-dimensions.ts +8 -12
- package/src/pixi/scene-capture.ts +12 -15
- package/src/react/world-state.tsx +1 -1
- package/src/render/light-camera-factory.ts +8 -11
- package/src/render/material-factory.ts +1 -1
- package/src/render/render-batch-system.ts +14 -6
- package/src/render/render-features.ts +17 -35
- package/src/runtime/create-runtime.ts +270 -108
- package/src/runtime/debug-registry.ts +84 -8
- package/src/runtime/dev-build.ts +2 -2
- package/src/runtime/game-input-seams.ts +2 -2
- package/src/runtime/game.ts +168 -80
- package/src/runtime/mount-game.ts +8 -56
- package/src/runtime/mount-manifest.ts +43 -34
- package/src/runtime/playtest.ts +22 -0
- package/src/runtime/state-bridge.ts +3 -3
- package/src/setup/setup-audio.ts +21 -11
- package/src/setup/setup-renderer.ts +2 -61
- package/src/world3d-react/r3f-root-factory.tsx +7 -7
- package/src/world3d-react/rapier-physics-bridge.tsx +107 -50
- package/dist/adapter/setup-three-root-adapter.d.ts +0 -86
- package/dist/adapter/setup-three-root-adapter.d.ts.map +0 -1
- package/dist/adapter/setup-three-root-adapter.js +0 -908
- package/dist/animation/clip-map.d.ts +0 -12
- package/dist/animation/clip-map.d.ts.map +0 -1
- package/dist/animation/clip-map.js +0 -31
- package/dist/asset-registry.d.ts +0 -38
- package/dist/asset-registry.d.ts.map +0 -1
- package/dist/asset-registry.js +0 -66
- package/dist/canvas-react/engine-bridge.d.ts +0 -45
- package/dist/canvas-react/engine-bridge.d.ts.map +0 -1
- package/dist/canvas-react/engine-bridge.js +0 -45
- package/dist/canvas-react/pixi-react-adapter.d.ts +0 -77
- package/dist/canvas-react/pixi-react-adapter.d.ts.map +0 -1
- package/dist/canvas-react/pixi-react-adapter.js +0 -294
- package/dist/canvas-react/world-context.d.ts +0 -98
- package/dist/canvas-react/world-context.d.ts.map +0 -1
- package/dist/canvas-react/world-context.js +0 -173
- package/dist/dev/debug-draw.d.ts +0 -24
- package/dist/dev/debug-draw.d.ts.map +0 -1
- package/dist/dev/debug-draw.js +0 -73
- package/dist/render/auto-batcher.d.ts +0 -34
- package/dist/render/auto-batcher.d.ts.map +0 -1
- package/dist/render/auto-batcher.js +0 -140
- package/dist/render/lod.d.ts +0 -13
- package/dist/render/lod.d.ts.map +0 -1
- package/dist/render/lod.js +0 -16
- package/dist/runtime/types.d.ts +0 -303
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js +0 -1
- package/dist/world3d-react/engine-bridge.d.ts +0 -47
- package/dist/world3d-react/engine-bridge.d.ts.map +0 -1
- package/dist/world3d-react/engine-bridge.js +0 -73
- package/dist/world3d-react/r3f-adapter.d.ts +0 -58
- package/dist/world3d-react/r3f-adapter.d.ts.map +0 -1
- package/dist/world3d-react/r3f-adapter.js +0 -634
- package/dist/world3d-react/world-context.d.ts +0 -182
- package/dist/world3d-react/world-context.d.ts.map +0 -1
- package/dist/world3d-react/world-context.js +0 -235
- package/src/adapter/setup-three-root-adapter.ts +0 -1032
- package/src/animation/clip-map.ts +0 -34
- package/src/asset-registry.ts +0 -89
- package/src/dev/debug-draw.ts +0 -80
- package/src/render/auto-batcher.ts +0 -168
- package/src/render/lod.ts +0 -17
- package/src/runtime/types.ts +0 -328
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type * as THREE from 'three';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Build the clip lookup shared by runtime and editor.
|
|
5
|
-
*
|
|
6
|
-
* GLTF exporters disagree about case and may prefix animation names with an
|
|
7
|
-
* armature (`Armature|Idle`). Keep the exact exported suffix while also
|
|
8
|
-
* exposing a lowercase lookup, then apply aliases case-insensitively. This
|
|
9
|
-
* lets authored graphs use either `Idle_Loop` or `idle_loop` without silently
|
|
10
|
-
* falling back to the bind pose.
|
|
11
|
-
*/
|
|
12
|
-
export function buildClipMap(
|
|
13
|
-
animations: THREE.AnimationClip[],
|
|
14
|
-
aliases: Record<string, string> = {},
|
|
15
|
-
): Map<string, THREE.AnimationClip> {
|
|
16
|
-
const clips = new Map<string, THREE.AnimationClip>();
|
|
17
|
-
const canonical = new Map<string, THREE.AnimationClip>();
|
|
18
|
-
|
|
19
|
-
for (const clip of animations) {
|
|
20
|
-
const raw = clip.name.split('|').pop()?.trim() || clip.name;
|
|
21
|
-
canonical.set(raw.toLowerCase(), clip);
|
|
22
|
-
if (!clips.has(raw)) clips.set(raw, clip);
|
|
23
|
-
if (!clips.has(raw.toLowerCase())) clips.set(raw.toLowerCase(), clip);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
for (const [source, alias] of Object.entries(aliases)) {
|
|
27
|
-
const clip = canonical.get(source.toLowerCase());
|
|
28
|
-
if (!clip) continue;
|
|
29
|
-
if (!clips.has(alias)) clips.set(alias, clip);
|
|
30
|
-
if (!clips.has(alias.toLowerCase())) clips.set(alias.toLowerCase(), clip);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return clips;
|
|
34
|
-
}
|
package/src/asset-registry.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Central asset registry — stores per-asset metadata (import corrections, etc.).
|
|
3
|
-
*
|
|
4
|
-
* Loaded once via fetch(), cached in memory. Both the runtime scene loader
|
|
5
|
-
* and editor entity factory import from this module.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import * as THREE from 'three';
|
|
9
|
-
import { resolveUrl } from './loader';
|
|
10
|
-
|
|
11
|
-
export interface ImportCorrection {
|
|
12
|
-
/** Uniform scale factor applied to the GLTF clone before entity transform. */
|
|
13
|
-
scale?: number;
|
|
14
|
-
/** Euler rotation in degrees [x, y, z] applied to the GLTF clone before entity transform. */
|
|
15
|
-
rotation?: [number, number, number];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface AssetMeta {
|
|
19
|
-
importCorrection?: ImportCorrection;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Apply an asset's visual-only import correction to the loaded GLTF content.
|
|
24
|
-
* Call this on the model child, before placing it under the entity wrapper, so
|
|
25
|
-
* gameplay transforms, physics, cameras, and movement remain in VGAI's Y-up /
|
|
26
|
-
* -Z-forward coordinate contract.
|
|
27
|
-
*/
|
|
28
|
-
export function applyImportCorrection(
|
|
29
|
-
content: THREE.Object3D,
|
|
30
|
-
correction: ImportCorrection | undefined,
|
|
31
|
-
): void {
|
|
32
|
-
if (!correction) return;
|
|
33
|
-
if (correction.scale !== undefined) content.scale.multiplyScalar(correction.scale);
|
|
34
|
-
if (correction.rotation) {
|
|
35
|
-
content.rotation.set(
|
|
36
|
-
THREE.MathUtils.degToRad(correction.rotation[0]),
|
|
37
|
-
THREE.MathUtils.degToRad(correction.rotation[1]),
|
|
38
|
-
THREE.MathUtils.degToRad(correction.rotation[2]),
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
type AssetRegistry = Record<string, AssetMeta>;
|
|
44
|
-
|
|
45
|
-
let registryCache: AssetRegistry | null = null;
|
|
46
|
-
let registryPromise: Promise<AssetRegistry> | null = null;
|
|
47
|
-
|
|
48
|
-
/** Normalize asset path for registry lookup (strip leading slash). */
|
|
49
|
-
function normalize(path: string): string {
|
|
50
|
-
return path.startsWith('/') ? path.slice(1) : path;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Fetch and cache the asset registry. Safe to call multiple times —
|
|
55
|
-
* returns the cached result after the first successful load.
|
|
56
|
-
*/
|
|
57
|
-
export function loadRegistry(): Promise<AssetRegistry> {
|
|
58
|
-
if (registryCache) return Promise.resolve(registryCache);
|
|
59
|
-
if (registryPromise) return registryPromise;
|
|
60
|
-
|
|
61
|
-
registryPromise = fetch(resolveUrl('asset-registry.json'))
|
|
62
|
-
.then((res) => {
|
|
63
|
-
if (!res.ok) return {};
|
|
64
|
-
return res.json() as Promise<AssetRegistry>;
|
|
65
|
-
})
|
|
66
|
-
.catch(() => ({}) as AssetRegistry)
|
|
67
|
-
.then((data) => {
|
|
68
|
-
registryCache = data;
|
|
69
|
-
return data;
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return registryPromise;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** Get metadata for an asset path, or undefined if not in the registry. */
|
|
76
|
-
export function getAssetMeta(path: string): AssetMeta | undefined {
|
|
77
|
-
if (!registryCache) return undefined;
|
|
78
|
-
// Try exact match first, then normalized
|
|
79
|
-
return registryCache[path] ?? registryCache[normalize(path)];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Update the in-memory cache directly (used by the editor after saving
|
|
84
|
-
* import settings, to avoid a re-fetch).
|
|
85
|
-
*/
|
|
86
|
-
export function setRegistryCache(data: AssetRegistry): void {
|
|
87
|
-
registryCache = data;
|
|
88
|
-
registryPromise = null;
|
|
89
|
-
}
|
package/src/dev/debug-draw.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Debug drawing utilities for development.
|
|
5
|
-
*
|
|
6
|
-
* Draw lines, spheres, boxes, and arrows for visualizing
|
|
7
|
-
* physics colliders, raycasts, AI paths, etc.
|
|
8
|
-
*
|
|
9
|
-
* All debug objects are added to a dedicated group that can be toggled.
|
|
10
|
-
*/
|
|
11
|
-
export function createDebugDraw(scene: THREE.Scene) {
|
|
12
|
-
const group = new THREE.Group();
|
|
13
|
-
group.name = 'debug-draw';
|
|
14
|
-
scene.add(group);
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
/** Draw a line between two points */
|
|
18
|
-
line(from: THREE.Vector3, to: THREE.Vector3, color = 0x00ff00) {
|
|
19
|
-
const geometry = new THREE.BufferGeometry().setFromPoints([from, to]);
|
|
20
|
-
const material = new THREE.LineBasicMaterial({ color });
|
|
21
|
-
const line = new THREE.Line(geometry, material);
|
|
22
|
-
group.add(line);
|
|
23
|
-
return line;
|
|
24
|
-
},
|
|
25
|
-
|
|
26
|
-
/** Draw a wireframe sphere at a position */
|
|
27
|
-
sphere(center: THREE.Vector3, radius = 0.1, color = 0xff0000) {
|
|
28
|
-
const geo = new THREE.SphereGeometry(radius, 8, 8);
|
|
29
|
-
const mat = new THREE.MeshBasicMaterial({ color, wireframe: true });
|
|
30
|
-
const mesh = new THREE.Mesh(geo, mat);
|
|
31
|
-
mesh.position.copy(center);
|
|
32
|
-
group.add(mesh);
|
|
33
|
-
return mesh;
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
/** Draw a wireframe box */
|
|
37
|
-
box(center: THREE.Vector3, size: THREE.Vector3, color = 0x00ffff) {
|
|
38
|
-
const geo = new THREE.BoxGeometry(size.x, size.y, size.z);
|
|
39
|
-
const mat = new THREE.MeshBasicMaterial({ color, wireframe: true });
|
|
40
|
-
const mesh = new THREE.Mesh(geo, mat);
|
|
41
|
-
mesh.position.copy(center);
|
|
42
|
-
group.add(mesh);
|
|
43
|
-
return mesh;
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
/** Draw an arrow (direction indicator) */
|
|
47
|
-
arrow(origin: THREE.Vector3, direction: THREE.Vector3, length = 1, color = 0xffff00) {
|
|
48
|
-
// Clone before normalize() — never mutate the caller's vector.
|
|
49
|
-
const dir = direction.clone().normalize();
|
|
50
|
-
const arrow = new THREE.ArrowHelper(dir, origin, length, color);
|
|
51
|
-
group.add(arrow);
|
|
52
|
-
return arrow;
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
/** Clear all debug drawings */
|
|
56
|
-
clear() {
|
|
57
|
-
while (group.children.length > 0) {
|
|
58
|
-
const child = group.children[0]!;
|
|
59
|
-
group.remove(child);
|
|
60
|
-
if (child instanceof THREE.Mesh || child instanceof THREE.Line) {
|
|
61
|
-
// Mesh, Line and LineSegments all own geometry + material.
|
|
62
|
-
child.geometry.dispose();
|
|
63
|
-
(child.material as THREE.Material).dispose();
|
|
64
|
-
} else if (child instanceof THREE.ArrowHelper) {
|
|
65
|
-
// ArrowHelper owns a line + cone; dispose() frees both.
|
|
66
|
-
child.dispose();
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
/** Toggle debug draw visibility */
|
|
72
|
-
set visible(v: boolean) {
|
|
73
|
-
group.visible = v;
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
get visible() {
|
|
77
|
-
return group.visible;
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Transparent auto-batcher (Strategy 1).
|
|
5
|
-
*
|
|
6
|
-
* The framework keeps each entity's Object3D as the logical handle (transform,
|
|
7
|
-
* gameplay, physics, picking) and renders eligible entities through a shared
|
|
8
|
-
* InstancedMesh under the hood — N logical objects, 1 draw call — WITHOUT the
|
|
9
|
-
* user changing any code. Identity is never merged, so selection/raycast survive
|
|
10
|
-
* (we keep an instanceId → entity map). The whole thing flips on/off live.
|
|
11
|
-
*
|
|
12
|
-
* Eligibility: an entity is a THREE.Mesh sharing geometry+material with others.
|
|
13
|
-
* Entities marked `userData.__noBatch` (the per-entity opt-out) always render
|
|
14
|
-
* individually. Custom/unique materials simply form their own (size-1) groups and
|
|
15
|
-
* cost a draw each — they degrade, they don't break.
|
|
16
|
-
*
|
|
17
|
-
* Cost model (measured in docs/research/bench/): per-frame cost is paid only for
|
|
18
|
-
* entities that MOVED (dirty-tracked via markMoved). A static scene re-syncs
|
|
19
|
-
* nothing — write-once at build, then 1 draw/frame.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
interface Batch {
|
|
23
|
-
key: string;
|
|
24
|
-
instanced: THREE.InstancedMesh;
|
|
25
|
-
members: THREE.Mesh[]; // localIndex → entity mesh (for picking + sync)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SIG = (m: THREE.Mesh): string => {
|
|
29
|
-
const mat = Array.isArray(m.material) ? m.material[0]! : m.material;
|
|
30
|
-
return `${(m.geometry as THREE.BufferGeometry).uuid}|${mat.uuid}`;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export class AutoBatcher {
|
|
34
|
-
/** Root the batcher owns under the scene (instanced meshes when on, entities when off). */
|
|
35
|
-
readonly root = new THREE.Group();
|
|
36
|
-
|
|
37
|
-
private entities: THREE.Mesh[] = [];
|
|
38
|
-
private batches = new Map<string, Batch>();
|
|
39
|
-
private enabled: boolean;
|
|
40
|
-
/** Indices of entities whose transform changed since last sync. */
|
|
41
|
-
private dirty = new Set<number>();
|
|
42
|
-
private touchedBatches = new Set<Batch>();
|
|
43
|
-
// Per-mesh bookkeeping is kept in WeakMaps, NOT on userData (the typed userData
|
|
44
|
-
// registry is reserved for documented engine keys — see user-data.ts).
|
|
45
|
-
private indexOf = new WeakMap<THREE.Mesh, number>();
|
|
46
|
-
private optOut = new WeakSet<THREE.Mesh>();
|
|
47
|
-
private batchOf = new WeakMap<THREE.Mesh, { key: string; localIndex: number }>();
|
|
48
|
-
private membersOf = new WeakMap<THREE.InstancedMesh, THREE.Mesh[]>();
|
|
49
|
-
|
|
50
|
-
constructor(parent: THREE.Object3D, enabled = true) {
|
|
51
|
-
this.enabled = enabled;
|
|
52
|
-
this.root.name = 'AutoBatcher';
|
|
53
|
-
parent.add(this.root);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Register an entity (a Mesh) as the logical handle. Call build() after adding. */
|
|
57
|
-
add(entity: THREE.Mesh, optOut = false): void {
|
|
58
|
-
this.indexOf.set(entity, this.entities.length);
|
|
59
|
-
if (optOut) this.optOut.add(entity);
|
|
60
|
-
this.entities.push(entity);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Mark an entity moved this frame (dirty-tracking input). */
|
|
64
|
-
markMoved(entity: THREE.Mesh): void {
|
|
65
|
-
const i = this.indexOf.get(entity);
|
|
66
|
-
if (i !== undefined) this.dirty.add(i);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** (Re)build the render representation for the current enabled state. */
|
|
70
|
-
build(): void {
|
|
71
|
-
this.clearRoot();
|
|
72
|
-
this.batches.clear();
|
|
73
|
-
if (!this.enabled) {
|
|
74
|
-
for (const e of this.entities) this.root.add(e);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
const m = new THREE.Matrix4();
|
|
78
|
-
// group eligible entities; opt-outs render individually
|
|
79
|
-
const groups = new Map<string, THREE.Mesh[]>();
|
|
80
|
-
for (const e of this.entities) {
|
|
81
|
-
if (this.optOut.has(e)) {
|
|
82
|
-
this.root.add(e);
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
const key = SIG(e);
|
|
86
|
-
const arr = groups.get(key) ?? [];
|
|
87
|
-
arr.push(e);
|
|
88
|
-
groups.set(key, arr);
|
|
89
|
-
}
|
|
90
|
-
for (const [key, members] of groups) {
|
|
91
|
-
const proto = members[0]!;
|
|
92
|
-
const mat = Array.isArray(proto.material) ? proto.material[0]! : proto.material;
|
|
93
|
-
const inst = new THREE.InstancedMesh(proto.geometry, mat, members.length);
|
|
94
|
-
inst.frustumCulled = false;
|
|
95
|
-
for (let i = 0; i < members.length; i++) {
|
|
96
|
-
const e = members[i]!;
|
|
97
|
-
e.updateMatrix();
|
|
98
|
-
m.copy(e.matrix);
|
|
99
|
-
inst.setMatrixAt(i, m);
|
|
100
|
-
this.batchOf.set(e, { key, localIndex: i });
|
|
101
|
-
}
|
|
102
|
-
inst.instanceMatrix.needsUpdate = true;
|
|
103
|
-
this.membersOf.set(inst, members); // localIndex → entity (picking)
|
|
104
|
-
this.root.add(inst);
|
|
105
|
-
this.batches.set(key, { key, instanced: inst, members });
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Apply the dirty set to the instance buffers. Cheap when few moved. */
|
|
110
|
-
sync(): void {
|
|
111
|
-
if (!this.enabled) return;
|
|
112
|
-
const m = new THREE.Matrix4();
|
|
113
|
-
this.touchedBatches.clear();
|
|
114
|
-
for (const i of this.dirty) {
|
|
115
|
-
const e = this.entities[i]!;
|
|
116
|
-
const info = this.batchOf.get(e);
|
|
117
|
-
if (!info) continue; // opt-out or not batched
|
|
118
|
-
const batch = this.batches.get(info.key);
|
|
119
|
-
if (!batch) continue;
|
|
120
|
-
e.updateMatrix();
|
|
121
|
-
m.copy(e.matrix);
|
|
122
|
-
batch.instanced.setMatrixAt(info.localIndex, m);
|
|
123
|
-
this.touchedBatches.add(batch);
|
|
124
|
-
}
|
|
125
|
-
for (const b of this.touchedBatches) b.instanced.instanceMatrix.needsUpdate = true;
|
|
126
|
-
this.dirty.clear();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** Live toggle: rebuilds the representation (one-time cost, not per-frame). */
|
|
130
|
-
setEnabled(on: boolean): void {
|
|
131
|
-
if (on === this.enabled) return;
|
|
132
|
-
this.enabled = on;
|
|
133
|
-
this.build();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
isEnabled(): boolean {
|
|
137
|
-
return this.enabled;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Map a raycast hit on a batch back to the logical entity (editor/gameplay picking). */
|
|
141
|
-
resolvePick(intersection: THREE.Intersection): THREE.Mesh | null {
|
|
142
|
-
const obj = intersection.object;
|
|
143
|
-
if ((obj as THREE.InstancedMesh).isInstancedMesh && intersection.instanceId != null) {
|
|
144
|
-
const members = this.membersOf.get(obj as THREE.InstancedMesh);
|
|
145
|
-
return members?.[intersection.instanceId] ?? null;
|
|
146
|
-
}
|
|
147
|
-
return obj instanceof THREE.Mesh ? obj : null;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Per-frame draw-call count this batcher contributes (for stats). */
|
|
151
|
-
get drawCallCount(): number {
|
|
152
|
-
return this.enabled ? this.batches.size + this.optOutCount : this.entities.length;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private get optOutCount(): number {
|
|
156
|
-
let n = 0;
|
|
157
|
-
for (const e of this.entities) if (this.optOut.has(e)) n++;
|
|
158
|
-
return n;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private clearRoot(): void {
|
|
162
|
-
for (let i = this.root.children.length - 1; i >= 0; i--) {
|
|
163
|
-
const c = this.root.children[i]!;
|
|
164
|
-
this.root.remove(c);
|
|
165
|
-
if ((c as THREE.InstancedMesh).isInstancedMesh) (c as THREE.InstancedMesh).dispose();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
package/src/render/lod.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type * as THREE from 'three';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Per-frame LOD tick. `THREE.LOD` only swaps its active level when
|
|
5
|
-
* `.update(camera)` runs, so every `THREE.LOD` in the scene graph needs this
|
|
6
|
-
* called once a frame. Wired into the runtime's `preRender` system in
|
|
7
|
-
* `adapter/setup-three-root-adapter.ts`.
|
|
8
|
-
*
|
|
9
|
-
* Format-neutral: it matches THREE's own `isLOD` marker and knows nothing about
|
|
10
|
-
* how the LOD was built. Formerly `@engine/scene/scene-loader`'s
|
|
11
|
-
* `updateSceneLODs`, relocated here when WO-8 deleted the `.vscn` scene loader.
|
|
12
|
-
*/
|
|
13
|
-
export function updateSceneLODs(scene: THREE.Object3D, camera: THREE.Camera): void {
|
|
14
|
-
scene.traverse((o) => {
|
|
15
|
-
if ((o as THREE.LOD).isLOD) (o as THREE.LOD).update(camera);
|
|
16
|
-
});
|
|
17
|
-
}
|