1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-21 18:09:39 +00:00

Add bullet debug drawer

This commit is contained in:
scrawl 2015-05-03 00:39:01 +02:00
parent 9cf9c2876e
commit 1943110170
10 changed files with 221 additions and 99 deletions

View file

@ -22,6 +22,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
actors objects renderingmanager animation sky npcanimation vismask actors objects renderingmanager animation sky npcanimation vismask
creatureanimation effectmanager util renderinginterface debugging rendermode creatureanimation effectmanager util renderinginterface debugging rendermode
bulletdebugdraw
# camera activatoranimation # camera activatoranimation
# localmap occlusionquery water shadows # localmap occlusionquery water shadows
# characterpreview globalmap ripplesimulation refraction # characterpreview globalmap ripplesimulation refraction

View file

@ -0,0 +1,98 @@
#include "bulletdebugdraw.hpp"
#include <iostream>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#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<osg::Group> 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;
}
}

View file

@ -0,0 +1,58 @@
#ifndef OPENMW_MWRENDER_BULLETDEBUGDRAW_H
#define OPENMW_MWRENDER_BULLETDEBUGDRAW_H
#include "btBulletDynamicsCommon.h"
#include <osg/ref_ptr>
#include <osg/Array>
#include <osg/PrimitiveSet>
namespace osg
{
class Group;
class Geode;
class Geometry;
}
namespace MWRender
{
class DebugDrawer : public btIDebugDraw
{
protected:
osg::ref_ptr<osg::Group> mParentNode;
btDynamicsWorld *mWorld;
osg::ref_ptr<osg::Geode> mGeode;
osg::ref_ptr<osg::Geometry> mGeometry;
osg::ref_ptr<osg::Vec3Array> mVertices;
osg::ref_ptr<osg::DrawArrays> mDrawArrays;
bool mDebugOn;
public:
DebugDrawer(osg::ref_ptr<osg::Group> 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

View file

@ -146,10 +146,6 @@ Debugging::~Debugging()
bool Debugging::toggleRenderMode (int mode){ bool Debugging::toggleRenderMode (int mode){
switch (mode) switch (mode)
{ {
//case Render_CollisionDebug:
//return mEngine->toggleDebugRendering();
case Render_Pathgrid: case Render_Pathgrid:
togglePathgrid(); togglePathgrid();
return mPathgridEnabled; return mPathgridEnabled;

View file

@ -10,6 +10,8 @@
#include <OgreTextureManager.h> #include <OgreTextureManager.h>
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <osg/Group>
#include <openengine/bullet/trace.h> #include <openengine/bullet/trace.h>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <openengine/bullet/BtOgreExtras.h> #include <openengine/bullet/BtOgreExtras.h>
@ -29,6 +31,8 @@
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwrender/bulletdebugdraw.hpp"
//#include "../apps/openmw/mwrender/animation.hpp" //#include "../apps/openmw/mwrender/animation.hpp"
#include "../apps/openmw/mwbase/world.hpp" #include "../apps/openmw/mwbase/world.hpp"
#include "../apps/openmw/mwbase/environment.hpp" #include "../apps/openmw/mwbase/environment.hpp"
@ -498,8 +502,8 @@ namespace MWWorld
}; };
PhysicsSystem::PhysicsSystem() : PhysicsSystem::PhysicsSystem(osg::ref_ptr<osg::Group> parentNode) :
mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0) mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0), mDebugDrawEnabled(false), mParentNode(parentNode)
{ {
// Create physics. shapeLoader is deleted by the physic engine // Create physics. shapeLoader is deleted by the physic engine
//NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); //NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader();
@ -514,6 +518,21 @@ namespace MWWorld
//delete OEngine::Physic::BulletShapeManager::getSingletonPtr(); //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() OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine()
{ {
return mEngine; return mEngine;
@ -799,6 +818,9 @@ namespace MWWorld
animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld); animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
mEngine->stepSimulation(dt); mEngine->stepSimulation(dt);
if (mDebugDrawer.get())
mDebugDrawer->step();
} }
bool PhysicsSystem::isActorStandingOn(const Ptr &actor, const Ptr &object) const bool PhysicsSystem::isActorStandingOn(const Ptr &actor, const Ptr &object) const

View file

@ -7,8 +7,14 @@
#include <btBulletCollisionCommon.h> #include <btBulletCollisionCommon.h>
#include <osg/ref_ptr>
#include "ptr.hpp" #include "ptr.hpp"
namespace osg
{
class Group;
}
namespace OEngine namespace OEngine
{ {
@ -18,6 +24,11 @@ namespace OEngine
} }
} }
namespace MWRender
{
class DebugDrawer;
}
namespace MWWorld namespace MWWorld
{ {
class World; class World;
@ -27,7 +38,7 @@ namespace MWWorld
class PhysicsSystem class PhysicsSystem
{ {
public: public:
PhysicsSystem (); PhysicsSystem (osg::ref_ptr<osg::Group> parentNode);
~PhysicsSystem (); ~PhysicsSystem ();
void enableWater(float height); void enableWater(float height);
@ -98,10 +109,14 @@ namespace MWWorld
/// Get the handle of all actors colliding with \a object in this frame. /// Get the handle of all actors colliding with \a object in this frame.
void getActorsCollidingWith(const MWWorld::Ptr& object, std::vector<std::string>& out) const; void getActorsCollidingWith(const MWWorld::Ptr& object, std::vector<std::string>& out) const;
bool toggleDebugRendering();
private: private:
void updateWater(); void updateWater();
bool mDebugDrawEnabled;
OEngine::Physic::PhysicEngine* mEngine; OEngine::Physic::PhysicEngine* mEngine;
std::map<std::string, std::string> handleToMesh; std::map<std::string, std::string> handleToMesh;
@ -123,6 +138,10 @@ namespace MWWorld
std::auto_ptr<btCollisionObject> mWaterCollisionObject; std::auto_ptr<btCollisionObject> mWaterCollisionObject;
std::auto_ptr<btCollisionShape> mWaterCollisionShape; std::auto_ptr<btCollisionShape> mWaterCollisionShape;
std::auto_ptr<MWRender::DebugDrawer> mDebugDrawer;
osg::ref_ptr<osg::Group> mParentNode;
PhysicsSystem (const PhysicsSystem&); PhysicsSystem (const PhysicsSystem&);
PhysicsSystem& operator= (const PhysicsSystem&); PhysicsSystem& operator= (const PhysicsSystem&);
}; };

View file

@ -18,7 +18,7 @@
#include "../mwrender/renderingmanager.hpp" #include "../mwrender/renderingmanager.hpp"
//#include "physicssystem.hpp" #include "physicssystem.hpp"
#include "player.hpp" #include "player.hpp"
#include "localscripts.hpp" #include "localscripts.hpp"
#include "esmstore.hpp" #include "esmstore.hpp"
@ -26,8 +26,6 @@
#include "cellfunctors.hpp" #include "cellfunctors.hpp"
#include "cellstore.hpp" #include "cellstore.hpp"
#include <osg/Timer>
namespace namespace
{ {
@ -194,26 +192,22 @@ namespace MWWorld
ListAndResetHandles functor; ListAndResetHandles functor;
(*iter)->forEach<ListAndResetHandles>(functor); (*iter)->forEach<ListAndResetHandles>(functor);
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin());
iter2!=functor.mHandles.end(); ++iter2)
{ {
// silence annoying g++ warning //Ogre::SceneNode* node = *iter2;
for (std::vector<Ogre::SceneNode*>::const_iterator iter2 (functor.mHandles.begin()); //mPhysics->removeObject (node->getName());
iter2!=functor.mHandles.end(); ++iter2)
{
//Ogre::SceneNode* node = *iter2;
//mPhysics->removeObject (node->getName());
}
} }
if ((*iter)->getCell()->isExterior()) if ((*iter)->getCell()->isExterior())
{ {
/*ESM::Land* land = ESM::Land* land =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search( MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
(*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridX(),
(*iter)->getCell()->getGridY() (*iter)->getCell()->getGridY()
); );
if (land && land->mDataTypes&ESM::Land::DATA_VHGT) if (land && land->mDataTypes&ESM::Land::DATA_VHGT)
mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY()); mPhysics->removeHeightField ((*iter)->getCell()->getGridX(), (*iter)->getCell()->getGridY());
*/
} }
mRendering.removeCell(*iter); mRendering.removeCell(*iter);
@ -234,10 +228,9 @@ namespace MWWorld
{ {
std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl; std::cout << "loading cell " << cell->getCell()->getDescription() << std::endl;
//float verts = ESM::Land::LAND_SIZE; float verts = ESM::Land::LAND_SIZE;
//float worldsize = ESM::Land::REAL_SIZE; float worldsize = ESM::Land::REAL_SIZE;
#if 0
// Load terrain physics first... // Load terrain physics first...
if (cell->getCell()->isExterior()) if (cell->getCell()->isExterior())
{ {
@ -262,7 +255,6 @@ namespace MWWorld
; ;
} }
} }
#endif
cell->respawn(); cell->respawn();
@ -316,9 +308,7 @@ namespace MWWorld
{ {
int newX, newY; int newX, newY;
MWBase::Environment::get().getWorld()->positionToIndex(pos.x(), pos.y(), newX, newY); MWBase::Environment::get().getWorld()->positionToIndex(pos.x(), pos.y(), newX, newY);
osg::Timer timer;
changeCellGrid(newX, newY); changeCellGrid(newX, newY);
std::cout << "changeCellGrid took " << timer.time_m() << std::endl;
//mRendering.updateTerrain(); //mRendering.updateTerrain();
} }
} }

View file

@ -161,7 +161,7 @@ namespace MWWorld
mStartCell (startCell), mStartupScript(startupScript), mStartCell (startCell), mStartupScript(startupScript),
mScriptsEnabled(true) mScriptsEnabled(true)
{ {
mPhysics = new PhysicsSystem(); mPhysics = new PhysicsSystem(rootNode);
//mPhysEngine = mPhysics->getEngine(); //mPhysEngine = mPhysics->getEngine();
#if 0 #if 0
mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine)); mProjectileManager.reset(new ProjectileManager(renderer.getScene(), *mPhysEngine));
@ -1409,9 +1409,8 @@ namespace MWWorld
void World::doPhysics(float duration) void World::doPhysics(float duration)
{ {
mPhysics->stepSimulation(duration);
#if 0 #if 0
//mPhysics->stepSimulation(duration);
processDoors(duration); processDoors(duration);
mProjectileManager->update(duration); mProjectileManager->update(duration);
@ -1503,7 +1502,13 @@ namespace MWWorld
bool World::toggleRenderMode (MWRender::RenderMode mode) 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) const ESM::Potion *World::createRecord (const ESM::Potion& record)
@ -1601,8 +1606,8 @@ namespace MWWorld
updateWeather(duration, paused); updateWeather(duration, paused);
//if (!paused) if (!paused)
// doPhysics (duration); doPhysics (duration);
mWorldScene->update (duration, paused); mWorldScene->update (duration, paused);

View file

@ -240,9 +240,7 @@ namespace Physic
PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) : PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader)
mDebugActive(0)
, mSceneMgr(NULL)
{ {
// Set up the collision configuration and dispatcher // Set up the collision configuration and dispatcher
collisionConfiguration = new btDefaultCollisionConfiguration(); collisionConfiguration = new btDefaultCollisionConfiguration();
@ -263,42 +261,6 @@ namespace Physic
mDynamicsWorld->setGravity(btVector3(0,0,-10)); mDynamicsWorld->setGravity(btVector3(0,0,-10));
mShapeLoader = shapeLoader; 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() PhysicEngine::~PhysicEngine()
@ -336,8 +298,6 @@ namespace Physic
} }
} }
delete mDebugDrawer;
delete mDynamicsWorld; delete mDynamicsWorld;
delete solver; delete solver;
delete collisionConfiguration; delete collisionConfiguration;
@ -652,10 +612,6 @@ namespace Physic
{ {
// This seems to be needed for character controller objects // This seems to be needed for character controller objects
mDynamicsWorld->stepSimulation(static_cast<btScalar>(deltaT), 10, 1 / 60.0f); mDynamicsWorld->stepSimulation(static_cast<btScalar>(deltaT), 10, 1 / 60.0f);
if(isDebugCreated)
{
mDebugDrawer->step();
}
} }
void PhysicEngine::addCharacter(const std::string &name, const std::string &mesh, void PhysicEngine::addCharacter(const std::string &name, const std::string &mesh,

View file

@ -271,22 +271,6 @@ namespace Physic
*/ */
void stepSimulation(double deltaT); 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). * 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) * 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<std::string, PhysicActor*> PhysicActorContainer; typedef std::map<std::string, PhysicActor*> PhysicActorContainer;
PhysicActorContainer mActorMap; PhysicActorContainer mActorMap;
Ogre::SceneManager* mSceneMgr;
//debug rendering
BtOgre::DebugDrawer* mDebugDrawer;
bool isDebugCreated;
bool mDebugActive;
private: private:
PhysicEngine(const PhysicEngine&); PhysicEngine(const PhysicEngine&);
PhysicEngine& operator=(const PhysicEngine&); PhysicEngine& operator=(const PhysicEngine&);