1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-10-15 08:56:35 +00:00

Merge branch 'skibidi-dop-doppler' into 'master'

Doppler, take two

See merge request OpenMW/openmw!4660
This commit is contained in:
Alexei Kotov 2025-08-04 09:24:50 +03:00
commit aae81264a2
23 changed files with 180 additions and 31 deletions

View file

@ -291,6 +291,7 @@ bool Launcher::SettingsPage::loadSettings()
} }
} }
loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox); loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox);
dopplerSpinBox->setValue(Settings::sound().mDopplerFactor);
} }
// Interface Changes // Interface Changes
@ -482,6 +483,8 @@ void Launcher::SettingsPage::saveSettings()
const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked; const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked;
Settings::sound().mCameraListener.set(cCameraListener); Settings::sound().mCameraListener.set(cCameraListener);
Settings::sound().mDopplerFactor.set(dopplerSpinBox->value());
} }
// Interface Changes // Interface Changes

View file

@ -1224,6 +1224,51 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QLabel" name="dopplerLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Doppler Factor</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="dopplerSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>283</width>
<height>0</height>
</size>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.250000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<spacer> <spacer>
<property name="orientation"> <property name="orientation">

View file

@ -234,6 +234,8 @@ namespace MWBase
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater) const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater)
= 0; = 0;
virtual void setListenerVel(const osg::Vec3f& vel) = 0;
virtual void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) = 0; virtual void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) = 0;
void setSimulationTimeScale(float scale) { mSimulationTimeScale = scale; } void setSimulationTimeScale(float scale) { mSimulationTimeScale = scale; }

View file

@ -496,6 +496,8 @@ namespace MWBase
virtual float getSunVisibility() const = 0; virtual float getSunVisibility() const = 0;
virtual float getSunPercentage() const = 0; virtual float getSunPercentage() const = 0;
virtual float getPhysicsFrameRateDt() const = 0;
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0; virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker) /// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)

View file

