Merge remote-tracking branch 'aesylwinn/RenderPathgrid'

This commit is contained in:
Marc Zinnschlag 2016-05-08 10:15:12 +02:00
commit b4e341e1e2
13 changed files with 476 additions and 113 deletions

View file

@ -1,10 +1,14 @@
#include "cell.hpp" #include "cell.hpp"
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group> #include <osg/Group>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/esm/loadcell.hpp> #include <components/esm/loadcell.hpp>
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
#include <components/sceneutil/pathgridutil.hpp>
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
@ -64,6 +68,18 @@ bool CSVRender::Cell::addObjects (int start, int end)
return modified; return modified;
} }
void CSVRender::Cell::recreatePathgrid()
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
mPathgridGeode->removeDrawable(mPathgridGeometry);
mPathgridGeometry = SceneUtil::createPathgridGeometry(pathgrids.getRecord(pathgridIndex).get());
mPathgridGeode->addDrawable(mPathgridGeometry);
}
}
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id, CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
bool deleted) bool deleted)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0), : mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
@ -77,6 +93,17 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
mCellNode = new osg::Group; mCellNode = new osg::Group;
rootNode->addChild(mCellNode); rootNode->addChild(mCellNode);
osg::ref_ptr<osg::PositionAttitudeTransform> pathgridTransform = new osg::PositionAttitudeTransform();
pathgridTransform->setPosition(osg::Vec3f(mCoordinates.getX() * ESM::Land::REAL_SIZE,
mCoordinates.getY() * ESM::Land::REAL_SIZE, 0));
pathgridTransform->setNodeMask(Mask_Pathgrid);
mCellNode->addChild(pathgridTransform);
mPathgridGeode = new osg::Geode();
pathgridTransform->addChild(mPathgridGeode);
mPathgridGeometry = 0;
setCellMarker(); setCellMarker();
if (!mDeleted) if (!mDeleted)
@ -104,6 +131,8 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
mCellBorder->buildShape(esmLand); mCellBorder->buildShape(esmLand);
} }
} }
recreatePathgrid();
} }
} }
@ -254,6 +283,31 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
return addObjects (start, end); return addObjects (start, end);
} }
void CSVRender::Cell::pathgridAdded(const CSMWorld::Pathgrid& pathgrid)
{
recreatePathgrid();
}
void CSVRender::Cell::pathgridRemoved()
{
mPathgridGeode->removeDrawable(mPathgridGeometry);
}
void CSVRender::Cell::pathgridDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
recreatePathgrid();
}
void CSVRender::Cell::pathgridRowRemoved(const QModelIndex& parent, int start, int end)
{
recreatePathgrid();
}
void CSVRender::Cell::pathgridRowAdded(const QModelIndex& parent, int start, int end)
{
recreatePathgrid();
}
void CSVRender::Cell::setSelection (int elementMask, Selection mode) void CSVRender::Cell::setSelection (int elementMask, Selection mode)
{ {
if (elementMask & Mask_Reference) if (elementMask & Mask_Reference)

View file

@ -23,12 +23,15 @@ class QModelIndex;
namespace osg namespace osg
{ {
class Group; class Group;
class Geometry;
class Geode;
} }
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
class CellCoordinates; class CellCoordinates;
class Pathgrid;
} }
namespace CSVRender namespace CSVRender
@ -40,6 +43,8 @@ namespace CSVRender
CSMWorld::Data& mData; CSMWorld::Data& mData;
std::string mId; std::string mId;
osg::ref_ptr<osg::Group> mCellNode; osg::ref_ptr<osg::Group> mCellNode;
osg::ref_ptr<osg::Geode> mPathgridGeode;
osg::ref_ptr<osg::Geometry> mPathgridGeometry;
std::map<std::string, Object *> mObjects; std::map<std::string, Object *> mObjects;
std::auto_ptr<Terrain::TerrainGrid> mTerrain; std::auto_ptr<Terrain::TerrainGrid> mTerrain;
CSMWorld::CellCoordinates mCoordinates; CSMWorld::CellCoordinates mCoordinates;
@ -64,6 +69,8 @@ namespace CSVRender
/// \return Have any objects been added? /// \return Have any objects been added?
bool addObjects (int start, int end); bool addObjects (int start, int end);
void recreatePathgrid();
public: public:
enum Selection enum Selection
@ -103,6 +110,16 @@ namespace CSVRender
/// this cell? /// this cell?
bool referenceAdded (const QModelIndex& parent, int start, int end); bool referenceAdded (const QModelIndex& parent, int start, int end);
void pathgridAdded(const CSMWorld::Pathgrid& pathgrid);
void pathgridRemoved();
void pathgridDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
void pathgridRowRemoved(const QModelIndex& parent, int start, int end);
void pathgridRowAdded(const QModelIndex& parent, int start, int end);
void setSelection (int elementMask, Selection mode); void setSelection (int elementMask, Selection mode);
// Select everything that references the same ID as at least one of the elements // Select everything that references the same ID as at least one of the elements

