UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
kDOP.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
8
9// Indicates how many "k / 2" there are in the k-DOP. 3 == AABB == 6 DOP. The code relies on this being 3.
10#define NUM_PLANES 3
11
12template <typename COLL_DATA_PROVIDER, typename KDOP_IDX_TYPE> struct TkDOPLineCollisionCheck;
13
15{
19 float Time;
22
24 : Normal (0,0,0,0)
25 , Time (1.0f)
27 {
28 }
29};
30
43
58
71
73template<typename KDOP_IDX_TYPE>
75{
80 enum { NodeHistoryLength = 1 };
82
84 {
85 for (int32 NodeIndex = 0; NodeIndex < NodeHistoryLength; NodeIndex++)
86 {
87 // Initialize the history to invalid index
88 Nodes[NodeIndex] = 0xFFFFFFFF;
89 }
90 }
91
93 {
94 TTraversalHistory NewHistory;
95 // Move all the indices toward the end of the array one element
96 CopyAssignItems(NewHistory.Nodes + 1, Nodes, NodeHistoryLength - 1);
97 // Insert the new node at the beginning of the array
98 NewHistory.Nodes[0] = NewNodeIndex;
99 return NewHistory;
100 }
101
103 {
104 // Accesses the oldest node that this traversal history is tracking
105 return Nodes[NodeHistoryLength - 1];
106 }
107};
108
122inline bool appLineCheckTriangle(const FVector4& Start, const FVector4& End, const FVector4& Dir, const FVector4& V0, const FVector4& V1, const FVector4& V2, const FVector4& Normal, float& IntersectionTime)
123{
124 const float StartDist = FPlane(Normal).PlaneDot(Start);
125 const float EndDist = FPlane(Normal).PlaneDot(End);
126
127 // Check if the line is completely on one side of the triangle, or if it's co-planar.
128#if 1
129 if ((StartDist == EndDist) || (StartDist < -0.001f && EndDist < -0.001f) || (StartDist > 0.001f && EndDist > 0.001f))
130#else
131 if ( (StartDist * EndDist) > -0.0001f )
132#endif
133 {
134 return false;
135 }
136
137 // Figure out when it will hit the triangle
138 float Time = -StartDist / (EndDist - StartDist);
139
140 // If this triangle is not closer than the previous hit, reject it
142 {
143 return false;
144 }
145
146 // Calculate the line's point of intersection with the node's plane
147 const FVector4& Intersection = Start + Dir * Time;
148 const FVector4* Verts[3] =
149 {
150 &V0, &V1, &V2
151 };
152
153 // Check if the point of intersection is inside the triangle's edges.
154 for( int32 SideIndex = 0; SideIndex < 3; SideIndex++ )
155 {
156 const FVector4& SideDirection = Normal ^ (*Verts[(SideIndex + 1) % 3] - *Verts[SideIndex]);
157 const float SideW = Dot3(SideDirection, *Verts[SideIndex]);
158 const float DotW = Dot3(SideDirection, Intersection);
159 if ((DotW - SideW) >= 0.001f)
160 {
161 return false;
162 }
163 }
165 return true;
166}
167
169static const VectorRegister GSmallNegativeNumber = MakeVectorRegister(-0.0001f, -0.0001f, -0.0001f, -0.0001f); //-V1043
170//extern const VectorRegister GSmallNegativeNumber;
171
173static const VectorRegister GSmallNumber = MakeVectorRegister( 0.0001f, 0.0001f, 0.0001f, 0.0001f ); //-V1043
174//extern const VectorRegister GSmallNumber;
175
176static const VectorRegister GZeroVectorRegister = MakeVectorRegister( 0.f, 0.f, 0.f, 0.f ); //-V1043
177
178static const VectorRegister VectorNegativeOne = MakeVectorRegister( -1.0f, -1.0f, -1.0f, -1.0f ); //-V1043
179
190static int32 appLineCheckTriangleSOA(const FVector3SOA& Start, const FVector3SOA& End, const FVector3SOA& Dir, const FTriangleSOA& Triangle4, float& InOutIntersectionTime)
191{
193
195 StartDist = VectorMultiplyAdd( Triangle4.Normals.X, Start.X, Triangle4.Normals.W );
198
200 EndDist = VectorMultiplyAdd( Triangle4.Normals.X, End.X, Triangle4.Normals.W );
201 EndDist = VectorMultiplyAdd( Triangle4.Normals.Y, End.Y, EndDist );
202 EndDist = VectorMultiplyAdd( Triangle4.Normals.Z, End.Z, EndDist );
203
204 // Are both end-points of the line on the same side of the triangle (or parallel to the triangle plane)?
205 TriangleMask = VectorMask_LE( VectorMultiply( StartDist, EndDist ), GSmallNegativeNumber );
206 if ( VectorMaskBits(TriangleMask) == 0 )
207 {
208 return -1;
209 }
210
211 // Figure out when it will hit the triangle
213
214 // If this triangle is not closer than the previous hit, reject it
218 if ( VectorMaskBits(TriangleMask) == 0 )
219 {
220 return -1;
221 }
222
223 // Calculate the line's point of intersection with the node's plane
227
228 // Check if the point of intersection is inside the triangle's edges.
229 for( int32 SideIndex = 0; SideIndex < 3; SideIndex++ )
230 {
231 const VectorRegister EdgeX = VectorSubtract( Triangle4.Positions[(SideIndex + 1) % 3].X, Triangle4.Positions[SideIndex].X );
232 const VectorRegister EdgeY = VectorSubtract( Triangle4.Positions[(SideIndex + 1) % 3].Y, Triangle4.Positions[SideIndex].Y );
233 const VectorRegister EdgeZ = VectorSubtract( Triangle4.Positions[(SideIndex + 1) % 3].Z, Triangle4.Positions[SideIndex].Z );
246 if ( VectorMaskBits(TriangleMask) == 0 )
247 {
248 return -1;
249 }
250 }
251
252 // Set all non-hitting times to 1.0
254
255 // Get the best intersection time out of the 4 possibilities.
259
260 // Get the triangle index that corresponds to the best time.
261 // NOTE: This will pick the first triangle, in case there are multiple hits at the same spot.
264
265 // Return results.
267 return SubIndex;
268}
269
270// This structure is used during the build process. It contains the triangle's
271// centroid for calculating which plane it should be split or not with
272template<typename KDOP_IDX_TYPE>
274{
287
290
291 inline FVector4 GetCentroid() const
292 {
293 return (V0 + V1 + V2) / 3.f;
294 }
296 {
297 FVector4 LocalNormal = ((V1 - V2) ^ (V0 - V2)).GetSafeNormal();
299 return LocalNormal;
300 }
301
313};
314
315// Forward declarations
316template <typename COLL_DATA_PROVIDER,typename KDOP_IDX_TYPE> struct TkDOPNode;
317template <typename COLL_DATA_PROVIDER,typename KDOP_IDX_TYPE> struct TkDOPTree;
318template <typename COLL_DATA_PROVIDER,typename KDOP_IDX_TYPE> struct TkDOPLineCollisionCheck;
319
324{
329
334
342 {
344 Min[1].Component(BoundingVolumeIndex) = Box.Min.Y;
345 Min[2].Component(BoundingVolumeIndex) = Box.Min.Z;
349 }
350
365};
366
367#if PLATFORM_64BITS
368 #define kDOPArray TArray
369#else
370 #define kDOPArray TChunkedArray
371#endif
372
377template <typename COLL_DATA_PROVIDER, typename KDOP_IDX_TYPE>
378struct TkDOPNode
379{
382
385
388
389 // Note this isn't smaller since 4 byte alignment will take over anyway
392
393 // Union of either child kDOP nodes or a list of enclosed triangles
394 union
395 {
396 // This structure contains the left and right child kDOP indices
397 // These index values correspond to the array in the FkDOPTree
398 struct
399 {
402 } n;
403 // This structure contains the list of enclosed triangles
404 // These index values correspond to the triangle information in the
405 // FkDOPTree using the start and count as the means of delineating
406 // which triangles are involved
407 struct
408 {
411 } t;
412 };
413
417 inline TkDOPNode()
418 {
419 n.LeftNode = ((KDOP_IDX_TYPE) -1);
420 n.RightNode = ((KDOP_IDX_TYPE) -1);
421 }
422
436 kDOPArray<FTriangleSOA>& SOATriangles,
437 kDOPArray<NodeType>& Nodes)
438 {
439 // Figure out if we are a leaf node or not
440 if (NumTris > 4)
441 {
442 // Still too many triangles, so continue subdividing the triangle list
443 bIsLeaf = 0;
444 Occupancy = 0;
445 int32 BestPlane = -1;
446 float BestMean = 0.f;
447 float BestVariance = 0.f;
448
449 // Determine how to split using the splatter algorithm
450 {
451 double Mean[NUM_PLANES] = { 0 };
452 double Variance[NUM_PLANES] = { 0 };
453
454 // Compute the mean for the triangle list
455 for (int32 nTriangle = Start; nTriangle < Start + NumTris; nTriangle++)
456 {
457 // Project the centroid of the triangle against the plane
458 // normals and accumulate to find the total projected
459 // weighting
460 FVector4 Centroid = BuildTriangles[nTriangle].GetCentroid();
461
462 for (int32 nPlane = 0; nPlane < NUM_PLANES; nPlane++)
463 {
464 Mean[nPlane] += Centroid[nPlane];
465 }
466 }
467
468 // Divide by the number of triangles to get the average
469 for (int32 nPlane = 0; nPlane < NUM_PLANES; nPlane++)
470 {
471 Mean[nPlane] /= NumTris;
472 }
473
474 // Compute variance of the triangle list
475 for (int32 nTriangle = Start; nTriangle < Start + NumTris; nTriangle++)
476 {
477 // Project the centroid again
478 FVector4 Centroid = BuildTriangles[nTriangle].GetCentroid();
479
480 // Now calculate the variance and accumulate it
481 for (int32 nPlane = 0; nPlane < NUM_PLANES; nPlane++)
482 {
483 Variance[nPlane] += (Centroid[nPlane] - Mean[nPlane]) * (Centroid[nPlane] - Mean[nPlane]);
484 }
485 }
486
487 // Determine which plane is the best to split on
488 for (int32 nPlane = 0; nPlane < NUM_PLANES; nPlane++)
489 {
490 // Get the average variance
493 {
496 BestMean = (float)Mean[nPlane];
497 }
498 }
499 }
500
501 // Now that we have the plane to split on, work through the triangle
502 // list placing them on the left or right of the splitting plane
503 int32 Left = Start - 1;
504 int32 Right = Start + NumTris;
505 // Keep working through until the left index passes the right; we test that condition after each interior loop
506 for (;;)
507 {
508 // Loop invariants: (1) Left < Right,
509 // (2) All triangles <= Left belong on the left, all triangles >= Right belong on the right
510 // (3) Left+1 is an untested triangle, Right-1 is an untested triangle
511 float Dot;
512 // Increment Left until it points to triangle that belongs on the right, or Right==Left
513 for (++Left; Left < Right; ++Left)
514 {
515 Dot = BuildTriangles[Left].GetCentroid()[BestPlane];
516 if (Dot < BestMean)
517 {
518 break;
519 }
520 }
521 if (Left == Right)
522 {
523 break;
524 }
525 // Decrement Right until it points to triangle that belongs on the left, or Right==Left
526 for (--Right; Left < Right; --Right)
527 {
528 Dot = BuildTriangles[Right].GetCentroid()[BestPlane];
529 if (Dot >= BestMean)
530 {
531 break;
532 }
533 }
534 if (Left == Right)
535 {
536 break;
537 }
538 // Left points to a triangle that belongs on the Right; Right points to a triangle that belongs on the Left. Swap them.
540 }
541 // After loop array is partitioned and Left is the first index that belongs on the right side of the plane.
542 // Check for wacky degenerate case where more than GKDOPMaxTrisPerLeaf
543 // fall all in the same kDOP
544 if (Left == Start + NumTris || Right == Start)
545 {
546 Left = Start + (NumTris / 2);
547 }
548 // Add the two child nodes
549 n.LeftNode = Nodes.AddZeroed(2);
550 n.RightNode = n.LeftNode + 1;
551 // Have the left node recursively subdivide it's list and set bounding volume.
552 FBox LeftBoundingVolume = Nodes[n.LeftNode].SplitTriangleList(Start,Left - Start,BuildTriangles,SOATriangles,Nodes);
554 // Set unused index 2,3 to child nodes of left node.
555 BoundingVolumes.SetBox(2,Nodes[n.LeftNode].BoundingVolumes.GetBox(0));
556 BoundingVolumes.SetBox(3,Nodes[n.LeftNode].BoundingVolumes.GetBox(1));
557
558 // And now have the right node recursively subdivide it's list and set bounding volume.
559 FBox RightBoundingVolume = Nodes[n.RightNode].SplitTriangleList(Left,Start + NumTris - Left,BuildTriangles,SOATriangles,Nodes);
561
562 // Non-leaf node bounds are the "sum" of the left and right nodes' volumes.
564 }
565 else
566 {
567 // Build SOA triangles
568
569 // "NULL triangle", used when a leaf can't fill all 4 triangles in a FTriangleSOA.
570 // No line should ever hit these triangles, set the values so that it can never happen.
572
573 t.StartIndex = SOATriangles.Num();
574 t.NumTriangles = Align<int32>(NumTris, 4) / 4;
575 SOATriangles.AddZeroed( t.NumTriangles );
576
577 int32 BuildTriIndex = Start;
578 for ( uint32 SOAIndex=0; SOAIndex < t.NumTriangles; ++SOAIndex )
579 {
581 FTriangleSOA& SOA = SOATriangles[t.StartIndex + SOAIndex];
582 int32 SubIndex = 0;
583 for ( ; SubIndex < 4 && BuildTriIndex < (Start+NumTris); ++SubIndex, ++BuildTriIndex )
584 {
586 SOA.Payload[SubIndex] = Tris[SubIndex]->MaterialIndex;
587 }
588 for ( ; SubIndex < 4; ++SubIndex )
589 {
590 SOA.Payload[SubIndex] = 0xffffffff;
591 }
592
593 SOA.Positions[0].X = VectorSet( Tris[0]->V0.X, Tris[1]->V0.X, Tris[2]->V0.X, Tris[3]->V0.X );
594 SOA.Positions[0].Y = VectorSet( Tris[0]->V0.Y, Tris[1]->V0.Y, Tris[2]->V0.Y, Tris[3]->V0.Y );
595 SOA.Positions[0].Z = VectorSet( Tris[0]->V0.Z, Tris[1]->V0.Z, Tris[2]->V0.Z, Tris[3]->V0.Z );
596 SOA.Positions[1].X = VectorSet( Tris[0]->V1.X, Tris[1]->V1.X, Tris[2]->V1.X, Tris[3]->V1.X );
597 SOA.Positions[1].Y = VectorSet( Tris[0]->V1.Y, Tris[1]->V1.Y, Tris[2]->V1.Y, Tris[3]->V1.Y );
598 SOA.Positions[1].Z = VectorSet( Tris[0]->V1.Z, Tris[1]->V1.Z, Tris[2]->V1.Z, Tris[3]->V1.Z );
599 SOA.Positions[2].X = VectorSet( Tris[0]->V2.X, Tris[1]->V2.X, Tris[2]->V2.X, Tris[3]->V2.X );
600 SOA.Positions[2].Y = VectorSet( Tris[0]->V2.Y, Tris[1]->V2.Y, Tris[2]->V2.Y, Tris[3]->V2.Y );
601 SOA.Positions[2].Z = VectorSet( Tris[0]->V2.Z, Tris[1]->V2.Z, Tris[2]->V2.Z, Tris[3]->V2.Z );
602
603 const FVector4& Tris0LocalNormal = Tris[0]->GetLocalNormal();
604 const FVector4& Tris1LocalNormal = Tris[1]->GetLocalNormal();
605 const FVector4& Tris2LocalNormal = Tris[2]->GetLocalNormal();
606 const FVector4& Tris3LocalNormal = Tris[3]->GetLocalNormal();
607
612 }
613
614 // No need to subdivide further so make this a leaf node
615 bIsLeaf = 1;
617
618 // Generate bounding volume for leaf which is passed up the call chain.
620 for (int32 TriangleIndex=Start; TriangleIndex<Start + NumTris; TriangleIndex++)
621 {
622 BoundingVolume += FVector(BuildTriangles[TriangleIndex].V0);
623 BoundingVolume += FVector(BuildTriangles[TriangleIndex].V1);
624 BoundingVolume += FVector(BuildTriangles[TriangleIndex].V2);
625 }
630
631 return BoundingVolume;
632 }
633 }
634
656 {
657#define PLAIN_C 0
658#if PLAIN_C
659 for( int32 BoxIndex=0; BoxIndex<4; BoxIndex++ )
660 {
661 // 0: Create constants
664
665 // 1: Calculate slabs.
666 FVector4 Slab1 = (BoxMin - Check.LocalStart) * Check.LocalOneOverDir;
667 FVector4 Slab2 = (BoxMax - Check.LocalStart) * Check.LocalOneOverDir;
668
669 // 2: Figure out per component min/ max
670 FVector4 SlabMin = FVector4( FMath::Min(Slab1.X, Slab2.X), FMath::Min(Slab1.Y, Slab2.Y), FMath::Min(Slab1.Z, Slab2.Z), FMath::Min(Slab1.W, Slab2.W) );
671 FVector4 SlabMax = FVector4( FMath::Max(Slab1.X, Slab2.X), FMath::Max(Slab1.Y, Slab2.Y), FMath::Max(Slab1.Z, Slab2.Z), FMath::Max(Slab1.W, Slab2.W) );
672
673 // 3: Figure out global min/ max
674 float MinTime = Max3( SlabMin.X, SlabMin.Y, SlabMin.Z );
675 float MaxTime = Min3( SlabMax.X, SlabMax.Y, SlabMax.Z );
676
677 // 4: Calculate hit time and determine whether there was a hit.
678 HitTime[BoxIndex] = MinTime;
679 NodeHit[BoxIndex] = (MaxTime >= 0 && MaxTime >= MinTime && MinTime < Check.Result->Time) ? 0xFFFFFFFF : 0;
680 }
681#else
682 // 0: load everything into registers
683 const VectorRegister OriginX = VectorSetFloat1( Check.LocalStart.X );
684 const VectorRegister OriginY = VectorSetFloat1( Check.LocalStart.Y );
685 const VectorRegister OriginZ = VectorSetFloat1( Check.LocalStart.Z );
686 const VectorRegister InvDirX = VectorSetFloat1( Check.LocalOneOverDir.X );
687 const VectorRegister InvDirY = VectorSetFloat1( Check.LocalOneOverDir.Y );
688 const VectorRegister InvDirZ = VectorSetFloat1( Check.LocalOneOverDir.Z );
689 const VectorRegister CurrentHitTime = VectorSetFloat1( Check.Result->Time );
690 // Boxes are FVector2D so we need to unshuffle the data.
697
698 // 1: Calculate slabs.
705
706 // 2: Figure out per component min/ max
713
714 // 3: Figure out global min/ max
716 const VectorRegister MinTime = VectorMax( SlabMinXY, SlabMinZ );
718 const VectorRegister MaxTime = VectorMin( SlabMaxXY, SlabMaxZ );
719
720 // 4: Calculate hit time and determine whether there was a hit.
721 VectorStoreAligned( MinTime, &HitTime );
722 const VectorRegister OutNodeHit = VectorBitwiseAnd( VectorCompareGE( MaxTime, VectorZero() ), VectorCompareGE( MaxTime, MinTime ) );
725#endif
726 }
727
736 {
737 bool bHit = 0;
738 // If this is a node, check the two child nodes and pick the closest one
739 // to recursively check against and only check the second one if there is
740 // not a hit or the hit returned is further out than the second node
741 if (bIsLeaf == 0)
742 {
743 // Check both left and right node at the same time.
745 MS_ALIGN(16) int32 NodeHit[4] GCC_ALIGN(16);
747
748 // Left node was hit.
749 if( NodeHit[0] )
750 {
751 // Left and Right node are hit.
752 if( NodeHit[1] )
753 {
754 // Left node is closer than right node.
755 if( NodeHitTime.X < NodeHitTime.Y )
756 {
757 bHit = Check.Nodes[n.LeftNode].LineCheckPreCalculated(Check,NodeHitTime,History.AddNode(n.LeftNode),NodeHit);
758 // Only check right node if it could possibly be a closer hit
759 if( NodeHitTime.Y < Check.Result->Time
760 // No need to check if we have a hit and don't care about closest
761 && (!bHit || Check.bFindClosestIntersection))
762 {
763 bHit |= Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
764 }
765 }
766 // Right node is closer than left node.
767 else
768 {
769 bHit = Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
770 // Only check left node if it could possibly be a closer hit
771 if( NodeHitTime.X < Check.Result->Time
772 // No need to check if we have a hit and don't care about closest
773 && (!bHit || Check.bFindClosestIntersection))
774 {
775 bHit |= Check.Nodes[n.LeftNode].LineCheckPreCalculated(Check,NodeHitTime,History.AddNode(n.LeftNode),NodeHit);
776 }
777 }
778 }
779 // Only left node was hit.
780 else
781 {
782 bHit = Check.Nodes[n.LeftNode].LineCheckPreCalculated(Check,NodeHitTime,History.AddNode(n.LeftNode),NodeHit);
783 }
784 }
785 // Left node was not hit.
786 else
787 {
788 // Only right node was hit.
789 if( NodeHit[1] )
790 {
791 bHit = Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
792 }
793 // No node was hit.
794 else
795 {
796 return false;
797 }
798 }
799 }
800 else
801 {
802 // This is a leaf, check the triangles for a hit
803 bHit = LineCheckTriangles(Check,History);
804 }
805 return bHit;
806 }
807
816 {
817 bool bHit = 0;
818 // If this is a node, check the two child nodes and pick the closest one
819 // to recursively check against and only check the second one if there is
820 // not a hit or the hit returned is further out than the second node
821 if (bIsLeaf == 0)
822 {
823 // Left node was hit.
824 if( NodeHit[2] )
825 {
826 // Left and Right node are hit.
827 if( NodeHit[3] )
828 {
829 // Left node is closer than right node.
830 if( NodeHitTime.Z < NodeHitTime.W )
831 {
832 bHit = Check.Nodes[n.LeftNode].LineCheck(Check,History.AddNode(n.LeftNode));
833 // Only check right node if it could possibly be a closer hit
834 if( NodeHitTime.W < Check.Result->Time
835 // No need to check if we have a hit and don't care about closest
836 && (!bHit || Check.bFindClosestIntersection))
837 {
838 bHit |= Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
839 }
840 }
841 // Right node is closer than left node.
842 else
843 {
844 bHit = Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
845 // Only check left node if it could possibly be a closer hit
846 if( NodeHitTime.Z < Check.Result->Time
847 // No need to check if we have a hit and don't care about closest
848 && (!bHit || Check.bFindClosestIntersection))
849 {
850 bHit |= Check.Nodes[n.LeftNode].LineCheck(Check,History.AddNode(n.LeftNode));
851 }
852 }
853 }
854 // Only left node was hit.
855 else
856 {
857 bHit = Check.Nodes[n.LeftNode].LineCheck(Check,History.AddNode(n.LeftNode));
858 }
859 }
860 // Left node was not hit.
861 else
862 {
863 // Only right node was hit.
864 if( NodeHit[3] )
865 {
866 bHit = Check.Nodes[n.RightNode].LineCheck(Check,History.AddNode(n.RightNode));
867 }
868 // No node was hit.
869 else
870 {
871 return false;
872 }
873 }
874 }
875 else
876 {
877 // This is a leaf, check the triangles for a hit
878 bHit = LineCheckTriangles(Check,History);
879 }
880 return bHit;
881 }
882
890 {
891 // Assume a miss
892 bool bHit = false;
893 for ( KDOP_IDX_TYPE SOAIndex = t.StartIndex; SOAIndex < (t.StartIndex + t.NumTriangles); SOAIndex++ )
894 {
895 const FTriangleSOA& TriangleSOA = Check.SOATriangles[SOAIndex];
896 int32 SubIndex = appLineCheckTriangleSOA( Check.StartSOA, Check.EndSOA, Check.DirSOA, TriangleSOA, Check.Result->Time );
897 if ( SubIndex >= 0 )
898 {
899 bHit = true;
900 Check.LocalHitNormal.X = VectorGetComponentDynamic(TriangleSOA.Normals.X, SubIndex);
901 Check.LocalHitNormal.Y = VectorGetComponentDynamic(TriangleSOA.Normals.Y, SubIndex);
902 Check.LocalHitNormal.Z = VectorGetComponentDynamic(TriangleSOA.Normals.Z, SubIndex);
903 Check.Result->Item = TriangleSOA.Payload[SubIndex];
904 Check.HitNodeIndex = History.GetOldestNode();
905
906 // Early out if we don't care about the closest intersection.
907 if( !Check.bFindClosestIntersection )
908 {
909 break;
910 }
911 }
912 }
913 return bHit;
914 }
915};
916
921template<typename COLL_DATA_PROVIDER, typename KDOP_IDX_TYPE>
922struct TkDOPTree
923{
926
929
932
935
943 {
944 float kDOPBuildTime = 0;
945 {
946 // Empty the current set of nodes and preallocate the memory so it doesn't
947 // reallocate memory while we are recursively walking the tree
948 // With near-perfect packing, we could easily size these to be
949 // Nodes = (n / 2) + 1 and SOATriangles = (n / 4) + 1
950 Nodes.Empty(BuildTriangles.Num());
951 SOATriangles.Empty(BuildTriangles.Num());
952
953 // Add the root node
954 Nodes.AddZeroed();
955
956 // Now tell that node to recursively subdivide the entire set of triangles
957 Nodes[0].SplitTriangleList(0,BuildTriangles.Num(),BuildTriangles,SOATriangles,Nodes);
958
959 // Don't waste memory.
960 Nodes.Shrink();
961 SOATriangles.Shrink();
962 }
963 }
964
972 {
973 // Recursively check for a hit
975 bool bHit = Nodes[0].LineCheck(Check, History.AddNode(0));
976 return bHit;
977 }
978};
979
1024
1030template <typename COLL_DATA_PROVIDER, typename KDOP_IDX_TYPE> struct TkDOPLineCollisionCheck :
1031 public TkDOPCollisionCheck<COLL_DATA_PROVIDER,KDOP_IDX_TYPE>
1032{
1037 // Constant input vars
1040
1045 // Locally calculated vectors
1050 // Normal in local space which gets transformed to world at the very end
1052
1055
1062
1079 :
1081 Result(InResult),
1082 Start(InStart),
1083 End(InEnd),
1085 HitNodeIndex(0xFFFFFFFF)
1086 {
1088 // Move start and end to local space
1089 LocalStart = WorldToLocal.TransformPosition(Start);
1090 LocalEnd = WorldToLocal.TransformPosition(End);
1091 // Calculate the vector's direction in local space
1093 // Build the one over dir
1097
1098 // Construct the SOA data
1108 }
1109
1115 {
1116 // Transform the hit back into world space using the transpose adjoint
1117 FVector4 Normal = TkDOPCollisionCheck<COLL_DATA_PROVIDER,KDOP_IDX_TYPE>::CollDataProvider.GetLocalToWorldTransposeAdjoint().TransformVector(LocalHitNormal).GetSafeNormal();
1118 // Flip the normal if the triangle is inverted
1120 {
1121 Normal = -Normal;
1122 }
1123 return Normal;
1124 }
1125};
@ Normal
Definition AndroidInputInterface.h:116
#define GCC_ALIGN(n)
Definition AndroidPlatform.h:163
@ INDEX_NONE
Definition CoreMiscDefines.h:150
@ ForceInit
Definition CoreMiscDefines.h:155
#define MS_ALIGN(n)
Definition Platform.h:916
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FORCEINLINE void CopyAssignItems(ElementType *Dest, const ElementType *Source, SizeType Count)
Definition MemoryOps.h:137
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
bool appLineCheckTriangle(const FVector4 &Start, const FVector4 &End, const FVector4 &Dir, const FVector4 &V0, const FVector4 &V1, const FVector4 &V2, const FVector4 &Normal, float &IntersectionTime)
Definition kDOP.h:122
#define NUM_PLANES
Definition kDOP.h:11
#define FVector
Definition IOSSystemIncludes.h:8
UE::Math::TVector4< double > FVector4
Definition MathFwd.h:49
UE::Math::TPlane< double > FPlane
Definition MathFwd.h:52
USkinnedMeshComponent float
Definition SkinnedMeshComponent.h:60
FORCEINLINE VectorRegister4Float VectorSubtract(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:731
FORCEINLINE VectorRegister4Float VectorMin(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1686
FORCEINLINE VectorRegister4Float MakeVectorRegister(uint32 X, uint32 Y, uint32 Z, uint32 W)
Definition UnrealMathFPU.h:195
FORCEINLINE VectorRegister4Float VectorSetFloat1(float F)
Definition UnrealMathFPU.h:518
FORCEINLINE VectorRegister4Float VectorDivide(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:834
FORCEINLINE VectorRegister4Float VectorMultiply(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:758
FORCEINLINE VectorRegister4Float VectorMax(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1713
FORCEINLINE VectorRegister4Float VectorBitwiseAnd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1165
FORCEINLINE VectorRegister4Float VectorLoadFloat1(const float *Ptr)
Definition UnrealMathFPU.h:468
VectorRegister4Float VectorLoadAligned(const float *Ptr)
Definition UnrealMathFPU.h:451
FORCEINLINE VectorRegister4Float VectorMultiplyAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2, const VectorRegister4Float &Vec3)
Definition UnrealMathFPU.h:786
FORCEINLINE VectorRegister4Float VectorSelect(const VectorRegister4Float &Mask, const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1105
FORCEINLINE VectorRegister4Float VectorCompareGT(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:974
FORCEINLINE VectorRegister4Float VectorCompareGE(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1000
FORCEINLINE float VectorGetComponentDynamic(const VectorRegister4Float &Vec, uint32 ComponentIndex)
Definition UnrealMathFPU.h:369
FORCEINLINE int32 VectorMaskBits(const VectorRegister4Float &Vec1)
Definition UnrealMathFPU.h:1075
FORCEINLINE VectorRegister4Float VectorNegateMultiplyAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2, const VectorRegister4Float &Vec3)
Definition UnrealMathFPU.h:815
void VectorStoreAligned(const VectorRegister4Float &Vec, float *Ptr)
Definition UnrealMathFPU.h:534
#define VectorSwizzle(Vec, X, Y, Z, W)
Definition UnrealMathFPU.h:639
FORCEINLINE void VectorStoreFloat1(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:610
#define VectorReplicate(Vec, ElementIndex)
Definition UnrealMathFPU.h:627
#define UE_MAX_FLT
Definition UnrealMathUtility.h:147
FORCEINLINE VectorRegister4Float VectorZero(void)
Definition UnrealMathVectorCommon.h.inl:16
FORCEINLINE VectorRegister4Float VectorSet(float X, float Y, float Z, float W)
Definition UnrealMathVectorCommon.h.inl:867
FORCEINLINE VectorRegister4Float VectorOne(void)
Definition UnrealMathVectorCommon.h.inl:21
FORCEINLINE uint32 appCountTrailingZeros(uint32 Value)
Definition UnrealMathVectorCommon.h.inl:932
UE_FORCEINLINE_HINT T Dot3(const UE::Math::TVector4< T > &V1, const UE::Math::TVector4< T > &V2)
Definition Vector4.h:1018
#define VectorMask_LT(Vec1, Vec2)
Definition VectorRegister.h:123
#define VectorMask_LE(Vec1, Vec2)
Definition VectorRegister.h:124
#define VectorMask_GE(Vec1, Vec2)
Definition VectorRegister.h:126
#define VectorMask_EQ(Vec1, Vec2)
Definition VectorRegister.h:127
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Array.h:670
@ Start
Definition GeoEnum.h:100
Definition kDOP.h:324
FBox GetBox(int32 BoundingVolumeIndex)
Definition kDOP.h:358
MS_ALIGN(16) FVector4 Min[3] GCC_ALIGN(16)
FVector4 Max[3]
Definition kDOP.h:333
void SetBox(int32 BoundingVolumeIndex, const FBox &Box)
Definition kDOP.h:341
Definition kDOP.h:63
FVector3SOA Positions[3]
Definition kDOP.h:65
uint32 Payload[4]
Definition kDOP.h:69
FVector4SOA Normals
Definition kDOP.h:67
Definition kDOP.h:35
VectorRegister Z
Definition kDOP.h:41
VectorRegister Y
Definition kDOP.h:39
VectorRegister X
Definition kDOP.h:37
Definition kDOP.h:48
VectorRegister W
Definition kDOP.h:56
VectorRegister Y
Definition kDOP.h:52
VectorRegister X
Definition kDOP.h:50
VectorRegister Z
Definition kDOP.h:54
Definition kDOP.h:274
FVector4 GetCentroid() const
Definition kDOP.h:291
FkDOPBuildCollisionTriangle(KDOP_IDX_TYPE InMaterialIndex, const FVector4 &vert0, const FVector4 &vert1, const FVector4 &vert2)
Definition kDOP.h:306
FVector4 GetLocalNormal() const
Definition kDOP.h:295
KDOP_IDX_TYPE MaterialIndex
Definition kDOP.h:289
FVector4 V2
Definition kDOP.h:286
FVector4 V1
Definition kDOP.h:282
FVector4 V0
Definition kDOP.h:278
Definition kDOP.h:15
FkHitResult()
Definition kDOP.h:23
int32 Item
Definition kDOP.h:21
float Time
Definition kDOP.h:19
FVector4 Normal
Definition kDOP.h:17
Definition kDOP.h:75
KDOP_IDX_TYPE Nodes[NodeHistoryLength]
Definition kDOP.h:81
KDOP_IDX_TYPE GetOldestNode() const
Definition kDOP.h:102
@ NodeHistoryLength
Definition kDOP.h:80
TTraversalHistory()
Definition kDOP.h:83
TTraversalHistory AddNode(KDOP_IDX_TYPE NewNodeIndex) const
Definition kDOP.h:92
Definition kDOP.h:986
const kDOPArray< FTriangleSOA > & SOATriangles
Definition kDOP.h:1011
const DataProviderType & CollDataProvider
Definition kDOP.h:999
TkDOPCollisionCheck(const DataProviderType &InCollDataProvider)
Definition kDOP.h:1016
TkDOPTree< DataProviderType, KDOP_IDX_TYPE > TreeType
Definition kDOP.h:994
TkDOPNode< DataProviderType, KDOP_IDX_TYPE > NodeType
Definition kDOP.h:991
const kDOPArray< NodeType > & Nodes
Definition kDOP.h:1007
const TreeType & kDOPTree
Definition kDOP.h:1003
COLL_DATA_PROVIDER DataProviderType
Definition kDOP.h:988
Definition kDOP.h:1036
FVector4 LocalStart
Definition kDOP.h:1046
KDOP_IDX_TYPE HitNodeIndex
Definition kDOP.h:1054
FkHitResult * Result
Definition kDOP.h:1036
FVector4 LocalHitNormal
Definition kDOP.h:1051
FVector4 LocalDir
Definition kDOP.h:1048
const FVector4 & Start
Definition kDOP.h:1038
const FVector4 & End
Definition kDOP.h:1039
FVector3SOA StartSOA
Definition kDOP.h:1057
TkDOPLineCollisionCheck(const FVector4 &InStart, const FVector4 &InEnd, bool bInbFindClosestIntersection, const COLL_DATA_PROVIDER &InCollDataProvider, FkHitResult *InResult)
Definition kDOP.h:1075
FVector3SOA EndSOA
Definition kDOP.h:1059
FVector3SOA DirSOA
Definition kDOP.h:1061
FVector4 LocalOneOverDir
Definition kDOP.h:1049
FVector4 LocalEnd
Definition kDOP.h:1047
FVector4 GetHitNormal(void)
Definition kDOP.h:1114
const bool bFindClosestIntersection
Definition kDOP.h:1044
Definition kDOP.h:381
FFourBox BoundingVolumes
Definition kDOP.h:387
bool LineCheck(TkDOPLineCollisionCheck< COLL_DATA_PROVIDER, KDOP_IDX_TYPE > &Check, TTraversalHistory< KDOP_IDX_TYPE > History) const
Definition kDOP.h:735
uint8 Occupancy
Definition kDOP.h:391
void LineCheckBounds(TkDOPLineCollisionCheck< COLL_DATA_PROVIDER, KDOP_IDX_TYPE > &Check, FVector4 &HitTime, int32 NodeHit[4]) const
Definition kDOP.h:655
FBox SplitTriangleList(int32 Start, int32 NumTris, TArray< FkDOPBuildCollisionTriangle< KDOP_IDX_TYPE > > &BuildTriangles, kDOPArray< FTriangleSOA > &SOATriangles, kDOPArray< NodeType > &Nodes)
Definition kDOP.h:434
TkDOPNode()
Definition kDOP.h:417
COLL_DATA_PROVIDER DataProviderType
Definition kDOP.h:381
bool LineCheckPreCalculated(TkDOPLineCollisionCheck< COLL_DATA_PROVIDER, KDOP_IDX_TYPE > &Check, const FVector4 &NodeHitTime, TTraversalHistory< KDOP_IDX_TYPE > History, int32 *NodeHit) const
Definition kDOP.h:815
bool LineCheckTriangles(TkDOPLineCollisionCheck< COLL_DATA_PROVIDER, KDOP_IDX_TYPE > &Check, const TTraversalHistory< KDOP_IDX_TYPE > &History) const
Definition kDOP.h:889
KDOP_IDX_TYPE StartIndex
Definition kDOP.h:410
KDOP_IDX_TYPE NumTriangles
Definition kDOP.h:409
KDOP_IDX_TYPE RightNode
Definition kDOP.h:401
bool bIsLeaf
Definition kDOP.h:390
TkDOPNode< DataProviderType, KDOP_IDX_TYPE > NodeType
Definition kDOP.h:384
struct TkDOPNode::@1148::@1152 t
struct TkDOPNode::@1148::@1151 n
KDOP_IDX_TYPE LeftNode
Definition kDOP.h:400
Definition kDOP.h:927
kDOPArray< NodeType > Nodes
Definition kDOP.h:931
TkDOPNode< DataProviderType, KDOP_IDX_TYPE > NodeType
Definition kDOP.h:928
bool LineCheck(TkDOPLineCollisionCheck< COLL_DATA_PROVIDER, KDOP_IDX_TYPE > &Check) const
Definition kDOP.h:971
COLL_DATA_PROVIDER DataProviderType
Definition kDOP.h:925
void Build(TArray< FkDOPBuildCollisionTriangle< KDOP_IDX_TYPE > > &BuildTriangles)
Definition kDOP.h:942
kDOPArray< FTriangleSOA > SOATriangles
Definition kDOP.h:934
TVector< T > Min
Definition Box.h:39
TVector4< T > TransformPosition(const TVector< T > &V) const
Definition Matrix.inl:184
UE_FORCEINLINE_HINT T PlaneDot(const TVector< T > &P) const
Definition Plane.h:474
T Y
Definition Vector4.h:46
T & Component(int32 Index)
Definition Vector4.h:782
T Z
Definition Vector4.h:49
T X
Definition Vector4.h:43
Definition UnrealMathFPU.h:42