5 #include "PhysicsEngine/BodySetup.h" 6 #include "PhysicsEngine/PhysicsSettings.h" 7 #include "IPhysXCookingModule.h" 13 DECLARE_CYCLE_STAT(TEXT(
"RM - Collision Update"), STAT_RuntimeMesh_CollisionUpdate, STATGROUP_RuntimeMesh);
14 DECLARE_CYCLE_STAT(TEXT(
"RM - Async Collision Cook Finish"), STAT_RuntimeMesh_AsyncCollisionFinish, STATGROUP_RuntimeMesh);
15 DECLARE_CYCLE_STAT(TEXT(
"RM - Collision Finalize"), STAT_RuntimeMesh_CollisionFinalize, STATGROUP_RuntimeMesh);
53 return Mesh->GetWorld();
62 URuntimeMesh::URuntimeMesh(
const FObjectInitializer& ObjectInitializer)
63 : UObject(ObjectInitializer)
65 , bCollisionIsDirty(
false)
66 , bUseComplexAsSimpleCollision(
true)
67 , bUseAsyncCooking(
false)
68 , bShouldSerializeMeshData(
true)
69 , CollisionMode(ERuntimeMeshCollisionCookingMode::CookingPerformance)
72 Data->Setup(TWeakObjectPtr<URuntimeMesh>(
this));
77 check(IsInGameThread());
79 if (bCollisionIsDirty)
81 UpdateCollision(
true);
82 bCollisionIsDirty =
false;
87 LinkedComponents.AddUnique(NewComponent);
92 check(LinkedComponents.Contains(ComponentToRemove));
94 LinkedComponents.RemoveSingleSwap(ComponentToRemove,
true);
101 CollisionData->bFastCook = CollisionMode == ERuntimeMeshCollisionCookingMode::CookingPerformance;
103 return GetRuntimeMeshData()->GetPhysicsTriMeshData(CollisionData, InUseAllTriData);
108 return GetRuntimeMeshData()->ContainsPhysicsTriMeshData(InUseAllTriData);
115 Super::Serialize(Ar);
131 MarkCollisionDirty();
136 SectionIndex = GetRuntimeMeshData()->GetSectionFromCollisionFaceIndex(FaceIndex);
138 if (Materials.IsValidIndex(SectionIndex))
140 return Materials[SectionIndex];
147 return GetRuntimeMeshData()->GetSectionFromCollisionFaceIndex(FaceIndex);
152 SectionFaceIndex = FaceIndex;
153 SectionIndex = GetRuntimeMeshData()->GetSectionAndFaceFromCollisionFaceIndex(SectionFaceIndex);
159 bCollisionIsDirty =
true;
161 if (!CookTickObject.IsValid())
163 CookTickObject = MakeUnique<FRuntimeMeshCollisionCookTickObject>(TWeakObjectPtr<URuntimeMesh>(
this));
167 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 21 168 UBodySetup* URuntimeMesh::CreateNewBodySetup()
170 UBodySetup* NewBodySetup = NewObject<UBodySetup>(
this, NAME_None, (IsTemplate() ? RF_Public : RF_NoFlags));
171 NewBodySetup->BodySetupGuid = FGuid::NewGuid();
179 GetRuntimeMeshData()->CopyCollisionElementsToBodySetup(Setup);
184 Setup->BodySetupGuid = FGuid::NewGuid();
186 Setup->bGenerateMirroredCollision =
false;
187 Setup->bDoubleSidedGeometry =
true;
188 Setup->CollisionTraceFlag = bUseComplexAsSimpleCollision ? CTF_UseComplexAsSimple : CTF_UseDefault;
193 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION < 21 194 DoForAllLinkedComponents([bForceCookNow](URuntimeMeshComponent* Mesh)
196 Mesh->UpdateCollision(bForceCookNow);
200 SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CollisionUpdate);
201 check(IsInGameThread());
203 UWorld* World = GetWorld();
204 const bool bShouldCookAsync = !bForceCookNow && World && World->IsGameWorld() && bUseAsyncCooking;
206 if (bShouldCookAsync)
209 for (UBodySetup* OldBody : AsyncBodySetupQueue)
211 OldBody->AbortPhysicsMeshAsyncCreation();
214 UBodySetup* NewBodySetup = CreateNewBodySetup();
215 AsyncBodySetupQueue.Add(NewBodySetup);
217 SetBasicBodySetupParameters(NewBodySetup);
218 CopyCollisionElementsToBodySetup(NewBodySetup);
220 NewBodySetup->CreatePhysicsMeshesAsync(
221 FOnAsyncPhysicsCookFinished::CreateUObject(
this, &URuntimeMesh::FinishPhysicsAsyncCook, NewBodySetup));
225 AsyncBodySetupQueue.Empty();
226 UBodySetup* NewBodySetup = CreateNewBodySetup();
229 NewBodySetup->BodySetupGuid = FGuid::NewGuid();
231 SetBasicBodySetupParameters(NewBodySetup);
232 CopyCollisionElementsToBodySetup(NewBodySetup);
235 NewBodySetup->bHasCookedCollisionData =
true;
236 NewBodySetup->InvalidatePhysicsData();
237 NewBodySetup->CreatePhysicsMeshes();
239 BodySetup = NewBodySetup;
240 FinalizeNewCookedData();
245 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 21 246 void URuntimeMesh::FinishPhysicsAsyncCook(
bool bSuccess, UBodySetup* FinishedBodySetup)
248 SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_AsyncCollisionFinish);
249 check(IsInGameThread());
252 if (AsyncBodySetupQueue.Find(FinishedBodySetup, FoundIdx))
257 BodySetup = FinishedBodySetup;
260 for (int32
Index = FoundIdx + 1;
Index < AsyncBodySetupQueue.Num();
Index++)
262 AsyncBodySetupQueue[
Index - (FoundIdx + 1)] = AsyncBodySetupQueue[
Index];
263 AsyncBodySetupQueue[
Index] =
nullptr;
265 AsyncBodySetupQueue.SetNum(AsyncBodySetupQueue.Num() - (FoundIdx + 1));
267 FinalizeNewCookedData();
272 AsyncBodySetupQueue.RemoveAt(FoundIdx);
277 void URuntimeMesh::FinalizeNewCookedData()
279 SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CollisionFinalize);
280 check(IsInGameThread());
283 DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
285 Mesh->NewCollisionMeshReceived();
289 if (CollisionUpdated.IsBound())
291 CollisionUpdated.Broadcast();
298 DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
300 Mesh->NewBoundsReceived();
306 DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
308 Mesh->ForceProxyRecreate();
314 DoForAllLinkedComponents([SectionIndex](URuntimeMeshComponent* Mesh)
316 Mesh->SendSectionCreation(SectionIndex);
322 DoForAllLinkedComponents([SectionIndex](URuntimeMeshComponent* Mesh)
324 Mesh->SendSectionPropertiesUpdate(SectionIndex);
virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData *CollisionData, bool InUseAllTriData) override
virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override
void MarkCollisionDirty()
UMaterialInterface * GetMaterialFromCollisionFaceIndex(int32 FaceIndex, int32 &SectionIndex) const
void UpdateCollision(bool bForceCookNow=false)
void SendSectionCreation(int32 SectionIndex)
void GetSectionIdAndFaceIdFromCollisionFaceIndex(int32 FaceIndex, int32 &SectionIndex, int32 &SectionFaceIndex) const
virtual UWorld * GetTickableGameObjectWorld() const
virtual void Serialize(FArchive &Ar) override
virtual void Tick(float DeltaTime)
int32 GetSectionIdFromCollisionFaceIndex(int32 FaceIndex) const
static const textual_icon check
DECLARE_CYCLE_STAT(TEXT("RM - Collision Update"), STAT_RuntimeMesh_CollisionUpdate, STATGROUP_RuntimeMesh)
virtual TStatId GetStatId() const
TWeakObjectPtr< URuntimeMesh > Owner
void CopyCollisionElementsToBodySetup(UBodySetup *Setup)
void SetBasicBodySetupParameters(UBodySetup *Setup)
void UnRegisterLinkedComponent(URuntimeMeshComponent *ComponentToRemove)
void ForceProxyRecreate()
void SendSectionPropertiesUpdate(int32 SectionIndex)
virtual bool IsTickable() const
void RegisterLinkedComponent(URuntimeMeshComponent *NewComponent)