UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DynamicMeshOctree3.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
7#include "MeshQueries.h"
9#include "Async/ParallelFor.h"
10
11
12namespace UE
13{
14namespace Geometry
15{
16
17
28{
29 // potential optimizations:
30 // - keep track of how many triangles are descendents of each cell? root cells?
31
32
33
34public:
37
40
45 {
46 this->Mesh = MeshIn;
47
48 for (int tid : Mesh->TriangleIndicesItr())
49 {
51 }
52 }
53
61
65 void InsertTriangle(int32 TriangleID)
66 {
67 if (Mesh->IsTriangle(TriangleID))
68 {
69 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
70 ModifiedBounds.Contain(Bounds);
71 InsertObject(TriangleID, Bounds);
72 }
73 }
74
78 void InsertTriangles(const TArray<int>& Triangles)
79 {
80 int N = Triangles.Num();
81 for (int i = 0; i < N; ++i)
82 {
83 if (Mesh->IsTriangle(Triangles[i]))
84 {
85 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(Triangles[i]);
86 ModifiedBounds.Contain(Bounds);
87 InsertObject(Triangles[i], Bounds);
88 }
89 }
90 }
91
95 void InsertTriangles(const TSet<int>& Triangles)
96 {
97 for (int TriangleID : Triangles)
98 {
99 if (Mesh->IsTriangle(TriangleID))
100 {
101 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
102 ModifiedBounds.Contain(Bounds);
103 InsertObject(TriangleID, Bounds);
104 }
105 }
106 }
107
108
112 bool RemoveTriangle(int32 TriangleID)
113 {
114 if (Mesh->IsTriangle(TriangleID))
115 {
116 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
117 ModifiedBounds.Contain(Bounds);
118 }
119 return RemoveObject(TriangleID); // will ignore if we do not contain this triangle
120 }
121
122
126 template<typename EnumerableType>
127 void RemoveTriangles(const EnumerableType& Triangles, bool bMarkModifiedBounds = true)
128 {
129 for (int TriangleID : Triangles)
130 {
131 if (RemoveObject(TriangleID) && bMarkModifiedBounds && Mesh->IsTriangle(TriangleID))
132 {
133 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
134 ModifiedBounds.Contain(Bounds);
135 }
136 }
137 }
138
139
143 template<typename EnumerableType>
144 void ReinsertTriangles(const EnumerableType& Triangles)
145 {
146 for (int TriangleID : Triangles)
147 {
148 if (Mesh->IsTriangle(TriangleID))
149 {
150 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
151 ModifiedBounds.Contain(Bounds);
152 ReinsertObject(TriangleID, Bounds);
153 }
154 else
155 {
156 RemoveObject(TriangleID); // can only remove, will ignore if we do not contain this triangle
157 }
158 }
159 }
160
161
167 {
168 int32 NumTriangles = Triangles.Num();
169 TempBuffer.SetNum(NumTriangles, EAllowShrinking::No);
170 TempFlagBuffer.SetNum(NumTriangles, EAllowShrinking::No);
171
172 // can check which triangles need reinsertion in parallel. This will also return which
173 // CellID the triangle is in, which saves time in the Reinsert function
174 ParallelFor(NumTriangles, [&](int k)
175 {
176 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(Triangles[k]);
177 TempFlagBuffer[k] = CheckIfObjectNeedsReinsert(Triangles[k], Bounds, TempBuffer[k]);
178 });
179
180 // now reinsert all necessary triangles
181 for (int32 k = 0; k < NumTriangles; ++k)
182 {
183 if (TempFlagBuffer[k])
184 {
185 ReinsertObject(Triangles[k], Mesh->GetTriBounds(Triangles[k]), TempBuffer[k]);
186 }
187 }
188 }
189
190
191
195 void NotifyPendingModification(int TriangleID)
196 {
197 if (Mesh->IsTriangle(TriangleID))
198 {
199 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
200 ModifiedBounds.Contain(Bounds);
201 }
202 }
203
207 template<typename EnumerableType>
209 {
210 for (int TriangleID : Triangles)
211 {
212 if (Mesh->IsTriangle(TriangleID))
213 {
214 FAxisAlignedBox3d Bounds = Mesh->GetTriBounds(TriangleID);
215 ModifiedBounds.Contain(Bounds);
216 }
217 }
218 }
219
220
226 {
228 [&](int tid) {return Mesh->GetTriBounds(tid); },
229 [&](int tid, const FRay3d& Ray) {
231 return (Intr.IntersectionType == EIntersectionType::Point) ?
232 Intr.RayParameter : TNumericLimits<double>::Max();
233
234 }, MaxDistance);
235 }
236
237
245 {
247 [&](int tid) {return Mesh->GetTriBounds(tid); },
248 [&](int tid, const FRay3d& Ray) {
249 if (IncludeTriangleIDFunc(tid) == false)
250 {
252 }
254 return (Intr.IntersectionType == EIntersectionType::Point) ?
255 Intr.RayParameter : TNumericLimits<double>::Max();
256 },
258 }
259
260
266 bool bVerbose = false,
267 bool bFailOnMissingObjects = false) const
268 {
270 [&](int tid) {return Mesh->IsTriangle(tid); },
271 [&](int tid) {return Mesh->GetTriBounds(tid); },
273 }
274
275
276
277
278
279
280 //
281 // Support for building "cuts" of the octree, which are sets
282 // of internal nodes which can be used to decompose the tree
283 // (eg into spatially-coherent chunks of triangles, for example)
284 //
285
288 {
290 };
291
294 {
295 public:
297
298 protected:
299 TSet<uint32> CutCellIDs; // just a set version of CutCells for internal use - maybe use set there instead, and add compare ops to FCellReference?
301
303 };
304
305
310 {
313
314 for (const FSparseOctreeCell& Cell : Cells)
315 {
316 if (Cell.Level == CutSet.FixedCutLevel)
317 {
319 CellRef.CellID = Cell.CellID;
320 CutSet.CutCells.Add(CellRef);
321
322 CutSet.CutCellIDs.Add(Cell.CellID);
323 }
324 }
325
326 return CutSet;
327 }
328
329
337 {
338 for (const FSparseOctreeCell& Cell : Cells)
339 {
340 if (Cell.Level == CutSet.FixedCutLevel)
341 {
342 if (CutSet.CutCellIDs.Contains(Cell.CellID) == false)
343 {
345 CellRef.CellID = Cell.CellID;
346 CutSet.CutCells.Add(CellRef);
347 CutSet.CutCellIDs.Add(Cell.CellID);
349 }
350 }
351 }
352 }
353
358 {
360 const FSparseOctreeCell& Cell = Cells[CellRef.CellID];
361 return GetCellBox(Cell, MaxExpandFactor).Intersects(Bounds);
362 }
363
368 const FCellReference& CellRef,
369 TFunctionRef<void(int)> TriangleFunc) const
370 {
372
374 Queue.Add(&Cells[CellRef.CellID]);
375 while (Queue.Num() > 0)
376 {
378
379 // process elements
380 for (int ObjectID : CellObjectLists.Values(CurCell->CellID))
381 {
382 TriangleFunc(ObjectID);
383 }
384
385 for (int k = 0; k < 8; ++k)
386 {
387 if (CurCell->HasChild(k))
388 {
389 const FSparseOctreeCell* ChildCell = &Cells[CurCell->GetChildCellID(k)];
390 Queue.Add(ChildCell);
391 }
392 }
393 }
394 }
395
396
402 TFunctionRef<void(int)> TriangleFunc) const
403 {
405
406 // start at root cells
408 {
410 Queue.Add(&Cells[*RootCellID]);
411 });
412
413 while (Queue.Num() > 0)
414 {
416 if (CutSet.CutCellIDs.Contains(CurCell->CellID))
417 {
418 continue;
419 }
420
421 // process elements
422 for (int TriangleID : CellObjectLists.Values(CurCell->CellID))
423 {
424 TriangleFunc(TriangleID);
425 }
426
427 for (int k = 0; k < 8; ++k)
428 {
429 if (CurCell->HasChild(k))
430 {
431 const FSparseOctreeCell* ChildCell = &Cells[CurCell->GetChildCellID(k)];
432 Queue.Add(ChildCell);
433 }
434 }
435 }
436 }
437
442 TFunctionRef<void(int)> TriangleFunc) const
443 {
444 for (int tid : SpillObjectSet)
445 {
447 }
448 }
449
450
451};
452
453
454
455} // end namespace UE::Geometry
456} // end namespace UE
#define check(expr)
Definition AssertionMacros.h:314
void ParallelFor(int32 Num, TFunctionRef< void(int32)> Body, bool bForceSingleThread, bool bPumpRenderingThread=false)
Definition ParallelFor.h:481
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void SetNum(SizeType NewNum, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2308
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
ElementType Pop(EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:1196
Definition AssetRegistryState.h:50
Definition DynamicMesh3.h:108
triangle_iterator TriangleIndicesItr() const
Definition DynamicMesh3.h:568
bool IsTriangle(int TriangleID) const
Definition DynamicMesh3.h:457
GEOMETRYCORE_API FAxisAlignedBox3d GetTriBounds(int TriangleID) const
Definition DynamicMesh3_Queries.cpp:836
Definition DynamicMeshOctree3.h:294
TArray< FCellReference > CutCells
Definition DynamicMeshOctree3.h:296
int FixedCutLevel
Definition DynamicMeshOctree3.h:300
TSet< uint32 > CutCellIDs
Definition DynamicMeshOctree3.h:299
Definition DynamicMeshOctree3.h:28
void InsertTriangles(const TArray< int > &Triangles)
Definition DynamicMeshOctree3.h:78
void InsertTriangle(int32 TriangleID)
Definition DynamicMeshOctree3.h:65
void NotifyPendingModification(const EnumerableType &Triangles)
Definition DynamicMeshOctree3.h:208
void CollectRootTriangles(const FTreeCutSet &CutSet, TFunctionRef< void(int)> TriangleFunc) const
Definition DynamicMeshOctree3.h:401
void CollectTriangles(const FCellReference &CellRef, TFunctionRef< void(int)> TriangleFunc) const
Definition DynamicMeshOctree3.h:367
void InsertTriangles(const TSet< int > &Triangles)
Definition DynamicMeshOctree3.h:95
void CollectSpillTriangles(TFunctionRef< void(int)> TriangleFunc) const
Definition DynamicMeshOctree3.h:441
int32 FindNearestHitObject(const FRay3d &Ray, TFunctionRef< bool(int)> IncludeTriangleIDFunc, double MaxDistance=TNumericLimits< double >::Max()) const
Definition DynamicMeshOctree3.h:242
void ReinsertTrianglesParallel(const TArray< int32 > &Triangles, TArray< uint32 > &TempBuffer, TArray< bool > &TempFlagBuffer)
Definition DynamicMeshOctree3.h:166
void Initialize(const FDynamicMesh3 *MeshIn)
Definition DynamicMeshOctree3.h:44
bool RemoveTriangle(int32 TriangleID)
Definition DynamicMeshOctree3.h:112
void ReinsertTriangles(const EnumerableType &Triangles)
Definition DynamicMeshOctree3.h:144
void ResetModifiedBounds()
Definition DynamicMeshOctree3.h:57
FTreeCutSet BuildLevelCutSet(uint32 CutLevel=5) const
Definition DynamicMeshOctree3.h:309
void CheckValidity(EValidityCheckFailMode FailMode=EValidityCheckFailMode::Check, bool bVerbose=false, bool bFailOnMissingObjects=false) const
Definition DynamicMeshOctree3.h:264
int32 FindNearestHitObject(const FRay3d &Ray, double MaxDistance=TNumericLimits< double >::Max()) const
Definition DynamicMeshOctree3.h:224
void UpdateLevelCutSet(FTreeCutSet &CutSet, TArray< FCellReference > &NewCutCellsOut) const
Definition DynamicMeshOctree3.h:336
const FDynamicMesh3 * Mesh
Definition DynamicMeshOctree3.h:36
bool TestCellIntersection(const FCellReference &CellRef, const FAxisAlignedBox3d &Bounds) const
Definition DynamicMeshOctree3.h:357
FAxisAlignedBox3d ModifiedBounds
Definition DynamicMeshOctree3.h:39
void NotifyPendingModification(int TriangleID)
Definition DynamicMeshOctree3.h:195
void RemoveTriangles(const EnumerableType &Triangles, bool bMarkModifiedBounds=true)
Definition DynamicMeshOctree3.h:127
bool IsValid(int Index) const
Definition RefCountVector.h:66
ValueEnumerable Values(int32 ListIndex) const
Definition SmallListSet.h:571
Definition SparseDynamicOctree3.h:165
GEOMETRYCORE_API void CheckValidity(TFunctionRef< bool(int)> IsValidObjectIDFunc, TFunctionRef< FAxisAlignedBox3d(int)> GetObjectBoundsFunc, EValidityCheckFailMode FailMode=EValidityCheckFailMode::Check, bool bVerbose=false, bool bFailOnMissingObjects=false) const
Definition SparseDynamicOctree3.cpp:806
GEOMETRYCORE_API bool CheckIfObjectNeedsReinsert(int32 ObjectID, const FAxisAlignedBox3d &NewBounds, uint32 &CellIDOut) const
Definition SparseDynamicOctree3.cpp:165
TSet< int32 > SpillObjectSet
Definition SparseDynamicOctree3.h:407
FSmallListSet CellObjectLists
Definition SparseDynamicOctree3.h:406
double MaxExpandFactor
Definition SparseDynamicOctree3.h:192
TDynamicVector< FSparseOctreeCell > Cells
Definition SparseDynamicOctree3.h:403
GEOMETRYCORE_API void InsertObject(int32 ObjectID, const FAxisAlignedBox3d &Bounds)
Definition SparseDynamicOctree3.cpp:24
GEOMETRYCORE_API int32 FindNearestHitObject(const FRay3d &Ray, TFunctionRef< FAxisAlignedBox3d(int)> GetObjectBoundsFunc, TFunctionRef< double(int, const FRay3d &)> HitObjectDistFunc, double MaxDistance=TNumericLimits< double >::Max()) const
Definition SparseDynamicOctree3.cpp:244
FAxisAlignedBox3d GetCellBox(const FSparseOctreeCell &Cell, double ExpandFactor=0) const
Definition SparseDynamicOctree3.h:439
TSparseGrid3< uint32 > RootCells
Definition SparseDynamicOctree3.h:414
FRefCountVector CellRefCounts
Definition SparseDynamicOctree3.h:400
GEOMETRYCORE_API bool ReinsertObject(int32 ObjectID, const FAxisAlignedBox3d &NewBounds, uint32 CellIDHint=InvalidCellID)
Definition SparseDynamicOctree3.cpp:185
Definition IntrRay3Triangle3.h:67
static FIntrRay3Triangle3d TriangleIntersection(const TriangleMeshType &Mesh, int TriIdx, const FRay3d &Ray)
Definition MeshQueries.h:41
void AllocatedIteration(Func ElementFunc) const
Definition SparseGrid3.h:176
EValidityCheckFailMode
Definition GeometryTypes.h:72
Definition AdvancedWidgetsModule.cpp:13
Definition NumericLimits.h:41
Definition DynamicMeshOctree3.h:288
uint32 CellID
Definition DynamicMeshOctree3.h:289
Definition SparseDynamicOctree3.h:83
static TAxisAlignedBox3< double > Empty()
Definition BoxTypes.h:382
void Contain(const TVector< RealType > &V)
Definition BoxTypes.h:438
bool Intersects(TAxisAlignedBox3 Box) const
Definition BoxTypes.h:526