coeng
changeset 6:2f872a179914
first component test:
- prs, xform, physics components with dependencies
- topological sort of components to update them in the correct order
- debug visualization component
todo: remove draw() from components, doesn't make sense
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 14 Feb 2015 07:27:12 +0200 |
parents | 0e5da17d589c |
children | af24cfbdf9b6 |
files | Makefile src/co_dbgvis.cc src/co_dbgvis.h src/co_phys.cc src/co_phys.h src/co_xform.cc src/co_xform.h src/comp.cc src/comp.h src/gobj.cc src/gobj.h src/sim.cc src/sim.h src/test.cc |
diffstat | 14 files changed, 511 insertions(+), 42 deletions(-) [+] |
line diff
1.1 --- a/Makefile Sat Feb 14 01:35:42 2015 +0200 1.2 +++ b/Makefile Sat Feb 14 07:27:12 2015 +0200 1.3 @@ -1,5 +1,6 @@ 1.4 ccsrc = $(wildcard src/*.cc) 1.5 obj = $(ccsrc:.cc=.o) 1.6 +dep = $(obj:.o=.d) 1.7 bin = test 1.8 1.9 warn = -pedantic -Wall 1.10 @@ -18,6 +19,15 @@ 1.11 $(bin): $(obj) 1.12 $(CXX) -o $@ $(obj) $(LDFLAGS) 1.13 1.14 +-include $(dep) 1.15 + 1.16 +%.d: %.cc 1.17 + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ 1.18 + 1.19 .PHONY: clean 1.20 clean: 1.21 rm -f $(obj) $(bin) 1.22 + 1.23 +.PHONY: cleandep 1.24 +cleandep: 1.25 + rm -f $(dep)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/co_dbgvis.cc Sat Feb 14 07:27:12 2015 +0200 2.3 @@ -0,0 +1,48 @@ 2.4 +#ifndef __APPLE__ 2.5 +#include <GL/glut.h> 2.6 +#else 2.7 +#include <GLUT/glut.h> 2.8 +#endif 2.9 +#include "co_dbgvis.h" 2.10 +#include "gobj.h" 2.11 + 2.12 +static CoSphereVis reg_co_sphere; 2.13 + 2.14 +static Component *cons_sphere() { return new CoSphereVis; } 2.15 + 2.16 + 2.17 +CoSphereVis::CoSphereVis() 2.18 + : color(1, 1, 1) 2.19 +{ 2.20 + name = "spherevis"; 2.21 + radius = 1.0; 2.22 + co_xform = 0; 2.23 + 2.24 + register_component(name, cons_sphere); 2.25 +} 2.26 + 2.27 +void CoSphereVis::update(float dt) 2.28 +{ 2.29 + if(!co_xform) { 2.30 + co_xform = COCAST(CoXForm, gobj->get_component("xform")); 2.31 + } 2.32 +} 2.33 + 2.34 +void CoSphereVis::draw() const 2.35 +{ 2.36 + if(co_xform) { 2.37 + Matrix4x4 xform = co_xform->xform.transposed(); 2.38 + 2.39 + glPushMatrix(); 2.40 + glMultMatrixf(xform.m[0]); 2.41 + } 2.42 + 2.43 + float diffuse[] = { color.x, color.y, color.z, 1.0f }; 2.44 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse); 2.45 + 2.46 + glutSolidSphere(radius, 16, 8); 2.47 + 2.48 + if(co_xform) { 2.49 + glPopMatrix(); 2.50 + } 2.51 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/co_dbgvis.h Sat Feb 14 07:27:12 2015 +0200 3.3 @@ -0,0 +1,22 @@ 3.4 +#ifndef CO_DBGVIS_H_ 3.5 +#define CO_DBGVIS_H_ 3.6 + 3.7 +#include "gobj.h" 3.8 +#include "comp.h" 3.9 +#include "co_xform.h" 3.10 + 3.11 +class CoSphereVis : public Component { 3.12 +protected: 3.13 + CoXForm *co_xform; 3.14 + 3.15 +public: 3.16 + float radius; 3.17 + Vector3 color; 3.18 + 3.19 + CoSphereVis(); 3.20 + 3.21 + void update(float dt); 3.22 + void draw() const; 3.23 +}; 3.24 + 3.25 +#endif // CO_DBGVIS_H_
4.1 --- a/src/co_phys.cc Sat Feb 14 01:35:42 2015 +0200 4.2 +++ b/src/co_phys.cc Sat Feb 14 07:27:12 2015 +0200 4.3 @@ -1,4 +1,6 @@ 4.4 +#include <assert.h> 4.5 #include "co_phys.h" 4.6 +#include "sim.h" 4.7 4.8 static CoRigid reg_co_rigid; 4.9 4.10 @@ -15,6 +17,42 @@ 4.11 register_component(name, cons_rigid); 4.12 } 4.13 4.14 -void CoRigid::update() 4.15 +const char **CoRigid::update_before() const 4.16 { 4.17 + static const char *before[] = { "prs", 0 }; 4.18 + return before; 4.19 } 4.20 + 4.21 +void CoRigid::add_impulse(const Vector3 &v) 4.22 +{ 4.23 + impulse += v; 4.24 +} 4.25 + 4.26 +void CoRigid::update(float dt) 4.27 +{ 4.28 + if(!gobj) return; 4.29 + 4.30 + if(!co_prs) { 4.31 + if(!(co_prs = COCAST(CoPRS, gobj->get_component("prs")))) { 4.32 + assert(co_prs); 4.33 + return; 4.34 + } 4.35 + } 4.36 + 4.37 + float damping = world ? world->get_damping() : 0.005; 4.38 + 4.39 + Vector3 newpos = co_prs->pos + vel * dt; 4.40 + 4.41 + Vector3 accel = impulse; 4.42 + impulse.x = impulse.y = impulse.z = 0.0f; // reset impulse 4.43 + 4.44 + if(world) { 4.45 + accel += world->get_gravity(); 4.46 + } 4.47 + 4.48 + vel = (vel - vel * damping * dt) + accel * dt; 4.49 + 4.50 + // TODO collisions 4.51 + 4.52 + co_prs->pos = newpos; 4.53 +}
5.1 --- a/src/co_phys.h Sat Feb 14 01:35:42 2015 +0200 5.2 +++ b/src/co_phys.h Sat Feb 14 07:27:12 2015 +0200 5.3 @@ -3,15 +3,27 @@ 5.4 5.5 #include <vmath/vmath.h> 5.6 #include "comp.h" 5.7 +#include "co_xform.h" 5.8 + 5.9 +class SimWorld; 5.10 5.11 class CoRigid : public Component { 5.12 +protected: 5.13 + CoPRS *co_prs; // cached PRS component of the parent object 5.14 + 5.15 + const char **update_before() const; 5.16 + 5.17 public: 5.18 + SimWorld *world; 5.19 float mass, elast, friction; 5.20 - Vector3 pos, vel; 5.21 + Vector3 vel, force; 5.22 + Vector3 impulse; 5.23 5.24 CoRigid(); 5.25 5.26 - void update(); 5.27 + void add_impulse(const Vector3 &v); 5.28 + 5.29 + void update(float dt); 5.30 }; 5.31 5.32 #endif // COMP_PHYS_H_
6.1 --- a/src/co_xform.cc Sat Feb 14 01:35:42 2015 +0200 6.2 +++ b/src/co_xform.cc Sat Feb 14 07:27:12 2015 +0200 6.3 @@ -15,20 +15,28 @@ 6.4 register_component(name, cons_xform); 6.5 } 6.6 6.7 +// ---- class CoPRS ---- 6.8 + 6.9 CoPRS::CoPRS() 6.10 + : scale(1, 1, 1) 6.11 { 6.12 name = "prs"; 6.13 6.14 register_component(name, cons_prs); 6.15 } 6.16 6.17 -void CoPRS::update() 6.18 +const char **CoPRS::update_before() const 6.19 +{ 6.20 + static const char *before[] = { "xform", 0 }; 6.21 + return before; 6.22 +} 6.23 + 6.24 +void CoPRS::update(float dt) 6.25 { 6.26 if(!gobj) return; 6.27 6.28 if(!co_xform) { 6.29 - Component *co = gobj->get_component("xform"); 6.30 - if(!co || !(co_xform = dynamic_cast<CoXForm*>(co))) { 6.31 + if(!(co_xform = COCAST(CoXForm, gobj->get_component("xform")))) { 6.32 assert(co_xform); 6.33 return; 6.34 }
7.1 --- a/src/co_xform.h Sat Feb 14 01:35:42 2015 +0200 7.2 +++ b/src/co_xform.h Sat Feb 14 07:27:12 2015 +0200 7.3 @@ -12,16 +12,18 @@ 7.4 }; 7.5 7.6 class CoPRS : public Component { 7.7 -private: 7.8 +protected: 7.9 CoXForm *co_xform; // cached xform component of the parent object 7.10 7.11 + const char **update_before() const; 7.12 + 7.13 public: 7.14 Vector3 pos, scale; 7.15 Quaternion rot; 7.16 7.17 CoPRS(); 7.18 7.19 - void update(); 7.20 + void update(float dt); 7.21 }; 7.22 7.23
8.1 --- a/src/comp.cc Sat Feb 14 01:35:42 2015 +0200 8.2 +++ b/src/comp.cc Sat Feb 14 07:27:12 2015 +0200 8.3 @@ -10,28 +10,41 @@ 8.4 { 8.5 name = "unknown"; 8.6 gobj = 0; 8.7 - upd_prio = 0; 8.8 } 8.9 8.10 Component::~Component() 8.11 { 8.12 } 8.13 8.14 +void Component::attach(GObject *gobj) 8.15 +{ 8.16 + this->gobj = gobj; 8.17 +} 8.18 + 8.19 +void Component::detach() 8.20 +{ 8.21 + gobj = 0; 8.22 +} 8.23 + 8.24 +const char **Component::update_before() const 8.25 +{ 8.26 + static const char *before[] = { 0 }; 8.27 + return before; 8.28 +} 8.29 + 8.30 const char *Component::get_name() const 8.31 { 8.32 return name; 8.33 } 8.34 8.35 -void Component::update() 8.36 +void Component::update(float dt) 8.37 { 8.38 } 8.39 8.40 -bool Component::operator <(const Component &c) const 8.41 +void Component::draw() const 8.42 { 8.43 - return upd_prio < c.upd_prio; 8.44 } 8.45 8.46 - 8.47 void register_component(const char *name, Component *(*cons_func)()) 8.48 { 8.49 if(!early_comp_cons) {
9.1 --- a/src/comp.h Sat Feb 14 01:35:42 2015 +0200 9.2 +++ b/src/comp.h Sat Feb 14 07:27:12 2015 +0200 9.3 @@ -3,13 +3,31 @@ 9.4 9.5 #include <string> 9.6 9.7 -class GameObject; 9.8 +#ifdef NDEBUG 9.9 +#define COCAST(type, x) ((type*)x) 9.10 +#else 9.11 +#define COCAST(type, x) dynamic_cast<type*>(x) 9.12 +#endif 9.13 + 9.14 +class GObject; 9.15 9.16 class Component { 9.17 protected: 9.18 const char *name; 9.19 - GameObject *gobj; 9.20 - int upd_prio; // update priority (0: normal) 9.21 + GObject *gobj; 9.22 + 9.23 + /* attach/detach to a particular GObject. 9.24 + * This is only called from GObject::add_component and 9.25 + * GObject::remove_component respectively 9.26 + */ 9.27 + virtual void attach(GObject *gobj); 9.28 + virtual void detach(); 9.29 + 9.30 + /* Returns an array of component names which depend on this and 9.31 + * must not be updated first if both exist in the same object. 9.32 + * Terminated by a null pointer. 9.33 + */ 9.34 + virtual const char **update_before() const; 9.35 9.36 public: 9.37 Component(); 9.38 @@ -17,11 +35,10 @@ 9.39 9.40 const char *get_name() const; 9.41 9.42 - virtual void update(); 9.43 + virtual void update(float dt); 9.44 + virtual void draw() const; 9.45 9.46 - bool operator <(const Component &c) const; // for sorting based on priority 9.47 - 9.48 - friend class GameObject; 9.49 + friend class GObject; 9.50 }; 9.51 9.52 void register_component(const char *name, Component *(*cons_func)());
10.1 --- a/src/gobj.cc Sat Feb 14 01:35:42 2015 +0200 10.2 +++ b/src/gobj.cc Sat Feb 14 07:27:12 2015 +0200 10.3 @@ -1,25 +1,27 @@ 10.4 #include <stdio.h> 10.5 +#include <string.h> 10.6 +#include <assert.h> 10.7 #include <algorithm> 10.8 #include "gobj.h" 10.9 10.10 -GameObject::GameObject() 10.11 +GObject::GObject() 10.12 { 10.13 sorted = true; 10.14 } 10.15 10.16 -GameObject::~GameObject() 10.17 +GObject::~GObject() 10.18 { 10.19 for(size_t i=0; i<comp.size(); i++) { 10.20 delete comp[i]; 10.21 } 10.22 } 10.23 10.24 -bool GameObject::add_component(Component *c) 10.25 +bool GObject::add_component(Component *c) 10.26 { 10.27 const char *name = c->get_name(); 10.28 10.29 if(comp_by_name.find(name) != comp_by_name.end()) { 10.30 - fprintf(stderr, "component %s already exists in this game object (%p)\n", name, (void*)this); 10.31 + fprintf(stderr, "component %s already exists in this gobject (%p)\n", name, (void*)this); 10.32 return false; 10.33 } 10.34 10.35 @@ -27,7 +29,7 @@ 10.36 comp.push_back(c); 10.37 comp_by_name[name] = c; 10.38 10.39 - c->gobj = this; 10.40 + c->attach(this); 10.41 } 10.42 catch(...) { 10.43 fprintf(stderr, "failed to add component: %s\n", name); 10.44 @@ -38,10 +40,11 @@ 10.45 return true; 10.46 } 10.47 10.48 -bool GameObject::remove_component(Component *c) 10.49 +bool GObject::remove_component(Component *c) 10.50 { 10.51 for(size_t i=0; i<comp.size(); i++) { 10.52 if(comp[i] == c) { 10.53 + c->detach(); 10.54 comp.erase(comp.begin() + i); 10.55 comp_by_name.erase(c->get_name()); 10.56 return true; 10.57 @@ -50,7 +53,7 @@ 10.58 return false; 10.59 } 10.60 10.61 -bool GameObject::delete_component(Component *c) 10.62 +bool GObject::delete_component(Component *c) 10.63 { 10.64 if(remove_component(c)) { 10.65 delete c; 10.66 @@ -59,7 +62,7 @@ 10.67 return false; 10.68 } 10.69 10.70 -Component *GameObject::get_component(const char *name) const 10.71 +Component *GObject::get_component(const char *name) const 10.72 { 10.73 std::map<std::string, Component*>::const_iterator it; 10.74 if((it = comp_by_name.find(name)) != comp_by_name.end()) { 10.75 @@ -68,13 +71,119 @@ 10.76 return 0; 10.77 } 10.78 10.79 -void GameObject::update() 10.80 +void GObject::update(float dt) 10.81 { 10.82 if(!sorted) { 10.83 - std::sort(comp.begin(), comp.end()); 10.84 + sort_components(); 10.85 + sorted = true; 10.86 } 10.87 10.88 + printf("obj(%p) update\n", (void*)this); 10.89 for(size_t i=0; i<comp.size(); i++) { 10.90 - comp[i]->update(); 10.91 + printf(" updating component: %s\n", comp[i]->get_name()); 10.92 + comp[i]->update(dt); 10.93 } 10.94 } 10.95 + 10.96 +void GObject::draw() const 10.97 +{ 10.98 + // TODO optimization: draw only specific components? 10.99 + for(size_t i=0; i<comp.size(); i++) { 10.100 + comp[i]->draw(); 10.101 + } 10.102 +} 10.103 + 10.104 +struct TopoSucNode { 10.105 + int idx; 10.106 + TopoSucNode *next; 10.107 +}; 10.108 + 10.109 +struct TopoItem { 10.110 + Component *co; 10.111 + int npre; // number of predeccessors 10.112 + TopoSucNode *suc; // successor list 10.113 + TopoItem *qnext, *qprev; // queue list links 10.114 +}; 10.115 + 10.116 +int countq(TopoItem *q) 10.117 +{ 10.118 + int n = 0; 10.119 + while(q) { 10.120 + n++; 10.121 + q = q->qnext; 10.122 + } 10.123 + return n; 10.124 +} 10.125 + 10.126 +// topological sort of components based on update_before() relationships 10.127 +void GObject::sort_components() 10.128 +{ 10.129 + int nitems = (int)comp.size(); 10.130 + TopoItem *items = (TopoItem*)alloca(nitems * sizeof *items); 10.131 + TopoItem *queue = items; 10.132 + 10.133 + // initialize the items 10.134 + for(int i=0; i<nitems; i++) { 10.135 + items[i].co = comp[i]; 10.136 + items[i].npre = 0; 10.137 + items[i].suc = 0; 10.138 + items[i].qnext = i + 1 < nitems ? items + i + 1 : 0; 10.139 + items[i].qprev = i > 0 ? items + i - 1 : 0; 10.140 + } 10.141 + 10.142 + // populate the array 10.143 + for(int i=0; i<nitems; i++) { 10.144 + const char **iter = comp[i]->update_before(); 10.145 + while(*iter) { 10.146 + const char *sucname = *iter++; 10.147 + 10.148 + for(int j=0; j<nitems; j++) { 10.149 + if(j == i) continue; 10.150 + if(strcmp(comp[j]->get_name(), sucname) == 0) { 10.151 + // found a component(j) depending on i, increment its predeccessor counter 10.152 + items[j].npre++; 10.153 + // remove it from the queue 10.154 + if(queue == items + j) { 10.155 + queue = items[j].qnext; 10.156 + assert(items[j].qprev == 0); 10.157 + } 10.158 + if(items[j].qprev) items[j].qprev->qnext = items[j].qnext; 10.159 + if(items[j].qnext) items[j].qnext->qprev = items[j].qprev; 10.160 + items[j].qprev = items[j].qnext = 0; 10.161 + 10.162 + // and add it to our successor list 10.163 + TopoSucNode *n = (TopoSucNode*)alloca(sizeof *n); 10.164 + n->idx = j; 10.165 + n->next = items[i].suc; 10.166 + items[i].suc = n; 10.167 + } 10.168 + } 10.169 + } 10.170 + } 10.171 + 10.172 + // now remove each item from the queue and add it to the sorted list 10.173 + int idx = 0; 10.174 + while(queue) { 10.175 + assert(idx < nitems); 10.176 + comp[idx++] = queue->co; 10.177 + 10.178 + // traverse the successor list, decrementing their predeccessor counts 10.179 + TopoSucNode *n = queue->suc; 10.180 + queue = queue->qnext; 10.181 + 10.182 + while(n) { 10.183 + TopoItem *it = items + n->idx; 10.184 + n = n->next; 10.185 + 10.186 + assert(it->npre > 0); 10.187 + if(--it->npre <= 0) { 10.188 + // if the count reached zero, add it to the queue 10.189 + it->qprev = 0; 10.190 + it->qnext = queue; 10.191 + queue = it; 10.192 + } 10.193 + } 10.194 + } 10.195 + 10.196 + assert(idx == nitems); 10.197 +}
11.1 --- a/src/gobj.h Sat Feb 14 01:35:42 2015 +0200 11.2 +++ b/src/gobj.h Sat Feb 14 07:27:12 2015 +0200 11.3 @@ -1,29 +1,32 @@ 11.4 -#ifndef GAMEOBJECT_H_ 11.5 -#define GAMEOBJECT_H_ 11.6 +#ifndef GOBJECT_H_ 11.7 +#define GOBJECT_H_ 11.8 11.9 #include <vector> 11.10 #include <map> 11.11 #include <string> 11.12 #include "comp.h" 11.13 11.14 -class GameObject { 11.15 +class GObject { 11.16 private: 11.17 std::vector<Component*> comp; 11.18 std::map<std::string, Component*> comp_by_name; 11.19 11.20 bool sorted; 11.21 11.22 + void sort_components(); 11.23 + 11.24 public: 11.25 - GameObject(); 11.26 - ~GameObject(); 11.27 + GObject(); 11.28 + ~GObject(); 11.29 11.30 - bool add_component(Component *c); // takes ownership 11.31 - bool remove_component(Component *c); 11.32 + bool add_component(Component *c); // takes ownership 11.33 + bool remove_component(Component *c); // whoever calls this, now has ownership 11.34 bool delete_component(Component *c); 11.35 11.36 Component *get_component(const char *name) const; 11.37 11.38 - void update(); 11.39 + void update(float dt = 0.0f); 11.40 + void draw() const; 11.41 }; 11.42 11.43 -#endif // GAMEOBJECT_H_ 11.44 +#endif // GOBJECT_H_
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/src/sim.cc Sat Feb 14 07:27:12 2015 +0200 12.3 @@ -0,0 +1,66 @@ 12.4 +#include <algorithm> 12.5 +#include "sim.h" 12.6 + 12.7 +SimWorld::SimWorld() 12.8 + : gravity(0, -9, 0) 12.9 +{ 12.10 + damping = 0.005; 12.11 +} 12.12 + 12.13 +void SimWorld::add_object(GObject *obj) 12.14 +{ 12.15 + CoRigid *co = COCAST(CoRigid, obj->get_component("phys")); 12.16 + if(co) { 12.17 + add_rigid_body(co); 12.18 + } else { 12.19 + fprintf(stderr, "SimWorld::add_object: trying to add object without rigid body component\n"); 12.20 + } 12.21 +} 12.22 + 12.23 +void SimWorld::add_rigid_body(CoRigid *co) 12.24 +{ 12.25 + if(std::find(rigid.begin(), rigid.end(), co) == rigid.end()) { 12.26 + rigid.push_back(co); 12.27 + co->world = this; 12.28 + } 12.29 +} 12.30 + 12.31 +void SimWorld::remove_object(GObject *obj) 12.32 +{ 12.33 + CoRigid *co = COCAST(CoRigid, obj->get_component("phys")); 12.34 + if(co) { 12.35 + remove_rigid_body(co); 12.36 + } else { 12.37 + fprintf(stderr, "SimWorld::remove_object: failed to remove object without rigid body component\n"); 12.38 + } 12.39 +} 12.40 + 12.41 +void SimWorld::remove_rigid_body(CoRigid *co) 12.42 +{ 12.43 + std::list<CoRigid*>::iterator it = std::find(rigid.begin(), rigid.end(), co); 12.44 + if(it != rigid.end()) { 12.45 + rigid.erase(it); 12.46 + } else { 12.47 + fprintf(stderr, "SimWorld::remove_rigid_body: failed to remove missing rigid body\n"); 12.48 + } 12.49 +} 12.50 + 12.51 +void SimWorld::set_damping(float damping) 12.52 +{ 12.53 + this->damping = damping; 12.54 +} 12.55 + 12.56 +float SimWorld::get_damping() const 12.57 +{ 12.58 + return damping; 12.59 +} 12.60 + 12.61 +void SimWorld::set_gravity(const Vector3 &v) 12.62 +{ 12.63 + gravity = v; 12.64 +} 12.65 + 12.66 +const Vector3 &SimWorld::get_gravity() const 12.67 +{ 12.68 + return gravity; 12.69 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/src/sim.h Sat Feb 14 07:27:12 2015 +0200 13.3 @@ -0,0 +1,30 @@ 13.4 +#ifndef COENG_SIM_H_ 13.5 +#define COENG_SIM_H_ 13.6 + 13.7 +#include <list> 13.8 +#include "co_phys.h" 13.9 +#include "gobj.h" 13.10 + 13.11 +class SimWorld { 13.12 +private: 13.13 + std::list<CoRigid*> rigid; 13.14 + Vector3 gravity; 13.15 + float damping; 13.16 + 13.17 +public: 13.18 + SimWorld(); 13.19 + 13.20 + void add_object(GObject *obj); // convenience function, calls add_rigid_body 13.21 + void add_rigid_body(CoRigid *co); 13.22 + 13.23 + void remove_object(GObject *obj); // convenience function, calls remove_rigid_body 13.24 + void remove_rigid_body(CoRigid *co); 13.25 + 13.26 + void set_damping(float damping); 13.27 + float get_damping() const; 13.28 + 13.29 + void set_gravity(const Vector3 &v); 13.30 + const Vector3 &get_gravity() const; 13.31 +}; 13.32 + 13.33 +#endif // COENG_SIM_H_
14.1 --- a/src/test.cc Sat Feb 14 01:35:42 2015 +0200 14.2 +++ b/src/test.cc Sat Feb 14 07:27:12 2015 +0200 14.3 @@ -1,6 +1,7 @@ 14.4 #include <stdio.h> 14.5 #include <stdlib.h> 14.6 #include <assert.h> 14.7 +#include <vector> 14.8 14.9 #ifndef __APPLE__ 14.10 #include <GL/glut.h> 14.11 @@ -8,6 +9,11 @@ 14.12 #include <GLUT/glut.h> 14.13 #endif 14.14 14.15 +#include "gobj.h" 14.16 +#include "co_xform.h" 14.17 +#include "co_dbgvis.h" 14.18 +#include "sim.h" 14.19 + 14.20 static bool init(); 14.21 static void cleanup(); 14.22 static void display(); 14.23 @@ -17,6 +23,11 @@ 14.24 static void mouse(int bn, int st, int x, int y); 14.25 static void motion(int x, int y); 14.26 14.27 +float cam_theta, cam_phi = 25, cam_dist = 8; 14.28 + 14.29 +std::vector<GObject*> objects; 14.30 +SimWorld simworld; 14.31 + 14.32 14.33 int main(int argc, char **argv) 14.34 { 14.35 @@ -26,7 +37,7 @@ 14.36 glutCreateWindow("component system test"); 14.37 14.38 glutDisplayFunc(display); 14.39 - glutIdleFunc(idle); 14.40 + //glutIdleFunc(idle); 14.41 glutReshapeFunc(reshape); 14.42 glutKeyboardFunc(keyb); 14.43 glutMouseFunc(mouse); 14.44 @@ -46,6 +57,26 @@ 14.45 glEnable(GL_DEPTH_TEST); 14.46 glEnable(GL_CULL_FACE); 14.47 14.48 + glEnable(GL_LIGHTING); 14.49 + glEnable(GL_LIGHT0); 14.50 + float ldir[] = {-1, 1, 2, 0}; 14.51 + glLightfv(GL_LIGHT0, GL_POSITION, ldir); 14.52 + 14.53 + GObject *obj = new GObject; 14.54 + obj->add_component(new CoSphereVis); 14.55 + obj->add_component(new CoXForm); 14.56 + obj->add_component(new CoPRS); 14.57 + obj->add_component(new CoRigid); 14.58 + COCAST(CoPRS, obj->get_component("prs"))->pos = Vector3(5, 1, 0); 14.59 + objects.push_back(obj); 14.60 + 14.61 + obj = new GObject; 14.62 + obj->add_component(new CoSphereVis); 14.63 + obj->add_component(new CoXForm); 14.64 + obj->add_component(new CoPRS); 14.65 + COCAST(CoPRS, obj->get_component("prs"))->pos = Vector3(-5, 1, 0); 14.66 + objects.push_back(obj); 14.67 + 14.68 return true; 14.69 } 14.70 14.71 @@ -53,10 +84,48 @@ 14.72 { 14.73 } 14.74 14.75 +static void update() 14.76 +{ 14.77 + static unsigned int prev_upd; 14.78 + unsigned int msec = glutGet(GLUT_ELAPSED_TIME); 14.79 + float dt = (float)(msec - prev_upd) / 1000.0f; 14.80 + prev_upd = msec; 14.81 + 14.82 + for(size_t i=0; i<objects.size(); i++) { 14.83 + objects[i]->update(dt); 14.84 + } 14.85 +} 14.86 + 14.87 static void display() 14.88 { 14.89 + update(); 14.90 + 14.91 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 14.92 14.93 + glMatrixMode(GL_MODELVIEW); 14.94 + glLoadIdentity(); 14.95 + glTranslatef(0, 0, -cam_dist); 14.96 + glRotatef(cam_phi, 1, 0, 0); 14.97 + glRotatef(cam_theta, 0, 1, 0); 14.98 + 14.99 + float floor_col[] = {0.2, 0.8, 0.2, 1}; 14.100 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, floor_col); 14.101 + 14.102 + glBegin(GL_QUADS); 14.103 + glNormal3f(0, 1, 0); 14.104 + glVertex3f(-10, 0, 10); 14.105 + glVertex3f(10, 0, 10); 14.106 + glVertex3f(10, 0, -10); 14.107 + glVertex3f(-10, 0, -10); 14.108 + glEnd(); 14.109 + 14.110 + for(size_t i=0; i<objects.size(); i++) { 14.111 + CoSphereVis *co = COCAST(CoSphereVis, objects[i]->get_component("spherevis")); 14.112 + if(co) { 14.113 + co->draw(); 14.114 + } 14.115 + } 14.116 + 14.117 glutSwapBuffers(); 14.118 assert(glGetError() == GL_NO_ERROR); 14.119 } 14.120 @@ -83,13 +152,35 @@ 14.121 } 14.122 } 14.123 14.124 -static int bnstate[16]; 14.125 +static bool bnstate[16]; 14.126 static int prev_x, prev_y; 14.127 14.128 static void mouse(int bn, int st, int x, int y) 14.129 { 14.130 + bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; 14.131 + prev_x = x; 14.132 + prev_y = y; 14.133 } 14.134 14.135 static void motion(int x, int y) 14.136 { 14.137 + int dx = x - prev_x; 14.138 + int dy = y - prev_y; 14.139 + prev_x = x; 14.140 + prev_y = y; 14.141 + 14.142 + if(bnstate[0]) { 14.143 + cam_theta += dx * 0.5; 14.144 + cam_phi += dy * 0.5; 14.145 + 14.146 + if(cam_phi < -90) cam_phi = -90; 14.147 + if(cam_phi > 90) cam_phi = 90; 14.148 + 14.149 + glutPostRedisplay(); 14.150 + } 14.151 + if(bnstate[2]) { 14.152 + cam_dist += dy * 0.1; 14.153 + 14.154 + if(cam_dist < 0.0) cam_dist = 0.0; 14.155 + } 14.156 }