From 9bf1321f8f1d2e116f44c2461a53f302c4ef4171 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 8 Dec 2020 17:31:49 +0100 Subject: Outsource the contact manifold, SAT, and some shapes. --- src_testbed/engine.rs | 2 +- src_testbed/lib.rs | 4 ++++ src_testbed/nphysics_backend.rs | 7 +++++-- src_testbed/objects/heightfield.rs | 17 ++++++++++------- src_testbed/objects/polyline.rs | 2 +- src_testbed/testbed.rs | 4 ++-- 6 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/engine.rs b/src_testbed/engine.rs index 040c883..a864cfd 100644 --- a/src_testbed/engine.rs +++ b/src_testbed/engine.rs @@ -501,7 +501,7 @@ impl GraphicsManager { object: DefaultColliderHandle, colliders: &DefaultColliderSet, delta: Isometry, - shape: &Cuboid, + shape: &Cuboid, color: Point3, out: &mut Vec, ) { diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs index 5358e7c..0d1483e 100644 --- a/src_testbed/lib.rs +++ b/src_testbed/lib.rs @@ -1,5 +1,9 @@ #[macro_use] extern crate kiss3d; +#[cfg(feature = "dim2")] +extern crate buckler2d as buckler; +#[cfg(feature = "dim3")] +extern crate buckler3d as buckler; extern crate nalgebra as na; #[cfg(feature = "dim2")] extern crate ncollide2d as ncollide; diff --git a/src_testbed/nphysics_backend.rs b/src_testbed/nphysics_backend.rs index e112c22..4384480 100644 --- a/src_testbed/nphysics_backend.rs +++ b/src_testbed/nphysics_backend.rs @@ -1,4 +1,4 @@ -use ncollide::shape::{Ball, Capsule, Cuboid, ShapeHandle}; +use ncollide::shape::{Ball, Capsule, Cuboid, HeightField, ShapeHandle}; use nphysics::force_generator::DefaultForceGeneratorSet; use nphysics::joint::{ DefaultJointConstraintSet, FixedConstraint, PrismaticConstraint, RevoluteConstraint, @@ -187,7 +187,10 @@ fn nphysics_collider_from_rapier_collider( pos *= capsule.transform_wrt_y(); ShapeHandle::new(Capsule::new(capsule.half_height(), capsule.radius)) } else if let Some(heightfield) = shape.as_heightfield() { - ShapeHandle::new(heightfield.clone()) + let heights = heightfield.heights(); + let scale = heightfield.scale(); + let heightfield = HeightField::new(heights.clone(), *scale); + ShapeHandle::new(heightfield) } else { #[cfg(feature = "dim3")] if let Some(trimesh) = shape.as_trimesh() { diff --git a/src_testbed/objects/heightfield.rs b/src_testbed/objects/heightfield.rs index 0815592..977bcca 100644 --- a/src_testbed/objects/heightfield.rs +++ b/src_testbed/objects/heightfield.rs @@ -1,15 +1,16 @@ #[cfg(feature = "dim3")] use crate::objects::node::{self, GraphicsNode}; +use buckler::shape; +use kiss3d::resource::Mesh; use kiss3d::window::Window; use na::{self, Point3}; -use ncollide::shape; -#[cfg(feature = "dim3")] -use ncollide::transformation::ToTriMesh; use rapier::geometry::{ColliderHandle, ColliderSet}; #[cfg(feature = "dim2")] use rapier::math::Point; #[cfg(feature = "dim3")] use rapier::math::Vector; +use std::cell::RefCell; +use std::rc::Rc; pub struct HeightField { color: Point3, @@ -25,7 +26,7 @@ impl HeightField { #[cfg(feature = "dim2")] pub fn new( collider: ColliderHandle, - heightfield: &shape::HeightField, + heightfield: &shape::HeightField, color: Point3, _: &mut Window, ) -> HeightField { @@ -47,16 +48,18 @@ impl HeightField { #[cfg(feature = "dim3")] pub fn new( collider: ColliderHandle, - heightfield: &shape::HeightField, + heightfield: &shape::HeightField, color: Point3, window: &mut Window, ) -> HeightField { - let mesh = heightfield.to_trimesh(()); + let (vertices, indices) = heightfield.to_trimesh(); + let indices = indices.into_iter().map(|i| na::convert(i)).collect(); + let mesh = Mesh::new(vertices, indices, None, None, false); let mut res = HeightField { color, base_color: color, - gfx: window.add_trimesh(mesh, Vector::repeat(1.0)), + gfx: window.add_mesh(Rc::new(RefCell::new(mesh)), Vector::repeat(1.0)), collider: collider, }; diff --git a/src_testbed/objects/polyline.rs b/src_testbed/objects/polyline.rs index 77841ae..efb5e95 100644 --- a/src_testbed/objects/polyline.rs +++ b/src_testbed/objects/polyline.rs @@ -1,6 +1,6 @@ +use buckler2d::shape; use kiss3d::window::Window; use na::{Isometry2, Point2, Point3}; -use ncollide2d::shape; use nphysics2d::object::{ColliderAnchor, DefaultColliderHandle, DefaultColliderSet}; pub struct Polyline { diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 4fac8e1..60fb5d9 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -1521,8 +1521,8 @@ fn draw_contacts(window: &mut Window, nf: &NarrowPhase, colliders: &ColliderSet) } else { Point3::new(1.0, 0.0, 0.0) }; - let pos1 = colliders[manifold.pair.collider1].position(); - let pos2 = colliders[manifold.pair.collider2].position(); + let pos1 = colliders[manifold.data.pair.collider1].position(); + let pos2 = colliders[manifold.data.pair.collider2].position(); let start = pos1 * pt.local_p1; let end = pos2 * pt.local_p2; let n = pos1 * manifold.local_n1; -- cgit From e231bacec608fa5efd24f7a876572927dbd6c9c4 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 10:24:36 +0100 Subject: Move all the contact manifold computations out of Rapier. --- src_testbed/lib.rs | 4 ++-- src_testbed/objects/heightfield.rs | 2 +- src_testbed/objects/polyline.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs index 0d1483e..0880419 100644 --- a/src_testbed/lib.rs +++ b/src_testbed/lib.rs @@ -1,9 +1,9 @@ #[macro_use] extern crate kiss3d; #[cfg(feature = "dim2")] -extern crate buckler2d as buckler; +extern crate eagl2d as eagl; #[cfg(feature = "dim3")] -extern crate buckler3d as buckler; +extern crate eagl3d as eagl; extern crate nalgebra as na; #[cfg(feature = "dim2")] extern crate ncollide2d as ncollide; diff --git a/src_testbed/objects/heightfield.rs b/src_testbed/objects/heightfield.rs index 977bcca..a631b71 100644 --- a/src_testbed/objects/heightfield.rs +++ b/src_testbed/objects/heightfield.rs @@ -1,6 +1,6 @@ #[cfg(feature = "dim3")] use crate::objects::node::{self, GraphicsNode}; -use buckler::shape; +use eagl::shape; use kiss3d::resource::Mesh; use kiss3d::window::Window; use na::{self, Point3}; diff --git a/src_testbed/objects/polyline.rs b/src_testbed/objects/polyline.rs index efb5e95..62edc69 100644 --- a/src_testbed/objects/polyline.rs +++ b/src_testbed/objects/polyline.rs @@ -1,4 +1,4 @@ -use buckler2d::shape; +use eagl2d::shape; use kiss3d::window::Window; use na::{Isometry2, Point2, Point3}; use nphysics2d::object::{ColliderAnchor, DefaultColliderHandle, DefaultColliderSet}; -- cgit From 29717c2887b2db39faf9c25053730b661dc5da2b Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 13:23:00 +0100 Subject: Externalize the proximity code (renamed intersection). --- src_testbed/testbed.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 60fb5d9..2a72414 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -202,11 +202,11 @@ impl Testbed { }; let contact_channel = crossbeam::channel::unbounded(); - let proximity_channel = crossbeam::channel::unbounded(); - let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0); + let intersection_channel = crossbeam::channel::unbounded(); + let event_handler = ChannelEventCollector::new(intersection_channel.0, contact_channel.0); let events = PhysicsEvents { contact_events: contact_channel.1, - proximity_events: proximity_channel.1, + intersection_events: intersection_channel.1, }; let physics = PhysicsState::new(); -- cgit From 8fe2df126a279a435cc544b150aadf8f7b757868 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 17 Dec 2020 18:37:16 +0100 Subject: Remove some irrelevant code. --- src_testbed/lib.rs | 4 ++-- src_testbed/objects/heightfield.rs | 2 +- src_testbed/objects/polyline.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/lib.rs b/src_testbed/lib.rs index 0880419..d6ea1c3 100644 --- a/src_testbed/lib.rs +++ b/src_testbed/lib.rs @@ -1,9 +1,9 @@ #[macro_use] extern crate kiss3d; #[cfg(feature = "dim2")] -extern crate eagl2d as eagl; +extern crate cdl2d as cdl; #[cfg(feature = "dim3")] -extern crate eagl3d as eagl; +extern crate cdl3d as cdl; extern crate nalgebra as na; #[cfg(feature = "dim2")] extern crate ncollide2d as ncollide; diff --git a/src_testbed/objects/heightfield.rs b/src_testbed/objects/heightfield.rs index a631b71..dbf14ad 100644 --- a/src_testbed/objects/heightfield.rs +++ b/src_testbed/objects/heightfield.rs @@ -1,6 +1,6 @@ #[cfg(feature = "dim3")] use crate::objects::node::{self, GraphicsNode}; -use eagl::shape; +use cdl::shape; use kiss3d::resource::Mesh; use kiss3d::window::Window; use na::{self, Point3}; diff --git a/src_testbed/objects/polyline.rs b/src_testbed/objects/polyline.rs index 62edc69..a7422b3 100644 --- a/src_testbed/objects/polyline.rs +++ b/src_testbed/objects/polyline.rs @@ -1,4 +1,4 @@ -use eagl2d::shape; +use cdl2d::shape; use kiss3d::window::Window; use na::{Isometry2, Point2, Point3}; use nphysics2d::object::{ColliderAnchor, DefaultColliderHandle, DefaultColliderSet}; -- cgit From 0fb4b4faefc59213b2731b9b3f7fa4bfde8212ba Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Fri, 18 Dec 2020 17:08:00 +0100 Subject: Use Isometry::inv_mul. --- src_testbed/testbed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src_testbed') diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 2a72414..cc4262f 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -745,7 +745,7 @@ impl Testbed { .unwrap() .position(); let attach1 = self.cursor_pos; - let attach2 = body_pos.inverse() * attach1; + let attach2 = body_pos.inv_mul(&attach1); if let Some(ground) = self.ground_handle { let joint = MouseConstraint::new( -- cgit From 486fbd972f7951edf2d576c7c6bcbd02dcc28011 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 21 Dec 2020 16:01:22 +0100 Subject: Add example for 3D convex polyhedron. --- src_testbed/engine.rs | 30 +++++++++++++++++++++++++----- src_testbed/objects/convex.rs | 9 ++++++++- 2 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/engine.rs b/src_testbed/engine.rs index a864cfd..b1ecc8b 100644 --- a/src_testbed/engine.rs +++ b/src_testbed/engine.rs @@ -14,7 +14,7 @@ use crate::objects::node::{GraphicsNode, Node}; use rapier::dynamics::{RigidBodyHandle, RigidBodySet}; use rapier::geometry::{Collider, ColliderHandle, ColliderSet}; //use crate::objects::capsule::Capsule; -//use crate::objects::convex::Convex; +use crate::objects::convex::Convex; //#[cfg(feature = "dim3")] //use crate::objects::mesh::Mesh; //use crate::objects::plane::Plane; @@ -292,7 +292,10 @@ impl GraphicsManager { // window, // ))), - if let Some(cuboid) = shape.as_cuboid() { + if let Some(cuboid) = shape + .as_cuboid() + .or(shape.as_round_cuboid().map(|r| &r.base_shape)) + { out.push(Node::Box(BoxNode::new( handle, cuboid.half_extents, @@ -305,7 +308,10 @@ impl GraphicsManager { out.push(Node::Capsule(Capsule::new(handle, capsule, color, window))) } - if let Some(triangle) = shape.as_triangle() { + if let Some(triangle) = shape + .as_triangle() + .or(shape.as_round_triangle().map(|r| &r.base_shape)) + { out.push(Node::Mesh(Mesh::new( handle, vec![triangle.a, triangle.b, triangle.c], @@ -338,10 +344,21 @@ impl GraphicsManager { ))) } + #[cfg(feature = "dim3")] + if let Some(convex_polyhedron) = shape + .as_convex_polyhedron() + .or(shape.as_round_convex_polyhedron().map(|r| &r.base_shape)) + { + let (vertices, indices) = convex_polyhedron.to_trimesh(); + out.push(Node::Convex(Convex::new( + handle, vertices, indices, color, window, + ))) + } + #[cfg(feature = "dim3")] if let Some(cylinder) = shape .as_cylinder() - .or(shape.as_round_cylinder().map(|r| &r.cylinder)) + .or(shape.as_round_cylinder().map(|r| &r.base_shape)) { out.push(Node::Cylinder(Cylinder::new( handle, @@ -353,7 +370,10 @@ impl GraphicsManager { } #[cfg(feature = "dim3")] - if let Some(cone) = shape.as_cone() { + if let Some(cone) = shape + .as_cone() + .or(shape.as_round_cone().map(|r| &r.base_shape)) + { out.push(Node::Cone(Cone::new( handle, cone.half_height, diff --git a/src_testbed/objects/convex.rs b/src_testbed/objects/convex.rs index 0347144..9f0983d 100644 --- a/src_testbed/objects/convex.rs +++ b/src_testbed/objects/convex.rs @@ -19,13 +19,20 @@ impl Convex { pub fn new( body: ColliderHandle, vertices: Vec>, + #[cfg(feature = "dim3")] indices: Vec>, color: Point3, window: &mut Window, ) -> Convex { #[cfg(feature = "dim2")] let node = window.add_convex_polygon(vertices, Vector::from_element(1.0)); #[cfg(feature = "dim3")] - let node = unimplemented!(); + let node = { + use std::cell::RefCell; + use std::rc::Rc; + let is = indices.into_iter().map(na::convert).collect(); + let mesh = kiss3d::resource::Mesh::new(vertices, is, None, None, false); + window.add_mesh(Rc::new(RefCell::new(mesh)), na::Vector3::from_element(1.0)) + }; let mut res = Convex { color, -- cgit From 27ebb541f8766477464ce3e910ba3fd0822df818 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 21 Dec 2020 16:02:57 +0100 Subject: Start upgrading to physx 0.10. --- src_testbed/physx_backend.rs | 543 +++++++++++++++++++------------------------ 1 file changed, 234 insertions(+), 309 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/physx_backend.rs b/src_testbed/physx_backend.rs index acec5c9..eac7323 100644 --- a/src_testbed/physx_backend.rs +++ b/src_testbed/physx_backend.rs @@ -1,7 +1,14 @@ #![allow(dead_code)] -use na::{Isometry3, Matrix3, Matrix4, Point3, Rotation3, Translation3, UnitQuaternion, Vector3}; +use na::{ + Isometry3, Matrix3, Matrix4, Point3, Quaternion, Rotation3, Translation3, Unit, UnitQuaternion, + Vector3, +}; +use physx::cooking::PxCooking; +use physx::foundation::DefaultAllocator; use physx::prelude::*; +use physx::scene::FrictionType; +use physx::triangle_mesh::TriangleMesh; use rapier::counters::Counters; use rapier::dynamics::{ IntegrationParameters, JointParams, JointSet, RigidBodyHandle, RigidBodySet, @@ -10,8 +17,6 @@ use rapier::geometry::{Collider, ColliderSet}; use rapier::utils::WBasis; use std::collections::HashMap; -const PX_PHYSICS_VERSION: u32 = physx::version(4, 1, 1); - trait IntoNa { type Output; fn into_na(self) -> Self::Output; @@ -24,37 +29,53 @@ impl IntoNa for glam::Mat4 { } } +impl IntoNa for PxVec3 { + type Output = Vector3; + fn into_na(self) -> Self::Output { + Vector3::new(self.x(), self.y(), self.z()) + } +} + +impl IntoNa for PxQuat { + type Output = Quaternion; + fn into_na(self) -> Self::Output { + Quaternion::new(self.w(), self.x(), self.y(), self.z()) + } +} + +impl IntoNa for PxTransform { + type Output = Isometry3; + fn into_na(self) -> Self::Output { + let tra = self.translation().into_na(); + let quat = self.rotation().into_na(); + let unit_quat = Unit::new_unchecked(quat); + Isometry3::from_parts(tra.into(), unit_quat) + } +} + trait IntoPhysx { type Output; fn into_physx(self) -> Self::Output; } impl IntoPhysx for Vector3 { - type Output = physx_sys::PxVec3; + type Output = PxVec3; fn into_physx(self) -> Self::Output { - physx_sys::PxVec3 { - x: self.x, - y: self.y, - z: self.z, - } + PxVec3::new(self.x, self.y, self.z) } } impl IntoPhysx for Point3 { - type Output = physx_sys::PxVec3; + type Output = PxVec3; fn into_physx(self) -> Self::Output { - physx_sys::PxVec3 { - x: self.x, - y: self.y, - z: self.z, - } + PxVec3::new(self.x, self.y, self.z) } } impl IntoPhysx for Isometry3 { - type Output = physx_sys::PxTransform; + type Output = PxTransform; fn into_physx(self) -> Self::Output { - physx::transform::gl_to_px_tf(self.into_glam()) + self.into_glam().into() } } @@ -92,14 +113,23 @@ impl IntoGlam for Isometry3 { } thread_local! { -pub static FOUNDATION: std::cell::RefCell = std::cell::RefCell::new(Foundation::new(PX_PHYSICS_VERSION)); +pub static FOUNDATION: std::cell::RefCell = std::cell::RefCell::new(PhysicsFoundation::default()); } pub struct PhysxWorld { - physics: Physics, - cooking: Cooking, - scene: Scene, - rapier2physx: HashMap, + // physics: Physics, + // cooking: Cooking, + materials: Vec>, + shapes: Vec>, + scene: Option>, +} + +impl Drop for PhysxWorld { + fn drop(&mut self) { + let scene = self.scene.take(); + // FIXME: we get a segfault if we don't forget the scene. + std::mem::forget(scene); + } } impl PhysxWorld { @@ -112,123 +142,72 @@ impl PhysxWorld { use_two_friction_directions: bool, num_threads: usize, ) -> Self { - let mut rapier2physx = HashMap::new(); - let mut physics = FOUNDATION.with(|f| { - PhysicsBuilder::default() - .load_extensions(false) - .build(&mut *f.borrow_mut()) - }); - let mut cooking = FOUNDATION.with(|f| unsafe { - let sc = physx_sys::PxTolerancesScale_new(); - let params = physx_sys::PxCookingParams_new(&sc); - Cooking::new(PX_PHYSICS_VERSION, &mut *f.borrow_mut(), params) - }); - - let scene_desc = MySceneBuilder::default() - .set_gravity(gravity.into_glam()) - .set_simulation_threading(SimulationThreadType::Dedicated(num_threads as u32)) - // .set_broad_phase_type(BroadPhaseType::SweepAndPrune) - // .set_solver_type(physx_sys::PxSolverType::eTGS) - .build_desc(&mut physics); - - let raw_scene = - unsafe { physx_sys::PxPhysics_createScene_mut(physics.get_raw_mut(), &scene_desc) }; - - // FIXME: we do this because we are also using two - // friction directions. We should add to rapier the option to use - // one friction direction too, and perhaps an equivalent of physX - // ePATCH friction type. - if use_two_friction_directions { - unsafe { - physx_sys::PxScene_setFrictionType_mut( - raw_scene, - physx_sys::PxFrictionType::eTWO_DIRECTIONAL, - ); - } - } + FOUNDATION.with(|physics| { + let mut physics = physics.borrow_mut(); + let mut shapes = Vec::new(); + let mut materials = Vec::new(); - let mut scene = Scene::new(raw_scene); + let friction_type = if use_two_friction_directions { + FrictionType::TwoDirectional + } else { + FrictionType::Patch + }; - for (rapier_handle, rb) in bodies.iter() { - use physx::rigid_dynamic::RigidDynamic; - use physx::rigid_static::RigidStatic; - use physx::transform; + let scene_desc = SceneDescriptor { + gravity: gravity.into_physx(), + thread_count: num_threads as u32, + broad_phase_type: BroadPhaseType::AutomaticBoxPruning, + solver_type: SolverType::PGS, + friction_type, + ..SceneDescriptor::new(()) + }; - let pos = transform::gl_to_px_tf(rb.position().to_homogeneous().into_glam()); - if rb.is_dynamic() { - let actor = unsafe { - physx_sys::PxPhysics_createRigidDynamic_mut(physics.get_raw_mut(), &pos) - }; + let mut scene: Owner = physics.create(scene_desc).unwrap(); + let mut rapier2dynamic = HashMap::new(); + let mut rapier2static = HashMap::new(); - unsafe { - physx_sys::PxRigidDynamic_setSolverIterationCounts_mut( - actor, + 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(); + actor.set_solver_iteration_counts( integration_parameters.max_position_iterations as u32, integration_parameters.max_velocity_iterations as u32, ); - } - let physx_handle = scene.add_dynamic(RigidDynamic::new(actor)); - rapier2physx.insert(rapier_handle, physx_handle); - } else { - let actor = unsafe { - physx_sys::PxPhysics_createRigidStatic_mut(physics.get_raw_mut(), &pos) - }; - - let physx_handle = scene.add_actor(RigidStatic::new(actor)); - rapier2physx.insert(rapier_handle, physx_handle); + rapier2dynamic.insert(rapier_handle, actor); + } else { + let actor = physics.create_static(pos, ()).unwrap(); + rapier2static.insert(rapier_handle, actor); + } } - } - for (_, collider) in colliders.iter() { - if let Some((px_collider, collider_pos)) = - physx_collider_from_rapier_collider(&collider) - { - let material = physics.create_material( - collider.friction, - collider.friction, - collider.restitution, - ); - let geometry = cooking.make_geometry(px_collider); - let flags = if collider.is_sensor() { - physx_sys::PxShapeFlags { - mBits: physx_sys::PxShapeFlag::eTRIGGER_SHAPE as u8, - } - } else { - physx_sys::PxShapeFlags { - mBits: physx_sys::PxShapeFlag::eSIMULATION_SHAPE as u8, // | physx_sys::PxShapeFlag::eSCENE_QUERY_SHAPE as u8, - } - }; + for (_, collider) in colliders.iter() { + if let Some((mut px_shape, px_material, collider_pos)) = + physx_collider_from_rapier_collider(&mut *physics, &collider) + { + let parent_body = &bodies[collider.parent()]; - let handle = rapier2physx[&collider.parent()]; - let parent_body = &bodies[collider.parent()]; - let parent = if !parent_body.is_dynamic() { - scene.get_static_mut(handle).unwrap().as_ptr_mut().ptr - as *mut physx_sys::PxRigidActor - } else { - scene.get_dynamic_mut(handle).unwrap().as_ptr_mut().ptr - as *mut physx_sys::PxRigidActor - }; + if !parent_body.is_dynamic() { + let actor = rapier2static.get_mut(&collider.parent()).unwrap(); + actor.attach_shape(&mut px_shape); + } else { + let actor = rapier2dynamic.get_mut(&collider.parent()).unwrap(); + actor.attach_shape(&mut px_shape); + } + // physx_sys::PxShape_setLocalPose_mut(shape, &pose); - unsafe { - let shape = physx_sys::PxPhysics_createShape_mut( - physics.get_raw_mut(), - geometry.as_raw(), - material, - true, - flags.into(), - ); - let pose = collider_pos.into_physx(); - physx_sys::PxShape_setLocalPose_mut(shape, &pose); - physx_sys::PxRigidActor_attachShape_mut(parent, shape); - }; + shapes.push(px_shape); + materials.push(px_material); + } } - } - // Update mass properties. - for (rapier_handle, physx_handle) in rapier2physx.iter() { - let rb = &bodies[*rapier_handle]; - if let Some(rp) = scene.get_dynamic_mut(*physx_handle) { + // Update mass properties. + for (rapier_handle, actor) in rapier2dynamic.iter_mut() { + let rb = &bodies[*rapier_handle]; let densities: Vec<_> = rb .colliders() .iter() @@ -237,7 +216,7 @@ impl PhysxWorld { unsafe { physx_sys::PxRigidBodyExt_updateMassAndInertia_mut( - rp.as_ptr_mut().ptr as *mut physx_sys::PxRigidBody, + std::mem::transmute(actor.as_mut()), densities.as_ptr(), densities.len() as u32, std::ptr::null(), @@ -245,20 +224,30 @@ impl PhysxWorld { ); } } - } - let mut res = Self { - physics, - cooking, - scene, - rapier2physx, - }; + /* + res.setup_joints(joints); + res + */ + + for (_, actor) in rapier2static { + scene.add_static_actor(actor); + } + + for (_, actor) in rapier2dynamic { + scene.add_dynamic_actor(actor); + } - res.setup_joints(joints); - res + Self { + scene: Some(scene), + shapes, + materials, + } + }) } fn setup_joints(&mut self, joints: &JointSet) { + /* unsafe { for joint in joints.iter() { let actor1 = self.rapier2physx[&joint.1.body1]; @@ -392,46 +381,73 @@ impl PhysxWorld { } } } + */ } pub fn step(&mut self, counters: &mut Counters, params: &IntegrationParameters) { + let mut scratch = unsafe { ScratchBuffer::new(4) }; + counters.step_started(); - self.scene.step(params.dt(), true); + self.scene + .as_mut() + .unwrap() + .step( + params.dt(), + None::<&mut physx_sys::PxBaseTask>, + Some(&mut scratch), + true, + ) + .expect("error occurred during PhysX simulation"); counters.step_completed(); } - pub fn sync(&self, bodies: &mut RigidBodySet, colliders: &mut ColliderSet) { - for (rapier_handle, physx_handle) in self.rapier2physx.iter() { - let rb = bodies.get_mut(*rapier_handle).unwrap(); - let ra = self.scene.get_rigid_actor(*physx_handle).unwrap(); - let pos = ra.get_global_pose().into_na(); - let iso = na::convert_unchecked(pos); - rb.set_position(iso, false); - - if rb.is_kinematic() {} + pub fn sync(&mut self, bodies: &mut RigidBodySet, colliders: &mut ColliderSet) { + for actor in self.scene.as_mut().unwrap().get_dynamic_actors() { + let handle = actor.get_user_data(); + let pos = actor.get_global_pose().into_na(); + let rb = &mut bodies[*handle]; + rb.set_position(pos, false); for coll_handle in rb.colliders() { let collider = &mut colliders[*coll_handle]; - collider.set_position_debug(iso * collider.position_wrt_parent()); + collider.set_position_debug(pos * collider.position_wrt_parent()); } } } } fn physx_collider_from_rapier_collider( + physics: &mut PxPhysicsFoundation, + // cooking: &PxCooking, collider: &Collider, -) -> Option<(ColliderDesc, Isometry3)> { +) -> Option<(Owner, Owner, Isometry3)> { let mut local_pose = *collider.position_wrt_parent(); let shape = collider.shape(); + let shape_flags = if collider.is_sensor() { + ShapeFlag::TriggerShape.into() + } else { + ShapeFlag::SimulationShape.into() + }; + let mut material = physics + .create_material( + collider.friction, + collider.friction, + collider.restitution, + (), + ) + .unwrap(); + let materials = &mut [material.as_mut()][..]; - let desc = if let Some(cuboid) = shape.as_cuboid() { - ColliderDesc::Box( + let shape = if let Some(cuboid) = shape.as_cuboid() { + let geometry = PxBoxGeometry::new( cuboid.half_extents.x, cuboid.half_extents.y, cuboid.half_extents.z, - ) + ); + physics.create_shape(&geometry, materials, true, shape_flags, ()) } else if let Some(ball) = shape.as_ball() { - ColliderDesc::Sphere(ball.radius) + let geometry = PxSphereGeometry::new(ball.radius); + physics.create_shape(&geometry, materials, true, shape_flags, ()) } else if let Some(capsule) = shape.as_capsule() { let center = capsule.center(); let mut dir = capsule.segment.b - capsule.segment.a; @@ -442,8 +458,11 @@ fn physx_collider_from_rapier_collider( let rot = UnitQuaternion::rotation_between(&Vector3::x(), &dir); local_pose *= Translation3::from(center.coords) * rot.unwrap_or(UnitQuaternion::identity()); - ColliderDesc::Capsule(capsule.radius, capsule.height()) + 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() @@ -452,176 +471,82 @@ fn physx_collider_from_rapier_collider( .collect(), indices: trimesh.flat_indices().to_vec(), mesh_scale: Vector3::repeat(1.0).into_glam(), + }; + let desc = cooking.create_triangle_mesh(physics, desc); + if let TriangleMeshCookingResult::Success(trimesh) = desc { + Some(trimesh) + } else { + eprintln!("PhysX triangle mesh construction failed."); + return None; } + */ } else { eprintln!("Creating a shape unknown to the PhysX backend."); return None; }; - Some((desc, local_pose)) -} - -/* - * - * XXX: All the remaining code is a duplicate from physx-rs to allow more customizations. - * - */ -use physx::scene::SimulationThreadType; - -pub struct MySceneBuilder { - gravity: glam::Vec3, - simulation_filter_shader: Option, - simulation_threading: Option, - broad_phase_type: BroadPhaseType, - use_controller_manager: bool, - controller_manager_locking: bool, - call_default_filter_shader_first: bool, - use_ccd: bool, - enable_ccd_resweep: bool, - solver_type: u32, + shape.map(|s| (s, material, local_pose)) } -impl Default for MySceneBuilder { - fn default() -> Self { - Self { - gravity: glam::Vec3::new(0.0, -9.80665, 0.0), // standard gravity value - call_default_filter_shader_first: true, - simulation_filter_shader: None, - simulation_threading: None, - broad_phase_type: BroadPhaseType::SweepAndPrune, - use_controller_manager: false, - controller_manager_locking: false, - use_ccd: false, - enable_ccd_resweep: false, - solver_type: physx_sys::PxSolverType::ePGS, - } - } -} - -impl MySceneBuilder { - /// Set the gravity for the scene. - /// - /// Default: [0.0, -9.80665, 0.0] (standard gravity) - pub fn set_gravity(&mut self, gravity: glam::Vec3) -> &mut Self { - self.gravity = gravity; - self - } - - /// Set a callback to be invoked on various simulation events. Note: - /// Currently only handles collision events - /// - /// Default: not set - pub fn set_simulation_filter_shader( +type PxPhysicsFoundation = PhysicsFoundation; +type PxMaterial = physx::material::PxMaterial<()>; +type PxShape = physx::shape::PxShape<(), PxMaterial>; +type PxArticulationLink = physx::articulation_link::PxArticulationLink<(), PxShape>; +type PxRigidStatic = physx::rigid_static::PxRigidStatic<(), PxShape>; +type PxRigidDynamic = physx::rigid_dynamic::PxRigidDynamic; +type PxArticulation = physx::articulation::PxArticulation<(), PxArticulationLink>; +type PxArticulationReducedCoordinate = + physx::articulation_reduced_coordinate::PxArticulationReducedCoordinate<(), PxArticulationLink>; +type PxScene = physx::scene::PxScene< + (), + PxArticulationLink, + PxRigidStatic, + PxRigidDynamic, + PxArticulation, + PxArticulationReducedCoordinate, + OnCollision, + OnTrigger, + OnConstraintBreak, + OnWakeSleep, + OnAdvance, +>; + +/// Next up, the simulation event callbacks need to be defined, and possibly an +/// allocator callback as well. +struct OnCollision; +impl CollisionCallback for OnCollision { + fn on_collision( &mut self, - simulation_filter_shader: physx_sys::SimulationFilterShader, - ) -> &mut Self { - self.simulation_filter_shader = Some(simulation_filter_shader); - self - } - - /// Enable the controller manager on the scene. - /// - /// Default: false, false - pub fn use_controller_manager( - &mut self, - use_controller_manager: bool, - locking_enabled: bool, - ) -> &mut Self { - self.use_controller_manager = use_controller_manager; - self.controller_manager_locking = locking_enabled; - self - } - - pub fn set_solver_type(&mut self, solver_type: u32) -> &mut Self { - self.solver_type = solver_type; - self - } - - /// Sets whether the filter should begin by calling the default filter shader - /// PxDefaultSimulationFilterShader that emulates the PhysX 2.8 rules. - /// - /// Default: true - pub fn set_call_default_filter_shader_first( - &mut self, - call_default_filter_shader_first: bool, - ) -> &mut Self { - self.call_default_filter_shader_first = call_default_filter_shader_first; - self + _header: &physx_sys::PxContactPairHeader, + _pairs: &[physx_sys::PxContactPair], + ) { } +} +struct OnTrigger; +impl TriggerCallback for OnTrigger { + fn on_trigger(&mut self, _pairs: &[physx_sys::PxTriggerPair]) {} +} - /// Set the number of threads to use for simulation - /// - /// Default: not set - pub fn set_simulation_threading( +struct OnConstraintBreak; +impl ConstraintBreakCallback for OnConstraintBreak { + fn on_constraint_break(&mut self, _constraints: &[physx_sys::PxConstraintInfo]) {} +} +struct OnWakeSleep; +impl WakeSleepCallback for OnWakeSleep { + fn on_wake_sleep( &mut self, - simulation_threading: SimulationThreadType, - ) -> &mut Self { - self.simulation_threading = Some(simulation_threading); - self - } - - /// Set collision detection type - /// - /// Default: Sweep and prune - pub fn set_broad_phase_type(&mut self, broad_phase_type: BroadPhaseType) -> &mut Self { - self.broad_phase_type = broad_phase_type; - self - } - - /// Set if CCD (continuous collision detection) should be available for use in the scene. - /// Doesn't automatically enable it for all rigid bodies, they still need to be flagged. - /// - /// If you don't set enable_ccd_resweep to true, eDISABLE_CCD_RESWEEP is set, which improves performance - /// at the cost of accuracy right after bounces. - /// - /// Default: false, false - pub fn set_use_ccd(&mut self, use_ccd: bool, enable_ccd_resweep: bool) -> &mut Self { - self.use_ccd = use_ccd; - self.enable_ccd_resweep = enable_ccd_resweep; - self + _actors: &[&physx::actor::ActorMap], + _is_waking: bool, + ) { } +} - pub(super) fn build_desc(&self, physics: &mut Physics) -> physx_sys::PxSceneDesc { - unsafe { - let tolerances = physics.get_tolerances_scale(); - let mut scene_desc = physx_sys::PxSceneDesc_new(tolerances); - - let dispatcher = match self.simulation_threading.as_ref().expect("foo") { - SimulationThreadType::Default => { - physx_sys::phys_PxDefaultCpuDispatcherCreate(1, std::ptr::null_mut()) as *mut _ - } - SimulationThreadType::Dedicated(count) => { - physx_sys::phys_PxDefaultCpuDispatcherCreate(*count, std::ptr::null_mut()) - as *mut _ - } - SimulationThreadType::Shared(dispatcher) => *dispatcher as *mut _, - }; - - scene_desc.cpuDispatcher = dispatcher; - scene_desc.gravity = physx::transform::gl_to_px_v3(self.gravity); - if self.use_ccd { - scene_desc.flags.mBits |= physx_sys::PxSceneFlag::eENABLE_CCD; - if !self.enable_ccd_resweep { - scene_desc.flags.mBits |= physx_sys::PxSceneFlag::eDISABLE_CCD_RESWEEP; - } - } - if let Some(filter_shader) = self.simulation_filter_shader { - physx_sys::enable_custom_filter_shader( - &mut scene_desc as *mut physx_sys::PxSceneDesc, - filter_shader, - if self.call_default_filter_shader_first { - 1 - } else { - 0 - }, - ); - } else { - scene_desc.filterShader = physx_sys::get_default_simulation_filter_shader(); - } - - scene_desc.broadPhaseType = self.broad_phase_type.into(); - scene_desc.solverType = self.solver_type; - scene_desc - } +struct OnAdvance; +impl AdvanceCallback for OnAdvance { + fn on_advance( + &self, + _actors: &[&physx::rigid_body::RigidBodyMap], + _transforms: &[PxTransform], + ) { } } -- cgit From 8d925a02ef97844bc937584a9095c1396daeee35 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Sun, 27 Dec 2020 18:14:22 +0100 Subject: Add convex polygons support. --- src_testbed/box2d_backend.rs | 8 ++++++++ src_testbed/engine.rs | 9 +++++++++ src_testbed/nphysics_backend.rs | 18 +++++++++++++++--- src_testbed/objects/heightfield.rs | 3 ++- 4 files changed, 34 insertions(+), 4 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/box2d_backend.rs b/src_testbed/box2d_backend.rs index f448a6f..2d4ef29 100644 --- a/src_testbed/box2d_backend.rs +++ b/src_testbed/box2d_backend.rs @@ -174,6 +174,14 @@ impl Box2dWorld { b2_shape.set_radius(b.radius); b2_shape.set_position(center); body.create_fixture(&b2_shape, &mut fixture_def); + } else if let Some(p) = shape.as_convex_polygon() { + let vertices: Vec<_> = p + .points() + .iter() + .map(|p| na_vec_to_b2_vec(p.coords)) + .collect(); + let b2_shape = b2::PolygonShape::new_with(&vertices); + body.create_fixture(&b2_shape, &mut fixture_def); } else if let Some(c) = shape.as_cuboid() { let b2_shape = b2::PolygonShape::new_box(c.half_extents.x, c.half_extents.y); body.create_fixture(&b2_shape, &mut fixture_def); diff --git a/src_testbed/engine.rs b/src_testbed/engine.rs index b1ecc8b..a1fd74e 100644 --- a/src_testbed/engine.rs +++ b/src_testbed/engine.rs @@ -344,6 +344,15 @@ impl GraphicsManager { ))) } + #[cfg(feature = "dim2")] + if let Some(convex_polygon) = shape + .as_convex_polygon() + .or(shape.as_round_convex_polygon().map(|r| &r.base_shape)) + { + let vertices = convex_polygon.points().to_vec(); + out.push(Node::Convex(Convex::new(handle, vertices, color, window))) + } + #[cfg(feature = "dim3")] if let Some(convex_polyhedron) = shape .as_convex_polyhedron() diff --git a/src_testbed/nphysics_backend.rs b/src_testbed/nphysics_backend.rs index 4384480..224b5d3 100644 --- a/src_testbed/nphysics_backend.rs +++ b/src_testbed/nphysics_backend.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "dim2")] +use ncollide::shape::ConvexPolygon; use ncollide::shape::{Ball, Capsule, Cuboid, HeightField, ShapeHandle}; use nphysics::force_generator::DefaultForceGeneratorSet; use nphysics::joint::{ @@ -144,6 +146,7 @@ impl NPhysicsWorld { self.mechanical_world .integration_parameters .set_dt(params.dt()); + self.mechanical_world.integration_parameters.warmstart_coeff = params.warmstart_coeff; counters.step_started(); self.mechanical_world.step( @@ -175,12 +178,15 @@ fn nphysics_collider_from_rapier_collider( collider: &Collider, is_dynamic: bool, ) -> Option> { - let margin = ColliderDesc::::default_margin(); + let mut margin = ColliderDesc::::default_margin(); let mut pos = *collider.position_wrt_parent(); let shape = collider.shape(); let shape = if let Some(cuboid) = shape.as_cuboid() { ShapeHandle::new(Cuboid::new(cuboid.half_extents.map(|e| e - margin))) + } else if let Some(cuboid) = shape.as_round_cuboid() { + margin = cuboid.border_radius; + ShapeHandle::new(Cuboid::new(cuboid.base_shape.half_extents)) } else if let Some(ball) = shape.as_ball() { ShapeHandle::new(Ball::new(ball.radius - margin)) } else if let Some(capsule) = shape.as_capsule() { @@ -208,7 +214,12 @@ fn nphysics_collider_from_rapier_collider( } #[cfg(feature = "dim2")] - { + if let Some(polygon) = shape.as_round_convex_polygon() { + margin = polygon.border_radius; + ShapeHandle::new(ConvexPolygon::try_from_points(polygon.base_shape.points()).unwrap()) + } else if let Some(polygon) = shape.as_convex_polygon() { + ShapeHandle::new(ConvexPolygon::try_from_points(polygon.points()).unwrap()) + } else { return None; } }; @@ -219,6 +230,7 @@ fn nphysics_collider_from_rapier_collider( ColliderDesc::new(shape) .position(pos) .density(density) - .sensor(collider.is_sensor()), + .sensor(collider.is_sensor()) + .margin(margin), ) } diff --git a/src_testbed/objects/heightfield.rs b/src_testbed/objects/heightfield.rs index dbf14ad..fed168d 100644 --- a/src_testbed/objects/heightfield.rs +++ b/src_testbed/objects/heightfield.rs @@ -10,7 +10,6 @@ use rapier::math::Point; #[cfg(feature = "dim3")] use rapier::math::Vector; use std::cell::RefCell; -use std::rc::Rc; pub struct HeightField { color: Point3, @@ -52,6 +51,8 @@ impl HeightField { color: Point3, window: &mut Window, ) -> HeightField { + use std::rc::Rc; + let (vertices, indices) = heightfield.to_trimesh(); let indices = indices.into_iter().map(|i| na::convert(i)).collect(); let mesh = Mesh::new(vertices, indices, None, None, false); -- cgit From 94c67a0c31e9da373c3aca3560dc9accc3308a7a Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Mon, 28 Dec 2020 18:12:33 +0100 Subject: Support compound shapes. --- src_testbed/harness/mod.rs | 2 +- src_testbed/physics/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/harness/mod.rs b/src_testbed/harness/mod.rs index fa6c4c6..c95a722 100644 --- a/src_testbed/harness/mod.rs +++ b/src_testbed/harness/mod.rs @@ -43,7 +43,7 @@ impl Harness { let event_handler = ChannelEventCollector::new(proximity_channel.0, contact_channel.0); let events = PhysicsEvents { contact_events: contact_channel.1, - proximity_events: proximity_channel.1, + intersection_events: proximity_channel.1, }; let physics = PhysicsState::new(); let state = HarnessState { diff --git a/src_testbed/physics/mod.rs b/src_testbed/physics/mod.rs index 4b1923f..808e9bd 100644 --- a/src_testbed/physics/mod.rs +++ b/src_testbed/physics/mod.rs @@ -1,6 +1,6 @@ use crossbeam::channel::Receiver; use rapier::dynamics::{IntegrationParameters, JointSet, RigidBodySet}; -use rapier::geometry::{BroadPhase, ColliderSet, ContactEvent, NarrowPhase, ProximityEvent}; +use rapier::geometry::{BroadPhase, ColliderSet, ContactEvent, IntersectionEvent, NarrowPhase}; use rapier::math::Vector; use rapier::pipeline::{PhysicsPipeline, QueryPipeline}; @@ -97,12 +97,12 @@ impl PhysicsState { pub struct PhysicsEvents { pub contact_events: Receiver, - pub proximity_events: Receiver, + pub intersection_events: Receiver, } impl PhysicsEvents { pub fn poll_all(&self) { while let Ok(_) = self.contact_events.try_recv() {} - while let Ok(_) = self.proximity_events.try_recv() {} + while let Ok(_) = self.intersection_events.try_recv() {} } } -- cgit From 5876a262daa3b6544f132e6654923c2bfabe35d9 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Wed, 30 Dec 2020 11:44:08 +0100 Subject: Remove the useless manifold.data.pair field. --- src_testbed/testbed.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index cc4262f..5924553 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -1521,8 +1521,8 @@ fn draw_contacts(window: &mut Window, nf: &NarrowPhase, colliders: &ColliderSet) } else { Point3::new(1.0, 0.0, 0.0) }; - let pos1 = colliders[manifold.data.pair.collider1].position(); - let pos2 = colliders[manifold.data.pair.collider2].position(); + let pos1 = colliders[pair.pair.collider1].position(); + let pos2 = colliders[pair.pair.collider2].position(); let start = pos1 * pt.local_p1; let end = pos2 * pt.local_p2; let n = pos1 * manifold.local_n1; -- cgit From 967145a9492175be59e8db33299b1687d69d84e2 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 11:16:03 +0100 Subject: Perform contact sorting in the narrow-phase directly. --- src_testbed/testbed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src_testbed') diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 5924553..1ab82da 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -1515,7 +1515,7 @@ Hashes at frame: {} fn draw_contacts(window: &mut Window, nf: &NarrowPhase, colliders: &ColliderSet) { for pair in nf.contact_pairs() { for manifold in &pair.manifolds { - for pt in manifold.all_contacts() { + for pt in manifold.contacts() { let color = if pt.dist > 0.0 { Point3::new(0.0, 0.0, 1.0) } else { -- cgit From 7b098606c230256c72b73291c15cbd5fabe02653 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Thu, 31 Dec 2020 16:30:38 +0100 Subject: QueryPipeline: add shape casting, point projection, and intersection queries. --- src_testbed/testbed.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src_testbed') diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index 1ab82da..b1a529f 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -1032,10 +1032,12 @@ impl Testbed { &self.physics.colliders, &ray, f32::MAX, + true, InteractionGroups::all(), ); - if let Some((_, collider, _)) = hit { + if let Some((handle, _)) = hit { + let collider = &self.physics.colliders[handle]; if self.physics.bodies[collider.parent()].is_dynamic() { self.state.highlighted_body = Some(collider.parent()); for node in self.graphics.body_nodes_mut(collider.parent()).unwrap() { -- cgit From 00da4aaa42cc921bbd8c469b45c5c1e304f46260 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 5 Jan 2021 15:34:48 +0100 Subject: Add compound shape support. --- src_testbed/engine.rs | 61 +++++++++++++++++++++++++++++------------ src_testbed/objects/ball.rs | 7 +++-- src_testbed/objects/box_node.rs | 7 +++-- src_testbed/objects/capsule.rs | 7 +++-- src_testbed/objects/cone.rs | 7 +++-- src_testbed/objects/convex.rs | 7 +++-- src_testbed/objects/cylinder.rs | 7 +++-- src_testbed/testbed.rs | 12 +++++--- 8 files changed, 81 insertions(+), 34 deletions(-) (limited to 'src_testbed') diff --git a/src_testbed/engine.rs b/src_testbed/engine.rs index a1fd74e..1b7ab4b 100644 --- a/src_testbed/engine.rs +++ b/src_testbed/engine.rs @@ -6,13 +6,13 @@ use kiss3d::window::Window; use na::Point3; -use crate::math::Point; +use crate::math::{Isometry, Point}; use crate::objects::ball::Ball; use crate::objects::box_node::Box as BoxNode; use crate::objects::heightfield::HeightField; use crate::objects::node::{GraphicsNode, Node}; use rapier::dynamics::{RigidBodyHandle, RigidBodySet}; -use rapier::geometry::{Collider, ColliderHandle, ColliderSet}; +use rapier::geometry::{Collider, ColliderHandle, ColliderSet, Shape}; //use crate::objects::capsule::Capsule; use crate::objects::convex::Convex; //#[cfg(feature = "dim3")] @@ -237,7 +237,14 @@ impl GraphicsManager { for collider_handle in bodies[handle].colliders() { let color = self.c2color.get(collider_handle).copied().unwrap_or(color); let collider = &colliders[*collider_handle]; - self.do_add_collider(window, *collider_handle, collider, color, &mut new_nodes); + self.do_add_shape( + window, + *collider_handle, + collider.shape(), + &Isometry::identity(), + color, + &mut new_nodes, + ); } new_nodes.iter_mut().for_each(|n| n.update(colliders)); @@ -267,37 +274,49 @@ impl GraphicsManager { let color = self.c2color.get(&handle).copied().unwrap_or(color); let mut nodes = std::mem::replace(self.b2sn.get_mut(&collider.parent()).unwrap(), Vec::new()); - self.do_add_collider(window, handle, collider, color, &mut nodes); + self.do_add_shape( + window, + handle, + collider.shape(), + &Isometry::identity(), + color, + &mut nodes, + ); self.b2sn.insert(collider.parent(), nodes); } - fn do_add_collider( + fn do_add_shape( &mut self, window: &mut Window, handle: ColliderHandle, - collider: &Collider, + shape: &dyn Shape, + delta: &Isometry, color: Point3, out: &mut Vec, ) { - let shape = collider.shape(); + if let Some(compound) = shape.as_compound() { + for (shape_pos, shape) in compound.shapes() { + self.do_add_shape(window, handle, &**shape, shape_pos, color, out) + } + } if let Some(ball) = shape.as_ball() { - out.push(Node::Ball(Ball::new(handle, ball.radius, color, window))) + out.push(Node::Ball(Ball::new( + handle, + *delta, + ball.radius, + color, + window, + ))) } - // Shape::Polygon(poly) => out.push(Node::Convex(Convex::new( - // handle, - // poly.vertices().to_vec(), - // color, - // window, - // ))), - if let Some(cuboid) = shape .as_cuboid() .or(shape.as_round_cuboid().map(|r| &r.base_shape)) { out.push(Node::Box(BoxNode::new( handle, + *delta, cuboid.half_extents, color, window, @@ -305,7 +324,9 @@ impl GraphicsManager { } if let Some(capsule) = shape.as_capsule() { - out.push(Node::Capsule(Capsule::new(handle, capsule, color, window))) + out.push(Node::Capsule(Capsule::new( + handle, *delta, capsule, color, window, + ))) } if let Some(triangle) = shape @@ -350,7 +371,9 @@ impl GraphicsManager { .or(shape.as_round_convex_polygon().map(|r| &r.base_shape)) { let vertices = convex_polygon.points().to_vec(); - out.push(Node::Convex(Convex::new(handle, vertices, color, window))) + out.push(Node::Convex(Convex::new( + handle, *delta, vertices, color, window, + ))) } #[cfg(feature = "dim3")] @@ -360,7 +383,7 @@ impl GraphicsManager { { let (vertices, indices) = convex_polyhedron.to_trimesh(); out.push(Node::Convex(Convex::new( - handle, vertices, indices, color, window, + handle, *delta, vertices, indices, color, window, ))) } @@ -371,6 +394,7 @@ impl GraphicsManager { { out.push(Node::Cylinder(Cylinder::new( handle, + *delta, cylinder.half_height, cylinder.radius, color, @@ -385,6 +409,7 @@ impl GraphicsManager { { out.push(Node::Cone(Cone::new( handle, + *delta, cone.half_height, cone.radius, color, diff --git a/src_testbed/objects/ball.rs b/src_testbed/objects/ball.rs index f72c284..4df3820 100644 --- a/src_testbed/objects/ball.rs +++ b/src_testbed/objects/ball.rs @@ -1,6 +1,6 @@ use crate::objects::node::{self, GraphicsNode}; use kiss3d::window::Window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{ColliderHandle, ColliderSet}; use rapier::math::Isometry; @@ -9,11 +9,13 @@ pub struct Ball { base_color: Point3, gfx: GraphicsNode, collider: ColliderHandle, + delta: Isometry3, } impl Ball { pub fn new( collider: ColliderHandle, + delta: Isometry3, radius: f32, color: Point3, window: &mut Window, @@ -28,6 +30,7 @@ impl Ball { base_color: color, gfx: node, collider, + delta, }; // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); @@ -55,7 +58,7 @@ impl Ball { colliders, self.collider, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/objects/box_node.rs b/src_testbed/objects/box_node.rs index 493ffba..4235ef1 100644 --- a/src_testbed/objects/box_node.rs +++ b/src_testbed/objects/box_node.rs @@ -1,6 +1,6 @@ use crate::objects::node::{self, GraphicsNode}; use kiss3d::window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{ColliderHandle, ColliderSet}; use rapier::math::{Isometry, Vector}; @@ -9,11 +9,13 @@ pub struct Box { base_color: Point3, gfx: GraphicsNode, collider: ColliderHandle, + delta: Isometry3, } impl Box { pub fn new( collider: ColliderHandle, + delta: Isometry3, half_extents: Vector, color: Point3, window: &mut window::Window, @@ -29,6 +31,7 @@ impl Box { base_color: color, gfx: node, collider, + delta, }; res.gfx.set_color(color.x, color.y, color.z); @@ -55,7 +58,7 @@ impl Box { colliders, self.collider, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/objects/capsule.rs b/src_testbed/objects/capsule.rs index 23160be..197d1e8 100644 --- a/src_testbed/objects/capsule.rs +++ b/src_testbed/objects/capsule.rs @@ -1,6 +1,6 @@ use crate::objects::node::{self, GraphicsNode}; use kiss3d::window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{self, ColliderHandle, ColliderSet}; use rapier::math::Isometry; @@ -9,11 +9,13 @@ pub struct Capsule { base_color: Point3, gfx: GraphicsNode, collider: ColliderHandle, + delta: Isometry3, } impl Capsule { pub fn new( collider: ColliderHandle, + delta: Isometry3, capsule: &geometry::Capsule, color: Point3, window: &mut window::Window, @@ -30,6 +32,7 @@ impl Capsule { base_color: color, gfx: node, collider, + delta, }; res.gfx.set_color(color.x, color.y, color.z); @@ -50,7 +53,7 @@ impl Capsule { colliders, self.collider, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/objects/cone.rs b/src_testbed/objects/cone.rs index 58b014f..89a6b47 100644 --- a/src_testbed/objects/cone.rs +++ b/src_testbed/objects/cone.rs @@ -1,6 +1,6 @@ use crate::objects::node::{self, GraphicsNode}; use kiss3d::window::Window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{ColliderHandle, ColliderSet}; use rapier::math::Isometry; @@ -9,11 +9,13 @@ pub struct Cone { base_color: Point3, gfx: GraphicsNode, collider: ColliderHandle, + delta: Isometry3, } impl Cone { pub fn new( collider: ColliderHandle, + delta: Isometry3, half_height: f32, radius: f32, color: Point3, @@ -29,6 +31,7 @@ impl Cone { base_color: color, gfx: node, collider, + delta, }; // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); @@ -56,7 +59,7 @@ impl Cone { colliders, self.collider, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/objects/convex.rs b/src_testbed/objects/convex.rs index 9f0983d..b0e0bbb 100644 --- a/src_testbed/objects/convex.rs +++ b/src_testbed/objects/convex.rs @@ -5,7 +5,7 @@ use crate::math::Vector; use crate::math::{Isometry, Point}; use crate::objects::node::{self, GraphicsNode}; use kiss3d::window::Window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{ColliderHandle, ColliderSet}; pub struct Convex { @@ -13,11 +13,13 @@ pub struct Convex { base_color: Point3, gfx: GraphicsNode, body: ColliderHandle, + delta: Isometry3, } impl Convex { pub fn new( body: ColliderHandle, + delta: Isometry3, vertices: Vec>, #[cfg(feature = "dim3")] indices: Vec>, color: Point3, @@ -39,6 +41,7 @@ impl Convex { base_color: color, gfx: node, body, + delta, }; // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); @@ -66,7 +69,7 @@ impl Convex { colliders, self.body, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/objects/cylinder.rs b/src_testbed/objects/cylinder.rs index 01a6737..a2ed102 100644 --- a/src_testbed/objects/cylinder.rs +++ b/src_testbed/objects/cylinder.rs @@ -1,6 +1,6 @@ use crate::objects::node::{self, GraphicsNode}; use kiss3d::window::Window; -use na::Point3; +use na::{Isometry3, Point3}; use rapier::geometry::{ColliderHandle, ColliderSet}; use rapier::math::Isometry; @@ -9,11 +9,13 @@ pub struct Cylinder { base_color: Point3, gfx: GraphicsNode, collider: ColliderHandle, + delta: Isometry3, } impl Cylinder { pub fn new( collider: ColliderHandle, + delta: Isometry3, half_height: f32, radius: f32, color: Point3, @@ -29,6 +31,7 @@ impl Cylinder { base_color: color, gfx: node, collider, + delta, }; // res.gfx.set_texture_from_file(&Path::new("media/kitten.png"), "kitten"); @@ -56,7 +59,7 @@ impl Cylinder { colliders, self.collider, &self.color, - &Isometry::identity(), + &self.delta, ); } diff --git a/src_testbed/testbed.rs b/src_testbed/testbed.rs index b1a529f..10b3a0a 100644 --- a/src_testbed/testbed.rs +++ b/src_testbed/testbed.rs @@ -17,7 +17,7 @@ use kiss3d::planar_camera::PlanarCamera; use kiss3d::post_processing::PostProcessingEffect; use kiss3d::text::Font; use kiss3d::window::{State, Window}; -use na::{self, Point2, Point3, Vector3}; +use na::{self, Isometry3, Point2, Point3, Vector3}; use rapier::dynamics::{ ActivationStatus, IntegrationParameters, JointSet, RigidBodyHandle, RigidBodySet, }; @@ -1525,9 +1525,13 @@ fn draw_contacts(window: &mut Window, nf: &NarrowPhase, colliders: &ColliderSet) }; let pos1 = colliders[pair.pair.collider1].position(); let pos2 = colliders[pair.pair.collider2].position(); - let start = pos1 * pt.local_p1; - let end = pos2 * pt.local_p2; - let n = pos1 * manifold.local_n1; + let start = +