@ -93,9 +93,10 @@ namespace
namespace MWPhysics namespace MWPhysics
{ {
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode) PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
: mShapeManager( : mPhysicsDt(1.f / 60.f)
std::make_unique<Resource::BulletShapeManager>(resourceSystem->getVFS(), resourceSystem->getSceneManager(), , mShapeManager(std::make_unique<Resource::BulletShapeManager>(resourceSystem->getVFS(),
resourceSystem->getNifFileManager(), Settings::cells().mCacheExpiryDelay)) resourceSystem->getSceneManager(), resourceSystem->getNifFileManager(),
Settings::cells().mCacheExpiryDelay))
, mResourceSystem(resourceSystem) , mResourceSystem(resourceSystem)
, mDebugDrawEnabled(false) , mDebugDrawEnabled(false)
, mTimeAccum(0.0f) , mTimeAccum(0.0f)
@ -103,7 +104,6 @@ namespace MWPhysics
, mWaterHeight(0) , mWaterHeight(0)
, mWaterEnabled(false) , mWaterEnabled(false)
, mParentNode(std::move(parentNode)) , mParentNode(std::move(parentNode))
, mPhysicsDt(1.f / 60.f)
{ {
mResourceSystem->addResourceManager(mShapeManager.get()); mResourceSystem->addResourceManager(mShapeManager.get());

View file

@ -287,6 +287,8 @@ namespace MWPhysics
void reportStats(unsigned int frameNumber, osg::Stats& stats) const; void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
void reportCollision(const btVector3& position, const btVector3& normal); void reportCollision(const btVector3& position, const btVector3& normal);
float mPhysicsDt;
private: private:
void updateWater(); void updateWater();
@ -330,8 +332,6 @@ namespace MWPhysics
osg::ref_ptr<osg::Group> mParentNode; osg::ref_ptr<osg::Group> mParentNode;
float mPhysicsDt;
std::size_t mSimulationsCounter = 0; std::size_t mSimulationsCounter = 0;
std::array<std::vector<Simulation>, 2> mSimulations; std::array<std::vector<Simulation>, 2> mSimulations;
std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>> mActorsPositions; std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>> mActorsPositions;

View file

@ -15,6 +15,7 @@
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/misc/thread.hpp> #include <components/misc/thread.hpp>
#include <components/settings/values.hpp>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#include "efxpresets.h" #include "efxpresets.h"
@ -963,6 +964,7 @@ namespace MWSound
// Speed of sound is in units per second. Take the sound speed in air (assumed // Speed of sound is in units per second. Take the sound speed in air (assumed
// meters per second), multiply by the units per meter to get the speed in u/s. // meters per second), multiply by the units per meter to get the speed in u/s.
alSpeedOfSound(Constants::SoundSpeedInAir * Constants::UnitsPerMeter); alSpeedOfSound(Constants::SoundSpeedInAir * Constants::UnitsPerMeter);
alDopplerFactor(Settings::sound().mDopplerFactor);
alGetError(); alGetError();
mInitialized = true; mInitialized = true;
@ -1142,8 +1144,8 @@ namespace MWSound
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
} }
void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist,
ALfloat gain, ALfloat pitch, bool loop, bool useenv) ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv)
{ {
alSourcef(source, AL_REFERENCE_DISTANCE, mindist); alSourcef(source, AL_REFERENCE_DISTANCE, mindist);
alSourcef(source, AL_MAX_DISTANCE, maxdist); alSourcef(source, AL_MAX_DISTANCE, maxdist);
@ -1179,11 +1181,11 @@ namespace MWSound
alSourcef(source, AL_PITCH, pitch); alSourcef(source, AL_PITCH, pitch);
alSourcefv(source, AL_POSITION, pos.ptr()); alSourcefv(source, AL_POSITION, pos.ptr());
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSourcefv(source, AL_VELOCITY, vel.ptr());
} }
void OpenALOutput::updateCommon( void OpenALOutput::updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist,
ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv) ALfloat gain, ALfloat pitch, bool useenv)
{ {
if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter) if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
{ {
@ -1195,7 +1197,7 @@ namespace MWSound
alSourcef(source, AL_PITCH, pitch); alSourcef(source, AL_PITCH, pitch);
alSourcefv(source, AL_POSITION, pos.ptr()); alSourcefv(source, AL_POSITION, pos.ptr());
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f); alSourcefv(source, AL_VELOCITY, vel.ptr());
} }
bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset) bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset)
@ -1248,8 +1250,9 @@ namespace MWSound
} }
source = mFreeSources.front(); source = mFreeSources.front();
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(), initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(), sound->getUseEnv()); sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(),
sound->getUseEnv());
alSourcei(source, AL_BUFFER, GET_PTRID(data)); alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcef(source, AL_SEC_OFFSET, offset); alSourcef(source, AL_SEC_OFFSET, offset);
if (getALError() != AL_NO_ERROR) if (getALError() != AL_NO_ERROR)
@ -1312,8 +1315,8 @@ namespace MWSound
return; return;
ALuint source = GET_PTRID(sound->mHandle); ALuint source = GET_PTRID(sound->mHandle);
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(), updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
getTimeScaledPitch(sound), sound->getUseEnv()); sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
getALError(); getALError();
} }
@ -1360,8 +1363,8 @@ namespace MWSound
if (sound->getIsLooping()) if (sound->getIsLooping())
Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\""; Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\"";
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(), initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv()); sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv());
if (getALError() != AL_NO_ERROR) if (getALError() != AL_NO_ERROR)
return false; return false;
@ -1443,8 +1446,8 @@ namespace MWSound
OpenAL_SoundStream* stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle); OpenAL_SoundStream* stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
ALuint source = stream->mSource; ALuint source = stream->mSource;
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(), updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
getTimeScaledPitch(sound), sound->getUseEnv()); sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
getALError(); getALError();
} }
@ -1459,12 +1462,13 @@ namespace MWSound
} }
void OpenALOutput::updateListener( void OpenALOutput::updateListener(
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, const osg::Vec3f& vel, Environment env)
{ {
if (mContext) if (mContext)
{ {
ALfloat orient[6] = { atdir.x(), atdir.y(), atdir.z(), updir.x(), updir.y(), updir.z() }; ALfloat orient[6] = { atdir.x(), atdir.y(), atdir.z(), updir.x(), updir.y(), updir.z() };
alListenerfv(AL_POSITION, pos.ptr()); alListenerfv(AL_POSITION, pos.ptr());
alListenerfv(AL_VELOCITY, vel.ptr());
alListenerfv(AL_ORIENTATION, orient); alListenerfv(AL_ORIENTATION, orient);
if (env != mListenerEnv) if (env != mListenerEnv)
@ -1497,6 +1501,7 @@ namespace MWSound
} }
mListenerPos = pos; mListenerPos = pos;
mListenerVel = vel;
mListenerEnv = env; mListenerEnv = env;
} }
@ -1582,7 +1587,6 @@ namespace MWSound
: SoundOutput(mgr) : SoundOutput(mgr)
, mDevice(nullptr) , mDevice(nullptr)
, mContext(nullptr) , mContext(nullptr)
, mListenerPos(0.0f, 0.0f, 0.0f)
, mListenerEnv(Env_Normal) , mListenerEnv(Env_Normal)
, mWaterFilter(0) , mWaterFilter(0)
, mWaterEffect(0) , mWaterEffect(0)

View file

@ -46,6 +46,7 @@ namespace MWSound
StreamVec mActiveStreams; StreamVec mActiveStreams;
osg::Vec3f mListenerPos; osg::Vec3f mListenerPos;
osg::Vec3f mListenerVel;
Environment mListenerEnv; Environment mListenerEnv;
ALuint mWaterFilter; ALuint mWaterFilter;
@ -64,11 +65,11 @@ namespace MWSound
std::unique_ptr<DefaultDeviceThread> mDefaultDeviceThread; std::unique_ptr<DefaultDeviceThread> mDefaultDeviceThread;
void initCommon2D(ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv); void initCommon2D(ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
void initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, ALfloat gain, void initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist, ALfloat maxdist,
ALfloat pitch, bool loop, bool useenv); ALfloat gain, ALfloat pitch, bool loop, bool useenv);
void updateCommon( void updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist, ALfloat gain,
ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv); ALfloat pitch, bool useenv);
float getTimeScaledPitch(SoundBase* sound); float getTimeScaledPitch(SoundBase* sound);
@ -108,8 +109,8 @@ namespace MWSound
void startUpdate() override; void startUpdate() override;
void finishUpdate() override; void finishUpdate() override;
void updateListener( void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) override; const osg::Vec3f& vel, Environment env) override;
void pauseSounds(int types) override; void pauseSounds(int types) override;
void resumeSounds(int types) override; void resumeSounds(int types) override;

