Skip to content

Text to collider #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 50 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a8818a5
feat: add basic CPIC implementation
sebcrozet Jan 25, 2025
824d895
feat: support one-way coupling with CPIC
sebcrozet Jan 31, 2025
7d592ef
feat: kinematic body coupling with rapier
sebcrozet Feb 3, 2025
a716219
feat: implement two-ways coupling with cpic
sebcrozet Feb 4, 2025
61d6973
fix incorrect stress calculation for neo-hookean (was cauchy instead …
sebcrozet Feb 5, 2025
754a4fd
feat: some adjustments for two-ways coupling
sebcrozet Feb 5, 2025
2357555
feat: support more geometric primitives
sebcrozet Feb 5, 2025
8b1c159
Fix 3D
sebcrozet Feb 6, 2025
f5fc1c2
Fix timestamps
sebcrozet Feb 6, 2025
4ef05b0
feat(wgsparkl2d): support polyline colliders
sebcrozet Feb 12, 2025
0a31f8a
feat(wgsparkl3d): support trimesh colliders
sebcrozet Feb 14, 2025
643ae49
feat: support kinematic bodies for rigid particles + misc coupling fixes
sebcrozet Feb 15, 2025
58b75fd
feat: make the DruckerPrager fields public
sebcrozet Feb 15, 2025
f457777
chore: cargo fmt
sebcrozet Feb 15, 2025
6114a73
fix: move path deps to cargo patches
sebcrozet Feb 15, 2025
409abe9
fix 2D simulations
sebcrozet Feb 17, 2025
f64d391
Fix support of non-macos platforms
sebcrozet Feb 17, 2025
aad0361
fix: disable the wireframe plugin on web
sebcrozet Feb 17, 2025
6a9e0b0
feat(wasm): group some of the particle properties to reduce the numbe…
sebcrozet Feb 17, 2025
3afe2e9
feat: further reduce storage binding counts to fix web support
sebcrozet Feb 17, 2025
5b3876c
feat: add COPY_SRC to the particle position flags
sebcrozet Feb 19, 2025
07c19b4
compiling 3d (from folder)
Vrixyz Mar 3, 2025
8922108
add an example loading a mesh into a particle
Vrixyz Mar 4, 2025
e94f20d
attempt to sample vertex colors from material
Vrixyz Mar 8, 2025
82e67e2
attempt to load glb into particles ; not working
Vrixyz Mar 10, 2025
ec3aa08
better model to showcase
Vrixyz Mar 11, 2025
56215de
correct color loading for gltf
Vrixyz Mar 11, 2025
6d6bbd1
wip loading banana and knife
Vrixyz Mar 12, 2025
00f01a1
format credits
Vrixyz Mar 12, 2025
d501afa
correctly load rigidbody coupling
Vrixyz Mar 12, 2025
4276c3e
knife cutting through banana (but cut is bugged)
Vrixyz Mar 12, 2025
25dc1f4
knife with open blade correctly cuts :)
Vrixyz Mar 12, 2025
37b7124
better time management
Vrixyz Mar 12, 2025
51c4af3
inside the banana is now white/yellow
Vrixyz Mar 12, 2025
841a565
attempt to use lib examples
Vrixyz Mar 13, 2025
8fc3d28
text to collider using comsic-text
Vrixyz Mar 14, 2025
cca0349
knif model follow its rigidbody
Vrixyz Mar 14, 2025
b8e81e5
Merge branch 'sample_color_model' into text_to_collider
Vrixyz Mar 14, 2025
0c1be37
add comment about sample_mesh
Vrixyz Mar 14, 2025
11cb379
Merge branch 'sample_color_model' into text_to_collider
Vrixyz Mar 14, 2025
bb25ea1
sand3: stop blade after some steps (wip, this should be done through …
Vrixyz Mar 14, 2025
5b38cf6
use binary for examples 3d
Vrixyz Mar 14, 2025
82ffe57
use binary for examples 2d
Vrixyz Mar 14, 2025
1b971d9
fix wasm build
Vrixyz Mar 14, 2025
27768c3
better banana cut ; moved utils functions to wgsparkl behind a featur…
Vrixyz Mar 17, 2025
0b2c38e
less bevy specific examples
Vrixyz Mar 18, 2025
f22a3f6
independant example for loading a glb to point cloud
Vrixyz Mar 18, 2025
c7fe2b3
fix some slippy lints
Vrixyz Mar 18, 2025
996eb87
better banana cut
Vrixyz Mar 18, 2025
2495f55
Merge branch 'sample_color_model' into text_to_collider
Vrixyz Mar 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[target.wasm32-unknown-unknown]
runner = "wasm-server-runner"
runner = "wasm-server-runner"
# Needed for getrandom/uuid: https://github.com/uuid-rs/uuid/issues/792
rustflags = ['--cfg', 'getrandom_backend="wasm_js"']
28 changes: 28 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ members = [
"crates/wgsparkl-testbed3d",
"crates/wgsparkl2d",
"crates/wgsparkl3d",
"crates/text_to_collider",
"examples3d",
"examples2d",
]
resolver = "2"

Expand All @@ -23,6 +26,31 @@ rust.unexpected_cfgs = { level = "warn", check-cfg = [
] }

[patch.crates-io]
# parry2d = { path = "../parry/crates/parry2d" }
# parry3d = { path = "../parry/crates/parry3d" }
# encase = { path = "../encase" }
# wgcore = { path = "../wgmath/crates/wgcore" }
# wgebra = { path = "../wgmath/crates/wgebra" }
# wgparry2d = { path = "../wgmath/crates/wgparry/crates/wgparry2d" }
# wgparry3d = { path = "../wgmath/crates/wgparry/crates/wgparry3d" }
# wgrapier2d = { path = "../wgmath/crates/wgrapier/crates/wgrapier2d" }
# wgrapier3d = { path = "../wgmath/crates/wgrapier/crates/wgrapier3d" }

parry2d = { git = "https://github.com/dimforge/parry.git", rev = "407fb449504dde7ba0a3d80a8de7e37ac991a77a" }
parry3d = { git = "https://github.com/dimforge/parry.git", rev = "407fb449504dde7ba0a3d80a8de7e37ac991a77a" }
encase = { git = "https://github.com/sebcrozet/encase.git", rev = "6755c1414c225cbeac9fde1ff9394b70d3b05404" }
# wgcore = { git = "https://github.com/dimforge/wgmath.git", rev = "32b54c802be6040c5f003e7d3def4a33e4730d92" }
wgcore = { git = "https://github.com/dimforge/wgmath.git", branch = "wgml-chat" }
wgcore-derive = { git = "https://github.com/dimforge/wgmath.git", branch = "wgml-chat" }
wgebra = { git = "https://github.com/dimforge/wgmath.git", branch = "wgml-chat" }
# wgparry2d = { git = "https://github.com/dimforge/wgmath.git", rev = "32b54c802be6040c5f003e7d3def4a33e4730d92" }
wgparry3d = { git = "https://github.com/dimforge/wgmath.git", branch = "wgml-chat" }
# wgrapier2d = { git = "https://github.com/dimforge/wgmath.git", rev = "32b54c802be6040c5f003e7d3def4a33e4730d92" }
wgrapier3d = { git = "https://github.com/dimforge/wgmath.git", branch = "wgml-chat" }
rapier3d = { git = "https://github.com/vrixyz/rapier.git", branch = "uber_physics_context" }

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

[profile.dev]
opt-level = 1
16 changes: 8 additions & 8 deletions build_wasm.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/bin/sh

cargo build --example elasticity2 --release --target wasm32-unknown-unknown --features dim2
cargo build --example elasticity3 --release --target wasm32-unknown-unknown --features dim3
wasm-bindgen --no-typescript --target web --out-dir dist2d --out-name elasticity2 ./target/wasm32-unknown-unknown/release/examples/elasticity2.wasm
wasm-bindgen --no-typescript --target web --out-dir dist3d --out-name elasticity3 ./target/wasm32-unknown-unknown/release/examples/elasticity3.wasm
wasm-opt -Oz -o ./dist2d/opt.wasm ./dist2d/elasticity2_bg.wasm && mv ./dist2d/opt.wasm ./dist2d/elasticity2_bg.wasm
wasm-opt -Oz -o ./dist3d/opt.wasm ./dist3d/elasticity3_bg.wasm && mv ./dist3d/opt.wasm ./dist3d/elasticity3_bg.wasm
# cargo build -p wgsparkl-examples-2d --release --target wasm32-unknown-unknown
cargo build -p wgsparkl-examples-3d --release --target wasm32-unknown-unknown
# wasm-bindgen --no-typescript --target web --out-dir dist2d --out-name wgsparkl-examples-2d ./target/wasm32-unknown-unknown/release/wgsparkl-examples-2d.wasm
wasm-bindgen --no-typescript --target web --out-dir dist3d --out-name wgsparkl-examples-3d ./target/wasm32-unknown-unknown/release/wgsparkl-examples-3d.wasm
# wasm-opt -Oz -o ./dist2d/opt.wasm ./dist2d/wgsparkl-examples-2d_bg.wasm && mv ./dist2d/opt.wasm ./dist2d/wgsparkl-examples-2d_bg.wasm
wasm-opt -Oz -o ./dist3d/opt.wasm ./dist3d/wgsparkl-examples-3d_bg.wasm && mv ./dist3d/opt.wasm ./dist3d/wgsparkl-examples-3d_bg.wasm

brotli ./dist2d/elasticity2_bg.wasm && mv ./dist2d/elasticity2_bg.wasm.br ./dist2d/elasticity2_bg.wasm
brotli ./dist3d/elasticity3_bg.wasm && mv ./dist3d/elasticity3_bg.wasm.br ./dist3d/elasticity3_bg.wasm
# brotli ./dist2d/wgsparkl-examples-2d_bg.wasm && mv ./dist2d/wgsparkl-examples-2d_bg.wasm.br ./dist2d/wgsparkl-examples-2d_bg.wasm
brotli ./dist3d/wgsparkl-examples-3d_bg.wasm && mv ./dist3d/wgsparkl-examples-3d_bg.wasm.br ./dist3d/wgsparkl-examples-3d_bg.wasm
18 changes: 18 additions & 0 deletions crates/text_to_collider/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "text_to_collider"
version = "0.1.0"
license = "Apache-2.0 OR Custom"
edition = "2021"

[lints]
workspace = true

[dependencies]
env_logger = "*"
cosmic-text = "*"
image = "*"
parry3d = "*"

[dev-dependencies]
bevy = "0.15"
rkyv = "0.8"
33 changes: 33 additions & 0 deletions crates/text_to_collider/examples/color_positions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::fs;

use bevy::math::Vec2;
use cosmic_text::Color;
use parry3d::{na::Vector2, shape::Cuboid};
use text_to_collider::{get_rects_for, Rect, HEIGHT, WIDTH};

fn main() {
let rects = get_rects_for("Wgsparkl 🌊✨");
let positions = std::fs::read("particles.bin")
.expect("Could not read particles.bin, generate it by running example sand3.");
let positions = rkyv::from_bytes::<Vec<[f32; 3]>, rkyv::rancor::Error>(&positions).unwrap();
let detection_radius = 2f32;
let colors = positions
.iter()
.map(|p| {
// dismiss the y coordinate
let pos_to_check =
Vec2::new(p[0], -p[2] + 20f32) * 8f32 + Vec2::new(WIDTH, 0f32) / 2f32;
if let Some(c) = rects.iter().find(|c| {
let c1 = Vec2::new(c.x as f32, c.y as f32);
c1.distance_squared(pos_to_check) < detection_radius
}) {
let color = c.color.as_rgba();
[color[0], color[1], color[2]]
} else {
[0, 55, 200]
}
})
.collect::<Vec<_>>();
let particle_bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&colors).unwrap();
std::fs::write("particles_colors.bin", &particle_bytes).unwrap();
}
69 changes: 69 additions & 0 deletions crates/text_to_collider/examples/display.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use bevy::{input::common_conditions::input_toggle_active, prelude::*};
use cosmic_text::Color;
use parry3d::{na::Vector2, shape::Cuboid};
use text_to_collider::{get_rects_for, Rect};

