use std::mem::MaybeUninit;
use crate::{
math::{PxBounds3, PxVec3},
owner::Owner,
traits::Class,
};
use physx_sys::{
PxMassProperties,
PxTriangleMesh_getLocalBounds,
PxTriangleMesh_getMassInformation,
PxTriangleMesh_getNbTriangles,
PxTriangleMesh_getNbVertices,
PxTriangleMesh_getTriangleMaterialIndex,
PxTriangleMesh_getTriangleMeshFlags,
PxTriangleMesh_getTriangles,
PxTriangleMesh_getTrianglesRemap,
PxTriangleMesh_getVertices,
PxTriangleMesh_getVerticesForModification_mut,
PxTriangleMesh_refitBVH_mut,
PxTriangleMesh_release_mut,
};
pub use physx_sys::{
PxTriangleMeshFlag as TriangleMeshFlag, PxTriangleMeshFlags as TriangleMeshFlags,
};
#[repr(transparent)]
pub struct TriangleMesh {
obj: physx_sys::PxTriangleMesh,
}
crate::DeriveClassForNewType!(TriangleMesh: PxTriangleMesh, PxBase);
impl TriangleMesh {
pub unsafe fn from_raw(ptr: *mut physx_sys::PxTriangleMesh) -> Option<Owner<TriangleMesh>> {
unsafe { Owner::from_raw(ptr as *mut Self) }
}
pub fn get_nb_vertices(&self) -> u32 {
unsafe { PxTriangleMesh_getNbVertices(self.as_ptr()) }
}
pub fn get_vertices(&self) -> &[PxVec3] {
unsafe {
std::slice::from_raw_parts(
PxTriangleMesh_getVertices(self.as_ptr()) as *const PxVec3,
self.get_nb_vertices() as usize,
)
}
}
pub fn get_vertices_mut(&mut self) -> &mut [PxVec3] {
unsafe {
std::slice::from_raw_parts_mut(
PxTriangleMesh_getVerticesForModification_mut(self.as_mut_ptr()) as *mut PxVec3,
self.get_nb_vertices() as usize,
)
}
}
pub fn refit_bvh(&mut self) -> PxBounds3 {
unsafe { PxTriangleMesh_refitBVH_mut(self.as_mut_ptr()) }.into()
}
pub fn get_nb_triangles(&self) -> u32 {
unsafe { PxTriangleMesh_getNbTriangles(self.as_ptr()) }
}
pub fn get_triangles(&self) -> TriangleMeshIndices<'_> {
let buffer = unsafe { PxTriangleMesh_getTriangles(self.as_ptr()) };
let length = self.get_nb_triangles() as usize * 3;
if self
.get_triangle_mesh_flags()
.contains(TriangleMeshFlags::E16BitIndices)
{
TriangleMeshIndices::U16(unsafe {
std::slice::from_raw_parts(buffer as *const u16, length)
})
} else {
TriangleMeshIndices::U32(unsafe {
std::slice::from_raw_parts(buffer as *const u32, length)
})
}
}
pub fn get_triangle_mesh_flags(&self) -> TriangleMeshFlags {
unsafe { PxTriangleMesh_getTriangleMeshFlags(self.as_ptr()) }
}
pub fn get_triangles_remap(&self) -> &[u32] {
unsafe {
std::slice::from_raw_parts(
PxTriangleMesh_getTrianglesRemap(self.as_ptr()),
self.get_nb_triangles() as usize,
)
}
}
pub fn get_triangle_material_index(&self, triangle_index: u32) -> u16 {
unsafe { PxTriangleMesh_getTriangleMaterialIndex(self.as_ptr(), triangle_index) }
}
pub fn get_mass_information(&self) -> PxMassProperties {
let mut mass = MaybeUninit::uninit();
let mut local_inertia = MaybeUninit::uninit();
let mut local_center_of_mass = MaybeUninit::uninit();
unsafe {
PxTriangleMesh_getMassInformation(
self.as_ptr(),
mass.as_mut_ptr(),
local_inertia.as_mut_ptr(),
local_center_of_mass.as_mut_ptr(),
);
PxMassProperties {
inertiaTensor: local_inertia.assume_init(),
centerOfMass: local_center_of_mass.assume_init(),
mass: mass.assume_init(),
}
}
}
pub fn get_local_bounds(&self) -> PxBounds3 {
unsafe { PxTriangleMesh_getLocalBounds(self.as_ptr()) }.into()
}
}
unsafe impl Send for TriangleMesh {}
unsafe impl Sync for TriangleMesh {}
impl Drop for TriangleMesh {
fn drop(&mut self) {
unsafe { PxTriangleMesh_release_mut(self.as_mut_ptr()) }
}
}
#[derive(Debug)]
pub enum TriangleMeshIndices<'a> {
U16(&'a [u16]),
U32(&'a [u32]),
}
impl<'a> TriangleMeshIndices<'a> {
pub fn len(&self) -> usize {
match self {
Self::U16(vec) => vec.len(),
Self::U32(vec) => vec.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}