Add comments.
This commit is contained in:
@@ -25,6 +25,7 @@ mod debug_friction3;
|
||||
mod debug_infinite_fall3;
|
||||
mod debug_prismatic3;
|
||||
mod debug_rollback3;
|
||||
mod debug_shape_modification3;
|
||||
mod debug_triangle3;
|
||||
mod debug_trimesh3;
|
||||
mod domino3;
|
||||
@@ -112,6 +113,10 @@ pub fn main() {
|
||||
("(Debug) infinite fall", debug_infinite_fall3::init_world),
|
||||
("(Debug) prismatic", debug_prismatic3::init_world),
|
||||
("(Debug) rollback", debug_rollback3::init_world),
|
||||
(
|
||||
"(Debug) shape modification",
|
||||
debug_shape_modification3::init_world,
|
||||
),
|
||||
];
|
||||
|
||||
// Lexicographic sort, with stress tests moved at the end of the list.
|
||||
|
||||
123
examples3d/debug_shape_modification3.rs
Normal file
123
examples3d/debug_shape_modification3.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
use na::{Isometry3, Point3, Vector3};
|
||||
use rapier3d::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
|
||||
use rapier3d::geometry::{ColliderBuilder, ColliderSet, SharedShape};
|
||||
use rapier_testbed3d::Testbed;
|
||||
|
||||
pub fn init_world(testbed: &mut Testbed) {
|
||||
/*
|
||||
* World
|
||||
*/
|
||||
let mut bodies = RigidBodySet::new();
|
||||
let mut colliders = ColliderSet::new();
|
||||
let joints = JointSet::new();
|
||||
/*
|
||||
* Ground.
|
||||
*/
|
||||
let ground_size = 20.0;
|
||||
let ground_height = 0.1;
|
||||
|
||||
let rigid_body = RigidBodyBuilder::new_static()
|
||||
.translation(0.0, -ground_height, 0.0)
|
||||
.build();
|
||||
let ground_handle = bodies.insert(rigid_body);
|
||||
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size)
|
||||
.friction(0.15)
|
||||
// .restitution(0.5)
|
||||
.build();
|
||||
colliders.insert(collider, ground_handle, &mut bodies);
|
||||
|
||||
/*
|
||||
* Rolling ball
|
||||
*/
|
||||
let ball_rad = 0.1;
|
||||
let rb = RigidBodyBuilder::new_dynamic()
|
||||
.translation(0.0, 0.2, 0.0)
|
||||
.linvel(10.0, 0.0, 0.0)
|
||||
.build();
|
||||
let ball_handle = bodies.insert(rb);
|
||||
let collider = ColliderBuilder::ball(ball_rad).density(100.0).build();
|
||||
let ball_coll_handle = colliders.insert(collider, ball_handle, &mut bodies);
|
||||
|
||||
let mut linvel = Vector3::zeros();
|
||||
let mut angvel = Vector3::zeros();
|
||||
let mut pos = Isometry3::identity();
|
||||
let mut step = 0;
|
||||
let snapped_frame = 51;
|
||||
|
||||
testbed.add_callback(move |_, _, physics, _, _| {
|
||||
step += 1;
|
||||
|
||||
// Snap the ball velocity or restore it.
|
||||
let ball = physics.bodies.get_mut(ball_handle).unwrap();
|
||||
|
||||
if step == snapped_frame {
|
||||
linvel = *ball.linvel();
|
||||
angvel = *ball.angvel();
|
||||
pos = *ball.position();
|
||||
}
|
||||
|
||||
if step == 100 {
|
||||
ball.set_linvel(linvel, true);
|
||||
ball.set_angvel(angvel, true);
|
||||
ball.set_position(pos, true);
|
||||
step = snapped_frame;
|
||||
}
|
||||
|
||||
let ball_coll = physics.colliders.get_mut(ball_coll_handle).unwrap();
|
||||
ball_coll.set_shape(SharedShape::ball(ball_rad * step as f32 * 2.0));
|
||||
});
|
||||
|
||||
/*
|
||||
* Create the primitives
|
||||
*/
|
||||
let num = 8;
|
||||
let rad = 1.0;
|
||||
|
||||
let shiftx = rad * 2.0 + rad;
|
||||
let shifty = rad * 2.0 + rad;
|
||||
let shiftz = rad * 2.0 + rad;
|
||||
let centerx = shiftx * (num / 2) as f32;
|
||||
let centery = shifty / 2.0;
|
||||
let centerz = shiftz * (num / 2) as f32;
|
||||
|
||||
let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5;
|
||||
|
||||
for j in 0usize..20 {
|
||||
for i in 0..num {
|
||||
for k in 0usize..num {
|
||||
let x = i as f32 * shiftx - centerx + offset + 5.0;
|
||||
let y = j as f32 * shifty + centery + 3.0;
|
||||
let z = k as f32 * shiftz - centerz + offset;
|
||||
|
||||
// Build the rigid body.
|
||||
let rigid_body = RigidBodyBuilder::new_dynamic().translation(x, y, z).build();
|
||||
let handle = bodies.insert(rigid_body);
|
||||
|
||||
let collider = match j % 5 {
|
||||
0 => ColliderBuilder::cuboid(rad, rad, rad).build(),
|
||||
1 => ColliderBuilder::ball(rad).build(),
|
||||
// Rounded cylinders are much more efficient that cylinder, even if the
|
||||
// rounding margin is small.
|
||||
2 => ColliderBuilder::round_cylinder(rad, rad, rad / 10.0).build(),
|
||||
3 => ColliderBuilder::cone(rad, rad).build(),
|
||||
_ => ColliderBuilder::capsule_y(rad, rad).build(),
|
||||
};
|
||||
|
||||
colliders.insert(collider, handle, &mut bodies);
|
||||
}
|
||||
}
|
||||
|
||||
offset -= 0.05 * rad * (num as f32 - 1.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the testbed.
|
||||
*/
|
||||
testbed.set_world(bodies, colliders, joints);
|
||||
testbed.look_at(Point3::new(10.0, 10.0, 10.0), Point3::origin());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let testbed = Testbed::from_builders(0, vec![("Boxes", init_world)]);
|
||||
testbed.run()
|
||||
}
|
||||
@@ -25,7 +25,7 @@ pub fn init_world(testbed: &mut Testbed) {
|
||||
colliders.insert(collider, handle, &mut bodies);
|
||||
|
||||
/*
|
||||
* Create the cubes
|
||||
* Create the primitives
|
||||
*/
|
||||
let num = 8;
|
||||
let rad = 1.0;
|
||||
|
||||
@@ -770,13 +770,13 @@ impl<T> Arena<T> {
|
||||
/// other kinds of bit-efficient indexing.
|
||||
///
|
||||
/// You should use the `get` method instead most of the time.
|
||||
pub fn get_unknown_gen(&self, i: usize) -> Option<(&T, Index)> {
|
||||
match self.items.get(i) {
|
||||
pub fn get_unknown_gen(&self, i: u32) -> Option<(&T, Index)> {
|
||||
match self.items.get(i as usize) {
|
||||
Some(Entry::Occupied { generation, value }) => Some((
|
||||
value,
|
||||
Index {
|
||||
generation: *generation,
|
||||
index: i as u32,
|
||||
index: i,
|
||||
},
|
||||
)),
|
||||
_ => None,
|
||||
@@ -793,13 +793,13 @@ impl<T> Arena<T> {
|
||||
/// other kinds of bit-efficient indexing.
|
||||
///
|
||||
/// You should use the `get_mut` method instead most of the time.
|
||||
pub fn get_unknown_gen_mut(&mut self, i: usize) -> Option<(&mut T, Index)> {
|
||||
match self.items.get_mut(i) {
|
||||
pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut T, Index)> {
|
||||
match self.items.get_mut(i as usize) {
|
||||
Some(Entry::Occupied { generation, value }) => Some((
|
||||
value,
|
||||
Index {
|
||||
generation: *generation,
|
||||
index: i as u32,
|
||||
index: i,
|
||||
},
|
||||
)),
|
||||
_ => None,
|
||||
|
||||
@@ -5,30 +5,47 @@ use crate::data::Index;
|
||||
// fn get(&self, handle: Index) -> Option<&T>;
|
||||
// }
|
||||
|
||||
/// A set of optional elements of type `T`.
|
||||
pub trait ComponentSetOption<T>: Sync {
|
||||
/// Get the element associated to the given `handle`, if there is one.
|
||||
fn get(&self, handle: Index) -> Option<&T>;
|
||||
}
|
||||
|
||||
/// A set of elements of type `T`.
|
||||
pub trait ComponentSet<T>: ComponentSetOption<T> {
|
||||
/// The estimated number of elements in this set.
|
||||
///
|
||||
/// This value is typically used for preallocating some arrays for
|
||||
/// better performances.
|
||||
fn size_hint(&self) -> usize;
|
||||
// TODO ECS: remove this, its only needed by the query pipeline update
|
||||
// which should only take the modified colliders into account.
|
||||
/// Iterate through all the elements on this set.
|
||||
fn for_each(&self, f: impl FnMut(Index, &T));
|
||||
/// Get the element associated to the given `handle`.
|
||||
fn index(&self, handle: Index) -> &T {
|
||||
self.get(handle).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of mutable elements of type `T`.
|
||||
pub trait ComponentSetMut<T>: ComponentSet<T> {
|
||||
/// Applies the given closure to the element associated to the given `handle`.
|
||||
///
|
||||
/// Return `None` if the element doesn't exist.
|
||||
fn map_mut_internal<Result>(
|
||||
&mut self,
|
||||
handle: crate::data::Index,
|
||||
f: impl FnOnce(&mut T) -> Result,
|
||||
) -> Option<Result>;
|
||||
|
||||
/// Set the value of this element.
|
||||
fn set_internal(&mut self, handle: crate::data::Index, val: T);
|
||||
}
|
||||
|
||||
/// Helper trait to address multiple elements at once.
|
||||
pub trait BundleSet<'a, T> {
|
||||
/// Access multiple elements from this set.
|
||||
fn index_bundle(&'a self, handle: Index) -> T;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ use crate::dynamics::{
|
||||
use crate::geometry::{ColliderParent, InteractionGraph, NarrowPhase};
|
||||
use crate::math::Real;
|
||||
|
||||
/// Structure responsible for maintaining the set of active rigid-bodies, and
|
||||
/// putting non-moving rigid-bodies to sleep to save computation times.
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
pub struct IslandManager {
|
||||
pub(crate) active_dynamic_set: Vec<RigidBodyHandle>,
|
||||
@@ -19,6 +21,7 @@ pub struct IslandManager {
|
||||
}
|
||||
|
||||
impl IslandManager {
|
||||
/// Creates a new empty island manager.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
active_dynamic_set: vec![],
|
||||
@@ -34,6 +37,7 @@ impl IslandManager {
|
||||
self.active_islands.len() - 1
|
||||
}
|
||||
|
||||
/// Update this data-structure after one or multiple rigid-bodies have been removed for `bodies`.
|
||||
pub fn cleanup_removed_rigid_bodies(
|
||||
&mut self,
|
||||
bodies: &mut impl ComponentSetMut<RigidBodyIds>,
|
||||
@@ -59,7 +63,7 @@ impl IslandManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rigid_body_removed(
|
||||
pub(crate) fn rigid_body_removed(
|
||||
&mut self,
|
||||
removed_handle: RigidBodyHandle,
|
||||
removed_ids: &RigidBodyIds,
|
||||
|
||||
@@ -94,7 +94,7 @@ impl JointSet {
|
||||
///
|
||||
/// Using this is discouraged in favor of `self.get(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
pub fn get_unknown_gen(&self, i: usize) -> Option<(&Joint, JointHandle)> {
|
||||
pub fn get_unknown_gen(&self, i: u32) -> Option<(&Joint, JointHandle)> {
|
||||
let (id, handle) = self.joint_ids.get_unknown_gen(i)?;
|
||||
Some((
|
||||
self.joint_graph.graph.edge_weight(*id)?,
|
||||
@@ -111,7 +111,7 @@ impl JointSet {
|
||||
///
|
||||
/// Using this is discouraged in favor of `self.get_mut(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
pub fn get_unknown_gen_mut(&mut self, i: usize) -> Option<(&mut Joint, JointHandle)> {
|
||||
pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut Joint, JointHandle)> {
|
||||
let (id, handle) = self.joint_ids.get_unknown_gen(i)?;
|
||||
Some((
|
||||
self.joint_graph.graph.edge_weight_mut(*id)?,
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::geometry::{
|
||||
Collider, ColliderHandle, ColliderMassProperties, ColliderParent, ColliderPosition,
|
||||
ColliderShape,
|
||||
};
|
||||
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Translation, Vector};
|
||||
use crate::utils::{self, WAngularInertia, WCross};
|
||||
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector};
|
||||
use crate::utils::{self, WCross};
|
||||
use na::ComplexField;
|
||||
use num::Zero;
|
||||
|
||||
@@ -18,21 +18,21 @@ use num::Zero;
|
||||
/// To create a new rigid-body, use the `RigidBodyBuilder` structure.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RigidBody {
|
||||
pub rb_pos: RigidBodyPosition, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_mprops: RigidBodyMassProps, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_vels: RigidBodyVelocity, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_damping: RigidBodyDamping, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_forces: RigidBodyForces, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_ccd: RigidBodyCcd, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_ids: RigidBodyIds, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub rb_colliders: RigidBodyColliders, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub(crate) rb_pos: RigidBodyPosition,
|
||||
pub(crate) rb_mprops: RigidBodyMassProps,
|
||||
pub(crate) rb_vels: RigidBodyVelocity,
|
||||
pub(crate) rb_damping: RigidBodyDamping,
|
||||
pub(crate) rb_forces: RigidBodyForces,
|
||||
pub(crate) rb_ccd: RigidBodyCcd,
|
||||
pub(crate) rb_ids: RigidBodyIds,
|
||||
pub(crate) rb_colliders: RigidBodyColliders,
|
||||
/// Whether or not this rigid-body is sleeping.
|
||||
pub rb_activation: RigidBodyActivation, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub changes: RigidBodyChanges, // TODO ECS: public only for initial tests with bevy_rapier.
|
||||
pub(crate) rb_activation: RigidBodyActivation,
|
||||
pub(crate) changes: RigidBodyChanges,
|
||||
/// The status of the body, governing how it is affected by external forces.
|
||||
pub rb_type: RigidBodyType, // TODO ECS: public only for initial tests with bevy_rapier
|
||||
pub(crate) rb_type: RigidBodyType,
|
||||
/// The dominance group this rigid-body is part of.
|
||||
pub rb_dominance: RigidBodyDominance,
|
||||
pub(crate) rb_dominance: RigidBodyDominance,
|
||||
/// User-defined data associated to this rigid-body.
|
||||
pub user_data: u128,
|
||||
}
|
||||
@@ -61,61 +61,48 @@ impl RigidBody {
|
||||
self.rb_ids = Default::default();
|
||||
}
|
||||
|
||||
pub fn user_data(&self) -> u128 {
|
||||
self.user_data
|
||||
}
|
||||
|
||||
pub fn set_user_data(&mut self, data: u128) {
|
||||
self.user_data = data;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rb_activation(&self) -> &RigidBodyActivation {
|
||||
/// The activation status of this rigid-body.
|
||||
pub fn activation(&self) -> &RigidBodyActivation {
|
||||
&self.rb_activation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Mutable reference to the activation status of this rigid-body.
|
||||
pub fn activation_mut(&mut self) -> &mut RigidBodyActivation {
|
||||
self.changes |= RigidBodyChanges::SLEEP;
|
||||
&mut self.rb_activation
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn changes(&self) -> RigidBodyChanges {
|
||||
self.changes
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn changes_mut_internal(&mut self) -> &mut RigidBodyChanges {
|
||||
&mut self.changes
|
||||
}
|
||||
|
||||
/// The linear damping coefficient of this rigid-body.
|
||||
#[inline]
|
||||
pub fn linear_damping(&self) -> Real {
|
||||
self.rb_damping.linear_damping
|
||||
}
|
||||
|
||||
/// Sets the linear damping coefficient of this rigid-body.
|
||||
#[inline]
|
||||
pub fn set_linear_damping(&mut self, damping: Real) {
|
||||
self.rb_damping.linear_damping = damping;
|
||||
}
|
||||
|
||||
/// The angular damping coefficient of this rigid-body.
|
||||
#[inline]
|
||||
pub fn angular_damping(&self) -> Real {
|
||||
self.rb_damping.angular_damping
|
||||
}
|
||||
|
||||
/// Sets the angular damping coefficient of this rigid-body.
|
||||
#[inline]
|
||||
pub fn set_angular_damping(&mut self, damping: Real) {
|
||||
self.rb_damping.angular_damping = damping
|
||||
}
|
||||
|
||||
/// The status of this rigid-body.
|
||||
pub fn rb_type(&self) -> RigidBodyType {
|
||||
/// The type of this rigid-body.
|
||||
pub fn body_type(&self) -> RigidBodyType {
|
||||
self.rb_type
|
||||
}
|
||||
|
||||
/// Sets the status of this rigid-body.
|
||||
pub fn set_rb_type(&mut self, status: RigidBodyType) {
|
||||
/// Sets the type of this rigid-body.
|
||||
pub fn set_body_type(&mut self, status: RigidBodyType) {
|
||||
if status != self.rb_type {
|
||||
self.changes.insert(RigidBodyChanges::TYPE);
|
||||
self.rb_type = status;
|
||||
@@ -336,22 +323,6 @@ impl RigidBody {
|
||||
!self.rb_vels.linvel.is_zero() || !self.rb_vels.angvel.is_zero()
|
||||
}
|
||||
|
||||
/// Computes the predict position of this rigid-body after `dt` seconds, taking
|
||||
/// into account its velocities and external forces applied to it.
|
||||
pub fn predict_position_using_velocity_and_forces(&self, dt: Real) -> Isometry<Real> {
|
||||
let dlinvel = self.rb_forces.force * (self.rb_mprops.effective_inv_mass * dt);
|
||||
let dangvel = self
|
||||
.rb_mprops
|
||||
.effective_world_inv_inertia_sqrt
|
||||
.transform_vector(self.rb_forces.torque * dt);
|
||||
let linvel = self.rb_vels.linvel + dlinvel;
|
||||
let angvel = self.rb_vels.angvel + dangvel;
|
||||
|
||||
let com = self.rb_pos.position * self.rb_mprops.mass_properties.local_com;
|
||||
let shift = Translation::from(com.coords);
|
||||
shift * Isometry::new(linvel * dt, angvel * dt) * shift.inverse() * self.rb_pos.position
|
||||
}
|
||||
|
||||
/// The linear velocity of this rigid-body.
|
||||
pub fn linvel(&self) -> &Vector<Real> {
|
||||
&self.rb_vels.linvel
|
||||
@@ -567,30 +538,13 @@ impl RigidBody {
|
||||
impl RigidBody {
|
||||
/// The velocity of the given world-space point on this rigid-body.
|
||||
pub fn velocity_at_point(&self, point: &Point<Real>) -> Vector<Real> {
|
||||
let dpt = point - self.rb_mprops.world_com;
|
||||
self.rb_vels.linvel + self.rb_vels.angvel.gcross(dpt)
|
||||
self.rb_vels
|
||||
.velocity_at_point(point, &self.rb_mprops.world_com)
|
||||
}
|
||||
|
||||
/// The kinetic energy of this body.
|
||||
pub fn kinetic_energy(&self) -> Real {
|
||||
let mut energy = (self.mass() * self.rb_vels.linvel.norm_squared()) / 2.0;
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
if !self.rb_mprops.effective_world_inv_inertia_sqrt.is_zero() {
|
||||
let inertia_sqrt = 1.0 / self.rb_mprops.effective_world_inv_inertia_sqrt;
|
||||
energy += (inertia_sqrt * self.rb_vels.angvel).powi(2) / 2.0;
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
if !self.rb_mprops.effective_world_inv_inertia_sqrt.is_zero() {
|
||||
let inertia_sqrt = self
|
||||
.rb_mprops
|
||||
.effective_world_inv_inertia_sqrt
|
||||
.inverse_unchecked();
|
||||
energy += (inertia_sqrt * self.rb_vels.angvel).norm_squared() / 2.0;
|
||||
}
|
||||
|
||||
energy
|
||||
self.rb_vels.kinetic_energy(&self.rb_mprops)
|
||||
}
|
||||
|
||||
/// The potential energy of this body in a gravity field.
|
||||
@@ -894,39 +848,6 @@ impl RigidBodyBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn components(
|
||||
&self,
|
||||
) -> (
|
||||
RigidBodyPosition,
|
||||
RigidBodyMassProps,
|
||||
RigidBodyVelocity,
|
||||
RigidBodyDamping,
|
||||
RigidBodyForces,
|
||||
RigidBodyCcd,
|
||||
RigidBodyIds,
|
||||
RigidBodyColliders,
|
||||
RigidBodyActivation,
|
||||
RigidBodyChanges,
|
||||
RigidBodyType,
|
||||
RigidBodyDominance,
|
||||
) {
|
||||
let rb = self.build();
|
||||
(
|
||||
rb.rb_pos,
|
||||
rb.rb_mprops,
|
||||
rb.rb_vels,
|
||||
rb.rb_damping,
|
||||
rb.rb_forces,
|
||||
rb.rb_ccd,
|
||||
rb.rb_ids,
|
||||
rb.rb_colliders,
|
||||
rb.rb_activation,
|
||||
rb.changes,
|
||||
rb.rb_type,
|
||||
rb.rb_dominance,
|
||||
)
|
||||
}
|
||||
|
||||
/// Build a new rigid-body with the parameters configured with this builder.
|
||||
pub fn build(&self) -> RigidBody {
|
||||
let mut rb = RigidBody::new();
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::geometry::{
|
||||
};
|
||||
use crate::math::{AngVector, AngularInertia, Isometry, Point, Real, Translation, Vector};
|
||||
use crate::parry::partitioning::IndexedData;
|
||||
use crate::utils::WDot;
|
||||
use crate::utils::{WCross, WDot};
|
||||
use num::Zero;
|
||||
|
||||
/// The unique handle of a rigid body added to a `RigidBodySet`.
|
||||
@@ -69,14 +69,17 @@ pub enum RigidBodyType {
|
||||
}
|
||||
|
||||
impl RigidBodyType {
|
||||
/// Is this rigid-body static (i.e. cannot move)?
|
||||
pub fn is_static(self) -> bool {
|
||||
self == RigidBodyType::Static
|
||||
}
|
||||
|
||||
/// Is this rigid-body dynamic (i.e. can move and be affected by forces)?
|
||||
pub fn is_dynamic(self) -> bool {
|
||||
self == RigidBodyType::Dynamic
|
||||
}
|
||||
|
||||
/// Is this rigid-body kinematic (i.e. can move but is unaffected by forces)?
|
||||
pub fn is_kinematic(self) -> bool {
|
||||
self == RigidBodyType::Kinematic
|
||||
}
|
||||
@@ -86,10 +89,15 @@ bitflags::bitflags! {
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// Flags describing how the rigid-body has been modified by the user.
|
||||
pub struct RigidBodyChanges: u32 {
|
||||
/// Flag indicating that any component of this rigid-body has been modified.
|
||||
const MODIFIED = 1 << 0;
|
||||
/// Flag indicating that the `RigidBodyPosition` component of this rigid-body has been modified.
|
||||
const POSITION = 1 << 1;
|
||||
/// Flag indicating that the `RigidBodyActivation` component of this rigid-body has been modified.
|
||||
const SLEEP = 1 << 2;
|
||||
/// Flag indicating that the `RigidBodyColliders` component of this rigid-body has been modified.
|
||||
const COLLIDERS = 1 << 3;
|
||||
/// Flag indicating that the `RigidBodyType` component of this rigid-body has been modified.
|
||||
const TYPE = 1 << 4;
|
||||
}
|
||||
}
|
||||
@@ -102,6 +110,7 @@ impl Default for RigidBodyChanges {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// The position of this rigid-body.
|
||||
pub struct RigidBodyPosition {
|
||||
/// The world-space position of the rigid-body.
|
||||
pub position: Isometry<Real>,
|
||||
@@ -127,6 +136,8 @@ impl Default for RigidBodyPosition {
|
||||
}
|
||||
|
||||
impl RigidBodyPosition {
|
||||
/// Computes the velocity need to travel from `self.position` to `self.next_position` in
|
||||
/// a time equal to `1.0 / inv_dt`.
|
||||
#[must_use]
|
||||
pub fn interpolate_velocity(&self, inv_dt: Real) -> RigidBodyVelocity {
|
||||
let dpos = self.next_position * self.position.inverse();
|
||||
@@ -143,6 +154,9 @@ impl RigidBodyPosition {
|
||||
RigidBodyVelocity { linvel, angvel }
|
||||
}
|
||||
|
||||
/// Compute new positions after integrating the given forces and velocities.
|
||||
///
|
||||
/// This uses a symplectic Euler integration scheme.
|
||||
#[must_use]
|
||||
pub fn integrate_forces_and_velocities(
|
||||
&self,
|
||||
@@ -173,16 +187,23 @@ bitflags::bitflags! {
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// Flags affecting the behavior of the constraints solver for a given contact manifold.
|
||||
pub struct RigidBodyMassPropsFlags: u8 {
|
||||
/// Flag indicating that the rigid-body cannot translate along any direction.
|
||||
const TRANSLATION_LOCKED = 1 << 0;
|
||||
/// Flag indicating that the rigid-body cannot rotate along the `X` axis.
|
||||
const ROTATION_LOCKED_X = 1 << 1;
|
||||
/// Flag indicating that the rigid-body cannot rotate along the `X` axis.
|
||||
const ROTATION_LOCKED_Y = 1 << 2;
|
||||
/// Flag indicating that the rigid-body cannot rotate along the `X` axis.
|
||||
const ROTATION_LOCKED_Z = 1 << 3;
|
||||
/// Combination of flags indicating that the rigid-body cannot rotate along any axis.
|
||||
const ROTATION_LOCKED = Self::ROTATION_LOCKED_X.bits | Self::ROTATION_LOCKED_Y.bits | Self::ROTATION_LOCKED_Z.bits;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: split this into "LocalMassProps" and `WorldMassProps"?
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// The mass properties of this rigid-bodies.
|
||||
pub struct RigidBodyMassProps {
|
||||
/// Flags for locking rotation and translation.
|
||||
pub flags: RigidBodyMassPropsFlags,
|
||||
@@ -219,16 +240,20 @@ impl From<RigidBodyMassPropsFlags> for RigidBodyMassProps {
|
||||
}
|
||||
|
||||
impl RigidBodyMassProps {
|
||||
/// The mass of the rigid-body.
|
||||
#[must_use]
|
||||
pub fn with_translations_locked(mut self) -> Self {
|
||||
self.flags |= RigidBodyMassPropsFlags::TRANSLATION_LOCKED;
|
||||
self
|
||||
pub fn mass(&self) -> Real {
|
||||
crate::utils::inv(self.mass_properties.inv_mass)
|
||||
}
|
||||
|
||||
/// The effective mass (that takes the potential translation locking into account) of
|
||||
/// this rigid-body.
|
||||
#[must_use]
|
||||
pub fn effective_mass(&self) -> Real {
|
||||
crate::utils::inv(self.effective_inv_mass)
|
||||
}
|
||||
|
||||
/// Update the world-space mass properties of `self`, taking into account the new position.
|
||||
pub fn update_world_mass_properties(&mut self, position: &Isometry<Real>) {
|
||||
self.world_com = self.mass_properties.world_com(&position);
|
||||
self.effective_inv_mass = self.mass_properties.inv_mass;
|
||||
@@ -286,6 +311,7 @@ impl RigidBodyMassProps {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// The velocities of this rigid-body.
|
||||
pub struct RigidBodyVelocity {
|
||||
/// The linear velocity of the rigid-body.
|
||||
pub linvel: Vector<Real>,
|
||||
@@ -300,6 +326,7 @@ impl Default for RigidBodyVelocity {
|
||||
}
|
||||
|
||||
impl RigidBodyVelocity {
|
||||
/// Velocities set to zero.
|
||||
#[must_use]
|
||||
pub fn zero() -> Self {
|
||||
Self {
|
||||
@@ -308,11 +335,16 @@ impl RigidBodyVelocity {
|
||||
}
|
||||
}
|
||||
|
||||
/// The approximate kinetic energy of this rigid-body.
|
||||
///
|
||||
/// This approximation does not take the rigid-body's mass and angular inertia
|
||||
/// into account.
|
||||
#[must_use]
|
||||
pub fn pseudo_kinetic_energy(&self) -> Real {
|
||||
self.linvel.norm_squared() + self.angvel.gdot(self.angvel)
|
||||
}
|
||||
|
||||
/// Returns the update velocities after applying the given damping.
|
||||
#[must_use]
|
||||
pub fn apply_damping(&self, dt: Real, damping: &RigidBodyDamping) -> Self {
|
||||
RigidBodyVelocity {
|
||||
@@ -321,6 +353,15 @@ impl RigidBodyVelocity {
|
||||
}
|
||||
}
|
||||
|
||||
/// The velocity of the given world-space point on this rigid-body.
|
||||
#[must_use]
|
||||
pub fn velocity_at_point(&self, point: &Point<Real>, world_com: &Point<Real>) -> Vector<Real> {
|
||||
let dpt = point - world_com;
|
||||
self.linvel + self.angvel.gcross(dpt)
|
||||
}
|
||||
|
||||
/// Integrate the velocities in `self` to compute obtain new positions when moving from the given
|
||||
/// inital position `init_pos`.
|
||||
#[must_use]
|
||||
pub fn integrate(
|
||||
&self,
|
||||
@@ -336,14 +377,81 @@ impl RigidBodyVelocity {
|
||||
result
|
||||
}
|
||||
|
||||
/// Are these velocities exactly equal to zero?
|
||||
#[must_use]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.linvel.is_zero() && self.angvel.is_zero()
|
||||
}
|
||||
|
||||
/// The kinetic energy of this rigid-body.
|
||||
#[must_use]
|
||||
pub fn kinetic_energy(&self, rb_mprops: &RigidBodyMassProps) -> Real {
|
||||
let mut energy = (rb_mprops.mass() * self.linvel.norm_squared()) / 2.0;
|
||||
|
||||
#[cfg(feature = "dim2")]
|
||||
if !rb_mprops.effective_world_inv_inertia_sqrt.is_zero() {
|
||||
let inertia_sqrt = 1.0 / rb_mprops.effective_world_inv_inertia_sqrt;
|
||||
energy += (inertia_sqrt * self.angvel).powi(2) / 2.0;
|
||||
}
|
||||
|
||||
#[cfg(feature = "dim3")]
|
||||
if !rb_mprops.effective_world_inv_inertia_sqrt.is_zero() {
|
||||
let inertia_sqrt = rb_mprops
|
||||
.effective_world_inv_inertia_sqrt
|
||||
.inverse_unchecked();
|
||||
energy += (inertia_sqrt * self.angvel).norm_squared() / 2.0;
|
||||
}
|
||||
|
||||
energy
|
||||
}
|
||||
|
||||
/// Applies an impulse at the center-of-mass of this rigid-body.
|
||||
/// The impulse is applied right away, changing the linear velocity.
|
||||
/// This does nothing on non-dynamic bodies.
|
||||
pub fn apply_impulse(&mut self, rb_mprops: &RigidBodyMassProps, impulse: Vector<Real>) {
|
||||
self.linvel += impulse * rb_mprops.effective_inv_mass;
|
||||
}
|
||||
|
||||
/// Applies an angular impulse at the center-of-mass of this rigid-body.
|
||||
/// The impulse is applied right away, changing the angular velocity.
|
||||
/// This does nothing on non-dynamic bodies.
|
||||
#[cfg(feature = "dim2")]
|
||||
pub fn apply_torque_impulse(&mut self, rb_mprops: &RigidBodyMassProps, torque_impulse: Real) {
|
||||
self.angvel += rb_mprops.effective_world_inv_inertia_sqrt
|
||||
* (rb_mprops.effective_world_inv_inertia_sqrt * torque_impulse);
|
||||
}
|
||||
|
||||
/// Applies an angular impulse at the center-of-mass of this rigid-body.
|
||||
/// The impulse is applied right away, changing the angular velocity.
|
||||
/// This does nothing on non-dynamic bodies.
|
||||
#[cfg(feature = "dim3")]
|
||||
pub fn apply_torque_impulse(
|
||||
&mut self,
|
||||
rb_mprops: &RigidBodyMassProps,
|
||||
torque_impulse: Vector<Real>,
|
||||
) {
|
||||
self.angvel += rb_mprops.effective_world_inv_inertia_sqrt
|
||||
* (rb_mprops.effective_world_inv_inertia_sqrt * torque_impulse);
|
||||
}
|
||||
|
||||
/// Applies an impulse at the given world-space point of this rigid-body.
|
||||
/// The impulse is applied right away, changing the linear and/or angular velocities.
|
||||
/// This does nothing on non-dynamic bodies.
|
||||
pub fn apply_impulse_at_point(
|
||||
&mut self,
|
||||
rb_mprops: &RigidBodyMassProps,
|
||||
impulse: Vector<Real>,
|
||||
point: Point<Real>,
|
||||
) {
|
||||
let torque_impulse = (point - rb_mprops.world_com).gcross(impulse);
|
||||
self.apply_impulse(rb_mprops, impulse);
|
||||
self.apply_torque_impulse(rb_mprops, torque_impulse);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// Damping factors to progressively slow down a rigid-body.
|
||||
pub struct RigidBodyDamping {
|
||||
/// Damping factor for gradually slowing down the translational motion of the rigid-body.
|
||||
pub linear_damping: Real,
|
||||
@@ -362,11 +470,14 @@ impl Default for RigidBodyDamping {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// The user-defined external forces applied to this rigid-body.
|
||||
pub struct RigidBodyForces {
|
||||
/// Accumulation of external forces (only for dynamic bodies).
|
||||
pub force: Vector<Real>,
|
||||
/// Accumulation of external torques (only for dynamic bodies).
|
||||
pub torque: AngVector<Real>,
|
||||
/// Gravity is multiplied by this scaling factor before it's
|
||||
/// applied to this rigid-body.
|
||||
pub gravity_scale: Real,
|
||||
}
|
||||
|
||||
@@ -381,6 +492,7 @@ impl Default for RigidBodyForces {
|
||||
}
|
||||
|
||||
impl RigidBodyForces {
|
||||
/// Integrate these forces to compute new velocities.
|
||||
#[must_use]
|
||||
pub fn integrate(
|
||||
&self,
|
||||
@@ -398,17 +510,41 @@ impl RigidBodyForces {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_linear_acceleration(&mut self, gravity: &Vector<Real>, mass: Real) {
|
||||
/// Adds to `self` the gravitational force that would result in a gravitational acceleration
|
||||
/// equal to `gravity`.
|
||||
pub fn add_gravity_acceleration(&mut self, gravity: &Vector<Real>, mass: Real) {
|
||||
self.force += gravity * self.gravity_scale * mass;
|
||||
}
|
||||
|
||||
/// Applies a force at the given world-space point of the rigid-body with the given mass properties.
|
||||
pub fn apply_force_at_point(
|
||||
&mut self,
|
||||
rb_mprops: &RigidBodyMassProps,
|
||||
force: Vector<Real>,
|
||||
point: Point<Real>,
|
||||
) {
|
||||
self.force += force;
|
||||
self.torque += (point - rb_mprops.world_com).gcross(force);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// Information used for Continuous-Collision-Detection.
|
||||
pub struct RigidBodyCcd {
|
||||
/// The distance used by the CCD solver to decide if a movement would
|
||||
/// result in a tunnelling problem.
|
||||
pub ccd_thickness: Real,
|
||||
/// The max distance between this rigid-body's center of mass and its
|
||||
/// furthest collider point.
|
||||
pub ccd_max_dist: Real,
|
||||
/// Is CCD active for this rigid-body?
|
||||
///
|
||||
/// If `self.ccd_enabled` is `true`, then this is automatically set to
|
||||
/// `true` when the CCD solver detects that the rigid-body is moving fast
|
||||
/// enough to potential cause a tunneling problem.
|
||||
pub ccd_active: bool,
|
||||
/// Is CCD enabled for this rigid-body?
|
||||
pub ccd_enabled: bool,
|
||||
}
|
||||
|
||||
@@ -424,6 +560,8 @@ impl Default for RigidBodyCcd {
|
||||
}
|
||||
|
||||
impl RigidBodyCcd {
|
||||
/// The maximum velocity any point of any collider attached to this rigid-body
|
||||
/// moving with the given velocity can have.
|
||||
pub fn max_point_velocity(&self, vels: &RigidBodyVelocity) -> Real {
|
||||
#[cfg(feature = "dim2")]
|
||||
return vels.linvel.norm() + vels.angvel.abs() * self.ccd_max_dist;
|
||||
@@ -431,6 +569,7 @@ impl RigidBodyCcd {
|
||||
return vels.linvel.norm() + vels.angvel.norm() * self.ccd_max_dist;
|
||||
}
|
||||
|
||||
/// Is this rigid-body moving fast enough so that it may cause a tunneling problem?
|
||||
pub fn is_moving_fast(
|
||||
&self,
|
||||
dt: Real,
|
||||
@@ -463,12 +602,13 @@ impl RigidBodyCcd {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// Internal identifiers used by the physics engine.
|
||||
pub struct RigidBodyIds {
|
||||
pub joint_graph_index: RigidBodyGraphIndex,
|
||||
pub active_island_id: usize,
|
||||
pub active_set_id: usize,
|
||||
pub active_set_offset: usize,
|
||||
pub active_set_timestamp: u32,
|
||||
pub(crate) joint_graph_index: RigidBodyGraphIndex,
|
||||
pub(crate) active_island_id: usize,
|
||||
pub(crate) active_set_id: usize,
|
||||
pub(crate) active_set_offset: usize,
|
||||
pub(crate) active_set_timestamp: u32,
|
||||
}
|
||||
|
||||
impl Default for RigidBodyIds {
|
||||
@@ -485,6 +625,11 @@ impl Default for RigidBodyIds {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug)]
|
||||
/// The set of colliders attached to this rigid-bodies.
|
||||
///
|
||||
/// This should not be modified manually unless you really know what
|
||||
/// you are doing (for example if you are trying to integrate Rapier
|
||||
/// to a game engine using its component-based interface).
|
||||
pub struct RigidBodyColliders(pub Vec<ColliderHandle>);
|
||||
|
||||
impl Default for RigidBodyColliders {
|
||||
@@ -494,6 +639,7 @@ impl Default for RigidBodyColliders {
|
||||
}
|
||||
|
||||
impl RigidBodyColliders {
|
||||
/// Detach a collider from this rigid-body.
|
||||
pub fn detach_collider(
|
||||
&mut self,
|
||||
rb_changes: &mut RigidBodyChanges,
|
||||
@@ -508,6 +654,7 @@ impl RigidBodyColliders {
|
||||
}
|
||||
}
|
||||
|
||||
/// Attach a collider to this rigid-body.
|
||||
pub fn attach_collider(
|
||||
&mut self,
|
||||
rb_changes: &mut RigidBodyChanges,
|
||||
@@ -541,6 +688,7 @@ impl RigidBodyColliders {
|
||||
rb_mprops.update_world_mass_properties(&rb_pos.position);
|
||||
}
|
||||
|
||||
/// Update the positions of all the colliders attached to this rigid-body.
|
||||
pub fn update_positions<Colliders>(
|
||||
&self,
|
||||
colliders: &mut Colliders,
|
||||
@@ -574,6 +722,7 @@ impl RigidBodyColliders {
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
#[derive(Clone, Debug, Copy)]
|
||||
/// The dominance groups of a rigid-body.
|
||||
pub struct RigidBodyDominance(pub i8);
|
||||
|
||||
impl Default for RigidBodyDominance {
|
||||
@@ -583,6 +732,7 @@ impl Default for RigidBodyDominance {
|
||||
}
|
||||
|
||||
impl RigidBodyDominance {
|
||||
/// The actually dominance group of this rigid-body, after taking into account its type.
|
||||
pub fn effective_group(&self, status: &RigidBodyType) -> i16 {
|
||||
if status.is_dynamic() {
|
||||
self.0 as i16
|
||||
@@ -643,6 +793,7 @@ impl RigidBodyActivation {
|
||||
self.energy != 0.0
|
||||
}
|
||||
|
||||
/// Wakes up this rigid-body.
|
||||
#[inline]
|
||||
pub fn wake_up(&mut self, strong: bool) {
|
||||
self.sleeping = false;
|
||||
@@ -651,6 +802,7 @@ impl RigidBodyActivation {
|
||||
}
|
||||
}
|
||||
|
||||
/// Put this rigid-body to sleep.
|
||||
#[inline]
|
||||
pub fn sleep(&mut self) {
|
||||
self.energy = 0.0;
|
||||
|
||||
@@ -125,7 +125,7 @@ impl RigidBodySet {
|
||||
// Make sure the internal links are reset, they may not be
|
||||
// if this rigid-body was obtained by cloning another one.
|
||||
rb.reset_internal_references();
|
||||
rb.changes_mut_internal().set(RigidBodyChanges::all(), true);
|
||||
rb.changes.set(RigidBodyChanges::all(), true);
|
||||
|
||||
let handle = RigidBodyHandle(self.bodies.insert(rb));
|
||||
self.modified_bodies.push(handle);
|
||||
@@ -170,7 +170,7 @@ impl RigidBodySet {
|
||||
///
|
||||
/// Using this is discouraged in favor of `self.get(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
pub fn get_unknown_gen(&self, i: usize) -> Option<(&RigidBody, RigidBodyHandle)> {
|
||||
pub fn get_unknown_gen(&self, i: u32) -> Option<(&RigidBody, RigidBodyHandle)> {
|
||||
self.bodies
|
||||
.get_unknown_gen(i)
|
||||
.map(|(b, h)| (b, RigidBodyHandle(h)))
|
||||
@@ -186,7 +186,7 @@ impl RigidBodySet {
|
||||
/// Using this is discouraged in favor of `self.get_mut(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
#[cfg(not(feature = "dev-remove-slow-accessors"))]
|
||||
pub fn get_unknown_gen_mut(&mut self, i: usize) -> Option<(&mut RigidBody, RigidBodyHandle)> {
|
||||
pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut RigidBody, RigidBodyHandle)> {
|
||||
let (rb, handle) = self.bodies.get_unknown_gen_mut(i)?;
|
||||
let handle = RigidBodyHandle(handle);
|
||||
Self::mark_as_modified(handle, rb, &mut self.modified_bodies);
|
||||
@@ -203,8 +203,8 @@ impl RigidBodySet {
|
||||
rb: &mut RigidBody,
|
||||
modified_bodies: &mut Vec<RigidBodyHandle>,
|
||||
) {
|
||||
if !rb.changes().contains(RigidBodyChanges::MODIFIED) {
|
||||
*rb.changes_mut_internal() = RigidBodyChanges::MODIFIED;
|
||||
if !rb.changes.contains(RigidBodyChanges::MODIFIED) {
|
||||
rb.changes = RigidBodyChanges::MODIFIED;
|
||||
modified_bodies.push(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::geometry::{
|
||||
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector, DIM};
|
||||
use crate::parry::transformation::vhacd::VHACDParameters;
|
||||
use na::Unit;
|
||||
use parry::bounding_volume::{BoundingVolume, AABB};
|
||||
use parry::bounding_volume::AABB;
|
||||
use parry::shape::Shape;
|
||||
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
@@ -16,22 +16,21 @@ use parry::shape::Shape;
|
||||
///
|
||||
/// To build a new collider, use the `ColliderBuilder` structure.
|
||||
pub struct Collider {
|
||||
pub co_type: ColliderType,
|
||||
pub co_shape: ColliderShape, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_mprops: ColliderMassProperties, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_changes: ColliderChanges, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_parent: ColliderParent, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_pos: ColliderPosition, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_material: ColliderMaterial, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_groups: ColliderGroups, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub co_bf_data: ColliderBroadPhaseData, // TODO ECS: this is public only for our bevy_rapier experiments.
|
||||
pub(crate) co_type: ColliderType,
|
||||
pub(crate) co_shape: ColliderShape,
|
||||
pub(crate) co_mprops: ColliderMassProperties,
|
||||
pub(crate) co_changes: ColliderChanges,
|
||||
pub(crate) co_parent: ColliderParent,
|
||||
pub(crate) co_pos: ColliderPosition,
|
||||
pub(crate) co_material: ColliderMaterial,
|
||||
pub(crate) co_groups: ColliderGroups,
|
||||
pub(crate) co_bf_data: ColliderBroadPhaseData,
|
||||
/// User-defined data associated to this rigid-body.
|
||||
pub user_data: u128,
|
||||
}
|
||||
|
||||
impl Collider {
|
||||
// TODO ECS: exists only for our bevy_ecs tests.
|
||||
pub fn reset_internal_references(&mut self) {
|
||||
pub(crate) fn reset_internal_references(&mut self) {
|
||||
self.co_parent.handle = RigidBodyHandle::invalid();
|
||||
self.co_bf_data.proxy_index = crate::INVALID_U32;
|
||||
self.co_changes = ColliderChanges::all();
|
||||
@@ -140,6 +139,7 @@ impl Collider {
|
||||
}
|
||||
}
|
||||
|
||||
/// The material (friction and restitution properties) of this collider.
|
||||
pub fn material(&self) -> &ColliderMaterial {
|
||||
&self.co_material
|
||||
}
|
||||
@@ -178,11 +178,11 @@ impl Collider {
|
||||
self.co_shape.compute_aabb(&self.co_pos)
|
||||
}
|
||||
|
||||
/// Compute the axis-aligned bounding box of this collider.
|
||||
/// Compute the axis-aligned bounding box of this collider moving from its current position
|
||||
/// to the given `next_position`
|
||||
pub fn compute_swept_aabb(&self, next_position: &Isometry<Real>) -> AABB {
|
||||
let aabb1 = self.co_shape.compute_aabb(&self.co_pos);
|
||||
let aabb2 = self.co_shape.compute_aabb(next_position);
|
||||
aabb1.merged(&aabb2)
|
||||
self.co_shape
|
||||
.compute_swept_aabb(&self.co_pos, next_position)
|
||||
}
|
||||
|
||||
/// Compute the local-space mass properties of this collider.
|
||||
|
||||
@@ -44,12 +44,18 @@ bitflags::bitflags! {
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// Flags describing how the collider has been modified by the user.
|
||||
pub struct ColliderChanges: u32 {
|
||||
const MODIFIED = 1 << 0;
|
||||
const PARENT = 1 << 1; // => BF & NF updates.
|
||||
const POSITION = 1 << 2; // => BF & NF updates.
|
||||
const GROUPS = 1 << 3; // => NF update.
|
||||
const SHAPE = 1 << 4; // => BF & NF update. NF pair workspace invalidation.
|
||||
const TYPE = 1 << 5; // => NF update. NF pair invalidation.
|
||||
/// Flag indicating that any component of the collider has been modified.
|
||||
const MODIFIED = 1 << 0;
|
||||
/// Flag indicating that the `RigidBodyParent` component of the collider has been modified.
|
||||
const PARENT = 1 << 1; // => BF & NF updates.
|
||||
/// Flag indicating that the `RigidBodyPosition` component of the collider has been modified.
|
||||
const POSITION = 1 << 2; // => BF & NF updates.
|
||||
/// Flag indicating that the `RigidBodyGroups` component of the collider has been modified.
|
||||
const GROUPS = 1 << 3; // => NF update.
|
||||
/// Flag indicating that the `RigidBodyShape` component of the collider has been modified.
|
||||
const SHAPE = 1 << 4; // => BF & NF update. NF pair workspace invalidation.
|
||||
/// Flag indicating that the `RigidBodyType` component of the collider has been modified.
|
||||
const TYPE = 1 << 5; // => NF update. NF pair invalidation.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +66,14 @@ impl Default for ColliderChanges {
|
||||
}
|
||||
|
||||
impl ColliderChanges {
|
||||
/// Do these changes justify a broad-phase update?
|
||||
pub fn needs_broad_phase_update(self) -> bool {
|
||||
self.intersects(
|
||||
ColliderChanges::PARENT | ColliderChanges::POSITION | ColliderChanges::SHAPE,
|
||||
)
|
||||
}
|
||||
|
||||
/// Do these changes justify a narrow-phase update?
|
||||
pub fn needs_narrow_phase_update(self) -> bool {
|
||||
self.bits() > 1
|
||||
}
|
||||
@@ -73,12 +81,16 @@ impl ColliderChanges {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// The type of collider.
|
||||
pub enum ColliderType {
|
||||
/// A collider that can generate contacts and contact events.
|
||||
Solid,
|
||||
/// A collider that can generate intersection and intersection events.
|
||||
Sensor,
|
||||
}
|
||||
|
||||
impl ColliderType {
|
||||
/// Is this collider a sensor?
|
||||
pub fn is_sensor(self) -> bool {
|
||||
self == ColliderType::Sensor
|
||||
}
|
||||
@@ -86,6 +98,7 @@ impl ColliderType {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// Data associated to a collider that takes part to a broad-phase algorithm.
|
||||
pub struct ColliderBroadPhaseData {
|
||||
pub(crate) proxy_index: SAPProxyIndex,
|
||||
}
|
||||
@@ -98,13 +111,19 @@ impl Default for ColliderBroadPhaseData {
|
||||
}
|
||||
}
|
||||
|
||||
/// The shape of a collider.
|
||||
pub type ColliderShape = SharedShape;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// The mass-properties of a collider.
|
||||
pub enum ColliderMassProperties {
|
||||
/// `MassProperties` are computed with the help of [`SharedShape::mass_properties`].
|
||||
/// The collider is given a density.
|
||||
///
|
||||
/// Its actual `MassProperties` are computed automatically with
|
||||
/// the help of [`SharedShape::mass_properties`].
|
||||
Density(Real),
|
||||
/// The collider is given explicit mass-properties.
|
||||
MassProperties(Box<MassProperties>),
|
||||
}
|
||||
|
||||
@@ -115,6 +134,12 @@ impl Default for ColliderMassProperties {
|
||||
}
|
||||
|
||||
impl ColliderMassProperties {
|
||||
/// The mass-properties of this collider.
|
||||
///
|
||||
/// If `self` is the `Density` variant, then this computes the mass-properties based
|
||||
/// on the given shape.
|
||||
///
|
||||
/// If `self` is the `MassProperties` variant, then this returns the stored mass-properties.
|
||||
pub fn mass_properties(&self, shape: &dyn Shape) -> MassProperties {
|
||||
match self {
|
||||
Self::Density(density) => shape.mass_properties(*density),
|
||||
@@ -125,13 +150,17 @@ impl ColliderMassProperties {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// Information about the rigid-body this collider is attached to.
|
||||
pub struct ColliderParent {
|
||||
/// Handle of the rigid-body this collider is attached to.
|
||||
pub handle: RigidBodyHandle,
|
||||
/// Const position of this collider relative to its parent rigid-body.
|
||||
pub pos_wrt_parent: Isometry<Real>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// The position of a collider.
|
||||
pub struct ColliderPosition(pub Isometry<Real>);
|
||||
|
||||
impl AsRef<Isometry<Real>> for ColliderPosition {
|
||||
@@ -156,8 +185,9 @@ impl Default for ColliderPosition {
|
||||
}
|
||||
|
||||
impl ColliderPosition {
|
||||
/// The identity position.
|
||||
#[must_use]
|
||||
fn identity() -> Self {
|
||||
pub fn identity() -> Self {
|
||||
ColliderPosition(Isometry::identity())
|
||||
}
|
||||
}
|
||||
@@ -173,8 +203,13 @@ where
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// The groups of this collider, for filtering contact and solver pairs.
|
||||
pub struct ColliderGroups {
|
||||
/// The groups controlling the pairs of colliders that can interact (generate
|
||||
/// interaction events or contacts).
|
||||
pub collision_groups: InteractionGroups,
|
||||
/// The groups controlling the pairs of collider that have their contact
|
||||
/// points taken into account for force computation.
|
||||
pub solver_groups: InteractionGroups,
|
||||
}
|
||||
|
||||
@@ -189,15 +224,30 @@ impl Default for ColliderGroups {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||
/// The constraints solver-related properties of this collider (friction, restitution, etc.)
|
||||
pub struct ColliderMaterial {
|
||||
/// The friction coefficient of this collider.
|
||||
///
|
||||
/// The greater the value, the stronger the friction forces will be.
|
||||
/// Should be `>= 0`.
|
||||
pub friction: Real,
|
||||
/// The restitution coefficient of this collider.
|
||||
///
|
||||
/// Increase this value to make contacts with this collider more "bouncy".
|
||||
/// Should be `>= 0` and should generally not be greater than `1` (perfectly elastic
|
||||
/// collision).
|
||||
pub restitution: Real,
|
||||
/// The rule applied to combine the friction coefficients of two colliders in contact.
|
||||
pub friction_combine_rule: CoefficientCombineRule,
|
||||
/// The rule applied to combine the restitution coefficients of two colliders.
|
||||
pub restitution_combine_rule: CoefficientCombineRule,
|
||||
/// The solver flags attached to this collider in order to customize the way the
|
||||
/// constraints solver will work with contacts involving this collider.
|
||||
pub solver_flags: SolverFlags,
|
||||
}
|
||||
|
||||
impl ColliderMaterial {
|
||||
/// Creates a new collider material with the given friction and restitution coefficients.
|
||||
pub fn new(friction: Real, restitution: Real) -> Self {
|
||||
Self {
|
||||
friction,
|
||||
|
||||
@@ -197,7 +197,7 @@ impl ColliderSet {
|
||||
///
|
||||
/// Using this is discouraged in favor of `self.get(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
pub fn get_unknown_gen(&self, i: usize) -> Option<(&Collider, ColliderHandle)> {
|
||||
pub fn get_unknown_gen(&self, i: u32) -> Option<(&Collider, ColliderHandle)> {
|
||||
self.colliders
|
||||
.get_unknown_gen(i)
|
||||
.map(|(c, h)| (c, ColliderHandle(h)))
|
||||
@@ -213,7 +213,7 @@ impl ColliderSet {
|
||||
/// Using this is discouraged in favor of `self.get_mut(handle)` which does not
|
||||
/// suffer form the ABA problem.
|
||||
#[cfg(not(feature = "dev-remove-slow-accessors"))]
|
||||
pub fn get_unknown_gen_mut(&mut self, i: usize) -> Option<(&mut Collider, ColliderHandle)> {
|
||||
pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut Collider, ColliderHandle)> {
|
||||
let (collider, handle) = self.colliders.get_unknown_gen_mut(i)?;
|
||||
let handle = ColliderHandle(handle);
|
||||
Self::mark_as_modified(handle, collider, &mut self.modified_colliders);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
//! are compliant with the IEEE 754-2008 floating point standard.
|
||||
|
||||
#![deny(bare_trait_objects)]
|
||||
// #![warn(missing_docs)] // TODO: re-enable this
|
||||
#![warn(missing_docs)]
|
||||
|
||||
#[cfg(all(feature = "dim2", feature = "f32"))]
|
||||
pub extern crate parry2d as parry;
|
||||
|
||||
@@ -271,7 +271,7 @@ impl PhysicsPipeline {
|
||||
})
|
||||
.unwrap();
|
||||
bodies.map_mut_internal(handle.0, |forces: &mut RigidBodyForces| {
|
||||
forces.add_linear_acceleration(&gravity, effective_inv_mass)
|
||||
forces.add_gravity_acceleration(&gravity, effective_inv_mass)
|
||||
});
|
||||
}
|
||||
self.counters.stages.update_time.pause();
|
||||
@@ -442,6 +442,10 @@ impl PhysicsPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes one timestep of the physics simulation.
|
||||
///
|
||||
/// This is the same as `self.step_generic`, except that it is specialized
|
||||
/// to work with `RigidBodySet` and `ColliderSet`.
|
||||
#[cfg(feature = "default-sets")]
|
||||
pub fn step(
|
||||
&mut self,
|
||||
|
||||
@@ -520,9 +520,9 @@ fn physx_collider_from_rapier_collider(
|
||||
};
|
||||
let mut material = physics
|
||||
.create_material(
|
||||
collider.co_material.friction,
|
||||
collider.co_material.friction,
|
||||
collider.co_material.restitution,
|
||||
collider.material().friction,
|
||||
collider.material().friction,
|
||||
collider.material().restitution,
|
||||
(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user