Skip to content

Commit

Permalink
Add an interaction group to specify fluid/boundary interactions (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrixyz authored Nov 15, 2024
1 parent 1b57c18 commit 7e598e8
Show file tree
Hide file tree
Showing 21 changed files with 425 additions and 25 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

### Added

- `Fluid` now has a new parameter `InteractionGroup`,
which controls which static particles (`Boundary`s) can interact with it.

### Changed

- Update dependencies:
Expand Down
1 change: 1 addition & 0 deletions build/salva2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ rapier2d = { version = "0.21", optional = true }
rapier_testbed2d = { version = "0.21", optional = true }

bevy_egui = { version = "0.26", features = ["immutable_ctx"], optional = true }
bitflags = "2"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = { version = "0.13.2", default-features = false, features = [
Expand Down
1 change: 1 addition & 0 deletions build/salva3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ rapier3d = { version = "0.21", optional = true }
rapier_testbed3d = { version = "0.21", optional = true }

bevy_egui = { version = "0.26", features = ["immutable_ctx"], optional = true }
bitflags = "2.6.0"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
bevy = { version = "0.13", default-features = false, features = [
Expand Down
2 changes: 2 additions & 0 deletions examples2d/all_examples2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rapier_testbed2d::{Testbed, TestbedApp};
mod basic2;
mod custom_forces2;
mod elasticity2;
mod layers2;
mod surface_tension2;

fn demo_name_from_command_line() -> Option<String> {
Expand Down Expand Up @@ -47,6 +48,7 @@ fn main() {

let mut builders: Vec<(_, fn(&mut Testbed))> = vec![
("Basic", basic2::init_world),
("Layers", layers2::init_world),
("Custom forces", custom_forces2::init_world),
("Elasticity", elasticity2::init_world),
("Surface tension", surface_tension2::init_world),
Expand Down
11 changes: 6 additions & 5 deletions examples2d/basic2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rapier2d::dynamics::{ImpulseJointSet, MultibodyJointSet, RigidBodyBuilder, R
use rapier2d::geometry::{Collider, ColliderBuilder, ColliderSet};
use rapier_testbed2d::Testbed;
use salva2d::integrations::rapier::{ColliderSampling, FluidsPipeline, FluidsTestbedPlugin};
use salva2d::object::interaction_groups::InteractionGroups;
use salva2d::object::{Boundary, Fluid};
use salva2d::solver::{ArtificialViscosity, Becker2009Elasticity, XSPHViscosity};
use std::f32;
Expand Down Expand Up @@ -52,22 +53,22 @@ pub fn init_world(testbed: &mut Testbed) {

let elasticity: Becker2009Elasticity = Becker2009Elasticity::new(1_000.0, 0.3, true);
let viscosity = XSPHViscosity::new(0.5, 1.0);
let mut fluid = Fluid::new(points1, PARTICLE_RADIUS, 1.0);
let mut fluid = Fluid::new(points1, PARTICLE_RADIUS, 1.0, InteractionGroups::default());
fluid.nonpressure_forces.push(Box::new(elasticity));
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(0.8, 0.7, 1.0));

let elasticity: Becker2009Elasticity = Becker2009Elasticity::new(1_000.0, 0.3, true);
let viscosity = XSPHViscosity::new(0.5, 1.0);
let mut fluid = Fluid::new(points2, PARTICLE_RADIUS, 1.0);
let mut fluid = Fluid::new(points2, PARTICLE_RADIUS, 1.0, InteractionGroups::default());
fluid.nonpressure_forces.push(Box::new(elasticity));
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(1.0, 0.4, 0.6));

let viscosity = ArtificialViscosity::new(0.5, 0.0);
let mut fluid = Fluid::new(points3, PARTICLE_RADIUS, 1.0);
let mut fluid = Fluid::new(points3, PARTICLE_RADIUS, 1.0, InteractionGroups::default());
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(0.6, 0.8, 0.5));
Expand All @@ -92,7 +93,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(collider, handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
Expand All @@ -113,7 +114,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(collider, rb_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
Expand Down
3 changes: 2 additions & 1 deletion examples2d/elasticity2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rapier_testbed2d::Testbed;
use salva2d::integrations::rapier::{
ColliderSampling, FluidsPipeline, FluidsRenderingMode, FluidsTestbedPlugin,
};
use salva2d::object::interaction_groups::InteractionGroups;
use salva2d::object::Boundary;
use salva2d::solver::{Becker2009Elasticity, XSPHViscosity};
use std::f32;
Expand Down Expand Up @@ -68,7 +69,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
Expand Down
4 changes: 2 additions & 2 deletions examples2d/helper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use na::{Point2, Vector2};
use salva2d::object::Fluid;
use salva2d::object::{interaction_groups::InteractionGroups, Fluid};

pub fn cube_fluid(ni: usize, nj: usize, particle_rad: f32, density: f32) -> Fluid {
let mut points = Vec::new();
Expand All @@ -13,5 +13,5 @@ pub fn cube_fluid(ni: usize, nj: usize, particle_rad: f32, density: f32) -> Flui
}
}

Fluid::new(points, particle_rad, density)
Fluid::new(points, particle_rad, density, InteractionGroups::default())
}
180 changes: 180 additions & 0 deletions examples2d/layers2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
extern crate nalgebra as na;

use na::{DVector, Point2, Point3, Vector2};
use rapier2d::dynamics::{ImpulseJointSet, MultibodyJointSet, RigidBodyBuilder, RigidBodySet};
use rapier2d::geometry::{Collider, ColliderBuilder, ColliderSet};
use rapier_testbed2d::Testbed;
use salva2d::integrations::rapier::{ColliderSampling, FluidsPipeline, FluidsTestbedPlugin};
use salva2d::object::interaction_groups::{Group, InteractionGroups};
use salva2d::object::{Boundary, Fluid};
use salva2d::solver::{ArtificialViscosity, Becker2009Elasticity, XSPHViscosity};
use std::f32;

const PARTICLE_RADIUS: f32 = 0.1;
const SMOOTHING_FACTOR: f32 = 2.0;

pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let gravity = Vector2::y() * -9.81;
let mut plugin = FluidsTestbedPlugin::new();
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let impulse_joints = ImpulseJointSet::new();
let multibody_joints = MultibodyJointSet::new();
let mut fluids_pipeline = FluidsPipeline::new(PARTICLE_RADIUS, SMOOTHING_FACTOR);

// Liquid.
let mut points1 = Vec::new();
let mut points2 = Vec::new();
let mut points3 = Vec::new();
let ni = 25;
let nj = 15;

let shift2 = (nj as f32) * PARTICLE_RADIUS * 2.0;

for i in 0..ni / 2 {
for j in 0..nj {
let x = (i as f32) * PARTICLE_RADIUS * 2.0 - ni as f32 * PARTICLE_RADIUS;
let y = (j as f32 + 1.0) * PARTICLE_RADIUS * 2.0 + 0.5;
points1.push(Point2::new(x, y));
points2.push(Point2::new(x + ni as f32 * PARTICLE_RADIUS, y));
}
}

for i in 0..ni {
for j in 0..nj * 2 {
let x = (i as f32) * PARTICLE_RADIUS * 2.0 - ni as f32 * PARTICLE_RADIUS;
let y = (j as f32 + 1.0) * PARTICLE_RADIUS * 2.0 + 0.5;
points3.push(Point2::new(x, y + shift2));
}
}

let elasticity: Becker2009Elasticity = Becker2009Elasticity::new(1_000.0, 0.3, true);
let viscosity = XSPHViscosity::new(0.5, 1.0);
let mut fluid = Fluid::new(
points1,
PARTICLE_RADIUS,
1.0,
InteractionGroups::new(Group::GROUP_1, Group::GROUP_1),
);
fluid.nonpressure_forces.push(Box::new(elasticity));
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(0.8, 0.7, 1.0));

let elasticity: Becker2009Elasticity = Becker2009Elasticity::new(1_000.0, 0.3, true);
let viscosity = XSPHViscosity::new(0.5, 1.0);
let mut fluid = Fluid::new(
points2,
PARTICLE_RADIUS,
1.0,
InteractionGroups::new(Group::GROUP_2, Group::GROUP_2),
);
fluid.nonpressure_forces.push(Box::new(elasticity));
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(1.0, 0.4, 0.6));

let viscosity = ArtificialViscosity::new(0.5, 0.0);
let mut fluid = Fluid::new(points3, PARTICLE_RADIUS, 1.0, InteractionGroups::none());
fluid.nonpressure_forces.push(Box::new(viscosity.clone()));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
plugin.set_fluid_color(fluid_handle, Point3::new(0.6, 0.8, 0.5));

/*
* Ground
*/
let ground_size = Vector2::new(10.0, 1.0);
let nsubdivs = 50;

let heights = DVector::from_fn(nsubdivs + 1, |i, _| {
if i == 0 || i == nsubdivs {
20.0
} else {
(i as f32 * ground_size.x / (nsubdivs as f32)).cos() * 0.5
}
});

let rigid_body = RigidBodyBuilder::fixed().build();
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::heightfield(heights, ground_size).build();
let co_handle = colliders.insert_with_parent(collider, handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::all()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
ColliderSampling::DynamicContactSampling,
);

/*
* Create a dynamic rigid-bodies.
*/
let rad = 0.4;
let mut build_rigid_body_with_coupling =
|x, y, mut collider: Collider, interaction_group: InteractionGroups| {
let samples =
salva2d::sampling::shape_surface_ray_sample(collider.shape(), PARTICLE_RADIUS)
.unwrap();
let rb = RigidBodyBuilder::dynamic()
.translation(Vector2::new(x, y))
.build();
let rb_handle = bodies.insert(rb);
let membership: u32 = interaction_group.memberships.into();
let filter: u32 = interaction_group.filter.into();
collider.set_collision_groups(rapier2d::geometry::InteractionGroups::new(
rapier2d::geometry::Group::from(membership),
rapier2d::geometry::Group::from(filter),
));
let co_handle = colliders.insert_with_parent(collider, rb_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new(), interaction_group));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
ColliderSampling::StaticSampling(samples.clone()),
);
};

let co1 = ColliderBuilder::cuboid(rad, rad).density(0.8).build();
let co2 = ColliderBuilder::ball(rad).density(0.8).build();
let co3 = ColliderBuilder::capsule_y(rad, rad).density(0.8).build();
build_rigid_body_with_coupling(
0.0,
10.0,
co1,
InteractionGroups::new(Group::GROUP_2, Group::GROUP_2),
);
build_rigid_body_with_coupling(
-2.0,
10.0,
co2,
InteractionGroups::new(Group::GROUP_1, Group::GROUP_1),
);
build_rigid_body_with_coupling(
2.0,
10.5,
co3,
InteractionGroups::new(Group::GROUP_3, Group::GROUP_3),
);

/*
* Set up the testbed.
*/
plugin.set_pipeline(fluids_pipeline);
testbed.add_plugin(plugin);
testbed.set_world_with_params(
bodies,
colliders,
impulse_joints,
multibody_joints,
gravity,
(),
);
testbed.integration_parameters_mut().dt = 1.0 / 200.0;
// testbed.enable_boundary_particles_rendering(true);
}
3 changes: 2 additions & 1 deletion examples2d/surface_tension2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rapier_testbed2d::{Testbed, TestbedApp};
use salva2d::integrations::rapier::{
ColliderSampling, FluidsPipeline, FluidsRenderingMode, FluidsTestbedPlugin,
};
use salva2d::object::interaction_groups::InteractionGroups;
use salva2d::object::Boundary;
use salva2d::solver::{Akinci2013SurfaceTension, ArtificialViscosity};
use std::f32;
Expand Down Expand Up @@ -50,7 +51,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
Expand Down
5 changes: 3 additions & 2 deletions examples3d/basic3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rapier3d::dynamics::{ImpulseJointSet, MultibodyJointSet, RigidBodyBuilder, R
use rapier3d::geometry::{ColliderBuilder, ColliderSet, SharedShape};
use rapier_testbed3d::{Testbed, TestbedApp};
use salva3d::integrations::rapier::{ColliderSampling, FluidsPipeline, FluidsTestbedPlugin};
use salva3d::object::interaction_groups::InteractionGroups;
use salva3d::object::Boundary;
use salva3d::solver::ArtificialViscosity;
use std::f32;
Expand Down Expand Up @@ -74,7 +75,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));

fluids_pipeline.coupling.register_coupling(
bo_handle,
Expand All @@ -89,7 +90,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));

