Merge remote-tracking branch 'aesylwinn/RenderPathgrid'

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

@ -1,10 +1,14 @@
#include "cell.hpp"
#include <osg/PositionAttitudeTransform>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <components/misc/stringops.hpp>
#include <components/esm/loadcell.hpp>
#include <components/esm/loadland.hpp>
#include <components/sceneutil/pathgridutil.hpp>
#include "../../model/world/idtable.hpp"
#include "../../model/world/columns.hpp"
@ -64,6 +68,18 @@ bool CSVRender::Cell::addObjects (int start, int end)
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,
bool deleted)
: 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;
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();
if (!mDeleted)
@ -104,6 +131,8 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
mCellBorder->buildShape(esmLand);
}
}
recreatePathgrid();
}
}
@ -254,6 +283,31 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
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)
{
if (elementMask & Mask_Reference)

@ -23,12 +23,15 @@ class QModelIndex;
namespace osg
{
class Group;
class Geometry;
class Geode;
}
namespace CSMWorld
{
class Data;
class CellCoordinates;
class Pathgrid;
}
namespace CSVRender
@ -40,6 +43,8 @@ namespace CSVRender
CSMWorld::Data& mData;
std::string mId;
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::auto_ptr<Terrain::TerrainGrid> mTerrain;
CSMWorld::CellCoordinates mCoordinates;
@ -64,6 +69,8 @@ namespace CSVRender
/// \return Have any objects been added?
bool addObjects (int start, int end);
void recreatePathgrid();
public:
enum Selection
@ -103,6 +110,16 @@ namespace CSVRender
/// this cell?
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);
// 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();
}
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()
{
osg::Vec3d eye, center, up;

@ -52,6 +52,14 @@ namespace CSVRender
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();
/// \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)
: WorldspaceWidget (document, parent), mCellId (cellId)
: WorldspaceWidget (document, parent), mDocument(document), mCellId (cellId)
{
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
@ -197,6 +197,90 @@ void CSVRender::UnpagedWorldspaceWidget::referenceAdded (const QModelIndex& pare
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 (
CSVWidget::SceneToolToggle2 *tool)
{

@ -25,6 +25,7 @@ namespace CSVRender
{
Q_OBJECT
CSMDoc::Document& mDocument;
std::string mCellId;
CSMWorld::IdTable *mCellsModel;
CSMWorld::IdTable *mReferenceablesModel;
@ -83,6 +84,15 @@ namespace CSVRender
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();
protected:

@ -59,6 +59,17 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
connect (references, SIGNAL (rowsInserted (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 =
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 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);
void debugProfileDataChanged (const QModelIndex& topLeft,

@ -8,6 +8,7 @@
#include <components/esm/loadstat.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/environment.hpp"
@ -23,107 +24,6 @@
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)
: mPathgridEnabled(false)
, mRootNode(root)
@ -212,12 +112,9 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store)
osg::ref_ptr<osg::PositionAttitudeTransform> cellPathGrid = new osg::PositionAttitudeTransform;
cellPathGrid->setPosition(cellPathGridPos);
osg::ref_ptr<osg::Geometry> lines = createPathgridLines(pathgrid);
osg::ref_ptr<osg::Geometry> points = createPathgridPoints(pathgrid);
osg::ref_ptr<osg::Geometry> geometry = SceneUtil::createPathgridGeometry(*pathgrid);
cellPathGrid->addChild(lines);
cellPathGrid->addChild(points);
cellPathGrid->addChild(geometry);
mPathGridRoot->addChild(cellPathGrid);

@ -48,9 +48,6 @@ namespace MWRender
void enableCellPathgrid(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:
Pathgrid(osg::ref_ptr<osg::Group> root);
~Pathgrid();

@ -22,7 +22,7 @@ endif (GIT_CHECKOUT)
if (OPENGL_ES)
find_package(OpenGLES REQUIRED)
else()
else()
find_package(OpenGL REQUIRED)
endif()
@ -50,7 +50,7 @@ add_component_dir (shader
add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue unrefqueue
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil
)
add_component_dir (nif
@ -191,7 +191,7 @@ else()
set(GL_LIB ${OPENGL_gl_LIBRARY})
endif()
target_link_libraries(components
target_link_libraries(components
${Boost_SYSTEM_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}

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