AkGeometryComponent.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "AkGeometryComponent.h"
  16. #include "AkAcousticTexture.h"
  17. #include "AkAudioDevice.h"
  18. #include "AkComponentHelpers.h"
  19. #include "AkReverbDescriptor.h"
  20. #include "AkRoomComponent.h"
  21. #include "AkSettings.h"
  22. #include "AkUEFeatures.h"
  23. #if AK_USE_PHYSX
  24. #include "PhysXPublic.h"
  25. #endif
  26. #if AK_USE_CHAOS
  27. #include "ChaosLog.h"
  28. #include "Chaos/CollisionConvexMesh.h"
  29. #include "Chaos/Convex.h"
  30. #endif
  31. #if WITH_EDITOR
  32. #include "Editor.h"
  33. #endif
  34. #include "RawIndexBuffer.h"
  35. #include "StaticMeshResources.h"
  36. #include "Components/StaticMeshComponent.h"
  37. #include "Engine/GameEngine.h"
  38. #include "Engine/Polys.h"
  39. #include "Engine/StaticMesh.h"
  40. #include "PhysicsEngine/BodySetup.h"
  41. #include "UObject/Object.h"
  42. static const float kVertexNear = 0.0001;
  43. UAkGeometryComponent::UAkGeometryComponent(const class FObjectInitializer& ObjectInitializer) :
  44. Super(ObjectInitializer)
  45. {
  46. // Property initialization
  47. bWantsOnUpdateTransform = true;
  48. MeshType = AkMeshType::CollisionMesh;
  49. LOD = 0;
  50. CollisionMeshSurfaceOverride.AcousticTexture = nullptr;
  51. CollisionMeshSurfaceOverride.bEnableOcclusionOverride = false;
  52. CollisionMeshSurfaceOverride.OcclusionValue = 1.f;
  53. WeldingThreshold = 0.001;
  54. bWasAddedByRoom = 0;
  55. bEnableDiffraction = 1;
  56. bEnableDiffractionOnBoundaryEdges = 0;
  57. #if WITH_EDITOR
  58. PrimaryComponentTick.bCanEverTick = true;
  59. bTickInEditor = true;
  60. #endif
  61. }
  62. void UAkGeometryComponent::OnComponentDestroyed(bool bDestroyingHierarchy)
  63. {
  64. Super::OnComponentDestroyed(bDestroyingHierarchy);
  65. RemoveGeometry();
  66. StaticMeshSurfaceOverride.Empty();
  67. #if WITH_EDITOR
  68. check(!OnMeshMaterialChangedHandle.IsValid());
  69. #endif
  70. }
  71. void UAkGeometryComponent::OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport)
  72. {
  73. Super::OnUpdateTransform(UpdateTransformFlags, Teleport);
  74. UpdateGeometry();
  75. if (ReverbDescriptor != nullptr)
  76. {
  77. DampingEstimationNeedsUpdate = true;
  78. }
  79. }
  80. bool UAkGeometryComponent::MoveComponentImpl(
  81. const FVector & Delta,
  82. const FQuat & NewRotation,
  83. bool bSweep,
  84. FHitResult * Hit,
  85. EMoveComponentFlags MoveFlags,
  86. ETeleportType Teleport)
  87. {
  88. if (AkComponentHelpers::DoesMovementRecenterChild(this, Parent, Delta))
  89. Super::MoveComponentImpl(Delta, NewRotation, bSweep, Hit, MoveFlags, Teleport);
  90. return false;
  91. }
  92. void UAkGeometryComponent::BeginPlay()
  93. {
  94. Super::BeginPlay();
  95. if (!IsBeingDestroyed())
  96. {
  97. #if WITH_EDITOR
  98. if (AkComponentHelpers::ShouldDeferBeginPlay(this))
  99. bRequiresDeferredBeginPlay = true;
  100. else
  101. BeginPlayInternal();
  102. #else
  103. BeginPlayInternal();
  104. #endif
  105. }
  106. }
  107. void UAkGeometryComponent::BeginPlayInternal()
  108. {
  109. if (Parent == nullptr)
  110. InitializeParent();
  111. if (GeometryData.Vertices.Num() == 0)
  112. ConvertMesh();
  113. for (int PosIndex = 0; PosIndex < GeometryData.Surfaces.Num(); ++PosIndex)
  114. {
  115. // set geometry surface names and update textures
  116. FString OwnerName;
  117. #if WITH_EDITOR
  118. OwnerName = GetOwner()->GetActorLabel();
  119. #else
  120. OwnerName = GetOwner()->GetName();
  121. #endif
  122. GeometryData.Surfaces[PosIndex].Name = OwnerName + GetName() + FString::FromInt(PosIndex);
  123. UPhysicalMaterial* physMat = GeometryData.ToOverrideAcousticTexture[PosIndex];
  124. if (physMat)
  125. {
  126. UAkAcousticTexture* acousticTexture = nullptr;
  127. if (GetDefault<UAkSettings>()->GetAssociatedAcousticTexture(physMat, acousticTexture))
  128. {
  129. if (acousticTexture)
  130. GeometryData.Surfaces[PosIndex].Texture = acousticTexture->GetShortID();
  131. }
  132. }
  133. physMat = GeometryData.ToOverrideOcclusion[PosIndex];
  134. if (physMat)
  135. {
  136. float occlusionValue = 1.f;
  137. if (GetDefault<UAkSettings>()->GetAssociatedOcclusionValue(physMat, occlusionValue))
  138. {
  139. GeometryData.Surfaces[PosIndex].Occlusion = occlusionValue;
  140. }
  141. }
  142. }
  143. SendGeometry();
  144. UpdateGeometry();
  145. DampingEstimationNeedsUpdate = true;
  146. }
  147. void UAkGeometryComponent::OnRegister()
  148. {
  149. Super::OnRegister();
  150. SetRelativeTransform(FTransform::Identity);
  151. InitializeParent();
  152. #if WITH_EDITOR
  153. OnMeshMaterialChangedHandle = FCoreUObjectDelegates::OnObjectPropertyChanged.AddLambda([this](UObject* Object, FPropertyChangedEvent& PropertyChangedEvent)
  154. {
  155. if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(UMeshComponent, OverrideMaterials) &&
  156. Parent != nullptr &&
  157. Parent == Object &&
  158. MeshType == AkMeshType::StaticMesh
  159. )
  160. {
  161. UpdateStaticMeshOverride();
  162. }
  163. });
  164. if (Parent != nullptr)
  165. {
  166. if (MeshType == AkMeshType::StaticMesh)
  167. {
  168. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  169. if (MeshParent != nullptr)
  170. CalculateSurfaceArea(MeshParent);
  171. }
  172. DampingEstimationNeedsUpdate = true;
  173. }
  174. #endif
  175. }
  176. void UAkGeometryComponent::OnUnregister()
  177. {
  178. #if WITH_EDITOR
  179. FCoreUObjectDelegates::OnObjectPropertyChanged.Remove(OnMeshMaterialChangedHandle);
  180. OnMeshMaterialChangedHandle.Reset();
  181. #endif
  182. Parent = nullptr;
  183. Super::OnUnregister();
  184. }
  185. void UAkGeometryComponent::InitializeParent()
  186. {
  187. USceneComponent* SceneParent = GetAttachParent();
  188. if (SceneParent != nullptr)
  189. {
  190. Parent = Cast<UPrimitiveComponent>(SceneParent);
  191. if (!Parent)
  192. {
  193. FString actorString = FString("NONE");
  194. if (GetOwner() != nullptr)
  195. actorString = GetOwner()->GetName();
  196. FString parentName = SceneParent->GetName();
  197. FString parentClass = SceneParent->GetClass()->GetName();
  198. UE_LOG(LogAkAudio, Error,
  199. TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
  200. , *actorString, *GetName(), *parentClass, *parentName);
  201. if (MeshType == AkMeshType::StaticMesh)
  202. {
  203. UE_LOG(LogAkAudio, Error, TEXT("When MeshType is set to Static Mesh, UAkGeometryComponent requires to be nested under a component inheriting from UStaticMeshComponent."));
  204. }
  205. else
  206. {
  207. UE_LOG(LogAkAudio, Error, TEXT("When MeshType is set to Simple Collision, UAkGeometryComponent requires to be nested under a component inheriting from UPrimitiveComponent."));
  208. }
  209. return;
  210. }
  211. if (MeshType == AkMeshType::StaticMesh)
  212. {
  213. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(SceneParent);
  214. if (MeshParent != nullptr)
  215. {
  216. bool fillMaterialKeys = true;
  217. #if WITH_EDITOR
  218. // 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).
  219. if (GetOwner() != nullptr && GetOwner()->CurrentTransactionAnnotation != nullptr)
  220. {
  221. fillMaterialKeys = false;
  222. }
  223. #endif
  224. if (fillMaterialKeys)
  225. {
  226. UpdateMeshAndArchetype(MeshParent);
  227. }
  228. }
  229. else
  230. {
  231. FString actorString = FString("NONE");
  232. if (GetOwner() != nullptr)
  233. actorString = GetOwner()->GetName();
  234. FString parentName = SceneParent->GetName();
  235. FString parentClass = SceneParent->GetClass()->GetName();
  236. UE_LOG(LogAkAudio, Warning,
  237. TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
  238. , *actorString, *GetName(), *parentClass, *parentName);
  239. 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."));
  240. MeshType = AkMeshType::CollisionMesh;
  241. // If we're in the Blueprint editor, update the Archetype object as well.
  242. UWorld* World = GetWorld();
  243. if (World != nullptr && World->WorldType == EWorldType::EditorPreview
  244. && CreationMethod == EComponentCreationMethod::SimpleConstructionScript)
  245. {
  246. UAkGeometryComponent* Archetype = Cast<UAkGeometryComponent>(GetArchetype());
  247. if (Archetype != nullptr)
  248. Archetype->MeshType = AkMeshType::CollisionMesh;
  249. }
  250. }
  251. }
  252. }
  253. }
  254. void UAkGeometryComponent::CalculateSurfaceArea(UStaticMeshComponent* StaticMeshComponent)
  255. {
  256. SurfaceAreas.Empty();
  257. UStaticMesh* mesh = StaticMeshComponent->GetStaticMesh();
  258. #if UE_4_27_OR_LATER
  259. if (mesh == nullptr || !mesh->GetRenderData())
  260. return;
  261. #else
  262. if (mesh == nullptr || !mesh->RenderData)
  263. return;
  264. #endif
  265. const FStaticMeshLODResources& RenderMesh = mesh->GetLODForExport(LOD);
  266. FIndexArrayView RawIndices = RenderMesh.IndexBuffer.GetArrayView();
  267. if (RawIndices.Num() == 0)
  268. return;
  269. const int32 PolygonsCount = RenderMesh.Sections.Num();
  270. double SurfaceArea = 0.0;
  271. const auto WorldScale = StaticMeshComponent->GetOwner()->ActorToWorld().GetScale3D();
  272. for (int32 PolygonsIndex = 0; PolygonsIndex < PolygonsCount; ++PolygonsIndex)
  273. {
  274. const FStaticMeshSection& Polygons = RenderMesh.Sections[PolygonsIndex];
  275. const uint32 TriangleCount = Polygons.NumTriangles;
  276. for (uint32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
  277. {
  278. const uint32 RawVertIndex0 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 0)];
  279. const uint32 RawVertIndex1 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 1)];
  280. const uint32 RawVertIndex2 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 2)];
  281. // Scale to world space to ensure proper area
  282. auto ScaledP0 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex0).GridSnap(WeldingThreshold));
  283. auto ScaledP1 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex1).GridSnap(WeldingThreshold));
  284. auto ScaledP2 = WorldScale * FVector(RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(RawVertIndex2).GridSnap(WeldingThreshold));
  285. SurfaceArea += FAkReverbDescriptor::TriangleArea(ScaledP0, ScaledP1, ScaledP2);
  286. }
  287. SurfaceAreas.Add(PolygonsIndex, SurfaceArea);
  288. }
  289. }
  290. bool AddVertsForEdge(const FPositionVertexBuffer& Positions, TArray<int32>& UniqueVerts, int32 P0UnrealIdx, int32 P0UniqueIdx, int32 P1UnrealIdx, int32 P1UniqueIdx, TArray< TPair<int32, float> > & VertsOnEdge, float WeldingThreshold)
  291. {
  292. auto p0 = Positions.VertexPosition(P0UnrealIdx).GridSnap(WeldingThreshold);
  293. auto p1 = Positions.VertexPosition(P1UnrealIdx).GridSnap(WeldingThreshold);
  294. FUnrealFloatVector Dir;
  295. float Length;
  296. (p1 - p0).ToDirectionAndLength(Dir, Length);
  297. if (Length <= FLT_MIN)
  298. return false;
  299. for (int32 i = 0; i < UniqueVerts.Num(); i++)
  300. {
  301. const int32 UnrealVertIdx = UniqueVerts[i];
  302. auto p = Positions.VertexPosition(UnrealVertIdx).GridSnap(WeldingThreshold);
  303. float Dot = FUnrealFloatVector::DotProduct(p - p0, Dir);
  304. const float RelLength = Dot / Length;
  305. if (RelLength > kVertexNear && RelLength < 1.f + kVertexNear)
  306. {
  307. FUnrealFloatVector PtOnLine = p0 + Dot * Dir;
  308. FUnrealFloatVector Diff = PtOnLine - p;
  309. const float RelDiff = Diff.GetAbsMax() / Length;
  310. if (RelDiff < kVertexNear)
  311. {
  312. VertsOnEdge.Emplace(i, Dot);
  313. }
  314. }
  315. }
  316. // VertsOnEdge should contain p1 but not p0
  317. check(VertsOnEdge.Num() > 0);
  318. VertsOnEdge.Sort([](const TPair<int32, float>& One, const TPair<int32, float>& Two)
  319. {
  320. return One.Value < Two.Value;
  321. });
  322. return true;
  323. }
  324. void DetermineVertsToWeld(TArray<int32>& VertRemap, TArray<int32>& UniqueVerts, const FStaticMeshLODResources& RenderMesh, float WeldingThreshold)
  325. {
  326. const int32 VertexCount = RenderMesh.VertexBuffers.PositionVertexBuffer.GetNumVertices();
  327. // Maps unreal verts to reduced list of verts
  328. VertRemap.Empty(VertexCount);
  329. VertRemap.AddUninitialized(VertexCount);
  330. // List of Unreal Verts to keep
  331. UniqueVerts.Empty(VertexCount);
  332. // Combine matching verts using hashed search to maintain good performance
  333. TMap<FUnrealFloatVector, int32> HashedVerts;
  334. for (int32 a = 0; a < VertexCount; a++)
  335. {
  336. auto PositionA = RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(a).GridSnap(WeldingThreshold);
  337. const int32* FoundIndex = HashedVerts.Find(PositionA);
  338. if (!FoundIndex)
  339. {
  340. int32 NewIndex = UniqueVerts.Add(a);
  341. VertRemap[a] = NewIndex;
  342. HashedVerts.Add(PositionA, NewIndex);
  343. }
  344. else
  345. {
  346. VertRemap[a] = *FoundIndex;
  347. }
  348. }
  349. }
  350. void UAkGeometryComponent::ConvertMesh()
  351. {
  352. if (!(Parent && IsValid(Parent)))
  353. return;
  354. const UAkSettings* AkSettings = GetDefault<UAkSettings>();
  355. switch (MeshType)
  356. {
  357. case AkMeshType::StaticMesh:
  358. {
  359. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  360. if (MeshParent != nullptr)
  361. ConvertStaticMesh(MeshParent, AkSettings);
  362. break;
  363. }
  364. case AkMeshType::CollisionMesh:
  365. {
  366. ConvertCollisionMesh(Parent, AkSettings);
  367. break;
  368. }
  369. }
  370. }
  371. void UAkGeometryComponent::ConvertStaticMesh(UStaticMeshComponent* StaticMeshComponent, const UAkSettings* AkSettings)
  372. {
  373. UStaticMesh* mesh = StaticMeshComponent->GetStaticMesh();
  374. if (!(mesh && IsValid(mesh)))
  375. return;
  376. if (LOD > mesh->GetNumLODs() - 1)
  377. LOD = mesh->GetNumLODs() - 1;
  378. #if UE_4_27_OR_LATER
  379. if (!mesh->GetRenderData())
  380. return;
  381. #else
  382. if (!mesh->RenderData)
  383. return;
  384. #endif
  385. const FStaticMeshLODResources& RenderMesh = mesh->GetLODForExport(LOD);
  386. FIndexArrayView RawIndices = RenderMesh.IndexBuffer.GetArrayView();
  387. if (RawIndices.Num() == 0)
  388. return;
  389. GeometryData.Clear();
  390. TArray<int32> VertRemap;
  391. TArray<int32> UniqueVerts;
  392. DetermineVertsToWeld(VertRemap, UniqueVerts, RenderMesh, WeldingThreshold);
  393. for (int PosIndex = 0; PosIndex < UniqueVerts.Num(); ++PosIndex)
  394. {
  395. const int32 UnrealPosIndex = UniqueVerts[PosIndex];
  396. auto VertexInActorSpace = RenderMesh.VertexBuffers.PositionVertexBuffer.VertexPosition(UnrealPosIndex);
  397. GeometryData.Vertices.Add(FVector(VertexInActorSpace));
  398. }
  399. UpdateMeshAndArchetype(StaticMeshComponent);
  400. CalculateSurfaceArea(StaticMeshComponent);
  401. const int32 PolygonsCount = RenderMesh.Sections.Num();
  402. for (int32 PolygonsIndex = 0; PolygonsIndex < PolygonsCount; ++PolygonsIndex)
  403. {
  404. const FStaticMeshSection& Polygons = RenderMesh.Sections[PolygonsIndex];
  405. FAkAcousticSurface Surface;
  406. UPhysicalMaterial* physMatTexture = nullptr;
  407. UPhysicalMaterial* physMatOcclusion = nullptr;
  408. FAkGeometrySurfaceOverride surfaceOverride;
  409. UMaterialInterface* Material = StaticMeshComponent->GetMaterial(Polygons.MaterialIndex);
  410. if (Material)
  411. {
  412. UPhysicalMaterial* physicalMaterial = Material->GetPhysicalMaterial();
  413. if (StaticMeshSurfaceOverride.Contains(Material))
  414. surfaceOverride = StaticMeshSurfaceOverride[Material];
  415. if (!surfaceOverride.AcousticTexture)
  416. physMatTexture = physicalMaterial;
  417. if (!surfaceOverride.bEnableOcclusionOverride)
  418. physMatOcclusion = physicalMaterial;
  419. }
  420. if (surfaceOverride.AcousticTexture)
  421. Surface.Texture = surfaceOverride.AcousticTexture->GetShortID();
  422. if (surfaceOverride.bEnableOcclusionOverride)
  423. Surface.Occlusion = surfaceOverride.OcclusionValue;
  424. GeometryData.Surfaces.Add(Surface);
  425. GeometryData.ToOverrideAcousticTexture.Add(physMatTexture);
  426. GeometryData.ToOverrideOcclusion.Add(physMatOcclusion);
  427. AkSurfIdx surfIdx = (AkSurfIdx)(GeometryData.Surfaces.Num() - 1);
  428. TArray< TPair<int32, float> > Edge0, Edge1, Edge2;
  429. const uint32 TriangleCount = Polygons.NumTriangles;
  430. for (uint32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
  431. {
  432. uint32 RawVertIndex0 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 0)];
  433. uint32 UniqueVertIndex0 = VertRemap[RawVertIndex0];
  434. uint32 RawVertIndex1 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 1)];
  435. uint32 UniqueVertIndex1 = VertRemap[RawVertIndex1];
  436. uint32 RawVertIndex2 = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + 2)];
  437. uint32 UniqueVertIndex2 = VertRemap[RawVertIndex2];
  438. Edge0.Empty(8);
  439. bool succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex0, UniqueVertIndex0, RawVertIndex1, UniqueVertIndex1, Edge0, WeldingThreshold);
  440. if (!succeeded)
  441. {
  442. 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);
  443. continue;
  444. }
  445. Edge1.Empty(8);
  446. succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex1, UniqueVertIndex1, RawVertIndex2, UniqueVertIndex2, Edge1, WeldingThreshold);
  447. if (!succeeded)
  448. {
  449. 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);
  450. continue;
  451. }
  452. Edge2.Empty(8);
  453. succeeded = AddVertsForEdge(RenderMesh.VertexBuffers.PositionVertexBuffer, UniqueVerts, RawVertIndex2, UniqueVertIndex2, RawVertIndex0, UniqueVertIndex0, Edge2, WeldingThreshold);
  454. if (!succeeded)
  455. {
  456. 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);
  457. continue;
  458. }
  459. FAkTriangle triangle;
  460. triangle.Surface = surfIdx;
  461. bool bDone = false;
  462. do
  463. {
  464. int32 v0, v1, v2;
  465. if (Edge0.Num() > 1)
  466. {
  467. v1 = Edge0.Pop().Key;
  468. v0 = Edge0.Last().Key;
  469. v2 = Edge1[0].Key;
  470. }
  471. else if (Edge1.Num() > 1)
  472. {
  473. v1 = Edge1.Pop().Key;
  474. v0 = Edge1.Last().Key;
  475. v2 = Edge2[0].Key;
  476. }
  477. else if (Edge2.Num() > 1)
  478. {
  479. v1 = Edge2.Pop().Key;
  480. v0 = Edge2.Last().Key;
  481. v2 = Edge0[0].Key;
  482. }
  483. else
  484. {
  485. v0 = Edge0[0].Key;
  486. v1 = Edge1[0].Key;
  487. v2 = Edge2[0].Key;
  488. bDone = true;
  489. }
  490. triangle.Point0 = (AkVertIdx)v0;
  491. triangle.Point1 = (AkVertIdx)v1;
  492. triangle.Point2 = (AkVertIdx)v2;
  493. if (triangle.Point0 != triangle.Point1 &&
  494. triangle.Point1 != triangle.Point2 &&
  495. triangle.Point2 != triangle.Point0)
  496. GeometryData.Triangles.Add(triangle);
  497. } while (!bDone);
  498. }
  499. if (SurfaceAreas.Contains(PolygonsIndex))
  500. surfaceOverride.SetSurfaceArea(SurfaceAreas[PolygonsIndex]);
  501. }
  502. }
  503. struct VertexIndexByAngle
  504. {
  505. AkVertIdx Index;
  506. float Angle;
  507. };
  508. #if AK_USE_PHYSX
  509. void ConvertConvexMeshToGeometryData(AkSurfIdx surfIdx, const FKConvexElem& convexHull, FAkGeometryData* GeometryData)
  510. {
  511. physx::PxConvexMesh* convexMesh = convexHull.GetConvexMesh();
  512. AkVertIdx initialVertIdx = GeometryData->Vertices.Num();
  513. if (convexMesh != nullptr)
  514. {
  515. const PxVec3* vertices = convexMesh->getVertices();
  516. uint32 numVerts = (uint32)convexMesh->getNbVertices();
  517. for (uint32 vertIdx = 0; vertIdx < numVerts; ++vertIdx)
  518. {
  519. FVector akvtx;
  520. akvtx.X = vertices[vertIdx].x;
  521. akvtx.Y = vertices[vertIdx].y;
  522. akvtx.Z = vertices[vertIdx].z;
  523. GeometryData->Vertices.Add(akvtx);
  524. }
  525. const physx::PxU8* indexBuf = convexMesh->getIndexBuffer();
  526. uint32 numPolys = (uint32)convexMesh->getNbPolygons();
  527. for (uint32 polyIdx = 0; polyIdx < numPolys; polyIdx++)
  528. {
  529. PxHullPolygon polyData;
  530. convexMesh->getPolygonData(polyIdx, polyData);
  531. // order the vertices of the polygon
  532. uint32 numVertsInPoly = (uint32)polyData.mNbVerts;
  533. uint32 vertIdxOffset = (uint32)polyData.mIndexBase;
  534. TArray<VertexIndexByAngle> orderedIndexes;
  535. // first element is first vertex index
  536. AkVertIdx firstVertIdx = (AkVertIdx)indexBuf[vertIdxOffset];
  537. orderedIndexes.Add(VertexIndexByAngle{ firstVertIdx, 0 });
  538. // get the center of the polygon
  539. FVector center(0, 0, 0);
  540. for (uint32 polyVertIdx = 0; polyVertIdx < numVertsInPoly; ++polyVertIdx)
  541. {
  542. auto vertIdx = indexBuf[vertIdxOffset + polyVertIdx];
  543. center.X += vertices[vertIdx].x;
  544. center.Y += vertices[vertIdx].y;
  545. center.Z += vertices[vertIdx].z;
  546. }
  547. center.X /= numVertsInPoly;
  548. center.Y /= numVertsInPoly;
  549. center.Z /= numVertsInPoly;
  550. // get the vector from center to the first vertex
  551. FVector v0;
  552. v0.X = vertices[firstVertIdx].x - center.X;
  553. v0.Y = vertices[firstVertIdx].y - center.Y;
  554. v0.Z = vertices[firstVertIdx].z - center.Z;
  555. v0.Normalize();
  556. // get the normal of the plane
  557. FVector n;
  558. n.X = polyData.mPlane[0];
  559. n.Y = polyData.mPlane[1];
  560. n.Z = polyData.mPlane[2];
  561. n.Normalize();
  562. // find the angles between v0 and the other vertices of the polygon
  563. for (uint32 polyVertIdx = 1; polyVertIdx < numVertsInPoly; polyVertIdx++)
  564. {
  565. // get the vector from center to the current vertex
  566. AkVertIdx vertIdx = (AkVertIdx)indexBuf[vertIdxOffset + polyVertIdx];
  567. FVector v1;
  568. v1.X = vertices[vertIdx].x - center.X;
  569. v1.Y = vertices[vertIdx].y - center.Y;
  570. v1.Z = vertices[vertIdx].z - center.Z;
  571. v1.Normalize();
  572. // get the angle between v0 and v1
  573. // to do so, we need the dot product and the determinant respectively proportional to cos and sin of the angle.
  574. // atan2(sin, cos) will give us the angle
  575. float dot = FVector::DotProduct(v0, v1);
  576. // the determinant of two 3D vectors in the same plane can be found with the dot product of the normal with the result of
  577. // a cross product between the vectors
  578. float det = FVector::DotProduct(n, FVector::CrossProduct(v0, v1));
  579. float angle = (float)atan2(det, dot);
  580. orderedIndexes.Add(VertexIndexByAngle{ vertIdx, angle });
  581. }
  582. orderedIndexes.Sort();
  583. // fan triangulation
  584. for (uint32 vertIdx = 1; vertIdx < numVertsInPoly - 1; ++vertIdx)
  585. {
  586. FAkTriangle tri;
  587. tri.Point0 = (AkVertIdx)orderedIndexes[0].Index + initialVertIdx;
  588. tri.Point1 = (AkVertIdx)orderedIndexes[vertIdx].Index + initialVertIdx;
  589. tri.Point2 = (AkVertIdx)orderedIndexes[vertIdx + 1].Index + initialVertIdx;
  590. tri.Surface = surfIdx;
  591. GeometryData->Triangles.Add(tri);
  592. }
  593. }
  594. }
  595. else
  596. {
  597. // bounding box
  598. GeometryData->AddBox(surfIdx,
  599. convexHull.ElemBox.GetCenter(),
  600. convexHull.ElemBox.GetExtent(),
  601. convexHull.GetTransform().Rotator());
  602. }
  603. }
  604. #endif
  605. bool operator<(const VertexIndexByAngle& lhs, const VertexIndexByAngle& rhs)
  606. {
  607. return lhs.Angle < rhs.Angle;
  608. }
  609. void UAkGeometryComponent::ConvertCollisionMesh(UPrimitiveComponent* PrimitiveComponent, const UAkSettings* AkSettings)
  610. {
  611. UBodySetup* bodySetup = PrimitiveComponent->GetBodySetup();
  612. if (!(bodySetup && IsValid(bodySetup)))
  613. return;
  614. GeometryData.Clear();
  615. FAkAcousticSurface Surface;
  616. UPhysicalMaterial* physicalMaterial = bodySetup->GetPhysMaterial();
  617. UPhysicalMaterial* physMatTexture = nullptr;
  618. UPhysicalMaterial* physMatOcclusion = nullptr;
  619. FAkGeometrySurfaceOverride surfaceOverride = CollisionMeshSurfaceOverride;
  620. if (surfaceOverride.AcousticTexture)
  621. Surface.Texture = surfaceOverride.AcousticTexture->GetShortID();
  622. else
  623. physMatTexture = physicalMaterial;
  624. if (surfaceOverride.bEnableOcclusionOverride)
  625. Surface.Occlusion = surfaceOverride.OcclusionValue;
  626. else
  627. physMatOcclusion = physicalMaterial;
  628. GeometryData.ToOverrideAcousticTexture.Add(physMatTexture);
  629. GeometryData.ToOverrideOcclusion.Add(physMatOcclusion);
  630. GeometryData.Surfaces.Add(Surface);
  631. AkSurfIdx surfIdx = (AkSurfIdx)(GeometryData.Surfaces.Num() - 1);
  632. int32 numBoxes = bodySetup->AggGeom.BoxElems.Num();
  633. for (int32 i = 0; i < numBoxes; i++)
  634. {
  635. FKBoxElem box = bodySetup->AggGeom.BoxElems[i];
  636. FVector extent;
  637. extent.X = box.X / 2;
  638. extent.Y = box.Y / 2;
  639. extent.Z = box.Z / 2;
  640. if ((extent.Z == 0.0f && (extent.X == 0.0f || extent.Y == 0.0f))
  641. || (extent.Y == 0.0f && (extent.X == 0.0f || extent.Z == 0.0f))
  642. || (extent.X == 0.0f && (extent.Y == 0.0f || extent.Z == 0.0f)))
  643. {
  644. 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);
  645. continue;
  646. }
  647. GeometryData.AddBox(surfIdx, box.Center, extent, box.Rotation);
  648. }
  649. const int sides = 16;
  650. int32 numSpheres = bodySetup->AggGeom.SphereElems.Num();
  651. for (int32 i = 0; i < numSpheres; i++)
  652. {
  653. FKSphereElem sphere = bodySetup->AggGeom.SphereElems[i];
  654. GeometryData.AddSphere(surfIdx, sphere.Center, sphere.Radius, sides, sides / 2);
  655. }
  656. int32 numCapsules = bodySetup->AggGeom.SphylElems.Num();
  657. for (int32 i = 0; i < numCapsules; i++)
  658. {
  659. FKSphylElem capsule = bodySetup->AggGeom.SphylElems[i];
  660. FVector X = capsule.GetTransform().GetUnitAxis(EAxis::X);
  661. FVector Y = capsule.GetTransform().GetUnitAxis(EAxis::Y);
  662. FVector Z = capsule.GetTransform().GetUnitAxis(EAxis::Z);
  663. GeometryData.AddCapsule(surfIdx, capsule.Center, X, Y, Z, capsule.Radius, capsule.Length / 2, sides / 2);
  664. }
  665. int32 numConvexElems = bodySetup->AggGeom.ConvexElems.Num();
  666. for (int32 i = 0; i < numConvexElems; i++)
  667. {
  668. FKConvexElem& convexElem = bodySetup->AggGeom.ConvexElems[i];
  669. int32 numVertices = convexElem.VertexData.Num();
  670. if (numVertices == 0)
  671. continue;
  672. #if AK_USE_CHAOS
  673. // will compute IndexData if it is empty
  674. convexElem.ComputeChaosConvexIndices(false);
  675. #endif
  676. int32 numTriangles = convexElem.IndexData.Num() / 3;
  677. if (numTriangles == 0)
  678. {
  679. #if AK_USE_PHYSX
  680. ConvertConvexMeshToGeometryData(surfIdx, convexElem, &GeometryData);
  681. #endif
  682. continue;
  683. }
  684. int32 vertexOffset = GeometryData.Vertices.Num();
  685. for (int32 vertIdx = 0; vertIdx < numVertices; ++vertIdx)
  686. {
  687. GeometryData.Vertices.Add(convexElem.GetTransform().TransformPosition(convexElem.VertexData[vertIdx]));
  688. }
  689. for (int32 triIdx = 0; triIdx < numTriangles; ++triIdx)
  690. {
  691. FAkTriangle tri;
  692. tri.Point0 = vertexOffset + convexElem.IndexData[3 * triIdx];
  693. tri.Point1 = vertexOffset + convexElem.IndexData[3 * triIdx + 1];
  694. tri.Point2 = vertexOffset + convexElem.IndexData[3 * triIdx + 2];
  695. tri.Surface = surfIdx;
  696. GeometryData.Triangles.Add(tri);
  697. }
  698. }
  699. }
  700. void UAkGeometryComponent::SendGeometry()
  701. {
  702. FAkAudioDevice* AkAudioDevice = FAkAudioDevice::Get();
  703. if (AkAudioDevice && ShouldSendGeometry())
  704. {
  705. if (GeometryData.Triangles.Num() > 0 && GeometryData.Vertices.Num() > 0)
  706. {
  707. AkGeometryParams params;
  708. params.NumSurfaces = GeometryData.Surfaces.Num();
  709. params.NumTriangles = GeometryData.Triangles.Num();
  710. params.NumVertices = GeometryData.Vertices.Num();
  711. TArray<AkAcousticSurface> Surfaces;
  712. TArray< TSharedPtr< decltype(StringCast<ANSICHAR>(TEXT(""))) > > SurfaceNames;
  713. Surfaces.SetNum(params.NumSurfaces);
  714. SurfaceNames.SetNum(params.NumSurfaces);
  715. if (params.NumSurfaces)
  716. {
  717. for (int i = 0; i < params.NumSurfaces; ++i)
  718. {
  719. Surfaces[i].transmissionLoss = GeometryData.Surfaces[i].Occlusion;
  720. Surfaces[i].strName = nullptr;
  721. if (!GeometryData.Surfaces[i].Name.IsEmpty())
  722. {
  723. SurfaceNames[i] = MakeShareable(new decltype(StringCast<ANSICHAR>(TEXT("")))(*GeometryData.Surfaces[i].Name));
  724. Surfaces[i].strName = SurfaceNames[i].Get()->Get();
  725. }
  726. Surfaces[i].textureID = GeometryData.Surfaces[i].Texture;
  727. }
  728. }
  729. params.Surfaces = Surfaces.GetData();
  730. TUniquePtr<AkTriangle[]> Triangles = MakeUnique<AkTriangle[]>(params.NumTriangles);// temp triangle buffer
  731. for (int i = 0; i < params.NumTriangles; ++i)
  732. {
  733. Triangles[i].point0 = GeometryData.Triangles[i].Point0;
  734. Triangles[i].point1 = GeometryData.Triangles[i].Point1;
  735. Triangles[i].point2 = GeometryData.Triangles[i].Point2;
  736. Triangles[i].surface = GeometryData.Triangles[i].Surface;
  737. }
  738. params.Triangles = Triangles.Get();
  739. TUniquePtr<AkVertex[]> Vertices = MakeUnique<AkVertex[]>(params.NumVertices); // temp vertex buffer
  740. for (int i = 0; i < params.NumVertices; ++i)
  741. {
  742. Vertices[i].X = GeometryData.Vertices[i].X;
  743. Vertices[i].Y = GeometryData.Vertices[i].Y;
  744. Vertices[i].Z = GeometryData.Vertices[i].Z;
  745. }
  746. params.Vertices = Vertices.Get();
  747. params.EnableDiffraction = bEnableDiffraction;
  748. params.EnableDiffractionOnBoundaryEdges = bEnableDiffractionOnBoundaryEdges;
  749. params.EnableTriangles = !bWasAddedByRoom;
  750. SendGeometryToWwise(params);
  751. }
  752. else
  753. {
  754. UE_LOG(LogAkAudio, Warning, TEXT("%s: UAkGeometryComponent::SendGeometry() Geometry Data is empty. Nothing was sent to Spatial Audio."), *GetOwner()->GetName());
  755. }
  756. }
  757. }
  758. void UAkGeometryComponent::RemoveGeometry()
  759. {
  760. RemoveGeometryFromWwise();
  761. }
  762. void UAkGeometryComponent::UpdateGeometry()
  763. {
  764. if (Parent)
  765. {
  766. AkRoomID roomID = AkRoomID();
  767. if (AssociatedRoom)
  768. {
  769. UAkRoomComponent* room = Cast<UAkRoomComponent>(AssociatedRoom->GetComponentByClass(UAkRoomComponent::StaticClass()));
  770. if (room != nullptr)
  771. roomID = room->GetRoomID();
  772. }
  773. SendGeometryInstanceToWwise(Parent->GetComponentRotation(), Parent->GetComponentLocation(), Parent->GetComponentTransform().GetScale3D(), roomID);
  774. }
  775. }
  776. void UAkGeometryComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
  777. {
  778. Super::EndPlay(EndPlayReason);
  779. RemoveGeometry();
  780. }
  781. float UAkGeometryComponent::GetSurfaceAreaSquaredMeters(const int& surfaceIndex) const
  782. {
  783. if (SurfaceAreas.Contains(surfaceIndex))
  784. return SurfaceAreas[surfaceIndex] / AkComponentHelpers::UnrealUnitsPerSquaredMeter(Parent);
  785. return 0.0f;
  786. }
  787. #if WITH_EDITOR
  788. void UAkGeometryComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
  789. {
  790. Super::PostEditChangeProperty(PropertyChangedEvent);
  791. if (AkComponentHelpers::IsGameWorldBlueprintComponent(this) || IsBeingDestroyed())
  792. return;
  793. if (AssociatedRoom && !Cast<UAkRoomComponent>(AssociatedRoom->GetComponentByClass(UAkRoomComponent::StaticClass())))
  794. {
  795. UE_LOG(LogAkAudio, Warning, TEXT("%s: The Associated Room is not of type UAkRoomComponent."), *GetOwner()->GetName());
  796. }
  797. const FName memberPropertyName = (PropertyChangedEvent.MemberProperty != nullptr) ? PropertyChangedEvent.MemberProperty->GetFName() : NAME_None;
  798. const FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None;
  799. if (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, MeshType))
  800. {
  801. if (Parent != nullptr && MeshType == AkMeshType::StaticMesh)
  802. {
  803. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  804. if (MeshParent == nullptr)
  805. {
  806. FString actorString = FString("NONE");
  807. if (GetOwner() != nullptr)
  808. actorString = GetOwner()->GetName();
  809. FString parentName = Parent->GetName();
  810. FString parentClass = Parent->GetClass()->GetName();
  811. UE_LOG(LogAkAudio, Warning,
  812. TEXT("On actor %s, there is a UAkGeometryComponent (%s) attached to parent of type %s (%s).")
  813. , *actorString, *GetName(), *parentClass, *parentName);
  814. 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."));
  815. MeshType = AkMeshType::CollisionMesh;
  816. }
  817. else
  818. {
  819. UpdateStaticMeshOverride();
  820. }
  821. }
  822. UnregisterTextureParamChangeCallbacks();
  823. RegisterAllTextureParamCallbacks();
  824. }
  825. else if ( (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, StaticMeshSurfaceOverride) && MeshType == AkMeshType::StaticMesh)
  826. || (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, CollisionMeshSurfaceOverride) && MeshType == AkMeshType::CollisionMesh))
  827. {
  828. UnregisterTextureParamChangeCallbacks();
  829. RegisterAllTextureParamCallbacks();
  830. DampingEstimationNeedsUpdate = true;
  831. }
  832. if (MeshType == AkMeshType::StaticMesh &&
  833. memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, WeldingThreshold) &&
  834. PropertyChangedEvent.ChangeType == EPropertyChangeType::ValueSet)
  835. {
  836. ConvertMesh();
  837. SendGeometry();
  838. UpdateGeometry();
  839. }
  840. else if (memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, bEnableDiffraction) ||
  841. memberPropertyName == GET_MEMBER_NAME_CHECKED(UAkGeometryComponent, bEnableDiffractionOnBoundaryEdges))
  842. {
  843. SendGeometry();
  844. UpdateGeometry();
  845. }
  846. }
  847. void UAkGeometryComponent::PostEditUndo()
  848. {
  849. OnRefreshDetails.ExecuteIfBound();
  850. Super::PostEditUndo();
  851. }
  852. void UAkGeometryComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
  853. {
  854. Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
  855. if (bRequiresDeferredBeginPlay)
  856. {
  857. BeginPlayInternal();
  858. bRequiresDeferredBeginPlay = false;
  859. }
  860. if (MeshType == AkMeshType::StaticMesh)
  861. {
  862. if (IsValid(Parent) && !Parent->IsBeingDestroyed())
  863. {
  864. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  865. if (MeshParent != nullptr && StaticMeshSurfaceOverride.Num() != MeshParent->GetNumMaterials())
  866. UpdateMeshAndArchetype(MeshParent);
  867. }
  868. if (bMeshMaterialChanged)
  869. {
  870. OnRefreshDetails.ExecuteIfBound();
  871. bMeshMaterialChanged = false;
  872. }
  873. }
  874. }
  875. #endif
  876. void UAkGeometryComponent::UpdateStaticMeshOverride()
  877. {
  878. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  879. if (MeshParent != nullptr)
  880. {
  881. UpdateMeshAndArchetype(MeshParent);
  882. }
  883. }
  884. void UAkGeometryComponent::UpdateMeshAndArchetype(UStaticMeshComponent* StaticMeshComponent)
  885. {
  886. _UpdateStaticMeshOverride(StaticMeshComponent);
  887. // If we're in the Blueprint editor, update the Archetype object as well.
  888. // (The archetype object is the object that's edited when properties are changed in the Blueprint editor details inspector.
  889. // This is a separate object from the objects shown in the Blueprint editor viewport.)
  890. UWorld* World = GetWorld();
  891. if (World != nullptr && World->WorldType == EWorldType::EditorPreview
  892. && CreationMethod == EComponentCreationMethod::SimpleConstructionScript)
  893. {
  894. UAkGeometryComponent* Archetype = Cast<UAkGeometryComponent>(GetArchetype());
  895. if (Archetype != nullptr)
  896. Archetype->_UpdateStaticMeshOverride(StaticMeshComponent);
  897. }
  898. }
  899. void UAkGeometryComponent::_UpdateStaticMeshOverride(UStaticMeshComponent* StaticMeshComponent)
  900. {
  901. auto ToRemove = StaticMeshSurfaceOverride;
  902. int numMaterials = StaticMeshComponent->GetNumMaterials();
  903. for (int i = 0; i < numMaterials; i++)
  904. {
  905. UMaterialInterface* material = StaticMeshComponent->GetMaterial(i);
  906. if (StaticMeshSurfaceOverride.Contains(material))
  907. ToRemove.Remove(material);
  908. else
  909. {
  910. FAkGeometrySurfaceOverride surfaceOverride;
  911. if (PreviousStaticMeshSurfaceOverride.Contains(material))
  912. surfaceOverride = PreviousStaticMeshSurfaceOverride[material];
  913. StaticMeshSurfaceOverride.Add(material, surfaceOverride);
  914. }
  915. }
  916. #if WITH_EDITORONLY_DATA
  917. if (ToRemove.Num() > 0)
  918. bMeshMaterialChanged = true;
  919. #endif
  920. for (auto& elemToRemove : ToRemove)
  921. StaticMeshSurfaceOverride.Remove(elemToRemove.Key);
  922. ToRemove.Empty();
  923. PreviousStaticMeshSurfaceOverride.Empty();
  924. PreviousStaticMeshSurfaceOverride = StaticMeshSurfaceOverride;
  925. }
  926. void UAkGeometryComponent::Serialize(FArchive& Ar)
  927. {
  928. #if WITH_EDITORONLY_DATA
  929. UWorld* World = GetWorld();
  930. if (Ar.IsSaving() && World != nullptr && !World->IsGameWorld())
  931. ConvertMesh();
  932. #endif
  933. Super::Serialize(Ar);
  934. }
  935. void UAkGeometryComponent::GetTexturesAndSurfaceAreas(TArray<FAkAcousticTextureParams>& textures, TArray<float>& surfaceAreas) const
  936. {
  937. textures.Empty();
  938. surfaceAreas.Empty();
  939. const UAkSettings* AkSettings = GetDefault<UAkSettings>();
  940. if (AkSettings != nullptr)
  941. {
  942. if (MeshType == AkMeshType::CollisionMesh)
  943. {
  944. if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
  945. {
  946. const FAkAcousticTextureParams* params = AkSettings->GetTextureParams(CollisionMeshSurfaceOverride.AcousticTexture->GetShortID());
  947. if (params != nullptr)
  948. {
  949. textures.Add(*params);
  950. surfaceAreas.Add(1.0f); // When there is only 1 acoustic texture, surface area magnitude is not important.
  951. }
  952. }
  953. }
  954. else
  955. {
  956. if (StaticMeshSurfaceOverride.Num() > 0)
  957. {
  958. int surfIdx = 0;
  959. float surfaceArea = 0.0f;
  960. for (auto it = StaticMeshSurfaceOverride.CreateConstIterator(); it; ++it)
  961. {
  962. surfaceArea = GetSurfaceAreaSquaredMeters(surfIdx);
  963. FAkGeometrySurfaceOverride surface = it.Value();
  964. surfaceAreas.Add(surfaceArea);
  965. if (surface.AcousticTexture != nullptr)
  966. {
  967. const FAkAcousticTextureParams* params = AkSettings->GetTextureParams(surface.AcousticTexture->GetShortID());
  968. if (params != nullptr)
  969. {
  970. textures.Add(*params);
  971. }
  972. }
  973. else
  974. {
  975. textures.Add(FAkAcousticTextureParams());
  976. }
  977. ++surfIdx;
  978. }
  979. }
  980. }
  981. }
  982. }
  983. #if WITH_EDITOR
  984. void UAkGeometryComponent::HandleObjectsReplaced(const TMap<UObject*, UObject*>& ReplacementMap)
  985. {
  986. Super::HandleObjectsReplaced(ReplacementMap);
  987. if (ReplacementMap.Contains(Parent))
  988. {
  989. InitializeParent();
  990. if (Parent != nullptr)
  991. {
  992. if (MeshType == AkMeshType::StaticMesh)
  993. {
  994. UStaticMeshComponent* MeshParent = Cast<UStaticMeshComponent>(Parent);
  995. if (MeshParent != nullptr)
  996. CalculateSurfaceArea(MeshParent);
  997. }
  998. DampingEstimationNeedsUpdate = true;
  999. }
  1000. }
  1001. }
  1002. bool UAkGeometryComponent::ContainsTexture(const FGuid& textureID)
  1003. {
  1004. if (MeshType == AkMeshType::CollisionMesh)
  1005. {
  1006. if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
  1007. return CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureInfo.WwiseGuid == textureID;
  1008. }
  1009. else
  1010. {
  1011. for (auto it = StaticMeshSurfaceOverride.CreateIterator(); it; ++it)
  1012. {
  1013. if (it.Value().AcousticTexture != nullptr)
  1014. {
  1015. if (it.Value().AcousticTexture->AcousticTextureInfo.WwiseGuid == textureID)
  1016. return true;
  1017. }
  1018. }
  1019. }
  1020. return false;
  1021. }
  1022. void UAkGeometryComponent::RegisterAllTextureParamCallbacks()
  1023. {
  1024. if (MeshType == AkMeshType::CollisionMesh)
  1025. {
  1026. if (CollisionMeshSurfaceOverride.AcousticTexture != nullptr)
  1027. RegisterTextureParamChangeCallback(CollisionMeshSurfaceOverride.AcousticTexture->AcousticTextureInfo.WwiseGuid);
  1028. }
  1029. else
  1030. {
  1031. for (auto it = StaticMeshSurfaceOverride.CreateIterator(); it; ++it)
  1032. {
  1033. if (it.Value().AcousticTexture != nullptr)
  1034. {
  1035. RegisterTextureParamChangeCallback(it.Value().AcousticTexture->AcousticTextureInfo.WwiseGuid);
  1036. }
  1037. }
  1038. }
  1039. }
  1040. #endif