View file

@ -275,6 +275,107 @@ void CSVRender::PagedWorldspaceWidget::referenceAdded (const QModelIndex& parent
flagAsModified(); flagAsModified();
} }
void CSVRender::PagedWorldspaceWidget::pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (topLeft.parent().isValid())
{
int row = topLeft.parent().row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
CSMWorld::CellCoordinates coords = CSMWorld::CellCoordinates(pathgrid.mData.mX, pathgrid.mData.mY);
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
if (searchResult != mCells.end())
{
searchResult->second->pathgridDataChanged(topLeft, bottomRight);
flagAsModified();
}
}
}
void CSVRender::PagedWorldspaceWidget::pathgridRemoved (const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (parent.isValid())
{
// Pathgrid data was modified
int row = parent.row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
CSMWorld::CellCoordinates coords = CSMWorld::CellCoordinates(pathgrid.mData.mX, pathgrid.mData.mY);
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
if (searchResult != mCells.end())
{
searchResult->second->pathgridRowRemoved(parent, start, end);
flagAsModified();
}
}
}
void CSVRender::PagedWorldspaceWidget::pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid())
{
// Pathgrid going to be deleted
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
CSMWorld::CellCoordinates coords = CSMWorld::CellCoordinates(pathgrid.mData.mX, pathgrid.mData.mY);
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
if (searchResult != mCells.end())
{
searchResult->second->pathgridRemoved();
flagAsModified();
}
}
}
}
void CSVRender::PagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid())
{
// Pathgrid added theoretically, unable to test until it is possible to add pathgrids
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
CSMWorld::CellCoordinates coords = CSMWorld::CellCoordinates(pathgrid.mData.mX, pathgrid.mData.mY);
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
if (searchResult != mCells.end())
{
searchResult->second->pathgridAdded(pathgrid);
flagAsModified();
}
}
}
else
{
// Pathgrid data was modified
int row = parent.row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
CSMWorld::CellCoordinates coords = CSMWorld::CellCoordinates(pathgrid.mData.mX, pathgrid.mData.mY);
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
if (searchResult != mCells.end())
{
searchResult->second->pathgridRowAdded(parent, start, end);
flagAsModified();
}
}
}
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction() std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
{ {
osg::Vec3d eye, center, up; osg::Vec3d eye, center, up;

View file

@ -52,6 +52,14 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end); virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
virtual void pathgridRemoved (const QModelIndex& parent, int start, int end);
virtual void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end);
virtual void pathgridAdded (const QModelIndex& parent, int start, int end);
virtual std::string getStartupInstruction(); virtual std::string getStartupInstruction();
/// \note Does not update the view or any cell marker /// \note Does not update the view or any cell marker

View file

