use std::ptr::drop_in_place;
use bevy::prelude::*;
use derive_more::{Deref, DerefMut};
use physx::prelude::*;
use physx::traits::Class;
use physx_sys::{PxMeshScale_new_3, PxPhysics_createShape_mut, PxShape_release_mut};
use crate::assets::GeometryInner;
use crate::prelude::{self as bpx, IntoPxQuat, IntoPxVec3};
use crate::resources::SceneRwLock;
use crate::types::*;
#[derive(Component, Clone, Copy, Debug, PartialEq, Eq)]
pub enum RigidBody {
Dynamic,
Static,
ArticulationLink,
}
#[derive(Default, Clone, Copy)]
pub enum ArticulationJointMotion {
#[default]
Locked,
Free,
Limited { min: f32, max: f32 },
}
#[derive(Component, Clone)]
pub struct ArticulationJoint {
pub parent: Entity,
pub joint_type: ArticulationJointType,
pub motion_twist: ArticulationJointMotion,
pub motion_swing1: ArticulationJointMotion,
pub motion_swing2: ArticulationJointMotion,
pub motion_x: ArticulationJointMotion,
pub motion_y: ArticulationJointMotion,
pub motion_z: ArticulationJointMotion,
pub parent_pose: Transform,
pub child_pose: Transform,
pub max_joint_velocity: f32,
pub friction_coefficient: f32,
}
impl Default for ArticulationJoint {
fn default() -> Self {
Self {
parent: unsafe { std::mem::transmute(u64::MAX) },
joint_type: ArticulationJointType::Fix,
motion_twist: default(),
motion_swing1: default(),
motion_swing2: default(),
motion_x: default(),
motion_y: default(),
motion_z: default(),
parent_pose: default(),
child_pose: default(),
max_joint_velocity: 100.,
friction_coefficient: 0.5,
}
}
}
#[derive(Component, Clone)]
pub struct Shape {
pub geometry: Handle<bpx::Geometry>,
pub material: Handle<bpx::Material>,
pub flags: ShapeFlags,
}
impl Default for Shape {
fn default() -> Self {
Self {
geometry: default(),
material: default(),
flags: ShapeFlags::SceneQueryShape
| ShapeFlags::SimulationShape
| ShapeFlags::Visualization,
}
}
}
#[derive(Component)]
pub struct ShapeHandle {
handle: Option<SceneRwLock<Owner<PxShape>>>,
pub custom_xform: Transform,
}
impl ShapeHandle {
pub fn new(px_shape: Owner<PxShape>, custom_xform: Transform) -> Self {
Self { handle: Some(SceneRwLock::new(px_shape)), custom_xform }
}
pub fn create_shape(
physics: &mut bpx::Physics,
geometry: &mut bpx::Geometry,
material: &bpx::Material,
flags: ShapeFlags,
user_data: Entity,
) -> Self {
let mut transform = Transform::IDENTITY;
let geometry_ptr = match &mut geometry.obj {
GeometryInner::Sphere(geom) => { geom.as_ptr() },
GeometryInner::Plane { plane, normal } => {
transform.rotate(Quat::from_rotation_arc(Vec3::X, *normal));
plane.as_ptr()
},
GeometryInner::Capsule(geom) => { geom.as_ptr() },
GeometryInner::Box(geom) => { geom.as_ptr() },
GeometryInner::ConvexMesh { mesh, scale, rotation, flags } => {
PxConvexMeshGeometry::new(
mesh.lock().unwrap().as_mut(),
unsafe { &PxMeshScale_new_3(scale.to_physx_sys().as_ptr(), rotation.to_physx().as_ptr()) },
*flags,
).as_ptr()
},
GeometryInner::TriangleMesh { mesh, scale, rotation, flags } => {
PxTriangleMeshGeometry::new(
mesh.lock().unwrap().as_mut(),
unsafe { &PxMeshScale_new_3(scale.to_physx_sys().as_ptr(), rotation.to_physx().as_ptr()) },
*flags,
).as_ptr()
},
GeometryInner::HeightField { mesh, scale, flags } => {
PxHeightFieldGeometry::new(
mesh.lock().unwrap().as_mut(),
*flags,
scale.y,
scale.x,
scale.z,
).as_ptr()
},
};
let shape : Owner<PxShape> = unsafe {
physx::shape::Shape::from_raw(
PxPhysics_createShape_mut(
physics.physics_mut().as_mut_ptr(),
geometry_ptr,
material.as_ptr(),
true,
flags,
),
user_data
).unwrap()
};
Self::new(shape, transform)
}
}
impl Drop for ShapeHandle {
fn drop(&mut self) {
let mut shape = self.handle.take().unwrap();
unsafe {
use physx::shape::Shape;
drop_in_place(shape.get_mut_unsafe().get_user_data_mut());
PxShape_release_mut(shape.get_mut_unsafe().as_mut_ptr());
}
std::mem::forget(shape);
}
}
impl std::ops::Deref for ShapeHandle {
type Target = SceneRwLock<Owner<PxShape>>;
fn deref(&self) -> &Self::Target {
self.handle.as_ref().unwrap()
}
}
impl std::ops::DerefMut for ShapeHandle {
fn deref_mut(&mut self) -> &mut Self::Target {
self.handle.as_mut().unwrap()
}
}
#[derive(Component, Deref, DerefMut)]
pub struct RigidDynamicHandle {
#[deref]
#[deref_mut]
handle: SceneRwLock<Owner<PxRigidDynamic>>,
pub predicted_gxform: GlobalTransform,
}
impl RigidDynamicHandle {
pub fn new(px_rigid_dynamic: Owner<PxRigidDynamic>, predicted_gxform: GlobalTransform) -> Self {
Self { handle: SceneRwLock::new(px_rigid_dynamic), predicted_gxform }
}
}
#[derive(Component, Deref, DerefMut)]
pub struct RigidStaticHandle {
#[deref]
#[deref_mut]
handle: SceneRwLock<Owner<PxRigidStatic>>,
pub predicted_gxform: GlobalTransform,
}
impl RigidStaticHandle {
pub fn new(px_rigid_static: Owner<PxRigidStatic>, predicted_gxform: GlobalTransform) -> Self {
Self { handle: SceneRwLock::new(px_rigid_static), predicted_gxform }
}
}
#[derive(Component)]
pub struct ArticulationRootHandle {
handle: Option<SceneRwLock<Owner<PxArticulationReducedCoordinate>>>,
}
impl ArticulationRootHandle {
pub fn new(px_articulation_root: Owner<PxArticulationReducedCoordinate>) -> Self {
Self { handle: Some(SceneRwLock::new(px_articulation_root)) }
}
}
impl std::ops::Deref for ArticulationRootHandle {
type Target = SceneRwLock<Owner<PxArticulationReducedCoordinate>>;
fn deref(&self) -> &Self::Target {
self.handle.as_ref().unwrap()
}
}
impl std::ops::DerefMut for ArticulationRootHandle {
fn deref_mut(&mut self) -> &mut Self::Target {
self.handle.as_mut().unwrap()
}
}
impl Drop for ArticulationRootHandle {
fn drop(&mut self) {
std::mem::forget(self.handle.take());
}
}
#[derive(Component)]
pub struct ArticulationLinkHandle {
handle: Option<SceneRwLock<Owner<PxArticulationLink>>>,
pub predicted_gxform: GlobalTransform,
}
impl ArticulationLinkHandle {
pub fn new(px_articulation_link: Owner<PxArticulationLink>, predicted_gxform: GlobalTransform) -> Self {
Self { handle: Some(SceneRwLock::new(px_articulation_link)), predicted_gxform }
}
}
impl std::ops::Deref for ArticulationLinkHandle {
type Target = SceneRwLock<Owner<PxArticulationLink>>;
fn deref(&self) -> &Self::Target {
self.handle.as_ref().unwrap()
}
}
impl std::ops::DerefMut for ArticulationLinkHandle {
fn deref_mut(&mut self) -> &mut Self::Target {
self.handle.as_mut().unwrap()
}
}
impl Drop for ArticulationLinkHandle {
fn drop(&mut self) {
std::mem::forget(self.handle.take());
}
}