fluids_pipeline.coupling.register_coupling(
bo_handle,
Expand Down
3 changes: 2 additions & 1 deletion examples3d/elasticity3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rapier_testbed3d::{Testbed, TestbedApp};
use salva3d::integrations::rapier::{
ColliderSampling, FluidsPipeline, FluidsRenderingMode, FluidsTestbedPlugin,
};
use salva3d::object::interaction_groups::InteractionGroups;
use salva3d::object::Boundary;
use salva3d::solver::{Becker2009Elasticity, XSPHViscosity};
use std::f32;
Expand Down Expand Up @@ -83,7 +84,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));
fluids_pipeline.coupling.register_coupling(
bo_handle,
co_handle,
Expand Down
10 changes: 8 additions & 2 deletions examples3d/faucet3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use rapier3d::{
};
use rapier_testbed3d::{Testbed, TestbedApp};
use salva3d::integrations::rapier::{ColliderSampling, FluidsPipeline, FluidsTestbedPlugin};
use salva3d::object::interaction_groups::InteractionGroups;
use salva3d::object::{Boundary, Fluid};
use salva3d::solver::{Akinci2013SurfaceTension, XSPHViscosity};
use std::f32;
Expand Down Expand Up @@ -35,7 +36,12 @@ pub fn init_world(testbed: &mut Testbed) {
// Initialize the fluid.
let viscosity = XSPHViscosity::new(0.5, 0.0);
let tension = Akinci2013SurfaceTension::new(1.0, 10.0);
let mut fluid = Fluid::new(Vec::new(), PARTICLE_RADIUS, 1000.0);
let mut fluid = Fluid::new(
Vec::new(),
PARTICLE_RADIUS,
1000.0,
InteractionGroups::default(),
);
fluid.nonpressure_forces.push(Box::new(viscosity));
fluid.nonpressure_forces.push(Box::new(tension));
let fluid_handle = fluids_pipeline.liquid_world.add_fluid(fluid);
Expand All @@ -49,7 +55,7 @@ pub fn init_world(testbed: &mut Testbed) {
let co_handle = colliders.insert_with_parent(co, ground_handle, &mut bodies);
let bo_handle = fluids_pipeline
.liquid_world
.add_boundary(Boundary::new(Vec::new()));
.add_boundary(Boundary::new(Vec::new(), InteractionGroups::default()));

fluids_pipeline.coupling.register_coupling(
bo_handle,
Expand Down
Loading

0 comments on commit 7e598e8

Please sign in to comment.