Flatland

Documentation

SourceForge.net Logo

flatland.cpp

Go to the documentation of this file.
00001 // Summary: Defines methods for the geometry class and world class.
00002 // Copyright: 2007  Philip Rideout.  All rights reserved.
00003 // License: see bsd-license.txt
00004 
00005 #include <ode/ode.h>
00006 #include <ode/source/objects.h>
00007 #include <cassert>
00008 
00009 using namespace Flatland;
00010 
00011 void dGeomMoved(dGeomID g) { g->Move(); }
00012 dGeomID dGeomGetBodyNext(dGeomID) { return 0; }
00013 void dGeomSetBody(dGeomID g, dBodyID b) {}
00014 
00015 ObjectProperties Object::defaults = { 5, dInfinity, 0.35, 0, ~0, ~0, 0 };
00016 std::stack<ObjectProperties> Object::defaultStack;
00017 
00018 Object::Object() : properties(defaults) {}
00019 
00020 Geometry::Geometry()
00021 {
00022     axis = vec2(1, 0);
00023     center = vec2(0, 0);
00024     bounds = aabb(0,0,0,0);
00025 }
00026 
00027 void Object::Move()
00028 {
00029     assert(IsDynamic() && GetBody());
00030     const float *R = dBodyGetRotation(GetBody());
00031     {
00032         float c[3] = {1, 0, 0};
00033         float a[4];
00034         dMultiply0(a, R, c, 4, 3, 1);
00035         GetGeometry().SetAxis(vec2(a));
00036     }
00037 
00038     const float *position = dBodyGetPosition(GetBody());
00039     GetGeometry().SetCenter(vec2(position));
00040     GetGeometry().UpdateBounds();
00041 }
00042 
00043 void Object::Rotate(float theta)
00044 {
00045     GetGeometry().SetAxis(vec2(0, 1));
00046     GetGeometry().Rotate(theta);
00047     if (IsDynamic() && GetBody())
00048     {
00049         // TODO this assumes that there was no previous rotation
00050         const float degreesToRadians = atan(1.0f) / 45;
00051         dMatrix3 R;
00052         dRFromAxisAndAngle(R, 0, 0, 1, theta * degreesToRadians);
00053         dBodySetRotation(GetBody(), R);
00054     }
00055 }
00056 
00057 void Object::SetCenter(const vec2 &center)
00058 {
00059     GetGeometry().SetCenter(center);
00060     if (IsDynamic() && GetBody())
00061         dBodySetPosition(GetBody(), center.x, center.y, 0);
00062 }
00063 
00064 void Geometry::Rotate(float theta)
00065 {
00066     SetAxis(this->axis.rotate(theta));
00067 }
00068 
00069 void Geometry::Rotate(const vec2 &xform)
00070 {
00071     SetAxis(this->axis.rotate(xform));
00072 }
00073 
00074 void Geometry::SetCenter(const vec2 &center)
00075 {
00076     this->center = center;
00077 }
00078 
00079 void Geometry::SetAxis(const vec2 &axis)
00080 {
00081     this->axis = axis;
00082 }
00083 
00084 World::World()
00085 {
00086     world = dWorldCreate();
00087     contactGroup = dJointGroupCreate(0);
00088     contactCount = 0;
00089 }
00090 
00091 World::~World()
00092 {
00093     dJointGroupDestroy(contactGroup);
00094     dWorldDestroy(world);
00095 }
00096 
00097 void World::QuickStep(float f)
00098 {
00099     dWorldQuickStep(world, f);
00100 }
00101 
00102 Body World::BodyCreate()
00103 {
00104     return dBodyCreate(world);
00105 }
00106 
00107 void World::SetAutoDisableLinearThreshold(float f)
00108 {
00109     dWorldSetAutoDisableLinearThreshold(world, f);
00110 }
00111 
00112 void World::SetAutoDisableAngularThreshold(float f)
00113 {
00114     dWorldSetAutoDisableAngularThreshold(world, f);
00115 }
00116 
00117 void World::SetCFM(float f)
00118 {
00119     dWorldSetCFM(world, f);
00120 }
00121 
00122 void World::SetAutoDisableFlag(bool b)
00123 {
00124     dWorldSetAutoDisableFlag(world, b ? 1 : 0);
00125 }
00126 
00127 void World::SetERP(float f)
00128 {
00129     dWorldSetERP(world, f);
00130 }
00131 
00132 void World::SetContactMaxCorrectingVel(float f)
00133 {
00134     dWorldSetContactMaxCorrectingVel(world, f);
00135 }
00136 
00137 void World::SetContactSurfaceLayer(float f)
00138 {
00139     dWorldSetContactSurfaceLayer(world, f);
00140 }
00141 
00142 void World::SetGravity(const vec2 &v)
00143 {
00144     dWorldSetGravity(world, v.x, v.y, 0);
00145 }
00146 
00147 dJointID World::AddMotor(Object &object)
00148 {
00149     dJointID joint = dJointCreateAMotor(world, 0);
00150     dJointAttach(joint, object.GetBody(), 0);
00151     dJointSetAMotorNumAxes(joint, 1);
00152     dJointSetAMotorAxis(joint, 0, 1, 0, 0, 1);
00153     dJointSetAMotorParam(joint, dParamFMax, dInfinity);
00154     return joint;
00155 }
00156 
00157 dJointID World::Glue(Object &object1, Object &object2)
00158 {
00159     dJointID joint = dJointCreateFixed(world, 0);
00160     dJointAttach(joint, object1.GetBody(), object2.GetBody());
00161     dJointSetFixed(joint);
00162     return joint;
00163 }
00164 
00165 dJointID World::AnchorAxis(Object &object, const vec2 &axis)
00166 {
00167     dJointID joint = dJointCreateSlider(world, 0);
00168     dJointAttach(joint, object.GetBody(), 0);
00169     dJointSetSliderAxis(joint, axis.x, axis.y, 0);
00170     return joint;
00171 }
00172 
00173 dJointID World::Anchor(Object &o1, Object &o2, const vec2 &point, float mu, float erp)
00174 {
00175     dJointID joint = dJointCreateHinge(world, 0);
00176     dJointAttach(joint, o1.GetBody(), o2.GetBody());
00177     dJointSetHingeAnchor(joint, point.x, point.y, 0);
00178     dJointSetHingeAxis(joint, 0, 0, 1);
00179     dJointSetErp(joint, erp);
00180 
00181     if (mu)
00182     {
00183         dJointID friction = dJointCreateAMotor(world, 0);
00184         dJointAttach(friction, o1.GetBody(), o2.GetBody());
00185 
00186         dJointSetAMotorNumAxes(friction, 1);
00187         dJointSetAMotorAxis(friction, 0, 1, 0, 0, 1);
00188         dJointSetAMotorParam(friction, dParamFMax, mu);
00189         dJointSetAMotorParam(friction, dParamVel, 0);
00190     }
00191     return joint;
00192 }
00193 
00194 dJointID World::Anchor(Object &o1, const vec2 &point, float mu, float erp)
00195 {
00196     dJointID joint = dJointCreateHinge(world, 0);
00197     dJointAttach(joint, o1.GetBody(), 0);
00198     dJointSetHingeAnchor(joint, point.x, point.y, 0);
00199     dJointSetHingeAxis(joint, 0, 0, 1);
00200     dJointSetErp(joint, erp);
00201 
00202     if (mu)
00203     {
00204         dJointID friction = dJointCreateAMotor(world, 0);
00205         dJointAttach(friction, o1.GetBody(), 0);
00206 
00207         dJointSetAMotorNumAxes(friction, 1);
00208         dJointSetAMotorAxis(friction, 0, 1, 0, 0, 1);
00209         dJointSetAMotorParam(friction, dParamFMax, mu);
00210         dJointSetAMotorParam(friction, dParamVel, 0);
00211     }
00212     return joint;
00213 }
00214 
00215 void World::DeleteJoint(dJointID joint)
00216 {
00217     dJointDestroy(joint);
00218 }
00219 
00220 void World::SetMotorVelocity(dJointID joint, float velocity)
00221 {
00222     dJointSetAMotorParam(joint, dParamVel, velocity);
00223 }
00224 
00225 float World::GetMotorVelocity(dJointID joint)
00226 {
00227     return dJointGetAMotorParam(joint, dParamVel);
00228 }
00229 
00230 ContactList::ContactList()
00231 {
00232     for (int i = 0; i < Max; ++i)
00233     {
00234         contacts[i].geom.pos[2] = 0;
00235         contacts[i].geom.normal[2] = 0;
00236     }
00237     Reset(0, 0);
00238 }
00239 
00240 void ContactList::Reset(Object *o1, Object *o2)
00241 {
00242     count = 0;
00243     invertNormals = false;
00244     this->o1 = o1;
00245     this->o2 = o2;
00246 }
00247 
00248 void ContactList::AddContact(const vec2 &position, const vec2 &normal, float depth)
00249 {
00250     assert(count < Max - 1);
00251     dContactGeom &cg = contacts[count].geom;
00252     cg.pos[0] = position.x;
00253     cg.pos[1] = position.y;
00254     if (invertNormals)
00255     {
00256         cg.normal[0] = -normal.x;
00257         cg.normal[1] = -normal.y;
00258     }
00259     else
00260     {
00261         cg.normal[0] = normal.x;
00262         cg.normal[1] = normal.y;
00263     }
00264     cg.depth = depth;
00265     ++count;
00266 }
00267 
00268 void ContactList::Finalize()
00269 {
00270     ObjectProperties &p1 = o1->Property();
00271     ObjectProperties &p2 = o2->Property();
00272 
00273     for (int i = 0; i < count; ++i)
00274     {
00275         dContact &c = contacts[i];
00276         c.surface.mode = dContactBounce;
00277 
00278         // Not sure how to resolve the frictions and bounciness from the two objects.
00279         // For now I'll multiply the frictions and average the bouncinesses.
00280 
00281         if (p1.frictionMask & p2.frictionMask)
00282         {
00283             if (p1.friction == dInfinity || p2.friction == dInfinity)
00284                 c.surface.mu = dInfinity;
00285             else
00286                 c.surface.mu = p1.friction * p2.friction;
00287         }
00288         else
00289             c.surface.mu = 0;
00290 
00291         c.surface.bounce = (p1.bounceFactor + p2.bounceFactor) / 2;
00292         c.surface.bounce_vel = (p1.bounceVelocity + p2.bounceVelocity) / 2;
00293 
00294         dContactGeom &cg = contacts[i].geom;
00295         cg.g1 = o1;
00296         cg.g2 = o2;
00297     }
00298 
00299     if (p1.callback)
00300         p1.callback(*this);
00301 
00302     if (p2.callback)
00303     {
00304         std::swap(o1, o2);
00305         p2.callback(*this);
00306         std::swap(o1, o2);
00307     }
00308 }
00309 
00310 void ContactList::CreateJoints(dWorldID world, dJointGroupID contactGroup) const
00311 {
00312     for (int i = 0; i < count; ++i)
00313     {
00314         const dContact &c = contacts[i];
00315         dJointID joint = dJointCreateContact(world, contactGroup, &c);
00316 
00317         const dContactGeom &cg = c.geom;
00318         dJointAttach(joint, cg.g1->GetBody(), cg.g2->GetBody());
00319     }
00320 }

Generated on Sat Jan 13 17:20:21 2007 for Flatland by doxygen 1.5.1