forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'aesylwinn/RenderPathgrid'
This commit is contained in:
commit
b4e341e1e2
13 changed files with 476 additions and 113 deletions
|
@ -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> geometry = SceneUtil::createPathgridGeometry(*pathgrid);
|
||||
|
||||
osg::ref_ptr<osg::Geometry> points = createPathgridPoints(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}
|
||||
|
|
158
components/sceneutil/pathgridutil.cpp
Normal file
158
components/sceneutil/pathgridutil.cpp
Normal 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;
|
||||
}
|
||||
}
|
17
components/sceneutil/pathgridutil.hpp
Normal file
17
components/sceneutil/pathgridutil.hpp
Normal 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
|
Loading…
Reference in a new issue