Camera System
Relevant source files
The following files were used as context for generating this wiki page:
The Camera System manages the viewpoint through which the world is rendered, balancing technical fidelity to the original game with modern inspection requirements. It differentiates between the logical camera pose, which dictates game logic and collision, and the render camera pose, which determines the visual output for the player.
The system integrates directly with the SOUP script engine to handle cinematic tasks, provides a "faithful" follow camera for gameplay, and includes a separate preview camera for the asset viewer.
Architecture
The system operates across three distinct layers: the Logical Session, the Per-Frame Driver, and the Render Camera.
Logical and Render Poses
Cyrus maintains two distinct poses for the camera to ensure smooth visuals without compromising logical consistency:
- CameraPose: Represents the logical state, including precise map-unit coordinates and orientation. It is used for collision detection and script triggers.
- RenderPose: Represents the visual state. During "cuts" (like scene starts), the render pose snaps to the logical pose. During gameplay, it glides toward the logical pose based on installed glide factors (position and angle).
Sources: crates/cyrus-game/src/script/registry/camera_drive.rs:22-25, crates/cyrus-game/tests/script_camera_session.rs:434-450
The diagram shows the flow from the logical session and drivers through the snap/glide transition into the final render pose used by the renderer.
Camera State Management
State is persisted in the CameraFrameState resource. This resource tracks collision hit history and the last published pose. It clears its data when the driven world changes to prevent stale collision or publication data from leaking into new sessions.
Sources: crates/cyrus-game/src/script/registry/camera_drive.rs:32-48
Scripting and Cinematic Tasks
The script engine controls the camera through "tasks" that manipulate CameraSlot records. Record zero is typically reserved for the player follow camera.
Native Camera Functions
Scripted tasks allow actors to request camera movement or focus. Key native functions include:
showPlayer: Resets the camera to follow the player actor.showObjPan: Initiates a cinematic pan toward a specific object over a defined duration.lookObj: Fixes the camera orientation toward an object until the task completes.showCyrusPan: Targets a pan specifically on the player character.
Sources: crates/cyrus-game/tests/script_camera_session.rs:232-242, crates/cyrus-game/tests/script_camera_session.rs:365-375
Camera Slots
The system uses multiple records (slots) to manage different camera behaviors. Record zero uses different defaults depending on the player type (e.g., standard vs. reduced defaults for specific character states).
| Slot Feature | Description |
|---|---|
| Record Zero | Primary follow camera; tracks the selected player actor. |
| Record Two | Often used for cinematic pans (showObjPan). |
| Flags | Bitmask for state (e.g., 0x40 for basic state, 0x01 for setup bypass, 0x02 for fixed orientation). |
| Bound Actor | The logical actor the camera is currently tracking. |
Sources: crates/cyrus-game/tests/script_camera_session.rs:205-220, crates/cyrus-game/tests/script_camera_session.rs:504-518
Rendering Integration
The ViewCamera component acts as the primary marker for rendering systems.
Billboard Facing
The face_camera system uses the ViewCamera global transform to rotate Flat components (billboards) so they always face the viewer. It calculates the rotation by inverting the parent's rotation and multiplying by the camera's rotation.
Sources: crates/cyrus-render/src/flat.rs:141-160
Model Clipping
Render-side model clipping relies on the ViewCamera to determine the projection matrix and viewport size. The system projects model vertices into clip space to handle authored RGB clipping and lighting calculations.
Sources: crates/cyrus-render/src/fog/clipping.rs:114-125, crates/cyrus-render/src/fog/clipping.rs:290-305
Viewer Preview Camera
The cyrus-viewer implements a specialized camera for asset inspection. It supports both 2D and 3D preview modes.
Preview Framing
The frame_camera system automatically centers the view on the inspected asset. For 3D models, it calculates a bounding box (Aabb) and adjusts the camera distance based on the field of view (FOV) and aspect ratio to ensure the entire model is visible.
Sources: crates/cyrus-viewer/src/preview.rs:136-160
Inspector Controls
In the viewer, the camera supports "flight" mode where movement is frame-rate independent. It allows users to manipulate yaw and pitch, with optional speed boosts when holding the shift key.
The sequence shows the viewer calculating the optimal camera position to frame a specific asset.
Summary
The Camera System provides a robust bridge between original game fidelity and modern rendering. By separating logical poses from render-side interpolation, it maintains precise script execution while providing smooth visual transitions. It serves as a foundational component for both the faithful gameplay reconstruction and the asset inspection tools.