Initial pathgrid editting, support for selection and movement.

pull/1/head
Aesylwinn 9 years ago
parent 9645d0cc8a
commit 32ba5bf8b8

@ -86,12 +86,12 @@ opencs_units (view/widget
opencs_units (view/render
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget editmode instancemode instanceselectionmode instancemovemode
orbitcameramode
orbitcameramode pathgridmode
)
opencs_units_noqt (view/render
lighting lightingday lightingnight lightingbright object cell terrainstorage tagbase
cellarrow cellmarker cellborder cameracontroller
cellarrow cellmarker cellborder cameracontroller pathgrid
)
opencs_hdrs_noqt (view/render

@ -17,6 +17,7 @@
#include "../../model/world/cellcoordinates.hpp"
#include "mask.hpp"
#include "pathgrid.hpp"
#include "terrainstorage.hpp"
bool CSVRender::Cell::removeObject (const std::string& id)
@ -68,18 +69,6 @@ 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),
@ -93,17 +82,6 @@ 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)
@ -132,7 +110,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
}
}
recreatePathgrid();
mPathgrid.reset(new Pathgrid(mData, mCellNode, mId, mCoordinates));
}
}
@ -285,27 +263,27 @@ bool CSVRender::Cell::referenceAdded (const QModelIndex& parent, int start, int
void CSVRender::Cell::pathgridAdded(const CSMWorld::Pathgrid& pathgrid)
{
recreatePathgrid();
mPathgrid->recreateGeometry();
}
void CSVRender::Cell::pathgridRemoved()
{
mPathgridGeode->removeDrawable(mPathgridGeometry);
mPathgrid->recreateGeometry();
}
void CSVRender::Cell::pathgridDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
recreatePathgrid();
mPathgrid->recreateGeometry();
}
void CSVRender::Cell::pathgridRowRemoved(const QModelIndex& parent, int start, int end)
{
recreatePathgrid();
mPathgrid->recreateGeometry();
}
void CSVRender::Cell::pathgridRowAdded(const QModelIndex& parent, int start, int end)
{
recreatePathgrid();
mPathgrid->recreateGeometry();
}
void CSVRender::Cell::setSelection (int elementMask, Selection mode)
@ -327,6 +305,15 @@ void CSVRender::Cell::setSelection (int elementMask, Selection mode)
iter->second->setSelected (selected);
}
}
if (elementMask & Mask_Pathgrid)
{
switch (mode)
{
case Selection_Clear: mPathgrid->clearSelected(); break;
case Selection_All: mPathgrid->selectAll(); break;
case Selection_Invert: mPathgrid->invertSelected(); break;
}
}
}
void CSVRender::Cell::selectAllWithSameParentId (int elementMask)
@ -406,6 +393,9 @@ std::vector<osg::ref_ptr<CSVRender::TagBase> > CSVRender::Cell::getSelection (un
iter!=mObjects.end(); ++iter)
if (iter->second->getSelected())
result.push_back (iter->second->getTag());
if (elementMask & Mask_Pathgrid)
if (mPathgrid->isSelected())
result.push_back(mPathgrid->getTag());
return result;
}
@ -440,4 +430,6 @@ void CSVRender::Cell::reset (unsigned int elementMask)
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
iter!=mObjects.end(); ++iter)
iter->second->reset();
if (elementMask & Mask_Pathgrid)
mPathgrid->resetMove();
}

