use std::collections::HashMap;
use crate::engine::graphics::MeshUploader;
use crate::engine::graphics::mesh::CpuMesh;
use crate::engine::graphics::mesh::MeshFactory;
use crate::engine::graphics::primitives::{CpuMeshHandle, MeshHandle};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BuiltinMeshType {
Triangle2D,
Quad2D,
Cube,
Tetrahedron,
Sphere,
Cone,
Circle2D,
}
#[derive(Debug, Default)]
pub struct RenderAssets {
cpu_meshes: Vec<CpuMesh>,
gpu_meshes: HashMap<CpuMeshHandle, MeshHandle>,
imported_meshes: HashMap<String, CpuMeshHandle>,
builtin_meshes: HashMap<BuiltinMeshType, CpuMeshHandle>,
wireframe_box_meshes: HashMap<u32, CpuMeshHandle>,
}
impl RenderAssets {
pub fn new() -> Self {
let mut s = Self::default();
s.register_builtin_meshes();
s
}
pub fn get_mesh(&mut self, mesh: BuiltinMeshType) -> CpuMeshHandle {
self.ensure_builtin_mesh(mesh)
}
fn register_builtin_meshes(&mut self) {
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Triangle2D);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Quad2D);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Cube);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Tetrahedron);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Sphere);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Cone);
let _ = self.ensure_builtin_mesh(BuiltinMeshType::Circle2D);
}
fn ensure_builtin_mesh(&mut self, mesh: BuiltinMeshType) -> CpuMeshHandle {
if let Some(h) = self.builtin_meshes.get(&mesh).copied() {
return h;
}
let cpu_mesh = match mesh {
BuiltinMeshType::Triangle2D => MeshFactory::triangle_2d(),
BuiltinMeshType::Quad2D => MeshFactory::quad_2d(),
BuiltinMeshType::Cube => MeshFactory::cube(),
BuiltinMeshType::Tetrahedron => MeshFactory::tetrahedron(),
BuiltinMeshType::Sphere => MeshFactory::sphere(),
BuiltinMeshType::Cone => MeshFactory::cone(32),
BuiltinMeshType::Circle2D => MeshFactory::circle_2d(0.45, 0.5, 64),
};
let h = self.register_mesh(cpu_mesh);
self.builtin_meshes.insert(mesh, h);
h
}
pub fn register_mesh(&mut self, mesh: CpuMesh) -> CpuMeshHandle {
let h = CpuMeshHandle(self.cpu_meshes.len() as u32);
self.cpu_meshes.push(mesh);
h
}
pub fn wireframe_box_mesh(&mut self, thickness: f32) -> CpuMeshHandle {
let thickness = thickness.clamp(1.0e-4, 1.0);
let key = thickness.to_bits();
if let Some(handle) = self.wireframe_box_meshes.get(&key).copied() {
return handle;
}
let handle = self.register_mesh(MeshFactory::wireframe_box(thickness));
self.wireframe_box_meshes.insert(key, handle);
handle
}
pub fn register_imported_mesh(
&mut self,
key: impl Into<String>,
mesh: CpuMesh,
) -> CpuMeshHandle {
let key = key.into();
let h = self.register_mesh(mesh);
self.imported_meshes.insert(key, h);
h
}
pub fn imported_mesh(&self, key: &str) -> Option<CpuMeshHandle> {
self.imported_meshes.get(key).copied()
}
pub fn cpu_mesh(&self, h: CpuMeshHandle) -> Option<&CpuMesh> {
self.cpu_meshes.get(h.0 as usize)
}
pub fn cpu_mesh_count(&self) -> usize {
self.cpu_meshes.len()
}
pub fn imported_mesh_count(&self) -> usize {
self.imported_meshes.len()
}
pub fn gpu_mesh_handle(
&mut self,
uploader: &mut dyn MeshUploader,
cpu_mesh: CpuMeshHandle,
) -> Result<MeshHandle, Box<dyn std::error::Error>> {
if let Some(h) = self.gpu_meshes.get(&cpu_mesh).copied() {
return Ok(h);
}
let mesh = self
.cpu_mesh(cpu_mesh)
.ok_or("RenderAssets: invalid CpuMeshHandle")?;
let h = uploader.upload_mesh(mesh)?;
self.gpu_meshes.insert(cpu_mesh, h);
Ok(h)
}
}