fn main() {
let rects = get_rects_for("Wgsparkl 🌊✨");

App::new()
.add_plugins(DefaultPlugins)
.insert_resource(Cuboids(rects.iter().map(|r| r.to_cuboid(2f32)).collect()))
.insert_resource(RectsStorage(rects))
.add_systems(Startup, setup)
.add_systems(
Update,
show_rects.run_if(input_toggle_active(true, KeyCode::Space)),
)
.add_systems(Update, show_cuboids)
.run();
}

#[derive(Resource)]
pub struct RectsStorage(pub Vec<Rect>);

#[derive(Resource)]
pub struct Cuboids(pub Vec<(Cuboid, Vector2<f32>, Color)>);

pub fn setup(mut commands: Commands) {
commands.spawn((Camera::default(), Camera2d));
}

pub fn show_rects(mut g: Gizmos, rects: Res<RectsStorage>) {
for r in rects.0.iter() {
let color = r.color.as_rgba();
g.rect(
Isometry3d::from_translation(Vec3::new(r.x as f32, r.y as f32, 0f32)),
Vec2::new(r.width as f32, r.height as f32),
bevy::prelude::Color::srgba_u8(color[0], color[1], color[2], color[3]),
);
}
}

pub fn show_cuboids(time: Res<Time>, mut g: Gizmos, cuboids: Res<Cuboids>) {
let detection_radius = 1f32;
for i in 0..8000 {
let t = ((time.elapsed_secs()) + i as f32 * 10.5) * 0.1f32;
let pos_to_check = Vec2::new(
(((t * (0.5 + (i + 1) as f32 / 5000f32) * 0.7f32).cos() + 1f32) / 2f32) * 500f32,
(((t * (0.5 + (i + 1) as f32 / 5000f32) * 0.71f32).cos() + 1f32) / 2f32) * -84f32,
);
if let Some(c) = cuboids.0.iter().find(|c| {
let c1 = Vec2::new(c.1.x, c.1.y);
c1.distance_squared(pos_to_check) < detection_radius
}) {
let color = c.2.as_rgba();
g.sphere(
Isometry3d::from_translation(pos_to_check.extend(0f32)),
detection_radius,
bevy::prelude::Color::srgba_u8(color[0], color[1], color[2], color[3]),
);
} else {
g.sphere(
Isometry3d::from_translation(pos_to_check.extend(0f32)),
detection_radius,
bevy::prelude::Color::srgba_u8(200, 0, 0, 255),
);
}
}
}
96 changes: 96 additions & 0 deletions crates/text_to_collider/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

