update deps; tweak constants
This commit is contained in:
parent
57e28360a0
commit
de5f28b4f7
4 changed files with 101 additions and 55 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -10,15 +10,15 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.9.0"
|
version = "2.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.20"
|
version = "1.2.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
|
checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
33
src/link.rs
33
src/link.rs
|
|
@ -1,36 +1,35 @@
|
||||||
use crate::particle::Particle;
|
use crate::particle::Particle;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
p1: Rc<RefCell<Particle>>,
|
p1: Rc<RefCell<Particle>>,
|
||||||
p2: Rc<RefCell<Particle>>,
|
p2: Rc<RefCell<Particle>>,
|
||||||
length: f32
|
length: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Link {
|
impl Link {
|
||||||
pub fn new(p1: Rc<RefCell<Particle>>, p2: Rc<RefCell<Particle>>, length: f32) -> Self {
|
pub fn new(p1: Rc<RefCell<Particle>>, p2: Rc<RefCell<Particle>>, length: f32) -> Self {
|
||||||
Link {
|
Link { p1, p2, length }
|
||||||
p1: p1,
|
|
||||||
p2: p2,
|
|
||||||
length: length
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn solve(&mut self) {
|
pub fn solve(&mut self) {
|
||||||
let vec = self.p2.borrow().pos - self.p1.borrow().pos;
|
let vec = self.p2.borrow().pos - self.p1.borrow().pos;
|
||||||
let vec_len = (vec.x*vec.x + vec.y*vec.y).sqrt();
|
let vec_len = (vec.x * vec.x + vec.y * vec.y).sqrt();
|
||||||
let vec_norm = vec/vec_len;
|
|
||||||
|
|
||||||
let max_stretch = 50.;
|
if vec_len > self.length {
|
||||||
let clamped_len = vec_len.min(self.length + max_stretch);
|
let vec_norm = vec / vec_len;
|
||||||
|
|
||||||
let displacement = clamped_len - vec_len;
|
let max_stretch = 0.5;
|
||||||
let stiffness = 99.;
|
let clamped_len = vec_len.min(self.length + max_stretch);
|
||||||
let vec_scaled = vec_norm * displacement * stiffness;
|
|
||||||
|
|
||||||
let damping = 0.98;
|
let displacement = clamped_len - vec_len;
|
||||||
self.p1.borrow_mut().apply_force(-vec_scaled * damping);
|
let stiffness = 999.;
|
||||||
self.p2.borrow_mut().apply_force(vec_scaled * damping);
|
let vec_scaled = vec_norm * displacement * stiffness;
|
||||||
|
|
||||||
|
let damping = 0.99;
|
||||||
|
self.p1.borrow_mut().apply_force(-vec_scaled * damping);
|
||||||
|
self.p2.borrow_mut().apply_force(vec_scaled * damping);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
src/main.rs
103
src/main.rs
|
|
@ -1,9 +1,9 @@
|
||||||
use sfml::graphics::*;
|
|
||||||
use sfml::window::*;
|
|
||||||
use sfml::SfResult;
|
use sfml::SfResult;
|
||||||
use sfml::system::{Vector2f, Clock};
|
use sfml::graphics::*;
|
||||||
use std::rc::Rc;
|
use sfml::system::{Clock, Vector2f};
|
||||||
|
use sfml::window::*;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
mod particle;
|
mod particle;
|
||||||
use particle::Particle;
|
use particle::Particle;
|
||||||
|
|
@ -15,8 +15,8 @@ const GRAVITY: f32 = 100.;
|
||||||
|
|
||||||
fn populate_particles(particles: &mut Vec<Rc<RefCell<Particle>>>, num: u32, cols: u32) {
|
fn populate_particles(particles: &mut Vec<Rc<RefCell<Particle>>>, num: u32, cols: u32) {
|
||||||
for i in 0..num {
|
for i in 0..num {
|
||||||
let x_pos = 200. + 50. * (i % cols) as f32;
|
let x_pos = 150. + 20. * (i % cols) as f32;
|
||||||
let y_pos = 100. + 50. * (i / cols) as f32;
|
let y_pos = 80. + 20. * (i / cols) as f32;
|
||||||
let immovable = i < cols;
|
let immovable = i < cols;
|
||||||
let particle = Particle::new(Vector2f::new(x_pos, y_pos), immovable);
|
let particle = Particle::new(Vector2f::new(x_pos, y_pos), immovable);
|
||||||
particles.push(Rc::new(RefCell::new(particle)));
|
particles.push(Rc::new(RefCell::new(particle)));
|
||||||
|
|
@ -31,16 +31,41 @@ fn populate_circles(circles: &mut Vec<CircleShape>, num: u32, rad: f32, pts: usi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_links(links: &mut Vec<Link>, particles: &Vec<Rc<RefCell<Particle>>>, num: u32) {
|
/*fn populate_links(links: &mut Vec<Link>, particles: &[Rc<RefCell<Particle>>], num: u32) {
|
||||||
for i in 0..(num-1) {
|
for i in 0..(num - 1) {
|
||||||
let p1 = &particles[i as usize];
|
let p1 = &particles[i as usize];
|
||||||
let p2 = &particles[(i as usize)+1];
|
let p2 = &particles[(i as usize) + 1];
|
||||||
//let vec = p2.borrow().pos - p1.borrow().pos;
|
//let vec = p2.borrow().pos - p1.borrow().pos;
|
||||||
//let dist = (vec.x*vec.x + vec.y*vec.y).sqrt();
|
//let dist = (vec.x*vec.x + vec.y*vec.y).sqrt();
|
||||||
let link = Link::new(Rc::clone(p1), Rc::clone(p2), 100.);
|
let link = Link::new(Rc::clone(p1), Rc::clone(p2), 100.);
|
||||||
|
|
||||||
links.push(link);
|
links.push(link);
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fn populate_links(
|
||||||
|
links: &mut Vec<Link>,
|
||||||
|
particles: &[Rc<RefCell<Particle>>],
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
) {
|
||||||
|
for y in 0..height {
|
||||||
|
for x in 0..width {
|
||||||
|
let i = y * width + x;
|
||||||
|
|
||||||
|
if x < width - 1 {
|
||||||
|
let right = i + 1;
|
||||||
|
let link = Link::new(Rc::clone(&particles[i]), Rc::clone(&particles[right]), 20.);
|
||||||
|
links.push(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
if y < height - 1 {
|
||||||
|
let below = i + width;
|
||||||
|
let link = Link::new(Rc::clone(&particles[i]), Rc::clone(&particles[below]), 20.);
|
||||||
|
links.push(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fn populate_lines(lines: &mut Vec<RectangleShape>, circles: &Vec<CircleShape>, num: u32) {
|
/*fn populate_lines(lines: &mut Vec<RectangleShape>, circles: &Vec<CircleShape>, num: u32) {
|
||||||
|
|
@ -53,25 +78,31 @@ fn apply_forces(particles: &Vec<Rc<RefCell<Particle>>>) {
|
||||||
for particle in particles {
|
for particle in particles {
|
||||||
let mut borrowed = particle.borrow_mut();
|
let mut borrowed = particle.borrow_mut();
|
||||||
borrowed.apply_force(Vector2f::new(0., GRAVITY));
|
borrowed.apply_force(Vector2f::new(0., GRAVITY));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_particles(particles: &Vec<Rc<RefCell<Particle>>>, dt: f32) {
|
fn update_particles(particles: &Vec<Rc<RefCell<Particle>>>, dt: f32) {
|
||||||
for particle in particles { particle.borrow_mut().update(dt); }
|
for particle in particles {
|
||||||
|
particle.borrow_mut().update(dt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve_links(links: &mut Vec<Link>) {
|
fn solve_links(links: &mut Vec<Link>) {
|
||||||
for link in links { link.solve(); }
|
for link in links {
|
||||||
|
link.solve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_positions(circles: &mut Vec<CircleShape>, particles: &Vec<Rc<RefCell<Particle>>>) {
|
fn update_positions(circles: &mut Vec<CircleShape>, particles: &[Rc<RefCell<Particle>>]) {
|
||||||
for (index, circle) in circles.iter_mut().enumerate() {
|
for (index, circle) in circles.iter_mut().enumerate() {
|
||||||
circle.set_position(particles[index].borrow().pos);
|
circle.set_position(particles[index].borrow().pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_all(window: &mut RenderWindow, circles: &Vec<CircleShape>, /* lines: &Vec<RectangleShape> */) {
|
fn draw_all(
|
||||||
|
window: &mut RenderWindow,
|
||||||
|
circles: &Vec<CircleShape>, /* lines: &Vec<RectangleShape> */
|
||||||
|
) {
|
||||||
for circle in circles {
|
for circle in circles {
|
||||||
window.draw(circle);
|
window.draw(circle);
|
||||||
}
|
}
|
||||||
|
|
@ -82,27 +113,31 @@ fn draw_all(window: &mut RenderWindow, circles: &Vec<CircleShape>, /* lines: &Ve
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> SfResult<()> {
|
fn main() -> SfResult<()> {
|
||||||
let mut window = RenderWindow::new(
|
let mut window = RenderWindow::new((800, 600), "Verlet", Style::CLOSE, &Default::default())?;
|
||||||
(800, 600),
|
|
||||||
"Verlet",
|
|
||||||
Style::CLOSE,
|
|
||||||
&Default::default()
|
|
||||||
)?;
|
|
||||||
window.set_framerate_limit(60);
|
window.set_framerate_limit(60);
|
||||||
|
|
||||||
let mut clock = Clock::start()?;
|
let mut clock = Clock::start()?;
|
||||||
|
|
||||||
let particle_count: u32 = 60;
|
let mouse_pos_prev = window.mouse_position();
|
||||||
let column_count: u32 = 10;
|
let mut mouse_coords_prev = window.map_pixel_to_coords_current_view(mouse_pos_prev);
|
||||||
|
|
||||||
|
let particle_count: u32 = 600;
|
||||||
|
let column_count: u32 = 30;
|
||||||
|
let row_count: u32 = particle_count / column_count;
|
||||||
|
|
||||||
let mut particles: Vec<Rc<RefCell<Particle>>> = vec![];
|
let mut particles: Vec<Rc<RefCell<Particle>>> = vec![];
|
||||||
populate_particles(&mut particles, particle_count, column_count);
|
populate_particles(&mut particles, particle_count, column_count);
|
||||||
|
|
||||||
let mut links: Vec<Link> = vec![];
|
let mut links: Vec<Link> = vec![];
|
||||||
populate_links(&mut links, &particles, particle_count);
|
populate_links(
|
||||||
|
&mut links,
|
||||||
|
&particles,
|
||||||
|
column_count as usize,
|
||||||
|
row_count as usize,
|
||||||
|
);
|
||||||
// let mut link3 = Link::new(Rc::clone(&(particles[0])), Rc::clone(&(particles[2])), 200.);
|
// let mut link3 = Link::new(Rc::clone(&(particles[0])), Rc::clone(&(particles[2])), 200.);
|
||||||
|
|
||||||
let radius: f32 = 32.;
|
let radius: f32 = 8.;
|
||||||
let point_count: usize = 100;
|
let point_count: usize = 100;
|
||||||
let mut circles: Vec<CircleShape> = vec![];
|
let mut circles: Vec<CircleShape> = vec![];
|
||||||
populate_circles(&mut circles, particle_count, radius, point_count);
|
populate_circles(&mut circles, particle_count, radius, point_count);
|
||||||
|
|
@ -112,17 +147,27 @@ fn main() -> SfResult<()> {
|
||||||
|
|
||||||
while window.is_open() {
|
while window.is_open() {
|
||||||
while let Some(event) = window.poll_event() {
|
while let Some(event) = window.poll_event() {
|
||||||
|
#[allow(clippy::single_match)]
|
||||||
match event {
|
match event {
|
||||||
Event::Closed => window.close(),
|
Event::Closed => window.close(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mouse_pos = window.mouse_position();
|
||||||
|
let mouse_coords = window.map_pixel_to_coords_current_view(mouse_pos);
|
||||||
|
let mouse_vel = mouse_coords - mouse_coords_prev;
|
||||||
|
mouse_coords_prev = mouse_coords;
|
||||||
|
|
||||||
if mouse::Button::is_pressed(mouse::Button::Left) {
|
if mouse::Button::is_pressed(mouse::Button::Left) {
|
||||||
let mouse_pos = window.mouse_position();
|
for particle in &particles {
|
||||||
let mouse_coords = window.map_pixel_to_coords_current_view(mouse_pos);
|
let p_pos = particle.borrow().pos;
|
||||||
let p_pos = particles[10].borrow().pos;
|
let dist_vec = mouse_coords - p_pos;
|
||||||
particles[10].borrow_mut().apply_force((mouse_coords - p_pos)*4.);
|
let dist = (dist_vec.x * dist_vec.x + dist_vec.y * dist_vec.y).sqrt();
|
||||||
|
if dist < 20. {
|
||||||
|
particle.borrow_mut().apply_force(mouse_vel * 128.);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dt = clock.restart().as_seconds();
|
let dt = clock.restart().as_seconds();
|
||||||
|
|
@ -137,7 +182,7 @@ fn main() -> SfResult<()> {
|
||||||
update_positions(&mut circles, &particles);
|
update_positions(&mut circles, &particles);
|
||||||
|
|
||||||
window.clear(Color::BLACK);
|
window.clear(Color::BLACK);
|
||||||
draw_all(&mut window, &circles, /* &lines */);
|
draw_all(&mut window, &circles /* &lines */);
|
||||||
window.display();
|
window.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,26 +5,28 @@ pub struct Particle {
|
||||||
prev_pos: Vector2f,
|
prev_pos: Vector2f,
|
||||||
accel: Vector2f,
|
accel: Vector2f,
|
||||||
|
|
||||||
immovable: bool
|
immovable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Particle {
|
impl Particle {
|
||||||
pub fn new(pos: Vector2f, immovable: bool) -> Self {
|
pub fn new(pos: Vector2f, immovable: bool) -> Self {
|
||||||
Particle {
|
Particle {
|
||||||
pos: pos,
|
pos,
|
||||||
prev_pos: pos,
|
prev_pos: pos,
|
||||||
accel: Vector2f::default(),
|
accel: Vector2f::default(),
|
||||||
|
|
||||||
immovable: immovable
|
immovable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_force(&mut self, force: Vector2f) {
|
pub fn apply_force(&mut self, force: Vector2f) {
|
||||||
|
if self.immovable {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.accel += force;
|
self.accel += force;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, dt: f32) {
|
pub fn update(&mut self, dt: f32) {
|
||||||
if self.immovable { return; }
|
|
||||||
let damping = 0.99;
|
let damping = 0.99;
|
||||||
let vel = (self.pos - self.prev_pos) * damping;
|
let vel = (self.pos - self.prev_pos) * damping;
|
||||||
let new_pos = self.pos + vel + self.accel * (dt * dt);
|
let new_pos = self.pos + vel + self.accel * (dt * dt);
|
||||||
|
|
@ -33,4 +35,4 @@ impl Particle {
|
||||||
self.pos = new_pos;
|
self.pos = new_pos;
|
||||||
self.accel = Vector2f::default();
|
self.accel = Vector2f::default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue