Merge remote-tracking branch 'scrawl/master'

This commit is contained in:
Marc Zinnschlag 2014-12-09 11:07:26 +01:00
commit 0522da257c
9 changed files with 74 additions and 36 deletions

View File

@ -42,15 +42,21 @@ namespace MWBase
Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position Play_NoTrack = 1<<2, /* (3D only) Play the sound at the given object's position
* but do not keep it updated (the sound will not move with * but do not keep it updated (the sound will not move with
* the object and will not stop when the object is deleted. */ * the object and will not stop when the object is deleted. */
Play_RemoveAtDistance = 1<<3, /* (3D only) If the listener gets further than 2000 units away
Play_LoopNoEnv = Play_Loop | Play_NoEnv from the sound source, the sound is removed.
This is weird stuff but apparently how vanilla works for sounds
played by the PlayLoopSound family of script functions. Perhaps we
can make this cut off a more subtle fade later, but have to
be careful to not change the overall volume of areas by too much. */
Play_LoopNoEnv = Play_Loop | Play_NoEnv,
Play_LoopRemoveAtDistance = Play_Loop | Play_RemoveAtDistance
}; };
enum PlayType { enum PlayType {
Play_TypeSfx = 1<<3, /* Normal SFX sound */ Play_TypeSfx = 1<<4, /* Normal SFX sound */
Play_TypeVoice = 1<<4, /* Voice sound */ Play_TypeVoice = 1<<5, /* Voice sound */
Play_TypeFoot = 1<<5, /* Footstep sound */ Play_TypeFoot = 1<<6, /* Footstep sound */
Play_TypeMusic = 1<<6, /* Music track */ Play_TypeMusic = 1<<7, /* Music track */
Play_TypeMovie = 1<<7, /* Movie audio track */ Play_TypeMovie = 1<<8, /* Movie audio track */
Play_TypeMask = Play_TypeSfx|Play_TypeVoice|Play_TypeFoot|Play_TypeMusic|Play_TypeMovie Play_TypeMask = Play_TypeSfx|Play_TypeVoice|Play_TypeFoot|Play_TypeMusic|Play_TypeMovie
}; };

View File

@ -7,7 +7,6 @@
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include "../mwworld/refdata.hpp" #include "../mwworld/refdata.hpp"
@ -120,15 +119,6 @@ namespace MWRender
setPosition(Ogre::Vector3(x,y,z)); setPosition(Ogre::Vector3(x,y,z));
} }
void Camera::updateListener()
{
Ogre::Vector3 pos = mCamera->getRealPosition();
Ogre::Vector3 dir = mCamera->getRealDirection();
Ogre::Vector3 up = mCamera->getRealUp();
MWBase::Environment::get().getSoundManager()->setListenerPosDir(pos, dir, up);
}
void Camera::update(float duration, bool paused) void Camera::update(float duration, bool paused)
{ {
if (mAnimation->upperBodyReady()) if (mAnimation->upperBodyReady())
@ -148,7 +138,6 @@ namespace MWRender
} }
} }
updateListener();
if (paused) if (paused)
return; return;

View File

@ -50,9 +50,6 @@ namespace MWRender
bool mVanityToggleQueued; bool mVanityToggleQueued;
bool mViewModeToggleQueued; bool mViewModeToggleQueued;
/// Updates sound manager listener data
void updateListener();
void setPosition(const Ogre::Vector3& position); void setPosition(const Ogre::Vector3& position);
void setPosition(float x, float y, float z); void setPosition(float x, float y, float z);

View File

@ -121,8 +121,8 @@ namespace MWScript
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, sound, 1.0, 1.0, MWBase::Environment::get().getSoundManager()->playSound3D(ptr, sound, 1.0, 1.0,
MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_TypeSfx,
mLoop ? MWBase::SoundManager::Play_Loop : mLoop ? MWBase::SoundManager::Play_LoopRemoveAtDistance
MWBase::SoundManager::Play_Normal); : MWBase::SoundManager::Play_Normal);
} }
}; };
@ -150,8 +150,8 @@ namespace MWScript
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, sound, volume, pitch, MWBase::Environment::get().getSoundManager()->playSound3D(ptr, sound, volume, pitch,
MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_TypeSfx,
mLoop ? MWBase::SoundManager::Play_Loop : mLoop ? MWBase::SoundManager::Play_LoopRemoveAtDistance
MWBase::SoundManager::Play_Normal); : MWBase::SoundManager::Play_Normal);
} }
}; };

View File

@ -696,7 +696,7 @@ void OpenAL_Output::init(const std::string &devname)
fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice))); fail(std::string("Failed to setup context: ")+alcGetString(mDevice, alcGetError(mDevice)));
} }
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
throwALerror(); throwALerror();
ALCint maxmono=0, maxstereo=0; ALCint maxmono=0, maxstereo=0;

View File