@ -36,6 +36,7 @@ namespace CSMWorld
namespace CSVRender
{
class Pathgrid;
class TagBase;
class Cell
@ -43,14 +44,13 @@ 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;
std::auto_ptr<CellArrow> mCellArrows[4];
std::auto_ptr<CellMarker> mCellMarker;
std::auto_ptr<CellBorder> mCellBorder;
std::auto_ptr<Pathgrid> mPathgrid;
bool mDeleted;
int mSubMode;
unsigned int mSubModeElementMask;
@ -69,8 +69,6 @@ namespace CSVRender
/// \return Have any objects been added?
bool addObjects (int start, int end);
void recreatePathgrid();
public:
enum Selection

@ -0,0 +1,287 @@
#include "pathgrid.hpp"
#include <algorithm>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/Vec3>
#include <components/sceneutil/pathgridutil.hpp>
#include "../../model/world/commands.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../../model/world/data.hpp"
namespace CSVRender
{
PathgridTag::PathgridTag(Pathgrid* pathgrid)
: TagBase(Mask_Pathgrid), mPathgrid(pathgrid)
{
}
Pathgrid* PathgridTag::getPathgrid() const
{
return mPathgrid;
}
QString PathgridTag::getToolTip(bool hideBasics) const
{
QString text("Pathgrid: ");
text += mPathgrid->getId().c_str();
if (!hideBasics)
{
text += "<p>Only one pathgrid may be edited at a time.";
}
return text;
}
Pathgrid::Pathgrid(CSMWorld::Data& data, osg::Group* parent, const std::string& pathgridId,
const CSMWorld::CellCoordinates& coordinates)
: mData(data)
, mId(pathgridId)
, mCoords(coordinates)
, mParent(parent)
, mPathgridGeometry(0)
, mSelectedGeometry(0)
, mTag(new PathgridTag(this))
{
const float CoordScalar = ESM::Land::REAL_SIZE;
mBaseNode = new osg::PositionAttitudeTransform ();
mBaseNode->setPosition(osg::Vec3f(mCoords.getX() * CoordScalar, mCoords.getY() * CoordScalar, 0.f));
mBaseNode->setUserData(mTag);
mBaseNode->setNodeMask(Mask_Pathgrid);
mParent->addChild(mBaseNode);
mSelectedNode = new osg::PositionAttitudeTransform();
mBaseNode->addChild(mSelectedNode);
mPathgridGeode = new osg::Geode();
mBaseNode->addChild(mPathgridGeode);
mSelectedGeode = new osg::Geode();
mSelectedNode->addChild(mSelectedGeode);
recreateGeometry();
}
Pathgrid::~Pathgrid()
{
mParent->removeChild(mBaseNode);
}
const CSMWorld::CellCoordinates& Pathgrid::getCoordinates() const
{
return mCoords;
}
const std::string& Pathgrid::getId() const
{
return mId;
}
bool Pathgrid::isSelected() const
{
return !mSelected.empty();
}
const Pathgrid::NodeList& Pathgrid::getSelected() const
{
return mSelected;
}
void Pathgrid::selectAll()
{
mSelected.clear();
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
const CSMWorld::Pathgrid& source = pathgrids.getRecord(pathgridIndex).get();
for (unsigned short i = 0; i < static_cast<unsigned short>(source.mPoints.size()); ++i)
mSelected.push_back(i);
recreateSelectedGeometry(source);
}
else
{
removeSelectedGeometry();
}
}
void Pathgrid::toggleSelected(unsigned short node)
{
NodeList::iterator searchResult = std::find(mSelected.begin(), mSelected.end(), node);
if (searchResult != mSelected.end())
{
mSelected.erase(searchResult);
}
else
{
mSelected.push_back(node);
}
recreateSelectedGeometry();
}
void Pathgrid::invertSelected()
{
NodeList temp = NodeList(mSelected.begin(), mSelected.end());
mSelected.clear();
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
const CSMWorld::Pathgrid& source = pathgrids.getRecord(pathgridIndex).get();
for (unsigned short i = 0; i < static_cast<unsigned short>(source.mPoints.size()); ++i)
{
if (std::find(temp.begin(), temp.end(), i) == temp.end())
mSelected.push_back(i);
}
recreateSelectedGeometry(source);
}
else
{
removeSelectedGeometry();
}
}
void Pathgrid::clearSelected()
{
mSelected.clear();
removeSelectedGeometry();
}
void Pathgrid::moveSelected(const osg::Vec3d& offset)
{
mSelectedNode->setPosition(mSelectedNode->getPosition() + offset);
}
void Pathgrid::resetMove()
{
mSelectedNode->setPosition(osg::Vec3f(0,0,0));
}
void Pathgrid::applyPosition(CSMWorld::CommandMacro& commands)
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
const CSMWorld::Pathgrid& source = pathgrids.getRecord(pathgridIndex).get();
osg::Vec3d localCoords = mSelectedNode->getPosition();
int oX = static_cast<int>(localCoords.x());
int oY = static_cast<int>(localCoords.y());
int oZ = static_cast<int>(localCoords.z());
CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& collection = mData.getPathgrids();
QAbstractItemModel* model = mData.getTableModel (CSMWorld::UniversalId::Type_Pathgrids);
int recordIndex = collection.getIndex (mId);
int parentColumn = collection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridPoints);
QModelIndex parent = model->index(recordIndex, parentColumn);
for (size_t i = 0; i < mSelected.size(); ++i)
{
const CSMWorld::Pathgrid::Point& point = source.mPoints[mSelected[i]];
int row = mSelected[i];
// X
int column = collection.searchNestedColumnIndex(parentColumn, CSMWorld::Columns::ColumnId_PathgridPosX);
commands.push (new CSMWorld::ModifyCommand(*model, model->index(row, column, parent), point.mX + oX));
// Y
column = collection.searchNestedColumnIndex(parentColumn, CSMWorld::Columns::ColumnId_PathgridPosY);
commands.push (new CSMWorld::ModifyCommand(*model, model->index(row, column, parent), point.mY + oY));
// Z
column = collection.searchNestedColumnIndex(parentColumn, CSMWorld::Columns::ColumnId_PathgridPosZ);
commands.push (new CSMWorld::ModifyCommand(*model, model->index(row, column, parent), point.mZ + oZ));
}
}
resetMove();
}
void Pathgrid::applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2)
{
// TODO
}
void Pathgrid::applyEdges(CSMWorld::CommandMacro& commands, unsigned short node)
{
// TODO
}
osg::ref_ptr<PathgridTag> Pathgrid::getTag() const
{
return mTag;
}
void Pathgrid::recreateGeometry()
{
removePathgridGeometry();
removeSelectedGeometry();
// Make new
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
const CSMWorld::Pathgrid& source = pathgrids.getRecord(pathgridIndex).get();
mPathgridGeometry = SceneUtil::createPathgridGeometry(source);
mPathgridGeode->addDrawable(mPathgridGeometry);
recreateSelectedGeometry(source);
}
}
void Pathgrid::recreateSelectedGeometry()
{
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids = mData.getPathgrids();
int pathgridIndex = pathgrids.searchId(mId);
if (pathgridIndex != -1)
{
const CSMWorld::Pathgrid& source = pathgrids.getRecord(pathgridIndex).get();
recreateSelectedGeometry(source);
}
else
{
removeSelectedGeometry();
}
}
void Pathgrid::recreateSelectedGeometry(const CSMWorld::Pathgrid& source)
{
removeSelectedGeometry();
mSelectedGeometry = SceneUtil::createPathgridSelectedWireframe(source, mSelected);
mSelectedGeode->addDrawable(mSelectedGeometry);
}
void Pathgrid::removePathgridGeometry()
{
if (mPathgridGeometry)
{
mPathgridGeode->removeDrawable(mPathgridGeometry);
mPathgridGeometry.release();
}
}
void Pathgrid::removeSelectedGeometry()
{
if (mSelectedGeometry)
{
mSelectedGeode->removeDrawable(mSelectedGeometry);
mSelectedGeometry.release();
}
}
}

