use crate::{
geometry::Geometry,
math::{PxTransform, PxVec3},
owner::Owner,
physics::Physics,
rigid_actor::RigidActor,
rigid_body::RigidBody,
shape::Shape,
traits::{Class, UserData},
};
use std::{marker::PhantomData, ptr::drop_in_place};
#[rustfmt::skip]
use physx_sys::{
phys_PxCreateDynamic,
PxRigidActor_release_mut,
PxRigidDynamic_getContactReportThreshold,
PxRigidDynamic_getKinematicTarget,
PxRigidDynamic_getRigidDynamicLockFlags,
PxRigidDynamic_getSleepThreshold,
PxRigidDynamic_getSolverIterationCounts,
PxRigidDynamic_getStabilizationThreshold,
PxRigidDynamic_getWakeCounter,
PxRigidDynamic_isSleeping,
PxRigidDynamic_putToSleep_mut,
PxRigidDynamic_setAngularVelocity_mut,
PxRigidDynamic_setContactReportThreshold_mut,
PxRigidDynamic_setKinematicTarget_mut,
PxRigidDynamic_setLinearVelocity_mut,
PxRigidDynamic_setRigidDynamicLockFlag_mut,
PxRigidDynamic_setRigidDynamicLockFlags_mut,
PxRigidDynamic_setSleepThreshold_mut,
PxRigidDynamic_setSolverIterationCounts_mut,
PxRigidDynamic_setStabilizationThreshold_mut,
PxRigidDynamic_setWakeCounter_mut,
PxRigidDynamic_wakeUp_mut,
};
pub use physx_sys::{
PxRigidDynamicLockFlag as RigidDynamicLockFlag,
PxRigidDynamicLockFlags as RigidDynamicLockFlags,
};
#[repr(transparent)]
pub struct PxRigidDynamic<D, Geom: Shape> {
pub(crate) obj: physx_sys::PxRigidDynamic,
phantom_user_data: PhantomData<(D, Geom)>,
}
unsafe impl<U, Geom: Shape> UserData for PxRigidDynamic<U, Geom> {
type UserData = U;
fn user_data_ptr(&self) -> &*mut std::ffi::c_void {
&self.obj.userData
}
fn user_data_ptr_mut(&mut self) -> &mut *mut std::ffi::c_void {
&mut self.obj.userData
}
}
impl<D, Geom: Shape> Drop for PxRigidDynamic<D, Geom> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.get_user_data_mut() as *mut _);
PxRigidActor_release_mut(self.as_mut_ptr());
}
}
}
unsafe impl<P, D, Geom: Shape> Class<P> for PxRigidDynamic<D, Geom>
where
physx_sys::PxRigidDynamic: Class<P>,
{
fn as_ptr(&self) -> *const P {
self.obj.as_ptr()
}
fn as_mut_ptr(&mut self) -> *mut P {
self.obj.as_mut_ptr()
}
}
unsafe impl<D: Send, Geom: Shape + Send> Send for PxRigidDynamic<D, Geom> {}
unsafe impl<D: Sync, Geom: Shape + Sync> Sync for PxRigidDynamic<D, Geom> {}
impl<D, Geom: Shape> RigidActor for PxRigidDynamic<D, Geom> {
type Shape = Geom;
}
impl<D, Geom: Shape> RigidDynamic for PxRigidDynamic<D, Geom> {}
pub trait RigidDynamic: Class<physx_sys::PxRigidDynamic> + RigidBody + UserData {
#[inline]
fn new(
physics: &mut impl Physics,
transform: PxTransform,
geometry: &impl Geometry,
material: &mut <Self::Shape as Shape>::Material,
density: f32,
shape_transform: PxTransform,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
unsafe {
RigidDynamic::from_raw(
phys_PxCreateDynamic(
physics.as_mut_ptr(),
transform.as_ptr(),
geometry.as_ptr(),
material.as_mut_ptr(),
density,
shape_transform.as_ptr(),
),
user_data,
)
}
}
#[inline]
unsafe fn from_raw(
ptr: *mut physx_sys::PxRigidDynamic,
user_data: Self::UserData,
) -> Option<Owner<Self>> {
unsafe {
let actor = (ptr as *mut Self).as_mut();
Owner::from_raw(actor?.init_user_data(user_data))
}
}
#[inline]
fn get_user_data(&self) -> &Self::UserData {
unsafe { UserData::get_user_data(self) }
}
#[inline]
fn get_user_data_mut(&mut self) -> &mut Self::UserData {
unsafe { UserData::get_user_data_mut(self) }
}
#[inline]
fn set_linear_velocity(&mut self, lin_vel: &PxVec3, autowake: bool) {
if !self
.get_actor_flags()
.contains(crate::actor::ActorFlags::DisableSimulation)
{
unsafe {
PxRigidDynamic_setLinearVelocity_mut(self.as_mut_ptr(), lin_vel.as_ptr(), autowake)
}
};
}
#[inline]
fn set_angular_velocity(&mut self, ang_vel: &PxVec3, autowake: bool) {
unsafe {
PxRigidDynamic_setAngularVelocity_mut(self.as_mut_ptr(), ang_vel.as_ptr(), autowake)
}
}
#[inline]
fn get_contact_report_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getContactReportThreshold(self.as_ptr()) }
}
#[inline]
fn get_kinematic_target(&self) -> Option<PxTransform> {
let mut transform = PxTransform::default();
unsafe {
if PxRigidDynamic_getKinematicTarget(self.as_ptr(), transform.as_mut_ptr()) {
Some(transform)
} else {
None
}
}
}
#[inline]
fn get_rigid_dynamic_lock_flags(&self) -> RigidDynamicLockFlags {
unsafe { PxRigidDynamic_getRigidDynamicLockFlags(self.as_ptr()) }
}
#[inline]
fn get_sleep_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getSleepThreshold(self.as_ptr()) }
}
#[inline]
fn get_solver_iteration_counts(&self) -> (u32, u32) {
let mut pos_iters = 0;
let mut vel_iters = 0;
unsafe {
PxRigidDynamic_getSolverIterationCounts(self.as_ptr(), &mut vel_iters, &mut pos_iters);
}
(pos_iters, vel_iters)
}
#[inline]
fn get_stabilization_threshold(&self) -> f32 {
unsafe { PxRigidDynamic_getStabilizationThreshold(self.as_ptr()) }
}
#[inline]
fn get_wake_counter(&self) -> f32 {
unsafe { PxRigidDynamic_getWakeCounter(self.as_ptr()) }
}
#[inline]
fn is_sleeping(&self) -> bool {
unsafe { PxRigidDynamic_isSleeping(self.as_ptr()) }
}
#[inline]
fn put_to_sleep(&mut self) {
unsafe { PxRigidDynamic_putToSleep_mut(self.as_mut_ptr()) }
}
#[inline]
fn set_contact_report_threshold(&mut self, threshold: f32) {
unsafe { PxRigidDynamic_setContactReportThreshold_mut(self.as_mut_ptr(), threshold) }
}
#[inline]
fn set_kinematic_target(&mut self, target: &PxTransform) {
unsafe { PxRigidDynamic_setKinematicTarget_mut(self.as_mut_ptr(), target.as_ptr()) }
}
#[inline]
fn set_rigid_dynamic_lock_flag(&mut self, flag: RigidDynamicLockFlag, value: bool) {
unsafe { PxRigidDynamic_setRigidDynamicLockFlag_mut(self.as_mut_ptr(), flag, value) }
}
#[inline]
fn set_rigid_dynamic_lock_flags(&mut self, flags: RigidDynamicLockFlags) {
unsafe { PxRigidDynamic_setRigidDynamicLockFlags_mut(self.as_mut_ptr(), flags) }
}
#[inline]
fn set_sleep_threshold(&mut self, mut threshold: f32) {
if threshold.is_sign_negative() {
threshold = 0.0
};
unsafe { PxRigidDynamic_setSleepThreshold_mut(self.as_mut_ptr(), threshold) }
}
#[inline]
fn set_solver_iteration_counts(
&mut self,
min_position_iterations: u32,
min_velocity_iterations: u32,
) {
unsafe {
PxRigidDynamic_setSolverIterationCounts_mut(
self.as_mut_ptr(),
min_position_iterations,
min_velocity_iterations,
)
}
}
#[inline]
fn set_stabilization_threshold(&mut self, threshold: f32) {
unsafe { PxRigidDynamic_setStabilizationThreshold_mut(self.as_mut_ptr(), threshold) }
}
#[inline]
fn set_wake_counter(&mut self, wake_counter: f32) {
unsafe { PxRigidDynamic_setWakeCounter_mut(self.as_mut_ptr(), wake_counter) }
}
#[inline]
fn wake_up(&mut self) {
unsafe { PxRigidDynamic_wakeUp_mut(self.as_mut_ptr()) }
}
}