@ -103,24 +103,31 @@ namespace MWSound
std::string SoundManager::lookup(const std::string &soundId, std::string SoundManager::lookup(const std::string &soundId,
float &volume, float &min, float &max) float &volume, float &min, float &max)
{ {
const ESM::Sound *snd = MWBase::World* world = MWBase::Environment::get().getWorld();
MWBase::Environment::get().getWorld()->getStore().get<ESM::Sound>().find(soundId); const ESM::Sound *snd = world->getStore().get<ESM::Sound>().find(soundId);
volume *= pow(10.0, (snd->mData.mVolume/255.0*3348.0 - 3348.0) / 2000.0); volume *= pow(10.0, (snd->mData.mVolume/255.0*3348.0 - 3348.0) / 2000.0);
if(snd->mData.mMinRange == 0 && snd->mData.mMaxRange == 0) if(snd->mData.mMinRange == 0 && snd->mData.mMaxRange == 0)
{ {
min = 100.0f; static const float fAudioDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMinDistance")->getFloat();
max = 2000.0f; static const float fAudioDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMaxDistance")->getFloat();
min = fAudioDefaultMinDistance;
max = fAudioDefaultMaxDistance;
} }
else else
{ {
min = snd->mData.mMinRange * 20.0f; min = snd->mData.mMinRange;
max = snd->mData.mMaxRange * 50.0f; max = snd->mData.mMaxRange;
min = std::max(min, 1.0f);
max = std::max(min, max);
} }
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->getFloat();
min *= fAudioMinDistanceMult;
max *= fAudioMaxDistanceMult;
min = std::max(min, 1.0f);
max = std::max(min, max);
return "Sound/"+snd->mSound; return "Sound/"+snd->mSound;
} }
@ -250,8 +257,19 @@ namespace MWSound
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
const Ogre::Vector3 objpos(pos.pos); const Ogre::Vector3 objpos(pos.pos);
MWBase::World* world = MWBase::Environment::get().getWorld();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->getFloat();
static const float fAudioVoiceDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMinDistance")->getFloat();
static const float fAudioVoiceDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMaxDistance")->getFloat();
float minDistance = fAudioVoiceDefaultMinDistance * fAudioMinDistanceMult;
float maxDistance = fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult;
minDistance = std::max(minDistance, 1.f);
maxDistance = std::max(minDistance, maxDistance);
MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f, MWBase::SoundPtr sound = mOutput->playSound3D(filePath, objpos, 1.0f, basevol, 1.0f,
20.0f, 1500.0f, Play_Normal|Play_TypeVoice, 0, true); minDistance, maxDistance, Play_Normal|Play_TypeVoice, 0, true);
mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound")); mActiveSounds[sound] = std::make_pair(ptr, std::string("_say_sound"));
} }
catch(std::exception &e) catch(std::exception &e)
@ -367,6 +385,11 @@ namespace MWSound
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
const Ogre::Vector3 objpos(pos.pos); const Ogre::Vector3 objpos(pos.pos);
if ((mode & Play_RemoveAtDistance) && mListenerPos.squaredDistance(objpos) > 2000*2000)
{
return MWBase::SoundPtr();
}
sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset); sound = mOutput->playSound3D(file, objpos, volume, basevol, pitch, min, max, mode|type, offset);
if((mode&Play_NoTrack)) if((mode&Play_NoTrack))
mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId); mActiveSounds[sound] = std::make_pair(MWWorld::Ptr(), soundId);
@ -632,6 +655,13 @@ namespace MWSound
const ESM::Position &pos = ptr.getRefData().getPosition(); const ESM::Position &pos = ptr.getRefData().getPosition();
const Ogre::Vector3 objpos(pos.pos); const Ogre::Vector3 objpos(pos.pos);
snditer->first->setPosition(objpos); snditer->first->setPosition(objpos);
if ((snditer->first->mFlags & Play_RemoveAtDistance)
&& mListenerPos.squaredDistance(Ogre::Vector3(ptr.getRefData().getPosition().pos)) > 2000*2000)
{
mActiveSounds.erase(snditer++);
continue;
}
} }
//update fade out //update fade out
if(snditer->first->mFadeOutTime>0) if(snditer->first->mFadeOutTime>0)

View File

@ -27,7 +27,9 @@ namespace MWWorld
LiveRef *find (const std::string& name) LiveRef *find (const std::string& name)
{ {
for (typename List::iterator iter (mList.begin()); iter!=mList.end(); ++iter) for (typename List::iterator iter (mList.begin()); iter!=mList.end(); ++iter)
if (iter->mRef.getRefId() == name) if (!iter->mData.isDeletedByContentFile()
&& (iter->mRef.getRefNum().mContentFile != -1 || iter->mData.getCount() > 0)
&& iter->mRef.getRefId() == name)
return &*iter; return &*iter;
return 0; return 0;

View File

@ -1560,6 +1560,8 @@ namespace MWWorld
updateWindowManager (); updateWindowManager ();
updateSoundListener();
if (!paused && mPlayer->getPlayer().getCell()->isExterior()) if (!paused && mPlayer->getPlayer().getCell()->isExterior())
{ {
ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition(); ESM::Position pos = mPlayer->getPlayer().getRefData().getPosition();
@ -1567,6 +1569,17 @@ namespace MWWorld
} }
} }
void World::updateSoundListener()
{
Ogre::Vector3 playerPos = mPlayer->getPlayer().getRefData().getBaseNode()->getPosition();
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(getPlayerPtr().getRefData().getHandle());
if(actor) playerPos.z += 1.85*actor->getHalfExtents().z;
Ogre::Quaternion playerOrient = Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z) *
Ogre::Quaternion(Ogre::Radian(getPlayerPtr().getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X);
MWBase::Environment::get().getSoundManager()->setListenerPosDir(playerPos, playerOrient.yAxis(),
playerOrient.zAxis());
}
void World::updateWindowManager () void World::updateWindowManager ()
{ {
// inform the GUI about focused object // inform the GUI about focused object

View File

@ -109,6 +109,7 @@ namespace MWWorld
Ptr copyObjectToCell(const Ptr &ptr, CellStore* cell, ESM::Position pos, bool adjustPos=true); Ptr copyObjectToCell(const Ptr &ptr, CellStore* cell, ESM::Position pos, bool adjustPos=true);
void updateSoundListener();
void updateWindowManager (); void updateWindowManager ();
void performUpdateSceneQueries (); void performUpdateSceneQueries ();
void getFacedHandle(std::string& facedHandle, float maxDistance, bool ignorePlayer=true); void getFacedHandle(std::string& facedHandle, float maxDistance, bool ignorePlayer=true);