Skip to main content

camera_demo/
camera_demo.rs

1//! Camera Demo - Orthographic and Perspective Cameras
2//!
3//! Demonstrates camera systems for 3D rendering:
4//! - Orthographic cameras (2D/UI, isometric games)
5//! - Perspective cameras (3D scenes)
6//! - View matrix construction
7//! - Projection matrix construction
8//! - Screen-to-world conversion
9//! - Camera movement and controls
10//!
11//! **Note:** This is a placeholder example demonstrating the Camera API structure.
12//! Full interactive camera controls are in development.
13
14use astrelis_core::logging;
15use astrelis_render::{Color, GraphicsContext, RenderWindow, RenderWindowBuilder, wgpu};
16use astrelis_winit::{
17    FrameTime, WindowId,
18    app::{App, AppCtx, run_app},
19    event::EventBatch,
20    window::{WindowDescriptor, WinitPhysicalSize},
21};
22use std::sync::Arc;
23
24struct CameraDemo {
25    _context: Arc<GraphicsContext>,
26    window: RenderWindow,
27    window_id: WindowId,
28}
29
30fn main() {
31    logging::init();
32
33    run_app(|ctx| {
34        let graphics_ctx =
35            GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
36
37        let window = ctx
38            .create_window(WindowDescriptor {
39                title: "Camera Demo - View & Projection".to_string(),
40                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
41                ..Default::default()
42            })
43            .expect("Failed to create window");
44
45        let window = RenderWindowBuilder::new()
46            .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
47            .with_depth_default()
48            .build(window, graphics_ctx.clone())
49            .expect("Failed to create render window");
50
51        let window_id = window.id();
52
53        println!("\n═══════════════════════════════════════════════════════");
54        println!("  📹 CAMERA DEMO - View & Projection");
55        println!("═══════════════════════════════════════════════════════");
56        println!("\n  CAMERA API FEATURES:");
57        println!("    • Orthographic cameras (2D, UI, isometric)");
58        println!("    • Perspective cameras (3D scenes)");
59        println!("    • View matrix (position, rotation, look-at)");
60        println!("    • Projection matrix (FOV, aspect, near/far planes)");
61        println!("    • Screen-to-world coordinate conversion");
62        println!("    • Camera movement helpers");
63        println!("\n  CAMERA TYPES:");
64        println!("    • OrthographicCamera - 2D games, UI overlays");
65        println!("      camera.orthographic(left, right, bottom, top, near, far)");
66        println!("    • PerspectiveCamera - 3D scenes");
67        println!("      camera.perspective(fov, aspect, near, far)");
68        println!("\n  Camera API Usage:");
69        println!("    let camera = Camera::new()");
70        println!("        .position(Vec3::new(0.0, 5.0, 10.0))");
71        println!("        .look_at(Vec3::ZERO)");
72        println!("        .perspective(60.0, aspect, 0.1, 100.0);");
73        println!("    let view_proj = camera.view_projection_matrix();");
74        println!("═══════════════════════════════════════════════════════\n");
75
76        tracing::info!("Camera demo initialized");
77
78        Box::new(CameraDemo {
79            _context: graphics_ctx,
80            window,
81            window_id,
82        })
83    });
84}
85
86impl App for CameraDemo {
87    fn update(&mut self, _ctx: &mut AppCtx, _time: &FrameTime) {}
88
89    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90        if window_id != self.window_id {
91            return;
92        }
93
94        events.dispatch(|event| {
95            if let astrelis_winit::event::Event::WindowResized(size) = event {
96                self.window.resized(*size);
97                astrelis_winit::event::HandleStatus::consumed()
98            } else {
99                astrelis_winit::event::HandleStatus::ignored()
100            }
101        });
102
103        let Some(frame) = self.window.begin_frame() else {
104            return; // Surface not available
105        };
106        {
107            let _pass = frame
108                .render_pass()
109                .clear_color(Color::from_rgb_u8(20, 30, 40))
110                .label("camera_demo_pass")
111                .build();
112        }
113        // Frame auto-submits on drop
114    }
115}