@solidrt/3d 0.0.56 → 0.0.57
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/AGENTS.md +199 -117
- package/README.md +2 -1
- package/examples/README.md +13 -8
- package/examples/collision.tsx +17 -4
- package/examples/first-person.tsx +20 -10
- package/examples/fleet.tsx +11 -5
- package/examples/model.tsx +3 -3
- package/examples/pick.tsx +144 -34
- package/examples/probe.tsx +10 -4
- package/examples/scene-views.tsx +49 -58
- package/examples/sky-lit.tsx +10 -4
- package/examples/skybox.tsx +10 -4
- package/examples/standard.tsx +10 -4
- package/package.json +2 -2
- package/src/collision.ts +14 -193
- package/src/components/context.tsx +35 -0
- package/src/components/directional-light.tsx +48 -0
- package/src/components/first-person-camera.tsx +72 -0
- package/src/components/group.tsx +18 -0
- package/src/components/hemisphere-light.tsx +24 -0
- package/src/components/index.ts +46 -0
- package/src/components/instanced-mesh.tsx +105 -0
- package/src/components/mesh.tsx +92 -0
- package/src/components/node-props.ts +90 -0
- package/src/components/orbit-camera.tsx +75 -0
- package/src/components/perspective-camera.tsx +32 -0
- package/src/components/point-light.tsx +52 -0
- package/src/components/record-mesh.tsx +68 -0
- package/src/components/scene.tsx +281 -0
- package/src/components/spot-light.tsx +65 -0
- package/src/components/sprite.tsx +38 -0
- package/src/components/view3d.tsx +152 -0
- package/src/first-person.ts +140 -188
- package/src/index.ts +13 -9
- package/src/input.ts +70 -0
- package/src/node.ts +98 -25
- package/src/orbit.ts +266 -235
- package/src/scene-pointer.ts +229 -101
- package/src/scene.ts +250 -76
- package/src/components.tsx +0 -1101
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// PerspectiveCamera) on top. See AGENTS.md for the model and the traps.
|
|
7
7
|
|
|
8
8
|
export { add, createGroup, getRotation, getTransform, lookAt, remove, setTransform, setTransition, setVisible, worldPosition } from "./node.ts"
|
|
9
|
-
export type { SceneNode, ScenePointerEvent, TransformUpdate, TransitionEndEvent } from "./node.ts"
|
|
9
|
+
export type { NodePointerEvent, NodeTapEvent, NodeWheelEvent, SceneEventBase, SceneNode, ScenePointerEvent, ScenePointerListener, SceneTapEvent, SceneWheelEvent, TransformUpdate, TransitionEndEvent } from "./node.ts"
|
|
10
10
|
export { addInstance, createInstancedMesh, createMesh, createRecordMesh, createSprite, disposeInstances, removeInstance, setCastShadow, setCulling, setGeometry, setInstanceStyle, setLayers, setMaterial, setMeshParams, setRecordCount, setRecords, setRenderOrder, INSTANCE_FLOATS } from "./mesh.ts"
|
|
11
11
|
export type { InstancedMesh as InstancedMeshNode, InstancedMeshOptions, InstanceNode, InstanceSlots, InstanceStyle, Mesh as MeshNode, MeshInstances, RecordMesh as RecordMeshNode, RecordMeshOptions } from "./mesh.ts"
|
|
12
12
|
export { createDirectionalLight, createHemisphereLight, createPointLight, createSpotLight, setLight, MAX_SHADOWS } from "./light.ts"
|
|
@@ -26,9 +26,10 @@ export type {
|
|
|
26
26
|
SpotShadowOptions,
|
|
27
27
|
} from "./light.ts"
|
|
28
28
|
export { createScene } from "./scene.ts"
|
|
29
|
-
export
|
|
29
|
+
export { feedPointer } from "./scene-pointer.ts"
|
|
30
|
+
export type { Capsule, EnvironmentOptions, FogOptions, Hit, Impact, MoveOptions, MoveResult, OrientedBox, Overlap, QueryOptions, ReflectionProbe, ReflectionProbeOptions, Scene as SceneHandle, SceneHandlers, SceneOptions, ScreenRay, SkyboxOptions, Sphere, ToneMapping, ViewHandle, ViewOptions, Volume } from "./scene.ts"
|
|
30
31
|
export { moveAndSlide } from "./collision.ts"
|
|
31
|
-
export type {
|
|
32
|
+
export type { MoveScene } from "./collision.ts"
|
|
32
33
|
export { equirectToCube, loadEnvironment } from "./environment.ts"
|
|
33
34
|
export { linearColor, linearToSrgb, srgbToLinear } from "./color.ts"
|
|
34
35
|
export type { CameraState, CameraUpdate, OrthoExtent } from "./camera.ts"
|
|
@@ -42,8 +43,9 @@ export { extrude, lathe, pathFrames, sweep, tube } from "./sweep.ts"
|
|
|
42
43
|
export type { ExtrudeOptions, LatheOptions, PathFrames, PathPoint, SweepPath, TubeOptions } from "./sweep.ts"
|
|
43
44
|
export { lit, shaderMaterial, shaderMaterialClass, sprite, standard, unlit } from "./material.ts"
|
|
44
45
|
export type { LitOptions, Material, ShaderMaterialClass, ShaderMaterialClassOptions, ShaderMaterialInstanceOptions, ShaderMaterialOptions, SpriteOptions, StandardOptions, UnlitOptions } from "./material.ts"
|
|
45
|
-
export { DirectionalLight, FirstPersonCamera, Group, HemisphereLight, Instance, InstancedMesh, Mesh, OrbitCamera, PerspectiveCamera, PointLight, RecordMesh, Scene, SpotLight, Sprite, useScene } from "./components.
|
|
46
|
+
export { DirectionalLight, FirstPersonCamera, Group, HemisphereLight, Instance, InstancedMesh, Mesh, OrbitCamera, PerspectiveCamera, PointLight, RecordMesh, Scene, SpotLight, Sprite, View3d, useScene } from "./components/index.ts"
|
|
46
47
|
export type {
|
|
48
|
+
CameraTarget,
|
|
47
49
|
DirectionalLightProps,
|
|
48
50
|
FirstPersonCameraProps,
|
|
49
51
|
HemisphereLightProps,
|
|
@@ -55,13 +57,13 @@ export type {
|
|
|
55
57
|
PointerEventProps,
|
|
56
58
|
PointLightProps,
|
|
57
59
|
RecordMeshProps,
|
|
58
|
-
|
|
59
|
-
SceneInputListener,
|
|
60
|
+
ScenePointerProps,
|
|
60
61
|
SceneProps,
|
|
61
62
|
SpotLightProps,
|
|
62
63
|
SpriteProps,
|
|
63
64
|
TransformProps,
|
|
64
|
-
|
|
65
|
+
View3dProps,
|
|
66
|
+
} from "./components/index.ts"
|
|
65
67
|
export { gltfExternalUris, isGlb, parseGltf } from "./gltf.ts"
|
|
66
68
|
export type { ModelChannel, ModelClip, ModelData, ModelMaterial, ModelNode, ModelPart, ModelSkin, UriResolver } from "./gltf.ts"
|
|
67
69
|
export { decodeModel, encodeModel } from "./model-file.ts"
|
|
@@ -71,9 +73,11 @@ export { createMixer } from "./mixer.ts"
|
|
|
71
73
|
export type { Mixer, MixerOptions, MixerPlayOptions } from "./mixer.ts"
|
|
72
74
|
export { sampleChannel } from "./clip.ts"
|
|
73
75
|
export { createOrbitCamera } from "./orbit.ts"
|
|
74
|
-
export type { OrbitCamera as OrbitCameraHandle, OrbitCameraOptions, OrbitPose, OrbitTarget } from "./orbit.ts"
|
|
76
|
+
export type { OrbitAxes, OrbitCamera as OrbitCameraHandle, OrbitCameraOptions, OrbitPose, OrbitTarget } from "./orbit.ts"
|
|
75
77
|
export { createFirstPersonCamera } from "./first-person.ts"
|
|
76
|
-
export type { FirstPersonCamera as FirstPersonCameraHandle, FirstPersonCameraOptions, FirstPersonPose, FirstPersonTarget } from "./first-person.ts"
|
|
78
|
+
export type { FirstPersonAxes, FirstPersonCamera as FirstPersonCameraHandle, FirstPersonCameraOptions, FirstPersonPose, FirstPersonTarget } from "./first-person.ts"
|
|
79
|
+
export { firstPersonActions, firstPersonBindings, orbitActions, orbitBindings } from "./input.ts"
|
|
80
|
+
export type { CameraDevices } from "./input.ts"
|
|
77
81
|
// math's lookAt (the camera view matrix) stays on the /math subpath: the
|
|
78
82
|
// root's lookAt is the scene verb, the same split as `add`.
|
|
79
83
|
export { rayBoxDistance, compose, copy, eulerFromQuat, identity, mat4, multiply, normalMatrix, orthographic, perspective, quat, quatFromAxisAngle, quatFromEuler, quatFromFrame, quatFromTo, quatMultiply, quatNormalize, quatSlerp } from "./math.ts"
|
package/src/input.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// The standard input wiring for the 3d camera controls: the action
|
|
2
|
+
// declarations each control consumes (its axes, by the shared vocabulary)
|
|
3
|
+
// and a preset per control that binds the devices an app hands in. A
|
|
4
|
+
// preset is plain data - the bindings the app could write by hand -
|
|
5
|
+
// applied with `input.bind(orbitBindings({ pointer, gamepad }))` and
|
|
6
|
+
// adjusted afterwards with unbind; nothing binds unless the app says so
|
|
7
|
+
// (ARCHITECTURE.md).
|
|
8
|
+
//
|
|
9
|
+
// Devices are the nouns: `pointer` is the feed of the element showing the
|
|
10
|
+
// scene (`createPointerFeed()`, handed to `<Scene pointer>`), `gamepad` a
|
|
11
|
+
// core gamepad device (`gamepad(0)`, or `gamepad()` for any pad), and
|
|
12
|
+
// `keyboard` the core keyboard device, whose key events reach the map
|
|
13
|
+
// through `input.handlers` spread on the window.
|
|
14
|
+
//
|
|
15
|
+
// Keys and sticks move the CAMERA where a drag moves the content (the
|
|
16
|
+
// stick right orbits the eye to the right; a drag right spins the scene
|
|
17
|
+
// to the right), so the rotate and pan bindings of those devices go
|
|
18
|
+
// through invert() and each axis keeps its one meaning. `look` is the
|
|
19
|
+
// exception by nature: a drag and a stick both turn the eye.
|
|
20
|
+
|
|
21
|
+
import { invert } from "@solidrt/core/input"
|
|
22
|
+
import type { Binding, GamepadDevice, KeyboardDevice, PointerFeed } from "@solidrt/core"
|
|
23
|
+
|
|
24
|
+
export type CameraDevices = {
|
|
25
|
+
pointer?: PointerFeed
|
|
26
|
+
gamepad?: GamepadDevice
|
|
27
|
+
keyboard?: KeyboardDevice
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The orbit control's actions: `rotate`, `zoom`, `pan`. */
|
|
31
|
+
export let orbitActions = { rotate: "vec2", zoom: "axis", pan: "vec2" } as const
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The orbit camera's standard bindings: a drag rotates, a pinch and the
|
|
35
|
+
* wheel zoom, two fingers pan; the right stick rotates, the triggers
|
|
36
|
+
* zoom, the left stick pans; the arrow keys rotate and minus/equals zoom.
|
|
37
|
+
*/
|
|
38
|
+
export function orbitBindings(devices: CameraDevices): Binding[] {
|
|
39
|
+
let out: Binding[] = []
|
|
40
|
+
let { pointer, gamepad, keyboard } = devices
|
|
41
|
+
if (pointer) {
|
|
42
|
+
out.push({ action: "rotate", source: pointer.drag }, { action: "zoom", source: pointer.pinch }, { action: "zoom", source: pointer.wheel }, { action: "pan", source: pointer.pan })
|
|
43
|
+
}
|
|
44
|
+
if (gamepad) {
|
|
45
|
+
out.push({ action: "rotate", source: invert(gamepad.rightStick) }, { action: "zoom", source: gamepad.triggers }, { action: "pan", source: invert(gamepad.leftStick) })
|
|
46
|
+
}
|
|
47
|
+
if (keyboard) {
|
|
48
|
+
out.push({ action: "rotate", source: invert(keyboard.arrows) }, { action: "zoom", source: keyboard.axis("Minus", "Equal") })
|
|
49
|
+
}
|
|
50
|
+
return out
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The first-person control's actions: `look`, `move`, `rise`. */
|
|
54
|
+
export let firstPersonActions = { look: "vec2", move: "vec2", rise: "axis" } as const
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The first-person camera's standard bindings: a drag looks around and so
|
|
58
|
+
* does mouse motion while the pointer is locked (the app locks it: see
|
|
59
|
+
* examples/first-person.tsx); the right stick looks, the left stick
|
|
60
|
+
* walks, the shoulders rise and sink in fly mode; WASD and the arrows
|
|
61
|
+
* walk, Q/E rise and sink.
|
|
62
|
+
*/
|
|
63
|
+
export function firstPersonBindings(devices: CameraDevices): Binding[] {
|
|
64
|
+
let out: Binding[] = []
|
|
65
|
+
let { pointer, gamepad, keyboard } = devices
|
|
66
|
+
if (pointer) out.push({ action: "look", source: pointer.drag }, { action: "look", source: pointer.mouseDelta })
|
|
67
|
+
if (gamepad) out.push({ action: "look", source: gamepad.rightStick }, { action: "move", source: gamepad.leftStick }, { action: "rise", source: gamepad.shoulders })
|
|
68
|
+
if (keyboard) out.push({ action: "move", source: keyboard.wasd }, { action: "move", source: keyboard.arrows }, { action: "rise", source: keyboard.axis("KeyQ", "KeyE") })
|
|
69
|
+
return out
|
|
70
|
+
}
|
package/src/node.ts
CHANGED
|
@@ -10,12 +10,14 @@ import * as spatial from "flux:spatial"
|
|
|
10
10
|
import type { NodeId, NodeTransition } from "flux:spatial"
|
|
11
11
|
import { on } from "srt:events"
|
|
12
12
|
import type { ShaderParams, TextureId } from "@solidrt/core/gpu"
|
|
13
|
+
import type { PointerEvent as ElementPointerEvent, WheelEvent as ElementWheelEvent } from "@solidrt/core"
|
|
13
14
|
// The scene's lookAt() aims a node; math's builds a camera's view matrix -
|
|
14
15
|
// the same pairing (and the same name) as Three's Object3D/Matrix4.
|
|
15
16
|
import { compose, eulerFromQuat, identity, mat4, multiply, quat, quatFromFrame, transformPoint, updateRotation, updateScale } from "./math.ts"
|
|
16
17
|
import type { Mat4, Quat, TransformUpdate, Vec3, Vec4 } from "./math.ts"
|
|
17
18
|
import type { CastingLight, Light } from "./light.ts"
|
|
18
19
|
import type { InstancedMesh, InstanceNode, Mesh } from "./mesh.ts"
|
|
20
|
+
import type { Scene, ViewHandle } from "./scene.ts"
|
|
19
21
|
|
|
20
22
|
// lookAt()'s default roll reference. Read-only: quatFromFrame never
|
|
21
23
|
// writes its inputs, so one shared vector is safe.
|
|
@@ -107,15 +109,23 @@ export type SceneNode = {
|
|
|
107
109
|
visible: boolean
|
|
108
110
|
/** Pointer event handlers - plain fields, assign freely (they touch no
|
|
109
111
|
* GPU state, so they need no setTransform-style write path; components
|
|
110
|
-
* sync their props here). Down/move/up dispatch on the
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
* sync their props here). Down/move/up/wheel/tap dispatch on the
|
|
113
|
+
* nearest hit - the struck instance of an instanced mesh, else the mesh
|
|
114
|
+
* - bubble through its ancestors and end at the scene's listeners
|
|
115
|
+
* (stopPropagation stops the walk, and a stopped down claims the whole
|
|
116
|
+
* press); enter/leave fire on the struck node alone. Events flow once
|
|
117
|
+
* the element showing the scene carries `scene.handlers`. */
|
|
118
|
+
onPointerDown?: (event: NodePointerEvent) => void
|
|
119
|
+
onPointerMove?: (event: NodePointerEvent) => void
|
|
120
|
+
onPointerUp?: (event: NodePointerEvent) => void
|
|
121
|
+
onPointerEnter?: (event: NodePointerEvent) => void
|
|
122
|
+
onPointerLeave?: (event: NodePointerEvent) => void
|
|
123
|
+
/** The wheel over the node (NodeWheelEvent: `deltaX`/`deltaY`), bubbling
|
|
124
|
+
* like down/move/up. */
|
|
125
|
+
onWheel?: (event: NodeWheelEvent) => void
|
|
126
|
+
/** A press released on this node within the slop, alone for its whole
|
|
127
|
+
* press (NodeTapEvent: `tapCount`); bubbles like down/move/up. */
|
|
128
|
+
onTap?: (event: NodeTapEvent) => void
|
|
119
129
|
/** A declared transition (setTransition) settled naturally on one
|
|
120
130
|
* component; a cancel, snap or scene leave never fires. */
|
|
121
131
|
onTransitionEnd?: (event: TransitionEndEvent) => void
|
|
@@ -146,26 +156,19 @@ export type TransitionEndEvent = {
|
|
|
146
156
|
component: "position" | "rotation" | "scale"
|
|
147
157
|
}
|
|
148
158
|
|
|
149
|
-
/**
|
|
150
|
-
*
|
|
151
|
-
|
|
152
|
-
* `point`/`distance` are null exactly when the ray misses the dispatch
|
|
153
|
-
* target - which happens only during a captured drag or on a leave.
|
|
154
|
-
*/
|
|
155
|
-
export type ScenePointerEvent = {
|
|
156
|
-
/** The mesh the event is about (the hit, or the captured mesh during a
|
|
157
|
-
* drag) - constant while the event bubbles. */
|
|
158
|
-
mesh: Mesh
|
|
159
|
+
/** What every scene pointer event carries, whichever handler sees it:
|
|
160
|
+
* the element pointer vocabulary carried over, plus the 3D fields. */
|
|
161
|
+
export type SceneEventBase = {
|
|
159
162
|
/** The instance struck when `mesh` is an instanced mesh (the walk
|
|
160
163
|
* starts there), null otherwise - constant while the event bubbles. */
|
|
161
164
|
instance: InstanceNode | null
|
|
162
|
-
/**
|
|
163
|
-
|
|
164
|
-
/** World-space hit point on `mesh`, or null when the ray misses it. */
|
|
165
|
+
/** World-space hit point on `mesh`, or null when there is no mesh or
|
|
166
|
+
* the ray misses it (a captured drag off the mesh, a leave). */
|
|
165
167
|
point: Vec3 | null
|
|
166
168
|
/** Camera-ray distance to `point` in world units, or null with it. */
|
|
167
169
|
distance: number | null
|
|
168
|
-
/** Pointer position in scene pixels - project()'s coordinate space
|
|
170
|
+
/** Pointer position in scene pixels - project()'s coordinate space
|
|
171
|
+
* (a view's own pixels under a view leaf). */
|
|
169
172
|
x: number
|
|
170
173
|
y: number
|
|
171
174
|
pointerId: number
|
|
@@ -175,10 +178,77 @@ export type ScenePointerEvent = {
|
|
|
175
178
|
ctrlKey: boolean
|
|
176
179
|
altKey: boolean
|
|
177
180
|
metaKey: boolean
|
|
178
|
-
/**
|
|
181
|
+
/**
|
|
182
|
+
* The element event the scene's leaf received, in the leaf's own frame
|
|
183
|
+
* (localX/localY, clientX/clientY, movementX/Y): what core's
|
|
184
|
+
* recognizers consume, so a mesh drags itself through `createPan` and
|
|
185
|
+
* a camera control's feed rides the same events the walk carries.
|
|
186
|
+
*/
|
|
187
|
+
native: ElementPointerEvent
|
|
188
|
+
/**
|
|
189
|
+
* Stops the walk after the current handler: no ancestor and none of the
|
|
190
|
+
* scene's listeners see the event. Stopping a DOWN claims the whole
|
|
191
|
+
* press - that pointer's move, up and tap never reach the scene either,
|
|
192
|
+
* so a mesh that drags itself stops its down once and an orbit control
|
|
193
|
+
* fed at the root never turns under it.
|
|
194
|
+
*/
|
|
179
195
|
stopPropagation(): void
|
|
180
196
|
}
|
|
181
197
|
|
|
198
|
+
/**
|
|
199
|
+
* The event a mesh, instance or ancestor group handler receives: `mesh`
|
|
200
|
+
* is the hit (or the captured mesh during a drag), constant while the
|
|
201
|
+
* event bubbles; `currentTarget` the node whose handler is running.
|
|
202
|
+
*/
|
|
203
|
+
export type NodePointerEvent = SceneEventBase & {
|
|
204
|
+
mesh: Mesh
|
|
205
|
+
currentTarget: SceneNode
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The event as the SCENE's listeners see it (scene.listen, the `<Scene>`
|
|
210
|
+
* pointer props; a view's under its own leaf), the last stop of the walk:
|
|
211
|
+
* `mesh` is the hit it bubbled from, or null over empty space, where the
|
|
212
|
+
* scene is the only target.
|
|
213
|
+
*/
|
|
214
|
+
export type ScenePointerEvent = SceneEventBase & {
|
|
215
|
+
mesh: Mesh | null
|
|
216
|
+
currentTarget: Scene | ViewHandle
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
type WheelFields = {
|
|
220
|
+
/** The wheel delta as the element event reports it. */
|
|
221
|
+
deltaX: number
|
|
222
|
+
deltaY: number
|
|
223
|
+
native: ElementWheelEvent
|
|
224
|
+
}
|
|
225
|
+
type TapFields = {
|
|
226
|
+
/** 1 for a tap, 2 for the second of a double tap (the same target,
|
|
227
|
+
* within the repeat interval and distance), and so on - DOM's `detail`,
|
|
228
|
+
* Unity's `clickCount`. */
|
|
229
|
+
tapCount: number
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export type NodeWheelEvent = NodePointerEvent & WheelFields
|
|
233
|
+
export type SceneWheelEvent = ScenePointerEvent & WheelFields
|
|
234
|
+
/**
|
|
235
|
+
* A press that released on the target it pressed without travelling past
|
|
236
|
+
* the slop, the only pointer down for its whole press (a pinch never
|
|
237
|
+
* taps). Dispatched after the up, bubbling the same way; `x`/`y` and
|
|
238
|
+
* `point` are the release point.
|
|
239
|
+
*/
|
|
240
|
+
export type NodeTapEvent = NodePointerEvent & TapFields
|
|
241
|
+
export type SceneTapEvent = ScenePointerEvent & TapFields
|
|
242
|
+
|
|
243
|
+
/** A listener at the scene's (or a view's) root; see Scene.listen. */
|
|
244
|
+
export type ScenePointerListener = {
|
|
245
|
+
onPointerDown?: (event: ScenePointerEvent) => void
|
|
246
|
+
onPointerMove?: (event: ScenePointerEvent) => void
|
|
247
|
+
onPointerUp?: (event: ScenePointerEvent) => void
|
|
248
|
+
onWheel?: (event: SceneWheelEvent) => void
|
|
249
|
+
onTap?: (event: SceneTapEvent) => void
|
|
250
|
+
}
|
|
251
|
+
|
|
182
252
|
/** A bare node record (internal: the mesh and light constructors build on it). */
|
|
183
253
|
export function makeNode(kind: SceneNode["kind"]): SceneNode {
|
|
184
254
|
return {
|
|
@@ -245,7 +315,10 @@ export function enterScene(node: SceneNode, scene: SceneHooks): void {
|
|
|
245
315
|
}
|
|
246
316
|
}
|
|
247
317
|
if (node._cullBounds !== null) spatial.setCullBounds(node._node, node._cullBounds)
|
|
248
|
-
if (node.kind === "mesh")
|
|
318
|
+
if (node.kind === "mesh") {
|
|
319
|
+
spatial.setLayers(node._node, (node as Mesh).layers)
|
|
320
|
+
scene._attach(node as Mesh)
|
|
321
|
+
}
|
|
249
322
|
else if (node.kind === "light") scene._attachLight(node as Light)
|
|
250
323
|
else if (node.kind === "instance") scene._attachInstance(node as InstanceNode)
|
|
251
324
|
for (let c of node.children) enterScene(c, scene)
|