cloth

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