Skip to content

Commit

Permalink
🎮 no longer apply the obstruction filter if the listener is inside an…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
Hiradur committed Nov 24, 2024
1 parent 2dbc482 commit 135303f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 84 deletions.
128 changes: 60 additions & 68 deletions source/main/audio/SoundManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool, Ogre::Real> 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<bool, Ogre::Real> 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;
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions source/main/audio/SoundScriptManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
6 changes: 0 additions & 6 deletions source/main/audio/SoundScriptManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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;
Expand Down

0 comments on commit 135303f

Please sign in to comment.