specs-physics

[Fork] Integration of Amethyst, SPECS and Nphysics together.
git clone https://git.jojolepro.com/specs-physics.git
Log | Files | Refs | README | LICENSE

commit e4cf436ee5f4b4b0fd85a8ee37ffaa2f330d972f
parent 3de1eca78baa0d9f3434c482aa75b5055af5a5b9
Author: Joël Lupien <jojolepromain@gmail.com>
Date:   Fri, 22 Feb 2019 01:59:35 -0500

Collision Performance Fix & nphysics update. (#20)

* Progres on updating nphysics.

* Progres updating nphysics.

* Fixed compilation issues from nphysics upgrade.

* Fixed optimisation issue with collision callback.

* Fixed collision handlers.

* Fix collision event issue (partially)

Diffstat:
MCargo.toml | 12+++++-------
Mexamples/amethyst.rs | 62+++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/colliders.rs | 12++++++++----
Msrc/systems/mod.rs | 2+-
Msrc/systems/physics_stepper.rs | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/systems/sync_bodies_from_physics.rs | 64+++++-----------------------------------------------------------
Msrc/systems/sync_bodies_to_physics.rs | 50+++++++++++++++++++++++++++++++++++++++-----------
Msrc/systems/sync_colliders_to_physics.rs | 92++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
8 files changed, 250 insertions(+), 139 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -8,16 +8,14 @@ edition = "2018" # default = [ "nphysics3d" ] [dependencies] -nphysics3d = { git = "https://github.com/jojolepro/nphysics", branch = "tmp", features = ["serde"] } -ncollide3d = { git = "https://github.com/jojolepro/ncollide", branch = "collidegroup" } -nalgebra = "0.16" num-traits = "0.2" derive-new = "0.5.6" derive_builder = "0.7.0" serde = { version = "1.0", features = ["derive"] } log = "*" +amethyst = { git = "https://github.com/amethyst/amethyst", branch = "master", features = ["nightly"] } -[dependencies.amethyst] -git = "https://github.com/amethyst/amethyst" -branch = "master" -features = ["nightly"] +#sertmp = ser branch + ncollide3d override to changes branch +nphysics3d = { git = "https://github.com/jojolepro/nphysics", branch = "sertmp", features = ["serde"] } +ncollide3d = { git = "https://github.com/jojolepro/ncollide", branch = "changes" } +nalgebra = "0.17" diff --git a/examples/amethyst.rs b/examples/amethyst.rs @@ -1,24 +1,30 @@ use amethyst::assets::{Handle, Loader}; use amethyst::core::nalgebra::{Matrix3, Vector3}; +use amethyst::core::shrev::{EventChannel, ReaderId}; use amethyst::core::specs::world::Builder; use amethyst::core::specs::Join; use amethyst::core::{GlobalTransform, Transform, TransformBundle}; +use amethyst::input::{is_close_requested, is_key_down}; use amethyst::renderer::{ AmbientColor, Camera, DisplayConfig, DrawShaded, Light, Material, MaterialDefaults, MeshData, MeshHandle, Pipeline, PointLight, PosNormTex, RenderBundle, Rgba, ScreenDimensions, Shape, Stage, Texture, VirtualKeyCode, }; -use amethyst::input::{is_close_requested, is_key_down}; -use amethyst::{Application, GameData, GameDataBuilder, SimpleState, StateData, StateEvent, SimpleTrans, Trans}; +use amethyst::{ + Application, GameData, GameDataBuilder, SimpleState, SimpleTrans, StateData, StateEvent, Trans, +}; use nphysics_ecs_dumb::ncollide::shape::{Ball, ShapeHandle}; +use nphysics_ecs_dumb::nphysics::material::BasicMaterial as PhysicsMaterial; use nphysics_ecs_dumb::nphysics::math::Velocity; -use nphysics_ecs_dumb::nphysics::object::Material as PhysicsMaterial; use nphysics_ecs_dumb::nphysics::volumetric::Volumetric; use nphysics_ecs_dumb::*; use num_traits::identities::One; use std::time::Duration; -struct GameState; +#[derive(Default)] +struct GameState { + pub collision_reader: Option<ReaderId<EntityContactEvent>>, +} impl SimpleState for GameState { fn on_start(&mut self, data: StateData<GameData>) { @@ -49,6 +55,12 @@ impl SimpleState for GameState { let camera_transform = Transform::from(Vector3::new(0.0, 5.0, 5.0)); + self.collision_reader = Some( + data.world + .write_resource::<EventChannel<EntityContactEvent>>() + .register_reader(), + ); + // Add Camera data.world .create_entity() @@ -93,7 +105,6 @@ impl SimpleState for GameState { )) .with( ColliderBuilder::from(ball.clone()) - .collision_group(0) .physics_material(PhysicsMaterial::default()) .build() .unwrap(), @@ -110,7 +121,6 @@ impl SimpleState for GameState { .with( //ColliderBuilder::from(ShapeHandle::new(Cuboid::new(Vector3::new(5.0, 1.0, 5.0)))) ColliderBuilder::from(ball) - .collision_group(0) .physics_material(PhysicsMaterial::default()) .build() .unwrap(), @@ -157,34 +167,51 @@ impl SimpleState for GameState { event: StateEvent, ) -> SimpleTrans { if let StateEvent::Window(event) = &event { + for _ in data + .world + .read_resource::<EventChannel<EntityContactEvent>>() + .read(self.collision_reader.as_mut().unwrap()) + { + println!("Collision Event Detected."); + } + // Exit if user hits Escape or closes the window if is_close_requested(&event) || is_key_down(&event, VirtualKeyCode::Escape) { return Trans::Quit; } - // + // if is_key_down(&event, VirtualKeyCode::T) { - *data.world.write_resource::<TimeStep>() = TimeStep::Fixed(1./120.); + *data.world.write_resource::<TimeStep>() = TimeStep::Fixed(1. / 120.); println!("Setting timestep to 1./120."); } if is_key_down(&event, VirtualKeyCode::Y) { - *data.world.write_resource::<TimeStep>() = TimeStep::Fixed(1./60.); + *data.world.write_resource::<TimeStep>() = TimeStep::Fixed(1. / 60.); println!("Setting timestep to 1./60."); } if is_key_down(&event, VirtualKeyCode::S) { - *data.world.write_resource::<TimeStep>() = TimeStep::SemiFixed(TimeStepConstraint::new( - vec![1. / 240., 1. / 120., 1. / 60.], - 0.4, - Duration::from_millis(50), - Duration::from_millis(500), - )) + *data.world.write_resource::<TimeStep>() = + TimeStep::SemiFixed(TimeStepConstraint::new( + vec![1. / 240., 1. / 120., 1. / 60.], + 0.4, + Duration::from_millis(50), + Duration::from_millis(500), + )) } // Reset the example if is_key_down(&event, VirtualKeyCode::Space) { - *(&mut data.world.write_storage::<Transform>(), &data.world.read_storage::<DynamicBody>()).join().next().unwrap().0.translation_mut() = Vector3::new(0.0, 15.0, -10.0); + *( + &mut data.world.write_storage::<Transform>(), + &data.world.read_storage::<DynamicBody>(), + ) + .join() + .next() + .unwrap() + .0 + .translation_mut() = Vector3::new(0.0, 15.0, -10.0); } } Trans::None @@ -210,6 +237,7 @@ fn main() -> amethyst::Result<()> { multitouch: true, resizable: true, transparent: false, + loaded_icon: None, }; let pipe = Pipeline::build().with_stage( Stage::with_backbuffer() @@ -226,7 +254,7 @@ fn main() -> amethyst::Result<()> { )? .with_bundle(RenderBundle::new(pipe, Some(display_config)))?; - let application = Application::new("./", GameState, game_data); + let application = Application::new("./", GameState::default(), game_data); assert_eq!(application.is_ok(), true); diff --git a/src/colliders.rs b/src/colliders.rs @@ -1,7 +1,9 @@ use amethyst::ecs::{Component, DenseVecStorage, FlaggedStorage}; use nalgebra::Isometry3; use ncollide::{shape::ShapeHandle, world::GeometricQueryType}; -use nphysics::object::{ColliderHandle, Material}; +use ncollide3d::world::CollisionGroups; +use nphysics::material::BasicMaterial; +use nphysics::object::ColliderHandle; #[derive(Clone, Serialize, Deserialize, Debug, new)] pub enum ColliderType { @@ -31,7 +33,7 @@ impl ColliderType { } } -#[derive(new, Clone, Builder, Debug)] +#[derive(new, Clone, Builder)] #[builder(pattern = "owned")] pub struct Collider { #[new(default)] @@ -42,8 +44,8 @@ pub struct Collider { pub margin: f32, pub shape: ShapeHandle<f32>, pub offset_from_parent: Isometry3<f32>, - pub physics_material: Material<f32>, - pub collision_group: u32, + pub physics_material: BasicMaterial<f32>, + pub collision_group: CollisionGroups, pub query_type: ColliderType, } @@ -54,6 +56,8 @@ impl From<ShapeHandle<f32>> for ColliderBuilder { .shape(shape) .offset_from_parent(Isometry3::identity()) .query_type(ColliderType::default()) + .physics_material(BasicMaterial::default()) + .collision_group(CollisionGroups::default()) } } diff --git a/src/systems/mod.rs b/src/systems/mod.rs @@ -9,7 +9,7 @@ use amethyst::core::specs::DispatcherBuilder; use amethyst::error::Error; use core::result::Result; -pub use self::physics_stepper::PhysicsStepperSystem; +pub use self::physics_stepper::*; pub use self::sync_bodies_from_physics::*; pub use self::sync_bodies_to_physics::SyncBodiesToPhysicsSystem; pub use self::sync_colliders_to_physics::SyncCollidersToPhysicsSystem; diff --git a/src/systems/physics_stepper.rs b/src/systems/physics_stepper.rs @@ -1,10 +1,17 @@ use crate::time_step::TimeStep; use crate::PhysicsWorld; use amethyst::core::Time; -use amethyst::ecs::{Read, System, WriteExpect, Write}; +use amethyst::ecs::{Entity, Read, System, Write, WriteExpect}; +use amethyst::shrev::EventChannel; +use ncollide3d::events::{ContactEvent, ProximityEvent}; use std::f32::EPSILON; use std::time::Instant; +// TODO: why is this here +// Might want to replace by better types. +pub type EntityContactEvent = (Entity, Entity, ContactEvent); +pub type EntityProximityEvent = (Entity, Entity, ProximityEvent); + /// Falloff factor for calculating the moving average step time. const AVERAGE_STEP_TIME_FALLOFF: f32 = 0.33; /// Factor to apply to available physics time before decreasing the timestep. Makes sure that the @@ -39,10 +46,24 @@ impl PhysicsStepperSystem { } impl<'a> System<'a> for PhysicsStepperSystem { - type SystemData = (WriteExpect<'a, PhysicsWorld>, Read<'a, Time>, Write<'a, TimeStep>); + type SystemData = ( + WriteExpect<'a, PhysicsWorld>, + Read<'a, Time>, + Write<'a, TimeStep>, + Write<'a, EventChannel<EntityContactEvent>>, + Write<'a, EventChannel<EntityProximityEvent>>, + ); // Simulate world using the current time frame - fn run(&mut self, (mut physical_world, time, mut intended_timestep): Self::SystemData) { + fn run(&mut self, data: Self::SystemData) { + let ( + mut physical_world, + time, + mut intended_timestep, + mut contact_events, + mut proximity_events, + ) = data; + let (timestep, mut change_timestep) = match &mut *intended_timestep { TimeStep::Fixed(timestep) => (*timestep, false), TimeStep::SemiFixed(constraint) => { @@ -108,9 +129,75 @@ impl<'a> System<'a> for PhysicsStepperSystem { while steps <= self.timestep_iter_limit && self.time_accumulator >= timestep { let physics_time = Instant::now(); - trace!("Stepping physics system. Step: {}, Timestep: {}, Time accumulator: {}", steps, timestep, self.time_accumulator); + trace!( + "Stepping physics system. Step: {}, Timestep: {}, Time accumulator: {}", + steps, + timestep, + self.time_accumulator + ); + physical_world.step(); + trace!("iterating collision events."); + + let collision_world = physical_world.collider_world(); + + let contact_ev = collision_world.contact_events().iter().cloned().flat_map(|ev| { + trace!("Emitting contact event: {:?}", ev); + + let (handle1, handle2) = match ev { + ContactEvent::Started(h1, h2) => (h1, h2), + ContactEvent::Stopped(h1, h2) => (h1, h2), + }; + let coll1 = physical_world.collider(handle1); + let coll2 = physical_world.collider(handle2); + if let (Some(c1), Some(c2)) = (coll1, coll2) { + // TODO: Check if the data is in fact the one we want. There might be + // user-inserted one. + let e1 = c1.user_data().map(|data| data.downcast_ref::<Entity>().unwrap()); + let e2 = c2.user_data().map(|data| data.downcast_ref::<Entity>().unwrap()); + if let (Some(e1), Some(e2)) = (e1, e2) { + Some((*e1, *e2, ev)) + } else { + error!("Failed to find entity for collider during proximity event iteration. Was the entity removed?"); + None + } + } else { + error!("Failed to fetch the rigid body from the physical world using the collider handle of the collision event. Was the entity removed?."); + None + } + }).collect::<Vec<_>>(); + + contact_events.iter_write(contact_ev.into_iter()); + + let proximity_ev = collision_world + .proximity_events() + .iter() + .cloned() + .flat_map(|ev| { + trace!("Emitting proximity event: {:?}", ev); + println!("hello there"); + let coll1 = physical_world.collider(ev.collider1); + let coll2 = physical_world.collider(ev.collider2); + if let (Some(c1), Some(c2)) = (coll1, coll2) { + // TODO: Check if the data is in fact the one we want. There might be + // user-inserted one. + let e1 = c1.user_data().map(|data| data.downcast_ref::<Entity>().unwrap()); + let e2 = c2.user_data().map(|data| data.downcast_ref::<Entity>().unwrap()); + if let (Some(e1), Some(e2)) = (e1, e2) { + Some((*e1, *e2, ev)) + } else { + error!("Failed to find entity for collider during proximity event iteration. Was the entity removed?"); + None + } + } else { + error!("Failed to fetch the rigid body from the physical world using the collider handle of the collision event. Was the entity removed?."); + None + } + }).collect::<Vec<_>>(); + + proximity_events.iter_write(proximity_ev.into_iter()); + let physics_time = physics_time.elapsed(); let physics_time = physics_time.as_secs() as f32 + physics_time.subsec_nanos() as f32 * 1e-9; diff --git a/src/systems/sync_bodies_from_physics.rs b/src/systems/sync_bodies_from_physics.rs @@ -3,15 +3,9 @@ use crate::colliders::Collider; use crate::PhysicsWorld; use amethyst::core::{GlobalTransform, Transform}; use amethyst::ecs::world::EntitiesRes; -use amethyst::ecs::{Entities, Entity, Join, ReadExpect, ReadStorage, System, Write, WriteStorage}; -use amethyst::shrev::EventChannel; +use amethyst::ecs::{Entities, Entity, Join, ReadExpect, ReadStorage, System, WriteStorage}; use nalgebra::Vector3; -use ncollide3d::events::{ContactEvent, ProximityEvent}; -use nphysics3d::object::ColliderHandle; - -// Might want to replace by better types. -pub type EntityContactEvent = (Entity, Entity, ContactEvent); -pub type EntityProximityEvent = (Entity, Entity, ProximityEvent); +use nphysics3d::object::{Body, BodyPart, ColliderHandle}; #[derive(Default)] pub struct SyncBodiesFromPhysicsSystem; @@ -26,24 +20,18 @@ impl<'a> System<'a> for SyncBodiesFromPhysicsSystem { type SystemData = ( Entities<'a>, ReadExpect<'a, PhysicsWorld>, - Write<'a, EventChannel<EntityContactEvent>>, - Write<'a, EventChannel<EntityProximityEvent>>, WriteStorage<'a, GlobalTransform>, WriteStorage<'a, DynamicBody>, WriteStorage<'a, Transform>, - ReadStorage<'a, Collider>, ); fn run(&mut self, data: Self::SystemData) { let ( - entities, + _entities, physical_world, - mut contact_events, - mut proximity_events, mut global_transforms, mut physics_bodies, mut local_transforms, - colliders, ) = data; trace!("Synchronizing bodies from physical world."); @@ -88,7 +76,7 @@ impl<'a> System<'a> for SyncBodiesFromPhysicsSystem { ); if let Some(ref mut local_transform) = local_transform { - *local_transform.isometry_mut() = updated_body.position(); + *local_transform.isometry_mut() = *updated_body.position(); } trace!( @@ -117,52 +105,10 @@ impl<'a> System<'a> for SyncBodiesFromPhysicsSystem { error!("Found body without handle!"); } } - - trace!("Iterating collision events."); - - let collision_world = physical_world.collision_world(); - - let contact_ev = collision_world.contact_events().iter().cloned().flat_map(|ev| { - trace!("Emitting contact event: {:?}", ev); - - let (handle1, handle2) = match ev { - ContactEvent::Started(h1, h2) => (h1, h2), - ContactEvent::Stopped(h1, h2) => (h1, h2), - }; - - let e1 = entity_from_handle(&entities, &colliders, handle1); - let e2 = entity_from_handle(&entities, &colliders, handle2); - if let (Some(e1), Some(e2)) = (e1, e2) { - Some((e1, e2, ev)) - } else { - error!("Failed to find entity for collider during contact event iteration. Was the entity removed?"); - None - } - }).collect::<Vec<_>>(); - - contact_events.iter_write(contact_ev.into_iter()); - - let proximity_ev = collision_world - .proximity_events() - .iter() - .cloned() - .flat_map(|ev| { - trace!("Emitting proximity event: {:?}", ev); - - let e1 = entity_from_handle(&entities, &colliders, ev.collider1); - let e2 = entity_from_handle(&entities, &colliders, ev.collider2); - if let (Some(e1), Some(e2)) = (e1, e2) { - Some((e1, e2, ev)) - } else { - error!("Failed to find entity for collider during proximity event iteration. Was the entity removed?"); - None - } - }).collect::<Vec<_>>(); - - proximity_events.iter_write(proximity_ev.into_iter()); } } +// TODO: why is this here pub fn entity_from_handle( entities: &EntitiesRes, colliders: &ReadStorage<Collider>, diff --git a/src/systems/sync_bodies_to_physics.rs b/src/systems/sync_bodies_to_physics.rs @@ -8,7 +8,10 @@ use amethyst::ecs::{ }; use core::ops::Deref; use nalgebra::try_convert; -use nphysics3d::math::{Force, Inertia, Isometry}; +use nalgebra::Isometry3; +use nphysics3d::math::Isometry; + +use nphysics3d::object::{Body, RigidBodyDesc}; #[derive(Default)] pub struct SyncBodiesToPhysicsSystem { @@ -64,7 +67,7 @@ impl<'a> System<'a> for SyncBodiesToPhysicsSystem { // Update simulation world with the value of Components flagged as changed #[allow(unused_mut)] - for (_entity, transform, mut body, id) in ( + for (entity, transform, mut body, id) in ( &entities, &transforms, &mut physics_bodies, @@ -86,20 +89,42 @@ impl<'a> System<'a> for SyncBodiesToPhysicsSystem { } } - body.handle = Some(physical_world.add_rigid_body( + /*body.handle = Some(physical_world.add_rigid_body( try_convert(transform.0).unwrap(), Inertia::new(body.mass, body.angular_mass), body.center_of_mass, - )); + ));*/ + + let iso: Isometry3<f32> = try_convert(transform.0).unwrap(); + + body.handle = Some( + RigidBodyDesc::new() + .position(iso) + //.gravity_enabled(false) + .status(body.body_status) + //.name("my rigid body".to_owned()) + .velocity(body.velocity) + //.angular_inertia(3.0) + .mass(1.2) + //.local_inertia(Inertia::new(1.0, 3.0)) + .local_center_of_mass(body.center_of_mass) + //.sleep_threshold(None) + //.kinematic_translations(Vector2::new(true, false)) + //.kinematic_rotation(true) + .user_data(entity) + .build(&mut physical_world) + .handle(), + ); trace!("Inserted rigid body to world with values: {:?}", body); - let physical_body = physical_world.rigid_body_mut(body.handle.unwrap()).unwrap(); + //let physical_body = physical_world.rigid_body_mut(body.handle.unwrap()).unwrap(); + + //physical_body.set_velocity(body.velocity); - physical_body.set_velocity(body.velocity); - physical_body.apply_force(&body.external_forces); - body.external_forces = Force::<f32>::zero(); - physical_body.set_status(body.body_status); + // TODO + //physical_body.apply_force(&body.external_forces); + //body.external_forces = Force::<f32>::zero(); trace!("Velocity and external forces applied, external forces reset to zero, for body with handle: {:?}", body.handle); } else if modified_transforms.contains(id) || modified_physics_bodies.contains(id) { @@ -116,8 +141,11 @@ impl<'a> System<'a> for SyncBodiesToPhysicsSystem { physical_body.set_position(position); physical_body.set_velocity(body.velocity); - physical_body.apply_force(&body.external_forces); - body.external_forces = Force::<f32>::zero(); + + // TODO + //physical_body.apply_force(&body.external_forces); + //body.external_forces = Force::<f32>::zero(); + physical_body.set_status(body.body_status); } None => error!( diff --git a/src/systems/sync_colliders_to_physics.rs b/src/systems/sync_colliders_to_physics.rs @@ -8,7 +8,8 @@ use amethyst::ecs::{ SystemData, Tracked, WriteExpect, WriteStorage, }; use core::ops::Deref; -use nphysics::object::BodyHandle; +use nphysics::material::MaterialHandle; +use nphysics::object::{BodyHandle, BodyPartHandle, ColliderDesc}; #[derive(Default, new)] pub struct SyncCollidersToPhysicsSystem { @@ -61,7 +62,7 @@ impl<'a> System<'a> for SyncCollidersToPhysicsSystem { let parent = if let Some(rb) = rigid_bodies.get(entity) { trace!("Attaching inserted collider to rigid body: {:?}", entity); - rb.handle().expect( + rb.handle.expect( "You should normally have a body handle at this point. This is a bug.", ) } else { @@ -73,51 +74,64 @@ impl<'a> System<'a> for SyncCollidersToPhysicsSystem { collider.offset_from_parent }; - collider.handle = Some(physical_world.add_collider( - collider.margin, - collider.shape.clone(), - parent, - position, - collider.physics_material.clone(), - )); - - trace!("Inserted collider to world with values: {:?}", collider); + //trace!("Inserted collider to world with values: {:?}", collider); let prediction = physical_world.prediction(); - let angular_prediction = physical_world.angular_prediction(); - - let collision_world = physical_world.collision_world_mut(); + let angular_prediction = 0.09; + + let parent_part_handle = physical_world + .rigid_body(parent) + .map(|body| body.part_handle()) + .unwrap_or_else(BodyPartHandle::ground); + + collider.handle = Some( + ColliderDesc::new(collider.shape.clone()) + .user_data(entity) + .margin(collider.margin) + .position(position) + .material(MaterialHandle::new(collider.physics_material)) + .build_with_parent(parent_part_handle, &mut physical_world) + .unwrap() + .handle(), + ); + + let collision_world = physical_world.collider_world_mut(); + + collision_world.as_collider_world_mut().set_query_type( + collider.handle.unwrap(), + collider.query_type.to_geometric_query_type( + collider.margin, + prediction, + angular_prediction, + ), + ); let collider_object = collision_world - .collision_object_mut(collider.handle.unwrap()) + .collider_mut(collider.handle.unwrap()) .unwrap(); - collider_object.set_query_type(collider.query_type.to_geometric_query_type( - collider.margin, - prediction, - angular_prediction, - )); - let collider_handle = collider_object.handle(); - collision_world.set_collision_group(collider_handle, collider.collision_group); + collision_world.set_collision_groups(collider_handle, collider.collision_group); } else if modified_colliders.contains(id) || modified_colliders.contains(id) { trace!("Detected changed collider with id {:?}", id); let prediction = physical_world.prediction(); - let angular_prediction = physical_world.angular_prediction(); + let angular_prediction = 0.09; - let collision_world = physical_world.collision_world_mut(); + let collision_world = physical_world.collider_world_mut(); let collider_handle = collision_world - .collision_object(collider.handle.unwrap()) + .collider(collider.handle.unwrap()) .unwrap() .handle(); - collision_world.set_collision_group(collider_handle, collider.collision_group); - collision_world.set_shape(collider_handle, collider.shape.clone()); + collision_world.set_collision_groups(collider_handle, collider.collision_group); + collision_world + .as_collider_world_mut() + .set_shape(collider_handle, collider.shape.clone()); let collider_object = collision_world - .collision_object_mut(collider.handle.unwrap()) + .collider_mut(collider.handle.unwrap()) .unwrap(); let parent = if let Some(rb) = rigid_bodies.get(entity) { @@ -139,14 +153,20 @@ impl<'a> System<'a> for SyncCollidersToPhysicsSystem { }; collider_object.set_position(position); - collider_object.set_query_type(collider.query_type.to_geometric_query_type( - collider.margin, - prediction, - angular_prediction, - )); - collider_object - .data_mut() - .set_material(collider.physics_material.clone()); + + collision_world.as_collider_world_mut().set_query_type( + collider.handle.unwrap(), + collider.query_type.to_geometric_query_type( + collider.margin, + prediction, + angular_prediction, + ), + ); + + // TODO: Material changes & more complex mats than BasicMaterial + /*collider_object + .user_data_mut() + .set_material(collider.physics_material.clone());*/ } }