@ -0,0 +1,105 @@
#ifndef CSV_RENDER_PATHGRID_H
#define CSV_RENDER_PATHGRID_H
#include <vector>
#include <QString>
#include <osg/ref_ptr>
#include "../../model/world/cellcoordinates.hpp"
#include "tagbase.hpp"
namespace osg
{
class Geode;
class Geometry;
class Group;
class PositionAttitudeTransform;
class Vec3d;
}
namespace CSMWorld
{
class CommandMacro;
class Data;
class Pathgrid;
}
namespace CSVRender
{
class Pathgrid;
class PathgridTag : public TagBase
{
public:
PathgridTag (Pathgrid* pathgrid);
Pathgrid* getPathgrid () const;
virtual QString getToolTip (bool hideBasics) const;
private:
Pathgrid* mPathgrid;
};
class Pathgrid
{
public:
typedef std::vector<unsigned short> NodeList;
Pathgrid(CSMWorld::Data& data, osg::Group* parent, const std::string& pathgridId,
const CSMWorld::CellCoordinates& coordinates);
~Pathgrid();
const CSMWorld::CellCoordinates& getCoordinates() const;
const std::string& getId() const;
bool isSelected() const;
const NodeList& getSelected() const;
void selectAll();
void toggleSelected(unsigned short node); // Adds to end of vector
void invertSelected();
void clearSelected();
void moveSelected(const osg::Vec3d& offset);
void resetMove();
void applyPosition(CSMWorld::CommandMacro& commands);
void applyEdge(CSMWorld::CommandMacro& commands, unsigned short node1, unsigned short node2);
void applyEdges(CSMWorld::CommandMacro& commands, unsigned short node);
osg::ref_ptr<PathgridTag> getTag() const;
void recreateGeometry();
private:
CSMWorld::Data& mData;
std::string mId;
CSMWorld::CellCoordinates mCoords;
NodeList mSelected;
osg::Group* mParent;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mSelectedNode;
osg::ref_ptr<osg::Geode> mPathgridGeode;
osg::ref_ptr<osg::Geode> mSelectedGeode;
osg::ref_ptr<osg::Geometry> mPathgridGeometry;
osg::ref_ptr<osg::Geometry> mSelectedGeometry;
osg::ref_ptr<PathgridTag> mTag;
void recreateSelectedGeometry();
void recreateSelectedGeometry(const CSMWorld::Pathgrid& source);
void removePathgridGeometry();
void removeSelectedGeometry();
};
}
#endif

