1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#[cfg(feature = "dim3")]
use crate::dynamics::RevoluteJoint;
use crate::dynamics::{BallJoint, FixedJoint, JointHandle, PrismaticJoint, RigidBodyHandle};

#[derive(Copy, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
/// An enum grouping all possible types of joints.
pub enum JointParams {
    /// A Ball joint that removes all relative linear degrees of freedom between the affected bodies.
    BallJoint(BallJoint),
    /// A fixed joint that removes all relative degrees of freedom between the affected bodies.
    FixedJoint(FixedJoint),
    /// A prismatic joint that removes all degrees of degrees of freedom between the affected
    /// bodies except for the translation along one axis.
    PrismaticJoint(PrismaticJoint),
    #[cfg(feature = "dim3")]
    /// A revolute joint that removes all degrees of degrees of freedom between the affected
    /// bodies except for the translation along one axis.
    RevoluteJoint(RevoluteJoint),
    // GenericJoint(GenericJoint),
}

impl JointParams {
    /// An integer identifier for each type of joint.
    pub fn type_id(&self) -> usize {
        match self {
            JointParams::BallJoint(_) => 0,
            JointParams::FixedJoint(_) => 1,
            JointParams::PrismaticJoint(_) => 2,
            // JointParams::GenericJoint(_) => 3,
            #[cfg(feature = "dim3")]
            JointParams::RevoluteJoint(_) => 4,
        }
    }

    /// Gets a reference to the underlying ball joint, if `self` is one.
    pub fn as_ball_joint(&self) -> Option<&BallJoint> {
        if let JointParams::BallJoint(j) = self {
            Some(j)
        } else {
            None
        }
    }

    /// Gets a reference to the underlying fixed joint, if `self` is one.
    pub fn as_fixed_joint(&self) -> Option<&FixedJoint> {
        if let JointParams::FixedJoint(j) = self {
            Some(j)
        } else {
            None
        }
    }

    // /// Gets a reference to the underlying generic joint, if `self` is one.
    // pub fn as_generic_joint(&self) -> Option<&GenericJoint> {
    //     if let JointParams::GenericJoint(j) = self {
    //         Some(j)
    //     } else {
    //         None
    //     }
    // }

    /// Gets a reference to the underlying prismatic joint, if `self` is one.
    pub fn as_prismatic_joint(&self) -> Option<&PrismaticJoint> {
        if let JointParams::PrismaticJoint(j) = self {
            Some(j)
        } else {
            None
        }
    }

    /// Gets a reference to the underlying revolute joint, if `self` is one.
    #[cfg(feature = "dim3")]
    pub fn as_revolute_joint(&self) -> Option<&RevoluteJoint> {
        if let JointParams::RevoluteJoint(j) = self {
            Some(j)
        } else {
            None
        }
    }
}

impl From<BallJoint> for JointParams {
    fn from(j: BallJoint) -> Self {
        JointParams::BallJoint(j)
    }
}

impl From<FixedJoint> for JointParams {
    fn from(j: FixedJoint) -> Self {
        JointParams::FixedJoint(j)
    }
}

// impl From<GenericJoint> for JointParams {
//     fn from(j: GenericJoint) -> Self {
//         JointParams::GenericJoint(j)
//     }
// }

#[cfg(feature = "dim3")]
impl From<RevoluteJoint> for JointParams {
    fn from(j: RevoluteJoint) -> Self {
        JointParams::RevoluteJoint(j)
    }
}

impl From<PrismaticJoint> for JointParams {
    fn from(j: PrismaticJoint) -> Self {
        JointParams::PrismaticJoint(j)
    }
}

#[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.
    pub body1: RigidBodyHandle,
    /// Handle to the second body attached to this joint.
    pub body2: RigidBodyHandle,
    // A joint needs to know its handle to simplify its removal.
    pub(crate) handle: JointHandle,
    #[cfg(feature = "parallel")]
    pub(crate) constraint_index: usize,
    #[cfg(feature = "parallel")]
    pub(crate) position_constraint_index: usize,
    /// The joint geometric parameters and impulse.
    pub params: JointParams,
}

impl Joint {
    /// Can this joint use SIMD-accelerated constraint formulations?
    pub fn supports_simd_constraints(&self) -> bool {
        match &self.params {
            JointParams::PrismaticJoint(joint) => joint.supports_simd_constraints(),
            JointParams::FixedJoint(joint) => joint.supports_simd_constraints(),
            JointParams::BallJoint(joint) => joint.supports_simd_constraints(),
            #[cfg(feature = "dim3")]
            JointParams::RevoluteJoint(joint) => joint.supports_simd_constraints(),
        }
    }
}