parry3d/query/contact_manifolds/
contact_manifolds_workspace.rs

1#![allow(clippy::multiple_bound_locations)] // for impl_downcast
2
3use alloc::boxed::Box;
4use downcast_rs::{impl_downcast, DowncastSync};
5
6use crate::query::contact_manifolds::{
7    CompositeShapeCompositeShapeContactManifoldsWorkspace,
8    CompositeShapeShapeContactManifoldsWorkspace,
9    HeightFieldCompositeShapeContactManifoldsWorkspace, HeightFieldShapeContactManifoldsWorkspace,
10    TriMeshShapeContactManifoldsWorkspace, VoxelsShapeContactManifoldsWorkspace,
11};
12
13#[derive(Copy, Clone)]
14#[cfg_attr(feature = "serde-serialize", derive(Serialize))]
15/// Enum representing workspace data of a specific type.
16pub enum TypedWorkspaceData<'a> {
17    /// A trimesh workspace.
18    TriMeshShapeContactManifoldsWorkspace(&'a TriMeshShapeContactManifoldsWorkspace),
19    /// A heightfield vs. shape workspace.
20    HeightfieldShapeContactManifoldsWorkspace(&'a HeightFieldShapeContactManifoldsWorkspace),
21    /// A heightfield vs. composite shape workspace.
22    HeightfieldCompositeShapeContactManifoldsWorkspace(
23        &'a HeightFieldCompositeShapeContactManifoldsWorkspace,
24    ),
25    /// A composite shape vs. composite shape workspace.
26    CompositeShapeCompositeShapeContactManifoldsWorkspace(
27        &'a CompositeShapeCompositeShapeContactManifoldsWorkspace,
28    ),
29    /// A composite shape vs. shape workspace.
30    CompositeShapeShapeContactManifoldsWorkspace(&'a CompositeShapeShapeContactManifoldsWorkspace),
31    /// A voxels vs. shape workspace.
32    VoxelsShapeContactManifoldsWorkspace(&'a VoxelsShapeContactManifoldsWorkspace<2>),
33    /// A voxels vs. composite shape workspace.
34    VoxelsCompositeShapeContactManifoldsWorkspace(&'a VoxelsShapeContactManifoldsWorkspace<3>),
35    /// A voxels vs. voxels workspace.
36    VoxelsVoxelsContactManifoldsWorkspace(&'a VoxelsShapeContactManifoldsWorkspace<4>),
37    /// A custom workspace.
38    Custom,
39}
40
41// NOTE: must match the TypedWorkspaceData enum.
42#[cfg(feature = "serde-serialize")]
43#[derive(Deserialize)]
44enum DeserializableWorkspaceData {
45    TriMeshShapeContactManifoldsWorkspace(TriMeshShapeContactManifoldsWorkspace),
46    HeightfieldShapeContactManifoldsWorkspace(HeightFieldShapeContactManifoldsWorkspace),
47    HeightfieldCompositeShapeContactManifoldsWorkspace(
48        HeightFieldCompositeShapeContactManifoldsWorkspace,
49    ),
50    CompositeShapeCompositeShapeContactManifoldsWorkspace(
51        CompositeShapeCompositeShapeContactManifoldsWorkspace,
52    ),
53    CompositeShapeShapeContactManifoldsWorkspace(CompositeShapeShapeContactManifoldsWorkspace),
54    VoxelsShapeContactManifoldsWorkspace(VoxelsShapeContactManifoldsWorkspace<2>),
55    VoxelsCompositeShapeContactManifoldsWorkspace(VoxelsShapeContactManifoldsWorkspace<3>),
56    VoxelsVoxelsContactManifoldsWorkspace(VoxelsShapeContactManifoldsWorkspace<4>),
57    #[allow(dead_code)]
58    Custom,
59}
60
61#[cfg(feature = "serde-serialize")]
62impl DeserializableWorkspaceData {
63    pub fn into_contact_manifold_workspace(self) -> Option<ContactManifoldsWorkspace> {
64        match self {
65            DeserializableWorkspaceData::TriMeshShapeContactManifoldsWorkspace(w) => {
66                Some(ContactManifoldsWorkspace(Box::new(w)))
67            }
68            DeserializableWorkspaceData::HeightfieldShapeContactManifoldsWorkspace(w) => {
69                Some(ContactManifoldsWorkspace(Box::new(w)))
70            }
71            DeserializableWorkspaceData::HeightfieldCompositeShapeContactManifoldsWorkspace(w) => {
72                Some(ContactManifoldsWorkspace(Box::new(w)))
73            }
74            DeserializableWorkspaceData::CompositeShapeCompositeShapeContactManifoldsWorkspace(
75                w,
76            ) => Some(ContactManifoldsWorkspace(Box::new(w))),
77            DeserializableWorkspaceData::CompositeShapeShapeContactManifoldsWorkspace(w) => {
78                Some(ContactManifoldsWorkspace(Box::new(w)))
79            }
80            DeserializableWorkspaceData::VoxelsShapeContactManifoldsWorkspace(w) => {
81                Some(ContactManifoldsWorkspace(Box::new(w)))
82            }
83            DeserializableWorkspaceData::VoxelsCompositeShapeContactManifoldsWorkspace(w) => {
84                Some(ContactManifoldsWorkspace(Box::new(w)))
85            }
86            DeserializableWorkspaceData::VoxelsVoxelsContactManifoldsWorkspace(w) => {
87                Some(ContactManifoldsWorkspace(Box::new(w)))
88            }
89            DeserializableWorkspaceData::Custom => None,
90        }
91    }
92}
93
94/// Data from a [`ContactManifoldsWorkspace`].
95pub trait WorkspaceData: DowncastSync {
96    /// Gets the underlying workspace as an enum.
97    fn as_typed_workspace_data(&self) -> TypedWorkspaceData<'_>;
98
99    /// Clones `self`.
100    fn clone_dyn(&self) -> Box<dyn WorkspaceData>;
101}
102
103impl_downcast!(sync WorkspaceData);
104
105// Note we have this newtype because it simplifies the serialization/deserialization code.
106/// A serializable workspace used by some contact-manifolds computation algorithms.
107pub struct ContactManifoldsWorkspace(pub Box<dyn WorkspaceData>);
108
109impl Clone for ContactManifoldsWorkspace {
110    fn clone(&self) -> Self {
111        ContactManifoldsWorkspace(self.0.clone_dyn())
112    }
113}
114
115impl<T: WorkspaceData> From<T> for ContactManifoldsWorkspace {
116    fn from(data: T) -> Self {
117        Self(Box::new(data) as Box<dyn WorkspaceData>)
118    }
119}
120
121#[cfg(feature = "serde-serialize")]
122impl serde::Serialize for ContactManifoldsWorkspace {
123    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
124    where
125        S: serde::Serializer,
126    {
127        self.0.as_typed_workspace_data().serialize(serializer)
128    }
129}
130
131#[cfg(feature = "serde-serialize")]
132impl<'de> serde::Deserialize<'de> for ContactManifoldsWorkspace {
133    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134    where
135        D: serde::Deserializer<'de>,
136    {
137        use crate::serde::de::Error;
138        DeserializableWorkspaceData::deserialize(deserializer)?
139            .into_contact_manifold_workspace()
140            .ok_or(D::Error::custom("Cannot deserialize custom shape."))
141    }
142}