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 }
|