use std::{mem::size_of, slice};
use anyhow::{bail, Result};
use crate::Device;
use super::Geometry;
pub struct TriangleMeshGeometry {
pub handle: embree4_sys::RTCGeometry,
}
impl TriangleMeshGeometry {
pub fn try_new(
device: &Device,
vertices: &[(f32, f32, f32)],
indices: &[(u32, u32, u32)],
) -> Result<Self> {
let geometry = unsafe {
embree4_sys::rtcNewGeometry(device.handle, embree4_sys::RTCGeometryType::TRIANGLE)
};
if geometry.is_null() {
bail!("Failed to create geometry: {:?}", device.error());
}
let vertex_buf_ptr = unsafe {
embree4_sys::rtcSetNewGeometryBuffer(
geometry,
embree4_sys::RTCBufferType::VERTEX,
0,
embree4_sys::RTCFormat::FLOAT3,
3 * size_of::<f32>(),
vertices.len(),
)
};
if vertex_buf_ptr.is_null() {
bail!(
"Failed to create triangle mesh vertex buffer: {:?}",
device.error()
);
}
device.error_or((), "Failed not create triangle mesh vertex buffer")?;
let vertex_buf =
unsafe { slice::from_raw_parts_mut(vertex_buf_ptr as *mut f32, 3 * vertices.len()) };
for (i, v) in vertices.iter().enumerate() {
vertex_buf[3 * i] = v.0;
vertex_buf[3 * i + 1] = v.1;
vertex_buf[3 * i + 2] = v.2;
}
let index_buf_ptr = unsafe {
embree4_sys::rtcSetNewGeometryBuffer(
geometry,
embree4_sys::RTCBufferType::INDEX,
0,
embree4_sys::RTCFormat::UINT3,
3 * size_of::<u32>(),
indices.len(),
)
};
if index_buf_ptr.is_null() {
bail!(
"Failed to create triangle mesh index buffer: {:?}",
device.error()
);
}
device.error_or((), "Failed to create triangle mesh index buffer")?;
let index_buf =
unsafe { slice::from_raw_parts_mut(index_buf_ptr as *mut u32, 3 * indices.len()) };
for (i, idx) in indices.iter().enumerate() {
index_buf[3 * i] = idx.0;
index_buf[3 * i + 1] = idx.1;
index_buf[3 * i + 2] = idx.2;
}
unsafe {
embree4_sys::rtcCommitGeometry(geometry);
}
device.error_or((), "Failed to commit triangle mesh geometry")?;
Ok(Self { handle: geometry })
}
}
impl Drop for TriangleMeshGeometry {
fn drop(&mut self) {
unsafe {
embree4_sys::rtcReleaseGeometry(self.handle);
}
}
}
impl Geometry for TriangleMeshGeometry {
fn handle(&self) -> &embree4_sys::RTCGeometry {
&self.handle
}
}