oxihuman_viewer/
render_loop.rs1use crate::camera::CameraState;
7use crate::gpu::MeshUploadBuffer;
8use crate::scene_state::{ViewerConfig, ViewerStats};
9
10pub struct Viewer {
14 config: ViewerConfig,
15 pub camera: CameraState,
16 pub current_mesh: Option<MeshUploadBuffer>,
17 frame_count: u64,
18}
19
20impl Viewer {
21 pub fn new(config: ViewerConfig) -> Self {
22 Viewer {
23 config,
24 camera: CameraState::default(),
25 current_mesh: None,
26 frame_count: 0,
27 }
28 }
29
30 pub fn upload_mesh(&mut self, buf: MeshUploadBuffer) {
32 self.current_mesh = Some(buf);
33 }
34
35 pub fn render_frame(&mut self) -> ViewerStats {
37 self.frame_count += 1;
38 let (verts, tris) = self
39 .current_mesh
40 .as_ref()
41 .map(|m| (m.positions.len(), m.indices.len() / 3))
42 .unwrap_or((0, 0));
43 ViewerStats {
44 frame_count: self.frame_count,
45 vertex_count: verts,
46 triangle_count: tris,
47 }
48 }
49
50 pub fn get_camera(&self) -> &CameraState {
52 &self.camera
53 }
54
55 pub fn orbit_camera(&mut self, yaw: f32, pitch: f32) {
57 self.camera.orbit(yaw, pitch);
58 }
59
60 pub fn config(&self) -> &ViewerConfig {
62 &self.config
63 }
64}
65
66#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn viewer_render_frame_returns_stats() {
74 let mut v = Viewer::new(ViewerConfig::default());
75 let stats = v.render_frame();
76 assert_eq!(stats.frame_count, 1);
77 assert_eq!(stats.vertex_count, 0);
78 assert_eq!(stats.triangle_count, 0);
79 }
80
81 #[test]
82 fn viewer_upload_mesh_reflected_in_stats() {
83 let buf = MeshUploadBuffer {
84 positions: vec![[0.0; 3], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
85 normals: vec![[0.0, 0.0, 1.0]; 3],
86 uvs: vec![[0.0; 2]; 3],
87 indices: vec![0, 1, 2],
88 timestamp: 0,
89 };
90 let mut v = Viewer::new(ViewerConfig::default());
91 v.upload_mesh(buf);
92 let stats = v.render_frame();
93 assert_eq!(stats.vertex_count, 3);
94 assert_eq!(stats.triangle_count, 1);
95 }
96
97 #[test]
98 fn viewer_orbit_camera_delegates() {
99 let mut v = Viewer::new(ViewerConfig::default());
100 let before = v.get_camera().position;
101 v.orbit_camera(30.0, 0.0);
102 assert_ne!(v.get_camera().position, before);
103 }
104
105 #[test]
106 fn viewer_frame_count_increments() {
107 let mut v = Viewer::new(ViewerConfig::default());
108 v.render_frame();
109 v.render_frame();
110 let s = v.render_frame();
111 assert_eq!(s.frame_count, 3);
112 }
113}