View file

@ -31,6 +31,8 @@ namespace MWSound
struct SoundParams struct SoundParams
{ {
osg::Vec3f mPos; osg::Vec3f mPos;
osg::Vec3f mLastPos;
osg::Vec3f mVel;
float mVolume = 1.0f; float mVolume = 1.0f;
float mBaseVolume = 1.0f; float mBaseVolume = 1.0f;
float mPitch = 1.0f; float mPitch = 1.0f;
@ -57,6 +59,8 @@ namespace MWSound
public: public:
void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; } void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; }
void setLastPosition(const osg::Vec3f& lastpos) { mParams.mLastPos = lastpos; }
void setVelocity(const osg::Vec3f& vel) { mParams.mVel = vel; }
void setVolume(float volume) { mParams.mVolume = volume; } void setVolume(float volume) { mParams.mVolume = volume; }
void setBaseVolume(float volume) { mParams.mBaseVolume = volume; } void setBaseVolume(float volume) { mParams.mBaseVolume = volume; }
void setFadeout(float duration) { setFade(duration, 0.0, Play_StopAtFadeEnd); } void setFadeout(float duration) { setFade(duration, 0.0, Play_StopAtFadeEnd); }
@ -150,6 +154,8 @@ namespace MWSound
} }
const osg::Vec3f& getPosition() const { return mParams.mPos; } const osg::Vec3f& getPosition() const { return mParams.mPos; }
const osg::Vec3f& getLastPosition() const { return mParams.mLastPos; }
const osg::Vec3f& getVelocity() const { return mParams.mVel; }
float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume * mParams.mFadeVolume; } float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume * mParams.mFadeVolume; }
float getPitch() const { return mParams.mPitch; } float getPitch() const { return mParams.mPitch; }
float getMinDistance() const { return mParams.mMinDistance; } float getMinDistance() const { return mParams.mMinDistance; }

View file

