dynamis_model/
constraint.rs1#[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}