From 135303f9bcb92437e187541b266dcd11a309cbd6 Mon Sep 17 00:00:00 2001 From: Niklas Kersten Date: Sun, 24 Nov 2024 08:57:29 +0100 Subject: [PATCH] :video_game: no longer apply the obstruction filter if the listener is inside an actor The implementation did not differentiate whether the actor had an open or closed cabin. For instace, it incorrectly applied the obstruction effect when the listener was in actors with open cabins, e.g. buggies. There does not seem to be an easy way to determine whether an actor has an open or closed cabin. An expensive(?) alternative might be to check against collisions with the mesh of an actor. --- source/main/audio/SoundManager.cpp | 128 +++++++++++------------ source/main/audio/SoundScriptManager.cpp | 10 -- source/main/audio/SoundScriptManager.h | 6 -- 3 files changed, 60 insertions(+), 84 deletions(-) diff --git a/source/main/audio/SoundManager.cpp b/source/main/audio/SoundManager.cpp index 1c0c9a55c3..780e71943d 100644 --- a/source/main/audio/SoundManager.cpp +++ b/source/main/audio/SoundManager.cpp @@ -834,91 +834,83 @@ void SoundManager::UpdateObstructionFilter(const int hardware_index) const // TODO: Simulate diffraction path. - // always obstruct sounds if the player is in a vehicle - if(App::GetSoundScriptManager()->ListenerIsInsideThePlayerCoupledActor()) - { - obstruction_detected = true; + /* + * Perform various line of sight checks until either a collision was detected + * and the filter has to be applied or no obstruction was detected. + */ + + std::pair intersection; + // no normalisation due to how the intersectsTris function determines its number of steps + Ogre::Vector3 direction_to_sound = corresponding_sound->getPosition() - m_listener_position; + Ogre::Real distance_to_sound = direction_to_sound.length(); + Ray direct_path_to_sound = Ray(m_listener_position, direction_to_sound); + + // perform line of sight check against terrain + intersection = App::GetGameContext()->GetTerrain()->GetCollisions()->intersectsTerrain(direct_path_to_sound, distance_to_sound); + obstruction_detected = intersection.first; + + if(!obstruction_detected) + { + // perform line of sight check against collision meshes + // for this to work correctly, the direction vector of the ray must have + // the length of the distance from the listener to the sound + intersection = App::GetGameContext()->GetTerrain()->GetCollisions()->intersectsTris(direct_path_to_sound); + obstruction_detected = intersection.first; } - else - { - /* - * Perform various line of sight checks until either a collision was detected - * and the filter has to be applied or no obstruction was detected. - */ - - std::pair intersection; - // no normalisation due to how the intersectsTris function determines its number of steps - Ogre::Vector3 direction_to_sound = corresponding_sound->getPosition() - m_listener_position; - Ogre::Real distance_to_sound = direction_to_sound.length(); - Ray direct_path_to_sound = Ray(m_listener_position, direction_to_sound); - // perform line of sight check against terrain - intersection = App::GetGameContext()->GetTerrain()->GetCollisions()->intersectsTerrain(direct_path_to_sound, distance_to_sound); - obstruction_detected = intersection.first; + // do not normalise before intersectsTris() due to how that function works + direction_to_sound.normalise(); + direct_path_to_sound.setDirection(direction_to_sound); - if(!obstruction_detected) + if(!obstruction_detected) + { + // perform line of sight check agains collision boxes + for (const collision_box_t& collision_box : App::GetGameContext()->GetTerrain()->GetCollisions()->getCollisionBoxes()) { - // perform line of sight check against collision meshes - // for this to work correctly, the direction vector of the ray must have - // the length of the distance from the listener to the sound - intersection = App::GetGameContext()->GetTerrain()->GetCollisions()->intersectsTris(direct_path_to_sound); - obstruction_detected = intersection.first; - } - - // do not normalise before intersectsTris() due to how that function works - direction_to_sound.normalise(); - direct_path_to_sound.setDirection(direction_to_sound); + if (!collision_box.enabled || collision_box.virt) { continue; } - if(!obstruction_detected) - { - // perform line of sight check agains collision boxes - for (const collision_box_t& collision_box : App::GetGameContext()->GetTerrain()->GetCollisions()->getCollisionBoxes()) + intersection = direct_path_to_sound.intersects(Ogre::AxisAlignedBox(collision_box.lo, collision_box.hi)); + if (intersection.first && intersection.second <= distance_to_sound) { - if (!collision_box.enabled || collision_box.virt) { continue; } - - intersection = direct_path_to_sound.intersects(Ogre::AxisAlignedBox(collision_box.lo, collision_box.hi)); - if (intersection.first && intersection.second <= distance_to_sound) - { - obstruction_detected = true; - break; - } + obstruction_detected = true; + break; } } + } - if(!obstruction_detected) + if(!obstruction_detected) + { + // perform line of sight check against actors + const ActorPtrVec& actors = App::GetGameContext()->GetActorManager()->GetActors(); + bool soundsource_belongs_to_current_actor = false; + for(const ActorPtr actor : actors) { - // perform line of sight check against actors - const ActorPtrVec& actors = App::GetGameContext()->GetActorManager()->GetActors(); - bool soundsource_belongs_to_current_actor = false; - for(const ActorPtr actor : actors) + // Trucks shouldn't obstruct their own sound sources since the + // obstruction is most likely already contained in the recording. + for (int soundsource_index = 0; soundsource_index < actor->ar_num_soundsources; ++soundsource_index) { - // Trucks shouldn't obstruct their own sound sources since the - // obstruction is most likely already contained in the recording. - for (int soundsource_index = 0; soundsource_index < actor->ar_num_soundsources; ++soundsource_index) + const soundsource_t& soundsource = actor->ar_soundsources[soundsource_index]; + const int num_sounds = soundsource.ssi->getTemplate()->getNumSounds(); + for (int num_sound = 0; num_sound < num_sounds; ++num_sound) { - const soundsource_t& soundsource = actor->ar_soundsources[soundsource_index]; - const int num_sounds = soundsource.ssi->getTemplate()->getNumSounds(); - for (int num_sound = 0; num_sound < num_sounds; ++num_sound) + if (soundsource.ssi->getSound(num_sound) == corresponding_sound) { - if (soundsource.ssi->getSound(num_sound) == corresponding_sound) - { - soundsource_belongs_to_current_actor = true; - } + soundsource_belongs_to_current_actor = true; } - if (soundsource_belongs_to_current_actor) { break; } } + if (soundsource_belongs_to_current_actor) { break; } + } - if (soundsource_belongs_to_current_actor) - { - continue; - } + if (soundsource_belongs_to_current_actor) + { + continue; + } - intersection = direct_path_to_sound.intersects(actor->ar_bounding_box); - obstruction_detected = intersection.first; - if (obstruction_detected) - { - break; - } + intersection = direct_path_to_sound.intersects(actor->ar_bounding_box); + obstruction_detected = intersection.first; + if (obstruction_detected) + { + break; } } } diff --git a/source/main/audio/SoundScriptManager.cpp b/source/main/audio/SoundScriptManager.cpp index e85d244d32..57075117e1 100644 --- a/source/main/audio/SoundScriptManager.cpp +++ b/source/main/audio/SoundScriptManager.cpp @@ -326,16 +326,6 @@ void SoundScriptManager::update(float dt_sec) const auto water = App::GetGameContext()->GetTerrain()->getWater(); m_listener_is_underwater = (water != nullptr ? water->IsUnderWater(listener_position) : false); - ActorPtr actor_of_player = App::GetGameContext()->GetPlayerCharacter()->GetActorCoupling(); - if (actor_of_player != nullptr) - { - m_listener_is_inside_the_player_coupled_actor = actor_of_player->ar_bounding_box.contains(listener_position); - } - else - { - m_listener_is_inside_the_player_coupled_actor = false; - } - SetListenerEnvironment(camera_position); sound_manager->Update(dt_sec); } diff --git a/source/main/audio/SoundScriptManager.h b/source/main/audio/SoundScriptManager.h index c8065433e6..583c223898 100644 --- a/source/main/audio/SoundScriptManager.h +++ b/source/main/audio/SoundScriptManager.h @@ -345,11 +345,6 @@ class SoundScriptManager : public Ogre::ScriptLoader */ bool ListenerIsUnderwater() const { return m_listener_is_underwater; } - /** - * @return True if the listener position is inside the AABB of the actor the player character is coupled to. False otherwise. - */ - bool ListenerIsInsideThePlayerCoupledActor() const { return m_listener_is_inside_the_player_coupled_actor; } - SoundManager* getSoundManager() { return sound_manager; } private: @@ -361,7 +356,6 @@ class SoundScriptManager : public Ogre::ScriptLoader bool disabled; bool loading_base; bool m_listener_is_underwater = false; - bool m_listener_is_inside_the_player_coupled_actor = false; float max_distance; float reference_distance; float rolloff_factor;