mirror of https://github.com/OpenMW/openmw.git
Support recast mesh rendering
parent
f603daecdc
commit
7ae7cb181d
@ -0,0 +1,92 @@
|
||||
#include "recastmesh.hpp"
|
||||
|
||||
#include <components/sceneutil/vismask.hpp>
|
||||
#include <components/sceneutil/recastmesh.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
RecastMesh::RecastMesh(const osg::ref_ptr<osg::Group>& root, bool enabled)
|
||||
: mRootNode(root)
|
||||
, mEnabled(enabled)
|
||||
{
|
||||
}
|
||||
|
||||
RecastMesh::~RecastMesh()
|
||||
{
|
||||
if (mEnabled)
|
||||
disable();
|
||||
}
|
||||
|
||||
bool RecastMesh::toggle()
|
||||
{
|
||||
if (mEnabled)
|
||||
disable();
|
||||
else
|
||||
enable();
|
||||
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
void RecastMesh::update(const DetourNavigator::RecastMeshTiles& tiles, const DetourNavigator::Settings& settings)
|
||||
{
|
||||
if (!mEnabled)
|
||||
return;
|
||||
|
||||
for (auto it = mGroups.begin(); it != mGroups.end();)
|
||||
{
|
||||
const auto tile = tiles.find(it->first);
|
||||
if (tile == tiles.end())
|
||||
{
|
||||
mRootNode->removeChild(it->second.mValue);
|
||||
it = mGroups.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (it->second.mGeneration != tile->second->getGeneration()
|
||||
|| it->second.mRevision != tile->second->getRevision())
|
||||
{
|
||||
const auto group = SceneUtil::createRecastMeshGroup(*tile->second, settings);
|
||||
group->setNodeMask(SceneUtil::Mask_Debug);
|
||||
mRootNode->removeChild(it->second.mValue);
|
||||
mRootNode->addChild(group);
|
||||
it->second.mValue = group;
|
||||
it->second.mGeneration = tile->second->getGeneration();
|
||||
it->second.mRevision = tile->second->getRevision();
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
for (const auto& tile : tiles)
|
||||
{
|
||||
if (mGroups.count(tile.first))
|
||||
continue;
|
||||
const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings);
|
||||
group->setNodeMask(SceneUtil::Mask_Debug);
|
||||
mGroups.emplace(tile.first, Group {tile.second->getGeneration(), tile.second->getRevision(), group});
|
||||
mRootNode->addChild(group);
|
||||
}
|
||||
}
|
||||
|
||||
void RecastMesh::reset()
|
||||
{
|
||||
std::for_each(mGroups.begin(), mGroups.end(), [&] (const auto& v) { mRootNode->removeChild(v.second.mValue); });
|
||||
mGroups.clear();
|
||||
}
|
||||
|
||||
void RecastMesh::enable()
|
||||
{
|
||||
std::for_each(mGroups.begin(), mGroups.end(), [&] (const auto& v) { mRootNode->addChild(v.second.mValue); });
|
||||
mEnabled = true;
|
||||
}
|
||||
|
||||
void RecastMesh::disable()
|
||||
{
|
||||
std::for_each(mGroups.begin(), mGroups.end(), [&] (const auto& v) { mRootNode->removeChild(v.second.mValue); });
|
||||
mEnabled = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
#ifndef OPENMW_MWRENDER_RECASTMESH_H
|
||||
#define OPENMW_MWRENDER_RECASTMESH_H
|
||||
|
||||
#include <components/detournavigator/navigator.hpp>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Geometry;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class RecastMesh
|
||||
{
|
||||
public:
|
||||
RecastMesh(const osg::ref_ptr<osg::Group>& root, bool enabled);
|
||||
~RecastMesh();
|
||||
|
||||
bool toggle();
|
||||
|
||||
void update(const DetourNavigator::RecastMeshTiles& recastMeshTiles, const DetourNavigator::Settings& settings);
|
||||
|
||||
void reset();
|
||||
|
||||
void enable();
|
||||
|
||||
void disable();
|
||||
|
||||
bool isEnabled() const
|
||||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Group
|
||||
{
|
||||
std::size_t mGeneration;
|
||||
std::size_t mRevision;
|
||||
osg::ref_ptr<osg::Group> mValue;
|
||||
};
|
||||
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
bool mEnabled;
|
||||
std::map<DetourNavigator::TilePosition, Group> mGroups;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHTILE_H
|
||||
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHTILE_H
|
||||
|
||||
#include "tileposition.hpp"
|
||||
#include "recastmesh.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
using RecastMeshTiles = std::map<TilePosition, std::shared_ptr<RecastMesh>>;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,48 @@
|
||||
#include "navmesh.hpp"
|
||||
#include "detourdebugdraw.hpp"
|
||||
|
||||
#include <components/detournavigator/settings.hpp>
|
||||
#include <components/detournavigator/recastmesh.hpp>
|
||||
|
||||
#include <RecastDebugDraw.h>
|
||||
|
||||
#include <osg/Group>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::vector<float> calculateNormals(const std::vector<float>& vertices, const std::vector<int>& indices)
|
||||
{
|
||||
std::vector<float> result(indices.size());
|
||||
for (std::size_t i = 0, n = indices.size(); i < n; i += 3)
|
||||
{
|
||||
const float* v0_ptr = &vertices[indices[i] * 3];
|
||||
const float* v1_ptr = &vertices[indices[i + 1] * 3];
|
||||
const float* v2_ptr = &vertices[indices[i + 2] * 3];
|
||||
const osg::Vec3f v0(v0_ptr[0], v0_ptr[1], v0_ptr[2]);
|
||||
const osg::Vec3f v1(v1_ptr[0], v1_ptr[1], v1_ptr[2]);
|
||||
const osg::Vec3f v2(v2_ptr[0], v2_ptr[1], v2_ptr[2]);
|
||||
const osg::Vec3f e0 = v1 - v0;
|
||||
const osg::Vec3f e1 = v2 - v0;
|
||||
osg::Vec3f normal = e0 ^ e1;
|
||||
normal.normalize();
|
||||
for (std::size_t j = 0; j < 3; ++j)
|
||||
result[i + j] = normal[j];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
||||
const DetourNavigator::Settings& settings)
|
||||
{
|
||||
const osg::ref_ptr<osg::Group> group(new osg::Group);
|
||||
DebugDraw debugDraw(*group, osg::Vec3f(0, 0, 0), 1.0f / settings.mRecastScaleFactor);
|
||||
const auto normals = calculateNormals(recastMesh.getVertices(), recastMesh.getIndices());
|
||||
const auto texScale = 1.0f / (settings.mCellSize * 10.0f);
|
||||
duDebugDrawTriMesh(&debugDraw, recastMesh.getVertices().data(), recastMesh.getVerticesCount(),
|
||||
recastMesh.getIndices().data(), normals.data(), recastMesh.getTrianglesCount(), nullptr, texScale);
|
||||
return group;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
#ifndef OPENMW_COMPONENTS_SCENEUTIL_RECASTMESH_H
|
||||
#define OPENMW_COMPONENTS_SCENEUTIL_RECASTMESH_H
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
}
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
class RecastMesh;
|
||||
struct Settings;
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
osg::ref_ptr<osg::Group> createRecastMeshGroup(const DetourNavigator::RecastMesh& recastMesh,
|
||||
const DetourNavigator::Settings& settings);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue