1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-25 06:35:30 +00:00

Add head bobbing in first person mode

This commit is contained in:
Petr Mikheev 2020-10-04 20:12:45 +02:00
parent ee22081ae1
commit be27b51279
7 changed files with 108 additions and 3 deletions

View File

@ -54,6 +54,7 @@
Feature #390: 3rd person look "over the shoulder"
Feature #2386: Distant Statics in the form of Object Paging
Feature #4894: Consider actors as obstacles for pathfinding
Feature #5043: Head Bobbing
Feature #5297: Add a search function to the "Datafiles" tab of the OpenMW launcher
Feature #5362: Show the soul gems' trapped soul in count dialog
Feature #5445: Handle NiLines

View File

@ -133,6 +133,7 @@ bool Launcher::AdvancedPage::loadSettings()
loadSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera");
loadSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera");
loadSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera");
loadSettingBool(headBobbingCheckBox, "head bobbing", "Camera");
defaultShoulderComboBox->setCurrentIndex(
mEngineSettings.getVector2("view over shoulder offset", "Camera").x() >= 0 ? 0 : 1);
}
@ -247,6 +248,7 @@ void Launcher::AdvancedPage::saveSettings()
saveSettingBool(autoSwitchShoulderCheckBox, "auto switch shoulder", "Camera");
saveSettingBool(previewIfStandStillCheckBox, "preview if stand still", "Camera");
saveSettingBool(deferredPreviewRotationCheckBox, "deferred preview rotation", "Camera");
saveSettingBool(headBobbingCheckBox, "head bobbing", "Camera");
osg::Vec2f shoulderOffset = mEngineSettings.getVector2("view over shoulder offset", "Camera");
if (defaultShoulderComboBox->currentIndex() != (shoulderOffset.x() >= 0 ? 0 : 1))

View File

