draco-rs 0.1.0

Rust-bindings to the c++ draco library, for compressing and decompressing 3D geometric meshes and point clouds.
Documentation
use crate::prelude::{
    ffi::{self},
    StatusOr,
};
use autocxx::prelude::*;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct AttrId(pub c_int);

pub type DracoStatusType<T> = Result<T, UniquePtr<ffi::draco::Status>>;

impl AttrId {
    pub fn as_u32(&self) -> u32 {
        self.0 .0 as u32
    }
}

impl From<c_int> for AttrId {
    fn from(value: c_int) -> Self {
        Self(value)
    }
}
impl From<AttrId> for c_int {
    fn from(value: AttrId) -> Self {
        value.0
    }
}

impl From<u32> for ffi::draco::PointIndex {
    fn from(val: u32) -> Self {
        ffi::draco::PointIndex { val }
    }
}

pub struct PointCloudBuilder {
    builder: UniquePtr<ffi::draco::PointCloudBuilder>,
}

impl PointCloudBuilder {
    pub fn new(num: u32) -> Self {
        let mut builder = ffi::draco::PointCloudBuilder::new().within_unique_ptr();
        builder.pin_mut().Start(num);
        Self { builder }
    }

    pub fn add_attribute(
        &mut self,
        attribute_type: ffi::draco::GeometryAttribute_Type,
        num_components: i8,
        data_type: ffi::draco::DataType,
    ) -> AttrId {
        self.builder
            .pin_mut()
            .AddAttribute(attribute_type, num_components, data_type)
            .into()
    }

    pub fn add_point(
        &mut self,
        attr_id: AttrId,
        point_index: ffi::draco::PointIndex,
        point: &[f64; 3],
    ) {
        unsafe {
            self.builder.pin_mut().SetAttributeValueForPoint(
                attr_id.0,
                point_index,
                point.as_ptr() as *const autocxx::c_void,
            );
        }
    }
    pub fn build(mut self, deduplicate_points: bool) -> PointCloud {
        PointCloud {
            pc: self.builder.pin_mut().Finalize(deduplicate_points),
        }
    }
}

pub struct PointCloud {
    pc: UniquePtr<ffi::draco::PointCloud>,
}
impl Default for PointCloud {
    fn default() -> Self {
        Self::new()
    }
}

impl PointCloud {
    pub fn new() -> Self {
        let pc = ffi::draco::PointCloud::new().within_unique_ptr();
        Self { pc }
    }

    // This function returns the attribute id of the attribute with the given name
    // It stores the value in-place
    pub fn get_point<T, const N: usize, Idx>(
        &mut self,
        attr_id: AttrId,
        point_index: Idx,
        point_container: &mut [T; N],
    ) where
        T: Default + Copy,
        Idx: Into<ffi::draco::PointIndex>,
    {
        let pa_ptr = self.pc.pin_mut().GetAttributeByUniqueId(attr_id.as_u32());
        unsafe {
            (*pa_ptr).GetMappedValue(
                point_index.into(),
                point_container.as_mut_ptr() as *mut c_void,
            );
        };
    }

    // This function allocates a new array of type T and fills it with the point data
    pub fn get_point_alloc<T, const N: usize, Idx>(
        &mut self,
        attr_id: AttrId,
        point_index: Idx,
    ) -> [T; N]
    where
        T: Default + Copy,
        Idx: Into<ffi::draco::PointIndex>,
    {
        let mut point = [T::default(); N];
        self.get_point(attr_id, point_index, &mut point);
        point
    }

    pub fn num_named_attributes(&self, attr_type: ffi::draco::GeometryAttribute_Type) -> i32 {
        self.pc.NumNamedAttributes(attr_type)
    }

    pub fn num_points(&self) -> u32 {
        self.pc.num_points()
    }

    pub fn len(&self) -> u32 {
        self.pc.num_points()
    }

    pub fn is_empty(&self) -> bool {
        self.pc.num_points() == 0
    }

    pub fn to_buffer(&self, encoder: &mut Encoder) -> DracoStatusType<EncoderBuffer> {
        let mut buffer = EncoderBuffer::new();

        let status = unsafe {
            encoder
                .encoder
                .pin_mut()
                .EncodePointCloudToBuffer(self.pc.as_ref().unwrap(), buffer.as_mut_ptr())
                .within_unique_ptr()
        };

        if status.ok() {
            Ok(buffer)
        } else {
            Err(status)
        }
    }

    pub fn from_buffer(decoder: &mut Decoder, buffer: &mut DecoderBuffer) -> DracoStatusType<Self> {
        let mut status_or = unsafe {
            decoder
                .decoder
                .pin_mut()
                .DecodePointCloudFromBuffer(buffer.buffer.as_mut_ptr())
        };
        if status_or.ok() {
            Ok(Self {
                pc: status_or.pin_mut().value(),
            })
        } else {
            Err(status_or.status().within_unique_ptr())
        }
    }
}

pub struct Encoder {
    pub(crate) encoder: UniquePtr<ffi::draco::Encoder>,
}

impl Encoder {
    pub fn new() -> Self {
        let encoder = ffi::draco::Encoder::new().within_unique_ptr();
        Self { encoder }
    }

    pub fn set_attribute_quantization(
        mut self,
        attr: ffi::draco::GeometryAttribute_Type,
        num_bits: i32,
    ) -> Self {
        self.encoder
            .pin_mut()
            .SetAttributeQuantization(attr, num_bits.into());
        self
    }

    pub fn set_speed_options(mut self, encoding_speed: i32, decoding_speed: i32) -> Self {
        self.encoder
            .pin_mut()
            .SetSpeedOptions(encoding_speed.into(), decoding_speed.into());
        self
    }
}

pub struct EncoderBuffer {
    pub(crate) buffer: UniquePtr<ffi::draco::EncoderBuffer>,
}

impl EncoderBuffer {
    pub fn new() -> Self {
        let buffer = ffi::draco::EncoderBuffer::new().within_unique_ptr();
        Self { buffer }
    }

    pub fn as_mut_ptr(&mut self) -> *mut ffi::draco::EncoderBuffer {
        self.buffer.as_mut_ptr()
    }
}

impl Default for EncoderBuffer {
    fn default() -> Self {
        Self::new()
    }
}

pub struct DecoderBuffer {
    pub(crate) buffer: UniquePtr<ffi::draco::DecoderBuffer>,
}

impl DecoderBuffer {
    pub fn new() -> Self {
        let buffer = ffi::draco::DecoderBuffer::new().within_unique_ptr();
        Self { buffer }
    }

    pub fn from_encoder_buffer(encoder_buffer: &mut EncoderBuffer) -> Self {
        let mut buffer = ffi::draco::DecoderBuffer::new().within_unique_ptr();
        unsafe {
            buffer.pin_mut().Init(
                encoder_buffer.buffer.as_ref().unwrap().data(),
                encoder_buffer.buffer.size(),
            )
        };
        Self { buffer }
    }
}

impl Default for DecoderBuffer {
    fn default() -> Self {
        Self::new()
    }
}

pub struct Decoder {
    pub(crate) decoder: UniquePtr<ffi::draco::Decoder>,
}

impl Decoder {
    pub fn new() -> Self {
        let decoder = ffi::draco::Decoder::new().within_unique_ptr();
        Self { decoder }
    }
}

impl Default for Encoder {
    fn default() -> Self {
        Self::new()
    }
}

impl Default for Decoder {
    fn default() -> Self {
        Self::new()
    }
}