use std::mem::MaybeUninit;
use physx::{
math::{PxBounds3, PxVec3},
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,
};
pub use physx_sys::{
PxTriangleMeshFlag as TriangleMeshFlag, PxTriangleMeshFlags as TriangleMeshFlags,
};
pub trait TriangleMeshExtras {
fn get_nb_vertices(&self) -> u32;
fn get_vertices(&self) -> &[PxVec3];
fn get_vertices_for_modification(&mut self) -> &mut [PxVec3];
fn refit_bvh(&mut self) -> PxBounds3;
fn get_nb_triangles(&self) -> u32;
fn get_triangles(&self) -> TriangleMeshIndices<'_>;
fn get_triangle_mesh_flags(&self) -> TriangleMeshFlags;
fn get_triangles_remap(&self) -> &[u32];
fn get_triangle_material_index(&self, triangle_index: u32) -> u16;
fn get_mass_information(&self) -> PxMassProperties;
fn get_local_bounds(&self) -> PxBounds3;
}
impl TriangleMeshExtras for physx::triangle_mesh::TriangleMesh {
fn get_nb_vertices(&self) -> u32 {
unsafe { PxTriangleMesh_getNbVertices(self.as_ptr()) }
}
fn get_vertices(&self) -> &[PxVec3] {
let vertices = unsafe {
std::slice::from_raw_parts(
PxTriangleMesh_getVertices(self.as_ptr()),
self.get_nb_vertices() as usize,
)
};
unsafe { std::mem::transmute(vertices) }
}
fn get_vertices_for_modification(&mut self) -> &mut [PxVec3] {
let vertices = unsafe {
std::slice::from_raw_parts_mut(
PxTriangleMesh_getVerticesForModification_mut(self.as_mut_ptr()),
self.get_nb_vertices() as usize,
)
};
unsafe { std::mem::transmute(vertices) }
}
fn refit_bvh(&mut self) -> PxBounds3 {
unsafe { PxTriangleMesh_refitBVH_mut(self.as_mut_ptr()) }.into()
}
fn get_nb_triangles(&self) -> u32 {
unsafe { PxTriangleMesh_getNbTriangles(self.as_ptr()) }
}
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)
})
}
}
fn get_triangle_mesh_flags(&self) -> TriangleMeshFlags {
unsafe { PxTriangleMesh_getTriangleMeshFlags(self.as_ptr()) }
}
fn get_triangles_remap(&self) -> &[u32] {
unsafe {
std::slice::from_raw_parts(
PxTriangleMesh_getTrianglesRemap(self.as_ptr()),
self.get_nb_triangles() as usize,
)
}
}
fn get_triangle_material_index(&self, triangle_index: u32) -> u16 {
unsafe { PxTriangleMesh_getTriangleMaterialIndex(self.as_ptr(), triangle_index) }
}
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(),
}
}
}
fn get_local_bounds(&self) -> PxBounds3 {
unsafe { PxTriangleMesh_getLocalBounds(self.as_ptr()) }.into()
}
}
#[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
}
}