The physical bounding volume of the object.
32-bit collision layer bitmask this object belongs to (default: 1).
32-bit collision mask specifying which layers this object interacts with (default: 0xFFFFFFFF).
Optional integer identifier for deterministic physics solver sorting and netcode lockstep.
Inverse bind matrix used to transform vertices from mesh space to bone space.
Whether this object should generate bounds and participate in physics/raycasting. Defaults to true.
If true, this object acts as a trigger/sensor (fires trigger events without physical force).
OptionalonOptionalpendingSet by Scene on its hidden root object. Lets remove() notify the owning scene to queue
GPU-resource release for a discarded subtree even when called on a nested object directly
(someParent.remove(child)) instead of through Scene.remove() -- see remove()/add().
OptionalprefabName of the Maker prefab this node was instantiated from, if any -- provenance only, per
ADR 0010's Phase 2 "stamped copies" decision: no live link back to the source, just a record
of where this subtree came from. Round-tripped via the SW_prefab_instance glTF extension
(WorldWriter/GltfLoader).
OptionalquaternionOptionalrigidOptionaltagOptional app-defined category tag, for typed identification instead of matching on name.
Custom user-defined data storage dictionary.
ReadonlyuuidStatic ReadonlyinspectorBase schema every object exposes regardless of subclass -- see
collectInspectorSchema() in ./Inspectable.js, which merges this with whatever a
subclass (e.g. AbstractLight, AbstractMaterial) declares on top. Transform fields use
path since position/rotation/scale are nested Vector3D instances, not own properties.
Set only by WebGPU Hierarchical-Z occlusion culling (see docs/adr/0008-...), one frame
stale by design (mapAsync GPU->CPU readback is never synchronous). Unlike inFrustum,
NOT reset every frame -- only WebGPURenderer.applyPendingOcclusionResults() writes it, for
whichever objects it has a fresh readback for; everything else keeps its last known value.
Always false on WebGL1/WebGL2 (never written there), making Scene._collectVisible()'s
check a permanent no-op on those backends.
Returns an independent copy of this object's subtree -- own uuid, own transform, own
material (via AbstractMaterial.clone()), own behaviors (via Behavior.clone(), re-attached
so onAttach() runs against the new instance), and a recursive clone of every child. Used by
Maker's Duplicate command.
geometry and any texture references stay shared by reference -- immutable data, same as
every other "place another instance" workflow in the engine. parent/bounds reset (the
caller reparents and bounds recompute lazily); rigidBody is deliberately dropped rather
than shared, since two objects driven by the same live physics body would move together.
Known gap: skinned meshes aren't specially handled -- a cloned SkinnedMesh's skeleton
would still reference the original subtree's bones, not the freshly cloned ones alongside
it. Not a concern for Maker's realistic Duplicate targets (props, lights, prefab instances);
character rigs go through the Prefab/glTF pipeline instead.
The bone's current accumulated uniform world-space scale -- 1.0 for a "clean" rig, but
often far from it: FBX-to-glTF pipelines (Mixamo included) commonly leave a leftover
cm-to-m unit-conversion scale (e.g. ~100x) baked into an ancestor node somewhere above the
bone. GPU skinning never shows this: Skeleton.update() computes
bone.worldMatrix * inverseBindMatrix, relative to the bone's own bind pose, so any scale
shared with the skinned mesh's own ancestor chain cancels out there regardless of its value.
A plain Object3D parented directly onto a bone (e.g. a hand-held prop) has no such
cancellation and inherits the raw scale -- multiply an attached child's own scale by
1 / bone.getAccumulatedWorldScale() to counteract it (and its local position offset the
same way, or track world position directly instead of parenting -- see
AndNowScene2._syncLanternTransform() in apps/and-now/scenes/flakturm-tunnel/showcase.ts
for a worked example, including why it deliberately does NOT parent onto the bone at all).
This is detection only, by design: automatically "baking" the scale out of the rig itself
(resetting ancestor scale to 1, distributing it into descendant positions, and correcting
inverseBindMatrix to compensate) was attempted and reverted -- it breaks skinning whenever
the skinned mesh and the bone hierarchy are SIBLING branches under the same scaled ancestor
(the common real-world topology, including this engine's own Mixamo-derived rigs): the mesh's
own world matrix shares and cancels that ancestor scale exactly the same way the bones' does,
so "fixing" only the bones' side re-introduces the scale factor into the skinning result
instead of removing it. Requires updateMatrixWorld() to have run at least once.
Reads this object's position in world space, i.e. after resolving the full parent
chain -- unlike position, which is always local to its immediate parent. Requires
worldMatrix to be current (see updateMatrixWorld()).
Optional vector to write into, to avoid allocating one per call. If omitted, a shared module-level scratch is used and overwritten by the next call.
Traverses the object and all its descendants in depth-first order, executing the callback for each.
Static_StaticresetResets the global object ID generator (useful for deterministic tests).
Represents a single bone in a skeletal hierarchy.