@volter/threejs-runtime 0.5.67 → 0.5.69
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/NOTICE +2 -2
- package/package.json +3 -3
- package/src/adapter/body-marks.ts +4 -4
- package/src/adapter/hierarchy-marks.ts +5 -5
- package/src/adapter/ingest/scene-capture.ts +7 -7
- package/src/adapter/ingest/structural-ids.ts +1 -1
- package/src/adapter/ingest/visible-capture-window.ts +3 -3
- package/src/animation/animation-clock.ts +1 -1
- package/src/asset-loaders.ts +1 -1
- package/src/ecs/object-marks.ts +4 -4
- package/src/ecs/user-data.ts +6 -6
- package/src/render/ibl-override-material.ts +1 -1
- package/vendor/realism-effects/UPSTREAM.md +2 -2
- package/vendor/realism-effects/package.json +2 -2
package/NOTICE
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Copyright 2026 Volter AI, Inc.
|
|
2
2
|
|
|
3
|
-
The files in this package were imported from volter-ai/
|
|
3
|
+
The files in this package were imported from volter-ai/volter-engine at
|
|
4
4
|
commit 09c2749ce (packages/threejs-runtime), where they were published as the
|
|
5
|
-
Apache-2.0 @
|
|
5
|
+
Apache-2.0 @volter/threejs-runtime package. They retain that license; LICENSE
|
|
6
6
|
contains its text.
|
|
7
7
|
|
|
8
8
|
vendor/realism-effects is a fork of realism-effects 1.1.2
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"name": "@volter/threejs-runtime",
|
|
3
3
|
"author": "Volter AI, Inc.",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.69",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"description": "THE THREE.JS SHIPPED TWIN: what a shipped game carries because its world is three.js \u2014 the renderer setup and render features, the asset loaders and asset-format descriptors, the Object3D marks the editor reads, Rapier-over-three physics, recast navigation, the three animation mixer and its xstate binding, and the scene-capture the ingest seam mounts through.",
|
|
10
10
|
"keywords": [
|
|
11
|
-
"
|
|
11
|
+
"volter",
|
|
12
12
|
"three",
|
|
13
13
|
"game-engine"
|
|
14
14
|
],
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@dimforge/rapier3d-compat": "^0.14.0",
|
|
44
44
|
"@recast-navigation/three": "^0.43.0",
|
|
45
45
|
"@sparkjsdev/spark": "^2.1.0",
|
|
46
|
-
"@volter/editor-project": "0.5.
|
|
46
|
+
"@volter/editor-project": "0.5.69",
|
|
47
47
|
"n8ao": "^1.10.1",
|
|
48
48
|
"postprocessing": "^6.38.0",
|
|
49
49
|
"quarks.core": "0.16.0",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Sibling of `hierarchy-marks.ts`, and the same shape of idea. That module's
|
|
6
6
|
* marks answer "what IS this node" for the panel; this one answers "who WRITES
|
|
7
7
|
* this node's pose" for an edit. Both are written by GAME code at the seam that
|
|
8
|
-
* knows the answer, read generically by the host, and namespaced `
|
|
8
|
+
* knows the answer, read generically by the host, and namespaced `volter*` because
|
|
9
9
|
* they are the host's namespace on a node the game owns.
|
|
10
10
|
*
|
|
11
11
|
* ## Why it exists
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* ## What to mark
|
|
38
38
|
*
|
|
39
39
|
* The node whose pose the body writes — normally the body's own root node. Not
|
|
40
|
-
* subtree-scoped (unlike `
|
|
40
|
+
* subtree-scoped (unlike `volterBuiltInternal`): a child of a body-driven node
|
|
41
41
|
* inherits its parent's motion through the transform chain, and its own local
|
|
42
42
|
* pose is still the node's to keep. Mark exactly the node the sync writes.
|
|
43
43
|
*/
|
|
@@ -57,13 +57,13 @@ import type { RapierEditableBody } from './rapier-physics-adapter';
|
|
|
57
57
|
* `RigidBody` classes are unrelated nominal types.
|
|
58
58
|
*/
|
|
59
59
|
export function markBodyOwnedNode(node: THREE.Object3D, body: RapierEditableBody): void {
|
|
60
|
-
setUserData(node, '
|
|
60
|
+
setUserData(node, 'volterBodyOwner', body);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/** The body that owns `node`'s pose, or `undefined` for a node that owns its own. */
|
|
64
64
|
export function bodyOwningNode(
|
|
65
65
|
node: THREE.Object3D | null | undefined,
|
|
66
66
|
): RapierEditableBody | undefined {
|
|
67
|
-
const body = getUserData(node, '
|
|
67
|
+
const body = getUserData(node, 'volterBodyOwner');
|
|
68
68
|
return body ?? undefined;
|
|
69
69
|
}
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
* ## What is NOT built-internal
|
|
103
103
|
*
|
|
104
104
|
* A node your game means as content — even one a class rather than JSX
|
|
105
|
-
* constructs — is content. `
|
|
105
|
+
* constructs — is content. `volterBuiltInternal` is not "the editor cannot write
|
|
106
106
|
* this"; that question is `TransformProvider.editability`'s, answered per
|
|
107
107
|
* channel with a sentence. This mark answers "is this implementation", and
|
|
108
108
|
* getting it wrong hides real content.
|
|
@@ -124,12 +124,12 @@ import { getObjectMark, setObjectMark } from '../ecs/object-marks';
|
|
|
124
124
|
* the instance is already named by `node.name`, and the editor prints both.
|
|
125
125
|
*/
|
|
126
126
|
export function markComponentRoot(node: THREE.Object3D, name: string): void {
|
|
127
|
-
setObjectMark(node, '
|
|
127
|
+
setObjectMark(node, 'volterComponentRoot', name);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
/** The component name `node` is the root of, or `undefined` for an ordinary node. */
|
|
131
131
|
export function componentRootName(node: THREE.Object3D | null | undefined): string | undefined {
|
|
132
|
-
const name = getObjectMark(node, '
|
|
132
|
+
const name = getObjectMark(node, 'volterComponentRoot');
|
|
133
133
|
return typeof name === 'string' && name ? name : undefined;
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -145,12 +145,12 @@ export function isComponentRoot(node: THREE.Object3D | null | undefined): boolea
|
|
|
145
145
|
* the seam and not a sweep.
|
|
146
146
|
*/
|
|
147
147
|
export function markBuiltInternal(node: THREE.Object3D): void {
|
|
148
|
-
setObjectMark(node, '
|
|
148
|
+
setObjectMark(node, 'volterBuiltInternal', true);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/** Whether `node` itself carries the implementation mark. Ancestry is the
|
|
152
152
|
* CALLER's walk — see this module's header for why the mark is subtree-scoped
|
|
153
153
|
* but not restamped onto descendants. */
|
|
154
154
|
export function isBuiltInternal(node: THREE.Object3D | null | undefined): boolean {
|
|
155
|
-
return getObjectMark(node, '
|
|
155
|
+
return getObjectMark(node, 'volterBuiltInternal') === true;
|
|
156
156
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* that captures `(scene, camera, renderer)` on the first real frame.
|
|
18
18
|
*
|
|
19
19
|
* This is the hardened, typed form of the `ingest-study` spike
|
|
20
|
-
* (`docs/ingest-study-spike/
|
|
20
|
+
* (`docs/ingest-study-spike/volter-ingest-adapter.js`), proven against an
|
|
21
21
|
* unmodified `three.js/examples/games_fps` game.
|
|
22
22
|
*
|
|
23
23
|
* DOM-backed addon renderers use ordinary prototype methods instead. The host
|
|
@@ -111,12 +111,12 @@ export interface SceneCaptureOptions {
|
|
|
111
111
|
* Identity, not shape, is the discriminator: a host renderer and a game
|
|
112
112
|
* renderer are the same class, both built after install, both drawing real
|
|
113
113
|
* scenes. The host is the only party that knows which is which, so it says
|
|
114
|
-
* so (`@
|
|
114
|
+
* so (`@volter/threejs/viewport/renderer-ownership`).
|
|
115
115
|
*/
|
|
116
116
|
isHostRenderer?: (renderer: unknown) => boolean;
|
|
117
117
|
/**
|
|
118
118
|
* The game's OWN declared world, read from its contract
|
|
119
|
-
* (`window.
|
|
119
|
+
* (`window.volterGame` — the host passes a reader, never a cached value, because
|
|
120
120
|
* the contract is declared by the game's modules and may not exist yet when
|
|
121
121
|
* the trap installs).
|
|
122
122
|
*
|
|
@@ -135,7 +135,7 @@ export interface SceneCaptureOptions {
|
|
|
135
135
|
* forever, and the real world that renders one frame later reaches no reader
|
|
136
136
|
* at all. This is that reader. It never changes which world is adopted — it
|
|
137
137
|
* makes the ambiguity a recorded fact (`packages/editor/src/world-adoption.ts`
|
|
138
|
-
* publishes it to `
|
|
138
|
+
* publishes it to `volter-game-editor status`).
|
|
139
139
|
*
|
|
140
140
|
* Post-processing games legitimately render several (scene, camera) pairs per
|
|
141
141
|
* frame, so alternates are INFORMATION, never an error. Host renders are
|
|
@@ -433,7 +433,7 @@ export function installSceneCapture(
|
|
|
433
433
|
|
|
434
434
|
// Stash the real render fn per-instance under a unique symbol so multiple
|
|
435
435
|
// renderers (editor's + game's) never collide.
|
|
436
|
-
const REAL = Symbol('
|
|
436
|
+
const REAL = Symbol('volter.realRender');
|
|
437
437
|
|
|
438
438
|
let captured: CapturedRuntime | null = null;
|
|
439
439
|
let drawCount = 0;
|
|
@@ -461,7 +461,7 @@ export function installSceneCapture(
|
|
|
461
461
|
// prototype getter/setter. The constructor's `this.setAnimationLoop = realFn` hits
|
|
462
462
|
// our SETTER (the instance has no own property yet) and we stash realFn per-instance;
|
|
463
463
|
// the GETTER returns a wrapper that records each non-null callback before forwarding.
|
|
464
|
-
const REAL_SAL = Symbol('
|
|
464
|
+
const REAL_SAL = Symbol('volter.realSetAnimationLoop');
|
|
465
465
|
const loopCallbacks = new WeakMap<object, (time: number) => void>();
|
|
466
466
|
const loopedRenderers = new Set<object>();
|
|
467
467
|
/** Visibility clock of the in-flight `waitForCapture`, if any. */
|
|
@@ -810,7 +810,7 @@ export function installSceneCapture(
|
|
|
810
810
|
waiters.push(wrapped);
|
|
811
811
|
waitingVisibility = opts.visibility ?? documentVisibilityClock();
|
|
812
812
|
opts.onWait?.(captureWindow);
|
|
813
|
-
// A waiter that starts already-hidden (the normal `
|
|
813
|
+
// A waiter that starts already-hidden (the normal `volter-game-editor play` path
|
|
814
814
|
// against a backgrounded tab) must not wait for a human to foreground
|
|
815
815
|
// it. Pump any loop the game has already registered.
|
|
816
816
|
queueMicrotask(pumpHiddenLoops);
|
|
@@ -28,7 +28,7 @@ export const CAMERA_ID = 'ingest:camera';
|
|
|
28
28
|
/**
|
|
29
29
|
* The editor parks its OWN objects — grid, its two lights, the particle
|
|
30
30
|
* BatchedRenderer, every TransformControls/gizmo helper — on layer 31
|
|
31
|
-
* (`@
|
|
31
|
+
* (`@volter/threejs/viewport/editor-layers`'s `EDITOR_LAYER`) so the game camera
|
|
32
32
|
* never sees them. On an ingest root those objects are added to the GAME'S OWN
|
|
33
33
|
* scene, which is the same tree this walk indexes.
|
|
34
34
|
*/
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* render while its tab is hidden, because the browser parks `requestAnimation
|
|
9
9
|
* Frame` for a backgrounded document. The two facts together make one
|
|
10
10
|
* deterministic failure: a tab that opens in the BACKGROUND (the normal human
|
|
11
|
-
* path — `
|
|
11
|
+
* path — `volter-game-editor edit` auto-opens a tab that routinely lands behind the current
|
|
12
12
|
* window) burns its whole capture window unable to draw, the deadline fires,
|
|
13
13
|
* the mount dies terminally, and foregrounding the tab later changes nothing.
|
|
14
14
|
* Agents, whose tabs happen to be visible, never saw it.
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* budget is not a failure — a human returning to the tab is what spends it —
|
|
27
27
|
* and a cap would be exactly the boot-time clock this module exists to
|
|
28
28
|
* remove. The parked wait is reported instead of being silent: see
|
|
29
|
-
* `CaptureWaitObserver` in `scene-capture.ts` and `
|
|
29
|
+
* `CaptureWaitObserver` in `scene-capture.ts` and `volter-game-editor status`'s
|
|
30
30
|
* `ingestCaptureWait`.
|
|
31
31
|
*
|
|
32
32
|
* The state machine is a pure function of (banked segments, now, hidden) so
|
|
@@ -223,7 +223,7 @@ export interface CaptureWaitOptions {
|
|
|
223
223
|
*
|
|
224
224
|
* A wait parked on a hidden tab is otherwise indistinguishable from a hung
|
|
225
225
|
* mount: nothing renders, nothing fails, and every door reports silence.
|
|
226
|
-
* This is the seam the editor publishes to `
|
|
226
|
+
* This is the seam the editor publishes to `volter-game-editor status` so the answer is
|
|
227
227
|
* "waiting for the first visible frame — the tab is hidden", not a countdown
|
|
228
228
|
* that is not running.
|
|
229
229
|
*/
|
|
@@ -3,7 +3,7 @@ import { PHASE_ORDER, type SystemPhaseName } from '@volter/editor-project/core/s
|
|
|
3
3
|
/**
|
|
4
4
|
* D1 — the canonical `AnimationClock` (spec §10 D1, §3.2, §4).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* VOLTER owns exactly one clock per cinematic/scene context. It is the single
|
|
7
7
|
* source of truth for "what time is it" that registered sequences,
|
|
8
8
|
* GSAP timelines, and cinematic cue evaluators are seeked against (D2/D5/D7
|
|
9
9
|
* — NOT implemented here, this unit is the clock only). The render seam
|
package/src/asset-loaders.ts
CHANGED
|
@@ -128,7 +128,7 @@ export async function loadSplat(url: string, providedBytes?: Uint8Array): Promis
|
|
|
128
128
|
const size = bounds.getSize(new THREE.Vector3()).multiplyScalar(1.5);
|
|
129
129
|
const center = bounds.getCenter(new THREE.Vector3());
|
|
130
130
|
const proxy = new THREE.Mesh(new THREE.BoxGeometry(size.x, size.y, size.z));
|
|
131
|
-
proxy.name = '
|
|
131
|
+
proxy.name = '__volter_splat_bounds';
|
|
132
132
|
proxy.position.copy(center);
|
|
133
133
|
proxy.visible = false;
|
|
134
134
|
proxy.raycast = () => {};
|
package/src/ecs/object-marks.ts
CHANGED
|
@@ -43,8 +43,8 @@ export interface ObjectMarkSchema {
|
|
|
43
43
|
skeletonEnabled: boolean;
|
|
44
44
|
engineInternal: boolean;
|
|
45
45
|
editorHelper: boolean;
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
volterComponentRoot: string;
|
|
47
|
+
volterBuiltInternal: boolean;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export const ObjectMarkKeys = {
|
|
@@ -53,8 +53,8 @@ export const ObjectMarkKeys = {
|
|
|
53
53
|
skeletonEnabled: 'skeletonEnabled',
|
|
54
54
|
engineInternal: 'engineInternal',
|
|
55
55
|
editorHelper: 'editorHelper',
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
volterComponentRoot: 'volterComponentRoot',
|
|
57
|
+
volterBuiltInternal: 'volterBuiltInternal',
|
|
58
58
|
} as const satisfies Record<keyof ObjectMarkSchema, string>;
|
|
59
59
|
|
|
60
60
|
export function getObjectMark<K extends keyof ObjectMarkSchema>(
|
package/src/ecs/user-data.ts
CHANGED
|
@@ -78,17 +78,17 @@
|
|
|
78
78
|
*
|
|
79
79
|
* Hierarchy-presentation convention (written by GAME code, read by the editor —
|
|
80
80
|
* see `../adapter/hierarchy-marks.ts`, which is the ONLY place these two are
|
|
81
|
-
* read/written from; the `
|
|
81
|
+
* read/written from; the `volter` prefix marks them as the HOST's namespace on a
|
|
82
82
|
* node a game owns, unlike every other key above, which the engine/editor also
|
|
83
83
|
* write):
|
|
84
|
-
* - `
|
|
84
|
+
* - `volterComponentRoot` — display name of the component instance this subtree
|
|
85
85
|
* IS. The node renders as one collapsed, expandable
|
|
86
86
|
* row named for it.
|
|
87
|
-
* - `
|
|
87
|
+
* - `volterBuiltInternal` — `true` on the ROOT of a subtree runtime code
|
|
88
88
|
* CONSTRUCTED rather than authored (skeleton bones,
|
|
89
89
|
* particle renderers). Subtree-scoped: everything
|
|
90
90
|
* below a marked node is built-internal too.
|
|
91
|
-
* - `
|
|
91
|
+
* - `volterBodyOwner` — the rigid body that OWNS this node's pose, written
|
|
92
92
|
* by the code that attaches the body (see
|
|
93
93
|
* `../adapter/body-marks.ts`, the only reader/writer).
|
|
94
94
|
* A transform edit on such a node must be applied to
|
|
@@ -147,7 +147,7 @@ export interface UserDataSchema extends ObjectMarkSchema {
|
|
|
147
147
|
authoringRoot: boolean;
|
|
148
148
|
authoringInstance: string;
|
|
149
149
|
authoringLabel: string;
|
|
150
|
-
|
|
150
|
+
volterBodyOwner: RapierEditableBody;
|
|
151
151
|
authoringComponent: string;
|
|
152
152
|
authoringDocument: {
|
|
153
153
|
readonly kind: 'project-tool';
|
|
@@ -198,7 +198,7 @@ export const UserDataKeys = {
|
|
|
198
198
|
authoringRoot: 'authoringRoot',
|
|
199
199
|
authoringInstance: 'authoringInstance',
|
|
200
200
|
authoringLabel: 'authoringLabel',
|
|
201
|
-
|
|
201
|
+
volterBodyOwner: 'volterBodyOwner',
|
|
202
202
|
authoringComponent: 'authoringComponent',
|
|
203
203
|
authoringDocument: 'authoringDocument',
|
|
204
204
|
authoringHierarchyId: 'authoringHierarchyId',
|
|
@@ -50,7 +50,7 @@ export type IblOverrideShader = Parameters<MeshStandardMaterial['onBeforeCompile
|
|
|
50
50
|
* lives here, so a per-consumer name would be a string two files have to agree
|
|
51
51
|
* on with nothing checking that they do.
|
|
52
52
|
*/
|
|
53
|
-
export const IBL_WORLD_POSITION = '
|
|
53
|
+
export const IBL_WORLD_POSITION = 'volterIblWorldPosition';
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Three's own IBL chunk with `getIBLIrradiance`/`getIBLRadiance` renamed to
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# realism-effects compatibility fork
|
|
2
2
|
|
|
3
3
|
This directory vendors the published `realism-effects@1.1.2` distribution
|
|
4
|
-
(MIT license) so `@
|
|
4
|
+
(MIT license) so `@volter/threejs-runtime` remains installable as a self-contained source
|
|
5
5
|
package. The upstream package still imports Three's removed
|
|
6
6
|
`WebGLMultipleRenderTargets` API and has no release compatible with Three r180.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
VOLTER's fork contains only the mechanical r180 MRT migration:
|
|
9
9
|
|
|
10
10
|
- `WebGLMultipleRenderTargets(width, height, count, options)` becomes
|
|
11
11
|
`WebGLRenderTarget(width, height, { ...options, count })`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "realism-effects",
|
|
3
|
-
"version": "1.1.2-
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.2-volter.1",
|
|
4
|
+
"description": "VOLTER-maintained Three r180-compatible fork of realism-effects 1.1.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|