mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 09:15:38 +00:00
Start cell border debug drawing
This commit is contained in:
parent
36f4f0ef85
commit
db8aaa74d6
18 changed files with 226 additions and 21 deletions
|
@ -120,6 +120,7 @@ namespace MWBase
|
|||
|
||||
virtual bool toggleWater() = 0;
|
||||
virtual bool toggleWorld() = 0;
|
||||
virtual bool toggleBorders() = 0;
|
||||
|
||||
virtual void adjustSky() = 0;
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ namespace MWRender
|
|||
, mNightEyeFactor(0.f)
|
||||
, mFieldOfViewOverride(0.f)
|
||||
, mFieldOfViewOverridden(false)
|
||||
, mBorders(false)
|
||||
{
|
||||
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
||||
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
|
||||
|
@ -219,9 +220,10 @@ namespace MWRender
|
|||
Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
|
||||
|
||||
if (distantTerrain)
|
||||
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile, Mask_Debug));
|
||||
else
|
||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile, Mask_Debug));
|
||||
|
||||
mTerrain->setDefaultViewer(mViewer->getCamera());
|
||||
|
||||
mCamera.reset(new Camera(mViewer->getCamera()));
|
||||
|
@ -441,6 +443,13 @@ namespace MWRender
|
|||
{
|
||||
mSky->setEnabled(enabled);
|
||||
}
|
||||
|
||||
bool RenderingManager::toggleBorders()
|
||||
{
|
||||
mBorders = !mBorders;
|
||||
mTerrain->setBordersVisible(mBorders);
|
||||
return mBorders;
|
||||
}
|
||||
|
||||
bool RenderingManager::toggleRenderMode(RenderMode mode)
|
||||
{
|
||||
|
|
|
@ -205,6 +205,8 @@ namespace MWRender
|
|||
|
||||
LandManager* getLandManager() const;
|
||||
|
||||
bool toggleBorders();
|
||||
|
||||
private:
|
||||
void updateProjectionMatrix();
|
||||
void updateTextureFiltering();
|
||||
|
@ -257,6 +259,7 @@ namespace MWRender
|
|||
bool mFieldOfViewOverridden;
|
||||
float mFieldOfView;
|
||||
float mFirstPersonFieldOfView;
|
||||
bool mBorders;
|
||||
|
||||
void operator = (const RenderingManager&);
|
||||
RenderingManager(const RenderingManager&);
|
||||
|
|
|
@ -454,5 +454,6 @@ op 0x2000303: Fixme, explicit
|
|||
op 0x2000304: Show
|
||||
op 0x2000305: Show, explicit
|
||||
op 0x2000306: OnActivate, explicit
|
||||
op 0x2000307: ToggleBorders, tb
|
||||
|
||||
opcodes 0x2000307-0x3ffffff unused
|
||||
opcodes 0x2000308-0x3ffffff unused
|
||||
|
|
|
@ -254,6 +254,20 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpToggleBorders : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
bool enabled =
|
||||
MWBase::Environment::get().getWorld()->toggleBorders();
|
||||
|
||||
runtime.getContext().report (enabled ?
|
||||
"Border Rendering -> On" : "Border Rendering -> Off");
|
||||
}
|
||||
};
|
||||
|
||||
class OpTogglePathgrid : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
@ -1374,6 +1388,7 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeRemoveFromLevItem, new OpRemoveFromLevItem);
|
||||
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraph, new OpShowSceneGraph<ImplicitRef>);
|
||||
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleBorders, new OpToggleBorders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1919,6 +1919,11 @@ namespace MWWorld
|
|||
return mRendering->toggleRenderMode(MWRender::Render_Scene);
|
||||
}
|
||||
|
||||
bool World::toggleBorders()
|
||||
{
|
||||
return mRendering->toggleBorders();
|
||||
}
|
||||
|
||||
void World::PCDropped (const Ptr& item)
|
||||
{
|
||||
std::string script = item.getClass().getScript(item);
|
||||
|
|
|
@ -217,6 +217,7 @@ namespace MWWorld
|
|||
|
||||
bool toggleWater() override;
|
||||
bool toggleWorld() override;
|
||||
bool toggleBorders() override;
|
||||
|
||||
void adjustSky() override;
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ add_component_dir (translation
|
|||
)
|
||||
|
||||
add_component_dir (terrain
|
||||
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata
|
||||
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata cellborder
|
||||
)
|
||||
|
||||
add_component_dir (loadinglistener
|
||||
|
|
|
@ -318,6 +318,8 @@ namespace Compiler
|
|||
extensions.registerInstruction ("removefromlevcreature", "ccl", opcodeRemoveFromLevCreature);
|
||||
extensions.registerInstruction ("addtolevitem", "ccl", opcodeAddToLevItem);
|
||||
extensions.registerInstruction ("removefromlevitem", "ccl", opcodeRemoveFromLevItem);
|
||||
extensions.registerInstruction ("tb", "", opcodeToggleBorders);
|
||||
extensions.registerInstruction ("toggleborders", "", opcodeToggleBorders);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -295,6 +295,7 @@ namespace Compiler
|
|||
const int opcodeRemoveFromLevItem = 0x20002fe;
|
||||
const int opcodeShowSceneGraph = 0x2002f;
|
||||
const int opcodeShowSceneGraphExplicit = 0x20030;
|
||||
const int opcodeToggleBorders = 0x2000307;
|
||||
}
|
||||
|
||||
namespace Sky
|
||||
|
|
91
components/terrain/cellborder.cpp
Normal file
91
components/terrain/cellborder.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "cellborder.hpp"
|
||||
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Geode>
|
||||
|
||||
#include "world.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
CellBorder::CellBorder(Terrain::World *world, osg::Group *root):
|
||||
mWorld(world),
|
||||
mRoot(root),
|
||||
mBorderRoot(0)
|
||||
{
|
||||
}
|
||||
|
||||
void CellBorder::createCellBorderGeometry(int x, int y)
|
||||
{
|
||||
const int cellSize = 8192;
|
||||
const int borderSegments = 40;
|
||||
const float offset = 10.0;
|
||||
|
||||
osg::Vec3 cellCorner = osg::Vec3(x * cellSize,y * cellSize,0);
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
|
||||
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
|
||||
|
||||
normals->push_back(osg::Vec3(0.0f,-1.0f, 0.0f));
|
||||
|
||||
float borderStep = cellSize / ((float) borderSegments);
|
||||
|
||||
for (int i = 0; i <= 2 * borderSegments; ++i)
|
||||
{
|
||||
osg::Vec3f pos = i < borderSegments ?
|
||||
osg::Vec3(i * borderStep,0.0f,0.0f) :
|
||||
osg::Vec3(cellSize,(i - borderSegments) * borderStep,0.0f);
|
||||
|
||||
pos += cellCorner;
|
||||
pos += osg::Vec3f(0,0,mWorld->getHeightAt(pos) + offset);
|
||||
|
||||
vertices->push_back(pos);
|
||||
|
||||
osg::Vec4f col = i % 2 == 0 ?
|
||||
osg::Vec4f(0,0,0,1) :
|
||||
osg::Vec4f(1,1,0,1);
|
||||
|
||||
colors->push_back(col);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Geometry> border = new osg::Geometry;
|
||||
border->setVertexArray(vertices.get());
|
||||
border->setNormalArray(normals.get());
|
||||
border->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
border->setColorArray(colors.get());
|
||||
border->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
border->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP,0,vertices->size()));
|
||||
|
||||
osg::ref_ptr<osg::Geode> borderGeode = new osg::Geode;
|
||||
borderGeode->addDrawable(border.get());
|
||||
|
||||
osg::StateSet *stateSet = borderGeode->getOrCreateStateSet();
|
||||
|
||||
osg::PolygonMode* polygonmode = new osg::PolygonMode;
|
||||
polygonmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
||||
stateSet->setAttributeAndModes(polygonmode,osg::StateAttribute::ON);
|
||||
|
||||
mRoot->addChild(borderGeode);
|
||||
|
||||
mBorderRoot = borderGeode;
|
||||
|
||||
mCellBorderNodes[std::make_pair(x,y)] = borderGeode;
|
||||
}
|
||||
|
||||
void CellBorder::destroyCellBorderGeometry(int x, int y)
|
||||
{
|
||||
CellGrid::iterator it = mCellBorderNodes.find(std::make_pair(x,y));
|
||||
|
||||
if (it == mCellBorderNodes.end())
|
||||
return;
|
||||
|
||||
osg::ref_ptr<osg::Node> borderNode = it->second;
|
||||
mBorderRoot->removeChild(borderNode);
|
||||
|
||||
mCellBorderNodes.erase(it);
|
||||
}
|
||||
|
||||
}
|
36
components/terrain/cellborder.hpp
Normal file
36
components/terrain/cellborder.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef GAME_RENDER_CELLBORDER
|
||||
#define GAME_RENDER_CELLBORDER
|
||||
|
||||
#include <map>
|
||||
#include <osg/Group>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class World;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
/**
|
||||
* @Brief Handles the debug cell borders.
|
||||
*/
|
||||
class CellBorder
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > CellGrid;
|
||||
|
||||
CellBorder(Terrain::World *world, osg::Group *root);
|
||||
|
||||
void createCellBorderGeometry(int x, int y);
|
||||
void destroyCellBorderGeometry(int x, int y);
|
||||
|
||||
protected:
|
||||
Terrain::World *mWorld;
|
||||
osg::Group *mRoot;
|
||||
osg::Group *mBorderRoot;
|
||||
|
||||
CellGrid mCellBorderNodes;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -235,8 +235,8 @@ private:
|
|||
osg::ref_ptr<RootNode> mRootNode;
|
||||
};
|
||||
|
||||
QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resource::ResourceSystem *resourceSystem, Storage *storage, int nodeMask, int preCompileMask)
|
||||
: World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask)
|
||||
QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resource::ResourceSystem *resourceSystem, Storage *storage, int nodeMask, int preCompileMask, int borderMask)
|
||||
: World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask, borderMask)
|
||||
, mViewDataMap(new ViewDataMap)
|
||||
, mQuadTreeBuilt(false)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Terrain
|
|||
class QuadTreeWorld : public Terrain::World
|
||||
{
|
||||
public:
|
||||
QuadTreeWorld(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0);
|
||||
QuadTreeWorld(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0, int borderMask=0);
|
||||
~QuadTreeWorld();
|
||||
|
||||
void accept(osg::NodeVisitor& nv);
|
||||
|
|
|
@ -17,8 +17,8 @@ public:
|
|||
virtual void reset(unsigned int frame) {}
|
||||
};
|
||||
|
||||
TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask)
|
||||
: Terrain::World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask)
|
||||
TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask)
|
||||
: Terrain::World(parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask, borderMask)
|
||||
, mNumSplits(4)
|
||||
{
|
||||
}
|
||||
|
@ -75,6 +75,8 @@ void TerrainGrid::loadCell(int x, int y)
|
|||
if (!terrainNode)
|
||||
return; // no terrain defined
|
||||
|
||||
Terrain::World::loadCell(x,y);
|
||||
|
||||
mTerrainRoot->addChild(terrainNode);
|
||||
|
||||
mGrid[std::make_pair(x,y)] = terrainNode;
|
||||
|
@ -82,7 +84,9 @@ void TerrainGrid::loadCell(int x, int y)
|
|||
|
||||
void TerrainGrid::unloadCell(int x, int y)
|
||||
{
|
||||
Grid::iterator it = mGrid.find(std::make_pair(x,y));
|
||||
World::unloadCell(x,y);
|
||||
|
||||
MWRender::CellBorder::CellGrid::iterator it = mGrid.find(std::make_pair(x,y));
|
||||
if (it == mGrid.end())
|
||||
return;
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "world.hpp"
|
||||
|
||||
#include "cellborder.hpp"
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
|
@ -14,7 +16,7 @@ namespace Terrain
|
|||
class TerrainGrid : public Terrain::World
|
||||
{
|
||||
public:
|
||||
TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0);
|
||||
TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask=~0, int borderMask=0);
|
||||
~TerrainGrid();
|
||||
|
||||
virtual void cacheCell(View* view, int x, int y);
|
||||
|
@ -33,8 +35,7 @@ namespace Terrain
|
|||
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
|
||||
unsigned int mNumSplits;
|
||||
|
||||
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > Grid;
|
||||
Grid mGrid;
|
||||
MWRender::CellBorder::CellGrid mGrid;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
namespace Terrain
|
||||
{
|
||||
|
||||
World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask)
|
||||
World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask)
|
||||
: mStorage(storage)
|
||||
, mParent(parent)
|
||||
, mResourceSystem(resourceSystem)
|
||||
|
@ -28,6 +28,12 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
|
|||
|
||||
mTerrainRoot->setName("Terrain Root");
|
||||
|
||||
mBorderRoot = new osg::Switch;
|
||||
mBorderRoot->setName("Border Root");
|
||||
mBorderRoot->setNodeMask(borderMask);
|
||||
|
||||
mTerrainRoot->addChild(mBorderRoot);
|
||||
|
||||
osg::ref_ptr<osg::Camera> compositeCam = new osg::Camera;
|
||||
compositeCam->setRenderOrder(osg::Camera::PRE_RENDER, -1);
|
||||
compositeCam->setProjectionMatrix(osg::Matrix::identity());
|
||||
|
@ -39,7 +45,6 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
|
|||
|
||||
compileRoot->addChild(compositeCam);
|
||||
|
||||
|
||||
mCompositeMapRenderer = new CompositeMapRenderer;
|
||||
compositeCam->addChild(mCompositeMapRenderer);
|
||||
|
||||
|
@ -48,8 +53,30 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
|
|||
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
|
||||
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get(), mCompositeMapRenderer));
|
||||
|
||||
mCellBorder.reset(new MWRender::CellBorder(this,mTerrainRoot.get()));
|
||||
|
||||
mResourceSystem->addResourceManager(mChunkManager.get());
|
||||
mResourceSystem->addResourceManager(mTextureManager.get());
|
||||
|
||||
setBordersVisible(false);
|
||||
}
|
||||
|
||||
void World::setBordersVisible(bool visible)
|
||||
{
|
||||
if (visible)
|
||||
mBorderRoot->setAllChildrenOn();
|
||||
else
|
||||
mBorderRoot->setAllChildrenOff();
|
||||
}
|
||||
|
||||
void World::loadCell(int x, int y)
|
||||
{
|
||||
mCellBorder->createCellBorderGeometry(x,y);
|
||||
}
|
||||
|
||||
void World::unloadCell(int x, int y)
|
||||
{
|
||||
mCellBorder->destroyCellBorderGeometry(x,y);
|
||||
}
|
||||
|
||||
World::~World()
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
#include <osg/ref_ptr>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/Vec3f>
|
||||
#include <osg/Switch>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "defs.hpp"
|
||||
|
||||
#include "cellborder.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
|
@ -54,7 +57,7 @@ namespace Terrain
|
|||
/// @param storage Storage instance to get terrain data from (heights, normals, colors, textures..)
|
||||
/// @param nodeMask mask for the terrain root
|
||||
/// @param preCompileMask mask for pre compiling textures
|
||||
World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask);
|
||||
World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, int nodeMask, int preCompileMask, int borderMask);
|
||||
virtual ~World();
|
||||
|
||||
/// Apply the scene manager's texture filtering settings to all cached textures.
|
||||
|
@ -73,16 +76,16 @@ namespace Terrain
|
|||
|
||||
/// Load the cell into the scene graph.
|
||||
/// @note Not thread safe.
|
||||
/// @note May be ignored by derived implementations that don't organize the terrain into cells.
|
||||
virtual void loadCell(int x, int y) {}
|
||||
virtual void loadCell(int x, int y);
|
||||
|
||||
/// Remove the cell from the scene graph.
|
||||
/// @note Not thread safe.
|
||||
/// @note May be ignored by derived implementations that don't organize the terrain into cells.
|
||||
virtual void unloadCell(int x, int y) {}
|
||||
virtual void unloadCell(int x, int y);
|
||||
|
||||
virtual void enable(bool enabled) {}
|
||||
|
||||
void setBordersVisible(bool visible);
|
||||
|
||||
/// Create a View to use with preload feature. The caller is responsible for deleting the view.
|
||||
/// @note Thread safe.
|
||||
virtual View* createView() { return NULL; }
|
||||
|
@ -98,10 +101,14 @@ namespace Terrain
|
|||
Storage* getStorage() { return mStorage; }
|
||||
|
||||
protected:
|
||||
void createCellBorderGeometry(int x, int y);
|
||||
void destroyCellBorderGeometry(int x, int y);
|
||||
|
||||
Storage* mStorage;
|
||||
|
||||
osg::ref_ptr<osg::Group> mParent;
|
||||
osg::ref_ptr<osg::Group> mTerrainRoot;
|
||||
osg::ref_ptr<osg::Switch> mBorderRoot;
|
||||
|
||||
osg::ref_ptr<osg::Group> mCompositeMapCamera;
|
||||
osg::ref_ptr<CompositeMapRenderer> mCompositeMapRenderer;
|
||||
|
@ -110,8 +117,9 @@ namespace Terrain
|
|||
|
||||
std::unique_ptr<TextureManager> mTextureManager;
|
||||
std::unique_ptr<ChunkManager> mChunkManager;
|
||||
};
|
||||
|
||||
std::unique_ptr<MWRender::CellBorder> mCellBorder;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue