1use na::{DVector, RealField};
2use ncollide::query::ContactId;
3
4use crate::counters::Counters;
5use crate::detection::ColliderContactManifold;
6use crate::joint::{JointConstraint, JointConstraintSet};
7use crate::material::MaterialsCoefficientsTable;
8use crate::object::{BodyHandle, BodySet, ColliderHandle, ColliderSet};
9use crate::solver::{
10 ConstraintSet, ContactModel, IntegrationParameters, NonlinearSORProx, SORProx,
11};
12
13pub struct MoreauJeanSolver<N: RealField + Copy, Handle: BodyHandle, CollHandle: ColliderHandle> {
15 jacobians: Vec<N>,
16 mj_lambda_vel: DVector<N>,
18 ext_vels: DVector<N>,
19 contact_model: Box<dyn ContactModel<N, Handle, CollHandle>>,
20 contact_constraints: ConstraintSet<N, Handle, CollHandle, ContactId>,
21 joint_constraints: ConstraintSet<N, Handle, CollHandle, usize>,
22 internal_constraints: Vec<Handle>,
23}
24
25impl<N: RealField + Copy, Handle: BodyHandle, CollHandle: ColliderHandle>
26 MoreauJeanSolver<N, Handle, CollHandle>
27{
28 pub fn new(contact_model: Box<dyn ContactModel<N, Handle, CollHandle>>) -> Self {
30 MoreauJeanSolver {
31 jacobians: Vec::new(),
32 mj_lambda_vel: DVector::zeros(0),
33 ext_vels: DVector::zeros(0),
34 contact_model,
35 contact_constraints: ConstraintSet::new(),
36 joint_constraints: ConstraintSet::new(),
37 internal_constraints: Vec::new(),
38 }
39 }
40
41 pub fn set_contact_model(&mut self, model: Box<dyn ContactModel<N, Handle, CollHandle>>) {
43 self.contact_model = model
44 }
45
46 pub fn step<
48 Colliders: ColliderSet<N, Handle, Handle = CollHandle>,
49 Constraints: JointConstraintSet<N, Handle>,
50 >(
51 &mut self,
52 counters: &mut Counters,
53 bodies: &mut dyn BodySet<N, Handle = Handle>,
54 colliders: &Colliders,
55 joints: &mut Constraints,
56 manifolds: &[ColliderContactManifold<N, Handle, CollHandle>],
57 island: &[Handle],
58 island_joints: &[Constraints::Handle],
59 parameters: &IntegrationParameters<N>,
60 coefficients: &MaterialsCoefficientsTable<N>,
61 ) {
62 counters.assembly_started();
63 self.assemble_system(
64 counters,
65 parameters,
66 coefficients,
67 bodies,
68 joints,
69 manifolds,
70 island,
71 island_joints,
72 );
73 counters.assembly_completed();
74 counters.set_nconstraints(
75 self.contact_constraints.velocity.len() + self.joint_constraints.velocity.len(),
76 );
77
78 counters.velocity_resolution_started();
79 self.solve_velocity_constraints(parameters, bodies);
80 self.cache_impulses(parameters, bodies, joints, island_joints);
81 counters.velocity_resolution_completed();
82
83 counters.velocity_update_started();
84 self.update_velocities_and_integrate(parameters, bodies, island);
85 counters.velocity_update_completed();
86
87 counters.position_resolution_started();
88 self.solve_position_constraints(parameters, bodies, colliders, joints, island_joints);
89 counters.position_resolution_completed();
90 }
91
92 pub fn step_ccd<
95 Colliders: ColliderSet<N, Handle, Handle = CollHandle>,
96 Constraints: JointConstraintSet<N, Handle>,
97 >(
98 &mut self,
99 counters: &mut Counters,
100 bodies: &mut dyn BodySet<N, Handle = Handle>,
101 colliders: &Colliders,
102 joints: &mut Constraints,
103 manifolds: &[ColliderContactManifold<N, Handle, CollHandle>],
104 ccd_bodies: &[Handle],
105 island: &[Handle],
106 island_joints: &[Constraints::Handle],
107 parameters: &IntegrationParameters<N>,
108 coefficients: &MaterialsCoefficientsTable<N>,
109 ) {
110 self.assemble_system(
111 counters,
112 parameters,
113 coefficients,
114 bodies,
115 joints,
116 manifolds,
117 island,
118 island_joints,
119 );
120 self.solve_position_constraints(parameters, bodies, colliders, joints, island_joints);
121 for ccd_body in ccd_bodies {
122 bodies.get_mut(*ccd_body).unwrap().validate_advancement();
123 }
124
125 self.solve_velocity_constraints(parameters, bodies);
126 self.update_velocities_and_integrate(parameters, bodies, island);
127 }
128
129 fn assemble_system<Constraints: JointConstraintSet<N, Handle>>(
130 &mut self,
131 counters: &mut Counters,
132 parameters: &IntegrationParameters<N>,
133 coefficients: &MaterialsCoefficientsTable<N>,
134 bodies: &mut dyn BodySet<N, Handle = Handle>,
135 joints: &mut Constraints,
136 manifolds: &[ColliderContactManifold<N, Handle, CollHandle>],
137 island: &[Handle],
138 island_joints: &[Constraints::Handle],
139 ) {
140 self.internal_constraints.clear();
141 let mut system_ndofs = 0;
142
143 for handle in island {
144 let body = try_continue!(bodies.get_mut(*handle));
145 body.set_companion_id(system_ndofs);
146 let ndofs = body.status_dependent_ndofs();
147 assert!(
148 ndofs != 0,
149 "Internal error: an island cannot contain a non-dynamic body."
150 );
151
152 system_ndofs += ndofs;
153
154 if ndofs != 0 && body.has_active_internal_constraints() {
155 self.internal_constraints.push(*handle)
156 }
157 }
158
159 self.resize_buffers(system_ndofs);
160 self.contact_constraints.clear();
161 self.joint_constraints.clear();
162
163 for handle in island {
167 let body = try_continue!(bodies.get(*handle));
168 let id = body.companion_id();
169 let accs = body.generalized_acceleration();
170
171 self.ext_vels
172 .rows_mut(id, accs.len())
173 .axpy(parameters.dt(), &accs, N::zero());
174 }
175
176 let mut jacobian_sz = 0;
182 let mut ground_jacobian_sz = 0;
183
184 for handle in island_joints {
185 if let Some(joint) = joints.get(*handle) {
186 let (b1, b2) = joint.anchors();
187 if let (Some(body1), Some(body2)) = (bodies.get(b1.0), bodies.get(b2.0)) {
188 let ndofs1 = body1.status_dependent_ndofs();
189 let ndofs2 = body2.status_dependent_ndofs();
190
191 let nconstraints = joint.num_velocity_constraints();
192 let sz = nconstraints * 2 * (ndofs1 + ndofs2);
193
194 if ndofs1 == 0 || ndofs2 == 0 {
195 ground_jacobian_sz += sz;
196 } else {
197 jacobian_sz += sz;
198 }
199 }
200 }
201 }
202
203 for m in manifolds {
204 let ndofs1 = try_continue!(bodies.get(m.body1())).status_dependent_ndofs();
205 let ndofs2 = try_continue!(bodies.get(m.body2())).status_dependent_ndofs();
206 let sz = self.contact_model.num_velocity_constraints(m) * (ndofs1 + ndofs2) * 2;
207
208 if ndofs1 == 0 || ndofs2 == 0 {
209 ground_jacobian_sz += sz;
210 } else {
211 jacobian_sz += sz;
212 }
213 }
214
215 self.jacobians
216 .resize(jacobian_sz + ground_jacobian_sz, N::zero());
217
218 let mut j_id = 0;
224 let mut ground_j_id = jacobian_sz;
225
226 for handle in island_joints {
227 if let Some(joint) = joints.get_mut(*handle) {
228 joint.velocity_constraints(
229 parameters,
230 bodies,
231 &self.ext_vels,
232 &mut ground_j_id,
233 &mut j_id,
234 &mut self.jacobians,
235 &mut self.joint_constraints.velocity,
236 );
237 }
238 }
239
240 counters.custom_started();
241 self.contact_model.constraints(
242 parameters,
243 coefficients,
244 bodies,
245 &self.ext_vels,
246 manifolds,
247 &mut ground_j_id,
248 &mut j_id,
249 &mut self.jacobians,
250 &mut self.contact_constraints,
251 );
252 counters.custom_completed();
253
254 for handle in &self.internal_constraints {
255 if let Some(body) = bodies.get_mut(*handle) {
256 let ext_vels = self.ext_vels.rows(body.companion_id(), body.ndofs());
257 body.setup_internal_velocity_constraints(&ext_vels, parameters);
258 }
259 }
260 }
261
262 fn solve_velocity_constraints(
263 &mut self,
264 parameters: &IntegrationParameters<N>,
265 bodies: &mut dyn BodySet<N, Handle = Handle>,
266 ) {
267 SORProx::solve(
268 bodies,
269 &mut self.contact_constraints.velocity,
270 &mut self.joint_constraints.velocity,
271 &self.internal_constraints,
272 &mut self.mj_lambda_vel,
273 &self.jacobians,
274 parameters.max_velocity_iterations,
275 );
276 }
277
278 fn solve_position_constraints<
279 Colliders: ColliderSet<N, Handle, Handle = CollHandle>,
280 Constraints: JointConstraintSet<N, Handle>,
281 >(
282 &mut self,
283 parameters: &IntegrationParameters<N>,
284 bodies: &mut dyn BodySet<N, Handle = Handle>,
285 colliders: &Colliders,
286 joints: &mut Constraints,
287 island_joints: &[Constraints::Handle],
288 ) {
289 let mut jacobians = self.jacobians.clone();
293 NonlinearSORProx::solve(
294 parameters,
295 bodies,
296 colliders,
297 &mut self.contact_constraints.position.unilateral,
298 joints,
299 island_joints,
300 &self.internal_constraints,
301 &mut jacobians,
302 parameters.max_position_iterations,
303 );
304 }
305
306 fn cache_impulses<Constraints: JointConstraintSet<N, Handle>>(
307 &mut self,
308 parameters: &IntegrationParameters<N>,
309 _bodies: &mut dyn BodySet<N, Handle = Handle>,
310 joints: &mut Constraints,
311 island_joints: &[Constraints::Handle],
312 ) {
313 self.contact_model.cache_impulses(&self.contact_constraints);
314
315 for handle in island_joints {
316 if let Some(j) = joints.get_mut(*handle) {
317 j.cache_impulses(&self.joint_constraints.velocity, parameters.inv_dt());
318 }
319 }
320 }
321
322 fn resize_buffers(&mut self, ndofs: usize) {
323 self.mj_lambda_vel = DVector::zeros(ndofs);
325 self.ext_vels = DVector::zeros(ndofs);
326 }
327
328 fn update_velocities_and_integrate(
329 &mut self,
330 parameters: &IntegrationParameters<N>,
331 bodies: &mut dyn BodySet<N, Handle = Handle>,
332 island: &[Handle],
333 ) {
334 for handle in island {
335 let body = try_continue!(bodies.get_mut(*handle));
336 let id = body.companion_id();
337 let ndofs = body.ndofs();
338
339 {
340 let mut mb_vels = body.generalized_velocity_mut();
341 mb_vels += self.ext_vels.rows(id, ndofs);
342 mb_vels += self.mj_lambda_vel.rows(id, ndofs);
343 }
344
345 body.integrate(parameters);
346 }
347 }
348}