embree4_rs/geometry/
tri_mesh.rs

1use std::{mem::size_of, slice};
2
3use anyhow::{bail, Result};
4
5use crate::Device;
6
7use super::Geometry;
8
9pub struct TriangleMeshGeometry {
10    pub handle: embree4_sys::RTCGeometry,
11}
12
13impl TriangleMeshGeometry {
14    /// Constructs a new `TriangleMeshGeometry` instance from the given vertices and indices.
15    ///
16    /// # Example
17    /// ```
18    /// use embree4_rs::{*, geometry::*};
19    /// use embree4_sys::*;
20    ///
21    /// let vertices = [
22    ///   (-1.0, -1.0, 0.0),
23    ///   (1.0, -1.0, 0.0),
24    ///   (1.0, 1.0, 0.0),
25    ///   (-1.0, 1.0, 0.0),
26    /// ];
27    /// let indices = [(0, 1, 2), (2, 3, 0)];
28    ///
29    /// let device = Device::try_new(None).unwrap();
30    /// let geometry = TriangleMeshGeometry::try_new(&device, &vertices, &indices).unwrap();
31    /// let scene = Scene::try_new(&device, SceneOptions::default()).unwrap();
32    /// scene.attach_geometry(&geometry);
33    /// ```
34    pub fn try_new(
35        device: &Device,
36        vertices: &[(f32, f32, f32)],
37        indices: &[(u32, u32, u32)],
38    ) -> Result<Self> {
39        let geometry = unsafe {
40            embree4_sys::rtcNewGeometry(device.handle, embree4_sys::RTCGeometryType::TRIANGLE)
41        };
42        if geometry.is_null() {
43            bail!("Failed to create geometry: {:?}", device.error());
44        }
45
46        let vertex_buf_ptr = unsafe {
47            embree4_sys::rtcSetNewGeometryBuffer(
48                geometry,
49                embree4_sys::RTCBufferType::VERTEX,
50                0,
51                embree4_sys::RTCFormat::FLOAT3,
52                3 * size_of::<f32>(),
53                vertices.len(),
54            )
55        };
56        if vertex_buf_ptr.is_null() {
57            bail!(
58                "Failed to create triangle mesh vertex buffer: {:?}",
59                device.error()
60            );
61        }
62        device.error_or((), "Failed not create triangle mesh vertex buffer")?;
63
64        let vertex_buf =
65            unsafe { slice::from_raw_parts_mut(vertex_buf_ptr as *mut f32, 3 * vertices.len()) };
66
67        // copy vertices into buffer
68        for (i, v) in vertices.iter().enumerate() {
69            vertex_buf[3 * i] = v.0;
70            vertex_buf[3 * i + 1] = v.1;
71            vertex_buf[3 * i + 2] = v.2;
72        }
73
74        let index_buf_ptr = unsafe {
75            embree4_sys::rtcSetNewGeometryBuffer(
76                geometry,
77                embree4_sys::RTCBufferType::INDEX,
78                0,
79                embree4_sys::RTCFormat::UINT3,
80                3 * size_of::<u32>(),
81                indices.len(),
82            )
83        };
84        if index_buf_ptr.is_null() {
85            bail!(
86                "Failed to create triangle mesh index buffer: {:?}",
87                device.error()
88            );
89        }
90        device.error_or((), "Failed to create triangle mesh index buffer")?;
91
92        let index_buf =
93            unsafe { slice::from_raw_parts_mut(index_buf_ptr as *mut u32, 3 * indices.len()) };
94
95        // copy indices into buffer
96        for (i, idx) in indices.iter().enumerate() {
97            index_buf[3 * i] = idx.0;
98            index_buf[3 * i + 1] = idx.1;
99            index_buf[3 * i + 2] = idx.2;
100        }
101
102        unsafe {
103            embree4_sys::rtcCommitGeometry(geometry);
104        }
105        device.error_or((), "Failed to commit triangle mesh geometry")?;
106
107        Ok(Self { handle: geometry })
108    }
109}
110
111impl Drop for TriangleMeshGeometry {
112    fn drop(&mut self) {
113        unsafe {
114            embree4_sys::rtcReleaseGeometry(self.handle);
115        }
116    }
117}
118
119impl Geometry for TriangleMeshGeometry {
120    fn handle(&self) -> &embree4_sys::RTCGeometry {
121        &self.handle
122    }
123}