diff --git a/AUTHORS.md b/AUTHORS.md
index 8873113da2..4d03fba227 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -79,6 +79,7 @@ Programmers
Eduard Cot (trombonecot)
Eli2
Emanuel Guével (potatoesmaster)
+ Epoch
Eris Caffee (eris)
eroen
escondida
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93eb959e18..c2a8c8e34d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -146,6 +146,7 @@
Feature #5173: Support for NiFogProperty
Feature #5492: Let rain and snow collide with statics
Feature #5926: Refraction based on water depth
+ Feature #5944: Option to use camera as sound listener
Feature #6149: Dehardcode Lua API_REVISION
Feature #6152: Playing music via lua scripts
Feature #6188: Specular lighting from point light sources
diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp
index c274b75f79..0b5f542888 100644
--- a/apps/launcher/settingspage.cpp
+++ b/apps/launcher/settingspage.cpp
@@ -294,6 +294,7 @@ bool Launcher::SettingsPage::loadSettings()
hrtfProfileSelectorComboBox->setCurrentIndex(hrtfProfileIndex);
}
}
+ loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox);
}
// Interface Changes
@@ -490,6 +491,9 @@ void Launcher::SettingsPage::saveSettings()
Settings::sound().mHrtf.set(hrtfProfileSelectorComboBox->currentText().toStdString());
else
Settings::sound().mHrtf.set({});
+
+ const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked;
+ Settings::sound().mCameraListener.set(cCameraListener);
}
// Interface Changes
diff --git a/apps/launcher/ui/settingspage.ui b/apps/launcher/ui/settingspage.ui
index a59891eb54..ca23ec1bb4 100644
--- a/apps/launcher/ui/settingspage.ui
+++ b/apps/launcher/ui/settingspage.ui
@@ -1320,6 +1320,16 @@
+ -
+
+
+ In third-person view, use the camera as the sound listener instead of the player character.
+
+
+ Use the camera as the sound listener
+
+
+
-
diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp
index 86d5699d75..1c163a6701 100644
--- a/apps/openmw/mwrender/camera.cpp
+++ b/apps/openmw/mwrender/camera.cpp
@@ -109,8 +109,7 @@ namespace MWRender
void Camera::updateCamera(osg::Camera* cam)
{
- osg::Quat orient = osg::Quat(mRoll + mExtraRoll, osg::Vec3d(0, 1, 0))
- * osg::Quat(mPitch + mExtraPitch, osg::Vec3d(1, 0, 0)) * osg::Quat(mYaw + mExtraYaw, osg::Vec3d(0, 0, 1));
+ osg::Quat orient = getOrient();
osg::Vec3d forward = orient * osg::Vec3d(0, 1, 0);
osg::Vec3d up = orient * osg::Vec3d(0, 0, 1);
@@ -209,6 +208,12 @@ namespace MWRender
mPosition = focal + offset;
}
+ osg::Quat Camera::getOrient() const
+ {
+ return osg::Quat(mRoll + mExtraRoll, osg::Vec3d(0, 1, 0)) * osg::Quat(mPitch + mExtraPitch, osg::Vec3d(1, 0, 0))
+ * osg::Quat(mYaw + mExtraYaw, osg::Vec3d(0, 0, 1));
+ }
+
void Camera::setMode(Mode newMode, bool force)
{
if (mMode == newMode)
diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp
index c6500160fd..e09a265293 100644
--- a/apps/openmw/mwrender/camera.hpp
+++ b/apps/openmw/mwrender/camera.hpp
@@ -72,6 +72,8 @@ namespace MWRender
void setExtraYaw(float angle) { mExtraYaw = angle; }
void setExtraRoll(float angle) { mExtraRoll = angle; }
+ osg::Quat getOrient() const;
+
/// @param Force view mode switch, even if currently not allowed by the animation.
void toggleViewMode(bool force = false);
bool toggleVanityMode(bool enable);
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index e28efbf671..cbef6789f1 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -1738,23 +1738,27 @@ namespace MWWorld
void World::updateSoundListener()
{
- osg::Vec3f cameraPosition = mRendering->getCamera()->getPosition();
+ const MWRender::Camera* camera = mRendering->getCamera();
const auto& player = getPlayerPtr();
const ESM::Position& refpos = player.getRefData().getPosition();
- osg::Vec3f listenerPos;
+ osg::Vec3f listenerPos, up, forward;
+ osg::Quat listenerOrient;
- if (isFirstPerson())
- listenerPos = cameraPosition;
+ if (isFirstPerson() || Settings::sound().mCameraListener)
+ listenerPos = camera->getPosition();
else
listenerPos = refpos.asVec3() + osg::Vec3f(0, 0, 1.85f * mPhysics->getHalfExtents(player).z());
- osg::Quat listenerOrient = osg::Quat(refpos.rot[1], osg::Vec3f(0, -1, 0))
- * osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1));
+ if (isFirstPerson() || Settings::sound().mCameraListener)
+ listenerOrient = camera->getOrient();
+ else
+ listenerOrient = osg::Quat(refpos.rot[1], osg::Vec3f(0, -1, 0))
+ * osg::Quat(refpos.rot[0], osg::Vec3f(-1, 0, 0)) * osg::Quat(refpos.rot[2], osg::Vec3f(0, 0, -1));
- osg::Vec3f forward = listenerOrient * osg::Vec3f(0, 1, 0);
- osg::Vec3f up = listenerOrient * osg::Vec3f(0, 0, 1);
+ forward = listenerOrient * osg::Vec3f(0, 1, 0);
+ up = listenerOrient * osg::Vec3f(0, 0, 1);
- bool underwater = isUnderwater(player.getCell(), cameraPosition);
+ bool underwater = isUnderwater(player.getCell(), camera->getPosition());
MWBase::Environment::get().getSoundManager()->setListenerPosDir(listenerPos, forward, up, underwater);
}
diff --git a/components/settings/categories/sound.hpp b/components/settings/categories/sound.hpp
index 995bce2a58..8398a38c55 100644
--- a/components/settings/categories/sound.hpp
+++ b/components/settings/categories/sound.hpp
@@ -23,6 +23,7 @@ namespace Settings
SettingValue mBufferCacheMax{ mIndex, "Sound", "buffer cache max", makeMaxSanitizerInt(1) };
SettingValue mHrtfEnable{ mIndex, "Sound", "hrtf enable" };
SettingValue mHrtf{ mIndex, "Sound", "hrtf" };
+ SettingValue mCameraListener{ mIndex, "Sound", "camera listener" };
};
}
diff --git a/docs/source/reference/modding/settings/sound.rst b/docs/source/reference/modding/settings/sound.rst
index 7a5718735c..dbcad65d0d 100644
--- a/docs/source/reference/modding/settings/sound.rst
+++ b/docs/source/reference/modding/settings/sound.rst
@@ -127,3 +127,16 @@ Allowed values for this field are enumerated in openmw.log file is an HRTF enabl
The default value is empty, which uses the default profile.
This setting can be controlled in the Settings tab of the launcher.
+
+camera listener
+---------------
+
+:Type: boolean
+:Range: True/False
+:Default: False
+
+When true, uses the camera position and direction for audio instead of the player position.
+This makes audio in third person sound relative to camera instead of the player.
+False is vanilla Morrowind behaviour.
+
+This setting can be controlled in the Settings tab of the launcher.
\ No newline at end of file
diff --git a/files/lang/launcher_de.ts b/files/lang/launcher_de.ts
index 3b911e2288..11dd865c56 100644
--- a/files/lang/launcher_de.ts
+++ b/files/lang/launcher_de.ts
@@ -1447,5 +1447,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
+
+
+
+
+
+
+
+
diff --git a/files/lang/launcher_fr.ts b/files/lang/launcher_fr.ts
index 757121d1d3..5df4822808 100644
--- a/files/lang/launcher_fr.ts
+++ b/files/lang/launcher_fr.ts
@@ -1447,5 +1447,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
+
+
+
+
+
+
+
+
diff --git a/files/lang/launcher_ru.ts b/files/lang/launcher_ru.ts
index dad899aff6..1db804e2df 100644
--- a/files/lang/launcher_ru.ts
+++ b/files/lang/launcher_ru.ts
@@ -1462,5 +1462,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
Минимальный уровень освещения в помещениях
+
+
+ Использовать в виде от третьего лица положение камеры, а не персонажа игрока для прослушивания звуков.
+
+
+
+ Использовать камеру как слушателя
+
diff --git a/files/settings-default.cfg b/files/settings-default.cfg
index 4a90a46cc5..1caf03c123 100644
--- a/files/settings-default.cfg
+++ b/files/settings-default.cfg
@@ -608,6 +608,9 @@ hrtf enable = -1
# Specifies which HRTF to use when HRTF is used. Blank means use the default.
hrtf =
+# Specifies whether to use camera as audio listener
+camera listener = false
+
[Video]
# Resolution of the OpenMW window or screen.