/******************************************************************************* 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. *******************************************************************************/ #pragma once #include "Math/GenericOctree.h" #include "WwiseUnrealDefines.h" #include "Components/SceneComponent.h" #include "EngineDefines.h" class UAkEnvironmentOctree; #if UE_4_26_OR_LATER #define AK_OCTREE_TYPE TOctree2 #define AK_OCTREE_ELEMENT_ID FOctreeElementId2 #else #define AK_OCTREE_TYPE TOctree #define AK_OCTREE_ELEMENT_ID FOctreeElementId #endif struct FAkEnvironmentOctreeElement { USceneComponent* Component; FBoxCenterAndExtent BoundingBox; FAkEnvironmentOctreeElement(USceneComponent* in_Component) { Component = in_Component; BoundingBox = FBoxCenterAndExtent(Component->Bounds.GetBox().GetCenter(), Component->Bounds.GetBox().GetExtent()); } }; struct FAkEnvironmentOctreeSemantics { typedef AK_OCTREE_TYPE FOctree; enum { MaxElementsPerLeaf = 16 }; enum { MinInclusiveElementsPerNode = 7 }; enum { MaxNodeDepth = 12 }; typedef TInlineAllocator ElementAllocator; FORCEINLINE static FBoxCenterAndExtent GetBoundingBox(const FAkEnvironmentOctreeElement& Element) { return Element.BoundingBox; } FORCEINLINE static bool AreElementsEqual(const FAkEnvironmentOctreeElement& A, const FAkEnvironmentOctreeElement& B) { return (A.Component == B.Component); } static void SetElementId(FOctree& OctreeOwner, const FAkEnvironmentOctreeElement& Element, AK_OCTREE_ELEMENT_ID Id); }; class UAkEnvironmentOctree : public AK_OCTREE_TYPE { public: UAkEnvironmentOctree() : AK_OCTREE_TYPE(FVector::ZeroVector, HALF_WORLD_MAX) {} TMap ObjectToOctreeId; }; /** A spatial indexing data structure used to accelerate geometric queries. Used for fast look up of UAkRoomComponents for Spatial Audio Rooms, and for UAkLateReverbComponents for auxiliary sends in Wwise. */ class FAkEnvironmentIndex { public: /** Query a world and location for an environmental rooms or late reverb components. Returns an array of components that overlap Location, sorted by decreasing priority. */ template TArray Query(const FVector& Location, const UWorld* World) { TArray Result; TUniquePtr* Octree = Map.Find(World); if (Octree != nullptr) { #if UE_4_26_OR_LATER FBoxCenterAndExtent BoxBounds(Location, FVector::ZeroVector); (*Octree)->FindElementsWithBoundsTest(BoxBounds, [&Result, Location](const FAkEnvironmentOctreeElement& Element) { EnvironmentType* Env = Cast(Element.Component); if (Env && Env->bEnable && Env->HasEffectOnLocation(Location)) { Result.Add(Env); } }); #else for (UAkEnvironmentOctree::TConstElementBoxIterator<> It(**Octree, FBoxCenterAndExtent(Location, FVector(ForceInitToZero))); It.HasPendingElements(); It.Advance()) { const FAkEnvironmentOctreeElement& Element = It.GetCurrentElement(); EnvironmentType* Env = Cast(Element.Component); if (Env && Env->bEnable && Env->HasEffectOnLocation(Location)) { Result.Add(Env); } } #endif } // Sort the found Volumes if (Result.Num() > 1) { Result.Sort([](const EnvironmentType& A, const EnvironmentType& B) { return A.Priority > B.Priority; }); } return Result; } /** Add a Component to the spatial index. */ void Add(USceneComponent* EnvironmentToAdd); /** * Remove a Component from the spatial index. */ bool Remove(USceneComponent* EnvironmentToRemove); /** * Update the bounds of a component that is already indexed. Must be called if the transform of the component changes. */ void Update(USceneComponent* EnvironmentToUpdate); /** * Clear all components in the given World. */ void Clear(const UWorld* WorldToClear); /** * Is the index empty for the given World. */ bool IsEmpty(const UWorld* World); private: TMap > Map; };