Skip to main content
BulletDebugDrawer         Subclass from btIDebugDraw that allows you to visualize collision shapes, contact points and more

Subclass from btIDebugDraw that allows you to visualize collision shapes, contact points and more. It inherits also from Ogre::FrameListener to get updates. Not all functionality is implemented yet.

See BulletSharpDebugDrawer for a C# version.

Instantiate and connect the debug drawing object like this:

Copy to clipboard
mDebugDrawer = new OgreDebugDrawer( mSceneMgr ); mDebugDrawer->setDebugMode( btIDebugDraw::DBG_DrawWireframe ); dynamicsWorld->setDebugDrawer( mDebugDrawer );


When you want it to draw:

Copy to clipboard
dynamicsWorld->debugDrawWorld()


Interpreting the debug draw output

  • If your object is drawn with a red wireframe that indicates the object is 'deactivated' and will not be subject to forces in the simulation.
  • A green wireframe indicates it's active.


OgreBulletUtils.h

Copy to clipboard
inline btVector3 cvt(const Ogre::Vector3 &V){ return btVector3(V.x, V.y, V.z); } inline Ogre::Vector3 cvt(const btVector3&V){ return Ogre::Vector3(V.x(), V.y(), V.z()); } inline btQuaternion cvt(const Ogre::Quaternion &Q) { return btQuaternion(Q.x, Q.y, Q.z, Q.w); }; inline Ogre::Quaternion cvt(const btQuaternion &Q) { return Ogre::Quaternion(Q.w(), Q.x(), Q.y(), Q.z()); };

DebugDrawer.h

Copy to clipboard
#ifndef DebugDrawer_h__ #define DebugDrawer_h__ #include "../common.h" class OgreDebugDrawer: public btIDebugDraw, public Ogre::FrameListener{ public: OgreDebugDrawer( Ogre::SceneManager *scm ); ~OgreDebugDrawer (); virtual void drawLine (const btVector3 &from, const btVector3 &to, const btVector3 &color); virtual void drawTriangle (const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &color, btScalar); virtual void drawContactPoint (const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color); virtual void reportErrorWarning (const char *warningString); virtual void draw3dText (const btVector3 &location, const char *textString); virtual void setDebugMode (int debugMode); virtual int getDebugMode () const; protected: bool frameStarted(const Ogre::FrameEvent& evt); bool frameEnded(const Ogre::FrameEvent& evt); private: struct ContactPoint{ Ogre::Vector3 from; Ogre::Vector3 to; Ogre::ColourValue color; size_t dieTime; }; DebugDrawModes mDebugModes; Ogre::ManualObject *mLines; Ogre::ManualObject *mTriangles; std::vector< ContactPoint > *mContactPoints; std::vector< ContactPoint > mContactPoints1; std::vector< ContactPoint > mContactPoints2; }; #endif // DebugDrawer_h__

DebugDrawer.cpp

Copy to clipboard
#include "DebugDrawer.h" #include "OgreBulletUtils.h" using namespace Ogre; OgreDebugDrawer::OgreDebugDrawer( SceneManager *scm ) { mContactPoints = &mContactPoints1; mLines = new ManualObject("physics lines"); ASSERT( mLines ); mTriangles = new ManualObject("physics triangles"); ASSERT( mTriangles ); mLines->setDynamic(true); mTriangles->setDynamic(true); //mLines->estimateVertexCount( 100000 ); //mLines->estimateIndexCount( 0 ); scm->getRootSceneNode()->attachObject( mLines ); scm->getRootSceneNode()->attachObject( mTriangles ); static const char * matName = "OgreBulletCollisionsDebugDefault"; MaterialPtr mtl = MaterialManager::getSingleton().getDefaultSettings()->clone(matName); mtl->setReceiveShadows(false); mtl->setSceneBlending( SBT_TRANSPARENT_ALPHA ); mtl->setDepthBias( 0.1, 0 ); TextureUnitState * tu = mtl->getTechnique(0)->getPass(0)->createTextureUnitState(); ASSERT( tu ); tu->setColourOperationEx( LBX_SOURCE1, LBS_DIFFUSE ); mtl->getTechnique(0)->setLightingEnabled(false); //mtl->getTechnique(0)->setSelfIllumination( ColourValue::White ); mLines->begin( matName, RenderOperation::OT_LINE_LIST ); mLines->position( Vector3::ZERO ); mLines->colour( ColourValue::Blue ); mLines->position( Vector3::ZERO ); mLines->colour( ColourValue::Blue ); mTriangles->begin( matName, RenderOperation::OT_TRIANGLE_LIST ); mTriangles->position( Vector3::ZERO ); mTriangles->colour( ColourValue::Blue ); mTriangles->position( Vector3::ZERO ); mTriangles->colour( ColourValue::Blue ); mTriangles->position( Vector3::ZERO ); mTriangles->colour( ColourValue::Blue ); mDebugModes = (DebugDrawModes) DBG_DrawWireframe; Root::getSingleton().addFrameListener(this); } OgreDebugDrawer::~OgreDebugDrawer() { Root::getSingleton().removeFrameListener(this); delete mLines; delete mTriangles; } void OgreDebugDrawer::drawLine( const btVector3 &from, const btVector3 &to, const btVector3 &color ) { ColourValue c( color.getX(), color.getY(), color.getZ() ); c.saturate(); mLines->position( cvt(from) ); mLines->colour( c ); mLines->position( cvt(to) ); mLines->colour( c ); } void OgreDebugDrawer::drawTriangle( const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &color, btScalar alpha ) { ColourValue c( color.getX(), color.getY(), color.getZ(), alpha ); c.saturate(); mTriangles->position( cvt(v0) ); mTriangles->colour( c ); mTriangles->position( cvt(v1) ); mTriangles->colour( c ); mTriangles->position( cvt(v2) ); mTriangles->colour( c ); } void OgreDebugDrawer::drawContactPoint( const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color ) { mContactPoints->resize( mContactPoints->size() + 1 ); ContactPoint p = mContactPoints->back(); p.from = cvt( PointOnB ); p.to = p.from + cvt( normalOnB ) * distance; p.dieTime = Root::getSingleton().getTimer()->getMilliseconds() + lifeTime; p.color.r = color.x(); p.color.g = color.y(); p.color.b = color.z(); } bool OgreDebugDrawer::frameStarted( const Ogre::FrameEvent& evt ) { size_t now = Root::getSingleton().getTimer()->getMilliseconds(); std::vector< ContactPoint > *newCP = mContactPoints == &mContactPoints1 ? &mContactPoints2 : &mContactPoints1; for ( std::vector< ContactPoint >::iterator i = mContactPoints->begin(); i < mContactPoints->end(); i++ ){ ContactPoint &cp = *i; mLines->position( cp.from ); mLines->colour( cp.color ); mLines->position( cp.to ); if ( now <= cp.dieTime ) newCP->push_back( cp ); } mContactPoints->clear(); mContactPoints = newCP; mLines->end(); mTriangles->end(); return true; } bool OgreDebugDrawer::frameEnded( const Ogre::FrameEvent& evt ) { mLines->beginUpdate(0); mTriangles->beginUpdate(0); return true; } void OgreDebugDrawer::reportErrorWarning( const char *warningString ) { LogManager::getSingleton().getDefaultLog()->logMessage( warningString ); } void OgreDebugDrawer::draw3dText( const btVector3 &location, const char *textString ) { } void OgreDebugDrawer::setDebugMode( int debugMode ) { mDebugModes = (DebugDrawModes) debugMode; } int OgreDebugDrawer::getDebugMode() const { return mDebugModes; }