/******************************************************************************* The content of this file includes portions of the proprietary AUDIOKINETIC Wwise Technology released in source code form as part of the game integration package. The content of this file may not be used without valid licenses to the AUDIOKINETIC Wwise Technology. Note that the use of the game engine is subject to the Unreal(R) Engine End User License Agreement at https://www.unrealengine.com/en-US/eula/unreal License Usage Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use this file in accordance with the end user license agreement provided with the software or, alternatively, in accordance with the terms contained in a written agreement between you and Audiokinetic Inc. Copyright (c) 2023 Audiokinetic Inc. *******************************************************************************/ /*============================================================================= AkObstructionAndOcclusionService.h: =============================================================================*/ #pragma once #include "AkInclude.h" #include "AkAudioDevice.h" #include "WorldCollision.h" #include "HAL/ThreadSafeBool.h" #define NUM_BOUNDING_BOX_TRACE_POINTS 12 class UAkComponent; class AActor; class AAkAcousticPortal; struct FAkListenerObstructionAndOcclusion { float CurrentValue; float TargetValue; float Rate; FAkListenerObstructionAndOcclusion(float in_TargetValue = 0.0f, float in_CurrentValue = 0.0f); void SetTarget(float in_TargetValue); bool ReachedTarget(); bool Update(float DeltaTime); }; struct FAkListenerObstructionAndOcclusionPair { FAkListenerObstructionAndOcclusionPair(); FAkListenerObstructionAndOcclusion Occ; FAkListenerObstructionAndOcclusion Obs; FVector Position; bool Update(float DeltaTime); bool ReachedTarget(); /** Trace a ray from a source position to a bounding box point asynchronously */ void AsyncTraceFromSource(const FVector& SourcePosition, const FVector& EndPosition, int BoundingBoxPointIndex, ECollisionChannel CollisionChannel, UWorld* World, const FCollisionQueryParams& CollisionParams); /** Trace a ray from a listener position to a bounding box point asynchronously */ void AsyncTraceFromListener(const FVector& ListenerPosition, const FVector& EndPosition, int BoundingBoxPointIndex, ECollisionChannel CollisionChannel, UWorld* World, const FCollisionQueryParams& CollisionParams); /** Get the total number of listener OR source collisions. */ int GetCollisionCount(); void Reset(); /** Iterate through all trace handles and handle the results if ready */ void CheckTraceResults(UWorld* World); private: /** Used to check when obstruction and occlusion targets need to be updated (when GetCollisionCount() != CurrentCollisionCount) */ int CurrentCollisionCount = 0; TArray SourceTraceHandles; TArray ListenerTraceHandles; /** Iterate through all listener trace handles and handle the trace results if ready */ void CheckListenerTraceHandles(UWorld* World); /** Iterate through all source trace handles and handle the trace results if ready */ void CheckSourceTraceHandles(UWorld* World); TArray SourceRayCollisions; TArray ListenerRayCollisions; }; class AKAUDIO_API AkObstructionAndOcclusionService { public: void Tick(const UAkComponentSet& in_Listeners, const FVector& SourcePosition, const AActor* Actor, AkRoomID RoomID, ECollisionChannel in_collisionChannel, float DeltaTime, float OcclusionRefreshInterval); /** * Calculates updated occlusion and obstruction values synchronously and then sends them to the Wwise engine. */ void UpdateObstructionAndOcclusion(const UAkComponentSet& in_Listeners, const FVector& SourcePosition, const AActor* Actor, AkRoomID RoomID, ECollisionChannel in_collisionChannel, float OcclusionRefreshInterval); void ClearOcclusionValues(); virtual void SetObstructionAndOcclusion(AkGameObjectID ListenerID, float Value) = 0; virtual ~AkObstructionAndOcclusionService() {} protected: void _Init(UWorld* in_world, float in_refreshInterval); private: /** * Fades active occlusions towards targets, sends updated values to the Wwise engine, then calculates refreshed occlusion and obstruction values asynchronously. */ void RefreshObstructionAndOcclusion(const UAkComponentSet& in_Listeners, const FVector& SourcePosition, const AActor* Actor, AkRoomID RoomID, ECollisionChannel in_collisionChannel, const float DeltaTime, float OcclusionRefreshInterval); /** * Loops through in_Listeners and sends the obstruction occlusion values on each to the Wwise engine. */ void SetObstructionAndOcclusion(const UAkComponentSet& in_Listeners, AkRoomID RoomID); /** * Calculates updated occlusion and obstruction values. */ void CalculateObstructionAndOcclusionValues(const UAkComponentSet& in_Listeners, const FVector& SourcePosition, const AActor* Actor, AkRoomID RoomID, ECollisionChannel in_collisionChannel, bool bAsync = true); /** Last time occlusion was refreshed */ float LastObstructionAndOcclusionRefresh = -1; float PreviousRefreshInterval = -1.0f; bool ClearingObstructionAndOcclusion = false; typedef AkGameObjectIdKeyFuncs ListenerOccObsPairGameObjectIDKeyFuncs; TMap ListenerInfoMap; };