1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-30 06:15:32 +00:00

Add command and settings option to enable actors paths render

This commit is contained in:
elsid 2018-07-21 13:37:02 +03:00
parent c95cea414c
commit dc09674362
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
21 changed files with 334 additions and 8 deletions

View file

@ -21,7 +21,7 @@ add_openmw_dir (mwrender
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
renderbin actoranimation landmanager navmesh
renderbin actoranimation landmanager navmesh actorspaths
)
add_openmw_dir (mwinput

View file

@ -4,6 +4,7 @@
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <components/esm/cellid.hpp>
@ -597,6 +598,9 @@ namespace MWBase
virtual void preloadEffects(const ESM::EffectList* effectList) = 0;
virtual DetourNavigator::Navigator* getNavigator() const = 0;
virtual void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const = 0;
};
}

View file

@ -5,6 +5,7 @@
#include <components/esm/loadcell.hpp>
#include <components/esm/loadland.hpp>
#include <components/esm/loadmgef.hpp>
#include <components/detournavigator/navigator.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
@ -102,6 +103,12 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
const ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
{
const auto halfExtents = MWBase::Environment::get().getWorld()->getHalfExtents(actor);
MWBase::Environment::get().getWorld()->updateActorPath(actor, mPathFinder.getPath(), halfExtents,
pos.asVec3(), dest);
}
/// Stops the actor when it gets too close to a unloaded cell
//... At current time, this test is unnecessary. AI shuts down when actor is more than 7168
//... units from player, and exterior cells are 8192 units long and wide.

View file

@ -0,0 +1,99 @@
#include "actorspaths.hpp"
#include "vismask.hpp"
#include <components/sceneutil/agentpath.hpp>
#include <osg/PositionAttitudeTransform>
namespace MWRender
{
ActorsPaths::ActorsPaths(const osg::ref_ptr<osg::Group>& root, bool enabled)
: mRootNode(root)
, mEnabled(enabled)
{
}
ActorsPaths::~ActorsPaths()
{
if (mEnabled)
disable();
}
bool ActorsPaths::toggle()
{
if (mEnabled)
disable();
else
enable();
return mEnabled;
}
void ActorsPaths::update(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
const DetourNavigator::Settings& settings)
{
if (!mEnabled)
return;
const auto group = mGroups.find(actor);
if (group != mGroups.end())
mRootNode->removeChild(group->second);
const auto newGroup = SceneUtil::createAgentPathGroup(path, halfExtents, start, end, settings);
if (newGroup)
{
newGroup->setNodeMask(Mask_Debug);
mRootNode->addChild(newGroup);
mGroups[actor] = newGroup;
}
}
void ActorsPaths::remove(const MWWorld::ConstPtr& actor)
{
const auto group = mGroups.find(actor);
if (group != mGroups.end())
{
mRootNode->removeChild(group->second);
mGroups.erase(group);
}
}
void ActorsPaths::removeCell(const MWWorld::CellStore* const store)
{
for (auto it = mGroups.begin(); it != mGroups.end(); )
{
if (it->first.getCell() == store)
{
mRootNode->removeChild(it->second);
it = mGroups.erase(it);
}
else
++it;
}
}
void ActorsPaths::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated)
{
const auto it = mGroups.find(old);
if (it == mGroups.end())
return;
auto group = std::move(it->second);
mGroups.erase(it);
mGroups.insert(std::make_pair(updated, std::move(group)));
}
void ActorsPaths::enable()
{
std::for_each(mGroups.begin(), mGroups.end(),
[&] (const Groups::value_type& v) { mRootNode->addChild(v.second); });
mEnabled = true;
}
void ActorsPaths::disable()
{
std::for_each(mGroups.begin(), mGroups.end(),
[&] (const Groups::value_type& v) { mRootNode->removeChild(v.second); });
mEnabled = false;
}
}

View file

