cgl_rs/graphics/mesh.rs
1//! The Mesh (CPU & GPU) module for CGL
2
3#![allow(non_camel_case_types)]
4use libc::{c_void, c_int, size_t, c_char, c_float};
5
6use crate::math::{IVector4, Vector4, Vector3, Matrix4x4};
7
8/// The internal handle used by CGL
9#[repr(C)]
10pub(crate) struct CGL_mesh_gpu {
11 _private: c_void
12}
13
14/// The Mesh Vertex Structure
15#[repr(C)] #[derive(Copy, Clone)]
16pub struct MeshVertex {
17 pub position: Vector4,
18 pub normal: Vector4,
19 pub texture_coordinates: Vector4,
20 pub bone_weights: Vector4,
21 pub bone_ids: IVector4
22}
23
24/// The Mesh Structure
25#[repr(C)] #[derive(Debug)]
26pub struct MeshCPU_C {
27 pub(crate) index_count: usize,
28 pub(crate) index_count_used: usize,
29 pub(crate) indices: *mut u32,
30 pub(crate) vertex_count: usize,
31 pub(crate) vertex_count_used: usize,
32 pub(crate) vertices: *mut MeshVertex
33}
34
35pub struct MeshCPU {
36 pub(crate) handle: *mut MeshCPU_C,
37 pub(crate) has_been_destroyed: bool
38}
39
40pub struct MeshGPU {
41 pub(crate) handle: *mut CGL_mesh_gpu,
42 pub(crate) has_been_destroyed: bool
43}
44
45
46extern {
47 fn CGL_mesh_cpu_create(vertex_count: size_t, index_count: size_t) -> *mut MeshCPU_C;
48 fn CGL_mesh_cpu_recalculate_normals(mesh: *mut MeshCPU_C) -> *mut MeshCPU_C;
49 fn CGL_mesh_cpu_load_obj(path: *const c_char) -> *mut MeshCPU_C;
50 fn CGL_mesh_cpu_triangle(a: Vector3, b: Vector3, c: Vector3) -> *mut MeshCPU_C;
51 fn CGL_mesh_cpu_plane(front: Vector3, right: Vector3, resolution: c_int, scale: c_float) -> *mut MeshCPU_C;
52 fn CGL_mesh_cpu_quad(a: Vector3, b: Vector3, c: Vector3, d: Vector3) -> *mut MeshCPU_C;
53 fn CGL_mesh_cpu_cube(use_3d_tex_coords: c_int) -> *mut MeshCPU_C;
54 fn CGL_mesh_cpu_sphere(res_u: c_int, res_v: c_int) -> *mut MeshCPU_C;
55 fn CGL_mesh_cpu_create_cylinder(start: Vector3, end: Vector3, radius0: c_float, radius1: c_float, resolution: c_int) -> *mut MeshCPU_C;
56 fn CGL_mesh_cpu_add_mesh(mesh: *mut MeshCPU_C, mesh_other: *mut MeshCPU_C) -> *mut MeshCPU_C;
57 fn CGL_mesh_cpu_add_cube(mesh: *mut MeshCPU_C, use_3d_tex_coords: c_int) -> *mut MeshCPU_C;
58 fn CGL_mesh_cpu_add_triangle(mesh: *mut MeshCPU_C, a: Vector3, b: Vector3, c: Vector3) -> *mut MeshCPU_C;
59 fn CGL_mesh_cpu_add_quad(mesh: *mut MeshCPU_C, a: Vector3, b: Vector3, c: Vector3, d: Vector3) -> *mut MeshCPU_C;
60 fn CGL_mesh_cpu_add_sphere(mesh: *mut MeshCPU_C, res_u: c_int, res_v: c_int) -> *mut MeshCPU_C;
61 fn CGL_mesh_cpu_add_cylinder(mesh: *mut MeshCPU_C, start: Vector3, end: Vector3, radius0: f32, radius1: f32, resolution: c_int) -> *mut MeshCPU_C;
62 fn CGL_mesh_cpu_offset_vertices(mesh: *mut MeshCPU_C, offset: Vector3) -> *mut MeshCPU_C;
63 fn CGL_mesh_cpu_scale_vertices(mesh: *mut MeshCPU_C, scale: c_float) -> *mut MeshCPU_C;
64 // fn CGL_mesh_cpu_rotate_vertices(mesh: *mut MeshCPU_C, CGL_quat rotation) -> *mut MeshCPU_C; // for future
65 fn CGL_mesh_cpu_transform_vertices(mesh: *mut MeshCPU_C, transform: &Matrix4x4) -> *mut MeshCPU_C;
66 fn CGL_mesh_cpu_destroy(mesh: *mut MeshCPU_C) -> c_void;
67
68 fn CGL_mesh_gpu_create() -> *mut CGL_mesh_gpu; // create mesh (gpu)
69 fn CGL_mesh_gpu_destroy(mesh: *mut CGL_mesh_gpu); // destroy mesh (gpu)
70 fn CGL_mesh_gpu_render(mesh: *mut CGL_mesh_gpu); // render mesh (gpu)
71 fn CGL_mesh_gpu_render_instanced(mesh: *mut CGL_mesh_gpu, count: u32); // render mesh instanced (gpu)
72 fn CGL_mesh_gpu_set_user_data(mesh: *mut CGL_mesh_gpu, user_data: *mut std::os::raw::c_void); // set mesh user data
73 fn CGL_mesh_gpu_get_user_data(mesh: *mut CGL_mesh_gpu) -> *mut std::os::raw::c_void; // get mesh user data
74 fn CGL_mesh_gpu_upload(mesh: *mut CGL_mesh_gpu, mesh_cpu: *mut MeshCPU_C, static_draw: c_int); // upload mesh from (cpu) to (gpu)
75}
76
77impl MeshVertex {
78 /// Creates a new `MeshVertex` object with default values.
79 ///
80 /// # Examples
81 ///
82 /// ```
83 /// let vertex = cgl_rs::graphics::MeshVertex::new();
84 /// ```
85 pub fn new() -> MeshVertex {
86 MeshVertex {
87 position: Vector4::new(0.0, 0.0, 0.0, 0.0),
88 normal: Vector4::new(0.0, 0.0, 0.0, 0.0),
89 texture_coordinates: Vector4::new(0.0, 0.0, 0.0, 0.0),
90 bone_weights: Vector4::new(0.0, 0.0, 0.0, 0.0),
91 bone_ids: IVector4::new(0, 0, 0, 0)
92 }
93 }
94}
95
96impl MeshCPU {
97
98 fn from_handle(handle: *mut MeshCPU_C) -> Result<MeshCPU, &'static str> {
99 if handle.is_null() {
100 Err("Failed to create MeshCPU_C")
101 } else {
102 Ok(MeshCPU {
103 handle: handle,
104 has_been_destroyed: false
105 })
106 }
107 }
108
109 /// Create a new MeshCPU object with the given vertex and index count
110 ///
111 /// # Arguments
112 ///
113 /// * `vertex_count` - The number of vertices in the mesh
114 /// * `index_count` - The number of indices in the mesh
115 ///
116 /// # Returns
117 ///
118 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
119 ///
120 /// # Example
121 ///
122 /// ```
123 /// cgl_rs::init();
124 /// {
125 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
126 /// }
127 /// cgl_rs::shutdown();
128 /// ```
129 pub fn new(vertex_count: usize, index_count: usize) -> Result<MeshCPU, &'static str> {
130 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_create(vertex_count, index_count) })
131 }
132
133 /// Loads a mesh from an OBJ file
134 ///
135 /// # Arguments
136 ///
137 /// * `path` - The path to the OBJ file
138 ///
139 /// # Returns
140 ///
141 /// * `Result<MeshCPU, &'static str>` - The loaded MeshCPU object, or an error message
142 ///
143 /// # Example
144 ///
145 /// ```no_run
146 /// cgl_rs::init();
147 /// {
148 /// let mesh = cgl_rs::graphics::MeshCPU::load_obj("path/to/mesh.obj").unwrap();
149 /// }
150 /// cgl_rs::shutdown();
151 /// ```
152 pub fn load_obj(path: &str) -> Result<MeshCPU, &'static str> {
153 let c_path = std::ffi::CString::new(path).unwrap();
154 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_load_obj(c_path.as_ptr()) })
155 }
156
157 /// Creates a new MeshCPU object with a single triangle
158 ///
159 /// # Arguments
160 ///
161 /// * `a` - The first vertex of the triangle
162 /// * `b` - The second vertex of the triangle
163 /// * `c` - The third vertex of the triangle
164 ///
165 /// # Returns
166 ///
167 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
168 ///
169 /// # Example
170 ///
171 /// ```
172 /// use cgl_rs::math::*;
173 /// cgl_rs::init();
174 /// {
175 /// let mesh = cgl_rs::graphics::MeshCPU::triangle(
176 /// Vector3::new(0.0, 0.0, 0.0),
177 /// Vector3::new(1.0, 0.0, 0.0),
178 /// Vector3::new(0.0, 1.0, 0.0)
179 /// ).unwrap();
180 /// }
181 /// cgl_rs::shutdown();
182 /// ```
183 pub fn triangle(a: Vector3, b: Vector3, c: Vector3) -> Result<MeshCPU, &'static str> {
184 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_triangle(a, b, c) })
185 }
186
187 /// Creates a new MeshCPU object representing a plane with the given front and right vectors, resolution, and scale.
188 ///
189 /// # Arguments
190 ///
191 /// * `front` - The front vector of the plane
192 /// * `right` - The right vector of the plane
193 /// * `resolution` - The number of subdivisions along each axis of the plane
194 /// * `scale` - The scale of the plane
195 ///
196 /// # Returns
197 ///
198 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
199 ///
200 /// # Example
201 ///
202 /// ```
203 /// use cgl_rs::math::*;
204 /// cgl_rs::init();
205 /// {
206 /// let mesh = cgl_rs::graphics::MeshCPU::plane(
207 /// Vector3::new(0.0, 0.0, 1.0),
208 /// Vector3::new(1.0, 0.0, 0.0),
209 /// 10,
210 /// 1.0
211 /// ).unwrap();
212 /// }
213 /// cgl_rs::shutdown();
214 /// ```
215 pub fn plane(front: Vector3, right: Vector3, resolution: i32, scale: f32) -> Result<MeshCPU, &'static str> {
216 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_plane(front, right, resolution, scale) })
217 }
218
219 /// Creates a new MeshCPU object representing a quad with the given vertices.
220 ///
221 /// # Arguments
222 ///
223 /// * `a` - The first vertex of the quad
224 /// * `b` - The second vertex of the quad
225 /// * `c` - The third vertex of the quad
226 /// * `d` - The fourth vertex of the quad
227 ///
228 /// # Returns
229 ///
230 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
231 ///
232 /// # Example
233 ///
234 /// ```
235 /// use cgl_rs::math::*;
236 /// cgl_rs::init();
237 /// {
238 /// let mesh = cgl_rs::graphics::MeshCPU::quad(
239 /// Vector3::new(-1.0, -1.0, 0.0),
240 /// Vector3::new(1.0, -1.0, 0.0),
241 /// Vector3::new(1.0, 1.0, 0.0),
242 /// Vector3::new(-1.0, 1.0, 0.0)
243 /// ).unwrap();
244 /// }
245 /// cgl_rs::shutdown();
246 /// ```
247 pub fn quad(a: Vector3, b: Vector3, c: Vector3, d: Vector3) -> Result<MeshCPU, &'static str> {
248 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_quad(a, b, c, d) })
249 }
250
251 /// Creates a new MeshCPU object representing a cube.
252 ///
253 /// # Arguments
254 ///
255 /// * `use_3d_tex_coords` - Whether to use 3D texture coordinates
256 ///
257 /// # Returns
258 ///
259 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
260 ///
261 /// # Example
262 ///
263 /// ```
264 /// cgl_rs::init();
265 /// {
266 /// let mesh = cgl_rs::graphics::MeshCPU::cube(true).unwrap();
267 /// }
268 /// cgl_rs::shutdown();
269 /// ```
270 pub fn cube(use_3d_tex_coords: bool) -> Result<MeshCPU, &'static str> {
271 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_cube(use_3d_tex_coords as i32) })
272 }
273
274 /// Creates a new MeshCPU object representing a sphere.
275 ///
276 /// # Arguments
277 ///
278 /// * `res_u` - The number of subdivisions along the u-axis of the sphere
279 /// * `res_v` - The number of subdivisions along the v-axis of the sphere
280 ///
281 /// # Returns
282 ///
283 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
284 ///
285 /// # Example
286 ///
287 /// ```
288 /// cgl_rs::init();
289 /// {
290 /// let mesh = cgl_rs::graphics::MeshCPU::sphere(10, 10).unwrap();
291 /// }
292 /// cgl_rs::shutdown();
293 /// ```
294 pub fn sphere(res_u: i32, res_v: i32) -> Result<MeshCPU, &'static str> {
295 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_sphere(res_u, res_v) })
296 }
297
298 /// Creates a new MeshCPU object representing a cylinder.
299 ///
300 /// # Arguments
301 ///
302 /// * `start` - The start position of the cylinder
303 /// * `end` - The end position of the cylinder
304 /// * `radius0` - The radius of the cylinder at the start position
305 /// * `radius1` - The radius of the cylinder at the end position
306 /// * `resolution` - The number of subdivisions around the cylinder
307 ///
308 /// # Returns
309 ///
310 /// * `Result<MeshCPU, &'static str>` - The new MeshCPU object, or an error message
311 ///
312 /// # Example
313 ///
314 /// ```
315 /// use cgl_rs::math::*;
316 /// cgl_rs::init();
317 /// {
318 /// let mesh = cgl_rs::graphics::MeshCPU::cylinder(
319 /// Vector3::new(0.0, 0.0, 0.0),
320 /// Vector3::new(0.0, 1.0, 0.0),
321 /// 1.0,
322 /// 1.0,
323 /// 10
324 /// ).unwrap();
325 /// }
326 /// cgl_rs::shutdown();
327 /// ```
328 pub fn cylinder(start: Vector3, end: Vector3, radius0: f32, radius1: f32, resolution: i32) -> Result<MeshCPU, &'static str> {
329 MeshCPU::from_handle(unsafe { CGL_mesh_cpu_create_cylinder(start, end, radius0, radius1, resolution) })
330 }
331
332 /// Adds the vertices and indices of another MeshCPU object to this MeshCPU object.
333 ///
334 /// # Arguments
335 ///
336 /// * `other` - The MeshCPU object to add to this MeshCPU object
337 ///
338 /// # Example
339 ///
340 /// ```
341 /// cgl_rs::init();
342 /// {
343 /// let mesh1 = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
344 /// let mesh2 = cgl_rs::graphics::MeshCPU::sphere(3, 3).unwrap();
345 /// mesh1.add_mesh(&mesh2);
346 /// }
347 /// cgl_rs::shutdown();
348 /// ```
349 pub fn add_mesh(&self, other: &MeshCPU) {
350 unsafe {
351 CGL_mesh_cpu_add_mesh(self.handle, other.handle);
352 }
353 }
354
355 /// Adds the vertices and indices of a cube to this MeshCPU object.
356 ///
357 /// # Arguments
358 ///
359 /// * `use_3d_tex_coords` - Whether or not to use 3D texture coordinates
360 ///
361 /// # Example
362 ///
363 /// ```
364 /// cgl_rs::init();
365 /// {
366 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
367 /// mesh.add_cube(true);
368 /// }
369 /// cgl_rs::shutdown();
370 /// ```
371 pub fn add_cube(&self, use_3d_tex_coords: bool) {
372 unsafe {
373 CGL_mesh_cpu_add_cube(self.handle, use_3d_tex_coords as i32);
374 }
375 }
376
377 /// Adds the vertices and indices of a sphere to this MeshCPU object.
378 ///
379 /// # Arguments
380 ///
381 /// * `res_u` - The number of subdivisions along the u-axis of the sphere
382 /// * `res_v` - The number of subdivisions along the v-axis of the sphere
383 ///
384 /// # Example
385 ///
386 /// ```
387 /// cgl_rs::init();
388 /// {
389 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
390 /// mesh.add_sphere(2, 2);
391 /// }
392 /// cgl_rs::shutdown();
393 /// ```
394 pub fn add_sphere(&self, res_u: i32, res_v: i32) {
395 unsafe {
396 CGL_mesh_cpu_add_sphere(self.handle, res_u, res_v);
397 }
398 }
399
400 /// Adds a triangle to this MeshCPU object.
401 ///
402 /// # Arguments
403 ///
404 /// * `a` - The first vertex of the triangle
405 /// * `b` - The second vertex of the triangle
406 /// * `c` - The third vertex of the triangle
407 ///
408 /// # Example
409 ///
410 /// ```
411 /// use cgl_rs::math::*;
412 /// cgl_rs::init();
413 /// {
414 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
415 /// mesh.add_triangle(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0));
416 /// }
417 /// cgl_rs::shutdown();
418 /// ```
419 pub fn add_triangle(&self, a: Vector3, b: Vector3, c: Vector3) {
420 unsafe {
421 CGL_mesh_cpu_add_triangle(self.handle, a, b, c);
422 }
423 }
424
425 /// Adds a quad to this MeshCPU object.
426 ///
427 /// # Arguments
428 ///
429 /// * `a` - The first vertex of the quad
430 /// * `b` - The second vertex of the quad
431 /// * `c` - The third vertex of the quad
432 /// * `d` - The fourth vertex of the quad
433 ///
434 /// # Example
435 ///
436 /// ```
437 /// use cgl_rs::math::*;
438 /// cgl_rs::init();
439 /// {
440 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
441 /// mesh.add_quad(Vector3::new(0.0, 0.0, 0.0), Vector3::new(1.0, 0.0, 0.0), Vector3::new(1.0, 1.0, 0.0), Vector3::new(0.0, 1.0, 0.0));
442 /// }
443 /// cgl_rs::shutdown();
444 /// ```
445 pub fn add_quad(&self, a: Vector3, b: Vector3, c: Vector3, d: Vector3) {
446 unsafe {
447 CGL_mesh_cpu_add_quad(self.handle, a, b, c, d);
448 }
449 }
450
451 // Adds a cylinder to this MeshCPU object.
452 ///
453 /// # Arguments
454 ///
455 /// * `start` - The starting point of the cylinder
456 /// * `end` - The ending point of the cylinder
457 /// * `radius0` - The radius of the cylinder at the starting point
458 /// * `radius1` - The radius of the cylinder at the ending point
459 /// * `resolution` - The number of subdivisions around the circumference of the cylinder
460 ///
461 /// # Example
462 ///
463 /// ```
464 /// use cgl_rs::math::*;
465 /// cgl_rs::init();
466 /// {
467 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
468 /// mesh.add_cylinder(Vector3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 1.0, 0.0), 0.5, 0.5, 10);
469 /// }
470 /// cgl_rs::shutdown();
471 /// ```
472 pub fn add_cylinder(&self, start: Vector3, end: Vector3, radius0: f32, radius1: f32, resolution: i32) {
473 unsafe {
474 CGL_mesh_cpu_add_cylinder(self.handle, start, end, radius0, radius1, resolution);
475 }
476 }
477
478 // Offsets the vertices of this MeshCPU object by a given vector.
479 ///
480 /// # Arguments
481 ///
482 /// * `offset` - The vector by which to offset the vertices
483 ///
484 /// # Example
485 ///
486 /// ```
487 /// use cgl_rs::math::*;
488 /// cgl_rs::init();
489 /// {
490 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
491 /// mesh.offset_vertices(Vector3::new(1.0, 0.0, 0.0));
492 /// }
493 /// cgl_rs::shutdown();
494 /// ```
495 pub fn offset_vertices(&self, offset: Vector3) {
496 unsafe {
497 CGL_mesh_cpu_offset_vertices(self.handle, offset);
498 }
499 }
500
501 // Scales the vertices of this MeshCPU object by a given factor.
502 ///
503 /// # Arguments
504 ///
505 /// * `scale` - The factor by which to scale the vertices
506 ///
507 /// # Example
508 ///
509 /// ```
510 /// cgl_rs::init();
511 /// {
512 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
513 /// mesh.scale_vertices(2.0);
514 /// }
515 /// cgl_rs::shutdown();
516 /// ```
517 pub fn scale_vertices(&self, scale: f32) {
518 unsafe {
519 CGL_mesh_cpu_scale_vertices(self.handle, scale);
520 }
521 }
522
523 // Transforms the vertices of this MeshCPU object by a given transformation matrix.
524 ///
525 /// # Arguments
526 ///
527 /// * `transform` - The transformation matrix by which to transform the vertices
528 ///
529 /// # Example
530 ///
531 /// ```
532 /// use cgl_rs::math::*;
533 /// cgl_rs::init();
534 /// {
535 /// let mesh = cgl_rs::graphics::MeshCPU::new(100, 100).unwrap();
536 /// let transform = Matrix4x4::identity();
537 /// mesh.transform_vertices(&transform);
538 /// }
539 /// cgl_rs::shutdown();
540 /// ```
541 pub fn transform_vertices(&self, transform: &Matrix4x4) {
542 unsafe {
543 CGL_mesh_cpu_transform_vertices(self.handle, transform);
544 }
545 }
546
547 /// Destroy the MeshCPU object
548 ///
549 /// # Example
550 ///
551 /// ```
552 /// cgl_rs::init();
553 /// {
554 /// let mut mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
555 /// mesh.destroy(); // or just let the mesh go out of scope
556 /// }
557 /// cgl_rs::shutdown();
558 /// ```
559 pub fn destroy(&mut self) {
560 if !self.has_been_destroyed {
561 unsafe {
562 CGL_mesh_cpu_destroy(self.handle);
563 }
564 self.has_been_destroyed = true;
565 }
566 }
567
568 /// Recalculates the normals of the mesh
569 ///
570 /// # Example
571 ///
572 /// ```
573 /// cgl_rs::init();
574 /// {
575 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
576 /// mesh.recalculate_normals();
577 /// }
578 /// cgl_rs::shutdown();
579 /// ```
580 pub fn recalculate_normals(&self) {
581 unsafe {
582 CGL_mesh_cpu_recalculate_normals(self.handle);
583 }
584 }
585
586
587 // Get the vertex at the specified index.
588 ///
589 /// # Arguments
590 ///
591 /// * `index` - The index of the vertex to retrieve
592 ///
593 /// # Example
594 ///
595 /// ```
596 /// cgl_rs::init();
597 /// {
598 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
599 /// let vertex = mesh.get_vertex(0);
600 /// }
601 /// cgl_rs::shutdown();
602 /// ```
603 pub fn get_vertex(&self, index: usize) -> &MeshVertex {
604 unsafe {
605 let vertex_array = self.handle.as_ref().unwrap().vertices;
606 vertex_array.offset(index as isize).as_ref().unwrap()
607 }
608 }
609
610 // Set the vertex at the specified index.
611 ///
612 /// # Arguments
613 ///
614 /// * `index` - The index of the vertex to set
615 /// * `vertex` - The vertex to set
616 ///
617 /// # Example
618 ///
619 /// ```
620 /// cgl_rs::init();
621 /// {
622 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
623 /// let vertex = cgl_rs::graphics::MeshVertex::new();
624 /// mesh.set_vertex(0, &vertex);
625 /// }
626 /// cgl_rs::shutdown();
627 /// ```
628 pub fn set_vertex(&self, index: usize, vertex: &MeshVertex) {
629 unsafe {
630 let vertex_array = self.handle.as_ref().unwrap().vertices;
631 let vertex_ptr = vertex_array.offset(index as isize);
632 *vertex_ptr = *vertex;
633 }
634 }
635
636 // Get the index at the specified index.
637 ///
638 /// # Arguments
639 ///
640 /// * `index` - The index of the index to retrieve
641 ///
642 /// # Example
643 ///
644 /// ```
645 /// cgl_rs::init();
646 /// {
647 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
648 /// let index = mesh.get_index(0);
649 /// }
650 /// cgl_rs::shutdown();
651 /// ```
652 pub fn get_index(&self, index: usize) -> u32 {
653 unsafe {
654 let index_array = self.handle.as_ref().unwrap().indices;
655 *index_array.offset(index as isize)
656 }
657 }
658
659 // Set the index at the specified index.
660 ///
661 /// # Arguments
662 ///
663 /// * `index` - The index of the index to set
664 /// * `value` - The value to set
665 ///
666 /// # Example
667 ///
668 /// ```
669 /// cgl_rs::init();
670 /// {
671 /// let mesh = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
672 /// mesh.set_index(0, 1);
673 /// }
674 /// cgl_rs::shutdown();
675 /// ```
676 pub fn set_index(&self, index: usize, value: u32) {
677 unsafe {
678 let index_array = self.handle.as_ref().unwrap().indices;
679 let index_ptr = index_array.offset(index as isize);
680 *index_ptr = value;
681 }
682 }
683
684
685}
686
687impl Drop for MeshCPU {
688 fn drop(&mut self) {
689 self.destroy();
690 }
691}
692
693impl Clone for MeshCPU {
694 fn clone(&self) -> Self {
695 MeshCPU {
696 handle: self.handle.clone(),
697 has_been_destroyed: true
698 }
699 }
700}
701
702
703impl MeshGPU {
704
705 /// Creates a new MeshGPU instance.
706 ///
707 /// # Returns
708 ///
709 /// Returns a `Result` containing a `MeshGPU` instance if successful, or a `&'static str` error message if unsuccessful.
710 ///
711 /// # Example
712 ///
713 /// ```
714 /// cgl_rs::init();
715 /// let mut window = cgl_rs::window::Window::new("Test Window", 800, 600).unwrap();
716 /// cgl_rs::graphics::init();
717 /// {
718 /// let mesh = cgl_rs::graphics::MeshGPU::new().unwrap();
719 /// }
720 /// cgl_rs::graphics::shutdown();
721 /// window.destroy();
722 /// cgl_rs::shutdown();
723 /// ```
724 pub fn new() -> Result<MeshGPU, &'static str> {
725 let handle = unsafe {
726 CGL_mesh_gpu_create()
727 };
728 if handle.is_null() {
729 Err("Failed to create MeshGPU")
730 } else {
731 Ok(MeshGPU {
732 handle: handle,
733 has_been_destroyed: false
734 })
735 }
736 }
737
738
739 /// Renders the mesh using the GPU.
740 ///
741 /// # Example
742 ///
743 /// ```
744 /// cgl_rs::init();
745 /// let mut window = cgl_rs::window::Window::new("Test Window", 800, 600).unwrap();
746 /// cgl_rs::graphics::init();
747 /// {
748 /// let mesh = cgl_rs::graphics::MeshGPU::new().unwrap();
749 /// mesh.render();
750 /// }
751 /// cgl_rs::graphics::shutdown();
752 /// window.destroy();
753 /// cgl_rs::shutdown();
754 /// ```
755 pub fn render(&self) {
756 unsafe {
757 CGL_mesh_gpu_render(self.handle);
758 }
759 }
760
761 /// Renders the mesh using the GPU with instancing.
762 ///
763 /// * `instance_count` - The number of instances to render.
764 ///
765 /// # Example
766 ///
767 /// ```
768 /// cgl_rs::init();
769 /// let mut window = cgl_rs::window::Window::new("Test Window", 800, 600).unwrap();
770 /// cgl_rs::graphics::init();
771 /// {
772 /// let mesh = cgl_rs::graphics::MeshGPU::new().unwrap();
773 /// mesh.render_instanced(10);
774 /// }
775 /// cgl_rs::graphics::shutdown();
776 /// window.destroy();
777 /// cgl_rs::shutdown();
778 /// ```
779 pub fn render_instanced(&self, instance_count: u32) {
780 unsafe {
781 CGL_mesh_gpu_render_instanced(self.handle, instance_count);
782 }
783 }
784
785 /// Uploads the mesh data to the GPU.
786 ///
787 /// * `mesh_cpu` - The mesh data to upload.
788 /// * `static_draw` - Whether the mesh data is static or dynamic.
789 ///
790 /// # Example
791 ///
792 /// ```
793 /// cgl_rs::init();
794 /// let mut window = cgl_rs::window::Window::new("Test Window", 800, 600).unwrap();
795 /// cgl_rs::graphics::init();
796 /// {
797 /// let mut mesh_cpu = cgl_rs::graphics::MeshCPU::new(3, 3).unwrap();
798 /// let mut mesh_gpu = cgl_rs::graphics::MeshGPU::new().unwrap();
799 /// mesh_gpu.upload(&mesh_cpu, true);
800 /// }
801 /// cgl_rs::graphics::shutdown();
802 /// window.destroy();
803 /// cgl_rs::shutdown();
804 /// ```
805 pub fn upload(&mut self, mesh_cpu: &MeshCPU, static_draw: bool) {
806 unsafe {
807 CGL_mesh_gpu_upload(self.handle, mesh_cpu.handle, static_draw as i32);
808 }
809 }
810
811 /// Destroys the mesh GPU handle if it has not already been destroyed.
812 ///
813 /// # Example
814 ///
815 /// ```
816 /// cgl_rs::init();
817 /// let mut window = cgl_rs::window::Window::new("Test Window", 800, 600).unwrap();
818 /// cgl_rs::graphics::init();
819 /// {
820 /// let mut mesh = cgl_rs::graphics::MeshGPU::new().unwrap();
821 /// mesh.destroy();
822 /// }
823 /// cgl_rs::graphics::shutdown();
824 /// window.destroy();
825 /// cgl_rs::shutdown();
826 /// ```
827 pub fn destroy(&mut self) {
828 if !self.has_been_destroyed {
829 unsafe {
830 CGL_mesh_gpu_destroy(self.handle);
831 }
832 self.has_been_destroyed = true;
833 }
834 }
835
836}
837
838impl Drop for MeshGPU {
839 fn drop(&mut self) {
840 self.destroy();
841 }
842}
843
844impl Clone for MeshGPU {
845 fn clone(&self) -> Self {
846 MeshGPU {
847 handle: self.handle.clone(),
848 has_been_destroyed: true
849 }
850 }
851}