Skip to main content

dynamis_model/
constraint.rs

1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2pub enum ConstraintKind {
3    Ball,
4    Distance,
5    Revolute,
6    Prismatic,
7    Fixed,
8}
9
10#[derive(Clone, Copy, Debug)]
11pub struct ConstraintLimit {
12    pub min: f32,
13    pub max: f32,
14}
15
16#[derive(Clone, Copy, Debug)]
17pub struct ConstraintMotor {
18    pub speed: f32,
19}
20
21#[derive(Clone, Copy, Debug)]
22pub struct ConstraintSpring {
23    pub frequency: f32,
24    pub damping_ratio: f32,
25}
26
27#[derive(Clone, Copy, Debug)]
28pub struct ConstraintDesc {
29    pub kind: ConstraintKind,
30    pub anchor_a: [f32; 3],
31    pub anchor_b: [f32; 3],
32    pub axis: [f32; 3],
33    pub distance: f32,
34    pub limit: Option<ConstraintLimit>,
35    pub motor: Option<ConstraintMotor>,
36    pub spring: Option<ConstraintSpring>,
37    pub disable_collisions: bool,
38}
39
40impl ConstraintDesc {
41    fn base(kind: ConstraintKind) -> Self {
42        Self {
43            kind,
44            anchor_a: [0.0; 3],
45            anchor_b: [0.0; 3],
46            axis: [0.0, 1.0, 0.0],
47            distance: 0.0,
48            limit: None,
49            motor: None,
50            spring: None,
51            disable_collisions: true,
52        }
53    }
54
55    pub fn ball(anchor_a: [f32; 3], anchor_b: [f32; 3]) -> Self {
56        Self::base(ConstraintKind::Ball).anchors(anchor_a, anchor_b)
57    }
58
59    pub fn distance(anchor_a: [f32; 3], anchor_b: [f32; 3], distance: f32) -> Self {
60        assert!(distance >= 0.0, "constraint distance must be non-negative");
61        Self::base(ConstraintKind::Distance)
62            .anchors(anchor_a, anchor_b)
63            .with_distance(distance)
64    }
65
66    pub fn revolute(anchor_a: [f32; 3], anchor_b: [f32; 3], axis: [f32; 3]) -> Self {
67        assert!(axis != [0.0; 3], "revolute axis must be non-zero");
68        Self::base(ConstraintKind::Revolute)
69            .anchors(anchor_a, anchor_b)
70            .with_axis(axis)
71    }
72
73    pub fn prismatic(anchor_a: [f32; 3], anchor_b: [f32; 3], axis: [f32; 3]) -> Self {
74        assert!(axis != [0.0; 3], "prismatic axis must be non-zero");
75        Self::base(ConstraintKind::Prismatic)
76            .anchors(anchor_a, anchor_b)
77            .with_axis(axis)
78    }
79
80    pub fn fixed(anchor_a: [f32; 3], anchor_b: [f32; 3]) -> Self {
81        Self::base(ConstraintKind::Fixed).anchors(anchor_a, anchor_b)
82    }
83
84    pub fn anchors(mut self, anchor_a: [f32; 3], anchor_b: [f32; 3]) -> Self {
85        self.anchor_a = anchor_a;
86        self.anchor_b = anchor_b;
87        self
88    }
89
90    pub fn with_axis(mut self, axis: [f32; 3]) -> Self {
91        assert!(axis != [0.0; 3], "constraint axis must be non-zero");
92        self.axis = axis;
93        self
94    }
95
96    pub fn with_distance(mut self, distance: f32) -> Self {
97        assert!(distance >= 0.0, "constraint distance must be non-negative");
98        self.distance = distance;
99        self
100    }
101
102    pub fn limit(mut self, min: f32, max: f32) -> Self {
103        assert!(max >= min, "constraint limit max must not be below min");
104        self.limit = Some(ConstraintLimit { min, max });
105        self
106    }
107
108    pub fn motor(mut self, speed: f32) -> Self {
109        self.motor = Some(ConstraintMotor { speed });
110        self
111    }
112
113    pub fn spring(mut self, frequency: f32, damping_ratio: f32) -> Self {
114        assert!(frequency >= 0.0, "spring frequency must be non-negative");
115        assert!(
116            damping_ratio >= 0.0,
117            "spring damping ratio must be non-negative"
118        );
119        self.spring = Some(ConstraintSpring {
120            frequency,
121            damping_ratio,
122        });
123        self
124    }
125
126    pub fn disable_collisions(mut self, disable: bool) -> Self {
127        self.disable_collisions = disable;
128        self
129    }
130}
131
132#[derive(Clone, Copy, Debug, PartialEq)]
133pub struct ConstraintHandle {
134    pub id: u32,
135    pub generation: u32,
136}