@ -0,0 +1,51 @@
#ifndef OPENMW_MWRENDER_AGENTSPATHS_H
#define OPENMW_MWRENDER_AGENTSPATHS_H
#include <apps/openmw/mwworld/ptr.hpp>
#include <components/detournavigator/navigator.hpp>
#include <osg/ref_ptr>
#include <unordered_map>
#include <deque>
namespace osg
{
class Group;
}
namespace MWRender
{
class ActorsPaths
{
public:
ActorsPaths(const osg::ref_ptr<osg::Group>& root, bool enabled);
~ActorsPaths();
bool toggle();
void update(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
const DetourNavigator::Settings& settings);
void remove(const MWWorld::ConstPtr& actor);
void removeCell(const MWWorld::CellStore* const store);
void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated);
void enable();
void disable();
private:
using Groups = std::map<MWWorld::ConstPtr, osg::ref_ptr<osg::Group>>;
osg::ref_ptr<osg::Group> mRootNode;
Groups mGroups;
bool mEnabled;
};
}
#endif

View file

@ -66,6 +66,7 @@
#include "terrainstorage.hpp"
#include "util.hpp"
#include "navmesh.hpp"
#include "actorspaths.hpp"
namespace
{
@ -234,7 +235,8 @@ namespace MWRender
mRootNode->addChild(mSceneRoot);
mNavMesh.reset(new NavMesh(mRootNode, Settings::Manager::getBool("enable 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")));
mPathgrid.reset(new Pathgrid(mRootNode));
mObjects.reset(new Objects(mResourceSystem, sceneRoot, mUnrefQueue.get()));
@ -472,6 +474,7 @@ namespace MWRender
void RenderingManager::removeCell(const MWWorld::CellStore *store)
{
mPathgrid->removeCell(store);
mActorsPaths->removeCell(store);
mObjects->removeCell(store);
if (store->getCell()->isExterior())
@ -527,6 +530,10 @@ namespace MWRender
{
return mNavMesh->toggle();
}
else if (mode == Render_ActorsPaths)
{
return mActorsPaths->toggle();
}
return false;
}
@ -666,6 +673,7 @@ namespace MWRender
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)
{
mActorsPaths->remove(ptr);
mObjects->removeObject(ptr);
mWater->removeEmitter(ptr);
}
@ -1049,6 +1057,7 @@ namespace MWRender
void RenderingManager::updatePtr(const MWWorld::Ptr &old, const MWWorld::Ptr &updated)
{
mObjects->updatePtr(old, updated);
mActorsPaths->updatePtr(old, updated);
}
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale, bool isMagicVFX)
@ -1369,5 +1378,14 @@ namespace MWRender
return mTerrainStorage->getLandManager();
}
void RenderingManager::updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const
{
mActorsPaths->update(actor, path, halfExtents, start, end, mNavigator.getSettings());
}
void RenderingManager::removeActorPath(const MWWorld::ConstPtr& actor) const
{
mActorsPaths->remove(actor);
}
}

View file

@ -12,6 +12,8 @@
#include "renderinginterface.hpp"
#include "rendermode.hpp"
#include <deque>
namespace osg
{
class Group;
@ -58,6 +60,7 @@ namespace SceneUtil
namespace DetourNavigator
{
class Navigator;
struct Settings;
}
namespace MWRender
@ -74,6 +77,7 @@ namespace MWRender
class TerrainStorage;
class LandManager;
class NavMesh;
class ActorsPaths;
class RenderingManager : public MWRender::RenderingInterface
{
@ -219,6 +223,11 @@ namespace MWRender
bool toggleBorders();
void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const;
void removeActorPath(const MWWorld::ConstPtr& actor) const;
private:
void updateProjectionMatrix();
void updateTextureFiltering();
@ -245,6 +254,7 @@ namespace MWRender
DetourNavigator::Navigator& mNavigator;
std::unique_ptr<NavMesh> mNavMesh;
std::unique_ptr<ActorsPaths> mActorsPaths;
std::unique_ptr<Pathgrid> mPathgrid;
std::unique_ptr<Objects> mObjects;
std::unique_ptr<Water> mWater;

View file

@ -12,6 +12,7 @@ namespace MWRender
Render_Water,
Render_Scene,
Render_NavMesh,
Render_ActorsPaths,
};
}

View file

