Merge remote-tracking branch 'aesylwinn/RenderPathgrid'

pull/1/head
Marc Zinnschlag 9 years ago
commit b4e341e1e2

@ -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)

@ -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

@ -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;

@ -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

@ -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)
{ {

@ -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:

@ -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);

@ -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,

@ -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(lines); cellPathGrid->addChild(geometry);
cellPathGrid->addChild(points);
mPathGridRoot->addChild(cellPathGrid); mPathGridRoot->addChild(cellPathGrid);

@ -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();

@ -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

@ -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;
}
}

@ -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
Loading…
Cancel
Save