use cosmic_text::{
Attrs, Buffer, Color, Edit, Editor, Family, FontSystem, Metrics, Shaping, SwashCache,
};
use parry3d::{
na::{Vector2, Vector3},
shape::Cuboid,
};

pub const WIDTH: f32 = 523f32;
pub const HEIGHT: f32 = 256f32;

pub fn get_rects_for(string: &str) -> Vec<Rect> {
let mut font_system = FontSystem::new();
let mut swash_cache = SwashCache::new();

let metrics = Metrics::new(32.0, 44.0);
let mut editor = Editor::new(Buffer::new_empty(metrics.scale(1f32)));
let mut editor = editor.borrow_with(&mut font_system);

editor.with_buffer_mut(|buffer| {
buffer.set_size(Some(WIDTH), Some(HEIGHT));
let attrs = Attrs::new();
let comic_attrs = attrs.family(Family::Name("Comic Neue"));

let spans: &[(&str, Attrs)] =
&[(string, comic_attrs.metrics(Metrics::relative(64.0, 1.2)))];

buffer.set_rich_text(spans.iter().copied(), comic_attrs, Shaping::Advanced);
});

editor.shape_as_needed(true);

let font_color = Color::rgb(0xFF, 0xFF, 0xFF);
let cursor_color = Color(0);
let selection_color = Color::rgba(0xFF, 0xFF, 0xFF, 0x33);
let selected_text_color = Color::rgb(0xA0, 0xA0, 0xFF);
let mut rects = Vec::new();
editor.draw(
&mut swash_cache,
font_color,
cursor_color,
selection_color,
selected_text_color,
|x, y, lw, lh, color| {
if color.a() == 0 {
return;
}
rects.push(Rect {
x,
// invert y for bevy.
y: -y,
width: lw,
height: lh,
color,
})
},
);
rects
}

