Merge branch 'seaofnodesmorelike' into 'master'

Use more sensible types in pathgridutil

Closes #8172

See merge request OpenMW/openmw!4395
pull/3236/head
AnyOldName3 3 months ago
commit 6c8055134d

@ -192,6 +192,7 @@
Bug #8124: Normal weapon resistance is applied twice for NPCs Bug #8124: Normal weapon resistance is applied twice for NPCs
Bug #8132: Actors without hello responses turn to face the player Bug #8132: Actors without hello responses turn to face the player
Bug #8171: Items with more than 100% health can be repaired Bug #8171: Items with more than 100% health can be repaired
Bug #8172: Openmw-cs crashes when viewing `Dantooine, Sea`
Feature #1415: Infinite fall failsafe Feature #1415: Infinite fall failsafe
Feature #2566: Handle NAM9 records for manual cell references Feature #2566: Handle NAM9 records for manual cell references
Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking Feature #3501: OpenMW-CS: Instance Editing - Shortcuts for axial locking

@ -75,7 +75,7 @@ namespace CSVRender
QString text("Pathgrid: "); QString text("Pathgrid: ");
text += mPathgrid->getId().c_str(); text += mPathgrid->getId().c_str();
text += " ("; text += " (";
text += QString::number(SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0))); text += QString::number(SceneUtil::getPathgridNode(hit.index0));
text += ")"; text += ")";
return text; return text;

