use opensubdiv_petite_sys as sys;
use std::marker::PhantomData;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct TopologyDescriptor<'a> {
pub(crate) descriptor: sys::OpenSubdiv_v3_7_0_Far_TopologyDescriptor,
_marker: PhantomData<*mut &'a ()>,
}
impl<'a> TopologyDescriptor<'a> {
#[inline]
pub fn new(
vertices_len: usize,
vertices_per_face: &'a [u32],
vertex_indices_per_face: &'a [u32],
) -> crate::Result<TopologyDescriptor<'a>> {
let mut descriptor = unsafe { sys::OpenSubdiv_v3_7_0_Far_TopologyDescriptor::new() };
#[cfg(feature = "topology_validation")]
{
if vertex_indices_per_face.len() != vertices_per_face.iter().sum::<u32>() as _ {
return Err(crate::Error::InvalidTopology(
"The number of vertex indices is not equal to the sum of face arities."
.to_string(),
));
}
for (i, &vertex_index) in vertex_indices_per_face.iter().enumerate() {
if vertices_len <= (vertex_index as usize) {
return Err(crate::Error::InvalidTopology(format!(
"Vertex index[{}] = {} is out of range (should be < {}).",
i, vertex_index, vertices_len
)));
}
}
}
descriptor.numVertices = vertices_len.min(i32::MAX as usize) as i32;
descriptor.numFaces = vertices_per_face.len().min(i32::MAX as usize) as i32;
descriptor.numVertsPerFace = vertices_per_face.as_ptr() as _;
descriptor.vertIndicesPerFace = vertex_indices_per_face.as_ptr() as _;
Ok(TopologyDescriptor {
descriptor,
_marker: PhantomData,
})
}
#[inline]
pub fn creases(&mut self, creases: &'a [u32], sharpness: &'a [f32]) -> &mut Self {
assert!(creases.len().is_multiple_of(2));
assert!(creases.len() / 2 <= sharpness.len());
#[cfg(feature = "topology_validation")]
{
for (i, &crease_vertex) in creases.iter().enumerate() {
if self.descriptor.numVertices as u32 <= crease_vertex {
panic!(
"Crease index[{}] = {} is out of range (should be < {}).",
i, crease_vertex, self.descriptor.numVertices
);
}
}
}
self.descriptor.numCreases = sharpness.len().min(i32::MAX as usize) as i32;
self.descriptor.creaseVertexIndexPairs = creases.as_ptr() as _;
self.descriptor.creaseWeights = sharpness.as_ptr();
self
}
#[inline]
pub fn corners(&mut self, corners: &'a [u32], sharpness: &'a [f32]) -> &mut Self {
assert!(corners.len() <= sharpness.len());
#[cfg(feature = "topology_validation")]
{
for corner in corners.iter().enumerate() {
if self.descriptor.numVertices as u32 <= *corner.1 {
panic!(
"Corner index[{}] = {} is out of range (should be < {}).",
corner.0, *corner.1, self.descriptor.numVertices
);
}
}
}
self.descriptor.numCorners = sharpness.len().min(i32::MAX as usize) as i32;
self.descriptor.cornerVertexIndices = corners.as_ptr() as _;
self.descriptor.cornerWeights = sharpness.as_ptr();
self
}
#[inline]
pub fn holes(&mut self, holes: &'a [u32]) -> &mut Self {
#[cfg(feature = "topology_validation")]
{
for hole in holes.iter().enumerate() {
if self.descriptor.numVertices as u32 <= *hole.1 {
panic!(
"Hole index[{}] = {} is out of range (should be < {}).",
hole.0, *hole.1, self.descriptor.numVertices
);
}
}
}
self.descriptor.numHoles = holes.len().min(i32::MAX as usize) as i32;
self.descriptor.holeIndices = holes.as_ptr() as _;
self
}
#[inline]
pub fn left_handed(&mut self, left_handed: bool) -> &mut Self {
self.descriptor.isLeftHanded = left_handed;
self
}
}