Skip to content

Camera TOML Demo

App: apps/camera_toml_demo/

Camera rigs authored as data, not Wren code (PLM-283, ADR 0104) — the data-authored twin of the Camera Showcase. The whole camera setup is one line: Cam.loadAssets(scene, "cameras.toml"). No Cam.thirdPerson / Cam.orbit calls, no draw() plumbing. Mid-run it blends to a rig looked up by its TOML name via Cam.rig(scene, "overview").

Terminal window
% ./plume3d camera_toml_demo

Self-screenshots cam_toml_follow (the “follow” rig, active on load) and cam_toml_overview (after blending to the “overview” rig), then exits.

cameras.toml declares two [[rig]]s. Each picks a preset by type, resolves target by SceneNode id (the Scene.addNode name — here "player"), and applies overrides; omitted keys keep the preset default. The active rig becomes the live camera on load, and each name registers the rig for Cam.rig.

[[rig]]
name = "follow"
type = "thirdPerson"
target = "player"
active = true
distance = 6.0
shoulder = [0.6, 1.6]
damping = 0.25
[[rig]]
name = "overview"
type = "orbit"
target = "player"
radius = 11.0
noise = [0.12, 0.5]
fov = 0.9

On init, the entire rig set is built from the file in a single call — no per-rig code:

var n = Cam.loadAssets(_scene, "cameras.toml") // -> 2 rigs; "follow" is active

Each frame it drives the player in a circle so the follow reads, then, on cue, blends to the rig it looks up by its TOML name — proving the name registry and a data-authored blend:

update(dt) {
_t = _t + dt
_player.setPosition(_t.sin * 5, 0.5, _t.cos * 5) // the "follow" rig tracks it
if (_fc == 130) {
var overview = Cam.rig(_scene, "overview") // look the rig up by its TOML name
if (overview != null) Cam.blendTo(overview, 1.2, Ease.easeInOut)
}
}
draw() {
_scene.draw() // the TOML-built director pushed view/proj
// ...draw the floor, player, and obstacle cubes...
}

Because the loader drives the same presets and field mapping as the fluent CameraRig setters, the TOML follow rig is identical to camera_showcase’s coded Cam.thirdPerson(...).distance(6).shoulder(...) — the two demos render the same, one authored in code and one authored as data.