@ -456,5 +456,6 @@ op 0x2000305: Show, explicit
op 0x2000306: OnActivate, explicit
op 0x2000307: ToggleBorders, tb
op 0x2000308: ToggleNavMesh
op 0x2000309: ToggleActorsPaths
opcodes 0x2000309-0x3ffffff unused
opcodes 0x200030a-0x3ffffff unused

View file

@ -1331,6 +1331,20 @@ namespace MWScript
}
};
class OpToggleActorsPaths : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
bool enabled =
MWBase::Environment::get().getWorld()->toggleRenderMode (MWRender::Render_ActorsPaths);
runtime.getContext().report (enabled ?
"Agents Paths Rendering -> On" : "Agents Paths Rendering -> Off");
}
};
void installOpcodes (Interpreter::Interpreter& interpreter)
{
interpreter.installSegment5 (Compiler::Misc::opcodeXBox, new OpXBox);
@ -1432,6 +1446,7 @@ namespace MWScript
interpreter.installSegment3 (Compiler::Misc::opcodeShowSceneGraphExplicit, new OpShowSceneGraph<ExplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleBorders, new OpToggleBorders);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleNavMesh, new OpToggleNavMesh);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleActorsPaths, new OpToggleActorsPaths);
}
}
}

View file

@ -278,7 +278,10 @@ namespace MWWorld
if (const auto object = mPhysics->getObject(ptr))
navigator->removeObject(reinterpret_cast<std::size_t>(object));
else if (const auto actor = mPhysics->getActor(ptr))
{
navigator->removeAgent(playerHalfExtents);
mRendering.removeActorPath(ptr);
}
mPhysics->remove(ptr);
}

View file

@ -3745,4 +3745,10 @@ namespace MWWorld
return mNavigator.get();
}
void World::updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const
{
mRendering->updateActorPath(actor, path, halfExtents, start, end);
}
}

View file

@ -691,6 +691,9 @@ namespace MWWorld
void preloadEffects(const ESM::EffectList* effectList) override;
DetourNavigator::Navigator* getNavigator() const override;
void updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end) const override;
};
}

View file

@ -51,7 +51,7 @@ add_component_dir (shader
add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue unrefqueue pathgridutil waterutil writescene serialize optimizer
actorutil detourdebugdraw navmesh
actorutil detourdebugdraw navmesh agentpath
)
add_component_dir (nif

View file

@ -321,7 +321,7 @@ namespace Compiler
extensions.registerInstruction ("tb", "", opcodeToggleBorders);
extensions.registerInstruction ("toggleborders", "", opcodeToggleBorders);
extensions.registerInstruction ("togglenavmesh", "", opcodeToggleNavMesh);
extensions.registerInstruction ("tnm", "", opcodeToggleNavMesh);
extensions.registerInstruction ("toggleactorspaths", "", opcodeToggleActorsPaths);
}
}

View file

@ -297,6 +297,7 @@ namespace Compiler
const int opcodeShowSceneGraphExplicit = 0x20030;
const int opcodeToggleBorders = 0x2000307;
const int opcodeToggleNavMesh = 0x2000308;
const int opcodeToggleActorsPaths = 0x2000309;
}
namespace Sky

View file

