00001
00002
00003
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
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 ¢er)
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 ¢er)
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
00279
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 }