@ -32,7 +32,7 @@ void CSVRender::UnpagedWorldspaceWidget::update()
} }
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent) CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
: WorldspaceWidget (document, parent), mCellId (cellId) : WorldspaceWidget (document, parent), mDocument(document), mCellId (cellId)
{ {
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> ( mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
@ -197,6 +197,90 @@ void CSVRender::UnpagedWorldspaceWidget::referenceAdded (const QModelIndex& pare
flagAsModified(); flagAsModified();
} }
void CSVRender::UnpagedWorldspaceWidget::pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (topLeft.parent().isValid())
{
int row = topLeft.parent().row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
{
mCell->pathgridDataChanged(topLeft, bottomRight);
flagAsModified();
}
}
}
void CSVRender::UnpagedWorldspaceWidget::pathgridRemoved (const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (parent.isValid()){
// Pathgrid data was modified
int row = parent.row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
{
mCell->pathgridRowRemoved(parent, start, end);
flagAsModified();
}
}
}
void CSVRender::UnpagedWorldspaceWidget::pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid())
{
// Pathgrid going to be deleted
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
{
mCell->pathgridRemoved();
flagAsModified();
}
}
}
}
void CSVRender::UnpagedWorldspaceWidget::pathgridAdded (const QModelIndex& parent, int start, int end)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mDocument.getData().getPathgrids();
if (!parent.isValid())
{
// Pathgrid added theoretically, unable to test until it is possible to add pathgrids
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
{
mCell->pathgridAdded(pathgrid);
flagAsModified();
}
}
}
else
{
// Pathgrid data was modified
int row = parent.row();
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
{
mCell->pathgridRowAdded(parent, start, end);
flagAsModified();
}
}
}
void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons ( void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle2 *tool) CSVWidget::SceneToolToggle2 *tool)
{ {

View file

@ -25,6 +25,7 @@ namespace CSVRender
{ {
Q_OBJECT Q_OBJECT
CSMDoc::Document& mDocument;
std::string mCellId; std::string mCellId;
CSMWorld::IdTable *mCellsModel; CSMWorld::IdTable *mCellsModel;
CSMWorld::IdTable *mReferenceablesModel; CSMWorld::IdTable *mReferenceablesModel;
@ -83,6 +84,15 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end); virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
virtual void pathgridRemoved (const QModelIndex& parent, int start, int end);
virtual void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end);
virtual void pathgridAdded (const QModelIndex& parent, int start, int end);
virtual std::string getStartupInstruction(); virtual std::string getStartupInstruction();
protected: protected:

View file

@ -59,6 +59,17 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)), connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (referenceAdded (const QModelIndex&, int, int))); this, SLOT (referenceAdded (const QModelIndex&, int, int)));
QAbstractItemModel *pathgrids = document.getData().getTableModel (CSMWorld::UniversalId::Type_Pathgrids);
connect (pathgrids, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (pathgridDataChanged (const QModelIndex&, const QModelIndex&)));
connect (pathgrids, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (pathgridRemoved (const QModelIndex&, int, int)));
connect (pathgrids, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (pathgridAboutToBeRemoved (const QModelIndex&, int, int)));
connect (pathgrids, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (pathgridAdded (const QModelIndex&, int, int)));
QAbstractItemModel *debugProfiles = QAbstractItemModel *debugProfiles =
document.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles); document.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles);

View file

