mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 21:26:48 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			296 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "debugging.hpp"
 | |
| 
 | |
| #include <cassert>
 | |
| 
 | |
| #include <OgreNode.h>
 | |
| #include <OgreSceneManager.h>
 | |
| #include <OgreMaterial.h>
 | |
| #include <OgreMaterialManager.h>
 | |
| #include <OgreManualObject.h>
 | |
| 
 | |
| #include <openengine/bullet/physic.hpp>
 | |
| 
 | |
| #include <components/esm/loadstat.hpp>
 | |
| #include <components/esm/loadpgrd.hpp>
 | |
| 
 | |
| #include "../mwworld/esmstore.hpp"
 | |
| 
 | |
| #include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone
 | |
| #include "../mwbase/environment.hpp"
 | |
| 
 | |
| #include "../mwworld/ptr.hpp"
 | |
| 
 | |
| #include "renderconst.hpp"
 | |
| 
 | |
| using namespace Ogre;
 | |
| 
 | |
| namespace MWRender
 | |
| {
 | |
| 
 | |
| static const std::string PATHGRID_POINT_MATERIAL = "pathgridPointMaterial";
 | |
| static const std::string PATHGRID_LINE_MATERIAL = "pathgridLineMaterial";
 | |
| static const std::string DEBUGGING_GROUP = "debugging";
 | |
| static const int POINT_MESH_BASE = 35;
 | |
| 
 | |
| void Debugging::createGridMaterials()
 | |
| {
 | |
|     if (mGridMatsCreated) return;
 | |
| 
 | |
|     if (MaterialManager::getSingleton().getByName(PATHGRID_LINE_MATERIAL, DEBUGGING_GROUP).isNull())
 | |
|     {
 | |
|         MaterialPtr lineMatPtr = MaterialManager::getSingleton().create(PATHGRID_LINE_MATERIAL, DEBUGGING_GROUP);
 | |
|         lineMatPtr->setReceiveShadows(false);
 | |
|         lineMatPtr->getTechnique(0)->setLightingEnabled(true);
 | |
|         lineMatPtr->getTechnique(0)->getPass(0)->setDiffuse(1,1,0,0);
 | |
|         lineMatPtr->getTechnique(0)->getPass(0)->setAmbient(1,1,0);
 | |
|         lineMatPtr->getTechnique(0)->getPass(0)->setSelfIllumination(1,1,0);
 | |
|     }
 | |
| 
 | |
|     if (MaterialManager::getSingleton().getByName(PATHGRID_POINT_MATERIAL, DEBUGGING_GROUP).isNull())
 | |
|     {
 | |
|         MaterialPtr pointMatPtr = MaterialManager::getSingleton().create(PATHGRID_POINT_MATERIAL, DEBUGGING_GROUP);
 | |
|         pointMatPtr->setReceiveShadows(false);
 | |
|         pointMatPtr->getTechnique(0)->setLightingEnabled(true);
 | |
|         pointMatPtr->getTechnique(0)->getPass(0)->setDiffuse(1,0,0,0);
 | |
|         pointMatPtr->getTechnique(0)->getPass(0)->setAmbient(1,0,0);
 | |
|         pointMatPtr->getTechnique(0)->getPass(0)->setSelfIllumination(1,0,0);
 | |
|     }
 | |
|     mGridMatsCreated = true;
 | |
| }
 | |
| 
 | |
| void Debugging::destroyGridMaterials()
 | |
| {
 | |
|     if (mGridMatsCreated)
 | |
|     {
 | |
|         MaterialManager::getSingleton().remove(PATHGRID_POINT_MATERIAL);
 | |
|         MaterialManager::getSingleton().remove(PATHGRID_LINE_MATERIAL);
 | |
|         mGridMatsCreated = false;
 | |
|     }
 | |
| }
 | |
| 
 | |
| ManualObject *Debugging::createPathgridLines(const ESM::Pathgrid *pathgrid)
 | |
| {
 | |
|     ManualObject *result = mSceneMgr->createManualObject();
 | |
| 
 | |
|     result->begin(PATHGRID_LINE_MATERIAL, RenderOperation::OT_LINE_LIST);
 | |
|     for(ESM::Pathgrid::EdgeList::const_iterator it = pathgrid->mEdges.begin();
 | |
|         it != pathgrid->mEdges.end();
 | |
|         ++it)
 | |
|     {
 | |
|         const ESM::Pathgrid::Edge &edge = *it;
 | |
|         const ESM::Pathgrid::Point &p1 = pathgrid->mPoints[edge.mV0], &p2 = pathgrid->mPoints[edge.mV1];
 | |
|         Vector3 direction = (Vector3(p2.mX, p2.mY, p2.mZ) - Vector3(p1.mX, p1.mY, p1.mZ));
 | |
|         Vector3 lineDisplacement = direction.crossProduct(Vector3::UNIT_Z).normalisedCopy();
 | |
|         lineDisplacement = lineDisplacement * POINT_MESH_BASE +
 | |
|                                 Vector3(0, 0, 10); // move lines up a little, so they will be less covered by meshes/landscape
 | |
|         result->position(Vector3(p1.mX, p1.mY, p1.mZ) + lineDisplacement);
 | |
|         result->position(Vector3(p2.mX, p2.mY, p2.mZ) + lineDisplacement);
 | |
|     }
 | |
|     result->end();
 | |
| 
 | |
|     result->setVisibilityFlags (RV_Debug);
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid)
 | |
| {
 | |
|     ManualObject *result = mSceneMgr->createManualObject();
 | |
|     const float height = POINT_MESH_BASE * sqrtf(2);
 | |
| 
 | |
|     result->begin(PATHGRID_POINT_MATERIAL, RenderOperation::OT_TRIANGLE_STRIP);
 | |
| 
 | |
|     bool first = true;
 | |
|     uint32 startIndex = 0;
 | |
|     for(ESM::Pathgrid::PointList::const_iterator it = pathgrid->mPoints.begin();
 | |
|         it != pathgrid->mPoints.end();
 | |
|         it++, startIndex += 6)
 | |
|     {
 | |
|         Vector3 pointPos(it->mX, it->mY, it->mZ);
 | |
| 
 | |
|         if (!first)
 | |
|         {
 | |
|             // degenerate triangle from previous octahedron
 | |
|             result->index(startIndex - 4); // 2nd point of previous octahedron
 | |
|             result->index(startIndex); // start point of current octahedron
 | |
|         }
 | |
| 
 | |
|         result->position(pointPos + Vector3(0, 0, height)); // 0
 | |
|         result->position(pointPos + Vector3(-POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 1
 | |
|         result->position(pointPos + Vector3(POINT_MESH_BASE, -POINT_MESH_BASE, 0)); // 2
 | |
|         result->position(pointPos + Vector3(POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 3
 | |
|         result->position(pointPos + Vector3(-POINT_MESH_BASE, POINT_MESH_BASE, 0)); // 4
 | |
|         result->position(pointPos + Vector3(0, 0, -height)); // 5
 | |
| 
 | |
|         result->index(startIndex + 0);
 | |
|         result->index(startIndex + 1);
 | |
|         result->index(startIndex + 2);
 | |
|         result->index(startIndex + 5);
 | |
|         result->index(startIndex + 3);
 | |
|         result->index(startIndex + 4);
 | |
|         // degenerates
 | |
|         result->index(startIndex + 4);
 | |
|         result->index(startIndex + 5);
 | |
|         result->index(startIndex + 5);
 | |
|         // end degenerates
 | |
|         result->index(startIndex + 1);
 | |
|         result->index(startIndex + 4);
 | |
|         result->index(startIndex + 0);
 | |
|         result->index(startIndex + 3);
 | |
|         result->index(startIndex + 2);
 | |
| 
 | |
|         first = false;
 | |
|     }
 | |
| 
 | |
|     result->end();
 | |
| 
 | |
|     result->setVisibilityFlags (RV_Debug);
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| Debugging::Debugging(SceneNode *root, OEngine::Physic::PhysicEngine *engine) :
 | |
|     mRootNode(root), mEngine(engine),
 | |
|     mSceneMgr(root->getCreator()),
 | |
|     mPathgridEnabled(false),
 | |
|     mInteriorPathgridNode(NULL), mPathGridRoot(NULL),
 | |
|     mGridMatsCreated(false)
 | |
| {
 | |
|     ResourceGroupManager::getSingleton().createResourceGroup(DEBUGGING_GROUP);
 | |
| }
 | |
| 
 | |
| Debugging::~Debugging()
 | |
| {
 | |
|     if (mPathgridEnabled)
 | |
|     {
 | |
|         togglePathgrid();
 | |
|     }
 | |
| 
 | |
|     ResourceGroupManager::getSingleton().destroyResourceGroup(DEBUGGING_GROUP);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool Debugging::toggleRenderMode (int mode){
 | |
|     switch (mode)
 | |
|     {
 | |
|         case MWBase::World::Render_CollisionDebug:
 | |
| 
 | |
|             return mEngine->toggleDebugRendering();
 | |
| 
 | |
|         case MWBase::World::Render_Pathgrid:
 | |
|             togglePathgrid();
 | |
|             return mPathgridEnabled;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| void Debugging::cellAdded(MWWorld::Ptr::CellStore *store)
 | |
| {
 | |
|     mActiveCells.push_back(store);
 | |
|     if (mPathgridEnabled)
 | |
|         enableCellPathgrid(store);
 | |
| }
 | |
| 
 | |
| void Debugging::cellRemoved(MWWorld::Ptr::CellStore *store)
 | |
| {
 | |
|     mActiveCells.erase(std::remove(mActiveCells.begin(), mActiveCells.end(), store), mActiveCells.end());
 | |
|     if (mPathgridEnabled)
 | |
|         disableCellPathgrid(store);
 | |
| }
 | |
| 
 | |
| void Debugging::togglePathgrid()
 | |
| {
 | |
|     mPathgridEnabled = !mPathgridEnabled;
 | |
|     if (mPathgridEnabled)
 | |
|     {
 | |
|         createGridMaterials();
 | |
| 
 | |
|         // add path grid meshes to already loaded cells
 | |
|         mPathGridRoot = mRootNode->createChildSceneNode();
 | |
|         for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it)
 | |
|         {
 | |
|             enableCellPathgrid(*it);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         // remove path grid meshes from already loaded cells
 | |
|         for(CellList::iterator it = mActiveCells.begin(); it != mActiveCells.end(); ++it)
 | |
|         {
 | |
|             disableCellPathgrid(*it);
 | |
|         }
 | |
|         mPathGridRoot->removeAndDestroyAllChildren();
 | |
|         mSceneMgr->destroySceneNode(mPathGridRoot);
 | |
|         mPathGridRoot = NULL;
 | |
|         destroyGridMaterials();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Debugging::enableCellPathgrid(MWWorld::Ptr::CellStore *store)
 | |
| {
 | |
|     const ESM::Pathgrid *pathgrid =
 | |
|         MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*store->mCell);
 | |
|     if (!pathgrid) return;
 | |
| 
 | |
|     Vector3 cellPathGridPos(0, 0, 0);
 | |
|     if (store->mCell->isExterior())
 | |
|     {
 | |
|         cellPathGridPos.x = store->mCell->mData.mX * ESM::Land::REAL_SIZE;
 | |
|         cellPathGridPos.y = store->mCell->mData.mY * ESM::Land::REAL_SIZE;
 | |
|     }
 | |
|     SceneNode *cellPathGrid = mPathGridRoot->createChildSceneNode(cellPathGridPos);
 | |
|     cellPathGrid->attachObject(createPathgridLines(pathgrid));
 | |
|     cellPathGrid->attachObject(createPathgridPoints(pathgrid));
 | |
| 
 | |
|     if (store->mCell->isExterior())
 | |
|     {
 | |
|         mExteriorPathgridNodes[std::make_pair(store->mCell->getGridX(), store->mCell->getGridY())] = cellPathGrid;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         assert(mInteriorPathgridNode == NULL);
 | |
|         mInteriorPathgridNode = cellPathGrid;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Debugging::disableCellPathgrid(MWWorld::Ptr::CellStore *store)
 | |
| {
 | |
|     if (store->mCell->isExterior())
 | |
|     {
 | |
|         ExteriorPathgridNodes::iterator it =
 | |
|                 mExteriorPathgridNodes.find(std::make_pair(store->mCell->getGridX(), store->mCell->getGridY()));
 | |
|         if (it != mExteriorPathgridNodes.end())
 | |
|         {
 | |
|             destroyCellPathgridNode(it->second);
 | |
|             mExteriorPathgridNodes.erase(it);
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if (mInteriorPathgridNode)
 | |
|         {
 | |
|             destroyCellPathgridNode(mInteriorPathgridNode);
 | |
|             mInteriorPathgridNode = NULL;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Debugging::destroyCellPathgridNode(SceneNode *node)
 | |
| {
 | |
|     mPathGridRoot->removeChild(node);
 | |
|     destroyAttachedObjects(node);
 | |
|     mSceneMgr->destroySceneNode(node);
 | |
| }
 | |
| 
 | |
| void Debugging::destroyAttachedObjects(SceneNode *node)
 | |
| {
 | |
|     SceneNode::ObjectIterator objIt = node->getAttachedObjectIterator();
 | |
|     while (objIt.hasMoreElements())
 | |
|     {
 | |
|         MovableObject *mesh = static_cast<MovableObject *>(objIt.getNext());
 | |
|         mSceneMgr->destroyMovableObject(mesh);
 | |
|     }
 | |
| }
 | |
| 
 | |
| }
 |