mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 12:41:36 +00:00
Rendering raycasts in Lua
This commit is contained in:
parent
a65f8ebbc6
commit
51845e9553
9 changed files with 77 additions and 6 deletions
|
@ -57,6 +57,7 @@ namespace ESM
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
|
class RayCastingResult;
|
||||||
class RayCastingInterface;
|
class RayCastingInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,6 +332,9 @@ namespace MWBase
|
||||||
|
|
||||||
virtual bool castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask, const MWWorld::ConstPtr& ignore) = 0;
|
virtual bool castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask, const MWWorld::ConstPtr& ignore) = 0;
|
||||||
|
|
||||||
|
virtual bool castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||||
|
bool ignorePlayer, bool ignoreActors) = 0;
|
||||||
|
|
||||||
virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0;
|
virtual void setActorCollisionMode(const MWWorld::Ptr& ptr, bool internal, bool external) = 0;
|
||||||
virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0;
|
virtual bool isActorCollisionEnabled(const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWLua
|
||||||
{
|
{
|
||||||
auto* lua = context.mLua;
|
auto* lua = context.mLua;
|
||||||
sol::table api(lua->sol(), sol::create);
|
sol::table api(lua->sol(), sol::create);
|
||||||
api["API_REVISION"] = 20;
|
api["API_REVISION"] = 21;
|
||||||
api["quit"] = [lua]()
|
api["quit"] = [lua]()
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||||
|
|
|
@ -226,6 +226,7 @@ namespace MWLua
|
||||||
return; // The game is not started yet.
|
return; // The game is not started yet.
|
||||||
|
|
||||||
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
|
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
|
||||||
|
mProcessingInputEvents = true;
|
||||||
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
|
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
|
||||||
if (playerScripts && !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
|
if (playerScripts && !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
|
||||||
{
|
{
|
||||||
|
@ -235,6 +236,7 @@ namespace MWLua
|
||||||
mInputEvents.clear();
|
mInputEvents.clear();
|
||||||
if (playerScripts && !mWorldView.isPaused())
|
if (playerScripts && !mWorldView.isPaused())
|
||||||
playerScripts->inputUpdate(MWBase::Environment::get().getFrameDuration());
|
playerScripts->inputUpdate(MWBase::Environment::get().getFrameDuration());
|
||||||
|
mProcessingInputEvents = false;
|
||||||
|
|
||||||
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
|
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
|
||||||
for (const std::string& message : mUIMessages)
|
for (const std::string& message : mUIMessages)
|
||||||
|
|
|
@ -111,12 +111,15 @@ namespace MWLua
|
||||||
|
|
||||||
LuaUi::ResourceManager* uiResourceManager() { return &mUiResourceManager; }
|
LuaUi::ResourceManager* uiResourceManager() { return &mUiResourceManager; }
|
||||||
|
|
||||||
|
bool isProcessingInputEvents() const { return mProcessingInputEvents; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initConfiguration();
|
void initConfiguration();
|
||||||
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScriptCfg::Flags);
|
LocalScripts* createLocalScripts(const MWWorld::Ptr& ptr, ESM::LuaScriptCfg::Flags);
|
||||||
|
|
||||||
bool mInitialized = false;
|
bool mInitialized = false;
|
||||||
bool mGlobalScriptsStarted = false;
|
bool mGlobalScriptsStarted = false;
|
||||||
|
bool mProcessingInputEvents = false;
|
||||||
LuaUtil::ScriptsConfiguration mConfiguration;
|
LuaUtil::ScriptsConfiguration mConfiguration;
|
||||||
LuaUtil::LuaState mLua;
|
LuaUtil::LuaState mLua;
|
||||||
LuaUi::ResourceManager mUiResourceManager;
|
LuaUi::ResourceManager mUiResourceManager;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwphysics/raycasting.hpp"
|
#include "../mwphysics/raycasting.hpp"
|
||||||
|
|
||||||
|
#include "luamanagerimp.hpp"
|
||||||
#include "worldview.hpp"
|
#include "worldview.hpp"
|
||||||
|
|
||||||
namespace sol
|
namespace sol
|
||||||
|
@ -91,6 +92,27 @@ namespace MWLua
|
||||||
// and use this callback from the main thread at the beginning of the next frame processing.
|
// 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);
|
rayCasting->asyncCastRay(callback, from, to, ignore, std::vector<MWWorld::Ptr>(), collisionType);
|
||||||
};*/
|
};*/
|
||||||
|
api["castRenderingRay"] = [manager=context.mLuaManager](const osg::Vec3f& from, const osg::Vec3f& to)
|
||||||
|
{
|
||||||
|
if (!manager->isProcessingInputEvents())
|
||||||
|
{
|
||||||
|
throw std::logic_error("castRenderingRay can be used only in player scripts during processing of input events; "
|
||||||
|
"use asyncCastRenderingRay instead.");
|
||||||
|
}
|
||||||
|
MWPhysics::RayCastingResult res;
|
||||||
|
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
api["asyncCastRenderingRay"] =
|
||||||
|
[manager=context.mLuaManager](const LuaUtil::Callback& callback, const osg::Vec3f& from, const osg::Vec3f& to)
|
||||||
|
{
|
||||||
|
manager->addAction([manager, callback, from, to]
|
||||||
|
{
|
||||||
|
MWPhysics::RayCastingResult res;
|
||||||
|
MWBase::Environment::get().getWorld()->castRenderingRay(res, from, to, false, false);
|
||||||
|
manager->queueCallback(callback, sol::make_object(callback.mFunc.lua_state(), res));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
api["activators"] = LObjectList{worldView->getActivatorsInScene()};
|
api["activators"] = LObjectList{worldView->getActivatorsInScene()};
|
||||||
api["actors"] = LObjectList{worldView->getActorsInScene()};
|
api["actors"] = LObjectList{worldView->getActorsInScene()};
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
struct RayCastingResult
|
class RayCastingResult
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
bool mHit;
|
bool mHit;
|
||||||
osg::Vec3f mHitPos;
|
osg::Vec3f mHitPos;
|
||||||
osg::Vec3f mHitNormal;
|
osg::Vec3f mHitNormal;
|
||||||
|
|
|
@ -2042,6 +2042,25 @@ namespace MWWorld
|
||||||
return facedObject;
|
return facedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool World::castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||||
|
bool ignorePlayer, bool ignoreActors)
|
||||||
|
{
|
||||||
|
MWRender::RenderingManager::RayResult rayRes = mRendering->castRay(from, to, ignorePlayer, ignoreActors);
|
||||||
|
res.mHit = rayRes.mHit;
|
||||||
|
res.mHitPos = rayRes.mHitPointWorld;
|
||||||
|
res.mHitNormal = rayRes.mHitNormalWorld;
|
||||||
|
res.mHitObject = rayRes.mHitObject;
|
||||||
|
if (res.mHitObject.isEmpty() && rayRes.mHitRefnum.isSet())
|
||||||
|
{
|
||||||
|
for (CellStore* cellstore : mWorldScene->getActiveCells())
|
||||||
|
{
|
||||||
|
res.mHitObject = cellstore->searchViaRefNum(rayRes.mHitRefnum);
|
||||||
|
if (!res.mHitObject.isEmpty()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res.mHit;
|
||||||
|
}
|
||||||
|
|
||||||
bool World::isCellExterior() const
|
bool World::isCellExterior() const
|
||||||
{
|
{
|
||||||
const CellStore *currentCell = mWorldScene->getCurrentCell();
|
const CellStore *currentCell = mWorldScene->getCurrentCell();
|
||||||
|
|
|
@ -421,6 +421,9 @@ namespace MWWorld
|
||||||
|
|
||||||
bool castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask, const MWWorld::ConstPtr& ignore) override;
|
bool castRay(const osg::Vec3f& from, const osg::Vec3f& to, int mask, const MWWorld::ConstPtr& ignore) override;
|
||||||
|
|
||||||
|
bool castRenderingRay(MWPhysics::RayCastingResult& res, const osg::Vec3f& from, const osg::Vec3f& to,
|
||||||
|
bool ignorePlayer, bool ignoreActors) override;
|
||||||
|
|
||||||
void setActorCollisionMode(const Ptr& ptr, bool internal, bool external) override;
|
void setActorCollisionMode(const Ptr& ptr, bool internal, bool external) override;
|
||||||
bool isActorCollisionEnabled(const Ptr& ptr) override;
|
bool isActorCollisionEnabled(const Ptr& ptr) override;
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,22 @@
|
||||||
-- radius = 10,
|
-- radius = 10,
|
||||||
-- })
|
-- })
|
||||||
|
|
||||||
|
---
|
||||||
|
-- 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.
|
||||||
|
-- In order to avoid threading issues can be used only in player scripts only in `onInputUpdate` or
|
||||||
|
-- in engine handlers for user input. In other cases use `asyncCastRenderingRay` instead.
|
||||||
|
-- @function [parent=#nearby] castRenderingRay
|
||||||
|
-- @param openmw.util#Vector3 from Start point of the ray.
|
||||||
|
-- @param openmw.util#Vector3 to End point of the ray.
|
||||||
|
-- @return #RayCastingResult
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Asynchronously cast ray from one point to another and find the first visual intersection with anything in the scene.
|
||||||
|
-- @function [parent=#nearby] asyncCastRenderingRay
|
||||||
|
-- @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.
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue