mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
Support recast mesh rendering
This commit is contained in:
parent
f603daecdc
commit
7ae7cb181d
35 changed files with 418 additions and 67 deletions
|
@ -21,7 +21,7 @@ add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation rotatecontroller sky npcanimation
|
actors objects renderingmanager animation rotatecontroller sky npcanimation
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
renderbin actoranimation landmanager navmesh actorspaths
|
renderbin actoranimation landmanager navmesh actorspaths recastmesh
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
|
92
apps/openmw/mwrender/recastmesh.cpp
Normal file
92
apps/openmw/mwrender/recastmesh.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
53
apps/openmw/mwrender/recastmesh.hpp
Normal file
53
apps/openmw/mwrender/recastmesh.hpp
Normal file
|
@ -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
|
|
@ -66,6 +66,7 @@
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "navmesh.hpp"
|
#include "navmesh.hpp"
|
||||||
#include "actorspaths.hpp"
|
#include "actorspaths.hpp"
|
||||||
|
#include "recastmesh.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -260,6 +261,7 @@ namespace MWRender
|
||||||
|
|
||||||
mNavMesh.reset(new NavMesh(mRootNode, Settings::Manager::getBool("enable nav mesh render", "Navigator")));
|
mNavMesh.reset(new NavMesh(mRootNode, Settings::Manager::getBool("enable nav mesh render", "Navigator")));
|
||||||
mActorsPaths.reset(new ActorsPaths(mRootNode, Settings::Manager::getBool("enable agents paths render", "Navigator")));
|
mActorsPaths.reset(new ActorsPaths(mRootNode, Settings::Manager::getBool("enable agents paths render", "Navigator")));
|
||||||
|
mRecastMesh.reset(new RecastMesh(mRootNode, Settings::Manager::getBool("enable recast mesh render", "Navigator")));
|
||||||
mPathgrid.reset(new Pathgrid(mRootNode));
|
mPathgrid.reset(new Pathgrid(mRootNode));
|
||||||
|
|
||||||
mObjects.reset(new Objects(mResourceSystem, sceneRoot, mUnrefQueue.get()));
|
mObjects.reset(new Objects(mResourceSystem, sceneRoot, mUnrefQueue.get()));
|
||||||
|
@ -585,6 +587,10 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
return mActorsPaths->toggle();
|
return mActorsPaths->toggle();
|
||||||
}
|
}
|
||||||
|
else if (mode == Render_RecastMesh)
|
||||||
|
{
|
||||||
|
return mRecastMesh->toggle();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,6 +657,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNavMesh();
|
updateNavMesh();
|
||||||
|
updateRecastMesh();
|
||||||
|
|
||||||
mCamera->update(dt, paused);
|
mCamera->update(dt, paused);
|
||||||
|
|
||||||
|
@ -1463,4 +1470,12 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::updateRecastMesh()
|
||||||
|
{
|
||||||
|
if (!mRecastMesh->isEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mRecastMesh->update(mNavigator.getRecastMeshTiles(), mNavigator.getSettings());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace MWRender
|
||||||
class LandManager;
|
class LandManager;
|
||||||
class NavMesh;
|
class NavMesh;
|
||||||
class ActorsPaths;
|
class ActorsPaths;
|
||||||
|
class RecastMesh;
|
||||||
|
|
||||||
class RenderingManager : public MWRender::RenderingInterface
|
class RenderingManager : public MWRender::RenderingInterface
|
||||||
{
|
{
|
||||||
|
@ -246,6 +247,8 @@ namespace MWRender
|
||||||
|
|
||||||
void updateNavMesh();
|
void updateNavMesh();
|
||||||
|
|
||||||
|
void updateRecastMesh();
|
||||||
|
|
||||||
osg::ref_ptr<osgUtil::IntersectionVisitor> getIntersectionVisitor(osgUtil::Intersector* intersector, bool ignorePlayer, bool ignoreActors);
|
osg::ref_ptr<osgUtil::IntersectionVisitor> getIntersectionVisitor(osgUtil::Intersector* intersector, bool ignorePlayer, bool ignoreActors);
|
||||||
|
|
||||||
osg::ref_ptr<osgUtil::IntersectionVisitor> mIntersectionVisitor;
|
osg::ref_ptr<osgUtil::IntersectionVisitor> mIntersectionVisitor;
|
||||||
|
@ -264,6 +267,7 @@ namespace MWRender
|
||||||
std::unique_ptr<NavMesh> mNavMesh;
|
std::unique_ptr<NavMesh> mNavMesh;
|
||||||
std::size_t mNavMeshNumber = 0;
|
std::size_t mNavMeshNumber = 0;
|
||||||
std::unique_ptr<ActorsPaths> mActorsPaths;
|
std::unique_ptr<ActorsPaths> mActorsPaths;
|
||||||
|
std::unique_ptr<RecastMesh> mRecastMesh;
|
||||||
std::unique_ptr<Pathgrid> mPathgrid;
|
std::unique_ptr<Pathgrid> mPathgrid;
|
||||||
std::unique_ptr<Objects> mObjects;
|
std::unique_ptr<Objects> mObjects;
|
||||||
std::unique_ptr<Water> mWater;
|
std::unique_ptr<Water> mWater;
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace MWRender
|
||||||
Render_Scene,
|
Render_Scene,
|
||||||
Render_NavMesh,
|
Render_NavMesh,
|
||||||
Render_ActorsPaths,
|
Render_ActorsPaths,
|
||||||
|
Render_RecastMesh,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -463,5 +463,6 @@ op 0x200030c: RepairedOnMe
|
||||||
op 0x200030d: RepairedOnMe, explicit
|
op 0x200030d: RepairedOnMe, explicit
|
||||||
op 0x200030e: TestCells
|
op 0x200030e: TestCells
|
||||||
op 0x200030f: TestInteriorCells
|
op 0x200030f: TestInteriorCells
|
||||||
|
op 0x2000310: ToggleRecastMesh
|
||||||
|
|
||||||
opcodes 0x2000310-0x3ffffff unused
|
opcodes 0x2000311-0x3ffffff unused
|
||||||
|
|
|
@ -1440,6 +1440,20 @@ namespace MWScript
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OpToggleRecastMesh : public Interpreter::Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
|
{
|
||||||
|
bool enabled =
|
||||||
|
MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_RecastMesh);
|
||||||
|
|
||||||
|
runtime.getContext().report (enabled ?
|
||||||
|
"Recast Mesh Rendering -> On" : "Recast Mesh Rendering -> Off");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
|
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
|
||||||
|
@ -1545,6 +1559,7 @@ namespace MWScript
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeSetNavMeshNumberToRender, new OpSetNavMeshNumberToRender);
|
interpreter.installSegment5 (Compiler::Misc::opcodeSetNavMeshNumberToRender, new OpSetNavMeshNumberToRender);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeRepairedOnMe, new OpRepairedOnMe<ImplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeRepairedOnMe, new OpRepairedOnMe<ImplicitRef>);
|
||||||
interpreter.installSegment5 (Compiler::Misc::opcodeRepairedOnMeExplicit, new OpRepairedOnMe<ExplicitRef>);
|
interpreter.installSegment5 (Compiler::Misc::opcodeRepairedOnMeExplicit, new OpRepairedOnMe<ExplicitRef>);
|
||||||
|
interpreter.installSegment5 (Compiler::Misc::opcodeToggleRecastMesh, new OpToggleRecastMesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,15 @@ namespace
|
||||||
{
|
{
|
||||||
const osg::Vec3f mAgentHalfExtents {1, 2, 3};
|
const osg::Vec3f mAgentHalfExtents {1, 2, 3};
|
||||||
const TilePosition mTilePosition {0, 0};
|
const TilePosition mTilePosition {0, 0};
|
||||||
|
const std::size_t mGeneration = 0;
|
||||||
|
const std::size_t mRevision = 0;
|
||||||
const std::vector<int> mIndices {{0, 1, 2}};
|
const std::vector<int> mIndices {{0, 1, 2}};
|
||||||
const std::vector<float> mVertices {{0, 0, 0, 1, 0, 0, 1, 1, 0}};
|
const std::vector<float> mVertices {{0, 0, 0, 1, 0, 0, 1, 1, 0}};
|
||||||
const std::vector<AreaType> mAreaTypes {1, AreaType_ground};
|
const std::vector<AreaType> mAreaTypes {1, AreaType_ground};
|
||||||
const std::vector<RecastMesh::Water> mWater {};
|
const std::vector<RecastMesh::Water> mWater {};
|
||||||
const std::size_t mTrianglesPerChunk {1};
|
const std::size_t mTrianglesPerChunk {1};
|
||||||
const RecastMesh mRecastMesh {mIndices, mVertices, mAreaTypes, mWater, mTrianglesPerChunk};
|
const RecastMesh mRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, mWater, mTrianglesPerChunk};
|
||||||
const std::vector<OffMeshConnection> mOffMeshConnections {};
|
const std::vector<OffMeshConnection> mOffMeshConnections {};
|
||||||
unsigned char* const mData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
unsigned char* const mData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData mNavMeshData {mData, 1};
|
NavMeshData mNavMeshData {mData, 1};
|
||||||
|
@ -128,7 +131,8 @@ namespace
|
||||||
const std::size_t maxSize = 1;
|
const std::size_t maxSize = 1;
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh unexistentRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, water, mTrianglesPerChunk};
|
||||||
|
|
||||||
cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, mOffMeshConnections, std::move(mNavMeshData));
|
cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, mOffMeshConnections, std::move(mNavMeshData));
|
||||||
EXPECT_FALSE(cache.get(mAgentHalfExtents, mTilePosition, unexistentRecastMesh, mOffMeshConnections));
|
EXPECT_FALSE(cache.get(mAgentHalfExtents, mTilePosition, unexistentRecastMesh, mOffMeshConnections));
|
||||||
|
@ -142,7 +146,8 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh anotherRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, water, mTrianglesPerChunk};
|
||||||
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData anotherNavMeshData {anotherData, 1};
|
NavMeshData anotherNavMeshData {anotherData, 1};
|
||||||
|
|
||||||
|
@ -162,7 +167,8 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh anotherRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, water, mTrianglesPerChunk};
|
||||||
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData anotherNavMeshData {anotherData, 1};
|
NavMeshData anotherNavMeshData {anotherData, 1};
|
||||||
|
|
||||||
|
@ -180,14 +186,14 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> leastRecentlySetWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> leastRecentlySetWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh leastRecentlySetRecastMesh {mIndices, mVertices, mAreaTypes, leastRecentlySetWater,
|
const RecastMesh leastRecentlySetRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
mTrianglesPerChunk};
|
mAreaTypes, leastRecentlySetWater, mTrianglesPerChunk};
|
||||||
const auto leastRecentlySetData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto leastRecentlySetData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData leastRecentlySetNavMeshData {leastRecentlySetData, 1};
|
NavMeshData leastRecentlySetNavMeshData {leastRecentlySetData, 1};
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> mostRecentlySetWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> mostRecentlySetWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
||||||
const RecastMesh mostRecentlySetRecastMesh {mIndices, mVertices, mAreaTypes, mostRecentlySetWater,
|
const RecastMesh mostRecentlySetRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
mTrianglesPerChunk};
|
mAreaTypes, mostRecentlySetWater, mTrianglesPerChunk};
|
||||||
const auto mostRecentlySetData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto mostRecentlySetData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData mostRecentlySetNavMeshData {mostRecentlySetData, 1};
|
NavMeshData mostRecentlySetNavMeshData {mostRecentlySetData, 1};
|
||||||
|
|
||||||
|
@ -212,14 +218,14 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> leastRecentlyUsedWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> leastRecentlyUsedWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh leastRecentlyUsedRecastMesh {mIndices, mVertices, mAreaTypes, leastRecentlyUsedWater,
|
const RecastMesh leastRecentlyUsedRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
mTrianglesPerChunk};
|
mAreaTypes, leastRecentlyUsedWater, mTrianglesPerChunk};
|
||||||
const auto leastRecentlyUsedData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto leastRecentlyUsedData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData leastRecentlyUsedNavMeshData {leastRecentlyUsedData, 1};
|
NavMeshData leastRecentlyUsedNavMeshData {leastRecentlyUsedData, 1};
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> mostRecentlyUsedWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> mostRecentlyUsedWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
||||||
const RecastMesh mostRecentlyUsedRecastMesh {mIndices, mVertices, mAreaTypes, mostRecentlyUsedWater,
|
const RecastMesh mostRecentlyUsedRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
mTrianglesPerChunk};
|
mAreaTypes, mostRecentlyUsedWater, mTrianglesPerChunk};
|
||||||
const auto mostRecentlyUsedData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto mostRecentlyUsedData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData mostRecentlyUsedNavMeshData {mostRecentlyUsedData, 1};
|
NavMeshData mostRecentlyUsedNavMeshData {mostRecentlyUsedData, 1};
|
||||||
|
|
||||||
|
@ -256,7 +262,7 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh tooLargeRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
||||||
const auto tooLargeData = reinterpret_cast<unsigned char*>(dtAlloc(2, DT_ALLOC_PERM));
|
const auto tooLargeData = reinterpret_cast<unsigned char*>(dtAlloc(2, DT_ALLOC_PERM));
|
||||||
NavMeshData tooLargeNavMeshData {tooLargeData, 2};
|
NavMeshData tooLargeNavMeshData {tooLargeData, 2};
|
||||||
|
|
||||||
|
@ -275,12 +281,13 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> anotherWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> anotherWater {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh anotherRecastMesh {mIndices, mVertices, mAreaTypes, anotherWater, mTrianglesPerChunk};
|
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, anotherWater, mTrianglesPerChunk};
|
||||||
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData anotherNavMeshData {anotherData, 1};
|
NavMeshData anotherNavMeshData {anotherData, 1};
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> tooLargeWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> tooLargeWater {1, RecastMesh::Water {2, btTransform::getIdentity()}};
|
||||||
const RecastMesh tooLargeRecastMesh {mIndices, mVertices, mAreaTypes, tooLargeWater, mTrianglesPerChunk};
|
const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, tooLargeWater, mTrianglesPerChunk};
|
||||||
const auto tooLargeData = reinterpret_cast<unsigned char*>(dtAlloc(2, DT_ALLOC_PERM));
|
const auto tooLargeData = reinterpret_cast<unsigned char*>(dtAlloc(2, DT_ALLOC_PERM));
|
||||||
NavMeshData tooLargeNavMeshData {tooLargeData, 2};
|
NavMeshData tooLargeNavMeshData {tooLargeData, 2};
|
||||||
|
|
||||||
|
@ -303,7 +310,8 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh anotherRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices,
|
||||||
|
mAreaTypes, water, mTrianglesPerChunk};
|
||||||
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData anotherNavMeshData {anotherData, 1};
|
NavMeshData anotherNavMeshData {anotherData, 1};
|
||||||
|
|
||||||
|
@ -326,7 +334,7 @@ namespace
|
||||||
NavMeshTilesCache cache(maxSize);
|
NavMeshTilesCache cache(maxSize);
|
||||||
|
|
||||||
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
const std::vector<RecastMesh::Water> water {1, RecastMesh::Water {1, btTransform::getIdentity()}};
|
||||||
const RecastMesh anotherRecastMesh {mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
const RecastMesh anotherRecastMesh {mGeneration, mRevision, mIndices, mVertices, mAreaTypes, water, mTrianglesPerChunk};
|
||||||
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
const auto anotherData = reinterpret_cast<unsigned char*>(dtAlloc(1, DT_ALLOC_PERM));
|
||||||
NavMeshData anotherNavMeshData {anotherData, 1};
|
NavMeshData anotherNavMeshData {anotherData, 1};
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace
|
||||||
{
|
{
|
||||||
Settings mSettings;
|
Settings mSettings;
|
||||||
TileBounds mBounds;
|
TileBounds mBounds;
|
||||||
|
const std::size_t mGeneration = 0;
|
||||||
|
const std::size_t mRevision = 0;
|
||||||
|
|
||||||
DetourNavigatorRecastMeshBuilderTest()
|
DetourNavigatorRecastMeshBuilderTest()
|
||||||
{
|
{
|
||||||
|
@ -45,7 +47,7 @@ namespace
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_return_empty)
|
||||||
{
|
{
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
||||||
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>());
|
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>());
|
||||||
|
@ -59,7 +61,7 @@ namespace
|
||||||
|
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -80,7 +82,7 @@ namespace
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
0, 3, 4,
|
0, 3, 4,
|
||||||
|
@ -96,7 +98,7 @@ namespace
|
||||||
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-0.5, 0, -0.5,
|
-0.5, 0, -0.5,
|
||||||
-0.5, 0, 0.5,
|
-0.5, 0, 0.5,
|
||||||
|
@ -114,7 +116,7 @@ namespace
|
||||||
btBoxShape shape(btVector3(1, 1, 2));
|
btBoxShape shape(btVector3(1, 1, 2));
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), AreaType_ground);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 2, 1,
|
1, 2, 1,
|
||||||
-1, 2, 1,
|
-1, 2, 1,
|
||||||
|
@ -161,7 +163,7 @@ namespace
|
||||||
btTransform::getIdentity(),
|
btTransform::getIdentity(),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -210,7 +212,7 @@ namespace
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
0, 3, 4,
|
0, 3, 4,
|
||||||
|
@ -234,7 +236,7 @@ namespace
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
3, 12, 2,
|
3, 12, 2,
|
||||||
1, 12, 10,
|
1, 12, 10,
|
||||||
|
@ -256,7 +258,7 @@ namespace
|
||||||
btTransform::getIdentity(),
|
btTransform::getIdentity(),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -284,7 +286,7 @@ namespace
|
||||||
btTransform::getIdentity(),
|
btTransform::getIdentity(),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-0.2f, 0, -0.3f,
|
-0.2f, 0, -0.3f,
|
||||||
-0.3f, 0, -0.2f,
|
-0.3f, 0, -0.2f,
|
||||||
|
@ -309,7 +311,7 @@ namespace
|
||||||
static_cast<btScalar>(-osg::PI_4))),
|
static_cast<btScalar>(-osg::PI_4))),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
0, -0.70710659027099609375, -3.535533905029296875,
|
0, -0.70710659027099609375, -3.535533905029296875,
|
||||||
0, 0.707107067108154296875, -3.535533905029296875,
|
0, 0.707107067108154296875, -3.535533905029296875,
|
||||||
|
@ -334,7 +336,7 @@ namespace
|
||||||
static_cast<btScalar>(osg::PI_4))),
|
static_cast<btScalar>(osg::PI_4))),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-3.535533905029296875, -0.70710659027099609375, 0,
|
-3.535533905029296875, -0.70710659027099609375, 0,
|
||||||
-3.535533905029296875, 0.707107067108154296875, 0,
|
-3.535533905029296875, 0.707107067108154296875, 0,
|
||||||
|
@ -359,7 +361,7 @@ namespace
|
||||||
static_cast<btScalar>(osg::PI_4))),
|
static_cast<btScalar>(osg::PI_4))),
|
||||||
AreaType_ground
|
AreaType_ground
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
||||||
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
||||||
|
@ -388,7 +390,7 @@ namespace
|
||||||
btTransform::getIdentity(),
|
btTransform::getIdentity(),
|
||||||
AreaType_null
|
AreaType_null
|
||||||
);
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
-1, 0, 1,
|
-1, 0, 1,
|
||||||
|
@ -405,7 +407,7 @@ namespace
|
||||||
{
|
{
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addWater(1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300)));
|
builder.addWater(1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300)));
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create(mGeneration, mRevision);
|
||||||
EXPECT_EQ(recastMesh->getWater(), std::vector<RecastMesh::Water>({
|
EXPECT_EQ(recastMesh->getWater(), std::vector<RecastMesh::Water>({
|
||||||
RecastMesh::Water {1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300))}
|
RecastMesh::Water {1000, btTransform(btMatrix3x3::getIdentity(), btVector3(100, 200, 300))}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -51,7 +51,7 @@ add_component_dir (shader
|
||||||
add_component_dir (sceneutil
|
add_component_dir (sceneutil
|
||||||
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
||||||
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer
|
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer
|
||||||
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique vismask
|
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique vismask recastmesh
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (nif
|
add_component_dir (nif
|
||||||
|
|
|
@ -327,6 +327,7 @@ namespace Compiler
|
||||||
extensions.registerInstruction ("toggleactorspaths", "", opcodeToggleActorsPaths);
|
extensions.registerInstruction ("toggleactorspaths", "", opcodeToggleActorsPaths);
|
||||||
extensions.registerInstruction ("setnavmeshnumber", "l", opcodeSetNavMeshNumberToRender);
|
extensions.registerInstruction ("setnavmeshnumber", "l", opcodeSetNavMeshNumberToRender);
|
||||||
extensions.registerFunction ("repairedonme", 'l', "S", opcodeRepairedOnMe, opcodeRepairedOnMeExplicit);
|
extensions.registerFunction ("repairedonme", 'l', "S", opcodeRepairedOnMe, opcodeRepairedOnMeExplicit);
|
||||||
|
extensions.registerInstruction ("togglerecastmesh", "", opcodeToggleRecastMesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -304,6 +304,7 @@ namespace Compiler
|
||||||
const int opcodeSetNavMeshNumberToRender = 0x200030a;
|
const int opcodeSetNavMeshNumberToRender = 0x200030a;
|
||||||
const int opcodeRepairedOnMe = 0x200030c;
|
const int opcodeRepairedOnMe = 0x200030c;
|
||||||
const int opcodeRepairedOnMeExplicit = 0x200030d;
|
const int opcodeRepairedOnMeExplicit = 0x200030d;
|
||||||
|
const int opcodeToggleRecastMesh = 0x2000310;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Sky
|
namespace Sky
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds,
|
||||||
: mImpl(settings, bounds)
|
std::size_t generation)
|
||||||
|
: mImpl(settings, bounds, generation)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool CachedRecastMeshManager::addObject(const ObjectId id, const btCollisionShape& shape,
|
bool CachedRecastMeshManager::addObject(const ObjectId id, const btCollisionShape& shape,
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace DetourNavigator
|
||||||
class CachedRecastMeshManager
|
class CachedRecastMeshManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation);
|
||||||
|
|
||||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType);
|
const AreaType areaType);
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
#include "objectid.hpp"
|
#include "objectid.hpp"
|
||||||
#include "navmeshcacheitem.hpp"
|
#include "navmeshcacheitem.hpp"
|
||||||
|
#include "recastmesh.hpp"
|
||||||
|
#include "recastmeshtiles.hpp"
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
|
@ -204,6 +206,8 @@ namespace DetourNavigator
|
||||||
*/
|
*/
|
||||||
boost::optional<osg::Vec3f> findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents,
|
boost::optional<osg::Vec3f> findRandomPointAroundCircle(const osg::Vec3f& agentHalfExtents,
|
||||||
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const;
|
const osg::Vec3f& start, const float maxRadius, const Flags includeFlags) const;
|
||||||
|
|
||||||
|
virtual RecastMeshTiles getRecastMeshTiles() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,11 @@ namespace DetourNavigator
|
||||||
mNavMeshManager.reportStats(frameNumber, stats);
|
mNavMeshManager.reportStats(frameNumber, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecastMeshTiles NavigatorImpl::getRecastMeshTiles()
|
||||||
|
{
|
||||||
|
return mNavMeshManager.getRecastMeshTiles();
|
||||||
|
}
|
||||||
|
|
||||||
void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId)
|
void NavigatorImpl::updateAvoidShapeId(const ObjectId id, const ObjectId avoidId)
|
||||||
{
|
{
|
||||||
updateId(id, avoidId, mWaterIds);
|
updateId(id, avoidId, mWaterIds);
|
||||||
|
|
|
@ -50,6 +50,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
|
||||||
|
|
||||||
|
RecastMeshTiles getRecastMeshTiles() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Settings mSettings;
|
Settings mSettings;
|
||||||
NavMeshManager mNavMeshManager;
|
NavMeshManager mNavMeshManager;
|
||||||
|
|
|
@ -81,6 +81,11 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void reportStats(unsigned int /*frameNumber*/, osg::Stats& /*stats*/) const override {}
|
void reportStats(unsigned int /*frameNumber*/, osg::Stats& /*stats*/) const override {}
|
||||||
|
|
||||||
|
RecastMeshTiles getRecastMeshTiles() override
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Settings mDefaultSettings {};
|
Settings mDefaultSettings {};
|
||||||
SharedNavMeshCacheItem mEmptyNavMeshCacheItem;
|
SharedNavMeshCacheItem mEmptyNavMeshCacheItem;
|
||||||
|
|
|
@ -220,6 +220,17 @@ namespace DetourNavigator
|
||||||
mAsyncNavMeshUpdater.reportStats(frameNumber, stats);
|
mAsyncNavMeshUpdater.reportStats(frameNumber, stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecastMeshTiles NavMeshManager::getRecastMeshTiles()
|
||||||
|
{
|
||||||
|
std::vector<TilePosition> tiles;
|
||||||
|
mRecastMeshManager.forEachTilePosition(
|
||||||
|
[&tiles] (const TilePosition& tile) { tiles.push_back(tile); });
|
||||||
|
RecastMeshTiles result;
|
||||||
|
std::transform(tiles.begin(), tiles.end(), std::inserter(result, result.end()),
|
||||||
|
[this] (const TilePosition& tile) { return std::make_pair(tile, mRecastMeshManager.getMesh(tile)); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
|
void NavMeshManager::addChangedTiles(const btCollisionShape& shape, const btTransform& transform,
|
||||||
const ChangeType changeType)
|
const ChangeType changeType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "cachedrecastmeshmanager.hpp"
|
#include "cachedrecastmeshmanager.hpp"
|
||||||
#include "offmeshconnectionsmanager.hpp"
|
#include "offmeshconnectionsmanager.hpp"
|
||||||
#include "sharednavmesh.hpp"
|
#include "sharednavmesh.hpp"
|
||||||
|
#include "recastmeshtiles.hpp"
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
|
|
||||||
|
@ -52,6 +53,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
|
|
||||||
|
RecastMeshTiles getRecastMeshTiles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Settings& mSettings;
|
const Settings& mSettings;
|
||||||
TileCachedRecastMeshManager mRecastMeshManager;
|
TileCachedRecastMeshManager mRecastMeshManager;
|
||||||
|
|
|
@ -5,9 +5,11 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastMesh::RecastMesh(std::vector<int> indices, std::vector<float> vertices, std::vector<AreaType> areaTypes,
|
RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, std::vector<int> indices, std::vector<float> vertices,
|
||||||
std::vector<Water> water, const std::size_t trianglesPerChunk)
|
std::vector<AreaType> areaTypes, std::vector<Water> water, const std::size_t trianglesPerChunk)
|
||||||
: mIndices(std::move(indices))
|
: mGeneration(generation)
|
||||||
|
, mRevision(revision)
|
||||||
|
, mIndices(std::move(indices))
|
||||||
, mVertices(std::move(vertices))
|
, mVertices(std::move(vertices))
|
||||||
, mAreaTypes(std::move(areaTypes))
|
, mAreaTypes(std::move(areaTypes))
|
||||||
, mWater(std::move(water))
|
, mWater(std::move(water))
|
||||||
|
|
|
@ -24,8 +24,18 @@ namespace DetourNavigator
|
||||||
btTransform mTransform;
|
btTransform mTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
RecastMesh(std::vector<int> indices, std::vector<float> vertices, std::vector<AreaType> areaTypes,
|
RecastMesh(std::size_t generation, std::size_t revision, std::vector<int> indices, std::vector<float> vertices,
|
||||||
std::vector<Water> water, const std::size_t trianglesPerChunk);
|
std::vector<AreaType> areaTypes, std::vector<Water> water, const std::size_t trianglesPerChunk);
|
||||||
|
|
||||||
|
std::size_t getGeneration() const
|
||||||
|
{
|
||||||
|
return mGeneration;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t getRevision() const
|
||||||
|
{
|
||||||
|
return mRevision;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<int>& getIndices() const
|
const std::vector<int>& getIndices() const
|
||||||
{
|
{
|
||||||
|
@ -68,6 +78,8 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::size_t mGeneration;
|
||||||
|
std::size_t mRevision;
|
||||||
std::vector<int> mIndices;
|
std::vector<int> mIndices;
|
||||||
std::vector<float> mVertices;
|
std::vector<float> mVertices;
|
||||||
std::vector<AreaType> mAreaTypes;
|
std::vector<AreaType> mAreaTypes;
|
||||||
|
|
|
@ -112,9 +112,10 @@ namespace DetourNavigator
|
||||||
mWater.push_back(RecastMesh::Water {cellSize, transform});
|
mWater.push_back(RecastMesh::Water {cellSize, transform});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> RecastMeshBuilder::create() const
|
std::shared_ptr<RecastMesh> RecastMeshBuilder::create(std::size_t generation, std::size_t revision) const
|
||||||
{
|
{
|
||||||
return std::make_shared<RecastMesh>(mIndices, mVertices, mAreaTypes, mWater, mSettings.get().mTrianglesPerChunk);
|
return std::make_shared<RecastMesh>(generation, revision, mIndices, mVertices, mAreaTypes,
|
||||||
|
mWater, mSettings.get().mTrianglesPerChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::reset()
|
void RecastMeshBuilder::reset()
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void addWater(const int mCellSize, const btTransform& transform);
|
void addWater(const int mCellSize, const btTransform& transform);
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> create() const;
|
std::shared_ptr<RecastMesh> create(std::size_t generation, std::size_t revision) const;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastMeshManager::RecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
RecastMeshManager::RecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation)
|
||||||
: mShouldRebuild(false)
|
: mGeneration(generation)
|
||||||
, mMeshBuilder(settings, bounds)
|
, mMeshBuilder(settings, bounds)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ namespace DetourNavigator
|
||||||
mObjectsOrder.erase(iterator);
|
mObjectsOrder.erase(iterator);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mShouldRebuild = true;
|
++mRevision;
|
||||||
return mShouldRebuild;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecastMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType)
|
bool RecastMeshManager::updateObject(const ObjectId id, const btTransform& transform, const AreaType areaType)
|
||||||
|
@ -30,8 +30,8 @@ namespace DetourNavigator
|
||||||
return false;
|
return false;
|
||||||
if (!object->second->update(transform, areaType))
|
if (!object->second->update(transform, areaType))
|
||||||
return false;
|
return false;
|
||||||
mShouldRebuild = true;
|
++mRevision;
|
||||||
return mShouldRebuild;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<RemovedRecastMeshObject> RecastMeshManager::removeObject(const ObjectId id)
|
boost::optional<RemovedRecastMeshObject> RecastMeshManager::removeObject(const ObjectId id)
|
||||||
|
@ -42,7 +42,7 @@ namespace DetourNavigator
|
||||||
const RemovedRecastMeshObject result {object->second->getShape(), object->second->getTransform()};
|
const RemovedRecastMeshObject result {object->second->getShape(), object->second->getTransform()};
|
||||||
mObjectsOrder.erase(object->second);
|
mObjectsOrder.erase(object->second);
|
||||||
mObjects.erase(object);
|
mObjects.erase(object);
|
||||||
mShouldRebuild = true;
|
++mRevision;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ namespace DetourNavigator
|
||||||
mWaterOrder.erase(iterator);
|
mWaterOrder.erase(iterator);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mShouldRebuild = true;
|
++mRevision;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ namespace DetourNavigator
|
||||||
const auto water = mWater.find(cellPosition);
|
const auto water = mWater.find(cellPosition);
|
||||||
if (water == mWater.end())
|
if (water == mWater.end())
|
||||||
return boost::none;
|
return boost::none;
|
||||||
mShouldRebuild = true;
|
++mRevision;
|
||||||
const auto result = *water->second;
|
const auto result = *water->second;
|
||||||
mWaterOrder.erase(water->second);
|
mWaterOrder.erase(water->second);
|
||||||
mWater.erase(water);
|
mWater.erase(water);
|
||||||
|
@ -74,7 +74,7 @@ namespace DetourNavigator
|
||||||
std::shared_ptr<RecastMesh> RecastMeshManager::getMesh()
|
std::shared_ptr<RecastMesh> RecastMeshManager::getMesh()
|
||||||
{
|
{
|
||||||
rebuild();
|
rebuild();
|
||||||
return mMeshBuilder.create();
|
return mMeshBuilder.create(mGeneration, mLastBuildRevision);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecastMeshManager::isEmpty() const
|
bool RecastMeshManager::isEmpty() const
|
||||||
|
@ -84,13 +84,13 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void RecastMeshManager::rebuild()
|
void RecastMeshManager::rebuild()
|
||||||
{
|
{
|
||||||
if (!mShouldRebuild)
|
if (mLastBuildRevision == mRevision)
|
||||||
return;
|
return;
|
||||||
mMeshBuilder.reset();
|
mMeshBuilder.reset();
|
||||||
for (const auto& v : mWaterOrder)
|
for (const auto& v : mWaterOrder)
|
||||||
mMeshBuilder.addWater(v.mCellSize, v.mTransform);
|
mMeshBuilder.addWater(v.mCellSize, v.mTransform);
|
||||||
for (const auto& v : mObjectsOrder)
|
for (const auto& v : mObjectsOrder)
|
||||||
mMeshBuilder.addObject(v.getShape(), v.getTransform(), v.getAreaType());
|
mMeshBuilder.addObject(v.getShape(), v.getTransform(), v.getAreaType());
|
||||||
mShouldRebuild = false;
|
mLastBuildRevision = mRevision;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace DetourNavigator
|
||||||
btTransform mTransform;
|
btTransform mTransform;
|
||||||
};
|
};
|
||||||
|
|
||||||
RecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
RecastMeshManager(const Settings& settings, const TileBounds& bounds, std::size_t generation);
|
||||||
|
|
||||||
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
bool addObject(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType);
|
const AreaType areaType);
|
||||||
|
@ -52,7 +52,9 @@ namespace DetourNavigator
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mShouldRebuild;
|
std::size_t mRevision = 0;
|
||||||
|
std::size_t mLastBuildRevision = 0;
|
||||||
|
std::size_t mGeneration;
|
||||||
RecastMeshBuilder mMeshBuilder;
|
RecastMeshBuilder mMeshBuilder;
|
||||||
std::list<RecastMeshObject> mObjectsOrder;
|
std::list<RecastMeshObject> mObjectsOrder;
|
||||||
std::unordered_map<ObjectId, std::list<RecastMeshObject>::iterator> mObjects;
|
std::unordered_map<ObjectId, std::list<RecastMeshObject>::iterator> mObjects;
|
||||||
|
|
15
components/detournavigator/recastmeshtiles.hpp
Normal file
15
components/detournavigator/recastmeshtiles.hpp
Normal file
|
@ -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
|
|
@ -121,7 +121,7 @@ namespace DetourNavigator
|
||||||
tileBounds.mMin -= osg::Vec2f(border, border);
|
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||||
tileBounds.mMax += osg::Vec2f(border, border);
|
tileBounds.mMax += osg::Vec2f(border, border);
|
||||||
tile = tiles->insert(std::make_pair(tilePosition,
|
tile = tiles->insert(std::make_pair(tilePosition,
|
||||||
CachedRecastMeshManager(mSettings, tileBounds))).first;
|
CachedRecastMeshManager(mSettings, tileBounds, mTilesGeneration))).first;
|
||||||
}
|
}
|
||||||
if (tile->second.addWater(cellPosition, cellSize, transform))
|
if (tile->second.addWater(cellPosition, cellSize, transform))
|
||||||
{
|
{
|
||||||
|
@ -151,7 +151,10 @@ namespace DetourNavigator
|
||||||
continue;
|
continue;
|
||||||
const auto tileResult = tile->second.removeWater(cellPosition);
|
const auto tileResult = tile->second.removeWater(cellPosition);
|
||||||
if (tile->second.isEmpty())
|
if (tile->second.isEmpty())
|
||||||
|
{
|
||||||
tiles->erase(tile);
|
tiles->erase(tile);
|
||||||
|
++mTilesGeneration;
|
||||||
|
}
|
||||||
if (tileResult && !result)
|
if (tileResult && !result)
|
||||||
result = tileResult;
|
result = tileResult;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +192,8 @@ namespace DetourNavigator
|
||||||
auto tileBounds = makeTileBounds(mSettings, tilePosition);
|
auto tileBounds = makeTileBounds(mSettings, tilePosition);
|
||||||
tileBounds.mMin -= osg::Vec2f(border, border);
|
tileBounds.mMin -= osg::Vec2f(border, border);
|
||||||
tileBounds.mMax += osg::Vec2f(border, border);
|
tileBounds.mMax += osg::Vec2f(border, border);
|
||||||
tile = tiles.insert(std::make_pair(tilePosition, CachedRecastMeshManager(mSettings, tileBounds))).first;
|
tile = tiles.insert(std::make_pair(
|
||||||
|
tilePosition, CachedRecastMeshManager(mSettings, tileBounds, mTilesGeneration))).first;
|
||||||
}
|
}
|
||||||
return tile->second.addObject(id, shape, transform, areaType);
|
return tile->second.addObject(id, shape, transform, areaType);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +213,10 @@ namespace DetourNavigator
|
||||||
return boost::optional<RemovedRecastMeshObject>();
|
return boost::optional<RemovedRecastMeshObject>();
|
||||||
const auto tileResult = tile->second.removeObject(id);
|
const auto tileResult = tile->second.removeObject(id);
|
||||||
if (tile->second.isEmpty())
|
if (tile->second.isEmpty())
|
||||||
|
{
|
||||||
tiles.erase(tile);
|
tiles.erase(tile);
|
||||||
|
++mTilesGeneration;
|
||||||
|
}
|
||||||
return tileResult;
|
return tileResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace DetourNavigator
|
||||||
std::unordered_map<ObjectId, std::set<TilePosition>> mObjectsTilesPositions;
|
std::unordered_map<ObjectId, std::set<TilePosition>> mObjectsTilesPositions;
|
||||||
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
|
||||||
std::size_t mRevision = 0;
|
std::size_t mRevision = 0;
|
||||||
|
std::size_t mTilesGeneration = 0;
|
||||||
|
|
||||||
bool addTile(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
bool addTile(const ObjectId id, const btCollisionShape& shape, const btTransform& transform,
|
||||||
const AreaType areaType, const TilePosition& tilePosition, float border,
|
const AreaType areaType, const TilePosition& tilePosition, float border,
|
||||||
|
|
|
@ -50,10 +50,8 @@ namespace SceneUtil
|
||||||
mDepthMask = state;
|
mDepthMask = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDraw::texture(bool state)
|
void DebugDraw::texture(bool)
|
||||||
{
|
{
|
||||||
if (state)
|
|
||||||
throw std::logic_error("DebugDraw does not support textures (at " __FILE__ ":" OPENMW_LINE_STRING ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDraw::begin(osg::PrimitiveSet::Mode mode, float size)
|
void DebugDraw::begin(osg::PrimitiveSet::Mode mode, float size)
|
||||||
|
@ -85,9 +83,10 @@ namespace SceneUtil
|
||||||
vertex(pos[0], pos[1], pos[2], color, uv[0], uv[1]);
|
vertex(pos[0], pos[1], pos[2], color, uv[0], uv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDraw::vertex(const float, const float, const float, unsigned, const float, const float)
|
void DebugDraw::vertex(const float x, const float y, const float z, unsigned color, const float, const float)
|
||||||
{
|
{
|
||||||
throw std::logic_error("Not implemented (at " __FILE__ ":" OPENMW_LINE_STRING ")");
|
addVertex(osg::Vec3f(x, y, z));
|
||||||
|
addColor(SceneUtil::colourFromRGBA(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugDraw::end()
|
void DebugDraw::end()
|
||||||
|
|
48
components/sceneutil/recastmesh.cpp
Normal file
48
components/sceneutil/recastmesh.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
23
components/sceneutil/recastmesh.hpp
Normal file
23
components/sceneutil/recastmesh.hpp
Normal file
|
@ -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
|
|
@ -166,6 +166,20 @@ Make visible all NPC's and creaure's plans where they are going.
|
||||||
Works even if Navigator is disabled.
|
Works even if Navigator is disabled.
|
||||||
Potentially decreases performance.
|
Potentially decreases performance.
|
||||||
|
|
||||||
|
enable recast mesh render
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: False
|
||||||
|
|
||||||
|
Render recast mesh that is built as set of culled tiles from physical mesh.
|
||||||
|
Should show similar mesh to physical one.
|
||||||
|
Little difference can be a result of floating point error.
|
||||||
|
Absent pieces usually mean a bug in recast mesh tiles building.
|
||||||
|
Allows to do in-game debug.
|
||||||
|
Potentially decreases performance.
|
||||||
|
|
||||||
Expert settings
|
Expert settings
|
||||||
***************
|
***************
|
||||||
|
|
||||||
|
|
|
@ -748,6 +748,9 @@ enable nav mesh render = false
|
||||||
# Render agents paths (true, false)
|
# Render agents paths (true, false)
|
||||||
enable agents paths render = false
|
enable agents paths render = false
|
||||||
|
|
||||||
|
# Render recast mesh (true, false)
|
||||||
|
enable recast mesh render = false
|
||||||
|
|
||||||
# Max number of navmesh tiles (value >= 0)
|
# Max number of navmesh tiles (value >= 0)
|
||||||
max tiles number = 512
|
max tiles number = 512
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue