mittens_engine/engine/graphics/
render_assets.rs1use std::collections::HashMap;
2
3use crate::engine::graphics::MeshUploader;
4use crate::engine::graphics::mesh::CpuMesh;
5use crate::engine::graphics::mesh::MeshFactory;
6use crate::engine::graphics::primitives::{CpuMeshHandle, MeshHandle};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum BuiltinMeshType {
10 Triangle2D,
11 Quad2D,
12 Cube,
13 Tetrahedron,
14 Sphere,
15 Cone,
16 Circle2D,
17}
18
19#[derive(Debug, Default)]
26pub struct RenderAssets {
27 cpu_meshes: Vec<CpuMesh>,
28 gpu_meshes: HashMap<CpuMeshHandle, MeshHandle>,
29
30 imported_meshes: HashMap<String, CpuMeshHandle>,
32
33 builtin_meshes: HashMap<BuiltinMeshType, CpuMeshHandle>,
38
39 wireframe_box_meshes: HashMap<u32, CpuMeshHandle>,
41}
42
43impl RenderAssets {
44 pub fn new() -> Self {
45 let mut s = Self::default();
46 s.register_builtin_meshes();
47 s
48 }
49
50 pub fn get_mesh(&mut self, mesh: BuiltinMeshType) -> CpuMeshHandle {
55 self.ensure_builtin_mesh(mesh)
56 }
57
58 fn register_builtin_meshes(&mut self) {
59 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Triangle2D);
62 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Quad2D);
63 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Cube);
64 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Tetrahedron);
65 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Sphere);
67 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Cone);
68 let _ = self.ensure_builtin_mesh(BuiltinMeshType::Circle2D);
69 }
70
71 fn ensure_builtin_mesh(&mut self, mesh: BuiltinMeshType) -> CpuMeshHandle {
72 if let Some(h) = self.builtin_meshes.get(&mesh).copied() {
73 return h;
74 }
75
76 let cpu_mesh = match mesh {
77 BuiltinMeshType::Triangle2D => MeshFactory::triangle_2d(),
78 BuiltinMeshType::Quad2D => MeshFactory::quad_2d(),
79 BuiltinMeshType::Cube => MeshFactory::cube(),
80 BuiltinMeshType::Tetrahedron => MeshFactory::tetrahedron(),
81 BuiltinMeshType::Sphere => MeshFactory::sphere(),
82 BuiltinMeshType::Cone => MeshFactory::cone(32),
83 BuiltinMeshType::Circle2D => MeshFactory::circle_2d(0.45, 0.5, 64),
84 };
85
86 let h = self.register_mesh(cpu_mesh);
87 self.builtin_meshes.insert(mesh, h);
88 h
89 }
90
91 pub fn register_mesh(&mut self, mesh: CpuMesh) -> CpuMeshHandle {
95 let h = CpuMeshHandle(self.cpu_meshes.len() as u32);
96 self.cpu_meshes.push(mesh);
97 h
98 }
99
100 pub fn wireframe_box_mesh(&mut self, thickness: f32) -> CpuMeshHandle {
102 let thickness = thickness.clamp(1.0e-4, 1.0);
103 let key = thickness.to_bits();
104 if let Some(handle) = self.wireframe_box_meshes.get(&key).copied() {
105 return handle;
106 }
107 let handle = self.register_mesh(MeshFactory::wireframe_box(thickness));
108 self.wireframe_box_meshes.insert(key, handle);
109 handle
110 }
111
112 pub fn register_imported_mesh(
114 &mut self,
115 key: impl Into<String>,
116 mesh: CpuMesh,
117 ) -> CpuMeshHandle {
118 let key = key.into();
119 let h = self.register_mesh(mesh);
120 self.imported_meshes.insert(key, h);
121 h
122 }
123
124 pub fn imported_mesh(&self, key: &str) -> Option<CpuMeshHandle> {
126 self.imported_meshes.get(key).copied()
127 }
128
129 pub fn cpu_mesh(&self, h: CpuMeshHandle) -> Option<&CpuMesh> {
130 self.cpu_meshes.get(h.0 as usize)
131 }
132
133 pub fn cpu_mesh_count(&self) -> usize {
134 self.cpu_meshes.len()
135 }
136
137 pub fn imported_mesh_count(&self) -> usize {
138 self.imported_meshes.len()
139 }
140
141 pub fn gpu_mesh_handle(
143 &mut self,
144 uploader: &mut dyn MeshUploader,
145 cpu_mesh: CpuMeshHandle,
146 ) -> Result<MeshHandle, Box<dyn std::error::Error>> {
147 if let Some(h) = self.gpu_meshes.get(&cpu_mesh).copied() {
148 return Ok(h);
149 }
150
151 let mesh = self
152 .cpu_mesh(cpu_mesh)
153 .ok_or("RenderAssets: invalid CpuMeshHandle")?;
154 let h = uploader.upload_mesh(mesh)?;
155 self.gpu_meshes.insert(cpu_mesh, h);
156 Ok(h)
157 }
158}