@ -119,6 +119,7 @@ namespace MWSound
, mListenerPos(0, 0, 0) , mListenerPos(0, 0, 0)
, mListenerDir(1, 0, 0) , mListenerDir(1, 0, 0)
, mListenerUp(0, 0, 1) , mListenerUp(0, 0, 1)
, mListenerVel(0, 0, 0)
, mUnderwaterSound(nullptr) , mUnderwaterSound(nullptr)
, mNearWaterSound(nullptr) , mNearWaterSound(nullptr)
, mPlaybackPaused(false) , mPlaybackPaused(false)
@ -960,7 +961,7 @@ namespace MWSound
} }
mOutput->startUpdate(); mOutput->startUpdate();
mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, env); mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, mListenerVel, env);
updateMusic(duration); updateMusic(duration);
@ -977,7 +978,13 @@ namespace MWSound
if (sound->getIs3D()) if (sound->getIs3D())
{ {
if (!ptr.isEmpty()) if (!ptr.isEmpty())
{
sound->setLastPosition(sound->getPosition());
sound->setPosition(ptr.getRefData().getPosition().asVec3()); sound->setPosition(ptr.getRefData().getPosition().asVec3());
MWBase::World* world = MWBase::Environment::get().getWorld();
sound->setVelocity(
(sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
}
cull3DSound(sound); cull3DSound(sound);
} }
@ -1013,8 +1020,11 @@ namespace MWSound
{ {
if (!ptr.isEmpty()) if (!ptr.isEmpty())
{ {
sound->setLastPosition(sound->getPosition());
MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::World* world = MWBase::Environment::get().getWorld();
sound->setPosition(world->getActorHeadTransform(ptr).getTrans()); sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
sound->setVelocity(
(sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
} }
cull3DSound(sound); cull3DSound(sound);
@ -1153,6 +1163,11 @@ namespace MWSound
mWaterSoundUpdater.setUnderwater(underwater); mWaterSoundUpdater.setUnderwater(underwater);
} }
void SoundManager::setListenerVel(const osg::Vec3f& vel)
{
mListenerVel = vel;
}
void SoundManager::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) void SoundManager::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated)
{ {
SoundMap::iterator snditer = mActiveSounds.find(old.mRef); SoundMap::iterator snditer = mActiveSounds.find(old.mRef);

View file

@ -92,6 +92,7 @@ namespace MWSound
osg::Vec3f mListenerPos; osg::Vec3f mListenerPos;
osg::Vec3f mListenerDir; osg::Vec3f mListenerDir;
osg::Vec3f mListenerUp; osg::Vec3f mListenerUp;
osg::Vec3f mListenerVel;
int mPausedSoundTypes[BlockerType::MaxCount] = {}; int mPausedSoundTypes[BlockerType::MaxCount] = {};
@ -283,6 +284,8 @@ namespace MWSound
void setListenerPosDir( void setListenerPosDir(
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater) override; const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater) override;
void setListenerVel(const osg::Vec3f& vel) override;
void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) override; void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) override;
void clear() override; void clear() override;

View file

@ -61,8 +61,8 @@ namespace MWSound
virtual void startUpdate() = 0; virtual void startUpdate() = 0;
virtual void finishUpdate() = 0; virtual void finishUpdate() = 0;
virtual void updateListener( virtual void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) const osg::Vec3f& vel, Environment env)
= 0; = 0;
virtual void pauseSounds(int types) = 0; virtual void pauseSounds(int types) = 0;

View file

@ -461,6 +461,11 @@ namespace MWWorld
update(magicBoltState, duration); update(magicBoltState, duration);
for (const auto& sound : magicBoltState.mSounds)
{
sound->setVelocity(direction * speed);
}
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit // For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit
// result. // result.
std::vector<MWWorld::Ptr> targetActors; std::vector<MWWorld::Ptr> targetActors;

View file

@ -1460,6 +1460,8 @@ namespace MWWorld
void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity) void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity)
{ {
mPhysics->queueObjectMovement(ptr, velocity); mPhysics->queueObjectMovement(ptr, velocity);
if (ptr == MWMechanics::getPlayer())
MWBase::Environment::get().getSoundManager()->setListenerVel(velocity);
} }
void World::updateAnimatedCollisionShape(const Ptr& ptr) void World::updateAnimatedCollisionShape(const Ptr& ptr)
@ -3182,6 +3184,11 @@ namespace MWWorld
return mWeatherManager->getSunPercentage(getTimeStamp().getHour()); return mWeatherManager->getSunPercentage(getTimeStamp().getHour());
} }
float World::getPhysicsFrameRateDt() const
{
return mPhysics->mPhysicsDt;
}
bool World::findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) bool World::findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result)
{ {
if (cell->isExterior()) if (cell->isExterior())

View file

@ -584,6 +584,8 @@ namespace MWWorld
float getSunVisibility() const override; float getSunVisibility() const override;
float getSunPercentage() const override; float getSunPercentage() const override;
float getPhysicsFrameRateDt() const override;
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override; bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker) /// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)

View file

@ -24,6 +24,7 @@ namespace Settings
SettingValue<HrtfMode> mHrtfEnable{ mIndex, "Sound", "hrtf enable" }; SettingValue<HrtfMode> mHrtfEnable{ mIndex, "Sound", "hrtf enable" };
SettingValue<std::string> mHrtf{ mIndex, "Sound", "hrtf" }; SettingValue<std::string> mHrtf{ mIndex, "Sound", "hrtf" };
SettingValue<bool> mCameraListener{ mIndex, "Sound", "camera listener" }; SettingValue<bool> mCameraListener{ mIndex, "Sound", "camera listener" };
SettingValue<float> mDopplerFactor{ mIndex, "Sound", "doppler factor", makeClampSanitizerFloat(0, 1) };
}; };
} }