@ -0,0 +1,71 @@
#include "agentpath.hpp"
#include "detourdebugdraw.hpp"
#include <components/detournavigator/settings.hpp>
#include <components/esm/loadpgrd.hpp>
#include <algorithm>
namespace
{
void drawAgent(duDebugDraw& debugDraw, const osg::Vec3f& pos, const float radius, const float height,
const float climb, const unsigned color)
{
debugDraw.depthMask(false);
duDebugDrawCylinderWire(&debugDraw, pos.x() - radius, pos.z() + 0.02f, pos.y() - radius, pos.x() + radius,
pos.z() + height, pos.y() + radius, color, radius * 0.2f);
duDebugDrawCircle(&debugDraw, pos.x(), pos.z() + climb, pos.y(), radius, duRGBA(0, 0 , 0, 64), radius * 0.1f);
const auto colb = duRGBA(0, 0, 0, 196);
debugDraw.begin(DU_DRAW_LINES);
debugDraw.vertex(pos.x(), pos.z() - climb, pos.y(), colb);
debugDraw.vertex(pos.x(), pos.z() + climb, pos.y(), colb);
debugDraw.vertex(pos.x() - radius / 2, pos.z() + 0.02f, pos.y(), colb);
debugDraw.vertex(pos.x() + radius / 2, pos.z() + 0.02f, pos.y(), colb);
debugDraw.vertex(pos.x(), pos.z() + 0.02f, pos.y() - radius / 2, colb);
debugDraw.vertex(pos.x(), pos.z() + 0.02f, pos.y() + radius / 2, colb);
debugDraw.end();
debugDraw.depthMask(true);
}
}
namespace SceneUtil
{
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
const DetourNavigator::Settings& settings)
{
using namespace DetourNavigator;
const osg::ref_ptr<osg::Group> group(new osg::Group);
DebugDraw debugDraw(*group, osg::Vec3f(0, 0, 0), 1);
const auto agentRadius = halfExtents.x();
const auto agentHeight = 2.0f * halfExtents.z();
const auto agentClimb = settings.mMaxClimb;
const auto startColor = duRGBA(128, 25, 0, 192);
const auto endColor = duRGBA(51, 102, 0, 129);
drawAgent(debugDraw, start, agentRadius, agentHeight, agentClimb, startColor);
drawAgent(debugDraw, end, agentRadius, agentHeight, agentClimb, endColor);
const auto pathColor = duRGBA(0, 0, 0, 220);
debugDraw.depthMask(false);
debugDraw.begin(osg::PrimitiveSet::LINE_STRIP, agentRadius * 0.5f);
debugDraw.vertex(osg::Vec3f(start.x(), start.z() + agentClimb, start.y()).ptr(), startColor);
std::for_each(path.begin(), path.end(),
[&] (const osg::Vec3f& v) { debugDraw.vertex(osg::Vec3f(v.x(), v.z() + agentClimb, v.y()).ptr(), pathColor); });
debugDraw.vertex(osg::Vec3f(end.x(), end.z() + agentClimb, end.y()).ptr(), endColor);
debugDraw.end();
debugDraw.depthMask(true);
return group;
}
}

View file

@ -0,0 +1,26 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_AGENTPATH_H
#define OPENMW_COMPONENTS_SCENEUTIL_AGENTPATH_H
#include <osg/ref_ptr>
#include <deque>
namespace osg
{
class Group;
class Vec3f;
}
namespace DetourNavigator
{
struct Settings;
}
namespace SceneUtil
{
osg::ref_ptr<osg::Group> createAgentPathGroup(const std::deque<osg::Vec3f>& path,
const osg::Vec3f& halfExtents, const osg::Vec3f& start, const osg::Vec3f& end,
const DetourNavigator::Settings& settings);
}
#endif

View file

@ -56,14 +56,19 @@ namespace SceneUtil
throw std::logic_error("DebugDraw does not support textures (at " __FILE__ ":" OPENMW_LINE_STRING ")");
}
void DebugDraw::begin(duDebugDrawPrimitives prim, float size)
void DebugDraw::begin(osg::PrimitiveSet::Mode mode, float size)
{
mMode = toOsgPrimitiveSetMode(prim);
mMode = mode;
mVertices = new osg::Vec3Array;
mColors = new osg::Vec4Array;
mSize = size * mRecastInvertedScaleFactor;
}
void DebugDraw::begin(duDebugDrawPrimitives prim, float size)
{
begin(toOsgPrimitiveSetMode(prim), size);
}
void DebugDraw::vertex(const float* pos, unsigned color)
{
vertex(pos[0], pos[1], pos[2], color);

View file

@ -18,6 +18,8 @@ namespace SceneUtil
void texture(bool state) override;
void begin(osg::PrimitiveSet::Mode mode, float size);
void begin(duDebugDrawPrimitives prim, float size) override;
void vertex(const float* pos, unsigned int color) override;

View file

@ -619,4 +619,7 @@ recast mesh path prefix =
nav mesh path prefix =
# Render nav mesh (true, false)
enable render = false
enable nav mesh render = false
# Render agents paths (true, false)
enable agents paths render = false