Skip to main content

oxiphysics_softbody/constraint/
volumeconstraint_traits.rs

1//! # VolumeConstraint - Trait Implementations
2//!
3//! This module contains trait implementations for `VolumeConstraint`.
4//!
5//! ## Implemented Traits
6//!
7//! - `SoftConstraint`
8//!
9//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
10
11use crate::particle::SoftParticle;
12use oxiphysics_core::math::Real;
13
14use super::functions::SoftConstraint;
15use super::types::VolumeConstraint;
16
17impl SoftConstraint for VolumeConstraint {
18    fn project(&mut self, particles: &mut [SoftParticle], dt_sub: Real) {
19        let [i0, i1, i2, i3] = self.indices;
20        let p0 = particles[i0].position;
21        let p1 = particles[i1].position;
22        let p2 = particles[i2].position;
23        let p3 = particles[i3].position;
24        let vol = Self::compute_tet_volume(&p0, &p1, &p2, &p3);
25        let c = vol - self.rest_volume;
26        if c.abs() < 1e-14 {
27            return;
28        }
29        let grad0 = (p1 - p2).cross(&(p3 - p2)) / 6.0;
30        let grad1 = (p2 - p0).cross(&(p3 - p0)) / 6.0;
31        let grad2 = (p0 - p1).cross(&(p3 - p1)) / 6.0;
32        let grad3 = (p1 - p0).cross(&(p2 - p0)) / 6.0;
33        let grads = [grad0, grad1, grad2, grad3];
34        let idxs = [i0, i1, i2, i3];
35        let mut w_sum = 0.0;
36        for k in 0..4 {
37            w_sum += particles[idxs[k]].inverse_mass * grads[k].norm_squared();
38        }
39        if w_sum < 1e-14 {
40            return;
41        }
42        let alpha_tilde = self.compliance / (dt_sub * dt_sub);
43        let delta_lambda = (-c - alpha_tilde * self.lambda) / (w_sum + alpha_tilde);
44        self.lambda += delta_lambda;
45        for k in 0..4 {
46            particles[idxs[k]].position +=
47                grads[k] * (delta_lambda * particles[idxs[k]].inverse_mass);
48        }
49    }
50}