@ -228,6 +228,15 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0; virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0;
virtual void pathgridDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) = 0;
virtual void pathgridRemoved (const QModelIndex& parent, int start, int end) = 0;
virtual void pathgridAboutToBeRemoved (const QModelIndex& parent, int start, int end) = 0;
virtual void pathgridAdded (const QModelIndex& parent, int start, int end) = 0;
virtual void runRequest (const std::string& profile); virtual void runRequest (const std::string& profile);
void debugProfileDataChanged (const QModelIndex& topLeft, void debugProfileDataChanged (const QModelIndex& topLeft,

View file

@ -8,6 +8,7 @@
#include <components/esm/loadstat.hpp> #include <components/esm/loadstat.hpp>
#include <components/esm/loadpgrd.hpp> #include <components/esm/loadpgrd.hpp>
#include <components/sceneutil/pathgridutil.hpp>
#include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone #include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -23,107 +24,6 @@
namespace MWRender namespace MWRender
{ {
static const int POINT_MESH_BASE = 35;
osg::ref_ptr<osg::Geometry> Pathgrid::createPathgridLines(const ESM::Pathgrid *pathgrid)
{
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
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];
osg::Vec3f direction = MWMechanics::PathFinder::MakeOsgVec3(p2) - MWMechanics::PathFinder::MakeOsgVec3(p1);
osg::Vec3f lineDisplacement = (direction^osg::Vec3f(0,0,1));
lineDisplacement.normalize();
lineDisplacement = lineDisplacement * POINT_MESH_BASE +
osg::Vec3f(0, 0, 10); // move lines up a little, so they will be less covered by meshes/landscape
vertices->push_back(MWMechanics::PathFinder::MakeOsgVec3(p1) + lineDisplacement);
vertices->push_back(MWMechanics::PathFinder::MakeOsgVec3(p2) + lineDisplacement);
}
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertices->size()));
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.f, 1.f, 0.f, 1.f));
geom->setColorArray(colors, osg::Array::BIND_OVERALL);
return geom;
}
osg::ref_ptr<osg::Geometry> Pathgrid::createPathgridPoints(const ESM::Pathgrid *pathgrid)
{
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
const float height = POINT_MESH_BASE * sqrtf(2);
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
osg::ref_ptr<osg::UShortArray> indices = new osg::UShortArray;
bool first = true;
unsigned short startIndex = 0;
for(ESM::Pathgrid::PointList::const_iterator it = pathgrid->mPoints.begin();
it != pathgrid->mPoints.end();
++it, startIndex += 6)
{
osg::Vec3f pointPos(MWMechanics::PathFinder::MakeOsgVec3(*it));
if (!first)
{
// degenerate triangle from previous octahedron
indices->push_back(startIndex - 4); // 2nd point of previous octahedron
indices->push_back(startIndex); // start point of current octahedron
}
float pointMeshBase = static_cast<float>(POINT_MESH_BASE);
vertices->push_back(pointPos + osg::Vec3f(0, 0, height)); // 0
vertices->push_back(pointPos + osg::Vec3f(-pointMeshBase, -pointMeshBase, 0)); // 1
vertices->push_back(pointPos + osg::Vec3f(pointMeshBase, -pointMeshBase, 0)); // 2
vertices->push_back(pointPos + osg::Vec3f(pointMeshBase, pointMeshBase, 0)); // 3
vertices->push_back(pointPos + osg::Vec3f(-pointMeshBase, pointMeshBase, 0)); // 4
vertices->push_back(pointPos + osg::Vec3f(0, 0, -height)); // 5
indices->push_back(startIndex + 0);
indices->push_back(startIndex + 1);
indices->push_back(startIndex + 2);
indices->push_back(startIndex + 5);
indices->push_back(startIndex + 3);
indices->push_back(startIndex + 4);
// degenerates
indices->push_back(startIndex + 4);
indices->push_back(startIndex + 5);
indices->push_back(startIndex + 5);
// end degenerates
indices->push_back(startIndex + 1);
indices->push_back(startIndex + 4);
indices->push_back(startIndex + 0);
indices->push_back(startIndex + 3);
indices->push_back(startIndex + 2);
first = false;
}
geom->setVertexArray(vertices);
geom->addPrimitiveSet(new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLE_STRIP, indices->size(), &(*indices)[0]));
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.f, 0.f, 0.f, 1.f));
geom->setColorArray(colors, osg::Array::BIND_OVERALL);
return geom;
}
Pathgrid::Pathgrid(osg::ref_ptr<osg::Group> root) Pathgrid::Pathgrid(osg::ref_ptr<osg::Group> root)
: mPathgridEnabled(false) : mPathgridEnabled(false)
, mRootNode(root) , mRootNode(root)
@ -212,12 +112,9 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store)
osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform; osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform;
cellPathGrid->setPosition(cellPathGridPos); cellPathGrid->setPosition(cellPathGridPos);
osg::ref_ptr<osg::Geometry> lines = createPathgridLines(pathgrid); osg::ref_ptr<osg::Geometry> geometry = SceneUtil::createPathgridGeometry(*pathgrid);
osg::ref_ptr<osg::Geometry> points = createPathgridPoints(pathgrid); cellPathGrid->addChild(geometry);
cellPathGrid->addChild(lines);
cellPathGrid->addChild(points);
mPathGridRoot->addChild(cellPathGrid); mPathGridRoot->addChild(cellPathGrid);

