gizmo_renderer/components/
mesh.rs1use gizmo_math::Vec3;
2use std::sync::Arc;
3use wgpu::util::DeviceExt;
4
5#[derive(Clone)]
6pub struct Mesh {
7 pub vbuf: Arc<wgpu::Buffer>,
8 pub vertex_count: u32,
9 pub center_offset: Vec3,
13 pub source: String,
14 pub bounds: gizmo_math::Aabb,
15 pub cpu_vertices: Arc<Vec<Vec3>>,
16 pub lod_vbufs: Vec<Arc<wgpu::Buffer>>,
17 pub lod_vertex_counts: Vec<u32>,
18}
19
20impl Mesh {
21 pub fn new(
25 device: &wgpu::Device,
26 vbuf: Arc<wgpu::Buffer>,
27 vertices: &[crate::gpu_types::Vertex],
28 center_offset: Vec3,
29 source: String,
30 ) -> Self {
31 debug_assert!(
32 !vertices.is_empty(),
33 "Kullanım hatası: Normal kullanımlarda vertices boş olamaz. Boş (fallback) mesh için Mesh::empty() kullanın."
34 );
35 let vertex_count = vertices.len() as u32;
36 debug_assert_eq!(
37 vertex_count as usize * std::mem::size_of::<crate::gpu_types::Vertex>(),
38 vbuf.size() as usize
39 );
40 let bounds = gizmo_math::Aabb::from_points(vertices.iter().map(|v| v.position));
41 let cpu_vertices = Arc::new(vertices.iter().map(|v| Vec3::from(v.position)).collect());
42
43 let mut lod_vbufs = Vec::new();
44 let mut lod_vertex_counts = Vec::new();
45
46 #[cfg(not(target_arch = "wasm32"))]
48 if vertex_count > 20000 {
49 let (unique_count, indices) = meshopt::generate_vertex_remap(vertices, None);
50
51 let mut unique_vertices = vec![crate::gpu_types::Vertex::default(); unique_count];
52 for (i, &new_idx) in indices.iter().enumerate() {
53 unique_vertices[new_idx as usize] = vertices[i];
54 }
55
56 let adapter = meshopt::VertexDataAdapter::new(
57 bytemuck::cast_slice(&unique_vertices),
58 std::mem::size_of::<crate::gpu_types::Vertex>(),
59 0,
60 )
61 .unwrap();
62
63 let target_count = (indices.len() as f32 * 0.5) as usize; let lod1_indices = meshopt::simplify(
65 &indices,
66 &adapter,
67 target_count,
68 0.1, meshopt::SimplifyOptions::empty(),
70 None,
71 );
72
73 if !lod1_indices.is_empty() && lod1_indices.len() < indices.len() {
75 let mut lod_flat = Vec::with_capacity(lod1_indices.len());
77 for &idx in &lod1_indices {
78 lod_flat.push(unique_vertices[idx as usize]);
79 }
80
81 let lod_vbuf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
82 label: Some(&format!("LOD1 VBuf: {}", source)),
83 contents: bytemuck::cast_slice(&lod_flat),
84 usage: wgpu::BufferUsages::VERTEX,
85 });
86
87 lod_vbufs.push(Arc::new(lod_vbuf));
88 lod_vertex_counts.push(lod_flat.len() as u32);
89 }
90 }
91
92 Self {
93 vbuf,
94 vertex_count,
95 center_offset,
96 source,
97 bounds,
98 cpu_vertices,
99 lod_vbufs,
100 lod_vertex_counts,
101 }
102 }
103
104 pub fn empty(vbuf: Arc<wgpu::Buffer>, source: String) -> Self {
107 Self {
108 vbuf,
109 vertex_count: 0,
110 center_offset: Vec3::ZERO,
111 source,
112 bounds: gizmo_math::Aabb::empty(),
113 cpu_vertices: Arc::new(Vec::new()),
114 lod_vbufs: Vec::new(),
115 lod_vertex_counts: Vec::new(),
116 }
117 }
118}
119
120#[derive(Clone)]
123pub struct MeshRenderer;
124
125impl MeshRenderer {
126 pub fn new() -> Self {
127 Self
128 }
129}
130
131impl Default for MeshRenderer {
132 fn default() -> Self {
133 Self::new()
134 }
135}