mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-01 04:39:44 +00:00
add ignore list to raycasts
This commit is contained in:
parent
c889026b71
commit
56b31ceaf5
16 changed files with 237 additions and 79 deletions
|
@ -72,7 +72,7 @@ message(STATUS "Configuring OpenMW...")
|
|||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 49)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
set(OPENMW_LUA_API_REVISION 53)
|
||||
set(OPENMW_LUA_API_REVISION 54)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 1)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
|
|
@ -304,7 +304,7 @@ namespace MWBase
|
|||
virtual const MWPhysics::RayCastingInterface* getRayCasting() const = 0;
|
||||
|
||||
virtual bool castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
bool ignorePlayer, bool ignoreActors)
|
||||
bool ignorePlayer, bool ignoreActors, std::span<const MWWorld::Ptr> ignoreList = {})
|
||||
= 0;
|
||||
|
||||
virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0;
|
||||
|
|
|
@ -16,6 +16,31 @@
|
|||
#include "luamanagerimp.hpp"
|
||||
#include "objectlists.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class T = MWWorld::Ptr>
|
||||
std::vector<T> parseIgnoreList(const sol::table& options)
|
||||
{
|
||||
std::vector<T> ignore;
|
||||
|
||||
if (const auto& ignoreObj = options.get<sol::optional<MWLua::LObject>>("ignore"))
|
||||
{
|
||||
ignore.push_back(ignoreObj->ptr());
|
||||
}
|
||||
else if (const auto& ignoreTable = options.get<sol::optional<sol::table>>("ignore"))
|
||||
{
|
||||
ignoreTable->for_each([&](const auto& _, const sol::object& value) {
|
||||
if (value.is<MWLua::LObject>())
|
||||
{
|
||||
ignore.push_back(value.as<MWLua::LObject>().ptr());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return ignore;
|
||||
}
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
|
@ -71,24 +96,27 @@ namespace MWLua
|
|||
}));
|
||||
|
||||
api["castRay"] = [](const osg::Vec3f& from, const osg::Vec3f& to, sol::optional<sol::table> options) {
|
||||
MWWorld::Ptr ignore;
|
||||
std::vector<MWWorld::ConstPtr> ignore;
|
||||
int collisionType = MWPhysics::CollisionType_Default;
|
||||
float radius = 0;
|
||||
if (options)
|
||||
{
|
||||
sol::optional<LObject> ignoreObj = options->get<sol::optional<LObject>>("ignore");
|
||||
if (ignoreObj)
|
||||
ignore = ignoreObj->ptr();
|
||||
ignore = parseIgnoreList<MWWorld::ConstPtr>(*options);
|
||||
collisionType = options->get<sol::optional<int>>("collisionType").value_or(collisionType);
|
||||
radius = options->get<sol::optional<float>>("radius").value_or(0);
|
||||
}
|
||||
const MWPhysics::RayCastingInterface* rayCasting = MWBase::Environment::get().getWorld()->getRayCasting();
|
||||
if (radius <= 0)
|
||||
return rayCasting->castRay(from, to, ignore, std::vector<MWWorld::Ptr>(), collisionType);
|
||||
{
|
||||
return rayCasting->castRay(from, to, ignore, {}, collisionType);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ignore.isEmpty())
|
||||
throw std::logic_error("Currently castRay doesn't support `ignore` when radius > 0");
|
||||
for (const auto& ptr : ignore)
|
||||
{
|
||||
if (!ptr.isEmpty())
|
||||
throw std::logic_error("Currently castRay doesn't support `ignore` when radius > 0");
|
||||
}
|
||||
return rayCasting->castSphere(from, to, radius, collisionType);
|
||||
}
|
||||
};
|
||||
|
@ -108,22 +136,37 @@ namespace MWLua
|
|||
// and use this callback from the main thread at the beginning of the next frame processing.
|
||||
rayCasting->asyncCastRay(callback, from, to, ignore, std::vector<MWWorld::Ptr>(), collisionType);
|
||||
};*/
|
||||
api["castRenderingRay"] = [manager = context.mLuaManager](const osg::Vec3f& from, const osg::Vec3f& to) {
|
||||
api["castRenderingRay"] = [manager = context.mLuaManager](const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
const sol::optional<sol::table>& options) {
|
||||
if (!manager->isProcessingInputEvents())
|
||||
{
|
||||
throw std::logic_error(
|
||||
"castRenderingRay can be used only in player scripts during processing of input events; "
|
||||
"use asyncCastRenderingRay instead.");
|
||||
}
|
||||
|
||||
std::vector<MWWorld::Ptr> ignore;
|
||||
if (options.has_value())
|
||||
{
|
||||
ignore = parseIgnoreList(*options);
|
||||
}
|
||||
|
||||
MWPhysics::RayCastingResult res;
|
||||
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
|
||||
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false, ignore);
|
||||
return res;
|
||||
};
|
||||
api["asyncCastRenderingRay"] = [context](
|
||||
const sol::table& callback, const osg::Vec3f& from, const osg::Vec3f& to) {
|
||||
context.mLuaManager->addAction([context, callback = LuaUtil::Callback::fromLua(callback), from, to] {
|
||||
api["asyncCastRenderingRay"] = [context](const sol::table& callback, const osg::Vec3f& from,
|
||||
const osg::Vec3f& to, const sol::optional<sol::table>& options) {
|
||||
std::vector<MWWorld::Ptr> ignore;
|
||||
if (options.has_value())
|
||||
{
|
||||
ignore = parseIgnoreList(*options);
|
||||
}
|
||||
|
||||
context.mLuaManager->addAction([context, ignore, callback = LuaUtil::Callback::fromLua(callback), from,
|
||||
to] {
|
||||
MWPhysics::RayCastingResult res;
|
||||
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
|
||||
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false, ignore);
|
||||
context.mLuaManager->queueCallback(callback, sol::main_object(context.mLua->sol(), sol::in_place, res));
|
||||
});
|
||||
};
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace MWMechanics
|
|||
return MWBase::Environment::get()
|
||||
.getWorld()
|
||||
->getRayCasting()
|
||||
->castRay(position, visibleDestination, actor, {}, mask)
|
||||
->castRay(position, visibleDestination, { actor }, {}, mask)
|
||||
.mHit;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace MWPhysics
|
|||
btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
|
||||
{
|
||||
const auto* hitObject = rayResult.m_collisionObject;
|
||||
if (hitObject == mMe)
|
||||
if (std::find(mIgnoreList.begin(), mIgnoreList.end(), hitObject) != mIgnoreList.end())
|
||||
return 1.f;
|
||||
|
||||
if (hitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor && !mTargets.empty())
|
||||
|
|
|
@ -14,10 +14,10 @@ namespace MWPhysics
|
|||
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||
{
|
||||
public:
|
||||
explicit ClosestNotMeRayResultCallback(const btCollisionObject* me, std::span<const btCollisionObject*> targets,
|
||||
const btVector3& from, const btVector3& to)
|
||||
explicit ClosestNotMeRayResultCallback(std::span<const btCollisionObject*> ignore,
|
||||
std::span<const btCollisionObject*> targets, const btVector3& from, const btVector3& to)
|
||||
: btCollisionWorld::ClosestRayResultCallback(from, to)
|
||||
, mMe(me)
|
||||
, mIgnoreList(ignore)
|
||||
, mTargets(targets)
|
||||
{
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace MWPhysics
|
|||
btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace) override;
|
||||
|
||||
private:
|
||||
const btCollisionObject* mMe;
|
||||
const std::span<const btCollisionObject*> mIgnoreList;
|
||||
const std::span<const btCollisionObject*> mTargets;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -192,7 +192,8 @@ namespace MWPhysics
|
|||
}
|
||||
|
||||
RayCastingResult PhysicsSystem::castRay(const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
const MWWorld::ConstPtr& ignore, const std::vector<MWWorld::Ptr>& targets, int mask, int group) const
|
||||
const std::vector<MWWorld::ConstPtr>& ignore, const std::vector<MWWorld::Ptr>& targets, int mask,
|
||||
int group) const
|
||||
{
|
||||
if (from == to)
|
||||
{
|
||||
|
@ -203,19 +204,22 @@ namespace MWPhysics
|
|||
btVector3 btFrom = Misc::Convert::toBullet(from);
|
||||
btVector3 btTo = Misc::Convert::toBullet(to);
|
||||
|
||||
const btCollisionObject* me = nullptr;
|
||||
std::vector<const btCollisionObject*> ignoreList;
|
||||
std::vector<const btCollisionObject*> targetCollisionObjects;
|
||||
|
||||
if (!ignore.isEmpty())
|
||||
for (const auto& ptr : ignore)
|
||||
{
|
||||
const Actor* actor = getActor(ignore);
|
||||
if (actor)
|
||||
me = actor->getCollisionObject();
|
||||
else
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
const Object* object = getObject(ignore);
|
||||
if (object)
|
||||
me = object->getCollisionObject();
|
||||
const Actor* actor = getActor(ptr);
|
||||
if (actor)
|
||||
ignoreList.push_back(actor->getCollisionObject());
|
||||
else
|
||||
{
|
||||
const Object* object = getObject(ptr);
|
||||
if (object)
|
||||
ignoreList.push_back(object->getCollisionObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +233,7 @@ namespace MWPhysics
|
|||
}
|
||||
}
|
||||
|
||||
ClosestNotMeRayResultCallback resultCallback(me, targetCollisionObjects, btFrom, btTo);
|
||||
ClosestNotMeRayResultCallback resultCallback(ignoreList, targetCollisionObjects, btFrom, btTo);
|
||||
resultCallback.m_collisionFilterGroup = group;
|
||||
resultCallback.m_collisionFilterMask = mask;
|
||||
|
||||
|
|
|
@ -209,12 +209,11 @@ namespace MWPhysics
|
|||
const MWWorld::ConstPtr& ptr, int collisionGroup, int collisionMask) const;
|
||||
osg::Vec3f traceDown(const MWWorld::Ptr& ptr, const osg::Vec3f& position, float maxHeight);
|
||||
|
||||
/// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all
|
||||
/// other actors.
|
||||
/// @param ignore Optional, a list of Ptr to ignore in the list of results. targets are actors to filter for,
|
||||
/// ignoring all other actors.
|
||||
RayCastingResult castRay(const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(),
|
||||
const std::vector<MWWorld::Ptr>& targets = std::vector<MWWorld::Ptr>(), int mask = CollisionType_Default,
|
||||
int group = 0xff) const override;
|
||||
const std::vector<MWWorld::ConstPtr>& ignore = {}, const std::vector<MWWorld::Ptr>& targets = {},
|
||||
int mask = CollisionType_Default, int group = 0xff) const override;
|
||||
using RayCastingInterface::castRay;
|
||||
|
||||
RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius,
|
||||
|
|
|
@ -23,16 +23,15 @@ namespace MWPhysics
|
|||
public:
|
||||
virtual ~RayCastingInterface() = default;
|
||||
|
||||
/// @param me Optional, a Ptr to ignore in the list of results. targets are actors to filter for, ignoring all
|
||||
/// other actors.
|
||||
/// @param ignore Optional, a list of Ptr to ignore in the list of results. targets are actors to filter for,
|
||||
/// ignoring all other actors.
|
||||
virtual RayCastingResult castRay(const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
const MWWorld::ConstPtr& ignore = MWWorld::ConstPtr(),
|
||||
const std::vector<MWWorld::Ptr>& targets = std::vector<MWWorld::Ptr>(), int mask = CollisionType_Default,
|
||||
int group = 0xff) const = 0;
|
||||
const std::vector<MWWorld::ConstPtr>& ignore = {}, const std::vector<MWWorld::Ptr>& targets = {},
|
||||
int mask = CollisionType_Default, int group = 0xff) const = 0;
|
||||
|
||||
RayCastingResult castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask) const
|
||||
{
|
||||
return castRay(from, to, MWWorld::ConstPtr(), std::vector<MWWorld::Ptr>(), mask);
|
||||
return castRay(from, to, {}, {}, mask);
|
||||
}
|
||||
|
||||
virtual RayCastingResult castSphere(const osg::Vec3f& from, const osg::Vec3f& to, float radius,
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/groundcoverstore.hpp"
|
||||
#include "../mwworld/scene.hpp"
|
||||
|
||||
#include "../mwgui/postprocessorhud.hpp"
|
||||
|
||||
|
@ -1014,20 +1015,17 @@ namespace MWRender
|
|||
return osg::Vec4f(min_x, min_y, max_x, max_y);
|
||||
}
|
||||
|
||||
RenderingManager::RayResult getIntersectionResult(osgUtil::LineSegmentIntersector* intersector)
|
||||
RenderingManager::RayResult getIntersectionResult(osgUtil::LineSegmentIntersector* intersector,
|
||||
const osg::ref_ptr<osgUtil::IntersectionVisitor>& visitor, std::span<const MWWorld::Ptr> ignoreList = {})
|
||||
{
|
||||
RenderingManager::RayResult result;
|
||||
result.mHit = false;
|
||||
result.mRatio = 0;
|
||||
if (intersector->containsIntersections())
|
||||
{
|
||||
result.mHit = true;
|
||||
osgUtil::LineSegmentIntersector::Intersection intersection = intersector->getFirstIntersection();
|
||||
|
||||
result.mHitPointWorld = intersection.getWorldIntersectPoint();
|
||||
result.mHitNormalWorld = intersection.getWorldIntersectNormal();
|
||||
result.mRatio = intersection.ratio;
|
||||
if (!intersector->containsIntersections())
|
||||
return result;
|
||||
|
||||
auto test = [&](const osgUtil::LineSegmentIntersector::Intersection& intersection) {
|
||||
PtrHolder* ptrHolder = nullptr;
|
||||
std::vector<RefnumMarker*> refnumMarkers;
|
||||
for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end();
|
||||
|
@ -1039,9 +1037,16 @@ namespace MWRender
|
|||
for (unsigned int i = 0; i < userDataContainer->getNumUserObjects(); ++i)
|
||||
{
|
||||
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
|
||||
ptrHolder = p;
|
||||
{
|
||||
if (std::find(ignoreList.begin(), ignoreList.end(), p->mPtr) == ignoreList.end())
|
||||
{
|
||||
ptrHolder = p;
|
||||
}
|
||||
}
|
||||
if (RefnumMarker* r = dynamic_cast<RefnumMarker*>(userDataContainer->getUserObject(i)))
|
||||
{
|
||||
refnumMarkers.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1056,21 +1061,113 @@ namespace MWRender
|
|||
|| (intersectionIndex >= vertexCounter
|
||||
&& intersectionIndex < vertexCounter + refnumMarkers[i]->mNumVertices))
|
||||
{
|
||||
result.mHitRefnum = refnumMarkers[i]->mRefnum;
|
||||
auto it = std::find_if(
|
||||
ignoreList.begin(), ignoreList.end(), [target = refnumMarkers[i]->mRefnum](const auto& ptr) {
|
||||
return target == ptr.getCellRef().getRefNum();
|
||||
});
|
||||
|
||||
if (it == ignoreList.end())
|
||||
{
|
||||
result.mHitRefnum = refnumMarkers[i]->mRefnum;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
vertexCounter += refnumMarkers[i]->mNumVertices;
|
||||
}
|
||||
|
||||
if (!result.mHitObject.isEmpty() || result.mHitRefnum.isSet())
|
||||
{
|
||||
result.mHit = true;
|
||||
result.mHitPointWorld = intersection.getWorldIntersectPoint();
|
||||
result.mHitNormalWorld = intersection.getWorldIntersectNormal();
|
||||
result.mRatio = intersection.ratio;
|
||||
}
|
||||
};
|
||||
|
||||
if (ignoreList.empty() || intersector->getIntersectionLimit() != osgUtil::LineSegmentIntersector::NO_LIMIT)
|
||||
{
|
||||
test(intersector->getFirstIntersection());
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& intersection : intersector->getIntersections())
|
||||
{
|
||||
test(intersection);
|
||||
|
||||
if (result.mHit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
class IntersectionVisitorWithIgnoreList : public osgUtil::IntersectionVisitor
|
||||
{
|
||||
public:
|
||||
bool skipTransform(osg::Transform& transform)
|
||||
{
|
||||
if (mContainsPagedRefs)
|
||||
return false;
|
||||
|
||||
osg::UserDataContainer* userDataContainer = transform.getUserDataContainer();
|
||||
if (!userDataContainer)
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < userDataContainer->getNumUserObjects(); ++i)
|
||||
{
|
||||
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
|
||||
{
|
||||
if (std::find(mIgnoreList.begin(), mIgnoreList.end(), p->mPtr) != mIgnoreList.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void apply(osg::Transform& transform) override
|
||||
{
|
||||
if (skipTransform(transform))
|
||||
{
|
||||
return;
|
||||
}
|
||||
osgUtil::IntersectionVisitor::apply(transform);
|
||||
}
|
||||
|
||||
void setIgnoreList(std::span<const MWWorld::Ptr> ignoreList) { mIgnoreList = ignoreList; }
|
||||
void setContainsPagedRefs(bool contains) { mContainsPagedRefs = contains; }
|
||||
|
||||
private:
|
||||
std::span<const MWWorld::Ptr> mIgnoreList;
|
||||
bool mContainsPagedRefs = false;
|
||||
};
|
||||
|
||||
osg::ref_ptr<osgUtil::IntersectionVisitor> RenderingManager::getIntersectionVisitor(
|
||||
osgUtil::Intersector* intersector, bool ignorePlayer, bool ignoreActors)
|
||||
osgUtil::Intersector* intersector, bool ignorePlayer, bool ignoreActors,
|
||||
std::span<const MWWorld::Ptr> ignoreList)
|
||||
{
|
||||
if (!mIntersectionVisitor)
|
||||
mIntersectionVisitor = new osgUtil::IntersectionVisitor;
|
||||
mIntersectionVisitor = new IntersectionVisitorWithIgnoreList;
|
||||
|
||||
mIntersectionVisitor->setIgnoreList(ignoreList);
|
||||
mIntersectionVisitor->setContainsPagedRefs(false);
|
||||
|
||||
MWWorld::Scene* worldScene = MWBase::Environment::get().getWorldScene();
|
||||
for (const auto& ptr : ignoreList)
|
||||
{
|
||||
if (worldScene->isPagedRef(ptr))
|
||||
{
|
||||
mIntersectionVisitor->setContainsPagedRefs(true);
|
||||
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::NO_LIMIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mIntersectionVisitor->setTraversalNumber(mViewer->getFrameStamp()->getFrameNumber());
|
||||
mIntersectionVisitor->setFrameStamp(mViewer->getFrameStamp());
|
||||
|
@ -1088,16 +1185,16 @@ namespace MWRender
|
|||
return mIntersectionVisitor;
|
||||
}
|
||||
|
||||
RenderingManager::RayResult RenderingManager::castRay(
|
||||
const osg::Vec3f& origin, const osg::Vec3f& dest, bool ignorePlayer, bool ignoreActors)
|
||||
RenderingManager::RayResult RenderingManager::castRay(const osg::Vec3f& origin, const osg::Vec3f& dest,
|
||||
bool ignorePlayer, bool ignoreActors, std::span<const MWWorld::Ptr> ignoreList)
|
||||
{
|
||||
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector(
|
||||
new osgUtil::LineSegmentIntersector(osgUtil::LineSegmentIntersector::MODEL, origin, dest));
|
||||
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST);
|
||||
|
||||
mRootNode->accept(*getIntersectionVisitor(intersector, ignorePlayer, ignoreActors));
|
||||
mRootNode->accept(*getIntersectionVisitor(intersector, ignorePlayer, ignoreActors, ignoreList));
|
||||
|
||||
return getIntersectionResult(intersector);
|
||||
return getIntersectionResult(intersector, mIntersectionVisitor, ignoreList);
|
||||
}
|
||||
|
||||
RenderingManager::RayResult RenderingManager::castCameraToViewportRay(
|
||||
|
@ -1117,7 +1214,7 @@ namespace MWRender
|
|||
|
||||
mViewer->getCamera()->accept(*getIntersectionVisitor(intersector, ignorePlayer, ignoreActors));
|
||||
|
||||
return getIntersectionResult(intersector);
|
||||
return getIntersectionResult(intersector, mIntersectionVisitor);
|
||||
}
|
||||
|
||||
void RenderingManager::updatePtr(const MWWorld::Ptr& old, const MWWorld::Ptr& updated)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef OPENMW_MWRENDER_RENDERINGMANAGER_H
|
||||
#define OPENMW_MWRENDER_RENDERINGMANAGER_H
|
||||
|
||||
#include <span>
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Light>
|
||||
#include <osg/ref_ptr>
|
||||
|
@ -87,6 +89,7 @@ namespace MWRender
|
|||
class StateUpdater;
|
||||
class SharedUniformStateUpdater;
|
||||
class PerViewUniformStateUpdater;
|
||||
class IntersectionVisitorWithIgnoreList;
|
||||
|
||||
class EffectManager;
|
||||
class ScreenshotManager;
|
||||
|
@ -177,8 +180,8 @@ namespace MWRender
|
|||
float mRatio;
|
||||
};
|
||||
|
||||
RayResult castRay(
|
||||
const osg::Vec3f& origin, const osg::Vec3f& dest, bool ignorePlayer, bool ignoreActors = false);
|
||||
RayResult castRay(const osg::Vec3f& origin, const osg::Vec3f& dest, bool ignorePlayer,
|
||||
bool ignoreActors = false, std::span<const MWWorld::Ptr> ignoreList = {});
|
||||
|
||||
/// Return the object under the mouse cursor / crosshair position, given by nX and nY normalized screen
|
||||
/// coordinates, where (0,0) is the top left corner.
|
||||
|
@ -299,10 +302,10 @@ namespace MWRender
|
|||
|
||||
const bool mSkyBlending;
|
||||
|
||||
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, std::span<const MWWorld::Ptr> ignoreList = {});
|
||||
|
||||
osg::ref_ptr<osgUtil::IntersectionVisitor> mIntersectionVisitor;
|
||||
osg::ref_ptr<IntersectionVisitorWithIgnoreList> mIntersectionVisitor;
|
||||
|
||||
osg::ref_ptr<osgViewer::Viewer> mViewer;
|
||||
osg::ref_ptr<osg::Group> mRootNode;
|
||||
|
|
|
@ -99,6 +99,10 @@ namespace
|
|||
return ptr.getClass().getCorrectedModel(ptr);
|
||||
}
|
||||
|
||||
// Null node meant to distinguish objects that aren't in the scene from paged objects
|
||||
// TODO: find a more clever way to make paging exclusion more reliable?
|
||||
static osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pagedNode = new SceneUtil::PositionAttitudeTransform;
|
||||
|
||||
void addObject(const MWWorld::Ptr& ptr, const MWWorld::World& world, const std::vector<ESM::RefNum>& pagedRefs,
|
||||
MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering)
|
||||
{
|
||||
|
@ -111,11 +115,6 @@ namespace
|
|||
std::string model = getModel(ptr);
|
||||
const auto rotation = makeDirectNodeRotation(ptr);
|
||||
|
||||
// Null node meant to distinguish objects that aren't in the scene from paged objects
|
||||
// TODO: find a more clever way to make paging exclusion more reliable?
|
||||
static const osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pagedNode(
|
||||
new SceneUtil::PositionAttitudeTransform);
|
||||
|
||||
ESM::RefNum refnum = ptr.getCellRef().getRefNum();
|
||||
if (!refnum.hasContentFile() || !std::binary_search(pagedRefs.begin(), pagedRefs.end(), refnum))
|
||||
ptr.getClass().insertObjectRendering(ptr, model, rendering);
|
||||
|
@ -164,13 +163,13 @@ namespace
|
|||
Misc::Convert::makeBulletQuaternion(ptr.getCellRef().getPosition()), transform.getOrigin());
|
||||
|
||||
const auto start = Misc::Convert::toOsg(closedDoorTransform(center + toPoint));
|
||||
const auto startPoint = physics.castRay(start, start - osg::Vec3f(0, 0, 1000), ptr, {},
|
||||
const auto startPoint = physics.castRay(start, start - osg::Vec3f(0, 0, 1000), { ptr }, {},
|
||||
MWPhysics::CollisionType_World | MWPhysics::CollisionType_HeightMap
|
||||
| MWPhysics::CollisionType_Water);
|
||||
const auto connectionStart = startPoint.mHit ? startPoint.mHitPos : start;
|
||||
|
||||
const auto end = Misc::Convert::toOsg(closedDoorTransform(center - toPoint));
|
||||
const auto endPoint = physics.castRay(end, end - osg::Vec3f(0, 0, 1000), ptr, {},
|
||||
const auto endPoint = physics.castRay(end, end - osg::Vec3f(0, 0, 1000), { ptr }, {},
|
||||
MWPhysics::CollisionType_World | MWPhysics::CollisionType_HeightMap
|
||||
| MWPhysics::CollisionType_Water);
|
||||
const auto connectionEnd = endPoint.mHit ? endPoint.mHitPos : end;
|
||||
|
@ -274,7 +273,6 @@ namespace
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
|
||||
void Scene::removeFromPagedRefs(const Ptr& ptr)
|
||||
{
|
||||
ESM::RefNum refnum = ptr.getCellRef().getRefNum();
|
||||
|
@ -288,6 +286,11 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
bool Scene::isPagedRef(const Ptr& ptr) const
|
||||
{
|
||||
return ptr.getRefData().getBaseNode() == pagedNode.get();
|
||||
}
|
||||
|
||||
void Scene::updateObjectRotation(const Ptr& ptr, RotationOrder order)
|
||||
{
|
||||
const auto rot = makeNodeRotation(ptr, order);
|
||||
|
|
|
@ -190,6 +190,8 @@ namespace MWWorld
|
|||
|
||||
void removeFromPagedRefs(const Ptr& ptr);
|
||||
|
||||
bool isPagedRef(const Ptr& ptr) const;
|
||||
|
||||
void updateObjectRotation(const Ptr& ptr, RotationOrder order);
|
||||
void updateObjectScale(const Ptr& ptr);
|
||||
|
||||
|
|
|
@ -1817,9 +1817,10 @@ namespace MWWorld
|
|||
}
|
||||
|
||||
bool World::castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
bool ignorePlayer, bool ignoreActors)
|
||||
bool ignorePlayer, bool ignoreActors, std::span<const MWWorld::Ptr> ignoreList)
|
||||
{
|
||||
MWRender::RenderingManager::RayResult rayRes = mRendering->castRay(from, to, ignorePlayer, ignoreActors);
|
||||
MWRender::RenderingManager::RayResult rayRes
|
||||
= mRendering->castRay(from, to, ignorePlayer, ignoreActors, ignoreList);
|
||||
res.mHit = rayRes.mHit;
|
||||
res.mHitPos = rayRes.mHitPointWorld;
|
||||
res.mHitNormal = rayRes.mHitNormalWorld;
|
||||
|
@ -2598,7 +2599,7 @@ namespace MWWorld
|
|||
collisionTypes |= MWPhysics::CollisionType_Water;
|
||||
}
|
||||
MWPhysics::RayCastingResult result
|
||||
= mPhysics->castRay(from, to, MWWorld::Ptr(), std::vector<MWWorld::Ptr>(), collisionTypes);
|
||||
= mPhysics->castRay(from, to, { MWWorld::Ptr() }, std::vector<MWWorld::Ptr>(), collisionTypes);
|
||||
|
||||
if (!result.mHit)
|
||||
return maxDist;
|
||||
|
@ -3064,8 +3065,8 @@ namespace MWWorld
|
|||
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
|
||||
|
||||
// Check for impact, if yes, handle hit, if not, launch projectile
|
||||
MWPhysics::RayCastingResult result
|
||||
= mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
||||
MWPhysics::RayCastingResult result = mPhysics->castRay(
|
||||
sourcePos, worldPos, { actor }, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
||||
if (result.mHit)
|
||||
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
|
||||
else
|
||||
|
|
|
@ -392,7 +392,7 @@ namespace MWWorld
|
|||
const MWPhysics::RayCastingInterface* getRayCasting() const override;
|
||||
|
||||
bool castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||
bool ignorePlayer, bool ignoreActors) override;
|
||||
bool ignorePlayer, bool ignoreActors, std::span<const MWWorld::Ptr> ignoreList) override;
|
||||
|
||||
void setActorCollisionMode(const Ptr& ptr, bool internal, bool external) override;
|
||||
bool isActorCollisionEnabled(const Ptr& ptr) override;
|
||||
|
|
|
@ -89,6 +89,11 @@
|
|||
-- radius = 10,
|
||||
-- })
|
||||
|
||||
---
|
||||
-- A table of parameters for @{#nearby.castRenderingRay} and @{#nearby.asyncCastRenderingRay}
|
||||
-- @type CastRenderingRayOptions
|
||||
-- @field #table ignore A list of @{openmw.core#GameObject} to ignore while doing the ray cast
|
||||
|
||||
---
|
||||
-- Cast ray from one point to another and find the first visual intersection with anything in the scene.
|
||||
-- As opposite to `castRay` can find an intersection with an object without collisions.
|
||||
|
@ -97,6 +102,7 @@
|
|||
-- @function [parent=#nearby] castRenderingRay
|
||||
-- @param openmw.util#Vector3 from Start point of the ray.
|
||||
-- @param openmw.util#Vector3 to End point of the ray.
|
||||
-- @param #CastRenderingRayOptions
|
||||
-- @return #RayCastingResult
|
||||
|
||||
---
|
||||
|
@ -105,6 +111,7 @@
|
|||
-- @param openmw.async#Callback callback The callback to pass the result to (should accept a single argument @{openmw.nearby#RayCastingResult}).
|
||||
-- @param openmw.util#Vector3 from Start point of the ray.
|
||||
-- @param openmw.util#Vector3 to End point of the ray.
|
||||
-- @param #CastRenderingRayOptions
|
||||
|
||||
---
|
||||
-- @type NAVIGATOR_FLAGS
|
||||
|
|
Loading…
Reference in a new issue