Tesbted physx backend: add heightfield, trimesh, and convex mesh support.

This commit is contained in:
Crozet Sébastien
2021-01-06 12:22:46 +01:00
parent 1e9a962d34
commit d1ed279c4e
8 changed files with 129 additions and 31 deletions

View File

@@ -4,13 +4,19 @@ use na::{
Isometry3, Matrix3, Matrix4, Point3, Quaternion, Rotation3, Translation3, Unit, UnitQuaternion,
Vector3,
};
use physx::cooking::PxCooking;
use physx::cooking::{
ConvexMeshCookingResult, PxConvexMeshDesc, PxCooking, PxCookingParams, PxHeightFieldDesc,
PxTriangleMeshDesc, TriangleMeshCookingResult,
};
use physx::foundation::DefaultAllocator;
use physx::prelude::*;
use physx::scene::FrictionType;
use physx::traits::Class;
use physx::triangle_mesh::TriangleMesh;
use physx_sys::{PxActor, PxRigidActor};
use physx_sys::{
PxBitAndByte, PxConvexFlags, PxConvexMeshGeometryFlags, PxHeightFieldSample,
PxMeshGeometryFlags, PxMeshScale_new, PxRigidActor,
};
use rapier::counters::Counters;
use rapier::dynamics::{
IntegrationParameters, JointParams, JointSet, RigidBodyHandle, RigidBodySet,
@@ -167,6 +173,10 @@ impl PhysxWorld {
let mut scene: Owner<PxScene> = physics.create(scene_desc).unwrap();
let mut rapier2dynamic = HashMap::new();
let mut rapier2static = HashMap::new();
let cooking_params =
PxCookingParams::new(&*physics).expect("Failed to init PhysX cooking.");
let mut cooking = PxCooking::new(physics.foundation_mut(), &cooking_params)
.expect("Failed to init PhysX cooking");
/*
*
@@ -174,9 +184,6 @@ impl PhysxWorld {
*
*/
for (rapier_handle, rb) in bodies.iter() {
use physx::rigid_dynamic::RigidDynamic;
use physx::rigid_static::RigidStatic;
let pos = rb.position().into_physx();
if rb.is_dynamic() {
let mut actor = physics.create_dynamic(&pos, rapier_handle).unwrap();
@@ -199,7 +206,7 @@ impl PhysxWorld {
*/
for (_, collider) in colliders.iter() {
if let Some((mut px_shape, px_material, collider_pos)) =
physx_collider_from_rapier_collider(&mut *physics, &collider)
physx_collider_from_rapier_collider(&mut *physics, &mut cooking, &collider)
{
let parent_body = &bodies[collider.parent()];
@@ -454,7 +461,7 @@ impl PhysxWorld {
fn physx_collider_from_rapier_collider(
physics: &mut PxPhysicsFoundation,
// cooking: &PxCooking,
cooking: &PxCooking,
collider: &Collider,
) -> Option<(Owner<PxShape>, Owner<PxMaterial>, Isometry3<f32>)> {
let mut local_pose = *collider.position_wrt_parent();
@@ -498,26 +505,109 @@ fn physx_collider_from_rapier_collider(
* rot.unwrap_or(UnitQuaternion::identity());
let geometry = PxCapsuleGeometry::new(capsule.radius, capsule.half_height());
physics.create_shape(&geometry, materials, true, shape_flags, ())
} else if let Some(trimesh) = shape.as_trimesh() {
return None;
/*
ColliderDesc::TriMesh {
vertices: trimesh
.vertices()
} else if let Some(heightfield) = shape.as_heightfield() {
let heights = heightfield.heights();
let scale = heightfield.scale();
local_pose = local_pose * Translation3::new(-scale.x / 2.0, 0.0, -scale.z / 2.0);
const Y_FACTOR: f32 = 1_000f32;
let mut heightfield_desc;
unsafe {
let samples: Vec<_> = heights
.iter()
.map(|pt| pt.into_physx())
.collect(),
indices: trimesh.flat_indices().to_vec(),
mesh_scale: Vector3::repeat(1.0).into_glam(),
.map(|h| PxHeightFieldSample {
height: (*h * Y_FACTOR) as i16,
materialIndex0: PxBitAndByte { mData: 0 },
materialIndex1: PxBitAndByte { mData: 0 },
})
.collect();
heightfield_desc = physx_sys::PxHeightFieldDesc_new();
heightfield_desc.nbRows = heights.nrows() as u32;
heightfield_desc.nbColumns = heights.ncols() as u32;
heightfield_desc.samples.stride = std::mem::size_of::<PxHeightFieldSample>() as u32;
heightfield_desc.samples.data = samples.as_ptr() as *const std::ffi::c_void;
}
let heightfield_desc = PxHeightFieldDesc {
obj: heightfield_desc,
};
let desc = cooking.create_triangle_mesh(physics, desc);
if let TriangleMeshCookingResult::Success(trimesh) = desc {
Some(trimesh)
let heightfield = cooking.create_height_field(physics, &heightfield_desc);
if let Some(mut heightfield) = heightfield {
let flags = PxMeshGeometryFlags {
mBits: physx_sys::PxMeshGeometryFlag::eDOUBLE_SIDED as u8,
};
let geometry = PxHeightFieldGeometry::new(
&mut *heightfield,
flags,
scale.y / Y_FACTOR,
scale.x / (heights.nrows() as f32 - 1.0),
scale.z / (heights.ncols() as f32 - 1.0),
);
physics.create_shape(&geometry, materials, true, shape_flags, ())
} else {
eprintln!("PhysX heightfield construction failed.");
return None;
}
} else if let Some(convex) = shape
.as_convex_polyhedron()
.or(shape.as_round_convex_polyhedron().map(|c| &c.base_shape))
{
let vertices = convex.points();
let mut convex_desc;
unsafe {
convex_desc = physx_sys::PxConvexMeshDesc_new();
convex_desc.points.count = vertices.len() as u32;
convex_desc.points.stride = (3 * std::mem::size_of::<f32>()) as u32;
convex_desc.points.data = vertices.as_ptr() as *const std::ffi::c_void;
convex_desc.flags = PxConvexFlags {
mBits: physx_sys::PxConvexFlag::eCOMPUTE_CONVEX as u16,
};
}
let convex_desc = PxConvexMeshDesc { obj: convex_desc };
let convex = cooking.create_convex_mesh(physics, &convex_desc);
if let ConvexMeshCookingResult::Success(mut convex) = convex {
let flags = PxConvexMeshGeometryFlags { mBits: 0 };
let scaling = unsafe { PxMeshScale_new() };
let geometry = PxConvexMeshGeometry::new(&mut convex, &scaling, flags);
physics.create_shape(&geometry, materials, true, shape_flags, ())
} else {
eprintln!("PhysX convex mesh construction failed.");
return None;
}
} else if let Some(trimesh) = shape.as_trimesh() {
let vertices = trimesh.vertices();
let indices = trimesh.flat_indices();
let mut mesh_desc;
unsafe {
mesh_desc = physx_sys::PxTriangleMeshDesc_new();
mesh_desc.points.count = trimesh.vertices().len() as u32;
mesh_desc.points.stride = (3 * std::mem::size_of::<f32>()) as u32;
mesh_desc.points.data = vertices.as_ptr() as *const std::ffi::c_void;
mesh_desc.triangles.count = (indices.len() as u32) / 3;
mesh_desc.triangles.stride = (3 * std::mem::size_of::<u32>()) as u32;
mesh_desc.triangles.data = indices.as_ptr() as *const std::ffi::c_void;
}
let mesh_desc = PxTriangleMeshDesc { obj: mesh_desc };
let trimesh = cooking.create_triangle_mesh(physics, &mesh_desc);
if let TriangleMeshCookingResult::Success(mut trimesh) = trimesh {
let flags = PxMeshGeometryFlags {
mBits: physx_sys::PxMeshGeometryFlag::eDOUBLE_SIDED as u8,
};
let scaling = unsafe { PxMeshScale_new() };
let geometry = PxTriangleMeshGeometry::new(&mut trimesh, &scaling, flags);
physics.create_shape(&geometry, materials, true, shape_flags, ())
} else {
eprintln!("PhysX triangle mesh construction failed.");
return None;
}
*/
} else {
eprintln!("Creating a shape unknown to the PhysX backend.");
return None;