nphysics3d/object/
rigid_body.rs

1use na::{DVectorSlice, DVectorSliceMut, RealField};
2use std::any::Any;
3
4use crate::math::{
5    Dim, Force, ForceType, Inertia, Isometry, Point, Rotation, SpatialVector, Translation, Vector,
6    Velocity, DIM, SPATIAL_DIM,
7};
8use crate::object::{
9    ActivationStatus, Body, BodyPart, BodyPartMotion, BodyStatus, BodyUpdateStatus,
10};
11use crate::solver::{ForceDirection, IntegrationParameters};
12
13use crate::utils::{UserData, UserDataBox};
14use ncollide::interpolation::{
15    ConstantLinearVelocityRigidMotion, ConstantVelocityRigidMotion, RigidMotion,
16};
17use ncollide::shape::DeformationsType;
18
19#[cfg(feature = "dim3")]
20use crate::math::AngularVector;
21#[cfg(feature = "dim3")]
22use crate::utils::GeneralizedCross;
23
24/// A rigid body.
25#[derive(Debug)]
26pub struct RigidBody<N: RealField + Copy> {
27    position0: Isometry<N>,
28    position: Isometry<N>,
29    velocity: Velocity<N>,
30    local_inertia: Inertia<N>,
31    inertia: Inertia<N>,
32    local_com: Point<N>,
33    com: Point<N>,
34    augmented_mass: Inertia<N>,
35    inv_augmented_mass: Inertia<N>,
36    external_forces: Force<N>,
37    acceleration: Velocity<N>,
38    linear_damping: N,
39    angular_damping: N,
40    max_linear_velocity: N,
41    max_angular_velocity: N,
42    status: BodyStatus,
43    gravity_enabled: bool,
44    linear_motion_interpolation_enabled: bool,
45    activation: ActivationStatus<N>,
46    jacobian_mask: SpatialVector<N>,
47    companion_id: usize,
48    update_status: BodyUpdateStatus,
49    user_data: Option<Box<dyn Any + Send + Sync>>,
50}
51
52impl<N: RealField + Copy> RigidBody<N> {
53    /// Create a new rigid body with the specified position.
54    fn new(position: Isometry<N>) -> Self {
55        let inertia = Inertia::zero();
56        let com = Point::from(position.translation.vector);
57
58        RigidBody {
59            position0: position,
60            position,
61            velocity: Velocity::zero(),
62            local_inertia: inertia,
63            inertia,
64            local_com: Point::origin(),
65            com,
66            augmented_mass: inertia,
67            inv_augmented_mass: inertia.inverse(),
68            external_forces: Force::zero(),
69            acceleration: Velocity::zero(),
70            linear_damping: N::zero(),
71            angular_damping: N::zero(),
72            max_linear_velocity: N::max_value(),
73            max_angular_velocity: N::max_value(),
74            status: BodyStatus::Dynamic,
75            gravity_enabled: true,
76            linear_motion_interpolation_enabled: false,
77            activation: ActivationStatus::new_active(),
78            jacobian_mask: SpatialVector::repeat(N::one()),
79            companion_id: 0,
80            update_status: BodyUpdateStatus::all(),
81            user_data: None,
82        }
83    }
84
85    user_data_accessors!();
86
87    /// Check if linear motion interpolation is enabled for CCD.
88    ///
89    /// If this is disabled, non-linear interpolation will be used.
90    #[inline]
91    pub fn linear_motion_interpolation_enabled(&self) -> bool {
92        self.linear_motion_interpolation_enabled
93    }
94
95    /// Enable linear motion interpolation for CCD.
96    ///
97    /// If this is disabled, non-linear interpolation will be used.
98    #[inline]
99    pub fn enable_linear_motion_interpolation(&mut self, enabled: bool) {
100        self.linear_motion_interpolation_enabled = enabled
101    }
102
103    /// Mark some translational degrees of freedom as kinematic.
104    pub fn set_translations_kinematic(&mut self, is_kinematic: Vector<bool>) {
105        self.update_status.set_status_changed(true);
106        for i in 0..DIM {
107            self.jacobian_mask[i] = if is_kinematic[i] { N::zero() } else { N::one() }
108        }
109    }
110
111    /// Mark some rotational degrees of freedom as kinematic.
112    #[cfg(feature = "dim3")]
113    pub fn set_rotations_kinematic(&mut self, is_kinematic: Vector<bool>) {
114        self.update_status.set_status_changed(true);
115        self.jacobian_mask[3] = if is_kinematic.x { N::zero() } else { N::one() };
116        self.jacobian_mask[4] = if is_kinematic.y { N::zero() } else { N::one() };
117        self.jacobian_mask[5] = if is_kinematic.z { N::zero() } else { N::one() };
118    }
119
120    /// Mark rotations as kinematic.
121    #[cfg(feature = "dim2")]
122    pub fn set_rotations_kinematic(&mut self, is_kinematic: bool) {
123        self.update_status.set_status_changed(true);
124        self.jacobian_mask[2] = if is_kinematic { N::zero() } else { N::one() };
125    }
126
127    /// Flags indicating which translational degrees of freedoms are kinematic.
128    pub fn kinematic_translations(&self) -> Vector<bool> {
129        self.jacobian_mask.fixed_rows::<DIM>(0).map(|m| m.is_zero())
130    }
131
132    /// Flags indicating which rotational degrees of freedoms are kinematic.
133    #[cfg(feature = "dim3")]
134    pub fn kinematic_rotations(&self) -> Vector<bool> {
135        Vector::new(
136            self.jacobian_mask[3].is_zero(),
137            self.jacobian_mask[4].is_zero(),
138            self.jacobian_mask[5].is_zero(),
139        )
140    }
141
142    /// Flags indicating if rotations are kinematic.
143    #[cfg(feature = "dim2")]
144    pub fn kinematic_rotations(&self) -> bool {
145        self.jacobian_mask[2].is_zero()
146    }
147
148    /// Disable all rotations of this rigid body.
149    ///
150    /// This is the same as setting all the rotations of this rigid body as kinematic and setting
151    /// its angular velocity to zero. The rotations will still be controllable at the velocity level
152    /// by the user afterwards.
153    pub fn disable_all_rotations(&mut self) {
154        self.update_status.set_velocity_changed(true);
155        #[cfg(feature = "dim3")]
156        {
157            self.set_rotations_kinematic(Vector::repeat(true));
158            self.velocity.angular = Vector::zeros();
159        }
160        #[cfg(feature = "dim2")]
161        {
162            self.set_rotations_kinematic(true);
163            self.velocity.angular = N::zero();
164        }
165    }
166
167    /// Enable all rotations for this rigid body.
168    ///
169    /// This is the same as setting all the rotations of this rigid body as non-kinematic.
170    pub fn enable_all_rotations(&mut self) {
171        #[cfg(feature = "dim3")]
172        {
173            self.set_rotations_kinematic(Vector::repeat(false))
174        }
175        #[cfg(feature = "dim2")]
176        {
177            self.set_rotations_kinematic(false)
178        }
179    }
180
181    /// Disable all translations of this rigid body.
182    ///
183    /// This is the same as setting all the translations of this rigid body as kinematic and setting
184    /// its linear velocity to zero. The translations will still be controllable at the velocity level
185    /// by the user afterwards.
186    pub fn disable_all_translations(&mut self) {
187        self.update_status.set_velocity_changed(true);
188        self.set_translations_kinematic(Vector::repeat(true));
189        self.velocity.linear = Vector::zeros();
190    }
191
192    /// Enable all translations for this rigid body.
193    ///
194    /// This is the same as setting all the translations of this rigid body as non-kinematic.
195    pub fn enable_all_translations(&mut self) {
196        self.set_translations_kinematic(Vector::repeat(false))
197    }
198
199    /// Sets the linear damping coefficient of this rigid body.
200    ///
201    /// Linear damping will make the rigid body loose linear velocity automatically velocity at each timestep.
202    /// There is no damping by default.
203    pub fn set_linear_damping(&mut self, damping: N) {
204        self.linear_damping = damping
205    }
206
207    /// The linear damping coefficient of this rigid body.
208    pub fn linear_damping(&self) -> N {
209        self.linear_damping
210    }
211
212    /// Sets the angular damping coefficient of this rigid body.
213    ///
214    /// Angular damping will make the rigid body loose angular velocity automatically velocity at each timestep.
215    /// There is no damping by default.
216    pub fn set_angular_damping(&mut self, damping: N) {
217        self.angular_damping = damping
218    }
219
220    /// The angular damping coefficient of this rigid body.
221    pub fn angular_damping(&self) -> N {
222        self.angular_damping
223    }
224
225    /// Caps the linear velocity of this rigid body to the given maximum.
226    ///
227    /// This will prevent a rigid body from having a linear velocity with magnitude greater than `max_vel`.
228    pub fn set_max_linear_velocity(&mut self, max_vel: N) {
229        self.max_linear_velocity = max_vel
230    }
231
232    /// The maximum allowed linear velocity of this rigid body.
233    pub fn max_linear_velocity(&self) -> N {
234        self.max_linear_velocity
235    }
236
237    /// Caps the angular velocity of this rigid body to the given maximum.
238    ///
239    /// This will prevent a rigid body from having a angular velocity with magnitude greater than `max_vel`.
240    pub fn set_max_angular_velocity(&mut self, max_vel: N) {
241        self.max_angular_velocity = max_vel
242    }
243
244    /// The maximum allowed angular velocity of this rigid body.
245    pub fn max_angular_velocity(&self) -> N {
246        self.max_angular_velocity
247    }
248
249    /// Mutable information regarding activation and deactivation (sleeping) of this rigid body.
250    #[inline]
251    pub fn activation_status_mut(&mut self) -> &mut ActivationStatus<N> {
252        &mut self.activation
253    }
254
255    /// Set the center of mass of this rigid body, expressed in its local space.
256    #[inline]
257    pub fn set_local_center_of_mass(&mut self, local_com: Point<N>) {
258        self.update_status.set_local_com_changed(true);
259        self.local_com = local_com;
260    }
261
262    fn update_inertia_from_local_inertia(&mut self) {
263        // Needed for 2D because the inertia is not updated on the `update_dynamics`.
264        self.inertia = self.local_inertia.transformed(&self.position);
265        self.augmented_mass = self.inertia;
266        self.inv_augmented_mass = self.inertia.inverse();
267    }
268
269    /// Set the local inertia of this rigid body, expressed in its local space.
270    #[inline]
271    pub fn set_local_inertia(&mut self, local_inertia: Inertia<N>) {
272        self.update_status.set_local_inertia_changed(true);
273        self.local_inertia = local_inertia;
274        self.update_inertia_from_local_inertia();
275    }
276
277    /// Set the mass of this rigid body.
278    #[inline]
279    pub fn set_mass(&mut self, mass: N) {
280        self.update_status.set_local_inertia_changed(true);
281        self.local_inertia.linear = mass;
282        self.update_inertia_from_local_inertia();
283    }
284
285    /// Set the angular inertia of this rigid body, expressed in its local space.
286    #[inline]
287    #[cfg(feature = "dim2")]
288    pub fn set_angular_inertia(&mut self, angular_inertia: N) {
289        self.update_status.set_local_inertia_changed(true);
290        self.local_inertia.angular = angular_inertia;
291        self.update_inertia_from_local_inertia();
292    }
293
294    /// Set the angular inertia of this rigid body, expressed in its local space.
295    #[inline]
296    #[cfg(feature = "dim3")]
297    pub fn set_angular_inertia(&mut self, angular_inertia: na::Matrix3<N>) {
298        self.update_status.set_local_inertia_changed(true);
299        self.local_inertia.angular = angular_inertia;
300        self.update_inertia_from_local_inertia();
301    }
302
303    /// Sets the position of this rigid body.
304    #[inline]
305    pub fn set_position(&mut self, mut pos: Isometry<N>) {
306        // Systematic renormalization is necessary with
307        // fixed-points numbers to prevent errors from
308        // increasing quickly.
309        #[cfg(feature = "improved_fixed_point_support")]
310        let _ = pos.rotation.renormalize();
311
312        self.update_status.set_position_changed(true);
313        self.position = pos;
314        self.com = pos * self.local_com;
315    }
316
317    /// Set the velocity of this rigid body.
318    #[inline]
319    pub fn set_velocity(&mut self, vel: Velocity<N>) {
320        self.update_status.set_velocity_changed(true);
321        self.velocity = vel;
322    }
323
324    /// Set the linear velocity of this rigid body.
325    #[inline]
326    pub fn set_linear_velocity(&mut self, vel: Vector<N>) {
327        self.update_status.set_velocity_changed(true);
328        self.velocity.linear = vel;
329    }
330
331    #[cfg(feature = "dim2")]
332    /// Set the angular velocity of this rigid body.
333    #[inline]
334    pub fn set_angular_velocity(&mut self, vel: N) {
335        self.update_status.set_velocity_changed(true);
336        self.velocity.angular = vel;
337    }
338
339    #[cfg(feature = "dim3")]
340    /// Set the angular velocity of this rigid body.
341    #[inline]
342    pub fn set_angular_velocity(&mut self, vel: AngularVector<N>) {
343        self.update_status.set_velocity_changed(true);
344        self.velocity.angular = vel;
345    }
346
347    /// The augmented mass (inluding gyroscropic terms) in world-space of this rigid body.
348    #[inline]
349    pub fn augmented_mass(&self) -> &Inertia<N> {
350        &self.augmented_mass
351    }
352
353    /// The inverse augmented mass (inluding gyroscropic terms) in world-space of this rigid body.
354    #[inline]
355    pub fn inv_augmented_mass(&self) -> &Inertia<N> {
356        &self.inv_augmented_mass
357    }
358
359    /// The position of this rigid body.
360    #[inline]
361    pub fn position(&self) -> &Isometry<N> {
362        &self.position
363    }
364
365    /// The velocity of this rigid body.
366    #[inline]
367    pub fn velocity(&self) -> &Velocity<N> {
368        &self.velocity
369    }
370
371    fn displacement_wrt_com(&self, disp: &Velocity<N>) -> Isometry<N> {
372        let shift = Translation::from(self.com.coords);
373        shift * disp.to_transform() * shift.inverse()
374    }
375
376    #[inline]
377    fn apply_displacement(&mut self, disp: &Velocity<N>) {
378        let disp = self.displacement_wrt_com(disp);
379        let new_pos = disp * self.position;
380        self.set_position(new_pos);
381    }
382}
383
384impl<N: RealField + Copy> Body<N> for RigidBody<N> {
385    #[inline]
386    fn activation_status(&self) -> &ActivationStatus<N> {
387        &self.activation
388    }
389
390    #[inline]
391    fn activate_with_energy(&mut self, energy: N) {
392        self.activation.set_energy(energy)
393    }
394
395    #[inline]
396    fn deactivate(&mut self) {
397        self.update_status.clear();
398        self.activation.set_energy(N::zero());
399        self.velocity = Velocity::zero();
400    }
401
402    #[inline]
403    fn set_deactivation_threshold(&mut self, threshold: Option<N>) {
404        self.activation.set_deactivation_threshold(threshold)
405    }
406
407    #[inline]
408    fn update_status(&self) -> BodyUpdateStatus {
409        self.update_status
410    }
411
412    #[inline]
413    fn status(&self) -> BodyStatus {
414        self.status
415    }
416
417    #[inline]
418    fn set_status(&mut self, status: BodyStatus) {
419        if status != self.status {
420            self.update_status.set_status_changed(true);
421        }
422        self.status = status
423    }
424
425    #[inline]
426    fn deformed_positions(&self) -> Option<(DeformationsType, &[N])> {
427        None
428    }
429
430    #[inline]
431    fn deformed_positions_mut(&mut self) -> Option<(DeformationsType, &mut [N])> {
432        None
433    }
434
435    #[inline]
436    fn companion_id(&self) -> usize {
437        self.companion_id
438    }
439
440    #[inline]
441    fn set_companion_id(&mut self, id: usize) {
442        self.companion_id = id
443    }
444
445    #[inline]
446    fn ndofs(&self) -> usize {
447        SPATIAL_DIM
448    }
449
450    #[inline]
451    fn generalized_velocity(&self) -> DVectorSlice<N> {
452        DVectorSlice::from_slice(self.velocity.as_slice(), SPATIAL_DIM)
453    }
454
455    #[inline]
456    fn generalized_velocity_mut(&mut self) -> DVectorSliceMut<N> {
457        self.update_status.set_velocity_changed(true);
458        DVectorSliceMut::from_slice(self.velocity.as_mut_slice(), SPATIAL_DIM)
459    }
460
461    #[inline]
462    fn generalized_acceleration(&self) -> DVectorSlice<N> {
463        DVectorSlice::from_slice(self.acceleration.as_slice(), SPATIAL_DIM)
464    }
465
466    #[inline]
467    fn integrate(&mut self, parameters: &IntegrationParameters<N>) {
468        self.velocity.linear *= N::one() / (N::one() + parameters.dt() * self.linear_damping);
469        self.velocity.angular *= N::one() / (N::one() + parameters.dt() * self.angular_damping);
470
471        let linvel_norm = self.velocity.linear.norm();
472
473        if linvel_norm > self.max_linear_velocity {
474            if self.max_linear_velocity.is_zero() {
475                self.velocity.linear = na::zero();
476            } else {
477                self.velocity.linear *= self.max_linear_velocity / linvel_norm;
478            }
479        }
480
481        #[cfg(feature = "dim2")]
482        {
483            if self.velocity.angular > self.max_angular_velocity {
484                self.velocity.angular = self.max_angular_velocity;
485            } else if self.velocity.angular < -self.max_angular_velocity {
486                self.velocity.angular = -self.max_angular_velocity;
487            }
488        }
489
490        #[cfg(feature = "dim3")]
491        {
492            let angvel_norm = self.velocity.angular.norm();
493
494            if angvel_norm > self.max_angular_velocity {
495                if self.max_angular_velocity.is_zero() {
496                    self.velocity.angular = na::zero()
497                } else {
498                    self.velocity.angular *= self.max_angular_velocity / angvel_norm;
499                }
500            }
501        }
502
503        let disp = self.velocity * parameters.dt();
504        self.apply_displacement(&disp);
505    }
506
507    fn clear_forces(&mut self) {
508        self.external_forces = Force::zero();
509    }
510
511    fn clear_update_flags(&mut self) {
512        self.update_status.clear();
513    }
514
515    fn update_kinematics(&mut self) {}
516
517    fn step_started(&mut self) {
518        self.position0 = self.position;
519    }
520
521    fn advance(&mut self, time_ratio: N) {
522        let motion = self.part_motion(0, N::zero()).unwrap();
523        self.position0 = motion.position_at_time(time_ratio);
524    }
525
526    fn validate_advancement(&mut self) {
527        self.position0 = self.position;
528    }
529
530    fn clamp_advancement(&mut self) {
531        if self.linear_motion_interpolation_enabled {
532            let p0 = Isometry::from_parts(self.position0.translation, self.position.rotation);
533            self.set_position(p0);
534        } else {
535            self.set_position(self.position0);
536        }
537    }
538
539    fn part_motion(&self, _: usize, time_origin: N) -> Option<BodyPartMotion<N>> {
540        if self.linear_motion_interpolation_enabled {
541            let p0 = Isometry::from_parts(self.position0.translation, self.position.rotation);
542            let motion =
543                ConstantLinearVelocityRigidMotion::new(time_origin, p0, self.velocity.linear);
544            Some(BodyPartMotion::RigidLinear(motion))
545        } else {
546            let motion = ConstantVelocityRigidMotion::new(
547                time_origin,
548                self.position0,
549                self.local_com,
550                self.velocity.linear,
551                self.velocity.angular,
552            );
553            Some(BodyPartMotion::RigidNonlinear(motion))
554        }
555    }
556
557    #[allow(unused_variables)] // for parameters used only in 3D.
558    fn update_dynamics(&mut self, dt: N) {
559        if !self.update_status.inertia_needs_update() || self.status != BodyStatus::Dynamic {
560            return;
561        }
562
563        if !self.is_active() {
564            self.activate();
565        }
566
567        match self.status {
568            #[cfg(feature = "dim3")]
569            BodyStatus::Dynamic => {
570                // The inverse inertia matrix is constant in 2D.
571                self.inertia = self.local_inertia.transformed(&self.position);
572                self.augmented_mass = self.inertia;
573
574                let i = &self.inertia.angular;
575                let w = &self.velocity.angular;
576                let iw = i * w;
577                let w_dt = w * dt;
578                let w_dt_cross = w_dt.gcross_matrix();
579                let iw_dt_cross = (iw * dt).gcross_matrix();
580                self.augmented_mass.angular += w_dt_cross * i - iw_dt_cross;
581
582                // NOTE: if we did not have the gyroscopic forces, we would not have to invert the inertia
583                // matrix at each time-step => add a flag to disable gyroscopic forces?
584                self.inv_augmented_mass = self.augmented_mass.inverse();
585            }
586            _ => {}
587        }
588    }
589
590    fn update_acceleration(&mut self, gravity: &Vector<N>, _: &IntegrationParameters<N>) {
591        self.acceleration = Velocity::zero();
592
593        match self.status {
594            BodyStatus::Dynamic => {
595                // The inverse inertia matrix is constant in 2D.
596                #[cfg(feature = "dim3")]
597                {
598                    /*
599                     * Compute acceleration due to gyroscopic forces.
600                     */
601                    let i = &self.inertia.angular;
602                    let w = &self.velocity.angular;
603                    let iw = i * w;
604                    let gyroscopic = -w.cross(&iw);
605                    self.acceleration.angular = self.inv_augmented_mass.angular * gyroscopic;
606                }
607
608                if self.inv_augmented_mass.linear != N::zero() && self.gravity_enabled {
609                    self.acceleration.linear = *gravity;
610                }
611
612                self.acceleration += self.inv_augmented_mass * self.external_forces;
613                self.acceleration
614                    .as_vector_mut()
615                    .component_mul_assign(&self.jacobian_mask);
616            }
617            _ => {}
618        }
619    }
620
621    #[inline]
622    fn num_parts(&self) -> usize {
623        1
624    }
625
626    #[inline]
627    fn part(&self, i: usize) -> Option<&dyn BodyPart<N>> {
628        if i == 0 {
629            Some(self)
630        } else {
631            None
632        }
633    }
634
635    #[inline]
636    fn apply_displacement(&mut self, displacement: &[N]) {
637        self.apply_displacement(&Velocity::from_slice(displacement));
638    }
639
640    #[inline]
641    fn world_point_at_material_point(&self, _: &dyn BodyPart<N>, point: &Point<N>) -> Point<N> {
642        self.position * point
643    }
644
645    #[inline]
646    fn position_at_material_point(&self, _: &dyn BodyPart<N>, point: &Point<N>) -> Isometry<N> {
647        self.position * Translation::from(point.coords)
648    }
649
650    #[inline]
651    fn material_point_at_world_point(&self, _: &dyn BodyPart<N>, point: &Point<N>) -> Point<N> {
652        self.position.inverse_transform_point(point)
653    }
654
655    #[inline]
656    fn gravity_enabled(&self) -> bool {
657        self.gravity_enabled
658    }
659
660    #[inline]
661    fn enable_gravity(&mut self, enabled: bool) {
662        self.gravity_enabled = enabled
663    }
664
665    #[inline]
666    fn velocity_at_point(&self, _: usize, point: &Point<N>) -> Velocity<N> {
667        let pos = point - self.com;
668        self.velocity.shift(&pos)
669    }
670
671    #[inline]
672    fn fill_constraint_geometry(
673        &self,
674        _: &dyn BodyPart<N>,
675        _: usize,
676        point: &Point<N>,
677        force_dir: &ForceDirection<N>,
678        j_id: usize,
679        wj_id: usize,
680        jacobians: &mut [N],
681        inv_r: &mut N,
682        ext_vels: Option<&DVectorSlice<N>>,
683        out_vel: Option<&mut N>,
684    ) {
685        let pos = point - self.com.coords;
686        let force = force_dir.at_point(&pos);
687        let mut masked_force = force.clone();
688        masked_force
689            .as_vector_mut()
690            .component_mul_assign(&self.jacobian_mask);
691
692        match self.status {
693            BodyStatus::Kinematic => {
694                if let Some(out_vel) = out_vel {
695                    // Don't use the masked force here so the locked
696                    // DOF remain controllable at the velocity level.
697                    *out_vel += force.as_vector().dot(&self.velocity.as_vector());
698                }
699            }
700            BodyStatus::Dynamic => {
701                jacobians[j_id..j_id + SPATIAL_DIM].copy_from_slice(masked_force.as_slice());
702
703                let inv_mass = self.inv_augmented_mass();
704                let imf = *inv_mass * masked_force;
705                jacobians[wj_id..wj_id + SPATIAL_DIM].copy_from_slice(imf.as_slice());
706
707                *inv_r +=
708                    inv_mass.mass() + masked_force.angular_vector().dot(&imf.angular_vector());
709
710                if let Some(out_vel) = out_vel {
711                    // Don't use the masked force here so the locked
712                    // DOF remain controllable at the velocity level.
713                    *out_vel += force.as_vector().dot(&self.velocity.as_vector());
714
715                    if let Some(ext_vels) = ext_vels {
716                        *out_vel += masked_force.as_vector().dot(ext_vels)
717                    }
718                }
719            }
720            BodyStatus::Static | BodyStatus::Disabled => {}
721        }
722    }
723
724    #[inline]
725    fn has_active_internal_constraints(&mut self) -> bool {
726        false
727    }
728
729    #[inline]
730    fn setup_internal_velocity_constraints(
731        &mut self,
732        _: &DVectorSlice<N>,
733        _: &IntegrationParameters<N>,
734    ) {
735    }
736
737    #[inline]
738    fn warmstart_internal_velocity_constraints(&mut self, _: &mut DVectorSliceMut<N>) {}
739
740    #[inline]
741    fn step_solve_internal_velocity_constraints(&mut self, _: &mut DVectorSliceMut<N>) {}
742
743    #[inline]
744    fn step_solve_internal_position_constraints(&mut self, _: &IntegrationParameters<N>) {}
745
746    #[inline]
747    fn add_local_inertia_and_com(&mut self, _: usize, com: Point<N>, inertia: Inertia<N>) {
748        self.update_status.set_local_com_changed(true);
749        self.update_status.set_local_inertia_changed(true);
750
751        let mass_sum = self.inertia.linear + inertia.linear;
752
753        // Update center of mass.
754        if !mass_sum.is_zero() {
755            self.local_com =
756                (self.local_com * self.inertia.linear + com.coords * inertia.linear) / mass_sum;
757            self.com = self.position * self.local_com;
758        } else {
759            self.local_com = Point::origin();
760            self.com = self.position.translation.vector.into();
761        }
762
763        // Update local inertia.
764        self.local_inertia += inertia;
765        self.update_inertia_from_local_inertia();
766    }
767
768    /*
769     * Application of forces/impulses.
770     */
771    fn apply_force(
772        &mut self,
773        _: usize,
774        force: &Force<N>,
775        force_type: ForceType,
776        auto_wake_up: bool,
777    ) {
778        if self.status != BodyStatus::Dynamic {
779            return;
780        }
781
782        if auto_wake_up {
783            self.activate();
784        }
785
786        match force_type {
787            ForceType::Force => self.external_forces.as_vector_mut().cmpy(
788                N::one(),
789                force.as_vector(),
790                &self.jacobian_mask,
791                N::one(),
792            ),
793            ForceType::Impulse => {
794                self.update_status.set_velocity_changed(true);
795                let dvel = self.inv_augmented_mass * *force;
796                self.velocity.as_vector_mut().cmpy(
797                    N::one(),
798                    dvel.as_vector(),
799                    &self.jacobian_mask,
800                    N::one(),
801                )
802            }
803            ForceType::AccelerationChange => {
804                let change = self.augmented_mass * *force;
805                self.external_forces.as_vector_mut().cmpy(
806                    N::one(),
807                    change.as_vector(),
808                    &self.jacobian_mask,
809                    N::one(),
810                )
811            }
812            ForceType::VelocityChange => {
813                self.update_status.set_velocity_changed(true);
814                self.velocity.as_vector_mut().cmpy(
815                    N::one(),
816                    force.as_vector(),
817                    &self.jacobian_mask,
818                    N::one(),
819                )
820            }
821        }
822    }
823
824    fn apply_local_force(
825        &mut self,
826        _: usize,
827        force: &Force<N>,
828        force_type: ForceType,
829        auto_wake_up: bool,
830    ) {
831        let world_force = force.transform_by(&self.position);
832        self.apply_force(0, &world_force, force_type, auto_wake_up)
833    }
834
835    fn apply_force_at_point(
836        &mut self,
837        _: usize,
838        force: &Vector<N>,
839        point: &Point<N>,
840        force_type: ForceType,
841        auto_wake_up: bool,
842    ) {
843        let force = Force::linear_at_point(*force, &(point - self.com.coords));
844        self.apply_force(0, &force, force_type, auto_wake_up)
845    }
846
847    fn apply_local_force_at_point(
848        &mut self,
849        _: usize,
850        force: &Vector<N>,
851        point: &Point<N>,
852        force_type: ForceType,
853        auto_wake_up: bool,
854    ) {
855        self.apply_force_at_point(0, &(self.position * force), point, force_type, auto_wake_up)
856    }
857
858    fn apply_force_at_local_point(
859        &mut self,
860        _: usize,
861        force: &Vector<N>,
862        point: &Point<N>,
863        force_type: ForceType,
864        auto_wake_up: bool,
865    ) {
866        self.apply_force_at_point(0, force, &(self.position * point), force_type, auto_wake_up)
867    }
868
869    fn apply_local_force_at_local_point(
870        &mut self,
871        _: usize,
872        force: &Vector<N>,
873        point: &Point<N>,
874        force_type: ForceType,
875        auto_wake_up: bool,
876    ) {
877        self.apply_force_at_point(
878            0,
879            &(self.position * force),
880            &(self.position * point),
881            force_type,
882            auto_wake_up,
883        )
884    }
885}
886
887impl<N: RealField + Copy> BodyPart<N> for RigidBody<N> {
888    #[inline]
889    fn is_ground(&self) -> bool {
890        false
891    }
892
893    #[inline]
894    fn velocity(&self) -> Velocity<N> {
895        self.velocity
896    }
897
898    #[inline]
899    fn position(&self) -> Isometry<N> {
900        self.position
901    }
902
903    #[inline]
904    fn safe_position(&self) -> Isometry<N> {
905        if self.linear_motion_interpolation_enabled {
906            Isometry::from_parts(self.position0.translation, self.position.rotation)
907        } else {
908            self.position0
909        }
910    }
911
912    #[inline]
913    fn local_inertia(&self) -> Inertia<N> {
914        self.local_inertia
915    }
916
917    #[inline]
918    fn inertia(&self) -> Inertia<N> {
919        self.inertia
920    }
921
922    #[inline]
923    fn center_of_mass(&self) -> Point<N> {
924        self.com
925    }
926
927    #[inline]
928    fn local_center_of_mass(&self) -> Point<N> {
929        self.local_com
930    }
931}
932
933/// The description of a rigid body, used to build a new `RigidBody`.
934///
935/// This is the structure to use in order to create and add a rigid body
936/// (as well as some attached colliders) to the `World`. It follows
937/// the builder pattern and defines three kinds of methods:
938///
939/// * Methods with the `.with_` prefix: sets a property of `self` and returns `Self` itself.
940/// * Methods with the `.set_`prefix: sets a property of `&mut self` and retuns the `&mut self` pointer.
941/// * The `build` method: actually build the rigid body into the given `World` and returns a mutable reference to the newly created rigid body.
942///   The `build` methods takes `self` by-ref so the same `RigidBodyDesc` can be re-used (possibly modified) to build other rigid bodies.
943///
944/// The `.with_` methods as well as the `.set_` method are designed to support chaining.
945/// Because the `.with_` methods takes `self` by-move, it is useful to use when initializing the
946/// `RigidBodyDesc` for the first time. The `.set_` methods are useful when modifying it after
947/// this initialization (including after calls to `.build`).
948#[derive(Clone)]
949pub struct RigidBodyDesc<N: RealField + Copy> {
950    user_data: Option<UserDataBox>,
951    gravity_enabled: bool,
952    linear_motion_interpolation_enabled: bool,
953    position: Isometry<N>,
954    velocity: Velocity<N>,
955    linear_damping: N,
956    angular_damping: N,
957    max_linear_velocity: N,
958    max_angular_velocity: N,
959    local_inertia: Inertia<N>,
960    local_center_of_mass: Point<N>,
961    status: BodyStatus,
962    sleep_threshold: Option<N>,
963    kinematic_translations: Vector<bool>,
964    #[cfg(feature = "dim3")]
965    kinematic_rotations: Vector<bool>,
966    #[cfg(feature = "dim2")]
967    kinematic_rotations: bool,
968}
969
970impl<'a, N: RealField + Copy> RigidBodyDesc<N> {
971    /// A default rigid body builder.
972    pub fn new() -> RigidBodyDesc<N> {
973        RigidBodyDesc {
974            user_data: None,
975            gravity_enabled: true,
976            linear_motion_interpolation_enabled: false,
977            position: Isometry::identity(),
978            velocity: Velocity::zero(),
979            linear_damping: N::zero(),
980            angular_damping: N::zero(),
981            max_linear_velocity: N::max_value(),
982            max_angular_velocity: N::max_value(),
983            local_inertia: Inertia::zero(),
984            local_center_of_mass: Point::origin(),
985            status: BodyStatus::Dynamic,
986            sleep_threshold: Some(ActivationStatus::default_threshold()),
987            kinematic_translations: Vector::repeat(false),
988            #[cfg(feature = "dim3")]
989            kinematic_rotations: Vector::repeat(false),
990            #[cfg(feature = "dim2")]
991            kinematic_rotations: false,
992        }
993    }
994
995    user_data_desc_accessors!();
996
997    #[cfg(feature = "dim3")]
998    desc_custom_setters!(
999        self.rotation, set_rotation, axisangle: Vector<N> | { self.position.rotation = Rotation::new(axisangle) }
1000        self.kinematic_rotations, set_rotations_kinematic, kinematic_rotations: Vector<bool> | { self.kinematic_rotations = kinematic_rotations }
1001        self.angular_inertia, set_angular_inertia, angular_inertia: na::Matrix3<N> | { self.local_inertia.angular = angular_inertia }
1002    );
1003
1004    #[cfg(feature = "dim2")]
1005    desc_custom_setters!(
1006        self.rotation, set_rotation, angle: N | { self.position.rotation = Rotation::new(angle) }
1007        self.kinematic_rotations, set_rotations_kinematic, is_kinematic: bool | { self.kinematic_rotations = is_kinematic }
1008        self.angular_inertia, set_angular_inertia, angular_inertia: N | { self.local_inertia.angular = angular_inertia }
1009    );
1010
1011    desc_custom_setters!(
1012        self.translation, set_translation, vector: Vector<N> | { self.position.translation.vector = vector }
1013        self.mass, set_mass, mass: N | { self.local_inertia.linear = mass }
1014    );
1015
1016    desc_setters!(
1017        gravity_enabled, enable_gravity, gravity_enabled: bool
1018        linear_motion_interpolation_enabled, enable_linear_motion_interpolation, linear_motion_interpolation_enabled: bool
1019        status, set_status, status: BodyStatus
1020        position, set_position, position: Isometry<N>
1021        velocity, set_velocity, velocity: Velocity<N>
1022        linear_damping, set_linear_damping, linear_damping: N
1023        angular_damping, set_angular_damping, angular_damping: N
1024        max_linear_velocity, set_max_linear_velocity, max_linear_velocity: N
1025        max_angular_velocity, set_max_angular_velocity, max_angular_velocity: N
1026        local_inertia, set_local_inertia, local_inertia: Inertia<N>
1027        local_center_of_mass, set_local_center_of_mass, local_center_of_mass: Point<N>
1028        sleep_threshold, set_sleep_threshold, sleep_threshold: Option<N>
1029        kinematic_translations, set_translations_kinematic, kinematic_translations: Vector<bool>
1030    );
1031
1032    #[cfg(feature = "dim3")]
1033    desc_custom_getters!(
1034        self.get_rotation: Vector<N> | { self.position.rotation.scaled_axis() }
1035        self.get_kinematic_rotations: Vector<bool> | { self.kinematic_rotations }
1036        self.get_angular_inertia: &na::Matrix3<N> | { &self.local_inertia.angular }
1037    );
1038
1039    #[cfg(feature = "dim2")]
1040    desc_custom_getters!(
1041        self.get_rotation: N | { self.position.rotation.angle() }
1042        self.get_kinematic_rotations: bool | { self.kinematic_rotations }
1043        self.get_angular_inertia: N | { self.local_inertia.angular }
1044    );
1045
1046    desc_custom_getters!(
1047        self.get_translation: &Vector<N> | { &self.position.translation.vector }
1048        self.get_mass: N | { self.local_inertia.linear }
1049    );
1050
1051    desc_getters!(
1052        [val] is_gravity_enabled -> gravity_enabled: bool
1053        [val] is_linear_motion_interpolation_enabled -> linear_motion_interpolation_enabled: bool
1054        [val] get_status -> status: BodyStatus
1055        [val] get_sleep_threshold -> sleep_threshold: Option<N>
1056        [val] get_linear_damping -> linear_damping: N
1057        [val] get_angular_damping -> angular_damping: N
1058        [val] get_max_linear_velocity -> max_linear_velocity: N
1059        [val] get_max_angular_velocity -> max_angular_velocity: N
1060        [ref] get_position -> position: Isometry<N>
1061        [ref] get_velocity -> velocity: Velocity<N>
1062        [ref] get_local_inertia -> local_inertia: Inertia<N>
1063        [ref] get_local_center_of_mass -> local_center_of_mass: Point<N>
1064    );
1065
1066    /// Builds a rigid body from this description.
1067    pub fn build(&self) -> RigidBody<N> {
1068        let mut rb = RigidBody::new(self.position);
1069        rb.enable_linear_motion_interpolation(self.linear_motion_interpolation_enabled);
1070        rb.set_velocity(self.velocity);
1071        rb.set_local_inertia(self.local_inertia);
1072        rb.set_local_center_of_mass(self.local_center_of_mass);
1073        rb.set_status(self.status);
1074        rb.set_deactivation_threshold(self.sleep_threshold);
1075        rb.set_translations_kinematic(self.kinematic_translations);
1076        rb.enable_gravity(self.gravity_enabled);
1077        rb.set_linear_damping(self.linear_damping);
1078        rb.set_angular_damping(self.angular_damping);
1079        rb.set_max_linear_velocity(self.max_linear_velocity);
1080        rb.set_max_angular_velocity(self.max_angular_velocity);
1081        let _ = rb.set_user_data(self.user_data.as_ref().map(|data| data.0.to_any()));
1082        rb.set_rotations_kinematic(self.kinematic_rotations);
1083
1084        rb
1085    }
1086}