use opensubdiv_petite_sys as sys;
use super::TopologyRefiner;
pub struct PrimvarRefiner<'a> {
ptr: sys::far::PrimvarRefinerPtr,
topology_refiner: &'a TopologyRefiner,
}
impl<'a> PrimvarRefiner<'a> {
pub fn new(topology_refiner: &TopologyRefiner) -> crate::Result<PrimvarRefiner<'_>> {
unsafe {
let ptr = sys::far::PrimvarRefiner_create(topology_refiner.0);
if ptr.is_null() {
return Err(crate::Error::Ffi(
"PrimvarRefiner_create() returned null".to_string(),
));
}
Ok(PrimvarRefiner {
ptr,
topology_refiner,
})
}
}
pub fn interpolate(
&self,
refinement_level: usize,
tuple_len: usize,
source: &[f32],
) -> Option<Vec<f32>> {
match self.topology_refiner.level(refinement_level) {
Some(refiner_level) => {
let dest_len = tuple_len * refiner_level.vertex_count();
let mut dest = Vec::<f32>::with_capacity(dest_len);
unsafe {
sys::far::PrimvarRefiner_Interpolate(
self.ptr,
tuple_len.min(i32::MAX as usize) as i32,
refinement_level.min(i32::MAX as usize) as i32,
source.as_ptr(),
dest.as_mut_ptr(),
);
dest.set_len(dest_len);
}
Some(dest)
}
None => None,
}
}
pub fn interpolate_face_varying(
&self,
refinement_level: usize,
tuple_len: usize,
source: &[f32],
) -> Option<Vec<f32>> {
match self.topology_refiner.level(refinement_level) {
Some(refiner_level) => {
let dest_len = tuple_len * refiner_level.vertex_count();
let mut dest = Vec::<f32>::with_capacity(dest_len);
unsafe {
sys::far::PrimvarRefiner_InterpolateFaceVarying(
self.ptr,
tuple_len.min(i32::MAX as usize) as i32,
refinement_level.min(i32::MAX as usize) as i32,
source.as_ptr(),
dest.as_mut_ptr(),
);
dest.set_len(dest_len);
}
Some(dest)
}
None => None,
}
}
pub fn interpolate_face_uniform(
&self,
refinement_level: usize,
tuple_len: usize,
source: &[f32],
) -> Option<Vec<f32>> {
match self.topology_refiner.level(refinement_level) {
Some(refiner_level) => {
let dest_len = tuple_len * refiner_level.vertex_count();
let mut dest = Vec::<f32>::with_capacity(dest_len);
unsafe {
sys::far::PrimvarRefiner_InterpolateFaceUniform(
self.ptr,
tuple_len.min(i32::MAX as usize) as i32,
refinement_level.min(i32::MAX as usize) as i32,
source.as_ptr(),
dest.as_mut_ptr(),
);
dest.set_len(dest_len);
}
Some(dest)
}
None => None,
}
}
pub fn interpolate_varying(
&self,
refinement_level: usize,
tuple_len: usize,
source: &[f32],
) -> Option<Vec<f32>> {
match self.topology_refiner.level(refinement_level) {
Some(refiner_level) => {
let dest_len = tuple_len * refiner_level.vertex_count();
let mut dest = Vec::<f32>::with_capacity(dest_len);
unsafe {
sys::far::PrimvarRefiner_InterpolateVarying(
self.ptr,
tuple_len.min(i32::MAX as usize) as i32,
refinement_level.min(i32::MAX as usize) as i32,
source.as_ptr(),
dest.as_mut_ptr(),
);
dest.set_len(dest_len);
}
Some(dest)
}
None => None,
}
}
}
impl<'a> Drop for PrimvarRefiner<'a> {
fn drop(&mut self) {
unsafe { sys::far::PrimvarRefiner_destroy(self.ptr) };
}
}