Skip to content

Commit 895339b

Browse files
committed
feat: add support for fixed particles
1 parent 0464f3e commit 895339b

6 files changed

Lines changed: 53 additions & 1 deletion

File tree

shaders/slosh/models/neo_hookean_elasticity.slang

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
module neo_hookean_elasticity;
44

5+
import stensor.geometry.svd2;
6+
import stensor.geometry.svd3;
57
import nexus.aliases;
68
import slosh.models.utils;
79
import slosh.models.interfaces;
@@ -41,4 +43,24 @@ public struct NeoHookeanModel {
4143
);
4244
return bound.timestep_bound(particle_density0, particle_def_grad_det, particle_velocity, cell_width);
4345
}
46+
47+
public func pos_energy_density(in def_grad: Mat<float>, elastic_hardening: float) -> float {
48+
let j = determinant(def_grad);
49+
50+
#if DIM == 2
51+
let svd = Svd2(def_grad);
52+
#else
53+
let svd = Svd3(def_grad);
54+
#endif
55+
56+
let sig = max(svd.S - Vect<float>(1.0), Vect<float>(0.0));
57+
let pos_dev_part = this.mu * elastic_hardening * dot(sig, sig);
58+
let spherical_part = this.lambda * elastic_hardening * 0.5 * (j - 1.0) * (j - 1.0);
59+
60+
if (j < 1.0) {
61+
return pos_dev_part;
62+
} else {
63+
return pos_dev_part + spherical_part;
64+
}
65+
}
4466
}

shaders/slosh/solver/particle.slang

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ public struct Dynamics {
3030
/// Rayleigh mass-proportional damping coefficient (1/s).
3131
public float damping;
3232
public float phase;
33+
// TODO: merge these two into a `flags` field?
3334
public uint enabled;
35+
public uint fixed;
3436

3537
public func init_density() -> float {
3638
return this.mass / this.init_volume;

shaders/slosh/solver/particle_update.slang

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ func particle_update(
5353
var dynamics = particles_dyn[particle_id];
5454
let particle_pos = particles_pos[particle_id].pt;
5555

56+
// If the particle is fixed, clear its velocity and its affine matrix.
57+
// This isn’t ideal (this should typically be handled on the grid) but we sometimes
58+
// need sub-grid-sized fixed particles.
59+
if (dynamics.fixed != 0) {
60+
dynamics.velocity = Vect<float>(0.0);
61+
dynamics.affine = Mat<float>(0.0);
62+
return;
63+
}
64+
5665
/*
5766
* Advection.
5867
*/

shaders_testbed/slosh_testbed/prep_readback2.slang

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func prep_readback(
4444
if (particle_id < instances.getCount()) {
4545
let def_grad = particles_dyn[particle_id].def_grad;
4646
let init_deformation = diag(Vect<float>(particles_dyn[particle_id].init_radius * 2.0));
47-
instances[particle_id].deformation = mul(init_deformation, def_grad);
47+
instances[particle_id].deformation = mul(init_deformation, clamp(def_grad, Mat<float>(-4.0), Mat<float>(4.0)));
4848
instances[particle_id].position = float2(particles_pos[particle_id].pt);
4949

5050
let color = base_colors[particle_id];

src/solver/particle.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ pub struct ParticleDynamics {
5353
pub phase: f32,
5454
/// Whether this particle is active (1) or disabled (0).
5555
pub enabled: u32,
56+
/// Whether this particle is fixed (1) or dynamic (0).
57+
pub fixed: u32,
5658
}
5759

5860
impl ParticleDynamics {
@@ -80,9 +82,15 @@ impl ParticleDynamics {
8082
cdf: Cdf::default(),
8183
phase: 1.0,
8284
enabled: 1,
85+
fixed: 0,
8386
}
8487
}
8588

89+
/// Sets whether this particle is fixed (true) or dynamic (false).
90+
pub fn set_fixed(&mut self, fixed: bool) {
91+
self.fixed = fixed as u32;
92+
}
93+
8694
/// Sets the damping coefficient for this particle.
8795
pub fn set_damping(&mut self, damping: f32) {
8896
self.damping = damping;
@@ -481,6 +489,11 @@ impl<B: Backend, GpuModel: GpuParticleModelData> GpuParticles<B, GpuModel> {
481489
&self.models
482490
}
483491

492+
/// Returns mutable reference to material model buffer.
493+
pub fn models_mut(&mut self) -> &mut GpuTensor<GpuModel, B> {
494+
&mut self.models
495+
}
496+
484497
/// Returns reference to position buffer.
485498
pub fn positions(&self) -> &GpuTensor<ParticlePosition, B> {
486499
&self.positions
@@ -491,6 +504,11 @@ impl<B: Backend, GpuModel: GpuParticleModelData> GpuParticles<B, GpuModel> {
491504
&self.dynamics
492505
}
493506

507+
/// Returns mutable reference to dynamics buffer (velocity, deformation, mass).
508+
pub fn dynamics_mut(&mut self) -> &mut GpuTensor<ParticleDynamics, B> {
509+
&mut self.dynamics
510+
}
511+
494512
/// Returns reference to sorted particle ID buffer.
495513
pub fn sorted_ids(&self) -> &GpuTensor<u32, B> {
496514
&self.sorted_ids

src_testbed/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl<GpuModel: GpuParticleModelData> Stage<GpuModel> {
8282
let limits = Limits {
8383
max_storage_buffers_per_shader_stage: 11,
8484
max_compute_workgroup_storage_size: 32768, // Why do we need this if wgsparkl didn’t?
85+
max_buffer_size: 1_000_000_000,
8586
max_storage_buffer_binding_size: 1_000_000_000,
8687
..Limits::default()
8788
};

0 commit comments

Comments
 (0)