Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pathgrid rendering v2 #933

Merged
merged 13 commits into from
May 8, 2016
Prev Previous commit
Next Next commit
Pathgrid geometry creator
  • Loading branch information
Aesylwinn committed May 3, 2016
commit d141672b53d83773613b5b1dd5e98650407870fa
6 changes: 3 additions & 3 deletions components/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ endif (GIT_CHECKOUT)

if (OPENGL_ES)
find_package(OpenGLES REQUIRED)
else()
else()
find_package(OpenGL REQUIRED)
endif()

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down
155 changes: 155 additions & 0 deletions components/sceneutil/pathgridutil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#include "pathgridutil.hpp"

#include <osg/Geometry>

#include <components/esm/loadland.hpp>
#include <components/esm/loadpgrd.hpp>

namespace SceneUtil
{
const unsigned short DiamondVertexCount = 24;
const float DiamondHalfHeight = 25.f;
const float DiamondHalfWidth = 10.f;

const osg::Vec3f DiamondPoints[6] =
{
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[DiamondVertexCount] =
{
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 osg::Vec4f DiamondColor = osg::Vec4f(1.f, 0.f, 0.f, 1.f);

osg::ref_ptr<osg::Geometry> PathgridGeometryFactory::create(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 * DiamondVertexCount;

osg::ref_ptr<osg::Geometry> gridGeometry = new osg::Geometry();

osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(VertexCount);
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array(VertexCount);
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
osg::ref_ptr<osg::DrawElementsUShort> pointIndices =
new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, VertexCount);
osg::ref_ptr<osg::DrawElementsUShort> lineIndices =
new osg::DrawElementsUShort(osg::PrimitiveSet::LINES, EdgeCount * 2);

// Add each point/node
for (unsigned short i = 0; i < PointCount; ++i)
{
const ESM::Pathgrid::Point& point = pathgrid.mPoints[i];
osg::Vec3f position = osg::Vec3f(point.mX, point.mY, point.mZ);

addPoint(i * DiamondVertexCount, position, vertices, normals, pointIndices);
}

// 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 = 2;
else if (dir.y() >= 0 && dir.x() > 0)
diamondIndex = 8;
else if (dir.x() <= 0 && dir.y() > 0)
diamondIndex = 11;
else if (dir.y() <= 0 && dir.x() < 0)
diamondIndex = 2;
else if (dir.x() >= 0 && dir.y() < 0)
diamondIndex = 5;

unsigned short fromIndex = static_cast<unsigned short>(edge->mV0);
unsigned short toIndex = static_cast<unsigned short>(edge->mV1);

lineIndices->setElement(lineIndex++, fromIndex * DiamondVertexCount + diamondIndex);
lineIndices->setElement(lineIndex++, toIndex * DiamondVertexCount + diamondIndex);
}

lineIndices->resize(lineIndex);

(*colors)[0] = DiamondColor;

gridGeometry->setVertexArray(vertices);
gridGeometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
gridGeometry->setColorArray(colors, osg::Array::BIND_OVERALL);
gridGeometry->addPrimitiveSet(pointIndices);
gridGeometry->addPrimitiveSet(lineIndices);

return gridGeometry;
}

PathgridGeometryFactory& PathgridGeometryFactory::get()
{
static PathgridGeometryFactory instance;
return instance;
}

PathgridGeometryFactory::PathgridGeometryFactory()
{
generateNormals();
}

void PathgridGeometryFactory::generateNormals()
{
mGeneratedNormals.resize(DiamondVertexCount);

for (unsigned short i = 0; i < DiamondVertexCount; i += 3)
{
osg::Vec3f v1 = DiamondPoints[DiamondIndices[i + 1]] - DiamondPoints[DiamondIndices[i]];
osg::Vec3f v2 = DiamondPoints[DiamondIndices[i + 2]] - DiamondPoints[DiamondIndices[i]];

osg::Vec3f normal = v1 ^ v2;

mGeneratedNormals[i] = normal;
mGeneratedNormals[i + 1] = normal;
mGeneratedNormals[i + 2] = normal;
}
}

void PathgridGeometryFactory::addPoint(unsigned short offset, const osg::Vec3f& position, osg::Vec3Array* vertices,
osg::Vec3Array* normals, osg::DrawElementsUShort* indices)
{
for (unsigned short i = 0; i < DiamondVertexCount; ++i)
{
(*vertices)[i + offset] = position + DiamondPoints[DiamondIndices[i]];
(*normals)[i + offset] = mGeneratedNormals[i];
indices->setElement(i + offset, i + offset);
}
}
}
39 changes: 39 additions & 0 deletions components/sceneutil/pathgridutil.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef OPENMW_COMPONENTS_PATHGRIDUTIL_H
#define OPENMW_COMPONENTS_PATHGRIDUTIL_H

#include <osg/ref_ptr>
#include <osg/Geometry>

namespace ESM
{
class Pathgrid;
}

namespace SceneUtil
{

class PathgridGeometryFactory
{
public:

osg::ref_ptr<osg::Geometry> create(const ESM::Pathgrid& pathgrid);
static PathgridGeometryFactory& get();

private:

PathgridGeometryFactory();

void generateNormals();

void addPoint(unsigned short offset, const osg::Vec3f& position, osg::Vec3Array* vertices,
osg::Vec3Array* normals, osg::DrawElementsUShort* indices);

// Not implemented
PathgridGeometryFactory(const PathgridGeometryFactory&);
PathgridGeometryFactory& operator=(const PathgridGeometryFactory&);

std::vector<osg::Vec3f> mGeneratedNormals;
};
}

#endif