avian3d/dynamics/solver/joints/
distance.rs1use crate::{dynamics::solver::xpbd::*, prelude::*};
4use bevy::{
5 ecs::{
6 entity::{EntityMapper, MapEntities},
7 reflect::ReflectMapEntities,
8 },
9 prelude::*,
10};
11
12#[derive(Component, Clone, Copy, Debug, PartialEq, Reflect)]
16#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
17#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
18#[reflect(Debug, Component, MapEntities, PartialEq)]
19pub struct DistanceJoint {
20 pub entity1: Entity,
22 pub entity2: Entity,
24 pub local_anchor1: Vector,
26 pub local_anchor2: Vector,
28 pub rest_length: Scalar,
30 pub length_limits: Option<DistanceLimit>,
32 pub damping_linear: Scalar,
34 pub damping_angular: Scalar,
36 pub lagrange: Scalar,
38 pub compliance: Scalar,
40 pub force: Vector,
42}
43
44impl XpbdConstraint<2> for DistanceJoint {
45 fn entities(&self) -> [Entity; 2] {
46 [self.entity1, self.entity2]
47 }
48
49 fn clear_lagrange_multipliers(&mut self) {
50 self.lagrange = 0.0;
51 }
52
53 fn solve(&mut self, bodies: [&mut RigidBodyQueryItem; 2], dt: Scalar) {
54 self.force = self.constrain_length(bodies, dt);
55 }
56}
57
58impl Joint for DistanceJoint {
59 fn new(entity1: Entity, entity2: Entity) -> Self {
60 Self {
61 entity1,
62 entity2,
63 local_anchor1: Vector::ZERO,
64 local_anchor2: Vector::ZERO,
65 rest_length: 0.0,
66 length_limits: None,
67 damping_linear: 0.0,
68 damping_angular: 0.0,
69 lagrange: 0.0,
70 compliance: 0.0,
71 force: Vector::ZERO,
72 }
73 }
74
75 fn with_compliance(self, compliance: Scalar) -> Self {
76 Self { compliance, ..self }
77 }
78
79 fn with_local_anchor_1(self, anchor: Vector) -> Self {
80 Self {
81 local_anchor1: anchor,
82 ..self
83 }
84 }
85
86 fn with_local_anchor_2(self, anchor: Vector) -> Self {
87 Self {
88 local_anchor2: anchor,
89 ..self
90 }
91 }
92
93 fn with_linear_velocity_damping(self, damping: Scalar) -> Self {
94 Self {
95 damping_linear: damping,
96 ..self
97 }
98 }
99
100 fn with_angular_velocity_damping(self, damping: Scalar) -> Self {
101 Self {
102 damping_angular: damping,
103 ..self
104 }
105 }
106
107 fn local_anchor_1(&self) -> Vector {
108 self.local_anchor1
109 }
110
111 fn local_anchor_2(&self) -> Vector {
112 self.local_anchor2
113 }
114
115 fn damping_linear(&self) -> Scalar {
116 self.damping_linear
117 }
118
119 fn damping_angular(&self) -> Scalar {
120 self.damping_angular
121 }
122}
123
124impl DistanceJoint {
125 fn constrain_length(&mut self, bodies: [&mut RigidBodyQueryItem; 2], dt: Scalar) -> Vector {
129 let [body1, body2] = bodies;
130 let world_r1 = *body1.rotation * self.local_anchor1;
131 let world_r2 = *body2.rotation * self.local_anchor2;
132
133 let limits = self
136 .length_limits
137 .unwrap_or(DistanceLimit::new(self.rest_length, self.rest_length));
138
139 let (dir, distance) = limits.compute_correction(
142 body1.current_position() + world_r1,
143 body2.current_position() + world_r2,
144 );
145
146 if distance.abs() < Scalar::EPSILON {
148 return Vector::ZERO;
149 }
150
151 let w1 = PositionConstraint::compute_generalized_inverse_mass(self, body1, world_r1, dir);
153 let w2 = PositionConstraint::compute_generalized_inverse_mass(self, body2, world_r2, dir);
154 let w = [w1, w2];
155
156 let delta_lagrange =
158 self.compute_lagrange_update(self.lagrange, distance, &w, self.compliance, dt);
159 self.lagrange += delta_lagrange;
160
161 self.apply_positional_lagrange_update(
163 body1,
164 body2,
165 delta_lagrange,
166 dir,
167 world_r1,
168 world_r2,
169 );
170
171 self.compute_force(self.lagrange, dir, dt)
173 }
174
175 pub fn with_limits(self, min: Scalar, max: Scalar) -> Self {
177 Self {
178 length_limits: Some(DistanceLimit::new(min, max)),
179 ..self
180 }
181 }
182
183 pub fn with_rest_length(self, rest_length: Scalar) -> Self {
185 Self {
186 rest_length,
187 ..self
188 }
189 }
190}
191
192impl PositionConstraint for DistanceJoint {}
193
194impl AngularConstraint for DistanceJoint {}
195
196impl MapEntities for DistanceJoint {
197 fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
198 self.entity1 = entity_mapper.get_mapped(self.entity1);
199 self.entity2 = entity_mapper.get_mapped(self.entity2);
200 }
201}