@ -0,0 +1,152 @@
#include "pathgridmode.hpp"
#include <components/sceneutil/pathgridutil.hpp>
#include "../../model/world/commands.hpp"
#include "../../model/world/commandmacro.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/idtree.hpp"
#include "mask.hpp"
#include "pathgrid.hpp"
#include "worldspacewidget.hpp"
namespace CSVRender
{
PathgridMode::PathgridMode(WorldspaceWidget* worldspaceWidget, QWidget* parent)
: EditMode(worldspaceWidget, QIcon(":placeholder"), Mask_Pathgrid, "Pathgrid editing", parent)
, mDragMode(DragMode_None)
, mFromNode(0)
{
}
void PathgridMode::primaryEditPressed(const WorldspaceHitResult& hit)
{
}
void PathgridMode::secondaryEditPressed(const WorldspaceHitResult& hit)
{
}
void PathgridMode::primarySelectPressed(const WorldspaceHitResult& hit)
{
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
if (hit.tag)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.i0));
tag->getPathgrid()->toggleSelected(node);
}
}
}
void PathgridMode::secondarySelectPressed(const WorldspaceHitResult& hit)
{
if (hit.tag)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{
if (tag->getPathgrid()->getId() != mLastId)
{
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
mLastId = tag->getPathgrid()->getId();
}
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.i0));
tag->getPathgrid()->toggleSelected(node);
return;
}
}
getWorldspaceWidget().clearSelection(Mask_Pathgrid);
}
bool PathgridMode::primaryEditStartDrag(const WorldspaceHitResult& hit)
{
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
if (!selection.empty())
{
mDragMode = DragMode_Move;
return true;
}
else
{
return false;
}
}
bool PathgridMode::secondaryEditStartDrag(const WorldspaceHitResult& hit)
{
if (hit.tag)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{
mDragMode = DragMode_Edge;
mFromNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.i0));
return true;
}
}
return false;
}
void PathgridMode::drag(int diffX, int diffY, double speedFactor)
{
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
{
if (mDragMode == DragMode_Move)
{
osg::Vec3d eye, center, up, offset;
getWorldspaceWidget().getCamera()->getViewMatrix().getLookAt (eye, center, up);
offset = (up * diffY * speedFactor) + (((center - eye) ^ up) * diffX * speedFactor);
tag->getPathgrid()->moveSelected(offset);
}
else if (mDragMode == DragMode_Edge)
{
// TODO make indicators
}
}
}
}
void PathgridMode::dragCompleted()
{
std::vector<osg::ref_ptr<TagBase> > selection = getWorldspaceWidget().getSelection (Mask_Pathgrid);
for (std::vector<osg::ref_ptr<TagBase> >::iterator it = selection.begin(); it != selection.end(); ++it)
{
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(it->get()))
{
if (mDragMode == DragMode_Move)
{
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Move pathgrid node(s)";
CSMWorld::CommandMacro macro(undoStack, description);
tag->getPathgrid()->applyPosition(macro);
}
else if (mDragMode == DragMode_Edge)
{
// TODO raycast for other node and apply if needed with mFromNode
}
}
}
mDragMode = DragMode_None;
}
void PathgridMode::dragAborted()
{
getWorldspaceWidget().reset(Mask_Pathgrid);
}
}