#[derive(Debug)]
pub struct Rect {
/// Left of the rect
pub x: i32,
/// Top of the rect
pub y: i32,
/// Width of the rect
pub width: u32,
/// Height of the rect
pub height: u32,
/// Color of the rect
pub color: Color,
}

impl Rect {
pub fn get_center(&self) -> (f32, f32) {
(
self.x as f32 - self.width as f32 / 2f32,
self.y as f32 + self.height as f32 / 2f32,
)
}
pub fn to_cuboid(&self, half_extent_z: f32) -> (Cuboid, Vector2<f32>, Color) {
let center = self.get_center();
return (
Cuboid::new(Vector3::new(
self.width as f32 / 2f32,
self.height as f32 / 2f32,
half_extent_z,
)),
Vector2::new(center.0, center.1),
self.color,
);
}
}
24 changes: 16 additions & 8 deletions crates/wgsparkl-testbed2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ path = "../../src_testbed/lib.rs"
required-features = ["dim2"]

[features]
default = ["dim2"]
dim2 = []
default_features = ["dim2"]

[dependencies]
nalgebra = { workspace = true, features = ["rand"] }
Expand All @@ -23,17 +23,25 @@ naga_oil = { workspace = true }
bytemuck = { workspace = true }
async-channel = { workspace = true }

