Skip to content

Commit

Permalink
Improve physics calculation and customization (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
ManevilleF authored Jun 7, 2024
1 parent b4e5afc commit 0f7f863
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 15 deletions.
2 changes: 1 addition & 1 deletion examples/2d_cloth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn setup(mut commands: Commands) {
),
..Default::default()
},
VerletPoint::default(),
VerletPoint::new(0.2),
Name::new(format!("Point {}", i)),
));
if j == 0 {
Expand Down
50 changes: 44 additions & 6 deletions examples/2d_cloth_cutter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use bevy::{math::Vec3Swizzles, prelude::*, window::PrimaryWindow};
use bevy_verlet::prelude::*;

const MOUSE_RADIUS: f32 = 20.0;

fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
Expand All @@ -13,7 +15,7 @@ fn main() {
}))
.add_plugins(VerletPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, cut_sticks)
.add_systems(Update, (drag_points, cut_sticks))
.run();
}

Expand All @@ -31,7 +33,7 @@ fn setup(mut commands: Commands) {
origin_y + (-10. * j as f32),
0.,
)),
VerletPoint::default(),
VerletPoint::new(0.1),
Name::new(format!("Point {}", i)),
));
if j == 0 && i % 2 == 0 {
Expand Down Expand Up @@ -67,7 +69,7 @@ fn spawn_stick(
point_b_entity: *other_entity,
length,
},
VerletStickMaxTension(5.),
VerletStickMaxTension(3.),
));
}
}
Expand All @@ -86,24 +88,60 @@ fn cut_sticks(
mouse_input: Res<ButtonInput<MouseButton>>,
windows: Query<&Window, With<PrimaryWindow>>,
) {
if !mouse_input.pressed(MouseButton::Left) {
if !mouse_input.pressed(MouseButton::Right) {
return;
}
let window = windows.single();
let p = match window.cursor_position() {
None => return,
Some(p) => mouse_coords(window, p),
};
let l = 20.;
for (entity, stick) in sticks.iter() {
let [a, b] = points
.get_many(stick.entities())
.map(|v| v.map(|t| t.translation.xy()))
.unwrap();
let distance_a = p.distance(a);
let distance_b = p.distance(b);
if distance_a > 0. && distance_a <= l && distance_b > 0. && distance_b <= l {
if distance_a > 0.
&& distance_a <= MOUSE_RADIUS
&& distance_b > 0.
&& distance_b <= MOUSE_RADIUS
{
commands.entity(entity).despawn_recursive();
}
}
}

fn drag_points(
mut points: Query<(Entity, &mut Transform), With<VerletPoint>>,
mouse_input: Res<ButtonInput<MouseButton>>,
windows: Query<&Window, With<PrimaryWindow>>,
mut dragged: Local<Vec<Entity>>,
) {
if !mouse_input.pressed(MouseButton::Left) {
*dragged = vec![];
return;
}
let window = windows.single();
let p = match window.cursor_position() {
None => return,
Some(p) => mouse_coords(window, p),
};
if dragged.is_empty() {
*dragged = points
.iter()
.filter_map(|(e, tr)| {
let point = tr.translation.xy();
let dist = point.distance(p);
(dist <= MOUSE_RADIUS).then_some(e)
})
.collect();
return;
};
let mut iter = points.iter_many_mut(&*dragged);
while let Some((_, mut tr)) = iter.fetch_next() {
tr.translation.x = p.x;
tr.translation.y = p.y;
}
}
2 changes: 1 addition & 1 deletion examples/2d_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn setup_free_line(mut commands: Commands) {
for i in 0..=points_count {
let mut cmd = commands.spawn((
sprite_bundle(Color::WHITE, Vec2::new(50. * i as f32, 300.)),
VerletPoint::default(),
VerletPoint::new(0.1),
Name::new(format!("Point {}", i)),
));
if previous_entity.is_none() {
Expand Down
2 changes: 1 addition & 1 deletion examples/3d_cloth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn setup(
let mesh = meshes.add(Cuboid::new(1., 1., 1.));
let stick_length: f32 = 2.;
let (origin_x, origin_y) = (-5., 10.);
let (points_x_count, points_y_count) = (20, 15);
let (points_x_count, points_y_count) = (30, 25);
let mut entities = Vec::new();
for j in 0..points_y_count {
for i in 0..points_x_count {
Expand Down
30 changes: 29 additions & 1 deletion src/components/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,35 @@ use bevy::prelude::{Component, Reflect, Vec3};

/// Main verlet physics component.
/// Any entity with this component will have physics applied to it
#[derive(Debug, Clone, Component, Default, Reflect)]
#[derive(Debug, Clone, Component, Reflect)]
pub struct VerletPoint {
pub(crate) old_position: Option<Vec3>,
/// Point mass, defaults to 1.0
pub mass: f32,
}

impl Default for VerletPoint {
fn default() -> Self {
Self {
old_position: None,
mass: 1.0,
}
}
}

impl VerletPoint {
/// Creates a point with a custom mass value
///
/// # Panics
///
/// Panics if `mass` is lesser or equal to zero
#[inline]
#[must_use]
pub fn new(mass: f32) -> Self {
assert!(mass > 0.0);
Self {
mass,
old_position: None,
}
}
}
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Default for VerletConfig {
fn default() -> Self {
Self {
gravity: Vec3::new(0., -9.81, 0.),
friction: 0.02,
friction: 0.01,
sticks_computation_depth: 5,
parallel_processing: true,
}
Expand Down
21 changes: 17 additions & 4 deletions src/systems/points.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ fn update_point(
point: &mut VerletPoint,
acceleration: Vec3,
friction: f32,
dt: f32,
) {
let position = transform.translation;
let velocity = point.old_position.map_or(Vec3::ZERO, |pos| position - pos);
transform.translation += velocity * friction + acceleration;
transform.translation += velocity * friction + (acceleration / point.mass) * friction * dt * dt;
point.old_position = Some(position);
}

Expand All @@ -22,18 +23,30 @@ pub fn update_points(
time: Res<Time>,
config: Res<VerletConfig>,
) {
let gravity = config.gravity * time.delta_seconds();
let gravity = config.gravity;
let friction = config.friction_coefficient();

if config.parallel_processing {
points_query
.par_iter_mut()
.for_each(|(mut transform, mut point)| {
update_point(&mut transform, &mut point, gravity, friction);
update_point(
&mut transform,
&mut point,
gravity,
friction,
time.delta_seconds(),
);
});
} else {
for (mut transform, mut point) in &mut points_query {
update_point(&mut transform, &mut point, gravity, friction);
update_point(
&mut transform,
&mut point,
gravity,
friction,
time.delta_seconds(),
);
}
}
}

0 comments on commit 0f7f863

Please sign in to comment.