View file

@ -48,9 +48,6 @@ namespace MWRender
void enableCellPathgrid(const MWWorld::CellStore *store); void enableCellPathgrid(const MWWorld::CellStore *store);
void disableCellPathgrid(const MWWorld::CellStore *store); void disableCellPathgrid(const MWWorld::CellStore *store);
// path grid meshes
osg::ref_ptr<osg::Geometry> createPathgridLines(const ESM::Pathgrid *pathgrid);
osg::ref_ptr<osg::Geometry> createPathgridPoints(const ESM::Pathgrid *pathgrid);
public: public:
Pathgrid(osg::ref_ptr<osg::Group> root); Pathgrid(osg::ref_ptr<osg::Group> root);
~Pathgrid(); ~Pathgrid();

View file

@ -50,7 +50,7 @@ add_component_dir (shader
add_component_dir (sceneutil add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue unrefqueue lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil
) )
add_component_dir (nif add_component_dir (nif

View file

@ -0,0 +1,158 @@
#include "pathgridutil.hpp"
#include <osg/Geometry>
#include <components/esm/loadland.hpp>
#include <components/esm/loadpgrd.hpp>
namespace SceneUtil
{
const unsigned short DiamondVertexCount = 6;
const unsigned short DiamondIndexCount = 24;
const unsigned short DiamondConnectorVertexCount = 4;
const unsigned short DiamondTotalVertexCount = DiamondVertexCount + DiamondConnectorVertexCount;
const float DiamondHalfHeight = 40.f;
const float DiamondHalfWidth = 16.f;
const osg::Vec3f DiamondPoints[DiamondVertexCount] =
{
osg::Vec3f( 0.f, 0.f, DiamondHalfHeight * 2.f),
osg::Vec3f(-DiamondHalfWidth, -DiamondHalfWidth, DiamondHalfHeight),
osg::Vec3f(-DiamondHalfWidth, DiamondHalfWidth, DiamondHalfHeight),
osg::Vec3f( DiamondHalfWidth, -DiamondHalfWidth, DiamondHalfHeight),
osg::Vec3f( DiamondHalfWidth, DiamondHalfWidth, DiamondHalfHeight),
osg::Vec3f( 0.f, 0.f, 0.f)
};
const unsigned short DiamondIndices[DiamondIndexCount] =
{
0, 2, 1,
0, 1, 3,
0, 3, 4,
0, 4, 2,
5, 1, 2,
5, 3, 1,
5, 4, 3,
5, 2, 4
};
const unsigned short DiamondConnectorVertices[DiamondConnectorVertexCount] =
{
1, 2, 3, 4
};
const osg::Vec4f DiamondColors[DiamondVertexCount] =
{
osg::Vec4f(0.f, 0.f, 1.f, 1.f),
osg::Vec4f(0.f, .05f, .95f, 1.f),
osg::Vec4f(0.f, .1f, .95f, 1.f),
osg::Vec4f(0.f, .15f, .95f, 1.f),
osg::Vec4f(0.f, .2f, .95f, 1.f),
osg::Vec4f(0.f, .25f, 9.f, 1.f)
};
const osg::Vec4f DiamondEdgeColor = osg::Vec4f(0.5f, 1.f, 1.f, 1.f);
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid)
{
const unsigned short PointCount = static_cast<unsigned short>(pathgrid.mPoints.size());
const size_t EdgeCount = pathgrid.mEdges.size();
const unsigned short VertexCount = PointCount * DiamondTotalVertexCount;
const unsigned short ColorCount = VertexCount;
const size_t PointIndexCount = PointCount * DiamondIndexCount;
const size_t EdgeIndexCount = EdgeCount * 2;
osg::ref_ptr<osg::Geometry> gridGeometry = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(VertexCount);
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(ColorCount);
osg::ref_ptr<osg::DrawElementsUShort> pointIndices =
new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, PointIndexCount);
osg::ref_ptr<osg::DrawElementsUShort> lineIndices =
new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, EdgeIndexCount);
// Add each point/node
for (unsigned short pointIndex = 0; pointIndex < PointCount; ++pointIndex)
{
const ESM::Pathgrid::Point& point = pathgrid.mPoints[pointIndex];
osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ);
unsigned short vertexOffset = pointIndex * DiamondTotalVertexCount;
unsigned short indexOffset = pointIndex * DiamondIndexCount;
// Point
for (unsigned short i = 0; i < DiamondVertexCount; ++i)
{
(*vertices)[vertexOffset + i] = position + DiamondPoints[i];
(*colors)[vertexOffset + i] = DiamondColors[i];
}
for (unsigned short i = 0; i < DiamondIndexCount; ++i)
{
pointIndices->setElement(indexOffset + i, vertexOffset + DiamondIndices[i]);
}
// Connectors
vertexOffset += DiamondVertexCount;
for (unsigned short i = 0; i < DiamondConnectorVertexCount; ++i)
{
(*vertices)[vertexOffset + i] = position + DiamondPoints[DiamondConnectorVertices[i]];
(*colors)[vertexOffset + i] = DiamondEdgeColor;
}
}
// Add edges
unsigned short lineIndex = 0;
for (ESM::Pathgrid::EdgeList::const_iterator edge = pathgrid.mEdges.begin();
edge != pathgrid.mEdges.end(); ++edge)
{
if (edge->mV0 == edge->mV1 || edge->mV0 < 0 || edge->mV0 >= PointCount ||
edge->mV1 < 0 || edge->mV1 >= PointCount)
continue;
const ESM::Pathgrid::Point& from = pathgrid.mPoints[edge->mV0];
const ESM::Pathgrid::Point& to = pathgrid.mPoints[edge->mV1];
osg::Vec3f fromPos = osg::Vec3f(from.mX, from.mY, from.mZ);
osg::Vec3f toPos = osg::Vec3f(to.mX, to.mY, to.mZ);
osg::Vec3f dir = toPos - fromPos;
dir.normalize();
osg::Quat rot = osg::Quat(-osg::PI / 2, osg::Vec3(0, 0, 1));
dir = rot * dir;
unsigned short diamondIndex = 0;
if (dir.isNaN())
diamondIndex = 0;
else if (dir.y() >= 0 && dir.x() > 0)
diamondIndex = 3;
else if (dir.x() <= 0 && dir.y() > 0)
diamondIndex = 1;
else if (dir.y() <= 0 && dir.x() < 0)
diamondIndex = 0;
else if (dir.x() >= 0 && dir.y() < 0)
diamondIndex = 2;
unsigned short fromIndex = static_cast<unsigned short>(edge->mV0);
unsigned short toIndex = static_cast<unsigned short>(edge->mV1);
lineIndices->setElement(lineIndex++, fromIndex * DiamondTotalVertexCount + DiamondVertexCount + diamondIndex);
lineIndices->setElement(lineIndex++, toIndex * DiamondTotalVertexCount + DiamondVertexCount + diamondIndex);
}
lineIndices->resize(lineIndex);
gridGeometry->setVertexArray(vertices);
gridGeometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
gridGeometry->addPrimitiveSet(pointIndices);
gridGeometry->addPrimitiveSet(lineIndices);
gridGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
return gridGeometry;
}
}

View file

@ -0,0 +1,17 @@
#ifndef OPENMW_COMPONENTS_PATHGRIDUTIL_H
#define OPENMW_COMPONENTS_PATHGRIDUTIL_H
#include <osg/ref_ptr>
#include <osg/Geometry>
namespace ESM
{
class Pathgrid;
}
namespace SceneUtil
{
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid);
}
#endif