wgcore = { version = "0.2", path = "../../../wgmath/crates/wgcore" }
wgebra = { version = "0.2", path = "../../../wgmath/crates/wgebra" }
wgparry2d = { version = "0.2", path = "../../../wgmath/crates/wgparry/crates/wgparry2d" }
wgcore = "0.2"
wgebra = "0.2"
wgparry2d = "0.2"

futures-test = "0.3"
serial_test = "3"
approx = "0.5"
async-std = { version = "1", features = ["attributes"] }
bevy = { version = "0.15.0", features = ["shader_format_glsl", "shader_format_spirv", "webgpu"] }
bevy = { version = "0.15.0", features = [
"shader_format_glsl",
"shader_format_spirv",
"webgpu",
] }
#bevy_wasm_window_resize = "0.4"
#bevy_editor_cam = "0.3"
#bevy_mod_picking = { version = "0.20", default-features = false }
bevy_egui = { version = "0.31", default-features = false, features = ["default_fonts", "render"] }
bevy_editor_cam = "0.5"
bevy_egui = { version = "0.31", default-features = false, features = [
"default_fonts",
"render",
] }
bevy_sprite = "0.15"
wgsparkl2d = { path = "../wgsparkl2d" }
futures = "0.3"
22 changes: 15 additions & 7 deletions crates/wgsparkl-testbed3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ path = "../../src_testbed/lib.rs"
required-features = ["dim3"]

[features]
default = ["dim3"]
dim3 = []
default_features = ["dim3"]

[dependencies]
nalgebra = { workspace = true, features = ["rand"] }
Expand All @@ -23,17 +23,25 @@ naga_oil = { workspace = true }
bytemuck = { workspace = true }
async-channel = { workspace = true }

wgcore = { version = "0.2", path = "../../../wgmath/crates/wgcore" }
wgebra = { version = "0.2", path = "../../../wgmath/crates/wgebra" }
wgparry3d = { version = "0.2", path = "../../../wgmath/crates/wgparry/crates/wgparry3d" }
wgcore = "0.2"
wgebra = "0.2"
wgparry3d = "0.2"

futures-test = "0.3"
serial_test = "3"
approx = "0.5"
async-std = { version = "1", features = ["attributes"] }
bevy = { version = "0.15.0", features = ["shader_format_glsl", "shader_format_spirv", "webgpu"] }
#bevy_editor_cam = "0.3"
bevy = { version = "0.15.0", features = [
"shader_format_glsl",
"shader_format_spirv",
"webgpu",
] }
bevy_editor_cam = "0.5"
#bevy_mod_picking = { version = "0.20", default-features = false }
#bevy_wasm_window_resize = "0.4"
bevy_egui = { version = "0.31", default-features = false, features = ["default_fonts", "render"] }
bevy_egui = { version = "0.31", default-features = false, features = [
"default_fonts",
"render",
] }
wgsparkl3d = { path = "../wgsparkl3d" }
futures = "0.3"
Loading