mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Refactoring. Move all code related to 'view over shoulder' to a separate file.
This commit is contained in:
parent
5bdf61a886
commit
51173ebcf5
@ -20,7 +20,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
|||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
bulletdebugdraw globalmap characterpreview camera viewovershoulder localmap water terrainstorage ripplesimulation
|
||||||
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging
|
renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
@ -63,13 +62,12 @@ namespace MWRender
|
|||||||
mVanityToggleQueuedValue(false),
|
mVanityToggleQueuedValue(false),
|
||||||
mViewModeToggleQueued(false),
|
mViewModeToggleQueued(false),
|
||||||
mCameraDistance(0.f),
|
mCameraDistance(0.f),
|
||||||
mThirdPersonMode(ThirdPersonViewMode::Standard),
|
|
||||||
mOverShoulderOffset(osg::Vec2f(30.0f, -10.0f)),
|
|
||||||
mDefaultShoulderIsRight(true),
|
|
||||||
mThirdPersionOffsetType(ThirdPersonOffsetType::RightShoulder),
|
|
||||||
mFocalPointCurrentOffset(osg::Vec2d()),
|
mFocalPointCurrentOffset(osg::Vec2d()),
|
||||||
|
mFocalPointTargetOffset(osg::Vec2d()),
|
||||||
mFocalPointTransitionSpeed(1.f),
|
mFocalPointTransitionSpeed(1.f),
|
||||||
mSmoothedSpeed(0.f)
|
mSmoothedSpeed(0.f),
|
||||||
|
mDynamicCameraDistanceEnabled(false),
|
||||||
|
mShowCrosshairInThirdPersonMode(false)
|
||||||
{
|
{
|
||||||
mVanity.enabled = false;
|
mVanity.enabled = false;
|
||||||
mVanity.allowed = true;
|
mVanity.allowed = true;
|
||||||
@ -124,7 +122,7 @@ namespace MWRender
|
|||||||
osg::Vec3d Camera::getFocalPointOffset() const
|
osg::Vec3d Camera::getFocalPointOffset() const
|
||||||
{
|
{
|
||||||
osg::Vec3d offset(0, 0, 10.f);
|
osg::Vec3d offset(0, 0, 10.f);
|
||||||
if (mThirdPersonMode == ThirdPersonViewMode::OverShoulder && !mPreviewMode && !mVanity.enabled)
|
if (!mPreviewMode && !mVanity.enabled)
|
||||||
{
|
{
|
||||||
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
|
offset.x() += mFocalPointCurrentOffset.x() * cos(getYaw());
|
||||||
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
|
offset.y() += mFocalPointCurrentOffset.x() * sin(getYaw());
|
||||||
@ -209,7 +207,7 @@ namespace MWRender
|
|||||||
// only show the crosshair in game mode
|
// only show the crosshair in game mode
|
||||||
MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager();
|
MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager();
|
||||||
wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode
|
wm->showCrosshair(!wm->isGuiMode() && !mVanity.enabled && !mPreviewMode
|
||||||
&& (mFirstPersonView || mThirdPersonMode != ThirdPersonViewMode::Standard));
|
&& (mFirstPersonView || mShowCrosshairInThirdPersonMode));
|
||||||
|
|
||||||
if(mVanity.enabled)
|
if(mVanity.enabled)
|
||||||
{
|
{
|
||||||
@ -223,68 +221,9 @@ namespace MWRender
|
|||||||
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
|
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setOverShoulderOffset(float horizontal, float vertical)
|
|
||||||
{
|
|
||||||
mOverShoulderOffset = osg::Vec2f(std::abs(horizontal), vertical);
|
|
||||||
mDefaultShoulderIsRight = horizontal >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::switchToLeftShoulder()
|
|
||||||
{
|
|
||||||
if (mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder)
|
|
||||||
mThirdPersionOffsetType = ThirdPersonOffsetType::LeftShoulder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::switchToRightShoulder()
|
|
||||||
{
|
|
||||||
if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder)
|
|
||||||
mThirdPersionOffsetType = ThirdPersonOffsetType::RightShoulder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::switchToDefaultShoulder()
|
|
||||||
{
|
|
||||||
if (mThirdPersionOffsetType == ThirdPersonOffsetType::LeftShoulder || mThirdPersionOffsetType == ThirdPersonOffsetType::RightShoulder)
|
|
||||||
mThirdPersionOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Camera::updateFocalPointOffset(float duration)
|
void Camera::updateFocalPointOffset(float duration)
|
||||||
{
|
{
|
||||||
if (mThirdPersonMode == ThirdPersonViewMode::Standard)
|
osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset;
|
||||||
return; // In Standard mode there is no focal point offset.
|
|
||||||
|
|
||||||
ThirdPersonOffsetType newOffsetType = mThirdPersionOffsetType;
|
|
||||||
if (mTrackingPtr.getClass().isActor() && mTrackingPtr.getClass().getCreatureStats(mTrackingPtr).getDrawState() != MWMechanics::DrawState_Nothing)
|
|
||||||
newOffsetType = ThirdPersonOffsetType::Combat;
|
|
||||||
else if (MWBase::Environment::get().getWorld()->isSwimming(mTrackingPtr))
|
|
||||||
newOffsetType = ThirdPersonOffsetType::Swimming;
|
|
||||||
else if (mThirdPersionOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Swimming)
|
|
||||||
newOffsetType = mDefaultShoulderIsRight ? ThirdPersonOffsetType::RightShoulder : ThirdPersonOffsetType::LeftShoulder;
|
|
||||||
if (newOffsetType != mThirdPersionOffsetType)
|
|
||||||
{
|
|
||||||
if (newOffsetType == ThirdPersonOffsetType::Combat || mThirdPersionOffsetType == ThirdPersonOffsetType::Combat)
|
|
||||||
mFocalPointTransitionSpeed = 5;
|
|
||||||
else
|
|
||||||
mFocalPointTransitionSpeed = 1;
|
|
||||||
mThirdPersionOffsetType = newOffsetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec2d focalPointTargetOffset;
|
|
||||||
switch (mThirdPersionOffsetType)
|
|
||||||
{
|
|
||||||
case ThirdPersonOffsetType::RightShoulder:
|
|
||||||
focalPointTargetOffset = mOverShoulderOffset;
|
|
||||||
break;
|
|
||||||
case ThirdPersonOffsetType::LeftShoulder:
|
|
||||||
focalPointTargetOffset = mOverShoulderOffset;
|
|
||||||
focalPointTargetOffset.x() *= -1;
|
|
||||||
break;
|
|
||||||
case ThirdPersonOffsetType::Combat:
|
|
||||||
case ThirdPersonOffsetType::Swimming:
|
|
||||||
default:
|
|
||||||
focalPointTargetOffset = osg::Vec2d(0, 15);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Vec2d delta = focalPointTargetOffset - mFocalPointCurrentOffset;
|
|
||||||
if (delta.length2() > 0)
|
if (delta.length2() > 0)
|
||||||
{
|
{
|
||||||
float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed;
|
float coef = duration * (1.0 + 5.0 / delta.length()) * mFocalPointTransitionSpeed;
|
||||||
@ -487,17 +426,15 @@ namespace MWRender
|
|||||||
|
|
||||||
float Camera::getCameraDistanceCorrection() const
|
float Camera::getCameraDistanceCorrection() const
|
||||||
{
|
{
|
||||||
if (mThirdPersonMode == ThirdPersonViewMode::Standard)
|
if (!mDynamicCameraDistanceEnabled)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
|
||||||
{
|
|
||||||
float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f;
|
|
||||||
|
|
||||||
float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed;
|
float pitchCorrection = std::max(-getPitch(), 0.f) * 50.f;
|
||||||
float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f;
|
|
||||||
|
|
||||||
return pitchCorrection + speedCorrection;
|
float smoothedSpeedSqr = mSmoothedSpeed * mSmoothedSpeed;
|
||||||
}
|
float speedCorrection = smoothedSpeedSqr / (smoothedSpeedSqr + 300.f*300.f) * 20.0f;
|
||||||
|
|
||||||
|
return pitchCorrection + speedCorrection;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setCameraDistance()
|
void Camera::setCameraDistance()
|
||||||
|
@ -23,12 +23,7 @@ namespace MWRender
|
|||||||
/// \brief Camera control
|
/// \brief Camera control
|
||||||
class Camera
|
class Camera
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum class ThirdPersonViewMode {Standard, OverShoulder};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ThirdPersonOffsetType { RightShoulder, LeftShoulder, Combat, Swimming };
|
|
||||||
|
|
||||||
struct CamData {
|
struct CamData {
|
||||||
float pitch, yaw, offset;
|
float pitch, yaw, offset;
|
||||||
};
|
};
|
||||||
@ -60,17 +55,14 @@ namespace MWRender
|
|||||||
|
|
||||||
float mCameraDistance;
|
float mCameraDistance;
|
||||||
|
|
||||||
ThirdPersonViewMode mThirdPersonMode;
|
|
||||||
osg::Vec2f mOverShoulderOffset;
|
|
||||||
bool mDefaultShoulderIsRight;
|
|
||||||
osg::Vec3d mFocalPointAdjustment;
|
osg::Vec3d mFocalPointAdjustment;
|
||||||
|
|
||||||
// Makes sense only if mThirdPersonMode is OverShoulder.
|
|
||||||
ThirdPersonOffsetType mThirdPersionOffsetType;
|
|
||||||
osg::Vec2d mFocalPointCurrentOffset;
|
osg::Vec2d mFocalPointCurrentOffset;
|
||||||
|
osg::Vec2d mFocalPointTargetOffset;
|
||||||
float mFocalPointTransitionSpeed;
|
float mFocalPointTransitionSpeed;
|
||||||
|
|
||||||
float mSmoothedSpeed;
|
float mSmoothedSpeed;
|
||||||
|
bool mDynamicCameraDistanceEnabled;
|
||||||
|
bool mShowCrosshairInThirdPersonMode;
|
||||||
|
|
||||||
void updateFocalPointOffset(float duration);
|
void updateFocalPointOffset(float duration);
|
||||||
float getCameraDistanceCorrection() const;
|
float getCameraDistanceCorrection() const;
|
||||||
@ -83,13 +75,10 @@ namespace MWRender
|
|||||||
|
|
||||||
MWWorld::Ptr getTrackingPtr() const;
|
MWWorld::Ptr getTrackingPtr() const;
|
||||||
|
|
||||||
void setThirdPersonViewMode(ThirdPersonViewMode mode) { mThirdPersonMode = mode; }
|
void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; }
|
||||||
ThirdPersonViewMode getThirdPersonViewMode() const { return mThirdPersonMode; }
|
void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; }
|
||||||
|
void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; }
|
||||||
void setOverShoulderOffset(float horizontal, float vertical);
|
void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; }
|
||||||
void switchToLeftShoulder();
|
|
||||||
void switchToRightShoulder();
|
|
||||||
void switchToDefaultShoulder();
|
|
||||||
|
|
||||||
/// Update the view matrix of \a cam
|
/// Update the view matrix of \a cam
|
||||||
void updateCamera(osg::Camera* cam);
|
void updateCamera(osg::Camera* cam);
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "camera.hpp"
|
#include "camera.hpp"
|
||||||
|
#include "viewovershoulder.hpp"
|
||||||
#include "water.hpp"
|
#include "water.hpp"
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
@ -306,6 +307,8 @@ namespace MWRender
|
|||||||
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
|
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
|
||||||
|
|
||||||
mCamera.reset(new Camera(mViewer->getCamera()));
|
mCamera.reset(new Camera(mViewer->getCamera()));
|
||||||
|
if (Settings::Manager::getBool("view over shoulder", "Camera"))
|
||||||
|
mViewOverShoulderController.reset(new ViewOverShoulderController(mCamera.get()));
|
||||||
|
|
||||||
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
||||||
|
|
||||||
@ -366,7 +369,6 @@ namespace MWRender
|
|||||||
float firstPersonFov = Settings::Manager::getFloat("first person field of view", "Camera");
|
float firstPersonFov = Settings::Manager::getFloat("first person field of view", "Camera");
|
||||||
mFirstPersonFieldOfView = std::min(std::max(1.f, firstPersonFov), 179.f);
|
mFirstPersonFieldOfView = std::min(std::max(1.f, firstPersonFov), 179.f);
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
mStateUpdater->setFogEnd(mViewDistance);
|
||||||
updateThirdPersonViewMode();
|
|
||||||
|
|
||||||
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip));
|
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip));
|
||||||
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
||||||
@ -382,19 +384,6 @@ namespace MWRender
|
|||||||
mWorkQueue = nullptr;
|
mWorkQueue = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::updateThirdPersonViewMode()
|
|
||||||
{
|
|
||||||
if (Settings::Manager::getBool("view over shoulder", "Camera"))
|
|
||||||
mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::OverShoulder);
|
|
||||||
else
|
|
||||||
mCamera->setThirdPersonViewMode(Camera::ThirdPersonViewMode::Standard);
|
|
||||||
|
|
||||||
std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera"));
|
|
||||||
float horizontal = 30.f, vertical = -10.f;
|
|
||||||
offset >> horizontal >> vertical;
|
|
||||||
mCamera->setOverShoulderOffset(horizontal, vertical);
|
|
||||||
}
|
|
||||||
|
|
||||||
osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation()
|
osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation()
|
||||||
{
|
{
|
||||||
return mViewer->getIncrementalCompileOperation();
|
return mViewer->getIncrementalCompileOperation();
|
||||||
@ -630,6 +619,8 @@ namespace MWRender
|
|||||||
updateNavMesh();
|
updateNavMesh();
|
||||||
updateRecastMesh();
|
updateRecastMesh();
|
||||||
|
|
||||||
|
if (mViewOverShoulderController)
|
||||||
|
mViewOverShoulderController->update();
|
||||||
mCamera->update(dt, paused);
|
mCamera->update(dt, paused);
|
||||||
|
|
||||||
osg::Vec3d focal, cameraPos;
|
osg::Vec3d focal, cameraPos;
|
||||||
|
@ -79,6 +79,7 @@ namespace MWRender
|
|||||||
class NpcAnimation;
|
class NpcAnimation;
|
||||||
class Pathgrid;
|
class Pathgrid;
|
||||||
class Camera;
|
class Camera;
|
||||||
|
class ViewOverShoulderController;
|
||||||
class Water;
|
class Water;
|
||||||
class TerrainStorage;
|
class TerrainStorage;
|
||||||
class LandManager;
|
class LandManager;
|
||||||
@ -294,6 +295,7 @@ namespace MWRender
|
|||||||
osg::ref_ptr<NpcAnimation> mPlayerAnimation;
|
osg::ref_ptr<NpcAnimation> mPlayerAnimation;
|
||||||
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> mPlayerNode;
|
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> mPlayerNode;
|
||||||
std::unique_ptr<Camera> mCamera;
|
std::unique_ptr<Camera> mCamera;
|
||||||
|
std::unique_ptr<ViewOverShoulderController> mViewOverShoulderController;
|
||||||
osg::Vec3f mCurrentCameraPos;
|
osg::Vec3f mCurrentCameraPos;
|
||||||
|
|
||||||
osg::ref_ptr<StateUpdater> mStateUpdater;
|
osg::ref_ptr<StateUpdater> mStateUpdater;
|
||||||
|
99
apps/openmw/mwrender/viewovershoulder.cpp
Normal file
99
apps/openmw/mwrender/viewovershoulder.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "viewovershoulder.hpp"
|
||||||
|
|
||||||
|
#include <osg/Quat>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/refdata.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/drawstate.hpp"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
ViewOverShoulderController::ViewOverShoulderController(Camera* camera) :
|
||||||
|
mCamera(camera), mMode(Mode::RightShoulder),
|
||||||
|
mAutoSwitchShoulder(Settings::Manager::getBool("auto switch shoulder", "Camera")),
|
||||||
|
mOverShoulderHorizontalOffset(30.f), mOverShoulderVerticalOffset(-10.f)
|
||||||
|
{
|
||||||
|
std::stringstream offset(Settings::Manager::getString("view over shoulder offset", "Camera"));
|
||||||
|
offset >> mOverShoulderHorizontalOffset >> mOverShoulderVerticalOffset;
|
||||||
|
mDefaultShoulderIsRight = mOverShoulderHorizontalOffset >= 0;
|
||||||
|
mOverShoulderHorizontalOffset = std::abs(mOverShoulderHorizontalOffset);
|
||||||
|
|
||||||
|
mCamera->enableDynamicCameraDistance(true);
|
||||||
|
mCamera->enableCrosshairInThirdPersonMode(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewOverShoulderController::update()
|
||||||
|
{
|
||||||
|
if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Mode newMode = mMode;
|
||||||
|
auto ptr = mCamera->getTrackingPtr();
|
||||||
|
if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing)
|
||||||
|
newMode = Mode::Combat;
|
||||||
|
else if (MWBase::Environment::get().getWorld()->isSwimming(ptr))
|
||||||
|
newMode = Mode::Swimming;
|
||||||
|
else if (mMode == Mode::Combat || mMode == Mode::Swimming)
|
||||||
|
newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
|
||||||
|
if (newMode != mMode)
|
||||||
|
{
|
||||||
|
if (newMode == Mode::Combat || mMode == Mode::Combat)
|
||||||
|
mCamera->setFocalPointTransitionSpeed(5.f);
|
||||||
|
else
|
||||||
|
mCamera->setFocalPointTransitionSpeed(1.f);
|
||||||
|
mMode = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder))
|
||||||
|
trySwitchShoulder();
|
||||||
|
|
||||||
|
osg::Vec2d focalPointTargetOffset;
|
||||||
|
switch (mMode)
|
||||||
|
{
|
||||||
|
case Mode::RightShoulder:
|
||||||
|
mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset});
|
||||||
|
break;
|
||||||
|
case Mode::LeftShoulder:
|
||||||
|
mCamera->setFocalPointTargetOffset({-mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset});
|
||||||
|
break;
|
||||||
|
case Mode::Combat:
|
||||||
|
case Mode::Swimming:
|
||||||
|
default:
|
||||||
|
mCamera->setFocalPointTargetOffset({0, 15});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewOverShoulderController::trySwitchShoulder()
|
||||||
|
{
|
||||||
|
const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit
|
||||||
|
const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance
|
||||||
|
|
||||||
|
auto orient = osg::Quat(mCamera->getYaw(), osg::Vec3d(0,0,1));
|
||||||
|
osg::Vec3d playerPos = mCamera->getFocalPoint() - mCamera->getFocalPointOffset();
|
||||||
|
|
||||||
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
osg::Vec3d sideOffset = orient * osg::Vec3d(world->getHalfExtents(mCamera->getTrackingPtr()).x() - 1, 0, 0);
|
||||||
|
float rayRight = world->getDistToNearestRayHit(
|
||||||
|
playerPos + sideOffset, orient * osg::Vec3d(1, 1, 0), limitToSwitchBack + 1);
|
||||||
|
float rayLeft = world->getDistToNearestRayHit(
|
||||||
|
playerPos - sideOffset, orient * osg::Vec3d(-1, 1, 0), limitToSwitchBack + 1);
|
||||||
|
float rayForward = world->getDistToNearestRayHit(
|
||||||
|
playerPos, orient * osg::Vec3d(0, 1, 0), limitToSwitchBack + 1);
|
||||||
|
|
||||||
|
if (rayLeft < limitToSwitch && rayRight > limitToSwitchBack)
|
||||||
|
mMode = Mode::RightShoulder;
|
||||||
|
else if (rayRight < limitToSwitch && rayLeft > limitToSwitchBack)
|
||||||
|
mMode = Mode::LeftShoulder;
|
||||||
|
else if (rayLeft > limitToSwitchBack && rayRight > limitToSwitchBack && rayForward > limitToSwitchBack)
|
||||||
|
mMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
apps/openmw/mwrender/viewovershoulder.hpp
Normal file
30
apps/openmw/mwrender/viewovershoulder.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef VIEWOVERSHOULDER_H
|
||||||
|
#define VIEWOVERSHOULDER_H
|
||||||
|
|
||||||
|
#include "camera.hpp"
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
class ViewOverShoulderController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewOverShoulderController(Camera* camera);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void trySwitchShoulder();
|
||||||
|
enum class Mode { RightShoulder, LeftShoulder, Combat, Swimming };
|
||||||
|
|
||||||
|
Camera* mCamera;
|
||||||
|
Mode mMode;
|
||||||
|
bool mAutoSwitchShoulder;
|
||||||
|
float mOverShoulderHorizontalOffset;
|
||||||
|
float mOverShoulderVerticalOffset;
|
||||||
|
bool mDefaultShoulderIsRight;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VIEWOVERSHOULDER_H
|
@ -1869,44 +1869,13 @@ namespace MWWorld
|
|||||||
float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f;
|
float cameraObstacleLimit = mRendering->getNearClipDistance() * 2.5f;
|
||||||
float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f);
|
float focalObstacleLimit = std::max(cameraObstacleLimit, 10.0f);
|
||||||
|
|
||||||
|
// Adjust focal point.
|
||||||
osg::Vec3d focal = camera->getFocalPoint();
|
osg::Vec3d focal = camera->getFocalPoint();
|
||||||
osg::Vec3d focalOffset = camera->getFocalPointOffset();
|
osg::Vec3d focalOffset = camera->getFocalPointOffset();
|
||||||
osg::Vec3d playerPos = focal - focalOffset;
|
|
||||||
|
|
||||||
static const bool autoSwitchShoulder = Settings::Manager::getBool("auto switch shoulder", "Camera");
|
|
||||||
if (camera->getThirdPersonViewMode() == MWRender::Camera::ThirdPersonViewMode::OverShoulder
|
|
||||||
&& autoSwitchShoulder && !camera->isVanityOrPreviewModeEnabled())
|
|
||||||
{
|
|
||||||
const float limitToSwitch = 120; // switch to other shoulder if wall is closer than this limit
|
|
||||||
const float limitToSwitchBack = 300; // switch back to default shoulder if there is no walls at this distance
|
|
||||||
auto orient = osg::Quat(camera->getYaw(), osg::Vec3d(0,0,1));
|
|
||||||
int mask = MWPhysics::CollisionType_World | MWPhysics::CollisionType_Door | MWPhysics::CollisionType_HeightMap;
|
|
||||||
MWPhysics::PhysicsSystem::RayResult rayRight = mPhysics->castRay(
|
|
||||||
playerPos + orient * osg::Vec3d(28, 0, 0),
|
|
||||||
playerPos + orient * osg::Vec3d(limitToSwitchBack, limitToSwitchBack, 0),
|
|
||||||
{}, {}, mask);
|
|
||||||
MWPhysics::PhysicsSystem::RayResult rayLeft = mPhysics->castRay(
|
|
||||||
playerPos + orient * osg::Vec3d(-28, 0, 0),
|
|
||||||
playerPos + orient * osg::Vec3d(-limitToSwitchBack, limitToSwitchBack, 0),
|
|
||||||
{}, {}, mask);
|
|
||||||
MWPhysics::PhysicsSystem::RayResult rayForward = mPhysics->castRay(
|
|
||||||
playerPos, playerPos + orient * osg::Vec3d(0, limitToSwitchBack, 0),
|
|
||||||
{}, {}, mask);
|
|
||||||
bool rightTooClose = rayRight.mHit && (rayRight.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch;
|
|
||||||
bool leftTooClose = rayLeft.mHit && (rayLeft.mHitPos - playerPos).length2() < limitToSwitch * limitToSwitch;
|
|
||||||
if (!rayRight.mHit && leftTooClose)
|
|
||||||
camera->switchToRightShoulder();
|
|
||||||
else if (!rayLeft.mHit && rightTooClose)
|
|
||||||
camera->switchToLeftShoulder();
|
|
||||||
else if (!rayRight.mHit && !rayLeft.mHit && !rayForward.mHit)
|
|
||||||
camera->switchToDefaultShoulder();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust focal point.
|
|
||||||
float offsetLen = focalOffset.length();
|
float offsetLen = focalOffset.length();
|
||||||
if (offsetLen > 0)
|
if (offsetLen > 0)
|
||||||
{
|
{
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(playerPos, focal, focalObstacleLimit);
|
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castSphere(focal - focalOffset, focal, focalObstacleLimit);
|
||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user