@ -0,0 +1,53 @@
#ifndef CSV_RENDER_PATHGRIDMODE_H
#define CSV_RENDER_PATHGRIDMODE_H
#include <string>
#include "editmode.hpp"
namespace CSVRender
{
class PathgridMode : public EditMode
{
Q_OBJECT
public:
PathgridMode(WorldspaceWidget* worldspace, QWidget* parent=0);
virtual void primaryEditPressed(const WorldspaceHitResult& hit);
virtual void secondaryEditPressed(const WorldspaceHitResult& hit);
virtual void primarySelectPressed(const WorldspaceHitResult& hit);
virtual void secondarySelectPressed(const WorldspaceHitResult& hit);
virtual bool primaryEditStartDrag (const WorldspaceHitResult& hit);
virtual bool secondaryEditStartDrag (const WorldspaceHitResult& hit);
virtual void drag (int diffX, int diffY, double speedFactor);
virtual void dragCompleted();
/// \note dragAborted will not be called, if the drag is aborted via changing
/// editing mode
virtual void dragAborted();
private:
enum DragMode
{
DragMode_None,
DragMode_Move,
DragMode_Edge
};
std::string mLastId;
DragMode mDragMode;
unsigned short mFromNode;
};
}
#endif

@ -27,8 +27,8 @@
#include "object.hpp"
#include "mask.hpp"
#include "editmode.hpp"
#include "instancemode.hpp"
#include "pathgridmode.hpp"
#include "cameracontroller.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
@ -295,7 +295,7 @@ unsigned int CSVRender::WorldspaceWidget::getVisibilityMask() const
void CSVRender::WorldspaceWidget::setInteractionMask (unsigned int mask)
{
mInteractionMask = mask | Mask_CellMarker | Mask_CellArrow;
mInteractionMask = mask | Mask_CellMarker | Mask_CellArrow | Mask_Pathgrid | Mask_Terrain;
}
unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const
@ -320,9 +320,7 @@ void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneTo
{
/// \todo replace EditMode with suitable subclasses
tool->addButton (new InstanceMode (this, tool), "object");
tool->addButton (
new EditMode (this, QIcon (":placeholder"), Mask_Pathgrid, "Pathgrid editing"),
"pathgrid");
tool->addButton (new PathgridMode (this, tool), "pathgrid");
}
CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument()