@ -108,7 +108,7 @@ namespace CSVRender
{ {
if (tag->getPathgrid()->isSelected()) if (tag->getPathgrid()->isSelected())
{ {
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short node = SceneUtil::getPathgridNode(hit.index0);
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack(); QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Connect node to selected nodes"; QString description = "Connect node to selected nodes";
@ -129,7 +129,7 @@ namespace CSVRender
if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get())) if (PathgridTag* tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
{ {
mLastId = tag->getPathgrid()->getId(); mLastId = tag->getPathgrid()->getId();
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short node = SceneUtil::getPathgridNode(hit.index0);
tag->getPathgrid()->toggleSelected(node); tag->getPathgrid()->toggleSelected(node);
} }
} }
@ -147,7 +147,7 @@ namespace CSVRender
mLastId = tag->getPathgrid()->getId(); mLastId = tag->getPathgrid()->getId();
} }
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short node = SceneUtil::getPathgridNode(hit.index0);
tag->getPathgrid()->toggleSelected(node); tag->getPathgrid()->toggleSelected(node);
return; return;
@ -190,7 +190,7 @@ namespace CSVRender
{ {
mDragMode = DragMode_Edge; mDragMode = DragMode_Edge;
mEdgeId = tag->getPathgrid()->getId(); mEdgeId = tag->getPathgrid()->getId();
mFromNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); mFromNode = SceneUtil::getPathgridNode(hit.index0);
tag->getPathgrid()->setDragOrigin(mFromNode); tag->getPathgrid()->setDragOrigin(mFromNode);
return true; return true;
@ -230,7 +230,7 @@ namespace CSVRender
if (hit.tag && (tag = dynamic_cast<PathgridTag*>(hit.tag.get())) if (hit.tag && (tag = dynamic_cast<PathgridTag*>(hit.tag.get()))
&& tag->getPathgrid()->getId() == mEdgeId) && tag->getPathgrid()->getId() == mEdgeId)
{ {
unsigned short node = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short node = SceneUtil::getPathgridNode(hit.index0);
cell->getPathgrid()->setDragEndpoint(node); cell->getPathgrid()->setDragEndpoint(node);
} }
else else
@ -268,7 +268,7 @@ namespace CSVRender
{ {
if (tag->getPathgrid()->getId() == mEdgeId) if (tag->getPathgrid()->getId() == mEdgeId)
{ {
unsigned short toNode = SceneUtil::getPathgridNode(static_cast<unsigned short>(hit.index0)); unsigned short toNode = SceneUtil::getPathgridNode(hit.index0);
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack(); QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
QString description = "Add edge between nodes"; QString description = "Add edge between nodes";

@ -5,17 +5,21 @@
#include <components/esm3/loadpgrd.hpp> #include <components/esm3/loadpgrd.hpp>
#include <limits>
namespace SceneUtil namespace SceneUtil
{ {
const unsigned short DiamondVertexCount = 6; namespace
const unsigned short DiamondIndexCount = 24; {
const unsigned short DiamondWireframeIndexCount = 24; constexpr unsigned short DiamondVertexCount = 6;
constexpr unsigned short DiamondIndexCount = 24;
constexpr unsigned short DiamondWireframeIndexCount = 24;
const unsigned short DiamondConnectorVertexCount = 4; constexpr unsigned short DiamondConnectorVertexCount = 4;
const unsigned short DiamondTotalVertexCount = DiamondVertexCount + DiamondConnectorVertexCount; constexpr unsigned short DiamondTotalVertexCount = DiamondVertexCount + DiamondConnectorVertexCount;
const float DiamondWireframeScalar = 1.1f; constexpr float DiamondWireframeScalar = 1.1f;
const osg::Vec3f DiamondPoints[DiamondVertexCount] = { osg::Vec3f(0.f, 0.f, DiamondHalfHeight * 2.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),
@ -23,13 +27,13 @@ namespace SceneUtil
osg::Vec3f(DiamondHalfWidth, -DiamondHalfWidth, DiamondHalfHeight), osg::Vec3f(DiamondHalfWidth, -DiamondHalfWidth, DiamondHalfHeight),
osg::Vec3f(DiamondHalfWidth, DiamondHalfWidth, DiamondHalfHeight), osg::Vec3f(0.f, 0.f, 0.f) }; osg::Vec3f(DiamondHalfWidth, DiamondHalfWidth, DiamondHalfHeight), osg::Vec3f(0.f, 0.f, 0.f) };
const unsigned short DiamondIndices[DiamondIndexCount] constexpr 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 }; = { 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 DiamondWireframeIndices[DiamondWireframeIndexCount] constexpr 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 }; = { 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 }; constexpr unsigned short DiamondConnectorVertices[DiamondConnectorVertexCount] = { 1, 2, 3, 4 };
const osg::Vec4f DiamondColors[DiamondVertexCount] 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, 0.f, 1.f, 1.f), osg::Vec4f(0.f, .05f, .95f, 1.f), osg::Vec4f(0.f, .1f, .95f, 1.f),
@ -39,35 +43,23 @@ namespace SceneUtil
const osg::Vec4f DiamondWireColor = osg::Vec4f(0.72f, 0.f, 0.96f, 1.f); const osg::Vec4f DiamondWireColor = osg::Vec4f(0.72f, 0.f, 0.96f, 1.f);
const osg::Vec4f DiamondFocusWireColor = osg::Vec4f(0.91f, 0.66f, 1.f, 1.f); const osg::Vec4f DiamondFocusWireColor = osg::Vec4f(0.91f, 0.66f, 1.f, 1.f);
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid) template <class PType, class LType>
void addPathgridToGeometry(const size_t vertexCount, const size_t pointIndexCount, const size_t edgeIndexCount,
osg::ref_ptr<osg::Geometry>& gridGeometry, const ESM::Pathgrid& pathgrid)
{ {
const unsigned short PointCount = static_cast<unsigned short>(pathgrid.mPoints.size()); osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(vertexCount);
const size_t EdgeCount = pathgrid.mEdges.size(); osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(vertexCount);
osg::ref_ptr<PType> pointIndices = new PType(osg::PrimitiveSet::TRIANGLES, pointIndexCount);
const unsigned short VertexCount = PointCount * DiamondTotalVertexCount; osg::ref_ptr<LType> lineIndices = new LType(osg::PrimitiveSet::LINES, edgeIndexCount);
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();
if (PointIndexCount || EdgeIndexCount)
{
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 // Add each point/node
for (unsigned short pointIndex = 0; pointIndex < PointCount; ++pointIndex) for (size_t pointIndex = 0; pointIndex < pathgrid.mPoints.size(); ++pointIndex)
{ {
const ESM::Pathgrid::Point& point = pathgrid.mPoints[pointIndex]; const ESM::Pathgrid::Point& point = pathgrid.mPoints[pointIndex];
osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ); osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ);
unsigned short vertexOffset = pointIndex * DiamondTotalVertexCount; size_t vertexOffset = pointIndex * DiamondTotalVertexCount;
unsigned short indexOffset = pointIndex * DiamondIndexCount; size_t indexOffset = pointIndex * DiamondIndexCount;
// Point // Point
for (unsigned short i = 0; i < DiamondVertexCount; ++i) for (unsigned short i = 0; i < DiamondVertexCount; ++i)
@ -91,16 +83,15 @@ namespace SceneUtil
} }
// Add edges // Add edges
unsigned short lineIndex = 0; unsigned int lineIndex = 0;
for (ESM::Pathgrid::EdgeList::const_iterator edge = pathgrid.mEdges.begin(); edge != pathgrid.mEdges.end(); for (const ESM::Pathgrid::Edge& edge : pathgrid.mEdges)
++edge)
{ {
if (edge->mV0 == edge->mV1 || edge->mV0 >= PointCount || edge->mV1 >= PointCount) if (edge.mV0 == edge.mV1 || edge.mV0 >= pathgrid.mPoints.size() || edge.mV1 >= pathgrid.mPoints.size())
continue; continue;
const ESM::Pathgrid::Point& from = pathgrid.mPoints[edge->mV0]; const ESM::Pathgrid::Point& from = pathgrid.mPoints[edge.mV0];
const ESM::Pathgrid::Point& to = pathgrid.mPoints[edge->mV1]; const ESM::Pathgrid::Point& to = pathgrid.mPoints[edge.mV1];
osg::Vec3f fromPos = osg::Vec3f(from.mX, from.mY, from.mZ); osg::Vec3f fromPos = osg::Vec3f(from.mX, from.mY, from.mZ);
osg::Vec3f toPos = osg::Vec3f(to.mX, to.mY, to.mZ); osg::Vec3f toPos = osg::Vec3f(to.mX, to.mY, to.mZ);
@ -122,8 +113,8 @@ namespace SceneUtil
else if (dir.x() >= 0 && dir.y() < 0) else if (dir.x() >= 0 && dir.y() < 0)
diamondIndex = 2; diamondIndex = 2;
unsigned short fromIndex = static_cast<unsigned short>(edge->mV0); unsigned fromIndex = static_cast<unsigned>(edge.mV0);
unsigned short toIndex = static_cast<unsigned short>(edge->mV1); unsigned toIndex = static_cast<unsigned>(edge.mV1);
lineIndices->setElement( lineIndices->setElement(
lineIndex++, fromIndex * DiamondTotalVertexCount + DiamondVertexCount + diamondIndex); lineIndex++, fromIndex * DiamondTotalVertexCount + DiamondVertexCount + diamondIndex);
@ -135,55 +126,39 @@ namespace SceneUtil
gridGeometry->setVertexArray(vertices); gridGeometry->setVertexArray(vertices);
gridGeometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX); gridGeometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
if (PointIndexCount) if (pointIndexCount)
gridGeometry->addPrimitiveSet(pointIndices); gridGeometry->addPrimitiveSet(pointIndices);
if (EdgeIndexCount) if (edgeIndexCount)
gridGeometry->addPrimitiveSet(lineIndices); gridGeometry->addPrimitiveSet(lineIndices);
gridGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); gridGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
} }
osg::ref_ptr<osg::Material> material = new osg::Material; template <class T>
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); void addWireFrameGeometry(const size_t vertexCount, const size_t indexCount,
gridGeometry->getOrCreateStateSet()->setAttribute(material); osg::ref_ptr<osg::Geometry>& wireframeGeometry, const ESM::Pathgrid& pathgrid,
const std::vector<unsigned short>& selected)
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();
if (IndexCount)
{ {
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(VertexCount); osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(vertexCount);
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(ColorCount); osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(vertexCount);
osg::ref_ptr<osg::DrawElementsUShort> indices osg::ref_ptr<T> indices = new T(osg::PrimitiveSet::LINES, indexCount);
= new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, IndexCount);
osg::Vec3f wireOffset = osg::Vec3f(0, 0, (1 - DiamondWireframeScalar) * DiamondHalfHeight); osg::Vec3f wireOffset = osg::Vec3f(0, 0, (1 - DiamondWireframeScalar) * DiamondHalfHeight);
// Add each point/node // Add each point/node
for (unsigned short it = 0; it < PointCount; ++it) for (size_t it = 0; it < selected.size(); ++it)
{ {
const ESM::Pathgrid::Point& point = pathgrid.mPoints[selected[it]]; const ESM::Pathgrid::Point& point = pathgrid.mPoints[selected[it]];
osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ) + wireOffset; osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ) + wireOffset;
unsigned short vertexOffset = it * DiamondVertexCount; size_t vertexOffset = it * DiamondVertexCount;
unsigned short indexOffset = it * DiamondWireframeIndexCount; size_t indexOffset = it * DiamondWireframeIndexCount;
// Point // Point
for (unsigned short i = 0; i < DiamondVertexCount; ++i) for (unsigned short i = 0; i < DiamondVertexCount; ++i)
{ {
(*vertices)[vertexOffset + i] = position + DiamondPoints[i] * DiamondWireframeScalar; (*vertices)[vertexOffset + i] = position + DiamondPoints[i] * DiamondWireframeScalar;
if (it == PointCount - 1) if (it == selected.size() - 1)
(*colors)[vertexOffset + i] = DiamondFocusWireColor; (*colors)[vertexOffset + i] = DiamondFocusWireColor;
else else
(*colors)[vertexOffset + i] = DiamondWireColor; (*colors)[vertexOffset + i] = DiamondWireColor;
@ -200,11 +175,63 @@ namespace SceneUtil
wireframeGeometry->addPrimitiveSet(indices); wireframeGeometry->addPrimitiveSet(indices);
wireframeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); wireframeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
} }
}
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid)
{
const size_t vertexCount = pathgrid.mPoints.size() * DiamondTotalVertexCount;
const size_t pointIndexCount = pathgrid.mPoints.size() * DiamondIndexCount;
const size_t edgeIndexCount = pathgrid.mEdges.size() * 2;
osg::ref_ptr<osg::Geometry> gridGeometry = new osg::Geometry();
if (pointIndexCount || edgeIndexCount)
{
const bool useIntPoints = pointIndexCount > std::numeric_limits<unsigned short>::max();
const bool useIntVertices = vertexCount > std::numeric_limits<unsigned short>::max();
if (useIntPoints && useIntVertices)
addPathgridToGeometry<osg::DrawElementsUInt, osg::DrawElementsUInt>(
vertexCount, pointIndexCount, edgeIndexCount, gridGeometry, pathgrid);
else if (useIntPoints)
addPathgridToGeometry<osg::DrawElementsUInt, osg::DrawElementsUShort>(
vertexCount, pointIndexCount, edgeIndexCount, gridGeometry, pathgrid);
else if (useIntVertices)
addPathgridToGeometry<osg::DrawElementsUShort, osg::DrawElementsUInt>(
vertexCount, pointIndexCount, edgeIndexCount, gridGeometry, pathgrid);
else
addPathgridToGeometry<osg::DrawElementsUShort, osg::DrawElementsUShort>(
vertexCount, pointIndexCount, edgeIndexCount, gridGeometry, pathgrid);
}
osg::ref_ptr<osg::Material> material = new osg::Material;
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
gridGeometry->getOrCreateStateSet()->setAttribute(material);
return gridGeometry;
}
osg::ref_ptr<osg::Geometry> createPathgridSelectedWireframe(
const ESM::Pathgrid& pathgrid, const std::vector<unsigned short>& selected)
{
const size_t vertexCount = selected.size() * DiamondVertexCount;
const size_t indexCount = selected.size() * DiamondWireframeIndexCount;
osg::ref_ptr<osg::Geometry> wireframeGeometry = new osg::Geometry();
if (indexCount)
{
if (vertexCount > std::numeric_limits<unsigned short>::max())
addWireFrameGeometry<osg::DrawElementsUInt>(
vertexCount, indexCount, wireframeGeometry, pathgrid, selected);
else
addWireFrameGeometry<osg::DrawElementsUShort>(
vertexCount, indexCount, wireframeGeometry, pathgrid, selected);
}
return wireframeGeometry; return wireframeGeometry;
} }
unsigned short getPathgridNode(unsigned short vertexIndex) unsigned short getPathgridNode(unsigned vertexIndex)
{ {
return vertexIndex / (DiamondVertexCount + DiamondConnectorVertexCount); return static_cast<unsigned short>(vertexIndex / (DiamondVertexCount + DiamondConnectorVertexCount));
} }
} }

@ -11,15 +11,15 @@ namespace ESM
namespace SceneUtil namespace SceneUtil
{ {
const float DiamondHalfHeight = 40.f; constexpr float DiamondHalfHeight = 40.f;
const float DiamondHalfWidth = 16.f; constexpr float DiamondHalfWidth = 16.f;
osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid); osg::ref_ptr<osg::Geometry> createPathgridGeometry(const ESM::Pathgrid& pathgrid);
osg::ref_ptr<osg::Geometry> createPathgridSelectedWireframe( osg::ref_ptr<osg::Geometry> createPathgridSelectedWireframe(
const ESM::Pathgrid& pathgrid, const std::vector<unsigned short>& selected); const ESM::Pathgrid& pathgrid, const std::vector<unsigned short>& selected);
unsigned short getPathgridNode(unsigned short vertexIndex); unsigned short getPathgridNode(unsigned vertexIndex);
} }
#endif #endif

Loading…
Cancel
Save