Lysa  0.0
Lysa 3D Engine
Loading and displaying an asset

RotatingAssetScene.cpp : constructor

Asset initialisation happens in RotatingAssetScene::RotatingAssetScene. The constructor sets the ambient environment, loads the pack, attaches the imported subtree to root, registers every mesh instance with the renderer, and positions the camera.

Ambient environment

setEnvironment({lysa::float3{1.0f, 1.0f, 1.0f}, 0.20f});

setEnvironment sets a constant-colour ambient term applied to all surfaces in the scene. The first argument is the RGB sky colour; the second is the intensity (0–1). A neutral white at 0.20 keeps shadowed surfaces visible without introducing a colour cast. Without an ambient term, surfaces facing away from all lights would be rendered pure black.

Asset packs

Lysa stores 3D scenes in binary .assets files produced by the gltf2lysa converter. A pack bundles meshes, materials, textures, and the scene hierarchy into a single file. Advantages of using a custom format include:

  • Binary layout : no JSON parsing; data can be memory-mapped directly.
  • GPU-native images : textures are pre-compressed in BCn formats and uploaded to VRAM in a single transfer without an intermediate CPU decode step.
  • Pre-baked mip levels : all mip chains are computed offline, saving runtime CPU cost.
  • Pre-calculated transforms : node transforms are baked as float4x4 so no decomposition or recomposition is needed at load time.

The app:// URI scheme is resolved by the engine's virtual filesystem relative to the working directory:

const auto asset = load("app://res/models/crate.assets");

load() calls lysa::AssetsPack::load internally (see Scene node hierarchy). It returns the root of the imported hierarchy as a std::shared_ptr<SceneInstance>.

Note
Because the loader uploads GPU resources on the async transfer queue and then waits for the queue to be idle before returning, the call to load may take a noticeable amount of time for large assets. It's considered a good practice to call it in a background thread.

Attaching and registering

root.setTransform(lysa::float4x4::identity());
root.addChild(asset);
addInstance(root);

root is the top-level node of the SceneTree. Attaching the loaded subtree to it makes the asset a child of the root, so any transform set on root — including the Y-axis rotation : is inherited by the entire asset hierarchy through the recursive update() chain.

addInstance(root) performs the first registration with the renderer by walking the full tree and calling lysa::Scene::addInstance on every SceneMeshInstance it finds (see Scene tree).

Camera placement

camera.setTransform(lysa::float4x4::translation(0.0f, 0.0f, 4.0f));

The camera is placed 4 units directly behind the world origin, centred vertically on the asset. This distance is appropriate for a unit-scale model such as the crate. For a larger model you have two options:

  • Move the camera farther back: lysa::float4x4::translation(0.0f, 0.0f, 40.0f)
  • Scale the root transform to normalise the model to unit size:
root.setTransform(lysa::float4x4::scale(0.01f));

Scaling via the root node is non-destructive: the asset's local-space data remains unchanged and you can rescale at any time.

Next : Lights