From 1943110170fb7c5242da9a4fa511f779fbc21121 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 3 May 2015 00:39:01 +0200 Subject: [PATCH] Add bullet debug drawer --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwrender/bulletdebugdraw.cpp | 98 ++++++++++++++++++++++++ apps/openmw/mwrender/bulletdebugdraw.hpp | 58 ++++++++++++++ apps/openmw/mwrender/debugging.cpp | 4 - apps/openmw/mwworld/physicssystem.cpp | 26 ++++++- apps/openmw/mwworld/physicssystem.hpp | 21 ++++- apps/openmw/mwworld/scene.cpp | 26 ++----- apps/openmw/mwworld/worldimp.cpp | 17 ++-- libs/openengine/bullet/physic.cpp | 46 +---------- libs/openengine/bullet/physic.hpp | 23 ------ 10 files changed, 221 insertions(+), 99 deletions(-) create mode 100644 apps/openmw/mwrender/bulletdebugdraw.cpp create mode 100644 apps/openmw/mwrender/bulletdebugdraw.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index ed55301260..81cecc2c87 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -22,6 +22,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender actors objects renderingmanager animation sky npcanimation vismask creatureanimation effectmanager util renderinginterface debugging rendermode + bulletdebugdraw # camera activatoranimation # localmap occlusionquery water shadows # characterpreview globalmap ripplesimulation refraction diff --git a/apps/openmw/mwrender/bulletdebugdraw.cpp b/apps/openmw/mwrender/bulletdebugdraw.cpp new file mode 100644 index 0000000000..9e683232b1 --- /dev/null +++ b/apps/openmw/mwrender/bulletdebugdraw.cpp @@ -0,0 +1,98 @@ +#include "bulletdebugdraw.hpp" + +#include + +#include +#include +#include + +#include "vismask.hpp" + +namespace +{ + osg::Vec3f toOsg(const btVector3& vec) + { + return osg::Vec3f(vec.x(), vec.y(), vec.z()); + } +} + +namespace MWRender +{ + +DebugDrawer::DebugDrawer(osg::ref_ptr parentNode, btDynamicsWorld *world) + : mParentNode(parentNode), + mWorld(world), + mDebugOn(true) +{ + mGeode = new osg::Geode; + mParentNode->addChild(mGeode); + mGeode->setNodeMask(Mask_Debug); + + mGeometry = new osg::Geometry; + + mVertices = new osg::Vec3Array; + + mDrawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES); + + mGeometry->setUseDisplayList(false); + mGeometry->setVertexArray(mVertices); + mGeometry->setDataVariance(osg::Object::DYNAMIC); + mGeometry->addPrimitiveSet(mDrawArrays); + + mGeode->addDrawable(mGeometry); + mParentNode->addChild(mGeode); +} + +DebugDrawer::~DebugDrawer() +{ + mParentNode->removeChild(mGeode); +} + +void DebugDrawer::step() +{ + if (mDebugOn) + { + mVertices->clear(); + mWorld->debugDrawWorld(); + mDrawArrays->setCount(mVertices->size()); + mVertices->dirty(); + } +} + +void DebugDrawer::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color) +{ + mVertices->push_back(toOsg(from)); + mVertices->push_back(toOsg(to)); +} + +void DebugDrawer::drawContactPoint(const btVector3 &PointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color) +{ + mVertices->push_back(toOsg(PointOnB)); + mVertices->push_back(toOsg(PointOnB) + (toOsg(normalOnB) * distance * 20)); +} + +void DebugDrawer::reportErrorWarning(const char *warningString) +{ + std::cerr << warningString << std::endl; +} + +void DebugDrawer::setDebugMode(int isOn) +{ + mDebugOn = (isOn == 0) ? false : true; + + if (!mDebugOn) + { + mVertices->clear(); + mVertices->releaseGLObjects(0); + mGeometry->releaseGLObjects(0); + } +} + +int DebugDrawer::getDebugMode() const +{ + return mDebugOn; +} + + + +} diff --git a/apps/openmw/mwrender/bulletdebugdraw.hpp b/apps/openmw/mwrender/bulletdebugdraw.hpp new file mode 100644 index 0000000000..288091e7ce --- /dev/null +++ b/apps/openmw/mwrender/bulletdebugdraw.hpp @@ -0,0 +1,58 @@ +#ifndef OPENMW_MWRENDER_BULLETDEBUGDRAW_H +#define OPENMW_MWRENDER_BULLETDEBUGDRAW_H + +#include "btBulletDynamicsCommon.h" + +#include +#include +#include + +namespace osg +{ + class Group; + class Geode; + class Geometry; +} + +namespace MWRender +{ + +class DebugDrawer : public btIDebugDraw +{ +protected: + osg::ref_ptr mParentNode; + btDynamicsWorld *mWorld; + osg::ref_ptr mGeode; + osg::ref_ptr mGeometry; + osg::ref_ptr mVertices; + osg::ref_ptr mDrawArrays; + + bool mDebugOn; + +public: + + DebugDrawer(osg::ref_ptr parentNode, btDynamicsWorld *world); + ~DebugDrawer(); + + void step(); + + void drawLine(const btVector3& from,const btVector3& to,const btVector3& color); + + void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color); + + void reportErrorWarning(const char* warningString); + + void draw3dText(const btVector3& location,const char* textString) {} + + //0 for off, anything else for on. + void setDebugMode(int isOn); + + //0 for off, anything else for on. + int getDebugMode() const; + +}; + + +} + +#endif diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 97ead9d7d3..9cbf94d46e 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -146,10 +146,6 @@ Debugging::~Debugging() bool Debugging::toggleRenderMode (int mode){ switch (mode) { - //case Render_CollisionDebug: - - //return mEngine->toggleDebugRendering(); - case Render_Pathgrid: togglePathgrid(); return mPathgridEnabled; diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 271b23d098..4222683977 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include #include @@ -29,6 +31,8 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwrender/bulletdebugdraw.hpp" + //#include "../apps/openmw/mwrender/animation.hpp" #include "../apps/openmw/mwbase/world.hpp" #include "../apps/openmw/mwbase/environment.hpp" @@ -498,8 +502,8 @@ namespace MWWorld }; - PhysicsSystem::PhysicsSystem() : - mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0) + PhysicsSystem::PhysicsSystem(osg::ref_ptr parentNode) : + mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0), mDebugDrawEnabled(false), mParentNode(parentNode) { // Create physics. shapeLoader is deleted by the physic engine //NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); @@ -514,6 +518,21 @@ namespace MWWorld //delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); } + bool PhysicsSystem::toggleDebugRendering() + { + mDebugDrawEnabled = !mDebugDrawEnabled; + + if (mDebugDrawEnabled && !mDebugDrawer.get()) + { + mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld)); + mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get()); + mDebugDrawer->setDebugMode(mDebugDrawEnabled); + } + else if (mDebugDrawer.get()) + mDebugDrawer->setDebugMode(mDebugDrawEnabled); + return mDebugDrawEnabled; + } + OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() { return mEngine; @@ -799,6 +818,9 @@ namespace MWWorld animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld); mEngine->stepSimulation(dt); + + if (mDebugDrawer.get()) + mDebugDrawer->step(); } bool PhysicsSystem::isActorStandingOn(const Ptr &actor, const Ptr &object) const diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 23bf47543c..1fc0e0e768 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -7,8 +7,14 @@ #include +#include + #include "ptr.hpp" +namespace osg +{ + class Group; +} namespace OEngine { @@ -18,6 +24,11 @@ namespace OEngine } } +namespace MWRender +{ + class DebugDrawer; +} + namespace MWWorld { class World; @@ -27,7 +38,7 @@ namespace MWWorld class PhysicsSystem { public: - PhysicsSystem (); + PhysicsSystem (osg::ref_ptr parentNode); ~PhysicsSystem (); void enableWater(float height); @@ -98,10 +109,14 @@ namespace MWWorld /// Get the handle of all actors colliding with \a object in this frame. void getActorsCollidingWith(const MWWorld::Ptr& object, std::vector& out) const; + bool toggleDebugRendering(); + private: void updateWater(); + bool mDebugDrawEnabled; + OEngine::Physic::PhysicEngine* mEngine; std::map handleToMesh; @@ -123,6 +138,10 @@ namespace MWWorld std::auto_ptr mWaterCollisionObject; std::auto_ptr mWaterCollisionShape; + std::auto_ptr mDebugDrawer; + + osg::ref_ptr mParentNode; + PhysicsSystem (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&); }; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 637fde18ca..1ccbc6b555 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -18,7 +18,7 @@ #include "../mwrender/renderingmanager.hpp" -//#include "physicssystem.hpp" +#include "physicssystem.hpp" #include "player.hpp" #include "localscripts.hpp" #include "esmstore.hpp" @@ -26,8 +26,6 @@ #include "cellfunctors.hpp" #include "cellstore.hpp" -#include - namespace { @@ -194,26 +192,22 @@ namespace MWWorld ListAndResetHandles functor; (*iter)->forEach(functor); + for (std::vector::const_iterator iter2 (functor.mHandles.begin()); + iter2!=functor.mHandles.end(); ++iter2) { - // silence annoying g++ warning - for (std::vector::const_iterator iter2 (functor.mHandles.begin()); - iter2!=functor.mHandles.end(); ++iter2) - { - //Ogre::SceneNode* node = *iter2; - //mPhysics->removeObject (node->getName()); - } + //Ogre::SceneNode* node = *iter2; + //mPhysics->removeObject (node->getName()); } if ((*iter)->getCell()->isExterior()) { - /*ESM::Land* land = + ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().get().search( (*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY() ); if (land && land->mDataTypes&ESM::Land::DATA_VHGT) mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY()); - */ } mRendering.removeCell(*iter); @@ -234,10 +228,9 @@ namespace MWWorld { std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl; - //float verts = ESM::Land::LAND_SIZE; - //float worldsize = ESM::Land::REAL_SIZE; + float verts = ESM::Land::LAND_SIZE; + float worldsize = ESM::Land::REAL_SIZE; -#if 0 // Load terrain physics first... if (cell->getCell()->isExterior()) { @@ -262,7 +255,6 @@ namespace MWWorld ; } } -#endif cell->respawn(); @@ -316,9 +308,7 @@ namespace MWWorld { int newX, newY; MWBase::Environment::get().getWorld()->positionToIndex(pos.x(), pos.y(), newX, newY); - osg::Timer timer; changeCellGrid(newX, newY); - std::cout << "changeCellGrid took " << timer.time_m() << std::endl; //mRendering.updateTerrain(); } } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index fda9d53af6..04fd82e80a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -161,7 +161,7 @@ namespace MWWorld mStartCell (startCell), mStartupScript(startupScript), mScriptsEnabled(true) { - mPhysics = new PhysicsSystem(); + mPhysics = new PhysicsSystem(rootNode); //mPhysEngine = mPhysics->getEngine(); #if 0 mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine)); @@ -1409,9 +1409,8 @@ namespace MWWorld void World::doPhysics(float duration) { + mPhysics->stepSimulation(duration); #if 0 - //mPhysics->stepSimulation(duration); - processDoors(duration); mProjectileManager->update(duration); @@ -1503,7 +1502,13 @@ namespace MWWorld bool World::toggleRenderMode (MWRender::RenderMode mode) { - return mRendering->toggleRenderMode (mode); + switch (mode) + { + case MWRender::Render_CollisionDebug: + return mPhysics->toggleDebugRendering(); + default: + return mRendering->toggleRenderMode(mode); + } } const ESM::Potion *World::createRecord (const ESM::Potion& record) @@ -1601,8 +1606,8 @@ namespace MWWorld updateWeather(duration, paused); - //if (!paused) - // doPhysics (duration); + if (!paused) + doPhysics (duration); mWorldScene->update (duration, paused); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index b1bd978c6b..35c767ca92 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -240,9 +240,7 @@ namespace Physic - PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) : - mDebugActive(0) - , mSceneMgr(NULL) + PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) { // Set up the collision configuration and dispatcher collisionConfiguration = new btDefaultCollisionConfiguration(); @@ -263,42 +261,6 @@ namespace Physic mDynamicsWorld->setGravity(btVector3(0,0,-10)); mShapeLoader = shapeLoader; - - isDebugCreated = false; - mDebugDrawer = NULL; - } - - void PhysicEngine::createDebugRendering() - { - if(!isDebugCreated) - { - Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); - mDebugDrawer = new BtOgre::DebugDrawer(node, mDynamicsWorld); - mDynamicsWorld->setDebugDrawer(mDebugDrawer); - isDebugCreated = true; - mDynamicsWorld->debugDrawWorld(); - } - } - - void PhysicEngine::setDebugRenderingMode(bool isDebug) - { - if(!isDebugCreated) - { - createDebugRendering(); - } - mDebugDrawer->setDebugMode(isDebug); - mDebugActive = isDebug; - } - - bool PhysicEngine::toggleDebugRendering() - { - setDebugRenderingMode(!mDebugActive); - return mDebugActive; - } - - void PhysicEngine::setSceneManager(Ogre::SceneManager* sceneMgr) - { - mSceneMgr = sceneMgr; } PhysicEngine::~PhysicEngine() @@ -336,8 +298,6 @@ namespace Physic } } - delete mDebugDrawer; - delete mDynamicsWorld; delete solver; delete collisionConfiguration; @@ -652,10 +612,6 @@ namespace Physic { // This seems to be needed for character controller objects mDynamicsWorld->stepSimulation(static_cast(deltaT), 10, 1 / 60.0f); - if(isDebugCreated) - { - mDebugDrawer->step(); - } } void PhysicEngine::addCharacter(const std::string &name, const std::string &mesh, diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index e92e9c3c1c..6322105e8e 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -271,22 +271,6 @@ namespace Physic */ void stepSimulation(double deltaT); - /** - * Create a debug rendering. It is called by setDebgRenderingMode if it's not created yet. - * Important Note: this will crash if the Render is not yet initialise! - */ - void createDebugRendering(); - - /** - * Set the debug rendering mode. 0 to turn it off. - * Important Note: this will crash if the Render is not yet initialise! - */ - void setDebugRenderingMode(bool isDebug); - - bool toggleDebugRendering(); - - void setSceneManager(Ogre::SceneManager* sceneMgr); - /** * Return the closest object hit by a ray. If there are no objects, it will return ("",-1). * If \a normal is non-NULL, the hit normal will be written there (if there is a hit) @@ -328,13 +312,6 @@ namespace Physic typedef std::map PhysicActorContainer; PhysicActorContainer mActorMap; - Ogre::SceneManager* mSceneMgr; - - //debug rendering - BtOgre::DebugDrawer* mDebugDrawer; - bool isDebugCreated; - bool mDebugActive; - private: PhysicEngine(const PhysicEngine&); PhysicEngine& operator=(const PhysicEngine&);