Merge pull request #54 from dimforge/idiomatic_clone

Allow cloning all the physics components worth cloning
This commit is contained in:
Sébastien Crozet
2020-11-03 15:33:11 +01:00
committed by GitHub
19 changed files with 81 additions and 39 deletions

View File

@@ -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> {

View File

@@ -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);

View File

@@ -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,

View File

@@ -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.

View File

@@ -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;

View File

@@ -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];

View File

@@ -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,

View File

@@ -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;
}
/// The rigid body this collider is attached to.
pub fn parent(&self) -> RigidBodyHandle {
self.parent

View File

@@ -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)

View File

@@ -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.

View File

@@ -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>)

View File

@@ -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())
}
}

View File

@@ -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())
}
}

View File

@@ -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())
}
}

View File

@@ -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>,
}

View File

@@ -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>,

View File

@@ -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.

View File

@@ -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,

View File

@@ -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,