diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 60b299acd1..f1e601af52 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -12,27 +12,141 @@ #include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwworld/ptr.hpp" #include +#include #include "player.hpp" using namespace MWRender; using namespace Ogre; -Debugging::Debugging(OEngine::Physic::PhysicEngine* engine){ - eng = engine; +Debugging::Debugging(const ESMS::ESMStore &store, SceneManager* sceneMgr, OEngine::Physic::PhysicEngine *engine) : + mStore(store), mSceneMgr(sceneMgr), mEngine(engine), pathgridEnabled(false) +{ } bool Debugging::toggleRenderMode (int mode){ - switch (mode) + switch (mode) { case MWWorld::World::Render_CollisionDebug: // TODO use a proper function instead of accessing the member variable // directly. - eng->setDebugRenderingMode (!eng->isDebugCreated); - return eng->isDebugCreated; + mEngine->setDebugRenderingMode (!mEngine->isDebugCreated); + return mEngine->isDebugCreated; + case MWWorld::World::Render_Pathgrid: + togglePathgrid(); + return pathgridEnabled; } return false; } + +void Debugging::cellAdded(MWWorld::Ptr::CellStore *store) +{ + std::cout << "Cell added to debugging" << std::endl; + mActiveCells.push_back(store); + if (pathgridEnabled) + togglePathgridForCell(store, true); +} + +void Debugging::cellRemoved(MWWorld::Ptr::CellStore *store) +{ + mActiveCells.erase(std::remove(mActiveCells.begin(), mActiveCells.end(), store), mActiveCells.end()); + std::cout << "Cell removed from debugging, active cells count: " << mActiveCells.size() << std::endl; + if (pathgridEnabled) + togglePathgridForCell(store, false); +} + +void Debugging::togglePathgrid() +{ + pathgridEnabled = !pathgridEnabled; + if (pathgridEnabled) + { + // add path grid meshes to already loaded cells + mPathGridRoot = mSceneMgr->getRootSceneNode()->createChildSceneNode(); + for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) + { + togglePathgridForCell(*it, true); + } + } + else { + // remove path grid meshes from already loaded cells + for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); it++) + { + togglePathgridForCell(*it, false); + } + mPathGridRoot->removeAndDestroyAllChildren(); + mSceneMgr->destroySceneNode(mPathGridRoot); + } +} + +void Debugging::togglePathgridForCell(MWWorld::Ptr::CellStore *store, bool enabled) +{ + ESM::Pathgrid *pathgrid = mStore.pathgrids.search(*store->cell); + if (!pathgrid) + { + std::cout << "No path grid :(" << std::endl; + return; + } + std::cout << "Path grid exists!" << std::endl; + + if (enabled) + { + Vector3 cellPathGridPos; + if (!(store->cell->data.flags & ESM::Cell::Interior)) + { + /// \todo Replace with ESM::Land::REAL_SIZE after merging with terrain branch + cellPathGridPos.x = store->cell->data.gridX * 8192; + cellPathGridPos.z = -store->cell->data.gridY * 8192; + } + SceneNode *cellPathGrid = mPathGridRoot->createChildSceneNode(cellPathGridPos); + ESM::Pathgrid::PointList points = pathgrid->points; + for (ESM::Pathgrid::PointList::iterator it = points.begin(); it != points.end(); it++) + { + Vector3 position(it->x, it->z, -it->y); + SceneNode* pointNode = cellPathGrid->createChildSceneNode(position); + pointNode->setScale(0.5, 0.5, 0.5); + Entity *pointMesh = mSceneMgr->createEntity(SceneManager::PT_CUBE); + pointNode->attachObject(pointMesh); + } + + if (!(store->cell->data.flags & ESM::Cell::Interior)) + { + mExteriorPathgridNodes[std::make_pair(store->cell->data.gridX, store->cell->data.gridY)] = cellPathGrid; + } + else + { + assert(mInteriorPathgridNode == NULL); + mInteriorPathgridNode = cellPathGrid; + } + } + else + { + /// \todo Don't forget to destroy cubes too! + SceneNode *cellPathGridNode; + if (!(store->cell->data.flags & ESM::Cell::Interior)) + { + ExteriorPathgridNodes::iterator it = + mExteriorPathgridNodes.find(std::make_pair(store->cell->data.gridX, store->cell->data.gridY)); + if (it != mExteriorPathgridNodes.end()) + { + cellPathGridNode = it->second; + mPathGridRoot->removeChild(cellPathGridNode); + cellPathGridNode->removeAndDestroyAllChildren(); + mSceneMgr->destroySceneNode(cellPathGridNode); + mExteriorPathgridNodes.erase(it); + } + } + else + { + if (mInteriorPathgridNode) + { + mPathGridRoot->removeChild(mInteriorPathgridNode); + mInteriorPathgridNode->removeAndDestroyAllChildren(); + mSceneMgr->destroySceneNode(mInteriorPathgridNode); + mInteriorPathgridNode = NULL; + } + } + } +} diff --git a/apps/openmw/mwrender/debugging.hpp b/apps/openmw/mwrender/debugging.hpp index b48cfaee2a..2258fec219 100644 --- a/apps/openmw/mwrender/debugging.hpp +++ b/apps/openmw/mwrender/debugging.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "../mwworld/ptr.hpp" #include #include @@ -28,14 +29,36 @@ namespace MWRender { class Player; - class Debugging{ - OEngine::Physic::PhysicEngine* eng; + class Debugging + { + OEngine::Physic::PhysicEngine* mEngine; + Ogre::SceneManager* mSceneMgr; + const ESMS::ESMStore& mStore; + // Path grid stuff + bool pathgridEnabled; - public: - Debugging(OEngine::Physic::PhysicEngine* engine); - bool toggleRenderMode (int mode); - }; + void togglePathgrid(); + + typedef std::vector CellList; + + CellList mActiveCells; + + Ogre::SceneNode *mPathGridRoot; + Ogre::SceneNode *mInteriorPathgridNode; + + typedef std::map, Ogre::SceneNode *> ExteriorPathgridNodes; + ExteriorPathgridNodes mExteriorPathgridNodes; + + void togglePathgridForCell(MWWorld::Ptr::CellStore *store, bool enabled); + + public: + Debugging(const ESMS::ESMStore &store, Ogre::SceneManager *mSceneMgr, OEngine::Physic::PhysicEngine* engine); + bool toggleRenderMode (int mode); + + void cellAdded(MWWorld::Ptr::CellStore* store); + void cellRemoved(MWWorld::Ptr::CellStore* store); + }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7b58a80d76..94197108d9 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -20,10 +20,12 @@ using namespace Ogre; namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) -:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine) + :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0) { mRendering.createScene("PlayerCam", 55, 5); + mDebugging = new Debugging(environment.mWorld->getStore(), mRendering.getScene(), engine); + // Set default mipmap level (NB some APIs ignore this) TextureManager::getSingleton().setDefaultNumMipmaps(5); @@ -40,7 +42,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mMwRoot->pitch(Degree(-90)); mObjects.setMwRoot(mMwRoot); mActors.setMwRoot(mMwRoot); - + //used to obtain ingame information of ogre objects (which are faced or selected) mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray()); @@ -49,7 +51,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); cameraPitchNode->attachObject(mRendering.getCamera()); - + //mSkyManager = 0; mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera()); @@ -62,6 +64,7 @@ RenderingManager::~RenderingManager () //TODO: destroy mSun? delete mPlayer; delete mSkyManager; + delete mDebugging; } MWRender::SkyManager* RenderingManager::getSkyManager() @@ -88,11 +91,13 @@ OEngine::Render::Fader* RenderingManager::getFader() void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store){ mObjects.removeCell(store); mActors.removeCell(store); + mDebugging->cellRemoved(store); } void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store) { mObjects.buildStaticGeometry (*store); + mDebugging->cellAdded(store); } void RenderingManager::addObject (const MWWorld::Ptr& ptr){ @@ -133,9 +138,9 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve void RenderingManager::update (float duration){ mActors.update (duration); - + mSkyManager->update(duration); - + mRendering.update(duration); } @@ -166,7 +171,7 @@ void RenderingManager::skySetDate (int day, int month) int RenderingManager::skyGetMasserPhase() const { - + return mSkyManager->getMasserPhase(); } @@ -182,8 +187,8 @@ void RenderingManager::skySetMoonColour (bool red){ bool RenderingManager::toggleRenderMode(int mode) { - if (mode == MWWorld::World::Render_CollisionDebug) - return mDebugging.toggleRenderMode(mode); + if (mode != MWWorld::World::Render_Wireframe) + return mDebugging->toggleRenderMode(mode); else // if (mode == MWWorld::World::Render_Wireframe) { if (mRendering.getCamera()->getPolygonMode() == PM_SOLID) @@ -208,13 +213,13 @@ void RenderingManager::configureFog(ESMS::CellStore &mCell) } void RenderingManager::configureFog(const float density, const Ogre::ColourValue& colour) -{ +{ /// \todo make the viewing distance and fog start/end configurable float low = 3000 / density; float high = 6200 / density; - + mRendering.getScene()->setFog (FOG_LINEAR, colour, 0, low, high); - + mRendering.getCamera()->setFarClipDistance ( high ); mRendering.getViewport()->setBackgroundColour (colour); } @@ -310,10 +315,10 @@ void RenderingManager::sunDisable() void RenderingManager::setSunDirection(const Ogre::Vector3& direction) { - // direction * -1 (because 'direction' is camera to sun vector and not sun to camera), + // direction * -1 (because 'direction' is camera to sun vector and not sun to camera), // then convert from MW to ogre coordinates (swap y,z and make y negative) if (mSun) mSun->setDirection(Vector3(-direction.x, -direction.z, direction.y)); - + mSkyManager->setSunDirection(direction); } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d84ee43e00..9be3892727 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -66,7 +66,7 @@ class RenderingManager: private RenderingInterface { void toggleLight(); bool toggleRenderMode(int mode); - + OEngine::Render::Fader* getFader(); void removeCell (MWWorld::Ptr::CellStore *store); @@ -86,13 +86,13 @@ class RenderingManager: private RenderingInterface { void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store); void update (float duration); - + void setAmbientColour(const Ogre::ColourValue& colour); void setSunColour(const Ogre::ColourValue& colour); void setSunDirection(const Ogre::Vector3& direction); void sunEnable(); void sunDisable(); - + void setGlare(bool glare); void skyEnable (); void skyDisable (); @@ -102,13 +102,13 @@ class RenderingManager: private RenderingInterface { int skyGetSecundaPhase() const; void skySetMoonColour (bool red); void configureAmbient(ESMS::CellStore &mCell); - + /// configure fog according to cell void configureFog(ESMS::CellStore &mCell); - + /// configure fog manually void configureFog(const float density, const Ogre::ColourValue& colour); - + void playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number = 1); ///< Run animation for a MW-reference. Calls to this function for references that are currently not @@ -124,9 +124,9 @@ class RenderingManager: private RenderingInterface { private: void setAmbientMode(); - + SkyManager* mSkyManager; - + OEngine::Render::OgreRenderer &mRendering; MWRender::Objects mObjects; @@ -147,7 +147,7 @@ class RenderingManager: private RenderingInterface { OEngine::Physic::PhysicEngine* mPhysicsEngine; MWRender::Player *mPlayer; - MWRender::Debugging mDebugging; + MWRender::Debugging *mDebugging; }; } diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 36b8df70b9..425fa3727d 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -133,7 +133,7 @@ namespace MWScript static_cast (runtime.getContext()); bool enabled = - context.getWorld().toggleRenderMode (MWWorld::World::Render_Wireframe); + context.getWorld().toggleRenderMode (MWWorld::World::Render_Pathgrid); context.report (enabled ? "Path Grid rendering -> On" : "Path Grid Rendering -> Off"); diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index c4bcf84d81..4f5b6b6ec4 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -123,6 +123,8 @@ namespace ESMS CellRefList statics; CellRefList weapons; + ESM::Pathgrid *pathgrid; + void load (const ESMStore &store, ESMReader &esm) { if (mState!=State_Loaded) @@ -134,6 +136,8 @@ namespace ESMS loadRefs (store, esm); + pathgrid = store.pathgrids.search(*cell); + mState = State_Loaded; } } diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 4aacf2332b..da6e9b3d5f 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -428,14 +428,16 @@ namespace ESMS if (grid->data.x == 0 && grid->data.y == 0) { intGrids[grid->cell] = grid; + std::cout << "int grids size " << intGrids.size() << std::endl; } else { extGrids[std::make_pair(grid->data.x, grid->data.y)] = grid; + std::cout << "ext grids size " << extGrids.size() << std::endl; } } - Pathgrid *find(int cellX, int cellY, std::string cellName) const + Pathgrid *find(int cellX, int cellY, const std::string &cellName) const { Pathgrid *result = search(cellX, cellY, cellName); if (!result) @@ -445,8 +447,10 @@ namespace ESMS return result; } - Pathgrid *search(int cellX, int cellY, std::string cellName) const + Pathgrid *search(int cellX, int cellY, const std::string &cellName) const { + std::cout << "int grids size " << intGrids.size() << std::endl; + std::cout << "ext grids size " << extGrids.size() << std::endl; Pathgrid *result = NULL; if (cellX == 0 && cellY == 0) // possibly interior {