00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <physics/ODESolid>
00026 #include <base/ref>
00027
00028
00029 #include <physics/Box>
00030 #include <physics/Sphere>
00031
00032 #include <physics/ODECollidableBody>
00033 #include <physics/ODESolidConnectedCollidableBody>
00034
00035
00036 using base::Point3;
00037 using base::Quat4;
00038 using base::Orient;
00039 using base::Vector3;
00040 using base::Matrix3;
00041
00042 using base::copyMemory;
00043
00044 using physics::Body;
00045 using physics::Shape;
00046 using physics::Material;
00047 using physics::MassProperties;
00048 using physics::ODESolid;
00049 using physics::Collidable;
00050 using physics::CollidableBody;
00051 using physics::ODECollidableBody;
00052 using physics::ODESolidConnectedCollidableBody;
00053
00054 using physics::Box;
00055 using physics::Sphere;
00056
00057
00058
00059
00060 ODESolid::ODESolid(ref<const Shape> shape, ref<const Material> material)
00061 : Solid(shape, material), created(false)
00062 {
00063 }
00064
00065 void ODESolid::create(dWorldID worldID) const
00066 {
00067 if (created)
00068 throw std::runtime_error(Exception("create() called twice"));
00069
00070 this->worldID = worldID;
00071
00072 bodyID = dBodyCreate(worldID);
00073
00074 dBodySetPosition(bodyID, 0,0,0);
00075 dQuaternion q = { 1,0,0,0 };
00076 dBodySetQuaternion(bodyID, q);
00077 dBodySetLinearVel(bodyID, 0,0,0);
00078 dBodySetAngularVel(bodyID, 0,0,0);
00079
00080
00081 MassProperties massProps( Solid::massProperties() );
00082
00083 dMass odemass;
00084 dMassSetZero(&odemass);
00085 const Matrix3& Ibody(massProps.Ibody());
00086 dMassSetParameters(&odemass, massProps.mass,
00087 0,0,0,
00088 Ibody(1,1), Ibody(2,2), Ibody(3,3),
00089 Ibody(1,2), Ibody(1,3), Ibody(2,3));
00090
00091 dBodySetMass(bodyID, &odemass);
00092
00093 created = true;
00094 }
00095
00096
00097 void ODESolid::destroy() const
00098 {
00099 if (created) {
00100 dBodyDestroy(bodyID);
00101 worldID = 0;
00102 bodyID = 0;
00103 created = false;
00104 }
00105 }
00106
00107
00108
00109
00110 ODESolid::ODESolid(const Solid& s)
00111 : Solid(s)
00112 {
00113
00114 setPosition(s.getPosition());
00115 setOrientation(s.getOrientation());
00116 setVelocity(s.getVelocity());
00117 setAngVelocity(s.getAngVelocity());
00118 setEnabled(s.isEnabled());
00119 }
00120
00121 ODESolid::~ODESolid()
00122 {
00123 if (created) destroy();
00124 }
00125
00126
00127 MassProperties ODESolid::massProperties() const
00128 {
00129 if (!created) return Solid::massProperties();
00130
00131
00132 dMass odemass;
00133 dBodyGetMass(bodyID, &odemass);
00134
00135 MassProperties massProps;
00136 massProps.mass = odemass.mass;
00137 massProps.centerOfMass = Point3(odemass.c[0], odemass.c[1], odemass.c[2]);
00138 Matrix3 Ibody;
00139
00140 for(int r=1; r<3; r++)
00141 for(int c=1; c<3; c++)
00142 Ibody(r,c) = odemass.I[(r-1)*4+(c-1)];
00143 massProps.setIbody(Ibody);
00144
00145 return massProps;
00146 }
00147
00148
00149
00150 Body& ODESolid::operator=(const Body& b)
00151 {
00152 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return *this; }
00153
00154 setPosition(b.getPosition());
00155 setOrientation(b.getOrientation());
00156 setVelocity(b.getVelocity());
00157 setAngVelocity(b.getAngVelocity());
00158 setEnabled(true);
00159 return *this;
00160 }
00161
00162
00163 void ODESolid::setEnabled(bool enable)
00164 {
00165 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00166
00167 if (enable)
00168 dBodyEnable(bodyID);
00169 else
00170 dBodyDisable(bodyID);
00171 }
00172
00173 bool ODESolid::isEnabled() const
00174 {
00175 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return false; }
00176
00177 return dBodyIsEnabled(bodyID);
00178 }
00179
00180
00181 void ODESolid::setPosition(const Point3& x)
00182 {
00183 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00184
00185 dBodySetPosition(bodyID, x.x, x.y, x.z);
00186 }
00187
00188 void ODESolid::ODESolid::setOrientation(const Orient& orient)
00189 {
00190 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00191
00192 dQuaternion quat;
00193 Quat4 q( orient );
00194 quat[0] = q.w; quat[1] = q.v.x; quat[2] = q.v.y; quat[3] = q.v.z;
00195 dBodySetQuaternion(bodyID, quat);
00196 }
00197
00198 void ODESolid::setVelocity(const Vector3& v)
00199 {
00200 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00201
00202 dBodySetLinearVel(bodyID, v.x, v.y, v.z);
00203 }
00204
00205 void ODESolid::setAngVelocity(const Vector3& w)
00206 {
00207 if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00208
00209 dBodySetAngularVel(bodyID, w.x, w.y, w.z);
00210
00211 }
00212
00213 Point3 ODESolid::getPosition() const
00214 {
00215 if (!created) return Point3();
00216
00217 const dReal* pos = dBodyGetPosition(bodyID);
00218 return Point3(pos[0],pos[1],pos[2]);
00219 }
00220
00221 Orient ODESolid::getOrientation() const
00222 {
00223 if (!created) return Orient();
00224
00225 const dReal* orient = dBodyGetQuaternion(bodyID);
00226 return Orient(Quat4(orient[1], orient[2], orient[3], orient[0]));
00227 }
00228
00229 Vector3 ODESolid::getVelocity() const
00230 {
00231 if (!created) return Vector3();
00232
00233 const dReal* vel = dBodyGetLinearVel(bodyID);
00234 return Vector3(vel[0], vel[1], vel[2]);
00235 }
00236
00237
00238 Vector3 ODESolid::getAngVelocity() const
00239 {
00240 if (!created) return Vector3();
00241
00242 const dReal* angVel = dBodyGetAngularVel(bodyID);
00243 return Vector3(angVel[0], angVel[1], angVel[2]);
00244 }
00245
00246 void ODESolid::saveState()
00247 {
00248 if (!created) return;
00249
00250 copyMemory(dBodyGetPosition(bodyID), savedPos, 3);
00251 copyMemory(dBodyGetQuaternion(bodyID), savedOrient, 4);
00252 copyMemory(dBodyGetLinearVel(bodyID), savedVel, 3);
00253 copyMemory(dBodyGetAngularVel(bodyID), savedAngVel, 3);
00254 }
00255
00256 void ODESolid::restoreState()
00257 {
00258 if (!created) return;
00259
00260 dBodySetPosition(bodyID, savedPos[0], savedPos[1], savedPos[2]);
00261 dBodySetQuaternion(bodyID, savedOrient);
00262 dBodySetLinearVel(bodyID, savedVel[0], savedVel[1], savedVel[2]);
00263 dBodySetAngularVel(bodyID, savedAngVel[0], savedAngVel[1], savedAngVel[2]);
00264 }
00265
00266 Point3 ODESolid::getSavedPosition() const
00267 {
00268 if (!created) return Point3();
00269
00270 return Point3(savedPos[0],savedPos[1],savedPos[2]);
00271 }
00272
00273 Orient ODESolid::getSavedOrientation() const
00274 {
00275 if (!created) return Orient();
00276
00277 return Orient(Quat4(savedOrient[1], savedOrient[2], savedOrient[2], savedOrient[0]));
00278 }
00279
00280 Vector3 ODESolid::getSavedVelocity() const
00281 {
00282 if (!created) return Vector3();
00283
00284 return Vector3(savedVel[0], savedVel[1], savedVel[2]);
00285 }
00286
00287 Vector3 ODESolid::getSavedAngVelocity() const
00288 {
00289 if (!created) return Vector3();
00290
00291 return Vector3(savedAngVel[0], savedAngVel[1], savedAngVel[2]);
00292 }
00293
00294
00295 Point3 ODESolid::getRelPointPos(const Point3& p)
00296 {
00297 if (!created) return p;
00298
00299 dVector3 result;
00300 dBodyGetRelPointPos(bodyID, p.x, p.y, p.z, result);
00301 return Point3(result[0], result[1], result[2]);
00302 }
00303
00304 Vector3 ODESolid::getRelPointVel(const Point3& p)
00305 {
00306 if (!created) return p;
00307
00308 dVector3 result;
00309 dBodyGetRelPointVel(bodyID, p.x, p.y, p.z, result);
00310 return Vector3(result[0], result[1], result[2]);
00311 }
00312
00313
00314 Point3 ODESolid::getGlobalPointRelPos(const Point3& p)
00315 {
00316 Point3 local(p - getPosition());
00317 getOrientation().invert().rotatePoint(local);
00318 return local;
00319 }
00320
00321
00322
00323 void ODESolid::addForce(const Vector3& f)
00324 {
00325 if (!created) return;
00326 dBodyAddForce(bodyID, f.x, f.y, f.z);
00327 }
00328
00329 void ODESolid::addTorque(const Vector3& t)
00330 {
00331 if (!created) return;
00332 dBodyAddTorque(bodyID, t.x, t.y, t.z);
00333 }
00334
00335 void ODESolid::addRelForce(const Vector3& f)
00336 {
00337 if (!created) return;
00338 dBodyAddRelForce(bodyID, f.x, f.y, f.z);
00339 }
00340
00341 void ODESolid::addRelTorque(const Vector3& t)
00342 {
00343 if (!created) return;
00344 dBodyAddRelTorque(bodyID, t.x, t.y, t.z);
00345 }
00346
00347 void ODESolid::addForceAtPos(const Vector3& f, const Point3& p)
00348 {
00349 if (!created) return;
00350 dBodyAddForceAtPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00351 }
00352
00353 void ODESolid::addForceAtRelPos(const Vector3& f, const Point3& p)
00354 {
00355 if (!created) return;
00356 dBodyAddForceAtRelPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00357 }
00358
00359 void ODESolid::addRelForceAtPos(const Vector3& f, const Point3& p)
00360 {
00361 if (!created) return;
00362 dBodyAddRelForceAtPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00363 }
00364
00365 void ODESolid::addRelForceAtRelPos(const Vector3& f, const Point3& p)
00366 {
00367 if (!created) return;
00368 dBodyAddRelForceAtRelPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00369 }
00370
00371 Vector3 ODESolid::getForce() const
00372 {
00373 if (!created) return Vector3();
00374
00375 const dReal* f = dBodyGetForce(bodyID);
00376 return Vector3(f[0], f[1], f[32]);
00377 }
00378
00379 Vector3 ODESolid::getTorque() const
00380 {
00381 if (!created) return Vector3();
00382
00383 const dReal* t = dBodyGetTorque(bodyID);
00384 return Vector3(t[0], t[1], t[2]);
00385 }
00386
00387
00388 ref<Collidable> ODESolid::createCollidable(ref<const Shape> collisionShape, CollidableFlags flags)
00389 {
00390 if (!flags.test(SolidNotConnected)) {
00391 ref<Solid> self( this );
00392 return ref<CollidableBody>(NewObj ODESolidConnectedCollidableBody(self, collisionShape));
00393 }
00394 else
00395 return ref<CollidableBody>(NewObj ODECollidableBody(getShape()));
00396 }
00397