First working version of non-linear CCD based on single-substep motion-clamping.
This commit is contained in:
@@ -37,7 +37,7 @@ impl Box2dWorld {
|
||||
joints: &JointSet,
|
||||
) -> Self {
|
||||
let mut world = b2::World::new(&na_vec_to_b2_vec(gravity));
|
||||
world.set_continuous_physics(false);
|
||||
world.set_continuous_physics(bodies.iter().any(|b| b.1.is_ccd_enabled()));
|
||||
|
||||
let mut res = Box2dWorld {
|
||||
world,
|
||||
@@ -77,14 +77,11 @@ impl Box2dWorld {
|
||||
angular_velocity: body.angvel(),
|
||||
linear_damping,
|
||||
angular_damping,
|
||||
bullet: body.is_ccd_enabled(),
|
||||
..b2::BodyDef::new()
|
||||
};
|
||||
let b2_handle = self.world.create_body(&def);
|
||||
self.rapier2box2d.insert(handle, b2_handle);
|
||||
|
||||
// Collider.
|
||||
let mut b2_body = self.world.body_mut(b2_handle);
|
||||
b2_body.set_bullet(false /* collider.is_ccd_enabled() */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +160,7 @@ impl Box2dWorld {
|
||||
|
||||
fixture_def.restitution = collider.restitution;
|
||||
fixture_def.friction = collider.friction;
|
||||
fixture_def.density = collider.density();
|
||||
fixture_def.density = collider.density().unwrap_or(1.0);
|
||||
fixture_def.is_sensor = collider.is_sensor();
|
||||
fixture_def.filter = b2::Filter::new();
|
||||
|
||||
@@ -215,8 +212,6 @@ impl Box2dWorld {
|
||||
}
|
||||
|
||||
pub fn step(&mut self, counters: &mut Counters, params: &IntegrationParameters) {
|
||||
// self.world.set_continuous_physics(world.integration_parameters.max_ccd_substeps != 0);
|
||||
|
||||
counters.step_started();
|
||||
self.world.step(
|
||||
params.dt,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
use kiss3d::window::Window;
|
||||
use plugin::HarnessPlugin;
|
||||
use rapier::dynamics::{IntegrationParameters, JointSet, RigidBodySet};
|
||||
use rapier::dynamics::{CCDSolver, IntegrationParameters, JointSet, RigidBodySet};
|
||||
use rapier::geometry::{BroadPhase, ColliderSet, NarrowPhase};
|
||||
use rapier::math::Vector;
|
||||
use rapier::pipeline::{ChannelEventCollector, PhysicsHooks, PhysicsPipeline, QueryPipeline};
|
||||
@@ -133,6 +133,7 @@ impl Harness {
|
||||
self.physics.broad_phase = BroadPhase::new();
|
||||
self.physics.narrow_phase = NarrowPhase::new();
|
||||
self.state.timestep_id = 0;
|
||||
self.physics.ccd_solver = CCDSolver::new();
|
||||
self.physics.query_pipeline = QueryPipeline::new();
|
||||
self.physics.pipeline = PhysicsPipeline::new();
|
||||
self.physics.pipeline.counters.enable();
|
||||
@@ -194,13 +195,14 @@ impl Harness {
|
||||
&mut self.physics.bodies,
|
||||
&mut self.physics.colliders,
|
||||
&mut self.physics.joints,
|
||||
Some(&mut self.physics.ccd_solver),
|
||||
&*self.physics.hooks,
|
||||
&self.event_handler,
|
||||
);
|
||||
|
||||
self.physics
|
||||
.query_pipeline
|
||||
.update(&self.physics.bodies, &self.physics.colliders);
|
||||
.update(&self.physics.bodies, &self.physics.colliders, false);
|
||||
|
||||
for plugin in &mut self.plugins {
|
||||
plugin.step(&mut self.physics, &self.state)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crossbeam::channel::Receiver;
|
||||
use rapier::dynamics::{IntegrationParameters, JointSet, RigidBodySet};
|
||||
use rapier::dynamics::{CCDSolver, IntegrationParameters, JointSet, RigidBodySet};
|
||||
use rapier::geometry::{BroadPhase, ColliderSet, ContactEvent, IntersectionEvent, NarrowPhase};
|
||||
use rapier::math::Vector;
|
||||
use rapier::pipeline::{PhysicsHooks, PhysicsPipeline, QueryPipeline};
|
||||
@@ -73,6 +73,7 @@ pub struct PhysicsState {
|
||||
pub bodies: RigidBodySet,
|
||||
pub colliders: ColliderSet,
|
||||
pub joints: JointSet,
|
||||
pub ccd_solver: CCDSolver,
|
||||
pub pipeline: PhysicsPipeline,
|
||||
pub query_pipeline: QueryPipeline,
|
||||
pub integration_parameters: IntegrationParameters,
|
||||
@@ -88,6 +89,7 @@ impl PhysicsState {
|
||||
bodies: RigidBodySet::new(),
|
||||
colliders: ColliderSet::new(),
|
||||
joints: JointSet::new(),
|
||||
ccd_solver: CCDSolver::new(),
|
||||
pipeline: PhysicsPipeline::new(),
|
||||
query_pipeline: QueryPipeline::new(),
|
||||
integration_parameters: IntegrationParameters::default(),
|
||||
|
||||
@@ -13,8 +13,8 @@ use physx::prelude::*;
|
||||
use physx::scene::FrictionType;
|
||||
use physx::traits::Class;
|
||||
use physx_sys::{
|
||||
PxBitAndByte, PxConvexFlags, PxConvexMeshGeometryFlags, PxHeightFieldSample,
|
||||
PxMeshGeometryFlags, PxMeshScale_new, PxRigidActor,
|
||||
FilterShaderCallbackInfo, PxBitAndByte, PxConvexFlags, PxConvexMeshGeometryFlags,
|
||||
PxHeightFieldSample, PxMeshGeometryFlags, PxMeshScale_new, PxRigidActor,
|
||||
};
|
||||
use rapier::counters::Counters;
|
||||
use rapier::dynamics::{
|
||||
@@ -160,7 +160,7 @@ impl PhysxWorld {
|
||||
FrictionType::Patch
|
||||
};
|
||||
|
||||
let scene_desc = SceneDescriptor {
|
||||
let mut scene_desc = SceneDescriptor {
|
||||
gravity: gravity.into_physx(),
|
||||
thread_count: num_threads as u32,
|
||||
broad_phase_type: BroadPhaseType::AutomaticBoxPruning,
|
||||
@@ -169,6 +169,14 @@ impl PhysxWorld {
|
||||
..SceneDescriptor::new(())
|
||||
};
|
||||
|
||||
let ccd_enabled = bodies.iter().any(|(_, rb)| rb.is_ccd_enabled());
|
||||
|
||||
if ccd_enabled {
|
||||
scene_desc.simulation_filter_shader =
|
||||
FilterShaderDescriptor::CallDefaultFirst(ccd_filter_shader);
|
||||
scene_desc.flags.insert(SceneFlag::EnableCcd);
|
||||
}
|
||||
|
||||
let mut scene: Owner<PxScene> = physics.create(scene_desc).unwrap();
|
||||
let mut rapier2dynamic = HashMap::new();
|
||||
let mut rapier2static = HashMap::new();
|
||||
@@ -231,7 +239,7 @@ impl PhysxWorld {
|
||||
}
|
||||
}
|
||||
|
||||
// Update mass properties.
|
||||
// Update mass properties and CCD flags.
|
||||
for (rapier_handle, actor) in rapier2dynamic.iter_mut() {
|
||||
let rb = &bodies[*rapier_handle];
|
||||
let densities: Vec<_> = rb
|
||||
@@ -248,6 +256,23 @@ impl PhysxWorld {
|
||||
std::ptr::null(),
|
||||
false,
|
||||
);
|
||||
|
||||
if rb.is_ccd_enabled() {
|
||||
physx_sys::PxRigidBody_setRigidBodyFlag_mut(
|
||||
std::mem::transmute(actor.as_mut()),
|
||||
RigidBodyFlag::EnableCCD as u32,
|
||||
true,
|
||||
);
|
||||
// physx_sys::PxRigidBody_setMinCCDAdvanceCoefficient_mut(
|
||||
// std::mem::transmute(actor.as_mut()),
|
||||
// 0.0,
|
||||
// );
|
||||
// physx_sys::PxRigidBody_setRigidBodyFlag_mut(
|
||||
// std::mem::transmute(actor.as_mut()),
|
||||
// RigidBodyFlag::EnableCCDFriction as u32,
|
||||
// true,
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,3 +724,8 @@ impl AdvanceCallback<PxArticulationLink, PxRigidDynamic> for OnAdvance {
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ccd_filter_shader(data: *mut FilterShaderCallbackInfo) -> u16 {
|
||||
(*(*data).pairFlags).mBits |= physx_sys::PxPairFlag::eDETECT_CCD_CONTACT as u16;
|
||||
0
|
||||
}
|
||||
|
||||
@@ -769,11 +769,38 @@ impl Testbed {
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
fn handle_special_event(&mut self, window: &mut Window, _event: Event) {
|
||||
fn handle_special_event(&mut self, window: &mut Window, event: Event) {
|
||||
use rapier::dynamics::RigidBodyBuilder;
|
||||
use rapier::geometry::ColliderBuilder;
|
||||
|
||||
if window.is_conrod_ui_capturing_mouse() {
|
||||
return;
|
||||
}
|
||||
|
||||
match event.value {
|
||||
WindowEvent::Key(Key::Space, Action::Release, _) => {
|
||||
let cam_pos = self.graphics.camera().view_transform().inverse();
|
||||
let forward = cam_pos * -Vector::z();
|
||||
let vel = forward * 1000.0;
|
||||
|
||||
let bodies = &mut self.harness.physics.bodies;
|
||||
let colliders = &mut self.harness.physics.colliders;
|
||||
|
||||
let collider = ColliderBuilder::cuboid(4.0, 2.0, 0.4).density(20.0).build();
|
||||
// let collider = ColliderBuilder::ball(2.0).density(1.0).build();
|
||||
let body = RigidBodyBuilder::new_dynamic()
|
||||
.position(cam_pos)
|
||||
.linvel(vel.x, vel.y, vel.z)
|
||||
.ccd_enabled(true)
|
||||
.build();
|
||||
|
||||
let body_handle = bodies.insert(body);
|
||||
colliders.insert(collider, body_handle, bodies);
|
||||
self.graphics.add(window, body_handle, bodies, colliders);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
/*
|
||||
match event.value {
|
||||
WindowEvent::MouseButton(MouseButton::Button1, Action::Press, modifier) => {
|
||||
@@ -1454,6 +1481,20 @@ 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 contact in &manifold.data.solver_contacts {
|
||||
let color = if contact.dist > 0.0 {
|
||||
Point3::new(0.0, 0.0, 1.0)
|
||||
} else {
|
||||
Point3::new(1.0, 0.0, 0.0)
|
||||
};
|
||||
|
||||
let p = contact.point;
|
||||
let n = manifold.data.normal;
|
||||
|
||||
use crate::engine::GraphicsWindow;
|
||||
window.draw_graphics_line(&p, &(p + n * 0.4), &Point3::new(0.5, 1.0, 0.5));
|
||||
}
|
||||
/*
|
||||
for pt in manifold.contacts() {
|
||||
let color = if pt.dist > 0.0 {
|
||||
Point3::new(0.0, 0.0, 1.0)
|
||||
@@ -1474,6 +1515,7 @@ fn draw_contacts(window: &mut Window, nf: &NarrowPhase, colliders: &ColliderSet)
|
||||
window.draw_graphics_line(&start, &(start + n * 0.4), &Point3::new(0.5, 1.0, 0.5));
|
||||
window.draw_graphics_line(&start, &end, &color);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user