1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-21 09:23:51 +00:00

Make transition in 'auto switch shoulder' smoother.

This commit is contained in:
Petr Mikheev 2020-07-12 01:55:20 +02:00
parent 51173ebcf5
commit 173c1fdabb
3 changed files with 53 additions and 21 deletions

View file

@ -64,7 +64,8 @@ namespace MWRender
mCameraDistance(0.f), mCameraDistance(0.f),
mFocalPointCurrentOffset(osg::Vec2d()), mFocalPointCurrentOffset(osg::Vec2d()),
mFocalPointTargetOffset(osg::Vec2d()), mFocalPointTargetOffset(osg::Vec2d()),
mFocalPointTransitionSpeed(1.f), mFocalPointTransitionSpeedCoef(1.f),
mPreviousTransitionInfluence(0.f),
mSmoothedSpeed(0.f), mSmoothedSpeed(0.f),
mDynamicCameraDistanceEnabled(false), mDynamicCameraDistanceEnabled(false),
mShowCrosshairInThirdPersonMode(false) mShowCrosshairInThirdPersonMode(false)
@ -221,16 +222,44 @@ namespace MWRender
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta); mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);
} }
void Camera::setFocalPointTargetOffset(osg::Vec2d v)
{
mFocalPointTargetOffset = v;
mPreviousTransitionSpeed = mFocalPointTransitionSpeed;
mPreviousTransitionInfluence = 1.0f;
}
void Camera::updateFocalPointOffset(float duration) void Camera::updateFocalPointOffset(float duration)
{ {
if (duration <= 0)
return;
osg::Vec2d oldOffset = mFocalPointCurrentOffset;
if (mPreviousTransitionInfluence > 0)
{
mFocalPointCurrentOffset -= mPreviousExtraOffset;
mPreviousExtraOffset = mPreviousExtraOffset / mPreviousTransitionInfluence + mPreviousTransitionSpeed * duration;
mPreviousTransitionInfluence =
std::max(0.f, mPreviousTransitionInfluence - duration * mFocalPointTransitionSpeedCoef);
mPreviousExtraOffset *= mPreviousTransitionInfluence;
mFocalPointCurrentOffset += mPreviousExtraOffset;
}
osg::Vec2d delta = mFocalPointTargetOffset - mFocalPointCurrentOffset; osg::Vec2d delta = mFocalPointTargetOffset - 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()) *
mFocalPointTransitionSpeedCoef * (1.0f - mPreviousTransitionInfluence);
mFocalPointCurrentOffset += delta * std::min(coef, 1.0f); mFocalPointCurrentOffset += delta * std::min(coef, 1.0f);
} }
else else
mFocalPointTransitionSpeed = 1.f; {
mPreviousExtraOffset = osg::Vec2d();
mPreviousTransitionInfluence = 0.f;
}
mFocalPointTransitionSpeed = (mFocalPointCurrentOffset - oldOffset) / duration;
} }
void Camera::toggleViewMode(bool force) void Camera::toggleViewMode(bool force)

View file

@ -58,7 +58,13 @@ namespace MWRender
osg::Vec3d mFocalPointAdjustment; osg::Vec3d mFocalPointAdjustment;
osg::Vec2d mFocalPointCurrentOffset; osg::Vec2d mFocalPointCurrentOffset;
osg::Vec2d mFocalPointTargetOffset; osg::Vec2d mFocalPointTargetOffset;
float mFocalPointTransitionSpeed; float mFocalPointTransitionSpeedCoef;
// This fields are used to make focal point transition smooth if previous transition was not finished.
float mPreviousTransitionInfluence;
osg::Vec2d mFocalPointTransitionSpeed;
osg::Vec2d mPreviousTransitionSpeed;
osg::Vec2d mPreviousExtraOffset;
float mSmoothedSpeed; float mSmoothedSpeed;
bool mDynamicCameraDistanceEnabled; bool mDynamicCameraDistanceEnabled;
@ -75,8 +81,8 @@ namespace MWRender
MWWorld::Ptr getTrackingPtr() const; MWWorld::Ptr getTrackingPtr() const;
void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeed = v; } void setFocalPointTransitionSpeed(float v) { mFocalPointTransitionSpeedCoef = v; }
void setFocalPointTargetOffset(osg::Vec2d v) { mFocalPointTargetOffset = v; } void setFocalPointTargetOffset(osg::Vec2d v);
void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; } void enableDynamicCameraDistance(bool v) { mDynamicCameraDistanceEnabled = v; }
void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; } void enableCrosshairInThirdPersonMode(bool v) { mShowCrosshairInThirdPersonMode = v; }

View file

@ -28,6 +28,7 @@ namespace MWRender
mCamera->enableDynamicCameraDistance(true); mCamera->enableDynamicCameraDistance(true);
mCamera->enableCrosshairInThirdPersonMode(true); mCamera->enableCrosshairInThirdPersonMode(true);
mCamera->setFocalPointTargetOffset({mOverShoulderHorizontalOffset, mOverShoulderVerticalOffset});
} }
void ViewOverShoulderController::update() void ViewOverShoulderController::update()
@ -35,27 +36,23 @@ namespace MWRender
if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson()) if (mCamera->isVanityOrPreviewModeEnabled() || mCamera->isFirstPerson())
return; return;
Mode newMode = mMode; Mode oldMode = mMode;
auto ptr = mCamera->getTrackingPtr(); auto ptr = mCamera->getTrackingPtr();
if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing) if (ptr.getClass().isActor() && ptr.getClass().getCreatureStats(ptr).getDrawState() != MWMechanics::DrawState_Nothing)
newMode = Mode::Combat; mMode = Mode::Combat;
else if (MWBase::Environment::get().getWorld()->isSwimming(ptr)) else if (MWBase::Environment::get().getWorld()->isSwimming(ptr))
newMode = Mode::Swimming; mMode = Mode::Swimming;
else if (mMode == Mode::Combat || mMode == Mode::Swimming) else if (oldMode == Mode::Combat || oldMode == Mode::Swimming)
newMode = mDefaultShoulderIsRight ? Mode::RightShoulder : Mode::LeftShoulder; mMode = 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)) if (mAutoSwitchShoulder && (mMode == Mode::LeftShoulder || mMode == Mode::RightShoulder))
trySwitchShoulder(); trySwitchShoulder();
if (oldMode == mMode) return;
if (oldMode == Mode::Combat || mMode == Mode::Combat)
mCamera->setFocalPointTransitionSpeed(5.f);
else
mCamera->setFocalPointTransitionSpeed(1.f);
osg::Vec2d focalPointTargetOffset;
switch (mMode) switch (mMode)
{ {
case Mode::RightShoulder: case Mode::RightShoulder: