RuntimeMesh.cpp
Go to the documentation of this file.
1 // Copyright 2016-2018 Chris Conway (Koderz). All Rights Reserved.
2 
3 #include "RuntimeMesh.h"
5 #include "PhysicsEngine/BodySetup.h"
6 #include "PhysicsEngine/PhysicsSettings.h"
7 #include "IPhysXCookingModule.h"
8 #include "RuntimeMeshComponent.h"
9 #include "RuntimeMeshProxy.h"
10 #include "RuntimeMeshBuilder.h"
11 #include "RuntimeMeshLibrary.h"
12 
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);
16 
17 
18 
19 
21 // FRuntimeMeshCollisionCookTickObject
23 {
24  URuntimeMesh* Mesh = Owner.Get();
25  if (Mesh && Mesh->bCollisionIsDirty)
26  {
27  Mesh->UpdateCollision();
28  Mesh->bCollisionIsDirty = false;
29  }
30 }
31 
33 {
34  URuntimeMesh* Mesh = Owner.Get();
35  if (Mesh)
36  {
37  return Mesh->bCollisionIsDirty;
38  }
39  return false;
40 }
41 
43 {
44  return TStatId();
45 }
46 
47 
49 {
50  URuntimeMesh* Mesh = Owner.Get();
51  if (Mesh)
52  {
53  return Mesh->GetWorld();
54  }
55  return nullptr;
56 }
57 
59 // URuntimeMesh
60 
61 
62 URuntimeMesh::URuntimeMesh(const FObjectInitializer& ObjectInitializer)
63  : UObject(ObjectInitializer)
64  , Data(new FRuntimeMeshData())
65  , bCollisionIsDirty(false)
66  , bUseComplexAsSimpleCollision(true)
67  , bUseAsyncCooking(false)
68  , bShouldSerializeMeshData(true)
69  , CollisionMode(ERuntimeMeshCollisionCookingMode::CookingPerformance)
70  , BodySetup(nullptr)
71 {
72  Data->Setup(TWeakObjectPtr<URuntimeMesh>(this));
73 }
74 
76 {
77  check(IsInGameThread());
78 
79  if (bCollisionIsDirty)
80  {
81  UpdateCollision(true);
82  bCollisionIsDirty = false;
83  }
84 }
85 void URuntimeMesh::RegisterLinkedComponent(URuntimeMeshComponent* NewComponent)
86 {
87  LinkedComponents.AddUnique(NewComponent);
88 }
89 
90 void URuntimeMesh::UnRegisterLinkedComponent(URuntimeMeshComponent* ComponentToRemove)
91 {
92  check(LinkedComponents.Contains(ComponentToRemove));
93 
94  LinkedComponents.RemoveSingleSwap(ComponentToRemove, true);
95 }
96 
97 
98 
99 bool URuntimeMesh::GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData)
100 {
101  CollisionData->bFastCook = CollisionMode == ERuntimeMeshCollisionCookingMode::CookingPerformance;
102 
103  return GetRuntimeMeshData()->GetPhysicsTriMeshData(CollisionData, InUseAllTriData);
104 }
105 
106 bool URuntimeMesh::ContainsPhysicsTriMeshData(bool InUseAllTriData) const
107 {
108  return GetRuntimeMeshData()->ContainsPhysicsTriMeshData(InUseAllTriData);
109 }
110 
111 
112 
113 void URuntimeMesh::Serialize(FArchive& Ar)
114 {
115  Super::Serialize(Ar);
116 
117  // Serialize the entire data object.
118  Ar.UsingCustomVersion(FRuntimeMeshVersion::GUID);
119 
120  if (Ar.CustomVer(FRuntimeMeshVersion::GUID) < FRuntimeMeshVersion::SerializationUpgradeToConfigurable || bShouldSerializeMeshData)
121  {
122  Ar << Data.Get();
123  }
124 }
125 
127 {
128  Super::PostLoad();
129 
130  UpdateLocalBounds();
131  MarkCollisionDirty();
132 }
133 
134 UMaterialInterface* URuntimeMesh::GetMaterialFromCollisionFaceIndex(int32 FaceIndex, int32& SectionIndex) const
135 {
136  SectionIndex = GetRuntimeMeshData()->GetSectionFromCollisionFaceIndex(FaceIndex);
137 
138  if (Materials.IsValidIndex(SectionIndex))
139  {
140  return Materials[SectionIndex];
141  }
142  return nullptr;
143 }
144 
146 {
147  return GetRuntimeMeshData()->GetSectionFromCollisionFaceIndex(FaceIndex);
148 }
149 
150 void URuntimeMesh::GetSectionIdAndFaceIdFromCollisionFaceIndex(int32 FaceIndex, int32 & SectionIndex, int32 & SectionFaceIndex) const
151 {
152  SectionFaceIndex = FaceIndex;
153  SectionIndex = GetRuntimeMeshData()->GetSectionAndFaceFromCollisionFaceIndex(SectionFaceIndex);
154 }
155 
157 {
158  // Flag the collision as dirty
159  bCollisionIsDirty = true;
160 
161  if (!CookTickObject.IsValid())
162  {
163  CookTickObject = MakeUnique<FRuntimeMeshCollisionCookTickObject>(TWeakObjectPtr<URuntimeMesh>(this));
164  }
165 }
166 
167 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 21
168 UBodySetup* URuntimeMesh::CreateNewBodySetup()
169 {
170  UBodySetup* NewBodySetup = NewObject<UBodySetup>(this, NAME_None, (IsTemplate() ? RF_Public : RF_NoFlags));
171  NewBodySetup->BodySetupGuid = FGuid::NewGuid();
172 
173  return NewBodySetup;
174 }
175 #endif
176 
178 {
179  GetRuntimeMeshData()->CopyCollisionElementsToBodySetup(Setup);
180 }
181 
183 {
184  Setup->BodySetupGuid = FGuid::NewGuid();
185 
186  Setup->bGenerateMirroredCollision = false;
187  Setup->bDoubleSidedGeometry = true;
188  Setup->CollisionTraceFlag = bUseComplexAsSimpleCollision ? CTF_UseComplexAsSimple : CTF_UseDefault;
189 }
190 
191 void URuntimeMesh::UpdateCollision(bool bForceCookNow)
192 {
193 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION < 21
194  DoForAllLinkedComponents([bForceCookNow](URuntimeMeshComponent* Mesh)
195  {
196  Mesh->UpdateCollision(bForceCookNow);
197  });
198 
199 #else
200  SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CollisionUpdate);
201  check(IsInGameThread());
202 
203  UWorld* World = GetWorld();
204  const bool bShouldCookAsync = !bForceCookNow && World && World->IsGameWorld() && bUseAsyncCooking;
205 
206  if (bShouldCookAsync)
207  {
208  // Abort all previous ones still standing
209  for (UBodySetup* OldBody : AsyncBodySetupQueue)
210  {
211  OldBody->AbortPhysicsMeshAsyncCreation();
212  }
213 
214  UBodySetup* NewBodySetup = CreateNewBodySetup();
215  AsyncBodySetupQueue.Add(NewBodySetup);
216 
217  SetBasicBodySetupParameters(NewBodySetup);
218  CopyCollisionElementsToBodySetup(NewBodySetup);
219 
220  NewBodySetup->CreatePhysicsMeshesAsync(
221  FOnAsyncPhysicsCookFinished::CreateUObject(this, &URuntimeMesh::FinishPhysicsAsyncCook, NewBodySetup));
222  }
223  else
224  {
225  AsyncBodySetupQueue.Empty();
226  UBodySetup* NewBodySetup = CreateNewBodySetup();
227 
228  // Change body setup guid
229  NewBodySetup->BodySetupGuid = FGuid::NewGuid();
230 
231  SetBasicBodySetupParameters(NewBodySetup);
232  CopyCollisionElementsToBodySetup(NewBodySetup);
233 
234  // Update meshes
235  NewBodySetup->bHasCookedCollisionData = true;
236  NewBodySetup->InvalidatePhysicsData();
237  NewBodySetup->CreatePhysicsMeshes();
238 
239  BodySetup = NewBodySetup;
240  FinalizeNewCookedData();
241  }
242 #endif
243 }
244 
245 #if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 21
246 void URuntimeMesh::FinishPhysicsAsyncCook(bool bSuccess, UBodySetup* FinishedBodySetup)
247 {
248  SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_AsyncCollisionFinish);
249  check(IsInGameThread());
250 
251  int32 FoundIdx;
252  if (AsyncBodySetupQueue.Find(FinishedBodySetup, FoundIdx))
253  {
254  if (bSuccess)
255  {
256  // The new body was found in the array meaning it's newer so use it
257  BodySetup = FinishedBodySetup;
258 
259  // Shift down all remaining body setups, removing any old setups
260  for (int32 Index = FoundIdx + 1; Index < AsyncBodySetupQueue.Num(); Index++)
261  {
262  AsyncBodySetupQueue[Index - (FoundIdx + 1)] = AsyncBodySetupQueue[Index];
263  AsyncBodySetupQueue[Index] = nullptr;
264  }
265  AsyncBodySetupQueue.SetNum(AsyncBodySetupQueue.Num() - (FoundIdx + 1));
266 
267  FinalizeNewCookedData();
268 
269  }
270  else
271  {
272  AsyncBodySetupQueue.RemoveAt(FoundIdx);
273  }
274  }
275 }
276 
277 void URuntimeMesh::FinalizeNewCookedData()
278 {
279  SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CollisionFinalize);
280  check(IsInGameThread());
281 
282  // Alert all linked components so they can update their physics state.
283  DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
284  {
285  Mesh->NewCollisionMeshReceived();
286  });
287 
288  // Call user event to notify of collision updated.
289  if (CollisionUpdated.IsBound())
290  {
291  CollisionUpdated.Broadcast();
292  }
293 }
294 #endif
295 
297 {
298  DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
299  {
300  Mesh->NewBoundsReceived();
301  });
302 }
303 
305 {
306  DoForAllLinkedComponents([](URuntimeMeshComponent* Mesh)
307  {
308  Mesh->ForceProxyRecreate();
309  });
310 }
311 
312 void URuntimeMesh::SendSectionCreation(int32 SectionIndex)
313 {
314  DoForAllLinkedComponents([SectionIndex](URuntimeMeshComponent* Mesh)
315  {
316  Mesh->SendSectionCreation(SectionIndex);
317  });
318 }
319 
321 {
322  DoForAllLinkedComponents([SectionIndex](URuntimeMeshComponent* Mesh)
323  {
324  Mesh->SendSectionPropertiesUpdate(SectionIndex);
325  });
326 }
327 
328 
void CookCollisionNow()
Definition: RuntimeMesh.cpp:75
virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData *CollisionData, bool InUseAllTriData) override
Definition: RuntimeMesh.cpp:99
virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override
bool bCollisionIsDirty
Definition: RuntimeMesh.h:61
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
Definition: RuntimeMesh.cpp:48
virtual void Serialize(FArchive &Ar) override
virtual void Tick(float DeltaTime)
Definition: RuntimeMesh.cpp:22
void UpdateLocalBounds()
int32 GetSectionIdFromCollisionFaceIndex(int32 FaceIndex) const
static const textual_icon check
Definition: model-views.h:260
DECLARE_CYCLE_STAT(TEXT("RM - Collision Update"), STAT_RuntimeMesh_CollisionUpdate, STATGROUP_RuntimeMesh)
struct Index Index
Definition: sqlite3.c:11789
virtual TStatId GetStatId() const
Definition: RuntimeMesh.cpp:42
TWeakObjectPtr< URuntimeMesh > Owner
Definition: RuntimeMesh.h:28
void CopyCollisionElementsToBodySetup(UBodySetup *Setup)
void SetBasicBodySetupParameters(UBodySetup *Setup)
void UnRegisterLinkedComponent(URuntimeMeshComponent *ComponentToRemove)
Definition: RuntimeMesh.cpp:90
static const FGuid GUID
void ForceProxyRecreate()
void SendSectionPropertiesUpdate(int32 SectionIndex)
virtual bool IsTickable() const
Definition: RuntimeMesh.cpp:32
void RegisterLinkedComponent(URuntimeMeshComponent *NewComponent)
Definition: RuntimeMesh.cpp:85


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:41