@ -9,6 +9,7 @@ namespace SceneUtil
{
const unsigned short DiamondVertexCount = 6;
const unsigned short DiamondIndexCount = 24;
const unsigned short DiamondWireframeIndexCount = 24;
const unsigned short DiamondConnectorVertexCount = 4;
@ -16,6 +17,7 @@ namespace SceneUtil
const float DiamondHalfHeight = 40.f;
const float DiamondHalfWidth = 16.f;
const float DiamondWireframeScalar = 1.1f;
const osg::Vec3f DiamondPoints[DiamondVertexCount] =
{
@ -39,6 +41,22 @@ namespace SceneUtil
5, 2, 4
};
const unsigned short DiamondWireframeIndices[DiamondWireframeIndexCount] =
{
0, 1,
0, 2,
0, 3,
0, 4,
1, 2,
2, 4,
4, 3,
3, 1,
5, 1,
5, 2,
5, 3,
5, 4
};
const unsigned short DiamondConnectorVertices[DiamondConnectorVertexCount] =
{
1, 2, 3, 4
@ -55,6 +73,8 @@ namespace SceneUtil
};
const osg::Vec4f DiamondEdgeColor = osg::Vec4f(0.5f, 1.f, 1.f, 1.f);
const osg::Vec4f DiamondWireColor = osg::Vec4f(0.8f, 1.f, 0.9f, 1.f);
const osg::Vec4f DiamondFocusWireColor = osg::Vec4f(0.4f, 1.f, 0.4f, 1.f);
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid)
{
@ -155,4 +175,61 @@ namespace SceneUtil
return gridGeometry;
}
osg::ref_ptr<osg::Geometry> createPathgridSelectedWireframe(const ESM::Pathgrid& pathgrid,
const std::vector<unsigned short>& selected)
{
const unsigned short PointCount = selected.size();
const unsigned short VertexCount = PointCount * DiamondVertexCount;
const unsigned short ColorCount = VertexCount;
const size_t IndexCount = PointCount * DiamondWireframeIndexCount;
osg::ref_ptr<osg::Geometry> wireframeGeometry = 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> indices =
new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, IndexCount);
osg::Vec3f wireOffset = osg::Vec3f(0, 0, (1 - DiamondWireframeScalar) * DiamondHalfHeight);
// Add each point/node
for (unsigned short it = 0; it < PointCount; ++it)
{
const ESM::Pathgrid::Point& point = pathgrid.mPoints[selected[it]];
osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ) + wireOffset;
unsigned short vertexOffset = it * DiamondVertexCount;
unsigned short indexOffset = it * DiamondWireframeIndexCount;
// Point
for (unsigned short i = 0; i < DiamondVertexCount; ++i)
{
(*vertices)[vertexOffset + i] = position + DiamondPoints[i] * DiamondWireframeScalar;
if (it == PointCount - 1)
(*colors)[vertexOffset + i] = DiamondFocusWireColor;
else
(*colors)[vertexOffset + i] = DiamondWireColor;
}
for (unsigned short i = 0; i < DiamondWireframeIndexCount; ++i)
{
indices->setElement(indexOffset + i, vertexOffset + DiamondWireframeIndices[i]);
}
}
wireframeGeometry->setVertexArray(vertices);
wireframeGeometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
wireframeGeometry->addPrimitiveSet(indices);
wireframeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
return wireframeGeometry;
}
unsigned short getPathgridNode(unsigned short vertexIndex)
{
return vertexIndex / (DiamondVertexCount + DiamondConnectorVertexCount);
}
}

@ -12,6 +12,11 @@ namespace ESM
namespace SceneUtil
{
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid);
osg::ref_ptr<osg::Geometry> createPathgridSelectedWireframe(const ESM::Pathgrid& pathgrid,
const std::vector<unsigned short>& selected);
unsigned short getPathgridNode(unsigned short vertexIndex);
}
#endif

Loading…
Cancel
Save