mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 09:09:43 +00:00
Update Lua bindings for the camera
This commit is contained in:
parent
7186ea8ab4
commit
3af8ea5dfc
11 changed files with 104 additions and 7 deletions
|
@ -64,6 +64,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
class Animation;
|
class Animation;
|
||||||
class Camera;
|
class Camera;
|
||||||
|
class RenderingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -664,6 +665,8 @@ namespace MWBase
|
||||||
virtual std::vector<MWWorld::Ptr> getAll(const std::string& id) = 0;
|
virtual std::vector<MWWorld::Ptr> getAll(const std::string& id) = 0;
|
||||||
|
|
||||||
virtual Misc::Rng::Generator& getPrng() = 0;
|
virtual Misc::Rng::Generator& getPrng() = 0;
|
||||||
|
|
||||||
|
virtual MWRender::RenderingManager* getRenderingManager() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "luabindings.hpp"
|
#include "luabindings.hpp"
|
||||||
|
|
||||||
|
#include <components/lua/utilpackage.hpp>
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwrender/camera.hpp"
|
#include "../mwrender/camera.hpp"
|
||||||
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
|
||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
@ -10,6 +14,7 @@ namespace MWLua
|
||||||
sol::table initCameraPackage(const Context& context)
|
sol::table initCameraPackage(const Context& context)
|
||||||
{
|
{
|
||||||
MWRender::Camera* camera = MWBase::Environment::get().getWorld()->getCamera();
|
MWRender::Camera* camera = MWBase::Environment::get().getWorld()->getCamera();
|
||||||
|
MWRender::RenderingManager* renderingManager = MWBase::Environment::get().getWorld()->getRenderingManager();
|
||||||
|
|
||||||
sol::table api(context.mLua->sol(), sol::create);
|
sol::table api(context.mLua->sol(), sol::create);
|
||||||
api["MODE"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
|
api["MODE"] = LuaUtil::makeReadOnly(context.mLua->sol().create_table_with(
|
||||||
|
@ -77,6 +82,31 @@ namespace MWLua
|
||||||
api["setFocalTransitionSpeed"] = [camera](float v) { camera->setFocalPointTransitionSpeed(v); };
|
api["setFocalTransitionSpeed"] = [camera](float v) { camera->setFocalPointTransitionSpeed(v); };
|
||||||
api["instantTransition"] = [camera]() { camera->instantTransition(); };
|
api["instantTransition"] = [camera]() { camera->instantTransition(); };
|
||||||
|
|
||||||
|
api["getCollisionType"] = [camera]() { return camera->getCollisionType(); };
|
||||||
|
api["setCollisionType"] = [camera](int collisionType) { camera->setCollisionType(collisionType); };
|
||||||
|
|
||||||
|
api["getBaseFieldOfView"] = []()
|
||||||
|
{
|
||||||
|
return osg::DegreesToRadians(std::clamp(Settings::Manager::getFloat("field of view", "Camera"), 1.f, 179.f));
|
||||||
|
};
|
||||||
|
api["getFieldOfView"] = [renderingManager]() { return osg::DegreesToRadians(renderingManager->getFieldOfView()); };
|
||||||
|
api["setFieldOfView"] = [renderingManager](float v) { renderingManager->setFieldOfView(osg::RadiansToDegrees(v)); };
|
||||||
|
|
||||||
|
api["getViewTransform"] = [camera]() { return LuaUtil::TransformM{camera->getViewMatrix()}; };
|
||||||
|
|
||||||
|
api["viewportToWorldVector"] = [camera, renderingManager](osg::Vec2f pos) -> osg::Vec3f
|
||||||
|
{
|
||||||
|
double width = Settings::Manager::getInt("resolution x", "Video");
|
||||||
|
double height = Settings::Manager::getInt("resolution y", "Video");
|
||||||
|
double aspect = (height == 0.0) ? 1.0 : width / height;
|
||||||
|
double fovTan = std::tan(osg::DegreesToRadians(renderingManager->getFieldOfView()) / 2);
|
||||||
|
osg::Matrixf invertedViewMatrix;
|
||||||
|
invertedViewMatrix.invert(camera->getViewMatrix());
|
||||||
|
float x = (pos.x() * 2 - 1) * aspect * fovTan;
|
||||||
|
float y = (1 - pos.y() * 2) * fovTan;
|
||||||
|
return invertedViewMatrix.preMult(osg::Vec3f(x, y, -1)) - camera->getPosition();
|
||||||
|
};
|
||||||
|
|
||||||
return LuaUtil::makeReadOnly(api);
|
return LuaUtil::makeReadOnly(api);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"] = 19;
|
api["API_REVISION"] = 20;
|
||||||
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();
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace MWRender
|
||||||
|
|
||||||
Camera::Camera (osg::Camera* camera)
|
Camera::Camera (osg::Camera* camera)
|
||||||
: mHeightScale(1.f),
|
: mHeightScale(1.f),
|
||||||
|
mCollisionType(MWPhysics::CollisionType::CollisionType_Default & ~MWPhysics::CollisionType::CollisionType_Actor),
|
||||||
mCamera(camera),
|
mCamera(camera),
|
||||||
mAnimation(nullptr),
|
mAnimation(nullptr),
|
||||||
mFirstPersonView(true),
|
mFirstPersonView(true),
|
||||||
|
@ -127,6 +128,7 @@ namespace MWRender
|
||||||
pos = calculateFirstPersonPosition(recalculatedTrackedPosition);
|
pos = calculateFirstPersonPosition(recalculatedTrackedPosition);
|
||||||
}
|
}
|
||||||
cam->setViewMatrixAsLookAt(pos, pos + forward, up);
|
cam->setViewMatrixAsLookAt(pos, pos + forward, up);
|
||||||
|
mViewMatrix = cam->getViewMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::update(float duration, bool paused)
|
void Camera::update(float duration, bool paused)
|
||||||
|
@ -174,7 +176,6 @@ namespace MWRender
|
||||||
constexpr float focalObstacleLimit = 10.f;
|
constexpr float focalObstacleLimit = 10.f;
|
||||||
|
|
||||||
const auto* rayCasting = MWBase::Environment::get().getWorld()->getRayCasting();
|
const auto* rayCasting = MWBase::Environment::get().getWorld()->getRayCasting();
|
||||||
constexpr int collisionType = (MWPhysics::CollisionType::CollisionType_Default & ~MWPhysics::CollisionType::CollisionType_Actor);
|
|
||||||
|
|
||||||
// Adjust focal point to prevent clipping.
|
// Adjust focal point to prevent clipping.
|
||||||
osg::Vec3d focalOffset = getFocalPointOffset();
|
osg::Vec3d focalOffset = getFocalPointOffset();
|
||||||
|
@ -184,7 +185,7 @@ namespace MWRender
|
||||||
float offsetLen = focalOffset.length();
|
float offsetLen = focalOffset.length();
|
||||||
if (offsetLen > 0)
|
if (offsetLen > 0)
|
||||||
{
|
{
|
||||||
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal - focalOffset, focal, focalObstacleLimit, collisionType);
|
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal - focalOffset, focal, focalObstacleLimit, mCollisionType);
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
{
|
{
|
||||||
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
|
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
|
||||||
|
@ -196,7 +197,7 @@ namespace MWRender
|
||||||
mCameraDistance = mPreferredCameraDistance;
|
mCameraDistance = mPreferredCameraDistance;
|
||||||
osg::Quat orient = osg::Quat(mPitch + mExtraPitch, osg::Vec3d(1,0,0)) * osg::Quat(mYaw + mExtraYaw, osg::Vec3d(0,0,1));
|
osg::Quat orient = osg::Quat(mPitch + mExtraPitch, osg::Vec3d(1,0,0)) * osg::Quat(mYaw + mExtraYaw, osg::Vec3d(0,0,1));
|
||||||
osg::Vec3d offset = orient * osg::Vec3d(0.f, -mCameraDistance, 0.f);
|
osg::Vec3d offset = orient * osg::Vec3d(0.f, -mCameraDistance, 0.f);
|
||||||
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, focal + offset, cameraObstacleLimit, collisionType);
|
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, focal + offset, cameraObstacleLimit, mCollisionType);
|
||||||
if (result.mHit)
|
if (result.mHit)
|
||||||
{
|
{
|
||||||
mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length();
|
mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length();
|
||||||
|
@ -211,7 +212,7 @@ namespace MWRender
|
||||||
if (mMode == newMode)
|
if (mMode == newMode)
|
||||||
return;
|
return;
|
||||||
Mode oldMode = mMode;
|
Mode oldMode = mMode;
|
||||||
if (!force && (newMode == Mode::FirstPerson || oldMode == Mode::FirstPerson) && !mAnimation->upperBodyReady())
|
if (!force && (newMode == Mode::FirstPerson || oldMode == Mode::FirstPerson) && mAnimation && !mAnimation->upperBodyReady())
|
||||||
{
|
{
|
||||||
// Changing the view will stop all playing animations, so if we are playing
|
// Changing the view will stop all playing animations, so if we are playing
|
||||||
// anything important, queue the view change for later
|
// anything important, queue the view change for later
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
#include <osg/Matrix>
|
||||||
#include <osg/Vec3>
|
#include <osg/Vec3>
|
||||||
#include <osg/Vec3d>
|
#include <osg/Vec3d>
|
||||||
|
|
||||||
|
@ -95,11 +96,17 @@ namespace MWRender
|
||||||
void setFirstPersonOffset(const osg::Vec3f& v) { mFirstPersonOffset = v; }
|
void setFirstPersonOffset(const osg::Vec3f& v) { mFirstPersonOffset = v; }
|
||||||
osg::Vec3f getFirstPersonOffset() const { return mFirstPersonOffset; }
|
osg::Vec3f getFirstPersonOffset() const { return mFirstPersonOffset; }
|
||||||
|
|
||||||
|
int getCollisionType() const { return mCollisionType; }
|
||||||
|
void setCollisionType(int collisionType) { mCollisionType = collisionType; }
|
||||||
|
|
||||||
|
const osg::Matrixf& getViewMatrix() const { return mViewMatrix; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MWWorld::Ptr mTrackingPtr;
|
MWWorld::Ptr mTrackingPtr;
|
||||||
osg::ref_ptr<const osg::Node> mTrackingNode;
|
osg::ref_ptr<const osg::Node> mTrackingNode;
|
||||||
osg::Vec3d mTrackedPosition;
|
osg::Vec3d mTrackedPosition;
|
||||||
float mHeightScale;
|
float mHeightScale;
|
||||||
|
int mCollisionType;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Camera> mCamera;
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
|
|
||||||
|
@ -121,6 +128,7 @@ namespace MWRender
|
||||||
float mExtraPitch = 0, mExtraYaw = 0;
|
float mExtraPitch = 0, mExtraYaw = 0;
|
||||||
bool mLockPitch = false, mLockYaw = false;
|
bool mLockPitch = false, mLockYaw = false;
|
||||||
osg::Vec3d mPosition;
|
osg::Vec3d mPosition;
|
||||||
|
osg::Matrixf mViewMatrix;
|
||||||
|
|
||||||
float mCameraDistance, mPreferredCameraDistance;
|
float mCameraDistance, mPreferredCameraDistance;
|
||||||
|
|
||||||
|
|
|
@ -817,6 +817,11 @@ namespace MWRender
|
||||||
updateNavMesh();
|
updateNavMesh();
|
||||||
updateRecastMesh();
|
updateRecastMesh();
|
||||||
|
|
||||||
|
if (mUpdateProjectionMatrix)
|
||||||
|
{
|
||||||
|
mUpdateProjectionMatrix = false;
|
||||||
|
updateProjectionMatrix();
|
||||||
|
}
|
||||||
mCamera->update(dt, paused);
|
mCamera->update(dt, paused);
|
||||||
|
|
||||||
bool isUnderwater = mWater->isUnderwater(mCamera->getPosition());
|
bool isUnderwater = mWater->isUnderwater(mCamera->getPosition());
|
||||||
|
@ -1161,8 +1166,7 @@ namespace MWRender
|
||||||
|
|
||||||
// Since our fog is not radial yet, we should take FOV in account, otherwise terrain near viewing distance may disappear.
|
// Since our fog is not radial yet, we should take FOV in account, otherwise terrain near viewing distance may disappear.
|
||||||
// Limit FOV here just for sure, otherwise viewing distance can be too high.
|
// Limit FOV here just for sure, otherwise viewing distance can be too high.
|
||||||
fov = std::min(mFieldOfView, 140.f);
|
float distanceMult = std::cos(osg::DegreesToRadians(std::min(fov, 140.f))/2.f);
|
||||||
float distanceMult = std::cos(osg::DegreesToRadians(fov)/2.f);
|
|
||||||
mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f/distanceMult : 1.f));
|
mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f/distanceMult : 1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,6 +1304,17 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::setFieldOfView(float val)
|
||||||
|
{
|
||||||
|
mFieldOfView = val;
|
||||||
|
mUpdateProjectionMatrix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float RenderingManager::getFieldOfView() const
|
||||||
|
{
|
||||||
|
return mFieldOfViewOverridden ? mFieldOfViewOverridden : mFieldOfView;
|
||||||
|
}
|
||||||
|
|
||||||
osg::Vec3f RenderingManager::getHalfExtents(const MWWorld::ConstPtr& object) const
|
osg::Vec3f RenderingManager::getHalfExtents(const MWWorld::ConstPtr& object) const
|
||||||
{
|
{
|
||||||
osg::Vec3f halfExtents(0, 0, 0);
|
osg::Vec3f halfExtents(0, 0, 0);
|
||||||
|
|
|
@ -214,6 +214,8 @@ namespace MWRender
|
||||||
|
|
||||||
/// temporarily override the field of view with given value.
|
/// temporarily override the field of view with given value.
|
||||||
void overrideFieldOfView(float val);
|
void overrideFieldOfView(float val);
|
||||||
|
void setFieldOfView(float val);
|
||||||
|
float getFieldOfView() const;
|
||||||
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
|
/// reset a previous overrideFieldOfView() call, i.e. revert to field of view specified in the settings file.
|
||||||
void resetFieldOfView();
|
void resetFieldOfView();
|
||||||
|
|
||||||
|
@ -301,6 +303,7 @@ namespace MWRender
|
||||||
float mFieldOfViewOverride;
|
float mFieldOfViewOverride;
|
||||||
float mFieldOfView;
|
float mFieldOfView;
|
||||||
float mFirstPersonFieldOfView;
|
float mFirstPersonFieldOfView;
|
||||||
|
bool mUpdateProjectionMatrix = false;
|
||||||
|
|
||||||
void operator = (const RenderingManager&);
|
void operator = (const RenderingManager&);
|
||||||
RenderingManager(const RenderingManager&);
|
RenderingManager(const RenderingManager&);
|
||||||
|
|
|
@ -743,6 +743,8 @@ namespace MWWorld
|
||||||
std::vector<MWWorld::Ptr> getAll(const std::string& id) override;
|
std::vector<MWWorld::Ptr> getAll(const std::string& id) override;
|
||||||
|
|
||||||
Misc::Rng::Generator& getPrng() override;
|
Misc::Rng::Generator& getPrng() override;
|
||||||
|
|
||||||
|
MWRender::RenderingManager* getRenderingManager() override { return mRendering.get(); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ local input = require('openmw.input')
|
||||||
local settings = require('openmw.settings')
|
local settings = require('openmw.settings')
|
||||||
local util = require('openmw.util')
|
local util = require('openmw.util')
|
||||||
local self = require('openmw.self')
|
local self = require('openmw.self')
|
||||||
|
local nearby = require('openmw.nearby')
|
||||||
|
|
||||||
local Actor = require('openmw.types').Actor
|
local Actor = require('openmw.types').Actor
|
||||||
|
|
||||||
|
@ -23,6 +24,8 @@ local noHeadBobbing = 0
|
||||||
local noZoom = 0
|
local noZoom = 0
|
||||||
|
|
||||||
local function init()
|
local function init()
|
||||||
|
camera.setCollisionType(util.bitAnd(nearby.COLLISION_TYPE.Default, util.bitNot(nearby.COLLISION_TYPE.Actor)))
|
||||||
|
camera.setFieldOfView(camera.getBaseFieldOfView())
|
||||||
camera.allowCharacterDeferredRotation(settings._getBoolFromSettingsCfg('Camera', 'deferred preview rotation'))
|
camera.allowCharacterDeferredRotation(settings._getBoolFromSettingsCfg('Camera', 'deferred preview rotation'))
|
||||||
if camera.getMode() == MODE.FirstPerson then
|
if camera.getMode() == MODE.FirstPerson then
|
||||||
primaryMode = MODE.FirstPerson
|
primaryMode = MODE.FirstPerson
|
||||||
|
|
|
@ -78,6 +78,8 @@ local function updateState()
|
||||||
state = STATE.Swimming
|
state = STATE.Swimming
|
||||||
elseif oldState == STATE.Combat or oldState == STATE.Swimming then
|
elseif oldState == STATE.Combat or oldState == STATE.Swimming then
|
||||||
state = defaultShoulder
|
state = defaultShoulder
|
||||||
|
elseif not state then
|
||||||
|
state = defaultShoulder
|
||||||
end
|
end
|
||||||
if autoSwitchShoulder and (mode == MODE.ThirdPerson or state ~= oldState or noThirdPersonLastFrame)
|
if autoSwitchShoulder and (mode == MODE.ThirdPerson or state ~= oldState or noThirdPersonLastFrame)
|
||||||
and (state == STATE.LeftShoulder or state == STATE.RightShoulder) then
|
and (state == STATE.LeftShoulder or state == STATE.RightShoulder) then
|
||||||
|
|
|
@ -166,6 +166,36 @@
|
||||||
-- Make instant the current transition of camera focal point and the current deferred rotation (see `allowCharacterDeferredRotation`).
|
-- Make instant the current transition of camera focal point and the current deferred rotation (see `allowCharacterDeferredRotation`).
|
||||||
-- @function [parent=#camera] instantTransition
|
-- @function [parent=#camera] instantTransition
|
||||||
|
|
||||||
|
--- Get current camera collision type (see @{openmw.nearby#COLLISION_TYPE}).
|
||||||
|
-- @function [parent=#camera] getCollisionType
|
||||||
|
-- @return #number
|
||||||
|
|
||||||
|
--- Set camera collision type (see @{openmw.nearby#COLLISION_TYPE}).
|
||||||
|
-- @function [parent=#camera] setCollisionType
|
||||||
|
-- @param #number collisionType
|
||||||
|
|
||||||
|
--- Return base field of view vertical angle in radians
|
||||||
|
-- @function [parent=#camera] getBaseFieldOfView
|
||||||
|
-- @return #number
|
||||||
|
|
||||||
|
--- Return current field of view vertical angle in radians
|
||||||
|
-- @function [parent=#camera] getFieldOfView
|
||||||
|
-- @return #number
|
||||||
|
|
||||||
|
--- Set field of view
|
||||||
|
-- @function [parent=#camera] setFieldOfView
|
||||||
|
-- @param #number fov Field of view vertical angle in radians
|
||||||
|
|
||||||
|
--- Get world to local transform for the camera.
|
||||||
|
-- @function [parent=#camera] getViewTransform
|
||||||
|
-- @return openmw.util#Transform
|
||||||
|
|
||||||
|
--- Get vector from the camera to the world for the given point in viewport.
|
||||||
|
-- (0, 0) is the top left corner of the screen.
|
||||||
|
-- @function [parent=#camera] viewportToWorldVector
|
||||||
|
-- @param openmw.util#Vector2 normalizedScreenPos
|
||||||
|
-- @return openmw.util#Vector3
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue