An object is a bundle of meaning#
A chair needs geometry, a position, a material, and perhaps a collision shape. A camera needs a position and a projection. An entity is the shared identity that ties such components together. Components hold data; systems perform work over the relevant component arrays. QubicEngine’s Scene stores a generation-checked Entity and dense component pools. An entity can have a Transform without a MeshRenderer. The renderer only extracts entities that have the required render components and ready assets. Deleting an entity removes its relationships and invalidates old handles.
From local space to world space#
A lamp attached to a moving vehicle keeps its own local position. Its world position changes when the parent changes. With this handbook’s row-vector convention, a child world matrix is localMatrix multiplied by parentWorld. Translation, rotation, and scale are composed consistently; camera view transforms perform the inverse operation.
Move the world. Move the camera. This illustration uses canvas. The explanation below describes the same process.
The cube demonstrates model transforms and perspective projection. Rotating the object changes its local-to-world transform. Moving the camera changes the view. Changing field of view changes projection rather than stretching the mesh in the world.
Implementation: hierarchy rules
// Conceptual engine math; Matrix4 stores row-major floats.
world[entity] = local[entity] * world[parent[entity]];
// With no parent:
world[root] = local[root];Scene validates a reparent operation before committing it. Walking ancestors must never return to the child. A hierarchy update orders parents before descendants and propagates dirty flags. To preserve world placement while reparenting, set newLocal to oldWorld multiplied by inverse(newParentWorld). A zero scale can make that inverse undefined; reject the operation or explicitly define the editor’s behavior.
Simulation and render state#
Physics writes authoritative dynamic body transforms at fixed intervals. Rendering interpolates previous and current simulation poses using the remaining accumulator fraction. Interpolation smooths motion; it does not run extra physics. A camera driven directly by user input may use a separately designed late update to reduce perceived latency. Animation updates local joint poses, then accumulates a skeleton hierarchy. Scene hierarchy and skeleton hierarchy are related concepts with different ownership: an entity transform places a character, while its joints deform vertices inside that character.
Serialization and references#
A scene file stores stable document IDs, component type/version identifiers, local transforms, parent IDs, and asset paths or asset IDs. It does not store raw pointers, GPU descriptors, or allocator addresses. Loading first creates identities, then resolves relationships, validates components, and requests assets. Asset requests may finish after the scene appears. A MeshRenderer uses a fallback material while its material loads; a missing mesh can use a deliberately designed proxy bounds display in the editor. The runtime reports a meaningful asset error with the source path instead of silently dereferencing an invalid handle.
Costs and common failures#
Dense component arrays improve iteration locality, but moving elements requires updating index maps. Deep transform chains increase dependency depth. Update only dirty subtrees, and avoid recalculating unchanged world matrices in unrelated systems. A child that jumps when reparented usually has a local/world conversion mistake. A mirrored mesh may have a negative scale that reverses winding. A camera that moves backward may mix left-handed and right-handed conventions. Inspect each space separately and use a known axis visualization before changing the renderer.
Related systems#
Continue with mesh and material data, editor commands, and skeletal animation. See matrix for the plain-language definition.