![]() |
Lysa
0.0
Lysa 3D Engine
|
SceneInstance.ixx and SceneInstance.cpp Lysa provides GPU-level primitives (lysa::MeshInstance, lysa::Scene, …) but does not prescribe a scene-graph or an ECS. This sample implements a thin wrapper that organises renderables into a parent-child tree.
SceneInstance SceneInstance is the base tree node. It stores a localTransform (the transform relative to its parent) and a globalTransform (the world-space result). update() recomputes the global transform recursively:
Calling setTransform() on a node sets its localTransform and marks it dirty. The dirty flag is purely a hint; in this sample the full tree is always re-evaluated from the root each process tick by SceneTree::onProcess (see Scene tree). In a larger scene graph or an ECS you would skip the GPU upload for nodes whose dirty flag is clear.
lysa::MeshInstance vs SceneMeshInstance Understanding the two-level split is important:
lysa::MeshInstance is the engine-side GPU handle. It stores the world transform, AABB, visibility, and shadow-cast flag that the renderer reads from GPU memory every frame. It is unaware of your application's scene-graph structure.SceneMeshInstance is your application-side wrapper. It owns a lysa::MeshInstance and keeps it in sync with the scene-graph transform.This separation lets you build any hierarchy you want while still satisfying the flat list of lysa::MeshInstance objects that the renderer expects.
SceneMeshInstance SceneMeshInstance extends SceneInstance and owns a lysa::MeshInstance. Its update() override pushes the world transform and the world-space AABB to the engine after the base class has computed globalTransform:
The AABB is used by the GPU draw commands generation and frustum-culling compute shaders. It must cover the mesh in world space after the transform is applied. AABB::toGlobal re-computes the axis-aligned bounds from the mesh's local-space AABB and the world transform, accounting for rotation.
DummyAnimationPlayer lysa::AssetsPack::load requires a third template parameter for an animation player node. DummyAnimationPlayer is a no-op stub that satisfies this interface when animation playback is not needed:
When a .assets file contains animation data the loader creates one DummyAnimationPlayer as a child of the root so the animation library is still accessible, but no playback logic runs.
The free function load() wraps lysa::AssetsPack::load with the three concrete node types used in this project:
Internally AssetsPack::load:
.assets file through the virtual filesystem.lysa::StandardMaterial objects from the material headers and upload them to GPU VRAM.lysa::Mesh objects and uploads vertex / index data to the GPU VRAM.std::shared_ptr<T_OBJECT>.The loader is designed to be called once per asset file. The resulting subtree is live: once addInstance has registered its mesh instances with the renderer, the subtree drives rendering every frame.
clone() performs a deep copy of an existing subtree. It is useful for placing multiple independent instances of the same loaded asset in the scene without reloading from disk:
SceneMeshInstance's copy constructor creates a new lysa::MeshInstance that shares the same underlying lysa::Mesh (GPU geometry is not duplicated). Only the per-instance transform, AABB, and visibility are independent. This makes instancing dozens of copies of the same model inexpensive in both VRAM and load time.
Next : Scene tree