cloth

view src/simworld.cc @ 0:92983e143a03

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 11 Feb 2013 19:40:36 +0200
parents
children 2eac424f58b2
line source
1 #include "simworld.h"
3 SimWorld::SimWorld()
4 {
5 bbmin = Vector2(-1, -1);
6 bbmax = Vector2(1, 1);
7 grav = Vector3(0, -9.81, 0);
8 damping = 0.99;
9 }
11 void SimWorld::set_bounds(float xmin, float xmax, float ymin, float ymax)
12 {
13 bbmin.x = xmin;
14 bbmin.y = ymin;
15 bbmax.x = xmax;
16 bbmax.y = ymax;
17 }
19 void SimWorld::add_particle(Particle *p)
20 {
21 part.push_back(p);
22 }
24 bool SimWorld::collision(const Ray &ray, float rad, Collision *col) const
25 {
26 bool found = false;
28 Vector2 min = bbmin + Vector2(rad, rad);
29 Vector2 max = bbmax - Vector2(rad, rad);
31 // collision with the boundaries
32 Vector3 npos = ray.origin + ray.dir;
34 Vector3 col_pos, col_norm;
35 float d, col_depth = 0;
37 if((d = min.x - npos.x) > col_depth) {
38 col->pos = npos;
39 col->pos.x = min.x;
40 col->normal = Vector3(1, 0, 0);
41 col_depth = d;
42 found = true;
43 }
44 if((d = min.y - npos.z) > col_depth) {
45 col->pos = npos;
46 col->pos.z = min.y;
47 col->normal = Vector3(0, 0, 1);
48 col_depth = d;
49 found = true;
50 }
51 if((d = npos.x - max.x) > col_depth) {
52 col->pos = npos;
53 col->pos.x = max.x;
54 col->normal = Vector3(-1, 0, 0);
55 col_depth = d;
56 found = true;
57 }
58 if((d = npos.z - max.y) > col_depth) {
59 col->pos = npos;
60 col->pos.z = max.y;
61 col->normal = Vector3(0, 0, -1);
62 col_depth = d;
63 found = true;
64 }
66 return found;
67 }
69 void SimWorld::step(float dt)
70 {
71 for(size_t i=0; i<part.size(); i++) {
72 // add gravity
73 part[i]->add_force(grav * part[i]->get_mass());
75 part[i]->step(this, dt);
77 // handle collisions with other particles
78 for(size_t j=0; j<part.size(); j++) {
79 Collision col;
80 if(i != j && part[i]->collision(part[j], &col)) {
81 Vector3 rel_vel = part[j]->get_velocity() - part[i]->get_velocity();
83 float kn = 1.0 / part[i]->get_mass() + 1.0 / part[j]->get_mass();
84 float imp = dot_product(rel_vel, col.normal) * (col.elast + 1) / kn;
86 if(imp < 0.0) imp = 0.0;
88 Vector3 v = part[i]->get_position() - part[j]->get_position();
89 float dist_sq = v.length_sq();
90 float pen_depth_sq = part[i]->get_radius() + part[j]->get_radius() - dist_sq;
91 if(pen_depth_sq < 0.0) pen_depth_sq = 0.0;
93 part[i]->add_force(col.normal * imp * (1.0 / dt * pen_depth_sq + 1));
94 }
95 }
96 }
97 }
99 void SimWorld::draw_particles() const
100 {
101 for(size_t i=0; i<part.size(); i++) {
102 part[i]->draw();
103 }
104 }