mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 19:10:12 +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 Camera;
|
||||
class RenderingManager;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -664,6 +665,8 @@ namespace MWBase
|
|||
virtual std::vector<MWWorld::Ptr> getAll(const std::string& id) = 0;
|
||||
|
||||
virtual Misc::Rng::Generator& getPrng() = 0;
|
||||
|
||||
virtual MWRender::RenderingManager* getRenderingManager() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "luabindings.hpp"
|
||||
|
||||
#include <components/lua/utilpackage.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwrender/camera.hpp"
|
||||
#include "../mwrender/renderingmanager.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
@ -10,6 +14,7 @@ namespace MWLua
|
|||
sol::table initCameraPackage(const Context& context)
|
||||
{
|
||||
MWRender::Camera* camera = MWBase::Environment::get().getWorld()->getCamera();
|
||||
MWRender::RenderingManager* renderingManager = MWBase::Environment::get().getWorld()->getRenderingManager();
|
||||
|
||||
sol::table api(context.mLua->sol(), sol::create);
|
||||
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["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);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace MWLua
|
|||
{
|
||||
auto* lua = context.mLua;
|
||||
sol::table api(lua->sol(), sol::create);
|
||||
api["API_REVISION"] = 19;
|
||||
api["API_REVISION"] = 20;
|
||||
api["quit"] = [lua]()
|
||||
{
|
||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace MWRender
|
|||
|
||||
Camera::Camera (osg::Camera* camera)
|
||||
: mHeightScale(1.f),
|
||||
mCollisionType(MWPhysics::CollisionType::CollisionType_Default & ~MWPhysics::CollisionType::CollisionType_Actor),
|
||||
mCamera(camera),
|
||||
mAnimation(nullptr),
|
||||
mFirstPersonView(true),
|
||||
|
@ -127,6 +128,7 @@ namespace MWRender
|
|||
pos = calculateFirstPersonPosition(recalculatedTrackedPosition);
|
||||
}
|
||||
cam->setViewMatrixAsLookAt(pos, pos + forward, up);
|
||||
mViewMatrix = cam->getViewMatrix();
|
||||
}
|
||||
|
||||
void Camera::update(float duration, bool paused)
|
||||
|
@ -174,7 +176,6 @@ namespace MWRender
|
|||
constexpr float focalObstacleLimit = 10.f;
|
||||
|
||||
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.
|
||||
osg::Vec3d focalOffset = getFocalPointOffset();
|
||||
|
@ -184,7 +185,7 @@ namespace MWRender
|
|||
float offsetLen = focalOffset.length();
|
||||
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)
|
||||
{
|
||||
double adjustmentCoef = -(result.mHitPos + result.mHitNormal * focalObstacleLimit - focal).length() / offsetLen;
|
||||
|
@ -196,7 +197,7 @@ namespace MWRender
|
|||
mCameraDistance = mPreferredCameraDistance;
|
||||
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);
|
||||
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, focal + offset, cameraObstacleLimit, collisionType);
|
||||
MWPhysics::RayCastingResult result = rayCasting->castSphere(focal, focal + offset, cameraObstacleLimit, mCollisionType);
|
||||
if (result.mHit)
|
||||
{
|
||||
mCameraDistance = (result.mHitPos + result.mHitNormal * cameraObstacleLimit - focal).length();
|
||||
|
@ -211,7 +212,7 @@ namespace MWRender
|
|||
if (mMode == newMode)
|
||||
return;
|
||||
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
|
||||
// anything important, queue the view change for later
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec3d>
|
||||
|
||||
|
@ -95,11 +96,17 @@ namespace MWRender
|
|||
void setFirstPersonOffset(const osg::Vec3f& v) { mFirstPersonOffset = v; }
|
||||
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:
|
||||
MWWorld::Ptr mTrackingPtr;
|
||||
osg::ref_ptr<const osg::Node> mTrackingNode;
|
||||
osg::Vec3d mTrackedPosition;
|
||||
float mHeightScale;
|
||||
int mCollisionType;
|
||||
|
||||
osg::ref_ptr<osg::Camera> mCamera;
|
||||
|
||||
|
@ -121,6 +128,7 @@ namespace MWRender
|
|||
float mExtraPitch = 0, mExtraYaw = 0;
|
||||
bool mLockPitch = false, mLockYaw = false;
|
||||
osg::Vec3d mPosition;
|
||||
osg::Matrixf mViewMatrix;
|
||||
|
||||
float mCameraDistance, mPreferredCameraDistance;
|
||||
|
||||
|
|
|
@ -817,6 +817,11 @@ namespace MWRender
|
|||
updateNavMesh();
|
||||
updateRecastMesh();
|
||||
|
||||
if (mUpdateProjectionMatrix)
|
||||
{
|
||||
mUpdateProjectionMatrix = false;
|
||||
updateProjectionMatrix();
|
||||
}
|
||||
mCamera->update(dt, paused);
|
||||
|
||||
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.
|
||||
// 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(fov)/2.f);
|
||||
float distanceMult = std::cos(osg::DegreesToRadians(std::min(fov, 140.f))/2.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 halfExtents(0, 0, 0);
|
||||
|
|
|
@ -214,6 +214,8 @@ namespace MWRender
|
|||
|
||||
/// temporarily override the field of view with given value.
|
||||
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.
|
||||
void resetFieldOfView();
|
||||
|
||||
|
@ -301,6 +303,7 @@ namespace MWRender
|
|||
float mFieldOfViewOverride;
|
||||
float mFieldOfView;
|
||||
float mFirstPersonFieldOfView;
|
||||
bool mUpdateProjectionMatrix = false;
|
||||
|
||||
void operator = (const RenderingManager&);
|
||||
RenderingManager(const RenderingManager&);
|
||||
|
|
|
@ -743,6 +743,8 @@ namespace MWWorld
|
|||
std::vector<MWWorld::Ptr> getAll(const std::string& id) 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 util = require('openmw.util')
|
||||
local self = require('openmw.self')
|
||||
local nearby = require('openmw.nearby')
|
||||
|
||||
local Actor = require('openmw.types').Actor
|
||||
|
||||
|
@ -23,6 +24,8 @@ local noHeadBobbing = 0
|
|||
local noZoom = 0
|
||||
|
||||
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'))
|
||||
if camera.getMode() == MODE.FirstPerson then
|
||||
primaryMode = MODE.FirstPerson
|
||||
|
|
|
@ -78,6 +78,8 @@ local function updateState()
|
|||
state = STATE.Swimming
|
||||
elseif oldState == STATE.Combat or oldState == STATE.Swimming then
|
||||
state = defaultShoulder
|
||||
elseif not state then
|
||||
state = defaultShoulder
|
||||
end
|
||||
if autoSwitchShoulder and (mode == MODE.ThirdPerson or state ~= oldState or noThirdPersonLastFrame)
|
||||
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`).
|
||||
-- @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
|
||||
|
||||
|
|
Loading…
Reference in a new issue