00001
00002
00003
00004
00005 #pragma once
00006 #include <flatland/ode/ode.h>
00007 #include <flatland/ode/source/objects.h>
00008 #include <flatland/aabb.hpp>
00009 #include <flatland/vector.hpp>
00010 #include <flatland/enums.hpp>
00011 #include <flatland/intersection.hpp>
00012 #include <cassert>
00013 #include <stack>
00014
00015
00016 namespace Flatland
00017 {
00018 class ContactList;
00019 class Object;
00020
00021 typedef unsigned int Mask;
00022 typedef dBodyID Body;
00023 typedef void (*Callback)(ContactList &contacts);
00024
00025
00026 class Geometry
00027 {
00028 public:
00029 Geometry();
00030 virtual void UpdateBounds() = 0;
00031 virtual void SetCenter(const vec2 ¢er);
00032 vec2 Center() const { return center; }
00033 virtual void SetAxis(const vec2 &axis);
00034 void Rotate(float theta);
00035 void Rotate(const vec2 &xform);
00036 vec2 Axis() const { return axis; }
00037 vec2 Axis(int i) const { return i ? axis.perp() : axis; }
00038 virtual void SetMass(Body body, float density) const {}
00039 virtual Shape GetShape() const = 0;
00040 const aabb &GetBounds() const { return bounds; }
00041 protected:
00042 aabb bounds;
00043 vec2 axis;
00044 vec2 center;
00045 };
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 struct ObjectProperties
00057 {
00058 float density;
00059 float friction;
00060 float bounceFactor;
00061 float bounceVelocity;
00062 Mask collisionMask;
00063 Mask frictionMask;
00064 Callback callback;
00065 };
00066
00067
00068
00069
00070
00071
00072
00073 class Object
00074 {
00075 public:
00076 Object();
00077 virtual ~Object() {}
00078 virtual Geometry &GetGeometry() = 0;
00079 virtual const Geometry &GetGeometry() const = 0;
00080 virtual bool IsDynamic() const = 0;
00081 virtual Body GetBody() = 0;
00082 virtual void SetMass(float density) = 0;
00083 void Move();
00084 void Rotate(float theta);
00085 void SetCenter(const vec2 ¢er);
00086 public:
00087 ObjectProperties &Property() { return properties; }
00088 const ObjectProperties &Property() const { return properties; }
00089 static ObjectProperties &Default() { return defaults; }
00090 static void PushProperties() { defaultStack.push(defaults); }
00091 static void PopProperties() { defaults = defaultStack.top(); defaultStack.pop(); }
00092 private:
00093 ObjectProperties properties;
00094 static ObjectProperties defaults;
00095 static std::stack<ObjectProperties> defaultStack;
00096 };
00097
00098
00099 template<class G>
00100 class Dynamic : public Object
00101 {
00102 public:
00103 Dynamic(G *geometry, Body b);
00104 virtual ~Dynamic() { dBodyDestroy(body); delete geometry; }
00105 G &GetGeometry() { return *geometry; }
00106 const G &GetGeometry() const { return *geometry; }
00107 bool IsDynamic() const { return true; }
00108 Body GetBody() { return body; }
00109 void SetMass(float density) { geometry->SetMass(body, density); }
00110 protected:
00111 G *geometry;
00112 Body body;
00113 };
00114
00115
00116 template<class G>
00117 class Static : public Object
00118 {
00119 public:
00120 Static(G *geometry) : geometry(geometry) {}
00121 virtual ~Static() { delete geometry; }
00122 G &GetGeometry() { return *geometry; }
00123 const G &GetGeometry() const { return *geometry; }
00124 bool IsDynamic() const { return false; }
00125 Body GetBody() { return 0; }
00126 void SetMass(float) {}
00127 protected:
00128 G *geometry;
00129 };
00130
00131
00132 class ContactList
00133 {
00134 public:
00135 ContactList();
00136 void Reset(Object *o1, Object *o2);
00137 Object *Self() { return o1; }
00138 Object *Other() { return o2; }
00139 void ToggleNormalInversion() { invertNormals = !invertNormals; }
00140 void AddContact(const vec2 &position, const vec2 &normal, float depth);
00141 void Finalize();
00142 void CreateJoints(dWorldID world, dJointGroupID contactGroup) const;
00143 int Count() const { return count; }
00144 static const int Max = 64;
00145 private:
00146 Object *o1;
00147 Object *o2;
00148 dContact contacts[Max];
00149 int count;
00150 bool invertNormals;
00151 };
00152
00153
00154 class World
00155 {
00156 public:
00157 World();
00158 ~World();
00159 void QuickStep(float);
00160 Body BodyCreate();
00161 template<class S> void GenerateContacts(const S &space);
00162 template<class S> bool IsCorrupt(const S &space) const;
00163 int ContactCount() const { return contactCount; }
00164 void SetCFM(float);
00165 void SetAutoDisableFlag(bool);
00166 void SetERP(float);
00167 void SetContactMaxCorrectingVel(float);
00168 void SetContactSurfaceLayer(float);
00169 void SetAutoDisableLinearThreshold(float);
00170 void SetAutoDisableAngularThreshold(float);
00171 void SetGravity(const vec2&);
00172 dJointID AddMotor(Object &object);
00173 dJointID Glue(Object &object1, Object &object2);
00174 dJointID AnchorAxis(Object &object, const vec2 &axis);
00175 dJointID Anchor(Object &o1, Object &o2, const vec2 &point, float mu, float erp);
00176 dJointID Anchor(Object &o1, const vec2 &point, float mu, float erp);
00177 void DeleteJoint(dJointID joint);
00178 static void SetMotorVelocity(dJointID joint, float velocity);
00179 static float GetMotorVelocity(dJointID joint);
00180 private:
00181 int contactCount;
00182 dWorldID world;
00183 dJointGroupID contactGroup;
00184 ContactList contactList;
00185 };
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 template<class Container>
00198 void World::GenerateContacts(const Container &space)
00199 {
00200 dJointGroupEmpty(contactGroup);
00201 contactCount = 0;
00202 typename Container::const_iterator o1;
00203 for (o1 = space.begin(); o1 != space.end(); ++o1)
00204 {
00205 Object *object1 = (*o1)->GetFlatlandObject();
00206 if (!object1)
00207 continue;
00208
00209 typename Container::const_iterator o2 = o1;
00210 for (++o2; o2 != space.end(); ++o2)
00211 {
00212 Object *object2 = (*o2)->GetFlatlandObject();
00213 if (!object2)
00214 continue;
00215
00216 if (!object1->IsDynamic() && !object2->IsDynamic())
00217 continue;
00218
00219 if (!(object1->Property().collisionMask & object2->Property().collisionMask))
00220 if (!object1->Property().callback && !object2->Property().callback)
00221 continue;
00222
00223 Geometry &g1 = object1->GetGeometry();
00224 Geometry &g2 = object2->GetGeometry();
00225
00226 if (Intersection::Test(g1, g2))
00227 {
00228 contactList.Reset(object1, object2);
00229 Intersection::Find(g1, g2, contactList);
00230 contactList.Finalize();
00231 if ((object1->Property().collisionMask & object2->Property().collisionMask))
00232 {
00233 contactList.CreateJoints(world, contactGroup);
00234 contactCount += contactList.Count();
00235 }
00236 }
00237 }
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 template<class Container>
00251 bool World::IsCorrupt(const Container &space) const
00252 {
00253 typename Container::const_iterator o;
00254 for (o = space.begin(); o != space.end(); ++o)
00255 {
00256 Object *object = (*o)->GetFlatlandObject();
00257 if (!object)
00258 continue;
00259
00260 Body body = object->GetBody();
00261 if (!body)
00262 continue;
00263
00264 const dReal *lvel = dBodyGetLinearVel(body);
00265 const dReal *avel = dBodyGetAngularVel(body);
00266
00267 if (is_nan(lvel[0])) return true;
00268 if (is_nan(lvel[1])) return true;
00269 if (is_nan(avel[0])) return true;
00270 if (is_nan(avel[1])) return true;
00271 }
00272 return false;
00273 }
00274
00275
00276 template<class G>
00277 Dynamic<G>::Dynamic(G *g, Body b) : geometry(g), body(b)
00278 {
00279 body->geom = this;
00280
00281 dMatrix3 R;
00282 float theta = atan2f(geometry->Axis(0).y, geometry->Axis(0).x);
00283 dRFromAxisAndAngle(R, 0, 0, 1, theta);
00284 dBodyInit(body, geometry->Center().x, geometry->Center().y, R);
00285
00286 SetMass(Object::Default().density);
00287 }
00288 }
00289
00290 typedef Flatland::Object *dGeomID;
00291 void dGeomMoved(dGeomID g);
00292 dGeomID dGeomGetBodyNext(dGeomID);
00293 void dGeomSetBody(dGeomID g, dBodyID b);