physxx 0.3.1

Wrapper around the PhysX C++ API that aims to preserve the original API as much as possible.
Documentation
use glam::Vec3;

use crate::{to_glam_vec3, to_physx_vec3, PxGeometry, PxRigidActorRef, PxShape, PxTransform};

#[derive(Debug, Clone)]
pub struct PxRaycastHit {
    pub actor: Option<PxRigidActorRef>,
    pub shape: Option<PxShape>,
    pub face_index: u32,
    pub flags: PxHitFlags,
    pub position: Vec3,
    pub normal: Vec3,
    pub distance: f32,
    pub u: f32,
    pub v: f32,
}
impl PxRaycastHit {
    pub(crate) fn from_px(hit: &physx_sys::PxRaycastHit) -> Self {
        Self {
            actor: if !hit.actor.is_null() {
                Some(PxRigidActorRef(hit.actor))
            } else {
                None
            },
            shape: if !hit.shape.is_null() {
                Some(PxShape::from_ptr(hit.shape))
            } else {
                None
            },
            face_index: hit.faceIndex,
            flags: PxHitFlags::from_bits(hit.flags.mBits as u32).unwrap(),
            position: to_glam_vec3(&hit.position),
            normal: to_glam_vec3(&hit.normal),
            distance: hit.distance,
            u: hit.u,
            v: hit.v,
        }
    }
}

bitflags! {
    pub struct PxHitFlags: u32 {
        const POSITION = physx_sys::PxHitFlag::ePOSITION;
        const NORMAL = physx_sys::PxHitFlag::eNORMAL;
        const UV = physx_sys::PxHitFlag::eUV;
        const ASSUME_NO_INITIAL_OVERLAP = physx_sys::PxHitFlag::eASSUME_NO_INITIAL_OVERLAP;
        const MESH_MULTIPLE = physx_sys::PxHitFlag::eMESH_MULTIPLE;
        const MESH_ANY = physx_sys::PxHitFlag::eMESH_ANY;
        const MESH_BOTH_SIDES = physx_sys::PxHitFlag::eMESH_BOTH_SIDES;
        const PRECISE_SWEEP = physx_sys::PxHitFlag::ePRECISE_SWEEP;
        const MTD = physx_sys::PxHitFlag::eMTD;
        const FACE_INDEX = physx_sys::PxHitFlag::eFACE_INDEX;
        const DEFAULT = physx_sys::PxHitFlag::eDEFAULT;
        const MODIFIABLE_FLAGS = physx_sys::PxHitFlag::eMODIFIABLE_FLAGS;
    }
}

pub fn raycast(
    origin: Vec3,
    unit_dir: Vec3,
    geom: &dyn PxGeometry,
    pose: &PxTransform,
    max_dist: f32,
    hit_flags: PxHitFlags,
    max_hits: u32,
) -> Vec<PxRaycastHit> {
    unsafe {
        let mut hits: Vec<_> = (0..max_hits)
            .map(|_| physx_sys::PxRaycastHit_new())
            .collect();
        let n_hits = physx_sys::PxGeometryQuery_raycast_mut(
            &to_physx_vec3(origin) as *const physx_sys::PxVec3,
            &to_physx_vec3(unit_dir) as *const physx_sys::PxVec3,
            geom.as_geometry_ptr(),
            &pose.0 as *const physx_sys::PxTransform,
            max_dist,
            physx_sys::PxHitFlags {
                mBits: hit_flags.bits as u16,
            },
            max_hits,
            hits.as_mut_ptr() as _,
        );
        hits.into_iter()
            .take(n_hits as usize)
            .map(|hit| PxRaycastHit::from_px(&hit))
            .collect()
    }
}