12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229 |
- /*******************************************************************************
- 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.
- *******************************************************************************/
- #include "AkGeometryComponent.h"
- #include "AkAcousticTexture.h"
- #include "AkAudioDevice.h"
- #include "AkComponentHelpers.h"
- #include "AkReverbDescriptor.h"
- #include "AkRoomComponent.h"
- #include "AkSettings.h"
- #include "WwiseUEFeatures.h"
- #if AK_USE_PHYSX
- #include "PhysXPublic.h"
- #endif
- #if AK_USE_CHAOS
- #include "ChaosLog.h"
- #include "Chaos/CollisionConvexMesh.h"
- #include "Chaos/Convex.h"
- #endif
- #if WITH_EDITOR
- #include "Editor.h"
- #endif
- #include "RawIndexBuffer.h"
- #include "StaticMeshResources.h"
- #include "Components/StaticMeshComponent.h"
- #include "Engine/GameEngine.h"
- #include "Engine/Polys.h"
- #include "Engine/StaticMesh.h"
- #include "PhysicsEngine/BodySetup.h"
- #include "UObject/Object.h"
- static const float kVertexNear = 0.0001;
- UAkGeometryComponent::UAkGeometryComponent(const class FObjectInitializer& ObjectInitializer) :
- Super(ObjectInitializer)
- {
- // Property initialization
- bWantsOnUpdateTransform = true;
- MeshType = AkMeshType::CollisionMesh;
- LOD = 0;
- CollisionMeshSurfaceOverride.AcousticTexture = nullptr;
- CollisionMeshSurfaceOverride.bEnableOcclusionOverride = false;
- CollisionMeshSurfaceOverride.OcclusionValue = 1.f;
- WeldingThreshold = 0.001;
- bWasAddedByRoom = 0;
- bEnableDiffraction = 1;
- bEnableDiffractionOnBoundaryEdges = 0;
- #if WITH_EDITOR
- PrimaryComponentTick.bCanEverTick = true;
- bTickInEditor = true;
- #endif
- }
- void UAkGeometryComponent::OnComponentDestroyed(bool bDestroyingHierarchy)
- {
- Super::OnComponentDestroyed(bDestroyingHierarchy);
- RemoveGeometry();
- StaticMeshSurfaceOverride.Empty();
- #if WITH_EDITOR
- check(!OnMeshMaterialChangedHandle.IsValid());
- #endif
- }
- void UAkGeometryComponent::OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport)
- {
- Super::OnUpdateTransform(UpdateTransformFlags, Teleport);
- UpdateGeometry();
- if (ReverbDescriptor != nullptr)
- {
- DampingEstimationNeedsUpdate = true;
- }
- }
- bool UAkGeometryComponent::MoveComponentImpl(
- const FVector & Delta,
- const FQuat & NewRotation,
- bool bSweep,
- FHitResult * Hit,
- EMoveComponentFlags MoveFlags,
- ETeleportType Teleport)
- {
- if (AkComponentHelpers::DoesMovementRecenterChild(this, Parent, Delta))
- Super::MoveComponentImpl(Delta, NewRotation, bSweep, Hit, MoveFlags, Teleport);
- return false;
- }
- void UAkGeometryComponent::BeginPlay()
- {
- Super::BeginPlay();
- if (!IsBeingDestroyed())
- {
- #if WITH_EDITOR
- if (AkComponentHelpers::ShouldDeferBeginPlay(this))
- bRequiresDeferredBeginPlay = true;
- else
- BeginPlayInternal();
- #else
- BeginPlayInternal();
- #endif
- }
- }
- void UAkGeometryComponent::BeginPlayInternal()
- {
- if (Parent == nullptr)
- InitializeParent();
- if (GeometryData.Vertices.Num() == 0)
- ConvertMesh();
- for (int PosIndex = 0; PosIndex < GeometryData.Surfaces.Num(); ++PosIndex)
- {
- // set geometry surface names and update textures
- FString OwnerName;
- #if WITH_EDITOR
- OwnerName = GetOwner()->GetActorLabel();
- #else
- OwnerName = GetOwner()->GetName();
- #endif
- GeometryData.Surfaces[PosIndex].Name = OwnerName + GetName() + FString::FromInt(PosIndex);
- UPhysicalMaterial* physMat = GeometryData.ToOverrideAcousticTexture[PosIndex];
- if (physMat)
- {
- UAkAcousticTexture* acousticTexture = nullptr;
- if (GetDefault<UAkSettings>()->GetAssociatedAcousticTexture(physMat, acousticTexture))
- {
- if (acousticTexture)
- GeometryData.Surfaces[PosIndex].Texture = acousticTexture->GetShortID();
- }
- }
- physMat = GeometryData.ToOverrideOcclusion[PosIndex];
- if (physMat)
- {
- float occlusionValue = 1.f;
- if (GetDefault<UAkSettings>()->GetAssociatedOcclusionValue(physMat, occlusionValue))
- {
- GeometryData.Surfaces[PosIndex].Occlusion = occlusionValue;
- }
- }
- }
- SendGeometry();
- UpdateGeometry();
- DampingEstimationNeedsUpdate = true;
- }
- void UAkGeometryComponent::OnRegister()
- {
- Super::OnRegister();
- SetRelativeTransform(FTransform::Identity);
- InitializeParent();
- #if WITH_EDITOR
- OnMeshMaterialChangedHandle = FCoreUObjectDelegates::OnObjectPropertyChanged.AddLambda([this](UObject* Object, FPropertyChangedEvent& PropertyChangedEvent)
- {
- if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UMeshComponent, OverrideMaterials) &&
- Parent != nullptr &&
- Parent == Object &&
- MeshType == AkMeshType::StaticMesh
- )
- {
- UpdateStaticMeshOverride();
- }
- });
- if (Parent != nullptr)
- {
- if (MeshType == AkMeshType::StaticMesh)
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent != nullptr)
- CalculateSurfaceArea(MeshParent);
- }
- DampingEstimationNeedsUpdate = true;
- }
- if (AssociatedRoom != nullptr)
- {
- UAkRoomComponent* room = Cast<UAkRoomComponent>(AssociatedRoom->GetComponentByClass(UAkRoomComponent::StaticClass()));
- if (room != nullptr)
- {
- UE_LOG(LogAkAudio, Warning, TEXT("AkGeometryComponent %s is associated to Room %s. The AssociatedRoom property is deprecated, it will be removed in a future version. We recommend not using it and leaving it set to None."), *GetOwner()->GetName(), *room->GetRoomName());
- }
- }
- #endif
- }
- void UAkGeometryComponent::OnUnregister()
- {
- #if WITH_EDITOR
- FCoreUObjectDelegates::OnObjectPropertyChanged.Remove(OnMeshMaterialChangedHandle);
- OnMeshMaterialChangedHandle.Reset();
- #endif
- Parent = nullptr;
- Super::OnUnregister();
- }
- void UAkGeometryComponent::InitializeParent()
- {
- USceneComponent* SceneParent = GetAttachParent();
- if (SceneParent != nullptr)
- {
- Parent = Cast<UPrimitiveComponent>(SceneParent);
- if (!Parent)
- {
- FString actorString = FString("NONE");
- if (GetOwner() != nullptr)
- actorString = GetOwner()->GetName();
- FString parentName = SceneParent->GetName();
- FString parentClass = SceneParent->GetClass()->GetName();
- UE_LOG(LogAkAudio, Error,
- TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
- , *actorString, *GetName(), *parentClass, *parentName);
- if (MeshType == AkMeshType::StaticMesh)
- {
- UE_LOG(LogAkAudio, Error, TEXT("When MeshType is set to Static Mesh, UAkGeometryComponent requires to be nested under a component inheriting from UStaticMeshComponent."));
- }
- else
- {
- UE_LOG(LogAkAudio, Error, TEXT("When MeshType is set to Simple Collision, UAkGeometryComponent requires to be nested under a component inheriting from UPrimitiveComponent."));
- }
- return;
- }
- if (MeshType == AkMeshType::StaticMesh)
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(SceneParent);
- if (MeshParent != nullptr)
- {
- bool fillMaterialKeys = true;
- #if WITH_EDITOR
- // Fill the materials in the StaticMeshSurfaceOverride map only when there is no ongoing transaction (e.g. a user changing a property in the details panel).
- if (GetOwner() != nullptr && GetOwner()->CurrentTransactionAnnotation != nullptr)
- {
- fillMaterialKeys = false;
- }
- #endif
- if (fillMaterialKeys)
- {
- UpdateMeshAndArchetype(MeshParent);
- }
- }
- else
- {
- FString actorString = FString("NONE");
- if (GetOwner() != nullptr)
- actorString = GetOwner()->GetName();
- FString parentName = SceneParent->GetName();
- FString parentClass = SceneParent->GetClass()->GetName();
- UE_LOG(LogAkAudio, Warning,
- TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
- , *actorString, *GetName(), *parentClass, *parentName);
- UE_LOG(LogAkAudio, Warning, TEXT("When MeshType is set to Static Mesh, UAkGeometryComponent requires to be nested under a component inheriting from UStaticMeshComponent. Reverting to Simple Collision."));
- MeshType = AkMeshType::CollisionMesh;
- // If we're in the Blueprint editor, update the Archetype object as well.
- UWorld* World = GetWorld();
- if (World != nullptr && World->WorldType == EWorldType::EditorPreview
- && CreationMethod == EComponentCreationMethod::SimpleConstructionScript)
- {
- UAkGeometryComponent* Archetype = Cast<UAkGeometryComponent>(GetArchetype());
- if (Archetype != nullptr)
- Archetype->MeshType = AkMeshType::CollisionMesh;
- }
- }
- }
- }
- }
- void UAkGeometryComponent::CalculateSurfaceArea(UStaticMeshComponent* StaticMeshComponent)
- {
- SurfaceAreas.Empty();
- UStaticMesh* mesh = StaticMeshComponent->GetStaticMesh();
- #if UE_4_27_OR_LATER
- if (mesh == nullptr || !mesh->GetRenderData())
- return;
- #else
- if (mesh == nullptr || !mesh->RenderData)
- return;
- #endif
- const FStaticMeshLODResources& RenderMesh = mesh->GetLODForExport(LOD);
- FIndexArrayView RawIndices = RenderMesh.IndexBuffer.GetArrayView();
- if (RawIndices.Num() == 0)
- return;
- const int32 PolygonsCount = RenderMesh.Sections.Num();
- double SurfaceArea = 0.0;
- const auto WorldScale = StaticMeshComponent->GetOwner()->ActorToWorld().GetScale3D();
- for (int32 PolygonsIndex = 0; PolygonsIndex < PolygonsCount; ++PolygonsIndex)
- {
- const FStaticMeshSection& Polygons = RenderMesh.Sections[PolygonsIndex];
- const uint32 TriangleCount = Polygons.NumTriangles;
- for (uint32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
- {
- const uint32 RawVertIndex0 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 0)];
- const uint32 RawVertIndex1 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 1)];
- const uint32 RawVertIndex2 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 2)];
- // Scale to world space to ensure proper area
- auto ScaledP0 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex0).GridSnap(WeldingThreshold));
- auto ScaledP1 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex1).GridSnap(WeldingThreshold));
- auto ScaledP2 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex2).GridSnap(WeldingThreshold));
- SurfaceArea += FAkReverbDescriptor::TriangleArea(ScaledP0, ScaledP1, ScaledP2);
- }
- SurfaceAreas.Add(PolygonsIndex, SurfaceArea);
- }
- }
- bool AddVertsForEdge(const FPositionVertexBuffer& Positions, TArray<int32>& UniqueVerts, int32 P0UnrealIdx, int32 P0UniqueIdx, int32 P1UnrealIdx, int32 P1UniqueIdx, TArray< TPair<int32, float> > & VertsOnEdge, float WeldingThreshold)
- {
- auto p0 = Positions.VertexPosition(P0UnrealIdx).GridSnap(WeldingThreshold);
- auto p1 = Positions.VertexPosition(P1UnrealIdx).GridSnap(WeldingThreshold);
- FUnrealFloatVector Dir;
- float Length;
- (p1 - p0).ToDirectionAndLength(Dir, Length);
- if (Length <= FLT_MIN)
- return false;
- for (int32 i = 0; i < UniqueVerts.Num(); i++)
- {
- const int32 UnrealVertIdx = UniqueVerts[i];
- auto p = Positions.VertexPosition(UnrealVertIdx).GridSnap(WeldingThreshold);
- float Dot = FUnrealFloatVector::DotProduct(p - p0, Dir);
- const float RelLength = Dot / Length;
- if (RelLength > kVertexNear && RelLength < 1.f + kVertexNear)
- {
- FUnrealFloatVector PtOnLine = p0 + Dot * Dir;
- FUnrealFloatVector Diff = PtOnLine - p;
- const float RelDiff = Diff.GetAbsMax() / Length;
- if (RelDiff < kVertexNear)
- {
- VertsOnEdge.Emplace(i, Dot);
- }
- }
- }
- // VertsOnEdge should contain p1 but not p0
- check(VertsOnEdge.Num() > 0);
- VertsOnEdge.Sort([](const TPair<int32, float>& One, const TPair<int32, float>& Two)
- {
- return One.Value < Two.Value;
- });
- return true;
- }
- void DetermineVertsToWeld(TArray<int32>& VertRemap, TArray<int32>& UniqueVerts, const FStaticMeshLODResources& RenderMesh, float WeldingThreshold)
- {
- const int32 VertexCount = RenderMesh.VertexBuffers.PositionVertexBuffer.GetNumVertices();
- // Maps unreal verts to reduced list of verts
- VertRemap.Empty(VertexCount);
- VertRemap.AddUninitialized(VertexCount);
- // List of Unreal Verts to keep
- UniqueVerts.Empty(VertexCount);
- // Combine matching verts using hashed search to maintain good performance
- TMap<FUnrealFloatVector, int32> HashedVerts;
- for (int32 a = 0; a < VertexCount; a++)
- {
- auto PositionA = RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(a).GridSnap(WeldingThreshold);
- const int32* FoundIndex = HashedVerts.Find(PositionA);
- if (!FoundIndex)
- {
- int32 NewIndex = UniqueVerts.Add(a);
- VertRemap[a] = NewIndex;
- HashedVerts.Add(PositionA, NewIndex);
- }
- else
- {
- VertRemap[a] = *FoundIndex;
- }
- }
- }
- void UAkGeometryComponent::ConvertMesh()
- {
- if (!(Parent && IsValid(Parent)))
- return;
- const UAkSettings* AkSettings = GetDefault<UAkSettings>();
- switch (MeshType)
- {
- case AkMeshType::StaticMesh:
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent != nullptr)
- ConvertStaticMesh(MeshParent, AkSettings);
- break;
- }
- case AkMeshType::CollisionMesh:
- {
- ConvertCollisionMesh(Parent, AkSettings);
- break;
- }
- }
- }
- void UAkGeometryComponent::ConvertStaticMesh(UStaticMeshComponent* StaticMeshComponent, const UAkSettings* AkSettings)
- {
- UStaticMesh* mesh = StaticMeshComponent->GetStaticMesh();
- if (!(mesh && IsValid(mesh)))
- return;
- if (LOD > mesh->GetNumLODs() - 1)
- LOD = mesh->GetNumLODs() - 1;
- #if UE_4_27_OR_LATER
- if (!mesh->GetRenderData())
- return;
- #else
- if (!mesh->RenderData)
- return;
- #endif
- const FStaticMeshLODResources& RenderMesh = mesh->GetLODForExport(LOD);
- FIndexArrayView RawIndices = RenderMesh.IndexBuffer.GetArrayView();
- if (RawIndices.Num() == 0)
- return;
- GeometryData.Clear();
- TArray<int32> VertRemap;
- TArray<int32> UniqueVerts;
- DetermineVertsToWeld(VertRemap, UniqueVerts, RenderMesh, WeldingThreshold);
- for (int PosIndex = 0; PosIndex < UniqueVerts.Num(); ++PosIndex)
- {
- const int32 UnrealPosIndex = UniqueVerts[PosIndex];
- auto VertexInActorSpace = RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(UnrealPosIndex);
- GeometryData.Vertices.Add(FVector(VertexInActorSpace));
- }
- UpdateMeshAndArchetype(StaticMeshComponent);
- CalculateSurfaceArea(StaticMeshComponent);
- const int32 PolygonsCount = RenderMesh.Sections.Num();
- for (int32 PolygonsIndex = 0; PolygonsIndex < PolygonsCount; ++PolygonsIndex)
- {
- const FStaticMeshSection& Polygons = RenderMesh.Sections[PolygonsIndex];
- FAkAcousticSurface Surface;
- UPhysicalMaterial* physMatTexture = nullptr;
- UPhysicalMaterial* physMatOcclusion = nullptr;
- FAkGeometrySurfaceOverride surfaceOverride;
- UMaterialInterface* Material = StaticMeshComponent->GetMaterial(Polygons.MaterialIndex);
- if (Material)
- {
- UPhysicalMaterial* physicalMaterial = Material->GetPhysicalMaterial();
- if (StaticMeshSurfaceOverride.Contains(Material))
- surfaceOverride = StaticMeshSurfaceOverride[Material];
-
- if (!surfaceOverride.AcousticTexture)
- physMatTexture = physicalMaterial;
- if (!surfaceOverride.bEnableOcclusionOverride)
- physMatOcclusion = physicalMaterial;
- }
- if (surfaceOverride.AcousticTexture)
- Surface.Texture = surfaceOverride.AcousticTexture->GetShortID();
- if (surfaceOverride.bEnableOcclusionOverride)
- Surface.Occlusion = surfaceOverride.OcclusionValue;
- GeometryData.Surfaces.Add(Surface);
- GeometryData.ToOverrideAcousticTexture.Add(physMatTexture);
- GeometryData.ToOverrideOcclusion.Add(physMatOcclusion);
- AkSurfIdx surfIdx = (AkSurfIdx)(GeometryData.Surfaces.Num() - 1);
- TArray< TPair<int32, float> > Edge0, Edge1, Edge2;
- const uint32 TriangleCount = Polygons.NumTriangles;
- for (uint32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
- {
- uint32 RawVertIndex0 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 0)];
- uint32 UniqueVertIndex0 = VertRemap[RawVertIndex0];
- uint32 RawVertIndex1 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 1)];
- uint32 UniqueVertIndex1 = VertRemap[RawVertIndex1];
- uint32 RawVertIndex2 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 2)];
- uint32 UniqueVertIndex2 = VertRemap[RawVertIndex2];
- Edge0.Empty(8);
- bool succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex0, UniqueVertIndex0, RawVertIndex1, UniqueVertIndex1, Edge0, WeldingThreshold);
- if (!succeeded)
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::ConvertStaticMesh Vertex IDs %i and %i are too close resulting in a triangle with an area of 0. The triangle will be skipped."), *GetOwner()->GetName(), RawVertIndex0, RawVertIndex1);
- continue;
- }
- Edge1.Empty(8);
- succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex1, UniqueVertIndex1, RawVertIndex2, UniqueVertIndex2, Edge1, WeldingThreshold);
- if (!succeeded)
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::ConvertStaticMesh Vertex IDs %i and %i are too close resulting in a triangle with an area of 0. The triangle will be skipped."), *GetOwner()->GetName(), RawVertIndex1, RawVertIndex2);
- continue;
- }
- Edge2.Empty(8);
- succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex2, UniqueVertIndex2, RawVertIndex0, UniqueVertIndex0, Edge2, WeldingThreshold);
- if (!succeeded)
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::ConvertStaticMesh Vertex IDs %i and %i are too close resulting in a triangle with an area of 0. The triangle will be skipped."), *GetOwner()->GetName(), RawVertIndex2, RawVertIndex0);
- continue;
- }
- FAkTriangle triangle;
- triangle.Surface = surfIdx;
- bool bDone = false;
- do
- {
- int32 v0, v1, v2;
- if (Edge0.Num() > 1)
- {
- v1 = Edge0.Pop().Key;
- v0 = Edge0.Last().Key;
- v2 = Edge1[0].Key;
- }
- else if (Edge1.Num() > 1)
- {
- v1 = Edge1.Pop().Key;
- v0 = Edge1.Last().Key;
- v2 = Edge2[0].Key;
- }
- else if (Edge2.Num() > 1)
- {
- v1 = Edge2.Pop().Key;
- v0 = Edge2.Last().Key;
- v2 = Edge0[0].Key;
- }
- else
- {
- v0 = Edge0[0].Key;
- v1 = Edge1[0].Key;
- v2 = Edge2[0].Key;
- bDone = true;
- }
- triangle.Point0 = (AkVertIdx)v0;
- triangle.Point1 = (AkVertIdx)v1;
- triangle.Point2 = (AkVertIdx)v2;
- if (triangle.Point0 != triangle.Point1 &&
- triangle.Point1 != triangle.Point2 &&
- triangle.Point2 != triangle.Point0)
- GeometryData.Triangles.Add(triangle);
- } while (!bDone);
- }
- if (SurfaceAreas.Contains(PolygonsIndex))
- surfaceOverride.SetSurfaceArea(SurfaceAreas[PolygonsIndex]);
- }
- }
- struct VertexIndexByAngle
- {
- AkVertIdx Index;
- float Angle;
- };
- #if AK_USE_PHYSX
- void ConvertConvexMeshToGeometryData(AkSurfIdx surfIdx, const FKConvexElem& convexHull, FAkGeometryData* GeometryData)
- {
- physx::PxConvexMesh* convexMesh = convexHull.GetConvexMesh();
- AkVertIdx initialVertIdx = GeometryData->Vertices.Num();
- if (convexMesh != nullptr)
- {
- const PxVec3* vertices = convexMesh->getVertices();
- uint32 numVerts = (uint32)convexMesh->getNbVertices();
- for (uint32 vertIdx = 0; vertIdx < numVerts; ++vertIdx)
- {
- FVector akvtx;
- akvtx.X = vertices[vertIdx].x;
- akvtx.Y = vertices[vertIdx].y;
- akvtx.Z = vertices[vertIdx].z;
- GeometryData->Vertices.Add(akvtx);
- }
- const physx::PxU8* indexBuf = convexMesh->getIndexBuffer();
- uint32 numPolys = (uint32)convexMesh->getNbPolygons();
- for (uint32 polyIdx = 0; polyIdx < numPolys; polyIdx++)
- {
- PxHullPolygon polyData;
- convexMesh->getPolygonData(polyIdx, polyData);
- // order the vertices of the polygon
- uint32 numVertsInPoly = (uint32)polyData.mNbVerts;
- uint32 vertIdxOffset = (uint32)polyData.mIndexBase;
- TArray<VertexIndexByAngle> orderedIndexes;
- // first element is first vertex index
- AkVertIdx firstVertIdx = (AkVertIdx)indexBuf[vertIdxOffset];
- orderedIndexes.Add(VertexIndexByAngle{ firstVertIdx, 0 });
- // get the center of the polygon
- FVector center(0, 0, 0);
- for (uint32 polyVertIdx = 0; polyVertIdx < numVertsInPoly; ++polyVertIdx)
- {
- auto vertIdx = indexBuf[vertIdxOffset + polyVertIdx];
- center.X += vertices[vertIdx].x;
- center.Y += vertices[vertIdx].y;
- center.Z += vertices[vertIdx].z;
- }
- center.X /= numVertsInPoly;
- center.Y /= numVertsInPoly;
- center.Z /= numVertsInPoly;
- // get the vector from center to the first vertex
- FVector v0;
- v0.X = vertices[firstVertIdx].x - center.X;
- v0.Y = vertices[firstVertIdx].y - center.Y;
- v0.Z = vertices[firstVertIdx].z - center.Z;
- v0.Normalize();
- // get the normal of the plane
- FVector n;
- n.X = polyData.mPlane[0];
- n.Y = polyData.mPlane[1];
- n.Z = polyData.mPlane[2];
- n.Normalize();
- // find the angles between v0 and the other vertices of the polygon
- for (uint32 polyVertIdx = 1; polyVertIdx < numVertsInPoly; polyVertIdx++)
- {
- // get the vector from center to the current vertex
- AkVertIdx vertIdx = (AkVertIdx)indexBuf[vertIdxOffset + polyVertIdx];
- FVector v1;
- v1.X = vertices[vertIdx].x - center.X;
- v1.Y = vertices[vertIdx].y - center.Y;
- v1.Z = vertices[vertIdx].z - center.Z;
- v1.Normalize();
- // get the angle between v0 and v1
- // to do so, we need the dot product and the determinant respectively proportional to cos and sin of the angle.
- // atan2(sin, cos) will give us the angle
- float dot = FVector::DotProduct(v0, v1);
- // the determinant of two 3D vectors in the same plane can be found with the dot product of the normal with the result of
- // a cross product between the vectors
- float det = FVector::DotProduct(n, FVector::CrossProduct(v0, v1));
- float angle = (float)atan2(det, dot);
- orderedIndexes.Add(VertexIndexByAngle{ vertIdx, angle });
- }
- orderedIndexes.Sort();
- // fan triangulation
- for (uint32 vertIdx = 1; vertIdx < numVertsInPoly - 1; ++vertIdx)
- {
- FAkTriangle tri;
- tri.Point0 = (AkVertIdx)orderedIndexes[0].Index + initialVertIdx;
- tri.Point1 = (AkVertIdx)orderedIndexes[vertIdx].Index + initialVertIdx;
- tri.Point2 = (AkVertIdx)orderedIndexes[vertIdx + 1].Index + initialVertIdx;
- tri.Surface = surfIdx;
- GeometryData->Triangles.Add(tri);
- }
- }
- }
- else
- {
- // bounding box
- GeometryData->AddBox(surfIdx,
- convexHull.ElemBox.GetCenter(),
- convexHull.ElemBox.GetExtent(),
- convexHull.GetTransform().Rotator());
- }
- }
- #endif
- bool operator<(const VertexIndexByAngle& lhs, const VertexIndexByAngle& rhs)
- {
- return lhs.Angle < rhs.Angle;
- }
- void UAkGeometryComponent::ConvertCollisionMesh(UPrimitiveComponent* PrimitiveComponent, const UAkSettings* AkSettings)
- {
- UBodySetup* bodySetup = PrimitiveComponent->GetBodySetup();
- if (!(bodySetup && IsValid(bodySetup)))
- return;
- GeometryData.Clear();
- FAkAcousticSurface Surface;
- UPhysicalMaterial* physicalMaterial = bodySetup->GetPhysMaterial();
- UPhysicalMaterial* physMatTexture = nullptr;
- UPhysicalMaterial* physMatOcclusion = nullptr;
- FAkGeometrySurfaceOverride surfaceOverride = CollisionMeshSurfaceOverride;
- if (surfaceOverride.AcousticTexture)
- Surface.Texture = surfaceOverride.AcousticTexture->GetShortID();
- else
- physMatTexture = physicalMaterial;
- if (surfaceOverride.bEnableOcclusionOverride)
- Surface.Occlusion = surfaceOverride.OcclusionValue;
- else
- physMatOcclusion = physicalMaterial;
-
- GeometryData.ToOverrideAcousticTexture.Add(physMatTexture);
- GeometryData.ToOverrideOcclusion.Add(physMatOcclusion);
- GeometryData.Surfaces.Add(Surface);
-
- AkSurfIdx surfIdx = (AkSurfIdx)(GeometryData.Surfaces.Num() - 1);
- int32 numBoxes = bodySetup->AggGeom.BoxElems.Num();
- for (int32 i = 0; i < numBoxes; i++)
- {
- FKBoxElem box = bodySetup->AggGeom.BoxElems[i];
- FVector extent;
- extent.X = box.X / 2;
- extent.Y = box.Y / 2;
- extent.Z = box.Z / 2;
- if ((extent.Z == 0.0f && (extent.X == 0.0f || extent.Y == 0.0f))
- || (extent.Y == 0.0f && (extent.X == 0.0f || extent.Z == 0.0f))
- || (extent.X == 0.0f && (extent.Y == 0.0f || extent.Z == 0.0f)))
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::ConvertCollisionMesh: Unable to add box geometry for box index %i as the box contains no triangles. The box will be skipped."), *GetOwner()->GetName(), i);
- continue;
- }
- GeometryData.AddBox(surfIdx, box.Center, extent, box.Rotation);
- }
- const int sides = 16;
- int32 numSpheres = bodySetup->AggGeom.SphereElems.Num();
- for (int32 i = 0; i < numSpheres; i++)
- {
- FKSphereElem sphere = bodySetup->AggGeom.SphereElems[i];
- GeometryData.AddSphere(surfIdx, sphere.Center, sphere.Radius, sides, sides / 2);
- }
- int32 numCapsules = bodySetup->AggGeom.SphylElems.Num();
- for (int32 i = 0; i < numCapsules; i++)
- {
- FKSphylElem capsule = bodySetup->AggGeom.SphylElems[i];
- FVector X = capsule.GetTransform().GetUnitAxis(EAxis::X);
- FVector Y = capsule.GetTransform().GetUnitAxis(EAxis::Y);
- FVector Z = capsule.GetTransform().GetUnitAxis(EAxis::Z);
- GeometryData.AddCapsule(surfIdx, capsule.Center, X, Y, Z, capsule.Radius, capsule.Length / 2, sides / 2);
- }
- int32 numConvexElems = bodySetup->AggGeom.ConvexElems.Num();
- for (int32 i = 0; i < numConvexElems; i++)
- {
- FKConvexElem& convexElem = bodySetup->AggGeom.ConvexElems[i];
- int32 numVertices = convexElem.VertexData.Num();
- if (numVertices == 0)
- continue;
- #if AK_USE_CHAOS
- // will compute IndexData if it is empty
- convexElem.ComputeChaosConvexIndices(false);
- #endif
- int32 numTriangles = convexElem.IndexData.Num() / 3;
- if (numTriangles == 0)
- {
- #if AK_USE_PHYSX
- ConvertConvexMeshToGeometryData(surfIdx, convexElem, &GeometryData);
- #endif
- continue;
- }
- int32 vertexOffset = GeometryData.Vertices.Num();
- for (int32 vertIdx = 0; vertIdx < numVertices; ++vertIdx)
- {
- GeometryData.Vertices.Add(convexElem.GetTransform().TransformPosition(convexElem.VertexData[vertIdx]));
- }
- for (int32 triIdx = 0; triIdx < numTriangles; ++triIdx)
- {
- FAkTriangle tri;
- tri.Point0 = vertexOffset + convexElem.IndexData[3 * triIdx];
- tri.Point1 = vertexOffset + convexElem.IndexData[3 * triIdx + 1];
- tri.Point2 = vertexOffset + convexElem.IndexData[3 * triIdx + 2];
- tri.Surface = surfIdx;
- GeometryData.Triangles.Add(tri);
- }
- }
- }
- void UAkGeometryComponent::SendGeometry()
- {
- FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
- if (AkAudioDevice && ShouldSendGeometry())
- {
- if (GeometryData.Triangles.Num() > 0 && GeometryData.Vertices.Num() > 0)
- {
- AkGeometryParams params;
- params.NumSurfaces = GeometryData.Surfaces.Num();
- params.NumTriangles = GeometryData.Triangles.Num();
- params.NumVertices = GeometryData.Vertices.Num();
-
- TArray<AkAcousticSurface> Surfaces;
- TArray< TSharedPtr< decltype(StringCast<ANSICHAR>(TEXT(""))) > > SurfaceNames;
- Surfaces.SetNum(params.NumSurfaces);
- SurfaceNames.SetNum(params.NumSurfaces);
- if (params.NumSurfaces)
- {
- for (int i = 0; i < params.NumSurfaces; ++i)
- {
- Surfaces[i].transmissionLoss = GeometryData.Surfaces[i].Occlusion;
- Surfaces[i].strName = nullptr;
- if (!GeometryData.Surfaces[i].Name.IsEmpty())
- {
- SurfaceNames[i] = MakeShareable(new decltype(StringCast<ANSICHAR>(TEXT("")))(*GeometryData.Surfaces[i].Name));
- Surfaces[i].strName = SurfaceNames[i].Get()->Get();
- }
- Surfaces[i].textureID = GeometryData.Surfaces[i].Texture;
- }
- }
- params.Surfaces = Surfaces.GetData();
- TUniquePtr<AkTriangle[]> Triangles = MakeUnique<AkTriangle[]>(params.NumTriangles);// temp triangle buffer
- for (int i = 0; i < params.NumTriangles; ++i)
- {
- Triangles[i].point0 = GeometryData.Triangles[i].Point0;
- Triangles[i].point1 = GeometryData.Triangles[i].Point1;
- Triangles[i].point2 = GeometryData.Triangles[i].Point2;
- Triangles[i].surface = GeometryData.Triangles[i].Surface;
- }
- params.Triangles = Triangles.Get();
- TUniquePtr<AkVertex[]> Vertices = MakeUnique<AkVertex[]>(params.NumVertices); // temp vertex buffer
- for (int i = 0; i < params.NumVertices; ++i)
- {
- Vertices[i].X = GeometryData.Vertices[i].X;
- Vertices[i].Y = GeometryData.Vertices[i].Y;
- Vertices[i].Z = GeometryData.Vertices[i].Z;
- }
- params.Vertices = Vertices.Get();
-
- params.EnableDiffraction = bEnableDiffraction;
- params.EnableDiffractionOnBoundaryEdges = bEnableDiffractionOnBoundaryEdges;
- SendGeometryToWwise(params);
- }
- else
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::SendGeometry() Geometry Data is empty. Nothing was sent to Spatial Audio."), *GetOwner()->GetName());
- }
- }
- }
- void UAkGeometryComponent::RemoveGeometry()
- {
- RemoveGeometryFromWwise();
- }
- void UAkGeometryComponent::UpdateGeometry()
- {
- if (Parent)
- {
- AkRoomID roomID = AkRoomID();
- if (AssociatedRoom)
- {
- UAkRoomComponent* room = Cast<UAkRoomComponent>(AssociatedRoom->GetComponentByClass(UAkRoomComponent::StaticClass()));
- if (room != nullptr)
- roomID = room->GetRoomID();
- }
- SendGeometryInstanceToWwise(Parent->GetComponentRotation(), Parent->GetComponentLocation(), Parent->GetComponentTransform().GetScale3D(), roomID, !bWasAddedByRoom);
- }
- }
- void UAkGeometryComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
- {
- Super::EndPlay(EndPlayReason);
- RemoveGeometry();
- }
- float UAkGeometryComponent::GetSurfaceAreaSquaredMeters(const int& surfaceIndex) const
- {
- if (SurfaceAreas.Contains(surfaceIndex))
- return SurfaceAreas[surfaceIndex] / AkComponentHelpers::UnrealUnitsPerSquaredMeter(Parent);
- return 0.0f;
- }
- #if WITH_EDITOR
- void UAkGeometryComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
- {
- Super::PostEditChangeProperty(PropertyChangedEvent);
- if (AkComponentHelpers::IsGameWorldBlueprintComponent(this) || IsBeingDestroyed())
- return;
- if (AssociatedRoom && !Cast<UAkRoomComponent>(AssociatedRoom->GetComponentByClass(UAkRoomComponent::StaticClass())))
- {
- UE_LOG(LogAkAudio, Warning, TEXT("%s: The Associated Room is not of type UAkRoomComponent."), *GetOwner()->GetName());
- }
- const FName memberPropertyName = (PropertyChangedEvent.MemberProperty != nullptr) ? PropertyChangedEvent.MemberProperty->GetFName() : NAME_None;
- const FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
- if (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, MeshType))
- {
- if (Parent != nullptr && MeshType == AkMeshType::StaticMesh)
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent == nullptr)
- {
- FString actorString = FString("NONE");
- if (GetOwner() != nullptr)
- actorString = GetOwner()->GetName();
- FString parentName = Parent->GetName();
- FString parentClass = Parent->GetClass()->GetName();
- UE_LOG(LogAkAudio, Warning,
- TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
- , *actorString, *GetName(), *parentClass, *parentName);
- UE_LOG(LogAkAudio, Warning, TEXT("When MeshType is set to Static Mesh, UAkGeometryComponent requires to be nested under a component inheriting from UStaticMeshComponent. Reverting to Simple Collision."));
- MeshType = AkMeshType::CollisionMesh;
- }
- else
- {
- UpdateStaticMeshOverride();
- }
- }
- UnregisterTextureParamChangeCallbacks();
- RegisterAllTextureParamCallbacks();
- }
- else if ( (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, StaticMeshSurfaceOverride) && MeshType == AkMeshType::StaticMesh)
- || (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, CollisionMeshSurfaceOverride) && MeshType == AkMeshType::CollisionMesh))
- {
- UnregisterTextureParamChangeCallbacks();
- RegisterAllTextureParamCallbacks();
- DampingEstimationNeedsUpdate = true;
- }
- if (MeshType == AkMeshType::StaticMesh &&
- memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, WeldingThreshold) &&
- PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet)
- {
- ConvertMesh();
- SendGeometry();
- UpdateGeometry();
- }
- else if (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, bEnableDiffraction) ||
- memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, bEnableDiffractionOnBoundaryEdges))
- {
- SendGeometry();
- UpdateGeometry();
- }
- }
- void UAkGeometryComponent::PostEditUndo()
- {
- OnRefreshDetails.ExecuteIfBound();
- Super::PostEditUndo();
- }
- void UAkGeometryComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
- {
- Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
- if (bRequiresDeferredBeginPlay)
- {
- BeginPlayInternal();
- bRequiresDeferredBeginPlay = false;
- }
- if (MeshType == AkMeshType::StaticMesh)
- {
- if (IsValid(Parent) && !Parent->IsBeingDestroyed())
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent != nullptr && StaticMeshSurfaceOverride.Num() != MeshParent->GetNumMaterials())
- UpdateMeshAndArchetype(MeshParent);
- }
- if (bMeshMaterialChanged)
- {
- OnRefreshDetails.ExecuteIfBound();
- bMeshMaterialChanged = false;
- }
- }
- }
- #endif
- void UAkGeometryComponent::UpdateStaticMeshOverride()
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent != nullptr)
- {
- UpdateMeshAndArchetype(MeshParent);
- }
- }
- void UAkGeometryComponent::UpdateMeshAndArchetype(UStaticMeshComponent* StaticMeshComponent)
- {
- _UpdateStaticMeshOverride(StaticMeshComponent);
- // If we're in the Blueprint editor, update the Archetype object as well.
- // (The archetype object is the object that's edited when properties are changed in the Blueprint editor details inspector.
- // This is a separate object from the objects shown in the Blueprint editor viewport.)
- UWorld* World = GetWorld();
- if (World != nullptr && World->WorldType == EWorldType::EditorPreview
- && CreationMethod == EComponentCreationMethod::SimpleConstructionScript)
- {
- UAkGeometryComponent* Archetype = Cast<UAkGeometryComponent>(GetArchetype());
- if (Archetype != nullptr)
- Archetype->_UpdateStaticMeshOverride(StaticMeshComponent);
- }
- }
- void UAkGeometryComponent::_UpdateStaticMeshOverride(UStaticMeshComponent* StaticMeshComponent)
- {
- auto ToRemove = StaticMeshSurfaceOverride;
- int numMaterials = StaticMeshComponent->GetNumMaterials();
- for (int i = 0; i < numMaterials; i++)
- {
- UMaterialInterface* material = StaticMeshComponent->GetMaterial(i);
- if (StaticMeshSurfaceOverride.Contains(material))
- ToRemove.Remove(material);
- else
- {
- FAkGeometrySurfaceOverride surfaceOverride;
- if (PreviousStaticMeshSurfaceOverride.Contains(material))
- surfaceOverride = PreviousStaticMeshSurfaceOverride[material];
- StaticMeshSurfaceOverride.Add(material, surfaceOverride);
- }
- }
- #if WITH_EDITORONLY_DATA
- if (ToRemove.Num() > 0)
- bMeshMaterialChanged = true;
- #endif
- for (auto& elemToRemove : ToRemove)
- StaticMeshSurfaceOverride.Remove(elemToRemove.Key);
- ToRemove.Empty();
- PreviousStaticMeshSurfaceOverride.Empty();
- PreviousStaticMeshSurfaceOverride = StaticMeshSurfaceOverride;
- }
- void UAkGeometryComponent::Serialize(FArchive& Ar)
- {
- #if WITH_EDITORONLY_DATA
- UWorld* World = GetWorld();
- if (Ar.IsSaving() && World != nullptr && !World->IsGameWorld())
- ConvertMesh();
- #endif
- Super::Serialize(Ar);
- }
- void UAkGeometryComponent::GetTexturesAndSurfaceAreas(TArray<FAkAcousticTextureParams>& textures, TArray<float>& surfaceAreas) const
- {
- textures.Empty();
- surfaceAreas.Empty();
- const UAkSettings* AkSettings = GetDefault<UAkSettings>();
- if (AkSettings != nullptr)
- {
- if (MeshType == AkMeshType::CollisionMesh)
- {
- if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
- {
- #if WITH_EDITOR
- // Get the most accurate absorption values from the list in the AkSettings
- const FAkAcousticTextureParams* params = AkSettings->GetTextureParams(CollisionMeshSurfaceOverride.AcousticTexture->GetShortID());
- if (params != nullptr)
- {
- textures.Add(*params);
- surfaceAreas.Add(1.0f); // When there is only 1 acoustic texture, surface area magnitude is not important.
- }
- #else
- // Get the absorption values from the cooked data
- FAkAcousticTextureParams params;
- params.AbsorptionValues = FVector4(
- CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureCookedData.AbsorptionLow / 100.0f,
- CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureCookedData.AbsorptionMidLow / 100.0f,
- CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureCookedData.AbsorptionMidHigh / 100.0f,
- CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureCookedData.AbsorptionHigh / 100.0f
- );
- textures.Add(params);
- surfaceAreas.Add(1.0f); // When there is only 1 acoustic texture, surface area magnitude is not important.
- #endif
- }
- }
- else
- {
- if (StaticMeshSurfaceOverride.Num() > 0)
- {
- int surfIdx = 0;
- float surfaceArea = 0.0f;
- for (auto it = StaticMeshSurfaceOverride.CreateConstIterator(); it; ++it)
- {
- surfaceArea = GetSurfaceAreaSquaredMeters(surfIdx);
- surfaceAreas.Add(surfaceArea);
- FAkAcousticTextureParams params;
- FAkGeometrySurfaceOverride surface = it.Value();
- if (surface.AcousticTexture != nullptr)
- {
- #if WITH_EDITOR
- // Get the most accurate absorption values from the list in the AkSettings
- const FAkAcousticTextureParams* paramsFound = AkSettings->GetTextureParams(surface.AcousticTexture->GetShortID());
- if (paramsFound != nullptr)
- {
- params = *paramsFound;
- }
- #else
- params.AbsorptionValues = FVector4(
- surface.AcousticTexture->AcousticTextureCookedData.AbsorptionLow / 100.0f,
- surface.AcousticTexture->AcousticTextureCookedData.AbsorptionMidLow / 100.0f,
- surface.AcousticTexture->AcousticTextureCookedData.AbsorptionMidHigh / 100.0f,
- surface.AcousticTexture->AcousticTextureCookedData.AbsorptionHigh / 100.0f
- );
- #endif
- }
- textures.Add(params);
- ++surfIdx;
- }
- }
- }
- }
- }
- #if WITH_EDITOR
- void UAkGeometryComponent::HandleObjectsReplaced(const TMap<UObject*, UObject*>& ReplacementMap)
- {
- Super::HandleObjectsReplaced(ReplacementMap);
- if (ReplacementMap.Contains(Parent))
- {
- InitializeParent();
- if (Parent != nullptr)
- {
- if (MeshType == AkMeshType::StaticMesh)
- {
- UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
- if (MeshParent != nullptr)
- CalculateSurfaceArea(MeshParent);
- }
- DampingEstimationNeedsUpdate = true;
- }
- }
- }
- bool UAkGeometryComponent::ContainsTexture(const FGuid& textureID)
- {
- if (MeshType == AkMeshType::CollisionMesh)
- {
- if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
- return CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureInfo.WwiseGuid == textureID;
- }
- else
- {
- for (auto it = StaticMeshSurfaceOverride.CreateIterator(); it; ++it)
- {
- if (it.Value().AcousticTexture != nullptr)
- {
- if (it.Value().AcousticTexture->AcousticTextureInfo.WwiseGuid == textureID)
- return true;
- }
- }
- }
- return false;
- }
- void UAkGeometryComponent::RegisterAllTextureParamCallbacks()
- {
- if (MeshType == AkMeshType::CollisionMesh)
- {
- if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
- RegisterTextureParamChangeCallback(CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureInfo.WwiseGuid);
- }
- else
- {
- for (auto it = StaticMeshSurfaceOverride.CreateIterator(); it; ++it)
- {
- if (it.Value().AcousticTexture != nullptr)
- {
- RegisterTextureParamChangeCallback(it.Value().AcousticTexture->AcousticTextureInfo.WwiseGuid);
- }
- }
- }
- }
- #endif
|