View file

@ -121,3 +121,13 @@ Sound Settings
When true, uses the camera position and direction for audio instead of the player position. 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. This makes audio in third person sound relative to camera instead of the player.
False is vanilla Morrowind behaviour. False is vanilla Morrowind behaviour.
.. omw-setting::
:title: doppler factor
:type: float32
:range: 0.0 (disabled), 1.0 (maximum strength)
:default: 0.25
:location: :bdg-success:`Launcher > Settings > Audio`
This setting controls the strength of the Doppler effect. The Doppler effect increases or decreases the pitch of sounds
relative to the velocity of the sound source and the listener.

View file

@ -1451,5 +1451,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
<source>Run Script After Startup:</source> <source>Run Script After Startup:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Doppler Factor</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -1451,5 +1451,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Doppler Factor</source>
<translation></translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -1454,5 +1454,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
<source>Run Script After Startup:</source> <source>Run Script After Startup:</source>
<translation>Script à lancer après démarrage :</translation> <translation>Script à lancer après démarrage :</translation>
</message> </message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Doppler Factor</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -1466,5 +1466,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
<source>Use the Camera as the Sound Listener</source> <source>Use the Camera as the Sound Listener</source>
<translation>Использовать камеру как слушателя</translation> <translation>Использовать камеру как слушателя</translation>
</message> </message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Определяет силу эффекта Доплера. Нулевое значение означает, что эффект отключен полностью.&lt;/p&gt;&lt;p&gt;Эффект Доплера увеличивает или уменьшает высоту звуков в зависимости от скорости источника звука и слушателя.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>Doppler Factor</source>
<translation>Множитель эффекта Доплера</translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -1470,5 +1470,13 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source> <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Vid aktivering gör denna funktion att övergångarna mellan olika animationer och poser blir mycket mjukare. Funktionen gör det också möjligt att konfigurera animationsövergångarna i YAML-filer. Dessa filer kan buntas ihop tillsammans med nya animationsfiler.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation> <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Vid aktivering gör denna funktion att övergångarna mellan olika animationer och poser blir mycket mjukare. Funktionen gör det också möjligt att konfigurera animationsövergångarna i YAML-filer. Dessa filer kan buntas ihop tillsammans med nya animationsfiler.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message> </message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls the strength of the Doppler effect. Zero means it is completely disabled.&lt;/p&gt;&lt;p&gt;The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Kontrollerar styrkan dopplereffekten. Noll innebär helt inaktiverat.&lt;/p&gt;&lt;p&gt;Dopplereffekten höjer eller sänker tonhöjden på ljud i förhållande till ljudkällans hastighet och lyssnaren.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>Doppler Factor</source>
<translation>Dopplerfaktor</translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -624,6 +624,9 @@ hrtf =
# Specifies whether to use camera as audio listener # Specifies whether to use camera as audio listener
camera listener = false camera listener = false
# Specifies strength of doppler effect
doppler factor = 0.25
[Video] [Video]
# Resolution of the OpenMW window or screen. # Resolution of the OpenMW window or screen.