00001
00002 #include "CollisionBody.h"
00003 #include "PhysicsManager.h"
00004 #include "BoxShape.h"
00005 #include "CylinderShape.h"
00006 #include "SphereShape.h"
00007 #include "NoShape.h"
00008 #include "PlaneShape.h"
00009
00010 #include "random_utils/LogManager.h"
00011
00012
00013 #include <ode/ode.h>
00014
00015 #include <vrs/container/iterator.h>
00016 #include <vrs/sg/scenething.h>
00017
00018 #include <vrs/box.h>
00019 #include <vrs/colorattribute.h>
00020 #include <vrs/constantdetail.h>
00021 #include <vrs/facestyle.h>
00022 #include <vrs/plane.h>
00023 #include <vrs/rotation.h>
00024 #include <vrs/shape.h>
00025 #include <vrs/sphere.h>
00026 #include <vrs/translation.h>
00027
00028 namespace vrsode
00029 {
00030
00031 CollisionBody::CollisionBody(VRS::SO<VRS::SceneThing> p_sceneThing,
00032 CollisionShape p_collisionShape, bool p_register)
00033 {
00034 m_cleanedUp = false;
00035 m_reportCollision = false;
00036 m_wantToDestroy = false;
00037 m_sceneThing = p_sceneThing;
00038 m_collisionShape = p_collisionShape;
00039
00040 setupTransformationNodes();
00041
00042 VRS::Bounds boundingBox = m_sceneThing->boundingBox(0);
00043
00044 switch(m_collisionShape)
00045 {
00046 case CS_Sphere:
00047 m_odeShape = new SphereShape(boundingBox);
00048 m_geomId = m_odeShape->geomId();
00049 break;
00050 case CS_Box:
00051 m_odeShape = new BoxShape(boundingBox);
00052 m_geomId = m_odeShape->geomId();
00053 break;
00054 case CS_None:
00055 m_odeShape = new NoShape();
00056 m_geomId = m_odeShape->geomId();
00057 break;
00058 default:
00059 rErr("NOT IMPLEMENTED: Provided CollisionShape cannot be "
00060 "generated, please provide a pre created shape.");
00061 m_odeShape = 0;
00062 m_geomId = 0;
00063 break;
00064 }
00065
00066 if(m_geomId)
00067 {
00068 dSpaceAdd(PhysicsManager::get()->spaceId(), m_geomId);
00069 dGeomSetData(m_geomId, this);
00070 syncTransformationsToODE();
00071 setSurface(new Surface());
00072 if(p_register)
00073 PhysicsManager::get()->registerCollisionBody(this);
00074 }
00075 }
00076
00077 CollisionBody::CollisionBody(VRS::SO<VRS::SceneThing> p_sceneThing,
00078 VRS::SO<Shape> p_shape, bool p_register)
00079 {
00080 m_cleanedUp = false;
00081 m_reportCollision = false;
00082 m_wantToDestroy = false;
00083 m_sceneThing = p_sceneThing;
00084 m_collisionShape = p_shape->collisionShape();
00085 m_sceneNodeLock = new SceneNodeLock;
00086
00087 setupTransformationNodes();
00088
00089 m_odeShape = p_shape;
00090 m_geomId = p_shape->geomId();
00091
00092 if(m_geomId)
00093 {
00094 dSpaceAdd(PhysicsManager::get()->spaceId(), m_geomId);
00095 dGeomSetData(m_geomId, this);
00096 syncTransformationsToODE();
00097 setSurface(new Surface());
00098 if(p_register)
00099 PhysicsManager::get()->registerCollisionBody(this);
00100 }
00101 }
00102
00103 CollisionBody::~CollisionBody()
00104 {
00105
00106
00107 }
00108
00109 void
00110 CollisionBody::destroy()
00111 {
00112 PhysicsManager::get()->unregisterCollisionBody(this);
00113 dGeomDestroy(geomId());
00114 m_cleanedUp = true;
00115 }
00116
00117 bool
00118 CollisionBody::cleanedUp()
00119 {
00120 return m_cleanedUp;
00121 }
00122
00123 void
00124 CollisionBody::setCleanedUp(bool p_cleanedUp)
00125 {
00126 m_cleanedUp = p_cleanedUp;
00127 }
00128
00129 VRS::SO<VRS::SceneThing>
00130 CollisionBody::sceneThing() const
00131 {
00132 return m_sceneThing;
00133 }
00134
00135 const dGeomID
00136 CollisionBody::geomId() const
00137 {
00138 return m_geomId;
00139 }
00140
00141 const CollisionShape
00142 CollisionBody::collisionShape() const
00143 {
00144 return m_collisionShape;
00145 }
00146
00147 void
00148 CollisionBody::setupTransformationNodes()
00149 {
00150 if(!m_sceneThing)
00151 {
00152 rErr("Tried to setup a PhysicsBody which does not have a SceneThing "
00153 "associated. Nothing done!");
00154 return;
00155 }
00156
00157
00158 m_vrsShape = 0;
00159 for(int i = 0; i < m_sceneThing->objects(); i++)
00160 if(m_vrsShape = dynamic_cast<VRS::Shape*>(m_sceneThing->object(i)))
00161 break;
00162
00163
00164 VRS::Iterator<VRS::SO<VRS::SharedObj> >* rotationItr =
00165 m_sceneThing->find(VRS::Rotation::ClassNameVRS());
00166
00167
00168 if(rotationItr->size() == 0)
00169 {
00170 m_rotation = new VRS::Rotation();
00171 m_sceneThing->prepend(m_rotation);
00172 }
00173 else
00174 {
00175
00176 rErr("Handling already existing rotations is not yet implemented!");
00177 return;
00178 }
00179
00180
00181 VRS::Iterator<VRS::SO<VRS::SharedObj> >* translationItr =
00182 m_sceneThing->find(VRS::Translation::ClassNameVRS());
00183
00184
00185 if(translationItr->size() == 0)
00186 {
00187 m_translation = new VRS::Translation(0, 0, 0);
00188 m_sceneThing->prepend(m_translation);
00189 }
00190 else
00191 {
00192
00193 rErr("Handling already existing translations is not yet implemented!");
00194 return;
00195 }
00196
00197
00198
00199 }
00200
00201 void
00202 CollisionBody::insertLocker()
00203 {
00204 while(m_sceneThing->objects())
00205 {
00206 m_sceneNodeLock->append(m_sceneThing->object(0));
00207 m_sceneThing->remove(0);
00208 }
00209
00210 m_sceneThing->append(m_sceneNodeLock);
00211 }
00212
00213 const VRS::Vector
00214 CollisionBody::position() const
00215 {
00216 return m_translation->getTranslate();
00217 }
00218
00219 void
00220 CollisionBody::setPosition(double p_x, double p_y, double p_z)
00221 {
00222 setPosition(VRS::Vector(p_x, p_y, p_z));
00223 }
00224
00225 void
00226 CollisionBody::setPosition(VRS::Vector p_position)
00227 {
00228
00229 m_translation->setTranslate(p_position);
00230
00231 syncTransformationsToODE();
00232 }
00233
00234 const VRS::Matrix&
00235 CollisionBody::rotation() const
00236 {
00237 return m_rotation->matrix();
00238 }
00239
00240
00241 void
00242 CollisionBody::setRotation(double p_axisX, double p_axisY, double p_axisZ,
00243 double p_angle)
00244 {
00245 setRotation(VRS::Vector(p_axisX, p_axisY, p_axisZ), p_angle);
00246 }
00247
00248 void
00249 CollisionBody::setRotation(VRS::Vector p_axis, double p_angle)
00250 {
00251
00252
00253 VRS::Vector offset;
00254 if(m_odeShape)
00255 offset = m_odeShape->offsetCenter();
00256
00257 m_rotation->setAxis(p_axis);
00258 m_rotation->setCenter(offset);
00259 m_rotation->setAngle(p_angle);
00260
00261 syncTransformationsToODE();
00262 }
00263
00264 void
00265 CollisionBody::syncTransformationsToODE()
00266 {
00267 if(dGeomGetClass(m_geomId) == dPlaneClass)
00268 return;
00269
00270 dMatrix3 rot;
00271 VRS::Matrix matrix;
00272
00273 if(m_odeShape)
00274 matrix = rotation() * m_odeShape->offsetRotation()->matrix();
00275 else
00276 matrix = rotation();
00277
00278 rot[ 0] = matrix.element(0, 0);
00279 rot[ 1] = matrix.element(0, 1);
00280 rot[ 2] = matrix.element(0, 2);
00281 rot[ 3] = matrix.element(3, 0);
00282 rot[ 4] = matrix.element(1, 0);
00283 rot[ 5] = matrix.element(1, 1);
00284 rot[ 6] = matrix.element(1, 2);
00285 rot[ 7] = matrix.element(3, 1);
00286 rot[ 8] = matrix.element(2, 0);
00287 rot[ 9] = matrix.element(2, 1);
00288 rot[10] = matrix.element(2, 2);
00289 rot[11] = matrix.element(3, 2);
00290
00291 dGeomSetRotation(m_geomId, rot);
00292
00293 VRS::Vector offset;
00294 if(m_odeShape)
00295 offset = m_odeShape->offsetCenter();
00296
00297 VRS::Vector pos = position() + offset;
00298 dGeomSetPosition(m_geomId, pos[0], pos[1], pos[2]);
00299 }
00300
00301 void
00302 CollisionBody::setDebugNode(bool p_debugNode)
00303 {
00304 if(!m_odeShape)
00305 return;
00306
00307 if(m_odeShape->debugNodeActive() == p_debugNode)
00308 return;
00309
00310 m_odeShape->activateDebugNode(p_debugNode);
00311
00312 if(p_debugNode)
00313 m_sceneThing->append(m_odeShape->debugNode());
00314 else
00315 m_sceneThing->remove(m_odeShape->debugNode());
00316 }
00317
00318 VRS::SO<VRS::Translation>
00319 CollisionBody::translationNode()
00320 {
00321 return m_translation;
00322 }
00323
00324 VRS::SO<VRS::Rotation>
00325 CollisionBody::rotationNode()
00326 {
00327 return m_rotation;
00328 }
00329
00330 VRS::SO<VRS::Shape>
00331 CollisionBody::vrsShape()
00332 {
00333 return m_vrsShape;
00334 }
00335
00336 void
00337 CollisionBody::handleCollision(VRS::SO<CollisionBody> p_partner)
00338 {
00339 if(m_reportCollision)
00340 std::cout << this << " collided with " << p_partner << std::endl;
00341 }
00342
00343 void
00344 CollisionBody::setSurface(VRS::SO<Surface> p_surface)
00345 {
00346 m_surface = p_surface;
00347 }
00348
00349 VRS::SO<Surface>
00350 CollisionBody::surface()
00351 {
00352 return m_surface;
00353 }
00354
00355 VRS::SO<Shape>
00356 CollisionBody::odeShape()
00357 {
00358 return m_odeShape;
00359 }
00360
00361 bool
00362 CollisionBody::debugNode()
00363 {
00364 if(m_odeShape)
00365 return m_odeShape->debugNodeActive();
00366 return false;
00367 }
00368
00369 void
00370 CollisionBody::setCollisionCategory(unsigned int p_value)
00371 {
00372
00373 if(m_geomId)
00374 dGeomSetCategoryBits(m_geomId, p_value);
00375 }
00376
00377 unsigned int
00378 CollisionBody::collisionCategory()
00379 {
00380 if(!m_geomId)
00381 return 0;
00382
00383
00384 return dGeomGetCategoryBits(m_geomId);
00385 }
00386
00387 void
00388 CollisionBody::setCollisionPartnerCategories(unsigned int p_value)
00389 {
00390
00391 if(m_geomId)
00392 dGeomSetCollideBits(m_geomId, p_value);
00393 }
00394
00395 unsigned int
00396 CollisionBody::collisionPartnerCategories()
00397 {
00398 if(!m_geomId)
00399 return 0;
00400
00401
00402 return dGeomGetCollideBits(m_geomId);
00403 }
00404
00405 VRS::SO<SceneNodeLock>
00406 CollisionBody::sceneNodeLock()
00407 {
00408 return m_sceneNodeLock;
00409 }
00410
00411 void
00412 CollisionBody::setReportCollision(bool p_report)
00413 {
00414 m_reportCollision = p_report;
00415 }
00416
00417 void
00418 CollisionBody::wantToDestroy()
00419 {
00420 m_wantToDestroy = true;
00421 }
00422
00423 void
00424 CollisionBody::update()
00425 {
00426 if(m_wantToDestroy)
00427 destroy();
00428 }
00429
00430 }