@ -80,6 +80,7 @@ namespace MWRender
mZoomOutWhenMoveCoef(Settings::Manager::getFloat("zoom out when move coef", "Camera")),
mDynamicCameraDistanceEnabled(false),
mShowCrosshairInThirdPersonMode(false),
mHeadBobbingEnabled(Settings::Manager::getBool("head bobbing", "Camera")),
mDeferredRotation(osg::Vec3f()),
mDeferredRotationDisabled(false)
{
@ -104,7 +105,9 @@ namespace MWRender
osg::Matrix worldMat = osg::computeLocalToWorld(nodepaths[0]);
osg::Vec3d position = worldMat.getTrans();
if (!isFirstPerson())
if (isFirstPerson())
position.z() += mHeadBobbingOffset;
else
{
position.z() += mHeight * mHeightScale;
@ -143,13 +146,31 @@ namespace MWRender
osg::Vec3d focal, position;
getPosition(focal, position);
osg::Quat orient = osg::Quat(getPitch(), osg::Vec3d(1,0,0)) * osg::Quat(getYaw(), osg::Vec3d(0,0,1));
osg::Quat orient = osg::Quat(mRoll, osg::Vec3d(0, 1, 0)) * osg::Quat(mPitch, osg::Vec3d(1, 0, 0)) * osg::Quat(mYaw, osg::Vec3d(0, 0, 1));
osg::Vec3d forward = orient * osg::Vec3d(0,1,0);
osg::Vec3d up = orient * osg::Vec3d(0,0,1);
cam->setViewMatrixAsLookAt(position, position + forward, up);
}
void Camera::updateHeadBobbing(float duration) {
static const float doubleStepLength = Settings::Manager::getFloat("head bobbing step", "Camera") * 2;
static const float stepHeight = Settings::Manager::getFloat("head bobbing height", "Camera");
static const float maxRoll = osg::DegreesToRadians(Settings::Manager::getFloat("head bobbing roll", "Camera"));
if (MWBase::Environment::get().getWorld()->isOnGround(mTrackingPtr))
mHeadBobbingWeight = std::min(mHeadBobbingWeight + duration * 5, 1.f);
else
mHeadBobbingWeight = std::max(mHeadBobbingWeight - duration * 5, 0.f);
float doubleStepState = mTotalMovement / doubleStepLength - std::floor(mTotalMovement / doubleStepLength); // from 0 to 1 during 2 steps
float stepState = std::abs(doubleStepState * 4 - 2) - 1; // from -1 to 1 on even steps and from 1 to -1 on odd steps
float effect = (1 - std::cos(stepState * osg::DegreesToRadians(30.f))) * 7.5f; // range from 0 to 1
float coef = std::min(mSmoothedSpeed / 300.f, 1.f) * mHeadBobbingWeight;
mHeadBobbingOffset = (0.5f - effect) * coef * stepHeight; // range from -stepHeight/2 to stepHeight/2
mRoll = osg::sign(stepState) * effect * coef * maxRoll; // range from -maxRoll to maxRoll
}
void Camera::reset()
{
togglePreviewMode(false);
@ -198,10 +219,16 @@ namespace MWRender
if(mMode == Mode::Vanity)
rotateCamera(0.f, osg::DegreesToRadians(3.f * duration), true);
if (isFirstPerson() && mHeadBobbingEnabled)
updateHeadBobbing(duration);
else
mRoll = mHeadBobbingOffset = 0;
updateFocalPointOffset(duration);
updatePosition();
float speed = mTrackingPtr.getClass().getCurrentSpeed(mTrackingPtr);
mTotalMovement += speed * duration;
speed /= (1.f + speed / 500.f);
float maxDelta = 300.f * duration;
mSmoothedSpeed += osg::clampBetween(speed - mSmoothedSpeed, -maxDelta, maxDelta);

View File

@ -46,7 +46,7 @@ namespace MWRender
bool mIsNearest;
float mHeight, mBaseCameraDistance;
float mPitch, mYaw;
float mPitch, mYaw, mRoll;
bool mVanityToggleQueued;
bool mVanityToggleQueuedValue;
@ -72,6 +72,12 @@ namespace MWRender
bool mDynamicCameraDistanceEnabled;
bool mShowCrosshairInThirdPersonMode;
bool mHeadBobbingEnabled;
float mHeadBobbingOffset;
float mHeadBobbingWeight = 0; // Value from 0 to 1 for smooth enabling/disabling.
float mTotalMovement = 0; // Needed for head bobbing.
void updateHeadBobbing(float duration);
void updateFocalPointOffset(float duration);
void updatePosition();
float getCameraDistanceCorrection() const;

View File

@ -199,3 +199,50 @@ If disabled then the camera rotates rather than the character.
This setting can be controlled in Advanced tab of the launcher.
head bobbing
------------
:Type: boolean
:Range: True/False
:Default: False
Enables head bobbing when move in first person mode.
This setting can be controlled in Advanced tab of the launcher.
head bobbing step
-----------------
:Type: floating point
:Range: >0
:Default: 90.0
Makes diffence only in first person mode if 'head bobbing' is enabled.
Length of each step.
This setting can only be configured by editing the settings configuration file.
head bobbing height
-------------------
:Type: floating point
:Range: Any
:Default: 3.0
Makes diffence only in first person mode if 'head bobbing' is enabled.
Amplitude of the head bobbing.
This setting can only be configured by editing the settings configuration file.
head bobbing roll
-----------------
:Type: floating point
:Range: 0-90
:Default: 0.2
Makes diffence only in first person mode if 'head bobbing' is enabled.
Maximum roll angle in degrees.
This setting can only be configured by editing the settings configuration file.

View File

@ -54,6 +54,18 @@ preview if stand still = false
# Rotate the character to the view direction after exiting preview mode.
deferred preview rotation = true
# Enables head bobbing in first person mode
head bobbing = false
# Length of each step
head bobbing step = 90.0
# Amplitude of the bobbing effect
head bobbing height = 3.0
# Maximum camera roll angle (degrees)
head bobbing roll = 0.2
[Cells]
# Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled.

View File

@ -553,6 +553,16 @@ True: In non-combat mode camera is positioned behind the character's shoulder. C
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="headBobbingCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enables head bobbing when move in first person mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Head bobbing in 1st person mode</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">