-
Notifications
You must be signed in to change notification settings - Fork 1
Camera System
The Camera System provides a first-person camera with smooth movement, mouse look, zoom, and console integration. It consists of a single class, SparkEngineCamera, used by the game module and graphics engine for view and projection matrix generation.
Source: SparkEngine/Source/Camera/
┌─────────────────────────────────────────────────────────┐
│ Game Loop │
│ input → Player → Camera.MoveForward/Yaw/Pitch → Update │
└──────────────────────────┬──────────────────────────────┘
│
▼
┌────────────────────────┐
│ SparkEngineCamera │
│ Position, Rotation │
│ View & Projection │
│ Zoom, Smooth Transitions │
│ Console Integration │
└────────────┬───────────┘
│
▼
┌────────────────────────┐
│ GraphicsEngine │
│ GetViewMatrix() │
│ GetProjectionMatrix() │
└────────────────────────┘
-
Single class:
SparkEngineCamera - Coordinate system: Right-handed, Y-up (DirectXMath)
-
Thread-safe: All state access protected by
m_stateMutex - Pitch clamping: Automatically clamped to approximately +/-89.4 degrees to prevent gimbal lock at the poles
| File | Responsibility |
|---|---|
SparkEngineCamera.h |
Class declaration, CameraState struct, all public methods |
SparkEngineCamera.cpp |
Implementation: matrix math, movement, rotation, console methods |
SparkEngineCamera camera;
camera.Initialize(16.0f / 9.0f); // Must be called before gameplay
// In game loop:
camera.Update(deltaTime); // Recalculates view matrix, processes smooth transitionsInitialize() sets the aspect ratio and builds the initial projection and view matrices. Update() must be called once per frame -- it updates the view matrix and advances any active smooth transition.
All movement methods multiply the input amount by m_moveSpeed and translate along the corresponding basis vector.
// Relative movement (scaled by move speed)
camera.MoveForward(amount); // Along forward vector (positive = forward)
camera.MoveRight(amount); // Along right vector (positive = right)
camera.MoveUp(amount); // Along up vector (positive = up)
// Absolute positioning
camera.SetPosition(XMFLOAT3(10.0f, 5.0f, -3.0f));Rotation methods multiply the input angle by m_rotationSpeed and m_mouseSensitivity. Pitch and Yaw also respect the m_invertY flag (Pitch only).
camera.Pitch(angle); // X-axis rotation, clamped to ~+/-89.4 degrees
camera.Yaw(angle); // Y-axis rotation, wraps at 360 degrees
camera.Roll(angle); // Z-axis rotation, wraps at 360 degreesPitch is clamped to [-PI/2 + 0.01, PI/2 - 0.01] radians to prevent over-rotation.
Toggles between default and zoomed field of view. Rebuilds the projection matrix immediately.
camera.SetZoom(true); // Switch to zoomed FOV (default: 45 degrees)
camera.SetZoom(false); // Switch to normal FOV (default: 90 degrees)const XMMATRIX& view = camera.GetViewMatrix();
const XMMATRIX& proj = camera.GetProjectionMatrix();
const XMFLOAT3& pos = camera.GetPosition();
const XMFLOAT3& forward = camera.GetForward();
XMFLOAT3 rotation = camera.GetRotation(); // (pitch, yaw, roll) in radiansGetPosition(), GetForward(), and GetRotation() are thread-safe (acquire m_stateMutex).
The camera supports smooth interpolation from one position to another using SmoothStep easing:
camera.Console_SmoothMoveTo(targetX, targetY, targetZ, durationSeconds);
// Check if still transitioning
if (camera.IsTransitioning()) { /* movement in progress */ }During a transition, Update() interpolates the position each frame using the formula t^2 * (3 - 2t) for natural acceleration and deceleration.
Console_GetState() returns a snapshot of all camera parameters:
struct CameraState {
XMFLOAT3 position;
XMFLOAT3 rotation; // In degrees (pitch, yaw, roll)
XMFLOAT3 forward, right, up;
float moveSpeed, rotationSpeed, mouseSensitivity;
float defaultFov, zoomedFov, currentFov; // In degrees
float aspectRatio, nearPlane, farPlane;
bool invertY, smoothMovement, isZoomed;
};All Console_* methods are thread-safe and log their actions to SimpleConsole.
| Method | Description |
|---|---|
Console_SetFOV(float degrees) |
Set default FOV (10-170 degrees) |
Console_SetMouseSensitivity(float) |
Set sensitivity multiplier (0.1-10.0) |
Console_SetInvertY(bool) |
Toggle Y-axis inversion for Pitch |
Console_SetMoveSpeed(float) |
Set movement speed (0.1-100.0) |
Console_SetRotationSpeed(float) |
Set rotation speed multiplier (0.1-10.0) |
Console_SetPosition(float x, y, z) |
Teleport camera to world position |
Console_SetRotation(float pitch, yaw, roll) |
Set rotation in degrees (pitch clamped) |
Console_SetClippingPlanes(float near, far) |
Set near (0.01-10.0) and far (100-10000) planes |
Console_ResetToDefaults() |
Reset all parameters to defaults |
Console_GetState() |
Return CameraState snapshot |
Console_LookAt(float x, y, z) |
Orient camera to face a world point |
Console_SmoothMoveTo(float x, y, z, duration) |
Smooth transition to target position |
Console_RegisterStateCallback(fn) |
Register a callback invoked on any state change |
| Parameter | Default | Range |
|---|---|---|
| Position | (0, 0, 0) | -- |
| Move Speed | 10.0 | 0.1 - 100.0 |
| Rotation Speed | 2.0 | 0.1 - 10.0 |
| Mouse Sensitivity | 1.0 | 0.1 - 10.0 |
| Default FOV | 90 degrees | 10 - 170 degrees |
| Zoomed FOV | 45 degrees | 10 - 170 degrees |
| Near Plane | 0.1 | 0.01 - 10.0 |
| Far Plane | 1000.0 | 100 - 10000 |
| Aspect Ratio | 16:9 (1.777) | Set via Initialize()
|
| Invert Y | false | -- |
| Smooth Movement | true | -- |
A typical integration flow in the game module:
// Startup
SparkEngineCamera camera;
camera.Initialize(windowWidth / windowHeight);
// Per frame
inputManager.Update();
float dt = timer.GetDeltaTime();
float moveAmount = dt;
if (input.IsKeyDown('W')) camera.MoveForward(moveAmount);
if (input.IsKeyDown('S')) camera.MoveForward(-moveAmount);
if (input.IsKeyDown('A')) camera.MoveRight(-moveAmount);
if (input.IsKeyDown('D')) camera.MoveRight(moveAmount);
int dx, dy;
if (input.GetMouseDelta(dx, dy)) {
camera.Yaw(dx * dt);
camera.Pitch(dy * dt);
}
camera.Update(dt);
// Pass matrices to renderer
graphicsEngine.SetViewMatrix(camera.GetViewMatrix());
graphicsEngine.SetProjectionMatrix(camera.GetProjectionMatrix());| Operation | Thread Safety | Details |
|---|---|---|
GetPosition(), GetForward(), GetRotation()
|
Thread-safe | Acquires m_stateMutex
|
SetPosition() |
Thread-safe | Acquires m_stateMutex, updates view matrix |
All Console_* methods |
Thread-safe | Each acquires m_stateMutex
|
Console_GetState() |
Thread-safe | Returns a full copy under lock |
MoveForward/Right/Up, Pitch, Yaw, Roll
|
Thread-safe | Each acquires m_stateMutex
|
Update() |
Main thread | Should be called once per frame from the main thread |
All mutable state access is protected by m_stateMutex. The state callback (m_stateCallback) is invoked while the mutex is held, so callbacks must not re-enter camera methods.
-
Initialize()asserts that the aspect ratio is positive. -
Update()asserts thatdeltaTimeis non-negative and finite. - Movement and rotation methods assert that input values are finite.
- Console methods with ranges log an error to
SimpleConsoleand return without modifying state if the value is out of range. -
Console_SetClippingPlanes()additionally validates thatnearPlane < farPlane.
- Input System -- Keyboard and mouse input that drives camera movement
- Rendering and Graphics -- Consumes view and projection matrices
- Gameplay Systems -- Player controller that owns the camera
- SparkConsole -- Console commands for camera tuning
- Cinematic Sequencer -- CameraPathTrack for scripted camera motion
- Creating a Game Module -- Accessing the camera via IEngineContext
Published from 708ae987d905. Edit the canonical source in wiki/.
- Documentation
- Docs route
- Wiki index
- Guides
- Tutorials
- Samples
- Examples
- API Reference
- API route
- Reference
- Build Guide
- Dependencies
- FAQ
- Changelog
- Roadmap
- Contributing
- Code of Conduct
- Home
- FAQ
- Getting Started
- Quick-Start Tutorial
- Making Your First Game
- Making Your First Multiplayer Game
- Artist Workflow Guide
- Editor Walkthrough
- Migration Guide
- How SparkEngine Works
- Architecture Overview
- Engine Architecture Flowchart
- Creating a Game Module
- Game Modules (catalog)
- Entity Component System
- Rendering and Graphics
- Physics
- Cloth Simulation
- Audio
- Input System
- Camera System
- Scripting with AngelScript
- Visual Scripting
- AI and Navigation
- Animation
- 2D Systems
- Networking
- Dedicated Server
- Multiplayer Quick Start
- Area Server Architecture
- Scene Management
- Large World Support
- Collaborative Editing
- Coroutine System
- Event System
- Event Response System
- Job System
- UI System
- UI Layout Extensions
- Localization
- Dialogue System
- Destruction System
- Replay System
- Achievement System
- Loading System
- Mod System
- Content Delivery
- Tween System
- Memory Integrity
- Gameplay Systems
- Terrain and Procedural Generation
- Save System
- Persistence System
- Day Night Cycle and Weather
- Cinematic Sequencer
- Runtime Prefabs
- SparkEditor
- Editor Tutorials
- SparkConsole
- SparkDaemon
- Shader Pipeline
- Asset Pipeline
- Asset Validation
- Asset Migration
- Game Packaging
- Online Services
- DataTable System
- Loot and Crafting System
- CSG System
- Font System
- Timer Manager
- Movie Render Pipeline
- HLOD and World Partition
- Remote Debug System
- Selection Manager
- Asset Dependency Graph
- Editor Automation
- File Watcher
- Project Templates
- System Requirements
- VR Support
- Mobile Platform
- Accessibility
- Platform Input
- Cross-Compilation: Wine Testing
- RHI Abstraction Layer
- D3D11 Backend
- D3D12 Backend
- Vulkan Backend
- OpenGL Backend
- Metal Backend
- DXR Raytracing
- Hybrid Ray Tracing
- Upscaling (DLSS/FSR)
- Render Graph
- Shader Graph
- GPU Particles
- GPU-Driven Rendering
- Volumetric Fog
- Volumetric Clouds
- Global Illumination
- Virtual Texturing
- Water Rendering
- Clustered Lighting
- Material System
- Post-Processing
- Shadow System
- Particle System
- Decal System
- Sky and Atmosphere
- Foliage System
- Mesh Shaders
- Neural Rendering
- Configuration Reference
- Performance Tips
- Benchmark Framework
- Threading Model
- Memory Safety
- Memory Management Patterns
- Build System and CMake Modules
- Profiler and Debugging
- Performance Profiling Guide
- Telemetry System
- Golden Image Testing
- Utilities
- Testing
- Codebase Statistics
- Codebase Health
- Error Handling Patterns
- Hot Reload Overview
- Troubleshooting
- Contributing
- Workflow Patterns
- Build Optimizations
- CI Reproducible Builds
- GitHub API and PR Checks
- Git Rebase Conflicts
- Clang-Format
- Code Quality Violations
- AI Bloat Pattern
- MinGW + Wine Cross-Compilation
- Live Editor Testing
- Engine & Renderer Landscape
- DuetOS Portability Catalog
- Five-Engine Analysis
- Eleven-Engine Analysis
- ThorVG / Unity Graphics Analysis
- Advanced Techniques Catalog
- Third-Party Library Evaluation
- Engine Viability Evaluation
- Engine Feature Recommendations
- Project Recommendations
- Mac Compatibility Analysis
- Codebase Observations
- Codebase Bloat Audit
- Test Suite Audit
- Documentation Coverage Audit
- ThirdParty Dependencies Audit
- Load Test Baseline
- Gameplay Systems Status
- SparkGame Module Status
- Stub and Abandoned Features
- Memory Integrity System
- Memory Safety Evaluation
- Hardware Acceleration Systems
- Jolt Physics Integration
- GPU/CPU Separation Plan
- Daemon Services Architecture
- Reflection & Polymorphism Refactoring Plan
- SparkBuild In-Tree
- Wine No-JobSystem Breakthrough
- Wine Role and Fallback Tiers