Skip to content

Commit d857579

Browse files
sebcrozetVrixyz
andauthored
feat: implement CPIC (two-ways rigid-body coupling) (#9)
* feat: add basic CPIC implementation * feat: support one-way coupling with CPIC * feat: kinematic body coupling with rapier * feat: implement two-ways coupling with cpic * fix incorrect stress calculation for neo-hookean (was cauchy instead of kirchoff). * feat: some adjustments for two-ways coupling * feat: support more geometric primitives * Fix 3D * Fix timestamps * feat(wgsparkl2d): support polyline colliders * feat(wgsparkl3d): support trimesh colliders * feat: support kinematic bodies for rigid particles + misc coupling fixes * feat: make the DruckerPrager fields public * chore: cargo fmt * fix: move path deps to cargo patches * fix 2D simulations * Fix support of non-macos platforms * fix: disable the wireframe plugin on web * feat(wasm): group some of the particle properties to reduce the number of storage bindings * feat: further reduce storage binding counts to fix web support * feat: add COPY_SRC to the particle position flags * fix dependencies to compile * chore: switch to wgmath/main * chore: add CI * chore: clippy fixes * chore: fix tests * chore: don’t run tests on CI, they will fail because there is no gpu --------- Co-authored-by: Thierry Berger <contact@thierryberger.com>
1 parent 21ba37f commit d857579

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+4775
-783
lines changed

.cargo/config.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
[target.wasm32-unknown-unknown]
2-
runner = "wasm-server-runner"
2+
runner = "wasm-server-runner"
3+
# Needed for getrandom/uuid: https://github.com/uuid-rs/uuid/issues/792
4+
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']

.github/workflows/ci.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
RUSTFLAGS: --deny warnings
12+
RUSTDOCFLAGS: --deny warnings
13+
14+
jobs:
15+
# Run clippy lints.
16+
clippy:
17+
name: Clippy
18+
runs-on: ubuntu-latest
19+
timeout-minutes: 30
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Install Rust toolchain
25+
uses: dtolnay/rust-toolchain@stable
26+
with:
27+
components: clippy
28+
29+
- name: Install dependencies
30+
run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
31+
32+
- name: Populate target directory from cache
33+
uses: Leafwing-Studios/cargo-cache@v2
34+
with:
35+
sweep-cache: true
36+
37+
- name: Run clippy lints
38+
run: cargo clippy --locked --workspace --all-targets --all-features -- --deny warnings
39+
40+
# Check formatting.
41+
format:
42+
name: Format
43+
runs-on: ubuntu-latest
44+
timeout-minutes: 30
45+
steps:
46+
- name: Checkout repository
47+
uses: actions/checkout@v4
48+
49+
- name: Install Rust toolchain
50+
uses: dtolnay/rust-toolchain@stable
51+
with:
52+
components: rustfmt
53+
54+
- name: Run cargo fmt
55+
run: cargo fmt --all -- --check
56+
57+
# Check documentation.
58+
doc:
59+
name: Docs
60+
runs-on: ubuntu-latest
61+
timeout-minutes: 30
62+
steps:
63+
- name: Checkout repository
64+
uses: actions/checkout@v4
65+
66+
- name: Install Rust toolchain
67+
uses: dtolnay/rust-toolchain@stable
68+
69+
- name: Install dependencies
70+
run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
71+
72+
- name: Populate target directory from cache
73+
uses: Leafwing-Studios/cargo-cache@v2
74+
with:
75+
sweep-cache: true
76+
77+
- name: Check documentation
78+
run: cargo doc --locked --workspace --all-features --document-private-items --no-deps

Cargo.toml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ resolver = "2"
1111
nalgebra = { version = "0.33", features = ["convert-bytemuck"] }
1212
wgpu = { version = "23", features = ["naga-ir"] }
1313
bytemuck = { version = "1", features = ["derive"] }
14-
anyhow = "1"
1514
async-channel = "2"
1615
naga_oil = "0.16"
17-
thiserror = "1"
1816
encase = { version = "0.10.0", features = ["nalgebra"] }
1917

2018
[workspace.lints]
@@ -23,6 +21,17 @@ rust.unexpected_cfgs = { level = "warn", check-cfg = [
2321
] }
2422

2523
[patch.crates-io]
24+
parry2d = { git = "https://github.com/dimforge/parry.git", rev = "407fb449504dde7ba0a3d80a8de7e37ac991a77a" }
25+
parry3d = { git = "https://github.com/dimforge/parry.git", rev = "407fb449504dde7ba0a3d80a8de7e37ac991a77a" }
26+
encase = { git = "https://github.com/sebcrozet/encase.git", rev = "6755c1414c225cbeac9fde1ff9394b70d3b05404" }
27+
wgcore = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
28+
wgcore-derive = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
29+
wgebra = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
30+
wgparry3d = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
31+
wgparry2d = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
32+
wgrapier3d = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
33+
wgrapier2d = { git = "https://github.com/dimforge/wgmath.git", rev = "6d17942bd841efdfcc696d8455b22be3a8ddfe8d" }
34+
rapier3d = { git = "https://github.com/vrixyz/rapier.git", branch = "uber_physics_context" }
2635

2736
[profile.release]
2837
opt-level = 'z'

crates/wgsparkl-testbed2d/Cargo.toml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ required-features = ["dim2"]
1414

1515
[features]
1616
dim2 = []
17-
default_features = ["dim2"]
17+
default = ["dim2"]
1818

1919
[dependencies]
2020
nalgebra = { workspace = true, features = ["rand"] }
@@ -23,17 +23,25 @@ naga_oil = { workspace = true }
2323
bytemuck = { workspace = true }
2424
async-channel = { workspace = true }
2525

26-
wgcore = { version = "0.2", path = "../../../wgmath/crates/wgcore" }
27-
wgebra = { version = "0.2", path = "../../../wgmath/crates/wgebra" }
28-
wgparry2d = { version = "0.2", path = "../../../wgmath/crates/wgparry/crates/wgparry2d" }
26+
wgcore = "0.2"
27+
wgebra = "0.2"
28+
wgparry2d = "0.2"
2929

3030
futures-test = "0.3"
3131
serial_test = "3"
3232
approx = "0.5"
3333
async-std = { version = "1", features = ["attributes"] }
34-
bevy = { version = "0.15.0", features = ["shader_format_glsl", "shader_format_spirv", "webgpu"] }
34+
bevy = { version = "0.15.0", features = [
35+
"shader_format_glsl",
36+
"shader_format_spirv",
37+
"webgpu",
38+
] }
3539
#bevy_wasm_window_resize = "0.4"
36-
#bevy_editor_cam = "0.3"
37-
#bevy_mod_picking = { version = "0.20", default-features = false }
38-
bevy_egui = { version = "0.31", default-features = false, features = ["default_fonts", "render"] }
40+
bevy_editor_cam = "0.5"
41+
bevy_egui = { version = "0.31", default-features = false, features = [
42+
"default_fonts",
43+
"render",
44+
] }
45+
bevy_sprite = "0.15"
3946
wgsparkl2d = { path = "../wgsparkl2d" }
47+
futures = "0.3"

crates/wgsparkl-testbed3d/Cargo.toml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ required-features = ["dim3"]
1414

1515
[features]
1616
dim3 = []
17-
default_features = ["dim3"]
17+
default = ["dim3"]
1818

1919
[dependencies]
2020
nalgebra = { workspace = true, features = ["rand"] }
@@ -23,17 +23,25 @@ naga_oil = { workspace = true }
2323
bytemuck = { workspace = true }
2424
async-channel = { workspace = true }
2525

26-
wgcore = { version = "0.2", path = "../../../wgmath/crates/wgcore" }
27-
wgebra = { version = "0.2", path = "../../../wgmath/crates/wgebra" }
28-
wgparry3d = { version = "0.2", path = "../../../wgmath/crates/wgparry/crates/wgparry3d" }
26+
wgcore = "0.2"
27+
wgebra = "0.2"
28+
wgparry3d = "0.2"
2929

3030
futures-test = "0.3"
3131
serial_test = "3"
3232
approx = "0.5"
3333
async-std = { version = "1", features = ["attributes"] }
34-
bevy = { version = "0.15.0", features = ["shader_format_glsl", "shader_format_spirv", "webgpu"] }
35-
#bevy_editor_cam = "0.3"
34+
bevy = { version = "0.15.0", features = [
35+
"shader_format_glsl",
36+
"shader_format_spirv",
37+
"webgpu",
38+
] }
39+
bevy_editor_cam = "0.5"
3640
#bevy_mod_picking = { version = "0.20", default-features = false }
3741
#bevy_wasm_window_resize = "0.4"
38-
bevy_egui = { version = "0.31", default-features = false, features = ["default_fonts", "render"] }
42+
bevy_egui = { version = "0.31", default-features = false, features = [
43+
"default_fonts",
44+
"render",
45+
] }
3946
wgsparkl3d = { path = "../wgsparkl3d" }
47+
futures = "0.3"

crates/wgsparkl2d/Cargo.toml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@ naga_oil = { workspace = true }
2323
bytemuck = { workspace = true }
2424
encase = { workspace = true }
2525

26-
wgcore = { version = "0.2", path = "../../../wgmath/crates/wgcore", features = ["hot_reloading"] }
27-
wgebra = { version = "0.2", path = "../../../wgmath/crates/wgebra" }
28-
wgparry2d = { version = "0.2", path = "../../../wgmath/crates/wgparry/crates/wgparry2d" }
29-
wgrapier2d = { version = "0.2", path = "../../../wgmath/crates/wgrapier/crates/wgrapier2d" }
26+
wgcore = "0.2"
27+
wgebra = "0.2"
28+
wgparry2d = "0.2"
29+
wgrapier2d = "0.2"
30+
31+
# TODO: make rapier optional?
32+
rapier2d = "0.23"
33+
34+
# For wasm?
35+
getrandom = { version = "0.3.1", features = ["wasm_js"] }
36+
uuid = { version = "1", features = ["js"] }
3037

3138
[dev-dependencies]
3239
nalgebra = { version = "0.33", features = ["rand"] }
@@ -35,4 +42,4 @@ serial_test = "3"
3542
approx = "0.5"
3643
async-std = { version = "1", features = ["attributes"] }
3744
bevy = { version = "0.15.0", features = ["shader_format_glsl", "shader_format_spirv", "webgpu"] }
38-
wgsparkl_testbed2d = { path = "../wgsparkl-testbed2d" }
45+
wgsparkl_testbed2d = { path = "../wgsparkl-testbed2d", features = ["dim2"] }
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use wgsparkl_testbed2d::{wgsparkl, RapierData};
2+
3+
use bevy::prelude::*;
4+
use bevy::render::renderer::RenderDevice;
5+
use nalgebra::{point, vector, Vector2};
6+
use rapier2d::prelude::{ColliderBuilder, RigidBodyBuilder};
7+
use wgsparkl::solver::ParticlePhase;
8+
use wgsparkl::{
9+
models::ElasticCoefficients,
10+
pipeline::MpmData,
11+
solver::{Particle, SimulationParams},
12+
};
13+
use wgsparkl2d::solver::ParticleDynamics;
14+
use wgsparkl_testbed2d::{AppState, PhysicsContext};
15+
16+
#[allow(dead_code)]
17+
fn main() {
18+
panic!("Run the `testbed3` example instead.");
19+
}
20+
21+
pub fn elastic_cut_demo(
22+
mut commands: Commands,
23+
device: Res<RenderDevice>,
24+
mut app_state: ResMut<AppState>,
25+
) {
26+
let mut rapier_data = RapierData::default();
27+
let device = device.wgpu_device();
28+
29+
let offset_y = 46.0;
30+
// let cell_width = 0.1;
31+
let cell_width = 0.2;
32+
let mut particles = vec![];
33+
for i in 0..700 {
34+
for j in 0..700 {
35+
let position = vector![i as f32 + 0.5, j as f32 + 0.5] * cell_width / 2.0
36+
+ Vector2::y() * offset_y;
37+
let density = 1000.0;
38+
let radius = cell_width / 4.0;
39+
particles.push(Particle {
40+
position,
41+
dynamics: ParticleDynamics::with_density(radius, density),
42+
model: ElasticCoefficients::from_young_modulus(5_000_000.0, 0.2),
43+
plasticity: None,
44+
phase: Some(ParticlePhase {
45+
phase: 1.0,
46+
max_stretch: f32::MAX,
47+
}),
48+
});
49+
}
50+
}
51+
52+
if !app_state.restarting {
53+
app_state.num_substeps = 15;
54+
app_state.gravity_factor = 1.0;
55+
};
56+
57+
let params = SimulationParams {
58+
gravity: vector![0.0, -9.81] * app_state.gravity_factor,
59+
dt: (1.0 / 60.0) / (app_state.num_substeps as f32),
60+
padding: 0.0,
61+
};
62+
63+
// const ANGVEL: f32 = 1.0; // 2.0;
64+
65+
/*
66+
* Static platforms.
67+
*/
68+
let rb = RigidBodyBuilder::fixed().translation(vector![35.0, 20.0]);
69+
let rb_handle = rapier_data.bodies.insert(rb);
70+
let co = ColliderBuilder::cuboid(70.0, 1.0);
71+
rapier_data
72+
.colliders
73+
.insert_with_parent(co, rb_handle, &mut rapier_data.bodies);
74+
75+
let mut polyline = vec![];
76+
let subdivs = 100;
77+
let length = 84.0;
78+
let start = point![35.0, 70.0] - vector![length / 2.0, 0.0];
79+
80+
for i in 0..=subdivs {
81+
let step = length / (subdivs as f32);
82+
let dx = i as f32 * step;
83+
polyline.push(start + vector![dx, dx.sin()])
84+
}
85+
86+
let rb = RigidBodyBuilder::fixed();
87+
let rb_handle = rapier_data.bodies.insert(rb);
88+
let co = ColliderBuilder::polyline(polyline, None).build();
89+
rapier_data
90+
.colliders
91+
.insert_with_parent(co, rb_handle, &mut rapier_data.bodies);
92+
93+
for k in 0..6 {
94+
let rb = RigidBodyBuilder::fixed();
95+
let rb_handle = rapier_data.bodies.insert(rb);
96+
let co = ColliderBuilder::polyline(
97+
vec![
98+
point![0.0 + k as f32 * 15.0, 20.0],
99+
point![-10.0 + k as f32 * 15.0, 45.0],
100+
],
101+
None,
102+
)
103+
.build();
104+
rapier_data
105+
.colliders
106+
.insert_with_parent(co, rb_handle, &mut rapier_data.bodies);
107+
}
108+
109+
let data = MpmData::new(
110+
device,
111+
params,
112+
&particles,
113+
&rapier_data.bodies,
114+
&rapier_data.colliders,
115+
cell_width,
116+
60_000,
117+
);
118+
commands.insert_resource(PhysicsContext {
119+
data,
120+
rapier_data,
121+
particles,
122+
});
123+
}

0 commit comments

Comments
 (0)