# Cameras (3D) `Camera3D` (in `simvx.core.nodes_3d`) is a `Node3D` subclass that supplies view + projection matrices to the renderer. The first `Camera3D` found in the scene tree is the active camera; render layers can be masked via `cull_mask`. ```python from simvx.core import Camera3D, Node, Vec3 class Scene(Node): def on_ready(self): self.add_child(Camera3D( position=(0, 5, 10), look_at=Vec3(0, 0, 0), fov=70.0, near=0.1, far=200.0, )) ``` ## Conventions SimVX uses the following conventions for 3D math and cameras. They are load-bearing: read them once and assume they hold everywhere unless a specific subsystem (e.g. the Vulkan clip-space transposition) states otherwise. ### Coordinate space - **Right-handed**, Y-up by default. - **Forward = local -Z.** `Node3D.forward` (and therefore `Camera3D.forward`) returns `world_rotation * (0, 0, -1)`. This matches Godot, glTF, Maya, Blender's runtime export, and the OpenGL family. It clashes with Unity and Unreal (+Z forward), so ports from those engines need to negate the forward vector once at import. - **Right = local +X**, **up = local +Y**. ### Look-at / face-along - `Node3D.look_at(target, up=…)` rotates the node so its local -Z axis points at `target` in world space. - `Node3D.face_along(direction, up=…)` does the same with a direction vector, skipping the target subtraction. Convenient for steering by velocity. - `Quat.look_at(direction, up=…)` is the underlying primitive. It already bakes the -Z negation: pass the direction the node should *face*, not the direction the local +Z axis should land on. ### Matrices - All matrices are stored **row-major** as NumPy arrays. - Vulkan shaders read column-major; the renderer transposes once at the GPU boundary in `renderer/forward.py`. - `Camera3D.projection_matrix()` flips the Y axis (`proj[1, 1] *= -1`) to match Vulkan's clip-space Y-down convention. Other renderers (web / WebGPU) apply their own clip-space fixup; the row-major matrix that leaves Camera3D is the same. ### Angles - All internal angles are in **radians** (`fov` on `Camera3D` is the exception: declared in degrees for the inspector and converted at matrix-build time). - UI / debug code converts to degrees for display. There is no separate "radians camera" type. ## OrbitCamera3D A turntable camera with `yaw`, `pitch`, `distance`, and `pivot` Properties. Useful for editor viewports and model viewers; not intended for first-person games. ## Multiple cameras The forward renderer's `ViewportManager` supports multiple active cameras for split-screen or picture-in-picture. Add several `Camera3D` nodes and bind them to viewports via the renderer's viewport API.