coeng

view src/co_phys.cc @ 8:8cce82794f90

seems to work nicely
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Feb 2015 05:14:20 +0200
parents 2f872a179914
children
line source
1 #include <assert.h>
2 #include <vmath/vmath.h>
3 #include "co_phys.h"
4 #include "sim.h"
5 #include "co_collider.h"
7 #define FIXED_MASS 1e9
9 static CoRigid reg_co_rigid;
11 static Component *cons_rigid() { return new CoRigid; }
13 CoRigid::CoRigid()
14 {
15 mass = 1.0;
16 elast = 0.85;
17 friction = 0.0;
18 fixed = false;
20 name = "rigid";
21 co_prs = 0;
23 register_component(name, cons_rigid);
24 }
26 const char **CoRigid::update_before() const
27 {
28 static const char *before[] = { "prs", 0 };
29 return before;
30 }
32 void CoRigid::set_fixed(bool f)
33 {
34 fixed = f;
35 }
37 bool CoRigid::get_fixed() const
38 {
39 return fixed;
40 }
42 void CoRigid::set_mass(float mass)
43 {
44 this->mass = mass;
45 }
47 float CoRigid::get_mass() const
48 {
49 return fixed ? FIXED_MASS : mass;
50 }
52 void CoRigid::add_impulse(const Vector3 &v)
53 {
54 impulse += v;
55 }
57 void CoRigid::update(float dt)
58 {
59 if(!gobj || fixed) return;
61 if(!co_prs) {
62 if(!(co_prs = COCAST(CoPRS, gobj->get_component("prs")))) {
63 assert(co_prs);
64 return;
65 }
66 }
68 // collision detection
69 CoCollider *co_col;
70 if(world && (co_col = gobj_co_collider(gobj, COGET_FAIL))) {
71 HitPoint hit;
73 // dot product subexpression is to ignore collisions when moving OUT
74 // of the object after an interpenetration
75 if(world->collide(co_col, &hit) && dot_product(vel, hit.normal) <= 0.0) {
76 Vector3 refl = -vel.reflection(hit.normal);
77 Vector3 vert = hit.normal * dot_product(refl, hit.normal);
78 Vector3 tang = refl - vert;
79 vel = vert * elast + tang * friction;
80 // TODO add an impulse to the other object and take account of the relative masses
81 }
82 }
85 float damping = world ? world->get_damping() : 0.005;
87 Vector3 newpos = co_prs->pos + vel * dt;
89 Vector3 accel = impulse;
90 impulse.x = impulse.y = impulse.z = 0.0f; // reset impulse
92 if(world) {
93 accel += world->get_gravity();
94 }
96 vel = (vel - vel * damping * dt) + accel * dt;
97 if(vel.length() < 1e-3) {
98 vel.x = vel.y = vel.z = 0.0f;
99 }
100 co_prs->pos = newpos;
101 }
103 CoRigid *gobj_co_rigid(const GObject *obj, bool nofail)
104 {
105 CoRigid *co = COCAST(CoRigid, obj->get_component("rigid"));
106 if(co) return co;
108 return nofail ? &reg_co_rigid : 0;
109 }