Skip to main content

box2d_rs/
b2_joint.rs

1use crate::b2_body::*;
2use crate::b2_draw::*;
3use crate::b2_math::*;
4use crate::b2_common::*;
5use crate::b2rs_common::UserDataType;
6use crate::b2_time_step::*;
7
8use crate::b2rs_double_linked_list::*;
9use crate::b2rs_linked_list::*;
10
11use std::cell::RefCell;
12use std::rc::{Rc, Weak};
13
14#[cfg(feature="serde_support")]
15use serde::{Serialize, Deserialize};
16
17use crate::joints::b2_distance_joint::*;
18use crate::joints::b2_friction_joint::*;
19use crate::joints::b2_gear_joint::*;
20use crate::joints::b2_motor_joint::*;
21use crate::joints::b2_mouse_joint::*;
22use crate::joints::b2_prismatic_joint::*;
23use crate::joints::b2_pulley_joint::*;
24use crate::joints::b2_revolute_joint::*;
25use crate::joints::b2_weld_joint::*;
26use crate::joints::b2_wheel_joint::*;
27
28use crate::private::dynamics::b2_joint as private;
29
30pub enum B2JointDefEnum<D: UserDataType> {
31	DistanceJoint(B2distanceJointDef<D>),
32	FrictionJoint(B2frictionJointDef<D>),
33	GearJoint(B2gearJointDef<D>),
34	MouseJoint(B2mouseJointDef<D>),
35	MotorJoint(B2motorJointDef<D>),
36	PulleyJoint(B2pulleyJointDef<D>),
37	RevoluteJoint(B2revoluteJointDef<D>),
38	PrismaticJoint(B2prismaticJointDef<D>),
39	WeldJoint(B2weldJointDef<D>),
40	WheelJoint(B2wheelJointDef<D>),
41}
42
43
44#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
45#[derive(Debug, Clone, Copy, PartialEq)]
46pub enum B2jointType {
47	EUnknownJoint,
48	EDistanceJoint,
49	EFrictionJoint,
50	EGearJoint,
51	EMotorJoint,
52	EMouseJoint,
53	EPrismaticJoint,
54	EPulleyJoint,
55	ERevoluteJoint,
56	EWeldJoint,
57	EWheelJoint,	
58}
59
60impl Default for B2jointType {
61	fn default() -> Self {
62		return B2jointType::EUnknownJoint;
63	}
64}
65
66//box2d-rs: not used yet
67// #[derive(Default, Clone, Copy, Debug)]
68// pub(crate) struct B2jacobian {
69// 	linear: B2vec2,
70// 	angular_a: f32,
71// 	angular_b: f32,
72// }
73
74pub type B2jointEdgePtr<D> = Rc<RefCell<B2jointEdge<D>>>;
75pub type B2jointEdgeWeakPtr<D> = Weak<RefCell<B2jointEdge<D>>>;
76
77impl<D: UserDataType> LinkedListNode<B2jointEdge<D>> for B2jointEdge<D> {
78	fn get_next(&self) -> Option<B2jointEdgePtr<D>> {
79		return self.next.clone();
80	}
81	fn set_next(&mut self, value: Option<B2jointEdgePtr<D>>) {
82		self.next = value;
83	}
84	fn take_next(&mut self) -> Option<B2jointEdgePtr<D>> {
85		return self.next.take();
86	}
87}
88
89impl<D: UserDataType> DoubleLinkedListNode<B2jointEdge<D>> for B2jointEdge<D> {
90	fn get_prev(&self) -> Option<B2jointEdgeWeakPtr<D>> {
91		return self.prev.clone();
92	}
93	fn set_prev(&mut self, value: Option<B2jointEdgeWeakPtr<D>>) {
94		self.prev = value;
95	}
96}
97
98/// A joint edge is used to connect bodies and joints together
99/// in a joint graph where each body is a node and each joint
100/// is an edge. A joint edge belongs to a doubly linked list
101/// maintained in each attached body. Each joint has two joint
102/// nodes, one for each attached body.
103pub struct B2jointEdge<D: UserDataType> {
104	///< provides quick access to the other body attached.
105	pub(crate) other: BodyWeakPtr<D>,
106	///< the joint
107	pub(crate) joint: B2jointWeakPtr<D>,
108	///< the previous joint edge in the body's joint list
109	pub(crate) prev: Option<B2jointEdgeWeakPtr<D>>,
110	///< the next joint edge in the body's joint list
111	pub(crate) next: Option<B2jointEdgePtr<D>>,
112}
113
114impl<D: UserDataType> Default for B2jointDef<D> {
115	fn default() -> Self {
116		return Self {
117			jtype: B2jointType::EUnknownJoint,
118			user_data: None,
119			body_a: None,
120			body_b: None,
121			collide_connected: false,
122		};
123	}
124}
125
126impl<D: UserDataType> LinkedListNode<dyn B2jointTraitDyn<D>> for dyn B2jointTraitDyn<D> {
127	fn get_next(&self) -> Option<B2jointPtr<D>> {
128		return self.get_base().m_next.clone();
129	}
130	fn set_next(&mut self, value: Option<B2jointPtr<D>>) {
131		self.get_base_mut().m_next = value;
132	}
133	fn take_next(&mut self) -> Option<B2jointPtr<D>> {
134		return self.get_base_mut().m_next.take();
135	}
136}
137
138impl<D: UserDataType> DoubleLinkedListNode<dyn B2jointTraitDyn<D>> for dyn B2jointTraitDyn<D> {
139	fn get_prev(&self) -> Option<B2jointWeakPtr<D>> {
140		return self.get_base().m_prev.clone();
141	}
142	fn set_prev(&mut self, value: Option<B2jointWeakPtr<D>>) {
143		self.get_base_mut().m_prev = value.clone();
144	}
145}
146
147/// Joint definitions are used to construct joints.
148#[derive(Clone)]
149pub struct B2jointDef<D: UserDataType> {
150	/// The joint type is set automatically for concrete joint types.
151	pub jtype: B2jointType,
152
153	/// Use this to attach application specific data to your joints.
154	pub user_data: Option<D::Joint>,
155
156	/// The first attached body.
157	pub body_a: Option<BodyPtr<D>>,
158
159	/// The second attached body.
160	pub body_b: Option<BodyPtr<D>>,
161
162	/// Set this flag to true if the attached bodies should collide.
163	pub collide_connected: bool,
164}
165
166pub type B2jointPtr<D> = Rc<RefCell<dyn B2jointTraitDyn<D>>>;
167pub type B2jointWeakPtr<D> = Weak<RefCell<dyn B2jointTraitDyn<D>>>;
168
169
170/// Utility to compute linear stiffness values from frequency and damping ratio
171pub fn b2_linear_stiffness<D: UserDataType>(stiffness: &mut f32, damping: &mut f32,
172	frequency_hertz: f32, damping_ratio: f32,
173	body_a: BodyPtr<D>, body_b: BodyPtr<D>)
174{
175	private::b2_linear_stiffness(stiffness, damping, frequency_hertz, damping_ratio, body_a, body_b);
176}
177
178/// Utility to compute rotational stiffness values frequency and damping ratio
179pub fn b2_angular_stiffness<D: UserDataType>(stiffness: &mut f32, damping: &mut f32,
180	frequency_hertz: f32, damping_ratio: f32,
181	body_a: BodyPtr<D>, body_b: BodyPtr<D>)
182{
183	private::b2_angular_stiffness(stiffness, damping, frequency_hertz, damping_ratio, body_a, body_b);
184}
185
186
187/// The base joint class. Joints are used to constraint two bodies together in
188/// various fashions. Some joints also feature limits and motors.
189impl<D: UserDataType> B2joint<D> {
190	/// Get the type of the concrete joint.
191	pub fn get_type(&self) -> B2jointType {
192		return self.m_type;
193	}
194
195	/// Get the first body attached to this joint.
196	pub fn get_body_a(&self) -> BodyPtr<D> {
197		return self.m_body_a.clone();
198	}
199
200	/// Get the second body attached to this joint.
201	pub fn get_body_b(&self) -> BodyPtr<D> {
202		return self.m_body_b.clone();
203	}
204
205	/// Get the next joint the world joint list.
206	pub fn get_next(&self) -> B2jointPtr<D> {
207		return self.m_next.as_ref().unwrap().clone();
208	}
209
210	/// Get the user data pointer.
211	pub fn get_user_data(&self) -> Option<D::Joint> {
212		return self.m_user_data.clone();
213	}
214
215	/// Set the user data pointer.
216	pub fn set_user_data(&mut self, data: D::Joint) {
217		self.m_user_data = Some(data);
218	}
219
220	/// Short-cut function to determine if either body is enabled.
221	pub fn is_enabled(&self) -> bool {
222		return private::is_enabled(self);
223	}
224
225	/// Get collide connected.
226	/// Note: modifying the collide connect flag won't work correctly because
227	/// the flag is only checked when fixture AABBs begin to overlap.
228	pub fn get_collide_connected(&self) -> bool {
229		return self.m_collide_connected;
230	}
231
232	// protected:
233
234	// 	static B2joint* create(const B2jointDef* def, b2BlockAllocator* allocator);
235	pub(crate) fn create(def: &B2JointDefEnum<D>) -> B2jointPtr<D> {
236		return private::create(def);
237	}
238	pub(crate) fn new(def: &B2jointDef<D>) -> B2joint<D> {
239		return private::new(def);
240	}
241}
242
243pub trait B2jointTraitDyn<D: UserDataType>: ToDerivedJoint<D> {
244	fn get_base(&self) -> &B2joint<D>;
245	fn get_base_mut(&mut self) -> &mut B2joint<D>;
246	/// Get the anchor point on body_a in world coordinates.
247	fn get_anchor_a(&self) -> B2vec2;
248
249	/// Get the anchor point on body_b in world coordinates.
250	fn get_anchor_b(&self) -> B2vec2;
251
252	/// Get the reaction force on body_b at the joint anchor in Newtons.
253	fn get_reaction_force(&self, inv_dt: f32) -> B2vec2;
254
255	/// Get the reaction torque on body_b in n*m.
256	fn get_reaction_torque(&self, inv_dt: f32) -> f32;
257
258	/// Shift the origin for any points stored in world coordinates.
259	fn shift_origin(&mut self, new_origin: B2vec2) {
260		b2_not_used(new_origin);
261	}
262
263	/// Debug draw this joint
264	fn draw(&self, draw: &mut dyn B2drawTrait) {
265		private::draw(self, draw);
266	} 
267
268	fn init_velocity_constraints(
269		&mut self,
270		data: &B2solverData,
271		positions: &[B2position],
272		velocities: &mut [B2velocity],
273	);
274	fn solve_velocity_constraints(
275		&mut self,
276		data: &B2solverData,
277		velocities: &mut [B2velocity],
278	);
279
280	// This returns true if the position errors are within tolerance.
281	fn solve_position_constraints(
282		&mut self,
283		data: &B2solverData,
284		positions: &mut [B2position],
285	) -> bool;
286}
287
288pub trait ToDerivedJoint<D: UserDataType> {
289	fn as_derived(&self) -> JointAsDerived<D>;
290	fn as_derived_mut(&mut self) -> JointAsDerivedMut<D>;
291}
292
293pub enum JointAsDerived<'a, D: UserDataType> {
294	EDistanceJoint(&'a B2distanceJoint<D>),
295	EFrictionJoint(&'a B2frictionJoint<D>),
296	EGearJoint(&'a B2gearJoint<D>),
297	EMouseJoint(&'a B2mouseJoint<D>),
298	EMotorJoint(&'a B2motorJoint<D>),
299	EPulleyJoint(&'a B2pulleyJoint<D>),
300	ERevoluteJoint(&'a B2revoluteJoint<D>),
301	EPrismaticJoint(&'a B2prismaticJoint<D>),
302	EWeldJoint(&'a B2weldJoint<D>),
303	EWheelJoint(&'a B2wheelJoint<D>),
304}
305
306pub enum JointAsDerivedMut<'a, D: UserDataType> {
307	EDistanceJoint(&'a mut B2distanceJoint<D>),
308	EFrictionJoint(&'a mut B2frictionJoint<D>),
309	EGearJoint(&'a mut B2gearJoint<D>),
310	EMouseJoint(&'a mut B2mouseJoint<D>),
311	EMotorJoint(&'a mut B2motorJoint<D>),
312	EPulleyJoint(&'a mut B2pulleyJoint<D>),
313	ERevoluteJoint(&'a mut B2revoluteJoint<D>),
314	EPrismaticJoint(&'a mut B2prismaticJoint<D>),
315	EWeldJoint(&'a mut B2weldJoint<D>),
316	EWheelJoint(&'a mut B2wheelJoint<D>),
317}
318
319#[derive(Clone)]
320pub struct B2joint<D: UserDataType> {
321	// protected:
322	pub(crate) m_type: B2jointType,
323	pub(crate) m_prev: Option<B2jointWeakPtr<D>>,
324	pub(crate) m_next: Option<B2jointPtr<D>>,
325	pub(crate) m_edge_a: Option<B2jointEdgePtr<D>>,
326	pub(crate) m_edge_b: Option<B2jointEdgePtr<D>>,
327	pub(crate) m_body_a: BodyPtr<D>,
328	pub(crate) m_body_b: BodyPtr<D>,
329
330	pub(crate) m_index: i32,
331
332	pub(crate) m_island_flag: bool,
333	pub(crate) m_collide_connected: bool,
334
335	pub(crate) m_user_data: Option<D::Joint>,
336}