globject_rs/
mesh.rs

1
2use crate::prelude::*;
3use std::{
4	any::type_name,
5	fmt::{self, Debug, Formatter},
6	marker::PhantomData,
7	rc::Rc,
8};
9
10/// The primitive mode of the mesh, indicating how to draw the vertices to which type of the shapes
11#[derive(Clone, Copy, PartialEq)]
12pub enum PrimitiveMode {
13	Points = GL_POINTS as isize,
14	LineStrip = GL_LINE_STRIP as isize,
15	LineLoop = GL_LINE_LOOP as isize,
16	Lines = GL_LINES as isize,
17	LineStripAdjacency = GL_LINE_STRIP_ADJACENCY as isize,
18	LinesAdjacency = GL_LINES_ADJACENCY as isize,
19	TriangleStrip = GL_TRIANGLE_STRIP as isize,
20	TriangleFan = GL_TRIANGLE_FAN as isize,
21	Triangles = GL_TRIANGLES as isize,
22	TriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY as isize,
23	TrianglesAdjacency = GL_TRIANGLES_ADJACENCY as isize,
24	Patches = GL_PATCHES as isize,
25}
26
27/// The type of the element buffer of the mesh, indicating the vertices were indexed by which type of index
28#[derive(Clone, Copy, PartialEq)]
29pub enum ElementType {
30	U8 = GL_UNSIGNED_BYTE as isize,
31	U16 = GL_UNSIGNED_SHORT as isize,
32	U32 = GL_UNSIGNED_INT as isize,
33}
34
35/// The mesh, every type of buffer is wrapped in a `BufferVec` can be manipulated just like a `Vec`
36#[derive(Debug, Clone)]
37pub struct Mesh<BV, V, BE, E, BI, I, BC, C>
38where
39	BV: BufferVec<V>,
40	BE: BufferVec<E>,
41	BI: BufferVec<I>,
42	BC: BufferVec<C>,
43	V: BufferVecItem,
44	E: BufferVecItem,
45	I: BufferVecItem,
46	C: BufferVecItem {
47	pub primitive: PrimitiveMode,
48	pub vertex_buffer: BV,
49	pub element_buffer: Option<BE>,
50	pub instance_buffer: Option<BI>,
51	pub command_buffer: Option<BC>,
52	_vertex_type: PhantomData<V>,
53	_element_type: PhantomData<E>,
54	_instance_type: PhantomData<I>,
55	_command_type: PhantomData<C>,
56}
57
58/// The most typical static mesh type: use `BufferVecStatic` for vertices and elements(indices), use `BufferVecDynamic` for instances and draw commands
59pub type StaticMesh<V, E, I, C> = Mesh<BufferVecStatic<V>, V, BufferVecStatic<E>, E, BufferVecDynamic<I>, I, BufferVecDynamic<C>, C>;
60
61impl<BV, V, BE, E, BI, I, BC, C> Mesh<BV, V, BE, E, BI, I, BC, C>
62where
63	BV: BufferVec<V>,
64	BE: BufferVec<E>,
65	BI: BufferVec<I>,
66	BC: BufferVec<C>,
67	V: BufferVecItem,
68	E: BufferVecItem,
69	I: BufferVecItem,
70	C: BufferVecItem {
71	/// Create a new mesh from the buffers
72	pub fn new(primitive: PrimitiveMode, vertex_buffer: BV, element_buffer: Option<BE>, instance_buffer: Option<BI>, command_buffer: Option<BC>) -> Self {
73		Self {
74			primitive,
75			vertex_buffer,
76			element_buffer,
77			instance_buffer,
78			command_buffer,
79			_vertex_type: PhantomData,
80			_element_type: PhantomData,
81			_instance_type: PhantomData,
82			_command_type: PhantomData,
83		}
84	}
85
86	/// Flush all of the buffers' caches to the GPU
87	pub fn flush(&mut self) -> Result<(), GLCoreError> {
88		self.vertex_buffer.flush()?;
89		if let Some(element_buffer) = &mut self.element_buffer {
90			element_buffer.flush()?;
91		}
92		if let Some(instance_buffer) = &mut self.instance_buffer {
93			instance_buffer.flush()?;
94		}
95		if let Some(command_buffer) = &mut self.command_buffer {
96			command_buffer.flush()?;
97		}
98		Ok(())
99	}
100}
101
102impl ElementType {
103	/// Get the size of each index
104	pub fn get_size(&self) -> usize {
105		match self {
106			Self::U8 => 1,
107			Self::U16 => 2,
108			Self::U32 => 4,
109		}
110	}
111}
112
113/// The `GenericMesh` trait helps the `Mesh` struct to be able to turn into an object
114pub trait GenericMesh: Debug {
115	/// Get the primitive mode of the mesh
116	fn get_primitive(&self) -> PrimitiveMode;
117
118	/// Get the vertex buffer of the mesh
119	fn get_vertex_buffer(&self) -> &Buffer;
120
121	/// Get the element buffer of the mesh
122	fn get_element_buffer(&self) -> Option<&Buffer>;
123
124	/// Get the type of the element buffer
125	fn get_element_type(&self) -> ElementType;
126
127	/// Get the instance buffer of the mesh
128	fn get_instance_buffer(&self) -> Option<&Buffer>;
129
130	/// Get the draw command buffer of the mesh
131	fn get_command_buffer(&self) -> Option<&Buffer>;
132
133	/// Get the size of each vertex
134	fn get_vertex_stride(&self) -> usize;
135
136	/// Get the size of each instance
137	fn get_instance_stride(&self) -> usize;
138
139	/// Get the number of vertices
140	fn get_vertex_count(&self) -> usize;
141
142	/// Get the number of the elements
143	fn get_element_count(&self) -> usize;
144
145	/// Get the number of the instances
146	fn get_instance_count(&self) -> usize;
147
148	/// Get the number of the draw commands
149	fn get_command_count(&self) -> usize;
150
151	/// Flush the cache if the mesh has a caching system
152	fn flush(&mut self) -> Result<(), GLCoreError> {Ok(())}
153
154	/// Bind the vertex buffer
155	fn bind_vertex_buffer<'a>(&'a self) -> Result<BufferBind<'a>, GLCoreError> {
156		self.get_vertex_buffer().bind_to(BufferTarget::ArrayBuffer)
157	}
158
159	/// Bind the element buffer
160	fn bind_element_buffer<'a>(&'a self) -> Result<Option<BufferBind<'a>>, GLCoreError> {
161		if let Some(element_buffer) = self.get_element_buffer() {
162			Ok(Some(element_buffer.bind_to(BufferTarget::ElementArrayBuffer)?))
163		} else {
164			Ok(None)
165		}
166	}
167
168	/// Bind the instance buffer
169	fn bind_instance_buffer<'a>(&'a self) -> Result<Option<BufferBind<'a>>, GLCoreError> {
170		if let Some(instance_buffer) = self.get_instance_buffer() {
171			Ok(Some(instance_buffer.bind_to(BufferTarget::ArrayBuffer)?))
172		} else {
173			Ok(None)
174		}
175	}
176
177	/// Bind the command buffer
178	fn bind_command_buffer<'a>(&'a self) -> Result<Option<BufferBind<'a>>, GLCoreError> {
179		if let Some(command_buffer) = self.get_command_buffer() {
180			Ok(Some(command_buffer.bind_to(BufferTarget::DrawIndirectBuffer)?))
181		} else {
182			Ok(None)
183		}
184	}
185}
186
187impl<BV, V, BE, E, BI, I, BC, C> GenericMesh for Mesh<BV, V, BE, E, BI, I, BC, C>
188where
189	BV: BufferVec<V>,
190	BE: BufferVec<E>,
191	BI: BufferVec<I>,
192	BC: BufferVec<C>,
193	V: BufferVecItem,
194	E: BufferVecItem,
195	I: BufferVecItem,
196	C: BufferVecItem {
197	fn get_primitive(&self) -> PrimitiveMode {
198		self.primitive
199	}
200
201	fn get_vertex_buffer(&self) -> &Buffer {
202		self.vertex_buffer.get_buffer()
203	}
204	
205	fn get_element_buffer(&self) -> Option<&Buffer> {
206		if let Some(buffer) = &self.element_buffer {
207			Some(buffer.get_buffer())
208		} else {
209			None
210		}
211	}
212
213	fn get_element_type(&self) -> ElementType {
214		match size_of::<E>() {
215			1 => ElementType::U8,
216			2 => ElementType::U16,
217			4 => ElementType::U32,
218			_ => panic!("Unsupported element type: {}", type_name::<E>()),
219		}
220	}
221
222	fn get_instance_buffer(&self) -> Option<&Buffer> {
223		if let Some(buffer) = &self.instance_buffer {
224			Some(buffer.get_buffer())
225		} else {
226			None
227		}
228	}
229
230	fn get_command_buffer(&self) -> Option<&Buffer> {
231		if let Some(buffer) = &self.command_buffer {
232			Some(buffer.get_buffer())
233		} else {
234			None
235		}
236	}
237
238	fn get_vertex_stride(&self) -> usize {
239		size_of::<V>()
240	}
241
242	fn get_instance_stride(&self) -> usize {
243		size_of::<I>()
244	}
245
246	fn get_vertex_count(&self) -> usize {
247		self.vertex_buffer.len()
248	}
249
250	fn get_element_count(&self) -> usize {
251		if let Some(element_buffer) = &self.element_buffer {
252			element_buffer.len()
253		} else {
254			0
255		}
256	}
257
258	fn get_instance_count(&self) -> usize {
259		if let Some(buffer) = &self.instance_buffer {
260			buffer.len()
261		} else {
262			0
263		}
264	}
265
266	fn get_command_count(&self) -> usize {
267		if let Some(buffer) = &self.command_buffer {
268			buffer.len()
269		} else {
270			0
271		}
272	}
273
274	fn flush(&mut self) -> Result<(), GLCoreError> {
275		Mesh::flush(self)
276	}
277}
278
279impl Debug for PrimitiveMode {
280	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
281		match self {
282			Self::Points => write!(f, "Points"),
283			Self::LineStrip => write!(f, "Line Strip"),
284			Self::LineLoop => write!(f, "Line Loop"),
285			Self::Lines => write!(f, "Lines"),
286			Self::LineStripAdjacency => write!(f, "Line Strip Adjacency"),
287			Self::LinesAdjacency => write!(f, "Lines Adjacency"),
288			Self::TriangleStrip => write!(f, "Triangle Strip"),
289			Self::TriangleFan => write!(f, "Triangle Fan"),
290			Self::Triangles => write!(f, "Triangles"),
291			Self::TriangleStripAdjacency => write!(f, "Triangle Strip Adjacency"),
292			Self::TrianglesAdjacency => write!(f, "Triangles Adjacency"),
293			Self::Patches => write!(f, "Patches"),
294		}
295	}
296}
297
298impl Debug for ElementType {
299	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
300		match self {
301			Self::U8 =>  write!(f, "U8"),
302			Self::U16 => write!(f, "U16"),
303			Self::U32 => write!(f, "U32"),
304		}
305	}
306}
307
308#[derive(Debug, Clone)]
309pub struct MeshWithMaterial<M: GenericMesh, Mat: Material> {
310	material: Rc<Mat>,
311	mesh: M,
312}
313
314impl<M: GenericMesh, Mat: Material> MeshWithMaterial<M, Mat> {
315	pub fn new(mesh: M, material: Rc<Mat>) -> Self {
316		Self {
317			material,
318			mesh,
319		}
320	}
321
322	pub fn get_material(&self) -> &Mat {
323		&self.material
324	}
325}
326
327impl<M: GenericMesh, Mat: Material> GenericMesh for MeshWithMaterial<M, Mat> {
328	fn get_primitive(&self) -> PrimitiveMode {
329		self.mesh.get_primitive()
330	}
331
332	fn get_vertex_buffer(&self) -> &Buffer {
333		self.mesh.get_vertex_buffer()
334	}
335
336	fn get_element_buffer(&self) -> Option<&Buffer> {
337		self.mesh.get_element_buffer()
338	}
339
340	fn get_element_type(&self) -> ElementType {
341		self.mesh.get_element_type()
342	}
343
344	fn get_instance_buffer(&self) -> Option<&Buffer> {
345		self.mesh.get_instance_buffer()
346	}
347
348	fn get_command_buffer(&self) -> Option<&Buffer> {
349		self.mesh.get_command_buffer()
350	}
351
352	fn get_vertex_stride(&self) -> usize {
353		self.mesh.get_vertex_stride()
354	}
355
356	fn get_instance_stride(&self) -> usize {
357		self.mesh.get_instance_stride()
358	}
359
360	fn get_vertex_count(&self) -> usize {
361		self.mesh.get_vertex_count()
362	}
363
364	fn get_element_count(&self) -> usize {
365		self.mesh.get_element_count()
366	}
367
368	fn get_instance_count(&self) -> usize {
369		self.mesh.get_instance_count()
370	}
371
372	fn get_command_count(&self) -> usize {
373		self.mesh.get_command_count()
374	}
375}
376
377/// The `GenericMeshWithMaterial` trait helps the `MeshWithMaterial` struct to be able to turn into an object
378pub trait GenericMeshWithMaterial: GenericMesh {
379	fn get_material(&self) -> Option<&dyn Material>;
380}
381
382impl<BV, V, BE, E, BI, I, BC, C> GenericMeshWithMaterial for Mesh<BV, V, BE, E, BI, I, BC, C>
383where
384	BV: BufferVec<V>,
385	BE: BufferVec<E>,
386	BI: BufferVec<I>,
387	BC: BufferVec<C>,
388	V: BufferVecItem,
389	E: BufferVecItem,
390	I: BufferVecItem,
391	C: BufferVecItem {
392	fn get_material(&self) -> Option<&dyn Material> {
393		None
394	}
395}
396
397impl<M: GenericMesh, Mat: Material> GenericMeshWithMaterial for MeshWithMaterial<M, Mat> {
398	fn get_material(&self) -> Option<&dyn Material> {
399		Some(&*self.material)
400	}
401}