aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-11-03 15:33:11 +0100
committerGitHub <noreply@github.com>2020-11-03 15:33:11 +0100
commitf70a840f79943aa6da49db2590e13dcd3f3a89ed (patch)
tree1c743ed924b10ebd0eb0982e5c7d798235c12cee /src
parent0cc850dc505a4034103d229fdce22f9ec7bc410a (diff)
parent71611d3e30ce2fddee20832db3c3e0c8b6ba0d07 (diff)
downloadrapier-f70a840f79943aa6da49db2590e13dcd3f3a89ed.tar.gz
rapier-f70a840f79943aa6da49db2590e13dcd3f3a89ed.tar.bz2
rapier-f70a840f79943aa6da49db2590e13dcd3f3a89ed.zip
Merge pull request #54 from dimforge/idiomatic_clone
Allow cloning all the physics components worth cloning
Diffstat (limited to 'src')
-rw-r--r--src/data/graph.rs10
-rw-r--r--src/data/maybe_serializable_data.rs3
-rw-r--r--src/data/pubsub.rs3
-rw-r--r--src/dynamics/joint/joint.rs1
-rw-r--r--src/dynamics/rigid_body.rs25
-rw-r--r--src/dynamics/rigid_body_set.rs7
-rw-r--r--src/geometry/broad_phase_multi_sap.rs5
-rw-r--r--src/geometry/collider.rs19
-rw-r--r--src/geometry/collider_set.rs5
-rw-r--r--src/geometry/contact.rs1
-rw-r--r--src/geometry/contact_generator/contact_generator_workspace.rs6
-rw-r--r--src/geometry/contact_generator/heightfield_shape_contact_generator.rs6
-rw-r--r--src/geometry/contact_generator/pfm_pfm_contact_generator.rs5
-rw-r--r--src/geometry/contact_generator/trimesh_shape_contact_generator.rs5
-rw-r--r--src/geometry/interaction_graph.rs1
-rw-r--r--src/geometry/narrow_phase.rs1
-rw-r--r--src/geometry/polyhedron_feature3d.rs2
-rw-r--r--src/geometry/proximity.rs12
-rw-r--r--src/pipeline/query_pipeline.rs1
19 files changed, 80 insertions, 38 deletions
diff --git a/src/data/graph.rs b/src/data/graph.rs
index ea27e03..de958c3 100644
--- a/src/data/graph.rs
+++ b/src/data/graph.rs
@@ -749,20 +749,12 @@ impl<N, E> IndexMut<EdgeIndex> for Graph<N, E> {
/// The walker does not borrow from the graph, so it lets you step through
/// neighbors or incident edges while also mutating graph weights, as
/// in the following example:
+#[derive(Clone)]
pub struct WalkNeighbors {
skip_start: NodeIndex,
next: [EdgeIndex; 2],
}
-impl Clone for WalkNeighbors {
- fn clone(&self) -> Self {
- WalkNeighbors {
- skip_start: self.skip_start,
- next: self.next,
- }
- }
-}
-
/// Reference to a `Graph` edge.
#[derive(Debug)]
pub struct EdgeReference<'a, E: 'a> {
diff --git a/src/data/maybe_serializable_data.rs b/src/data/maybe_serializable_data.rs
index db38963..8b14e1a 100644
--- a/src/data/maybe_serializable_data.rs
+++ b/src/data/maybe_serializable_data.rs
@@ -9,6 +9,9 @@ pub trait MaybeSerializableData: DowncastSync {
fn as_serialize(&self) -> Option<(u32, &dyn Serialize)> {
None
}
+
+ /// Clones `self`.
+ fn clone_dyn(&self) -> Box<dyn MaybeSerializableData>;
}
impl_downcast!(sync MaybeSerializableData);
diff --git a/src/data/pubsub.rs b/src/data/pubsub.rs
index b2c9e27..80fb3a2 100644
--- a/src/data/pubsub.rs
+++ b/src/data/pubsub.rs
@@ -5,6 +5,7 @@ use std::marker::PhantomData;
/// A permanent subscription to a pub-sub queue.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct Subscription<T> {
// Position on the cursor array.
id: u32,
@@ -12,6 +13,7 @@ pub struct Subscription<T> {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
struct PubSubCursor {
// Position on the offset array.
id: u32,
@@ -36,6 +38,7 @@ impl PubSubCursor {
/// A pub-sub queue.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct PubSub<T> {
deleted_messages: u32,
deleted_offsets: u32,
diff --git a/src/dynamics/joint/joint.rs b/src/dynamics/joint/joint.rs
index 074f802..9fe6488 100644
--- a/src/dynamics/joint/joint.rs
+++ b/src/dynamics/joint/joint.rs
@@ -95,6 +95,7 @@ impl From<PrismaticJoint> for JointParams {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
/// A joint attached to two bodies.
pub struct Joint {
/// Handle to the first body attached to this joint.
diff --git a/src/dynamics/rigid_body.rs b/src/dynamics/rigid_body.rs
index 6b897a6..d3bd8d7 100644
--- a/src/dynamics/rigid_body.rs
+++ b/src/dynamics/rigid_body.rs
@@ -27,7 +27,7 @@ pub enum BodyStatus {
/// A rigid body.
///
/// To create a new rigid-body, use the `RigidBodyBuilder` structure.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct RigidBody {
/// The world-space position of the rigid-body.
pub position: Isometry<f32>,
@@ -58,20 +58,6 @@ pub struct RigidBody {
pub user_data: u128,
}
-impl Clone for RigidBody {
- fn clone(&self) -> Self {
- Self {
- colliders: Vec::new(),
- joint_graph_index: RigidBodyGraphIndex::new(crate::INVALID_U32),
- active_island_id: crate::INVALID_USIZE,
- active_set_id: crate::INVALID_USIZE,
- active_set_offset: crate::INVALID_USIZE,
- active_set_timestamp: crate::INVALID_U32,
- ..*self
- }
- }
-}
-
impl RigidBody {
fn new() -> Self {
Self {
@@ -96,6 +82,15 @@ impl RigidBody {
}
}
+ pub(crate) fn reset_internal_references(&mut self) {
+ self.colliders = Vec::new();
+ self.joint_graph_index = InteractionGraph::<()>::invalid_graph_index();
+ self.active_island_id = 0;
+ self.active_set_id = 0;
+ self.active_set_offset = 0;
+ self.active_set_timestamp = 0;
+ }
+
pub(crate) fn integrate_accelerations(&mut self, dt: f32, gravity: Vector<f32>) {
if self.mass_properties.inv_mass != 0.0 {
self.linvel += (gravity + self.linacc) * dt;
diff --git a/src/dynamics/rigid_body_set.rs b/src/dynamics/rigid_body_set.rs
index 83f1c51..b857173 100644
--- a/src/dynamics/rigid_body_set.rs
+++ b/src/dynamics/rigid_body_set.rs
@@ -75,6 +75,7 @@ impl BodyPair {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
/// A set of rigid bodies that can be handled by a physics pipeline.
pub struct RigidBodySet {
// NOTE: the pub(crate) are needed by the broad phase
@@ -154,7 +155,11 @@ impl RigidBodySet {
}
/// Insert a rigid body into this set and retrieve its handle.
- pub fn insert(&mut self, rb: RigidBody) -> RigidBodyHandle {
+ pub fn insert(&mut self, mut rb: RigidBody) -> RigidBodyHandle {
+ // 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();
+
let handle = self.bodies.insert(rb);
let rb = &mut self.bodies[handle];
diff --git a/src/geometry/broad_phase_multi_sap.rs b/src/geometry/broad_phase_multi_sap.rs
index 1afda5a..21413ef 100644
--- a/src/geometry/broad_phase_multi_sap.rs
+++ b/src/geometry/broad_phase_multi_sap.rs
@@ -132,6 +132,7 @@ impl Endpoint {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
struct SAPAxis {
min_bound: f32,
max_bound: f32,
@@ -331,6 +332,7 @@ impl SAPAxis {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
struct SAPRegion {
axes: [SAPAxis; DIM],
existing_proxies: BitVec,
@@ -411,6 +413,7 @@ impl SAPRegion {
/// A broad-phase based on multiple Sweep-and-Prune instances running of disjoint region of the 3D world.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct BroadPhase {
proxies: Proxies,
regions: HashMap<Point<i32>, SAPRegion>,
@@ -438,6 +441,7 @@ pub struct BroadPhase {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub(crate) struct BroadPhaseProxy {
handle: ColliderHandle,
aabb: AABB<f32>,
@@ -445,6 +449,7 @@ pub(crate) struct BroadPhaseProxy {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
struct Proxies {
elements: Vec<BroadPhaseProxy>,
first_free: u32,
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs
index f53d75a..c2adc59 100644
--- a/src/geometry/collider.rs
+++ b/src/geometry/collider.rs
@@ -188,6 +188,7 @@ impl<'de> serde::Deserialize<'de> for ColliderShape {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
/// A geometric entity that can be attached to a body so it can be affected by contacts and proximity queries.
///
/// To build a new collider, use the `ColliderBuilder` structure.
@@ -212,20 +213,14 @@ pub struct Collider {
pub user_data: u128,
}
-impl Clone for Collider {
- fn clone(&self) -> Self {
- Self {
- shape: self.shape.clone(),
- parent: RigidBodySet::invalid_handle(),
- contact_graph_index: ColliderGraphIndex::new(crate::INVALID_U32),
- proximity_graph_index: ColliderGraphIndex::new(crate::INVALID_U32),
- proxy_index: crate::INVALID_USIZE,
- ..*self
- }
+impl Collider {
+ pub(crate) fn reset_internal_references(&mut self) {
+ self.parent = RigidBodySet::invalid_handle();
+ self.contact_graph_index = InteractionGraph::<Contact>::invalid_graph_index();
+ self.proximity_graph_index = InteractionGraph::<Proximity>::invalid_graph_index();
+ self.proxy_index = crate::INVALID_USIZE;
}
-}
-impl Collider {
/// The rigid body this collider is attached to.
pub fn parent(&self) -> RigidBodyHandle {
self.parent
diff --git a/src/geometry/collider_set.rs b/src/geometry/collider_set.rs
index 5ac9658..fd94675 100644
--- a/src/geometry/collider_set.rs
+++ b/src/geometry/collider_set.rs
@@ -17,6 +17,7 @@ pub(crate) struct RemovedCollider {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
/// A set of colliders that can be handled by a physics `World`.
pub struct ColliderSet {
pub(crate) removed_colliders: PubSub<RemovedCollider>,
@@ -59,6 +60,10 @@ impl ColliderSet {
parent_handle: RigidBodyHandle,
bodies: &mut RigidBodySet,
) -> ColliderHandle {
+ // Make sure the internal links are reset, they may not be
+ // if this rigid-body was obtained by cloning another one.
+ coll.reset_internal_references();
+
coll.parent = parent_handle;
let parent = bodies
.get_mut_internal(parent_handle)
diff --git a/src/geometry/contact.rs b/src/geometry/contact.rs
index 53e9064..a4a176e 100644
--- a/src/geometry/contact.rs
+++ b/src/geometry/contact.rs
@@ -172,6 +172,7 @@ impl Contact {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
/// The description of all the contacts between a pair of colliders.
pub struct ContactPair {
/// The pair of colliders involved.
diff --git a/src/geometry/contact_generator/contact_generator_workspace.rs b/src/geometry/contact_generator/contact_generator_workspace.rs
index fb6d7b4..e89395f 100644
--- a/src/geometry/contact_generator/contact_generator_workspace.rs
+++ b/src/geometry/contact_generator/contact_generator_workspace.rs
@@ -9,6 +9,12 @@ use crate::geometry::contact_generator::{
// Note we have this newtype because it simplifies the serialization/deserialization code.
pub struct ContactGeneratorWorkspace(pub Box<dyn MaybeSerializableData>);
+impl Clone for ContactGeneratorWorkspace {
+ fn clone(&self) -> Self {
+ ContactGeneratorWorkspace(self.0.clone_dyn())
+ }
+}
+
impl<T: MaybeSerializableData> From<T> for ContactGeneratorWorkspace {
fn from(data: T) -> Self {
Self(Box::new(data) as Box<dyn MaybeSerializableData>)
diff --git a/src/geometry/contact_generator/heightfield_shape_contact_generator.rs b/src/geometry/contact_generator/heightfield_shape_contact_generator.rs
index 62c6365..70360c9 100644
--- a/src/geometry/contact_generator/heightfield_shape_contact_generator.rs
+++ b/src/geometry/contact_generator/heightfield_shape_contact_generator.rs
@@ -12,6 +12,7 @@ use crate::ncollide::bounding_volume::BoundingVolume;
use erased_serde::Serialize;
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
struct SubDetector {
#[cfg_attr(feature = "serde-serialize", serde(skip))]
generator: Option<PrimitiveContactGenerator>,
@@ -21,6 +22,7 @@ struct SubDetector {
}
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct HeightFieldShapeContactGeneratorWorkspace {
timestamp: bool,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
@@ -182,4 +184,8 @@ impl MaybeSerializableData for HeightFieldShapeContactGeneratorWorkspace {
self,
))
}
+
+ fn clone_dyn(&self) -> Box<dyn MaybeSerializableData> {
+ Box::new(self.clone())
+ }
}
diff --git a/src/geometry/contact_generator/pfm_pfm_contact_generator.rs b/src/geometry/contact_generator/pfm_pfm_contact_generator.rs
index 027c398..5bc213e 100644
--- a/src/geometry/contact_generator/pfm_pfm_contact_generator.rs
+++ b/src/geometry/contact_generator/pfm_pfm_contact_generator.rs
@@ -9,6 +9,7 @@ use ncollide::query;
use ncollide::query::algorithms::{gjk::GJKResult, VoronoiSimplex};
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct PfmPfmContactManifoldGeneratorWorkspace {
#[cfg_attr(
feature = "serde-serialize",
@@ -136,4 +137,8 @@ impl MaybeSerializableData for PfmPfmContactManifoldGeneratorWorkspace {
self,
))
}
+
+ fn clone_dyn(&self) -> Box<dyn MaybeSerializableData> {
+ Box::new(self.clone())
+ }
}
diff --git a/src/geometry/contact_generator/trimesh_shape_contact_generator.rs b/src/geometry/contact_generator/trimesh_shape_contact_generator.rs
index 26ccfaa..3f7d7cd 100644
--- a/src/geometry/contact_generator/trimesh_shape_contact_generator.rs
+++ b/src/geometry/contact_generator/trimesh_shape_contact_generator.rs
@@ -8,6 +8,7 @@ use crate::ncollide::bounding_volume::{BoundingVolume, AABB};
use erased_serde::Serialize;
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct TrimeshShapeContactGeneratorWorkspace {
interferences: Vec<usize>,
local_aabb2: AABB<f32>,
@@ -213,4 +214,8 @@ impl MaybeSerializableData for TrimeshShapeContactGeneratorWorkspace {
self,
))
}
+
+ fn clone_dyn(&self) -> Box<dyn MaybeSerializableData> {
+ Box::new(self.clone())
+ }
}
diff --git a/src/geometry/interaction_graph.rs b/src/geometry/interaction_graph.rs
index c0cf093..2abb6d1 100644
--- a/src/geometry/interaction_graph.rs
+++ b/src/geometry/interaction_graph.rs
@@ -10,6 +10,7 @@ pub type TemporaryInteractionIndex = EdgeIndex;
/// A graph where nodes are collision objects and edges are contact or proximity algorithms.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct InteractionGraph<T> {
pub(crate) graph: Graph<ColliderHandle, T>,
}
diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs
index e3e52e5..059a640 100644
--- a/src/geometry/narrow_phase.rs
+++ b/src/geometry/narrow_phase.rs
@@ -29,6 +29,7 @@ use std::collections::HashMap;
/// The narrow-phase responsible for computing precise contact information between colliders.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct NarrowPhase {
contact_graph: InteractionGraph<ContactPair>,
proximity_graph: InteractionGraph<ProximityPair>,
diff --git a/src/geometry/polyhedron_feature3d.rs b/src/geometry/polyhedron_feature3d.rs
index d7f0a23..5ad62df 100644
--- a/src/geometry/polyhedron_feature3d.rs
+++ b/src/geometry/polyhedron_feature3d.rs
@@ -5,7 +5,7 @@ use crate::utils::WBasis;
use na::Point2;
use ncollide::shape::Segment;
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub struct PolyhedronFace {
pub vertices: [Point<f32>; 4],
pub vids: [u8; 4], // Feature ID of the vertices.
diff --git a/src/geometry/proximity.rs b/src/geometry/proximity.rs
index 88e6e76..d3e0dc4 100644
--- a/src/geometry/proximity.rs
+++ b/src/geometry/proximity.rs
@@ -15,6 +15,18 @@ pub struct ProximityPair {
pub(crate) detector_workspace: Option<Box<dyn Any + Send + Sync>>,
}
+// TODO: use the `derive(Clone)` instead?
+impl Clone for ProximityPair {
+ fn clone(&self) -> Self {
+ ProximityPair {
+ pair: self.pair.clone(),
+ proximity: self.proximity.clone(),
+ detector: None,
+ detector_workspace: None,
+ }
+ }
+}
+
impl ProximityPair {
pub(crate) fn new(
pair: ColliderPair,
diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs
index 00d4396..c21574a 100644
--- a/src/pipeline/query_pipeline.rs
+++ b/src/pipeline/query_pipeline.rs
@@ -5,6 +5,7 @@ use crate::geometry::{
/// A pipeline for performing queries on all the colliders of a scene.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+#[derive(Clone)]
pub struct QueryPipeline {
quadtree: WQuadtree<ColliderHandle>,
tree_built: bool,