UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SQVisitor.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
14
15#include <type_traits>
16
17#if WITH_CHAOS_VISUAL_DEBUGGER
19#endif
20
22
23#if CHAOS_DEBUG_DRAW
26#endif
27
28template <typename TLocationHit>
29void FillHitHelper(TLocationHit& Hit, const Chaos::FReal Distance, const FVector& WorldPosition, const FVector& WorldNormal, int32 FaceIdx, bool bComputeMTD)
30{
31 if constexpr (std::is_base_of_v<ChaosInterface::FLocationHit, TLocationHit> || std::is_base_of_v<ChaosInterface::FPTLocationHit, TLocationHit>)
32 {
33 Hit.Distance = Distance;
34 Hit.WorldPosition = WorldPosition;
35 Hit.WorldNormal = WorldNormal;
37 Hit.FaceIndex = FaceIdx;
38 }
39}
40
41template <typename QueryGeometryType, typename TPayload, typename THitType, bool bGTData = true>
42struct TSQVisitor : public Chaos::ISpatialVisitor<TPayload, Chaos::FReal>
43{
44 using TGeometryType = std::conditional_t<bGTData, Chaos::FGeometryParticle, Chaos::FGeometryParticleHandle>;
49 : StartPoint(InStartPoint)
50 , Dir(InDir)
51 , OutputFlags(InOutputFlags)
52 , bAnyHit(false)
53 , DebugParams(InDebugParams)
54 , HitFaceNormal(Chaos::FVec3::ZeroVector)
55 , HitBuffer(InHitBuffer)
56 , QueryFilterData(InQueryFilterData)
57 , QueryFilterDataConcrete(C2UFilterData(QueryFilterData.data))
58 , QueryCallback(InQueryCallback)
59 , QueryCenter(StartTM.GetLocation())
60 {
61 QueryGeomWorldBounds = FAABB3(QueryCenter, QueryCenter);
62 bAnyHit = QueryFilterData.flags & FChaosQueryFlag::eANY_HIT;
63 }
64
67 : Dir(InDir)
68 , OutputFlags(InOutputFlags)
69 , bAnyHit(false)
70 , DebugParams(InDebugParams)
71 , HitFaceNormal(Chaos::FVec3::ZeroVector)
72 , HitBuffer(InHitBuffer)
73 , QueryFilterData(InQueryFilterData)
74 , QueryFilterDataConcrete(C2UFilterData(QueryFilterData.data))
75 , QueryGeom(&InQueryGeom)
76 , QueryCallback(InQueryCallback)
77 , StartTM(InStartTM)
78 , QueryGeomWorldBounds(InQueryGeomWorldBounds)
79 , QueryCenter(InQueryGeomWorldBounds.Center())
80 {
81 bAnyHit = QueryFilterData.flags & FChaosQueryFlag::eANY_HIT;
82 //todo: check THitType is sweep
83 }
84
85 UE_DEPRECATED(5.8, "Use the overload that takes the QueryGeomWorldBounds")
91
94 : bAnyHit(false)
95 , DebugParams(InDebugParams)
96 , HitFaceNormal(Chaos::FVec3::ZeroVector)
97 , HitBuffer(InHitBuffer)
98 , QueryFilterData(InQueryFilterData)
99 , QueryFilterDataConcrete(C2UFilterData(QueryFilterData.data))
100 , QueryGeom(&InQueryGeom)
101 , QueryCallback(InQueryCallback)
102 , StartTM(InWorldTM)
103 , QueryGeomWorldBounds(InQueryGeomWorldBounds)
104 , QueryCenter(InQueryGeomWorldBounds.Center())
105 {
106 bAnyHit = QueryFilterData.flags & FChaosQueryFlag::eANY_HIT;
107 //todo: check THitType is overlap
108 }
109
110 UE_DEPRECATED(5.8, "Use the overload that takes the QueryGeomWorldBounds")
116
117 virtual ~TSQVisitor() {}
118
123
128
130 {
131 return Visit<ESQType::Overlap>(Instance, nullptr);
132 }
133
134 virtual const void* GetQueryData() const override
135 {
136 return &QueryFilterDataConcrete;
137 }
138
139 virtual const void* GetSimData() const override
140 {
141 return nullptr;
142 }
143
145 virtual const void* GetQueryPayload() const override
146 {
147 return nullptr;
148 }
149
150 virtual bool HasBlockingHit() const override
151 {
152 return HitBuffer.HasBlockingHit();
153 }
154
155private:
156
157 enum class ESQType
158 {
159 Raycast,
160 Sweep,
161 Overlap
162 };
163
164 TGeometryType* GetPayloadForThread(const TPayload& Payload)
165 {
166 if constexpr (bGTData)
167 {
168 return Payload.GetExternalGeometryParticle_ExternalThread();
169 }
170 else if constexpr (TPayload::bHasPayloadOnInternalThread)
171 {
172 return Payload.GetGeometryParticleHandle_PhysicsThread();
173 }
174 else
175 {
176 return nullptr;
177 }
178 }
179
180 template <ESQType SQ>
182 {
183 //QUICK_SCOPE_CYCLE_COUNTER(SQVisit);
184 TPayload Payload = Instance.Payload;
185
186 //todo: add a check to ensure hitbuffer matches SQ type
187 using namespace Chaos;
188 TGeometryType* GeometryParticle = GetPayloadForThread(Payload);
189
190 if (!GeometryParticle)
191 {
192 // This case handles particles created by the physics simulation without the main thread
193 // being made aware of their creation. We have a PT particle but no external particle
195
196 return true;
197 }
198
199 // Detect and fix any dangling handles on the game and physics threads
200 if constexpr (bGTData)
201 {
202 if (!(GeometryParticle->UniqueIdx() == Payload.UniqueIdx()))
203 {
204 UE_LOG(LogChaos, Warning, TEXT("Query Dangling handle detected on game Thread. Payload Id: %d, Particle Id: %d"), Payload.UniqueIdx().Idx, GeometryParticle->UniqueIdx().Idx);
205 ensureMsgf(false, TEXT("Query dangling handle detected on game Thread. Payload Id: %d, Particle Id: %d"), Payload.UniqueIdx().Idx, GeometryParticle->UniqueIdx().Idx);
206 return true;
207 }
208 }
209 else
210 {
211 if (GeometryParticle->GetHandleIdx() == INDEX_NONE || !(GeometryParticle->UniqueIdx() == Payload.UniqueIdx()))
212 {
213 UE_LOG(LogChaos, Warning, TEXT("Query Dangling handle detected on Physics Thread. Payload Id: %d, Particle Id: %d"), Payload.UniqueIdx().Idx, GeometryParticle->UniqueIdx().Idx);
214 ensureMsgf(false, TEXT("Query dangling handle detected on Physics Thread. Payload Id: %d, Particle Id: %d"), Payload.UniqueIdx().Idx, GeometryParticle->UniqueIdx().Idx);
215 return true;
216 }
217 }
218
219 const FShapesArray& Shapes = GeometryParticle->ShapesArray();
220
221 const bool bTestShapeBounds = Shapes.Num() > 1;
222 bool bContinue = true;
223
225
226#if CHAOS_DEBUG_DRAW
228 bool bHitBufferIncreased = false;
229#endif
230
231 for (int32 ShapeIndex = 0; ShapeIndex < Shapes.Num(); ++ShapeIndex)
232 {
233 const TUniquePtr<FPerShapeData>& Shape = Shapes[ShapeIndex];
234
235 const FImplicitObject* Geom = Shape->GetGeometry();
236
238
240 {
242 if (SQ == ESQType::Raycast)
243 {
244 InflatedWorldBounds = Shape->GetWorldSpaceShapeBounds();
245 }
246 else
247 {
248 // Transform to world bounds and get the proper half extent.
249 const FVec3 WorldHalfExtent = QueryGeomWorldBounds.Extents() * 0.5f;
250
251 InflatedWorldBounds = FAABB3(Shape->GetWorldSpaceShapeBounds().Min() - WorldHalfExtent, Shape->GetWorldSpaceShapeBounds().Max() + WorldHalfExtent);
252 }
253
254 if (SQ != ESQType::Overlap)
255 {
256 //todo: use fast raycast
258 const FVec3 InflatedBoundsTraceStart = SQ == ESQType::Raycast ? StartPoint : QueryGeomWorldBounds.Center();
259 if (!InflatedWorldBounds.RaycastFast(InflatedBoundsTraceStart, CurData->Dir, CurData->InvDir, CurData->bParallel, CurData->CurrentLength, CurData->InvCurrentLength, TmpTime, TmpExitTime))
260 {
262 continue;
263 }
264 }
265 else
266 {
267 if (!InflatedWorldBounds.Contains(QueryCenter))
268 {
270 continue;
271 }
272 }
273 }
274
275 //TODO: use gt particles directly
276 ECollisionQueryHitType HitType = QueryFilterData.flags & FChaosQueryFlag::ePREFILTER ? QueryCallback.PreFilter(QueryFilterDataConcrete, *Shape, *GeometryParticle) : ECollisionQueryHitType::Block;
277
278 if (HitType != ECollisionQueryHitType::None)
279 {
280#if CHAOS_DEBUG_DRAW
282#endif
283
284 //QUICK_SCOPE_CYCLE_COUNTER(SQNarrow);
285 THitType Hit;
286 Hit.Actor = GeometryParticle;
287 Hit.Shape = Shape.Get();
288
289 bool bHit = false;
290
291 FVec3 WorldPosition{ 0.0f }, WorldNormal{0.0f};
292 Chaos::FReal Distance = 0; //not needed but fixes compiler warning for overlap
293 int32 FaceIdx = INDEX_NONE; //not needed but fixes compiler warning for overlap
294 FVec3 FaceNormal = FVec3::ZeroVector;
295 const bool bComputeMTD = !!((uint16)(OutputFlags.HitFlags & EHitFlags::MTD));
296
297 if (SQ == ESQType::Raycast)
298 {
300 FVec3 LocalPosition;
301
302 const FVec3 DirLocal = ActorTM.InverseTransformVectorNoScale(Dir);
303 const FVec3 StartLocal = ActorTM.InverseTransformPositionNoScale(StartPoint);
304 bHit = Geom->Raycast(StartLocal, DirLocal, CurData->CurrentLength, /*Thickness=*/0.0, Distance, LocalPosition, LocalNormal, FaceIdx);
305 if (bHit)
306 {
307 WorldPosition = ActorTM.TransformPositionNoScale(LocalPosition);
308 WorldNormal = ActorTM.TransformVectorNoScale(LocalNormal);
309 }
310 }
311 else if (SQ == ESQType::Sweep && ensure(QueryGeom))
312 {
313 bHit = SweepQuery(*Geom, ActorTM, *QueryGeom, StartTM, CurData->Dir, CurData->CurrentLength, Distance, WorldPosition, WorldNormal, FaceIdx, FaceNormal, 0.f, bComputeMTD);
314 }
315 else if (SQ == ESQType::Overlap && ensure(QueryGeom))
316 {
317 if (bComputeMTD)
318 {
320 bHit = OverlapQuery(*Geom, ActorTM, *QueryGeom, StartTM, /*Thickness=*/0, &MTDInfo);
321 if (bHit)
322 {
323 WorldNormal = MTDInfo.Normal;
324 WorldPosition = MTDInfo.Position;
325 Distance = -MTDInfo.Penetration;
326 }
327 }
328 else
329 {
330 bHit = OverlapQuery(*Geom, ActorTM, *QueryGeom, StartTM, /*Thickness=*/0);
331 }
332 }
333
334 if (bHit)
335 {
336 //QUICK_SCOPE_CYCLE_COUNTER(SQNarrowHit);
337
338 bool bAcceptHit = true;
339 if constexpr (SQ == ESQType::Sweep && std::is_same_v<THitType, ChaosInterface::FSweepHit>)
340 {
341 const THitType* CurrentHit = HitBuffer.GetCurrentHit();
342 bool bIsCoLocatedHit = false;
343 if (FaceIdx != INDEX_NONE || !FaceNormal.IsNearlyZero())
344 {
345 if (CurrentHit)
346 {
347 constexpr static FReal CoLocationEpsilon = 1e-6;
348 const FReal DistDelta = FMath::Abs(Distance - CurrentHit->Distance);
349
350 if (DistDelta < CoLocationEpsilon && !HitFaceNormal.IsNearlyZero())
351 {
352 bIsCoLocatedHit = true;
353 // We already have a face hit from another triangle mesh - see if this one is better (more opposing the sweep)
354 const FReal OldDot = FVec3::DotProduct(CurData->Dir, HitFaceNormal);
355 const FReal NewDot = FVec3::DotProduct(CurData->Dir, FaceNormal);
356
357 if (NewDot < OldDot)
358 {
359 // More opposing
360 HitFaceNormal = FaceNormal;
361 }
362 else
363 {
365 // This hit is co-located but has a worse normal
366 bAcceptHit = false;
367 }
368 }
369 }
370
371 if (bAcceptHit)
372 {
373 // Record the new face normal
374 HitFaceNormal = FaceNormal;
375 }
376 }
377 // If we're not in a co-located hit, we need to make sure the new hit is actually better than the old.
378 // For normal hits this is redundant due to clipping length.
379 // When there is an initial overlaps though, we cannot clip length < 0, so we must check the returned distance.
380 if (CurrentHit != nullptr && !bIsCoLocatedHit && CurrentHit->Distance < Distance)
381 {
382 bAcceptHit = false;
383 }
384 }
385
386 if (bAcceptHit)
387 {
388 FillHitHelper(Hit, Distance, WorldPosition, WorldNormal, FaceIdx, bComputeMTD);
389
390 if constexpr (std::is_base_of_v<ChaosInterface::FQueryHit, THitType> || std::is_base_of_v<ChaosInterface::FPTQueryHit, THitType>)
391 {
392 Hit.FaceNormal = HitFaceNormal;
393 }
394
395 HitType = QueryFilterData.flags & FChaosQueryFlag::ePOSTFILTER ? QueryCallback.PostFilter(QueryFilterDataConcrete, Hit) : HitType;
396
397 if (HitType != ECollisionQueryHitType::None)
398 {
399 //overlap never blocks
400 const bool bBlocker = (HitType == ECollisionQueryHitType::Block || bAnyHit || HitBuffer.WantsSingleResult());
401 HitBuffer.InsertHit(Hit, bBlocker);
402
403 CVD_FILL_HIT_DATA_HELPER(Hit, HitType);
404
405#if CHAOS_DEBUG_DRAW
406 bHitBufferIncreased = true;
407#endif
408
409 if (bBlocker && SQ != ESQType::Overlap)
410 {
411 // When there is an initial overlap, MTD will return a negative distance. We need to clamp this to 0 as many checks don't work properly with a negative length.
412 CurData->SetLength(FMath::Max((FReal)0., Distance));
413 // If we have a zero length raycast, this is an initial overlap and there's no better result possible.
414 // Note: We do not do this check with sweeps as some initial overlap sweeps are better than others (more negative MTD).
415 if (CurData->CurrentLength == 0 && (SQ == ESQType::Raycast))
416 {
417 bContinue = false;
418 break;
419 }
420 }
421
422 if (bAnyHit)
423 {
424 bContinue = false;
425 break;
426 }
427 }
428 else
429 {
431 }
432 }
433 }
434 else
435 {
437 }
438 }
439 else
440 {
442 }
443 }
444
445#if CHAOS_DEBUG_DRAW
446 if (DebugParams.IsDebugQuery() && ChaosSQDrawDebugVisitorQueries)
447 {
449 }
450#endif
451
452 return bContinue;
453 }
454
455#if CHAOS_DEBUG_DRAW
456
457 void DebugDrawPayloadImpl(const TPayload& Payload, const bool bExternal, const bool bHit, decltype(&TPayload::DebugDraw))
458 {
459 Payload.DebugDraw(bExternal, bHit);
460 }
461 void DebugDrawPayloadImpl(const TPayload& Payload, const bool bExternal, const bool bHit, ...)
462 {}
463 void DebugDrawPayload(const TPayload& Payload, const bool bExternal, const bool bHit)
464 {
465 DebugDrawPayloadImpl(Payload, bExternal, bHit, 0);
466 }
467
468 template <ESQType SQ>
469 void DebugDraw(const Chaos::TSpatialVisitorData<TPayload>& Instance, const Chaos::FQueryFastData* CurData, const bool bPrefiltered, const bool bHit)
470 {
471 if (SQ == ESQType::Raycast)
472 {
473 const FVector EndPoint = StartPoint + (Dir * CurData->CurrentLength);
474 Chaos::FDebugDrawQueue::GetInstance().DrawDebugDirectionalArrow(StartPoint, EndPoint, 5.f, bHit ? FColor::Red : FColor::Green);
475 }
476 else if (SQ == ESQType::Overlap)
477 {
478 Chaos::DebugDraw::DrawShape(StartTM, QueryGeom, nullptr, bHit ? FColor::Red : FColor::Green, 0.0f);
479 }
480
481 if (Instance.bHasBounds)
482 {
483 Chaos::FDebugDrawQueue::GetInstance().DrawDebugBox(Instance.Bounds.Center(), Instance.Bounds.Extents(), FQuat::Identity, bHit ? FColor(100, 50, 50) : FColor(50, 100, 50), false, -1.f, 0, 0.f);
484 }
485
486 if (!bPrefiltered)
487 {
488 DebugDrawPayload(Instance.Payload, DebugParams.bExternalQuery, bHit);
489 }
490 }
491#endif
492
493 const FVector StartPoint = FVector::ZeroVector;
494 const FVector Dir = FVector::ZeroVector;
495 FHitFlags OutputFlags;
496 bool bAnyHit;
497 const ChaosInterface::FQueryDebugParams DebugParams;
498 Chaos::FVec3 HitFaceNormal;
500 const ChaosInterface::FQueryFilterData& QueryFilterData;
501 const FCollisionFilterData QueryFilterDataConcrete;
502 const QueryGeometryType* QueryGeom = nullptr;
504 const FTransform StartTM;
505 FAABB3 QueryGeomWorldBounds = FAABB3::ZeroAABB();
506 FVec3 QueryCenter = FVec3::ZeroVector;
507};
508
509
510template <typename QueryGeometryType, typename TPayload, typename THitType, bool bGTData = true>
511struct TBPVisitor : public Chaos::ISpatialVisitor<TPayload, Chaos::FReal>
512{
513 using TGeometryType = std::conditional_t<bGTData, Chaos::FGeometryParticle, Chaos::FGeometryParticleHandle>;
514
517 : HalfExtents(InQueryGeom.BoundingBox().Extents() * 0.5)
518 , bAnyHit(false)
519 , DebugParams(InDebugParams)
520 , HitBuffer(InHitBuffer)
521 , QueryFilterData(InQueryFilterData)
522 , QueryFilterDataConcrete(ToUnrealFilterData(InQueryFilterData.data))
523 , QueryGeom(&InQueryGeom)
524 , QueryCallback(InQueryCallback)
525 , StartTM(InWorldTM)
526 {
527 bAnyHit = QueryFilterData.flags & FPhysicsQueryFlag::eANY_HIT;
528 }
529
530 virtual ~TBPVisitor() {}
531
533 {
534 return Visit<ESQType::Overlap>(Instance, nullptr);
535 }
536
538 {
539 ensure(false);
540 return false;
541 }
542
544 {
545 ensure(false);
546 return false;
547 }
548
549 virtual const void* GetQueryData() const override
550 {
551 return &QueryFilterDataConcrete;
552 }
553
554 virtual const void* GetSimData() const override
555 {
556 return nullptr;
557 }
558
560 virtual const void* GetQueryPayload() const override
561 {
562 return nullptr;
563 }
564
565private:
566
567 enum class ESQType
568 {
569 Raycast,
570 Sweep,
571 Overlap
572 };
573
574 TGeometryType* GetPayloadForThread(const TPayload& Payload)
575 {
576 if constexpr (bGTData)
577 {
578 return Payload.GetExternalGeometryParticle_ExternalThread();
579 }
580 else if constexpr (TPayload::bHasPayloadOnInternalThread)
581 {
582 return Payload.GetGeometryParticleHandle_PhysicsThread();
583 }
584 else
585 {
586 return nullptr;
587 }
588 }
589
590 template <ESQType SQ>
592 {
593 bool bContinue = true;
594 TPayload Payload = Instance.Payload;
595 //todo: add a check to ensure hitbuffer matches SQ type
596 using namespace Chaos;
597 TGeometryType* GeometryParticle = GetPayloadForThread(Payload);
598 if (!GeometryParticle)
599 {
600 // This case handles particles created by the physics simulation without the main thread
601 // being made aware of their creation. We have a PT particle but no external particle
603 return true;
604 }
605 const FShapesArray& Shapes = GeometryParticle->ShapesArray();
606 THitType Hit;
607 Hit.Actor = GeometryParticle;
608
609 for (int32 ShapeIndex = 0; ShapeIndex < Shapes.Num(); ++ShapeIndex)
610 {
611 const TUniquePtr<FPerShapeData>& Shape = Shapes[ShapeIndex];
612
614
615 ECollisionQueryHitType HitType = QueryFilterData.flags & FPhysicsQueryFlag::ePREFILTER ? QueryCallback.PreFilter(QueryFilterDataConcrete, *Shape, *GeometryParticle) : ECollisionQueryHitType::Block;
616 if (HitType != ECollisionQueryHitType::None)
617 {
618 const bool bBlocker = (HitType == ECollisionQueryHitType::Block || bAnyHit || HitBuffer.WantsSingleResult());
619 Hit.Shape = Shape.Get();
620 HitBuffer.InsertHit(Hit, bBlocker);
621
622 CVD_FILL_HIT_DATA_HELPER(Hit, HitType);
623
624 if (bAnyHit)
625 {
626 bContinue = false;
627 }
628 break;
629 }
630 else
631 {
633 }
634 }
635 return bContinue;
636 }
637
638 const FVector StartPoint = FVector::ZeroVector;
639 const FVector Dir = FVector::ZeroVector;
640 const FVector HalfExtents = FVector::ZeroVector;
641 FHitFlags OutputFlags;
642 bool bAnyHit;
643 const ChaosInterface::FQueryDebugParams DebugParams;
645 const ChaosInterface::FQueryFilterData& QueryFilterData;
646 const FCollisionFilterData QueryFilterDataConcrete;
647 const QueryGeometryType* QueryGeom;
649 const FTransform StartTM;
650};
651
652
653template <typename QueryGeomType, typename TSweepHit, typename TPayload>
654void SweepHelper(const QueryGeomType& QueryGeom, const Chaos::ISpatialAcceleration<TPayload, Chaos::FReal, 3>& SpatialAcceleration, const FTransform& StartTM, const FVector& Dir, const float DeltaMagnitude, ChaosInterface::FSQHitBuffer<TSweepHit>& HitBuffer, EHitFlags OutputFlags, const ChaosInterface::FQueryFilterData& QueryFilterData, ICollisionQueryFilterCallbackBase& QueryCallback, const ChaosInterface::FQueryDebugParams& DebugParams)
655{
656 using namespace Chaos;
657 using namespace ChaosInterface;
658
659 const FAABB3 Bounds = QueryGeom.CalculateTransformedBounds(StartTM);
660 // There are cases where an invalid shape comes in which produces an invalid bounds. In this case, nan will enter causing the entire tree to be queried which will timeout.
661 const bool bIsValid = !Bounds.Min().ContainsNaN() && !Bounds.Max().ContainsNaN();
662 if (ensure(bIsValid))
663 {
664 TSQVisitor<QueryGeomType, TPayload, TSweepHit, std::is_same<TSweepHit, FSweepHit>::value> SweepVisitor(StartTM, Dir, HitBuffer, OutputFlags, QueryFilterData, QueryCallback, QueryGeom, Bounds, DebugParams);
665
666 HitBuffer.IncFlushCount();
667
668 // NOTE: Previously, we'd attempt to perform a sweep as an overlap if the DeltaMagnitude was 0.
669 // This caused various discrepancies as some of the out info couldn't be computed. Instead, sweep has been updated to handle 0 length sweeps.
670 const FVector HalfExtents = Bounds.Extents() * 0.5f;
671 SpatialAcceleration.Sweep(Bounds.GetCenter(), Dir, DeltaMagnitude, HalfExtents, SweepVisitor);
672
673 HitBuffer.DecFlushCount();
674 }
675}
676
677
678template <typename QueryGeomType, typename TOverlapHit, typename TPayload>
680{
681 using namespace Chaos;
682 using namespace ChaosInterface;
683
684 const FAABB3 Bounds = QueryGeom.CalculateTransformedBounds(GeomPose);
685 // There are cases where an invalid shape comes in which produces an invalid bounds. In this case, nan will enter causing the entire tree to be queried which will timeout.
686 const bool bIsValid = !Bounds.Min().ContainsNaN() && !Bounds.Max().ContainsNaN();
687 if (ensure(bIsValid))
688 {
689 HitBuffer.IncFlushCount();
690
691 bool bSkipNarrowPhase = QueryFilterData.flags & FPhysicsQueryFlag::eSKIPNARROWPHASE;
692
693 constexpr bool bGTData = std::is_same<TOverlapHit, FOverlapHit>::value;
694 if (bSkipNarrowPhase)
695 {
696 TBPVisitor<QueryGeomType, TPayload, TOverlapHit, bGTData> OverlapVisitor(GeomPose, HitBuffer, QueryFilterData, QueryCallback, QueryGeom, DebugParams);
697 SpatialAcceleration.Overlap(Bounds, OverlapVisitor);
698 }
699 else
700 {
701 TSQVisitor<QueryGeomType, TPayload, TOverlapHit, bGTData> OverlapVisitor(GeomPose, HitBuffer, QueryFilterData, QueryCallback, QueryGeom, Bounds, DebugParams);
702 SpatialAcceleration.Overlap(Bounds, OverlapVisitor);
703 }
704 HitBuffer.DecFlushCount();
705 }
706}
#define ensureMsgf( InExpression, InFormat,...)
Definition AssertionMacros.h:465
#define ensure( InExpression)
Definition AssertionMacros.h:464
#define CVD_FILL_HIT_DATA_HELPER(Hit, HitType)
Definition ChaosVDSQVisitorHelpers.h:98
#define CVD_TRACE_SCOPED_SCENE_QUERY_VISIT_HELPER(Type, ParticleTransform, ParticleIndex, ShapeIndex, CurData)
Definition ChaosVDSQVisitorHelpers.h:95
#define CVD_SET_SQ_SHAPE_REJECT_REASON(RejectReason)
Definition ChaosVDSQVisitorHelpers.h:101
ECollisionQueryHitType
Definition CollisionQueryFilterCallbackCore.h:13
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define TEXT(x)
Definition Platform.h:1272
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
EHitFlags
Definition PhysicsInterfaceWrapperShared.h:65
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
UE::Math::TTransform< double > FTransform
Definition MathFwd.h:53
FCollisionFilterData C2UFilterData(const FChaosFilterData &PFilterData)
Definition PhysicsInterfaceUtilsCore.cpp:9
FCollisionFilterData ToUnrealFilterData(const FChaosFilterData &FilterData)
Definition PhysicsInterfaceUtilsCore.cpp:24
void OverlapHelper(const QueryGeomType &QueryGeom, const Chaos::ISpatialAcceleration< TPayload, Chaos::FReal, 3 > &SpatialAcceleration, const FTransform &GeomPose, ChaosInterface::FSQHitBuffer< TOverlapHit > &HitBuffer, const ChaosInterface::FQueryFilterData &QueryFilterData, ICollisionQueryFilterCallbackBase &QueryCallback, const ChaosInterface::FQueryDebugParams &DebugParams)
Definition SQVisitor.h:679
void SweepHelper(const QueryGeomType &QueryGeom, const Chaos::ISpatialAcceleration< TPayload, Chaos::FReal, 3 > &SpatialAcceleration, const FTransform &StartTM, const FVector &Dir, const float DeltaMagnitude, ChaosInterface::FSQHitBuffer< TSweepHit > &HitBuffer, EHitFlags OutputFlags, const ChaosInterface::FQueryFilterData &QueryFilterData, ICollisionQueryFilterCallbackBase &QueryCallback, const ChaosInterface::FQueryDebugParams &DebugParams)
Definition SQVisitor.h:654
void FillHitHelper(TLocationHit &Hit, const Chaos::FReal Distance, const FVector &WorldPosition, const FVector &WorldNormal, int32 FaceIdx, bool bComputeMTD)
Definition SQVisitor.h:29
uint16_t uint16
Definition binka_ue_file_header.h:7
Definition SQTypes.h:220
const HitType * GetCurrentHit() const
Definition SQTypes.h:268
void IncFlushCount()
Definition SQTypes.h:233
void DecFlushCount()
Definition SQTypes.h:238
void InsertHit(const HitType &Hit, bool bBlocking)
Definition SQTypes.h:271
bool HasBlockingHit() const
Definition SQTypes.h:255
bool WantsSingleResult() const
Definition SQTypes.h:286
Definition ImplicitObject.h:111
virtual bool Raycast(const FVec3 &StartPoint, const FVec3 &Dir, const FReal Length, const FReal Thickness, FReal &OutTime, FVec3 &OutPosition, FVec3 &OutNormal, int32 &OutFaceIndex) const
Definition ImplicitObject.h:299
Definition ISpatialAcceleration.h:267
virtual void Overlap(const FAABB3 &QueryBounds, ISpatialVisitor< TPayloadType, FReal > &Visitor) const
Definition ISpatialAcceleration.h:298
virtual void Sweep(const FVec3 &Start, const FVec3 &Dir, const FReal Length, const FVec3 QueryHalfExtents, ISpatialVisitor< TPayloadType, FReal > &Visitor) const
Definition ISpatialAcceleration.h:297
Definition ISpatialAcceleration.h:120
FORCEINLINE const TVector< T, d > & Max() const
Definition AABB.h:596
FORCEINLINE TVector< T, d > Center() const
Definition AABB.h:450
FORCEINLINE TVector< T, d > Extents() const
Definition AABB.h:453
static FORCEINLINE TAABB< FReal, d > ZeroAABB()
Definition AABB.h:630
FORCEINLINE const TVector< T, d > & Min() const
Definition AABB.h:595
FORCEINLINE TVector< T, d > GetCenter() const
Definition AABB.h:451
bool ContainsNaN() const
Definition Vector.h:188
Definition IConsoleManager.h:1580
Definition CollisionQueryFilterCallbackCore.h:25
virtual ECollisionQueryHitType PostFilter(const FCollisionFilterData &FilterData, const ChaosInterface::FQueryHit &Hit)=0
virtual ECollisionQueryHitType PreFilter(const FCollisionFilterData &FilterData, const Chaos::FPerShapeData &Shape, const Chaos::FGeometryParticle &Actor)=0
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
Definition UniquePtr.h:107
UE_FORCEINLINE_HINT T * Get() const
Definition UniquePtr.h:324
Definition ChaosInterfaceUtils.cpp:28
Definition SkeletalMeshComponent.h:307
bool SweepQuery(const FImplicitObject &A, const FRigidTransform3 &ATM, const SweptGeometry &B, const FRigidTransform3 &BTM, const FVec3 &Dir, const FReal Length, FReal &OutTime, FVec3 &OutPosition, FVec3 &OutNormal, int32 &OutFaceIndex, FVec3 &OutFaceNormal, const FReal Thickness, const bool bComputeMTD)
Definition GeometryQueries.h:252
FRealDouble FReal
Definition Real.h:22
TVector< FReal, 3 > FVec3
Definition Core.h:17
bool OverlapQuery(const FImplicitObject &A, const FRigidTransform3 &ATM, const QueryGeometry &B, const FRigidTransform3 &BTM, const FReal Thickness=0, FMTDInfo *OutMTD=nullptr)
Definition GeometryQueries.h:34
TAABB< FReal, 3 > FAABB3
Definition ImplicitObject.h:34
@ false
Definition radaudio_common.h:23
Definition ChaosInterfaceWrapperCore.h:79
constexpr bool IsDebugQuery() const
Definition ChaosInterfaceWrapperCore.h:91
Definition GeometryQueries.h:27
Definition ISpatialAcceleration.h:14
Definition ISpatialAcceleration.h:99
Definition PhysicsInterfaceTypesCore.h:390
FChaosQueryFlags flags
Definition PhysicsInterfaceTypesCore.h:398
@ ePOSTFILTER
Run the post-intersection-test filter.
Definition PhysicsInterfaceTypesCore.h:289
@ ePREFILTER
Run the pre-intersection-test filter.
Definition PhysicsInterfaceTypesCore.h:287
@ eANY_HIT
Definition PhysicsInterfaceTypesCore.h:291
@ eSKIPNARROWPHASE
Skip narrow phase check for the query.
Definition PhysicsInterfaceTypesCore.h:297
Definition CollisionFilterData.h:46
Definition Color.h:486
static CORE_API const FColor Red
Definition Color.h:752
Definition PhysicsInterfaceWrapperShared.h:86
EHitFlags HitFlags
Definition PhysicsInterfaceWrapperShared.h:113
Definition SQVisitor.h:512
virtual const void * GetQueryPayload() const override
Definition SQVisitor.h:560
virtual const void * GetSimData() const override
Definition SQVisitor.h:554
virtual const void * GetQueryData() const override
Definition SQVisitor.h:549
virtual ~TBPVisitor()
Definition SQVisitor.h:530
std::conditional_t< bGTData, Chaos::FGeometryParticle, Chaos::FGeometryParticleHandle > TGeometryType
Definition SQVisitor.h:513
TBPVisitor(const FTransform &InWorldTM, ChaosInterface::FSQHitBuffer< THitType > &InHitBuffer, const ChaosInterface::FQueryFilterData &InQueryFilterData, ICollisionQueryFilterCallbackBase &InQueryCallback, const QueryGeometryType &InQueryGeom, const ChaosInterface::FQueryDebugParams &InDebugParams)
Definition SQVisitor.h:515
virtual bool Overlap(const Chaos::TSpatialVisitorData< TPayload > &Instance) override
Definition SQVisitor.h:532
virtual bool Raycast(const Chaos::TSpatialVisitorData< TPayload > &Instance, Chaos::FQueryFastData &CurData) override
Definition SQVisitor.h:537
virtual bool Sweep(const Chaos::TSpatialVisitorData< TPayload > &Instance, Chaos::FQueryFastData &CurData) override
Definition SQVisitor.h:543
Definition DelegateInstanceInterface.h:67
Definition SQVisitor.h:43
virtual const void * GetSimData() const override
Definition SQVisitor.h:139
virtual bool Overlap(const Chaos::TSpatialVisitorData< TPayload > &Instance) override
Definition SQVisitor.h:129
virtual bool Sweep(const Chaos::TSpatialVisitorData< TPayload > &Instance, Chaos::FQueryFastData &CurData) override
Definition SQVisitor.h:124
TSQVisitor(const FTransform &InWorldTM, ChaosInterface::FSQHitBuffer< THitType > &InHitBuffer, const ChaosInterface::FQueryFilterData &InQueryFilterData, ICollisionQueryFilterCallbackBase &InQueryCallback, const QueryGeometryType &InQueryGeom, const FAABB3 &InQueryGeomWorldBounds, const ChaosInterface::FQueryDebugParams &InDebugParams)
Definition SQVisitor.h:92
virtual ~TSQVisitor()
Definition SQVisitor.h:117
virtual bool HasBlockingHit() const override
Definition SQVisitor.h:150
virtual bool Raycast(const Chaos::TSpatialVisitorData< TPayload > &Instance, Chaos::FQueryFastData &CurData) override
Definition SQVisitor.h:119
TSQVisitor(const FVector &InStartPoint, const FVector &InDir, ChaosInterface::FSQHitBuffer< THitType > &InHitBuffer, EHitFlags InOutputFlags, const ChaosInterface::FQueryFilterData &InQueryFilterData, ICollisionQueryFilterCallbackBase &InQueryCallback, const ChaosInterface::FQueryDebugParams &InDebugParams)
Definition SQVisitor.h:47
virtual const void * GetQueryData() const override
Definition SQVisitor.h:134
std::conditional_t< bGTData, Chaos::FGeometryParticle, Chaos::FGeometryParticleHandle > TGeometryType
Definition SQVisitor.h:44
TSQVisitor(const FTransform &InStartTM, const FVector &InDir, ChaosInterface::FSQHitBuffer< THitType > &InHitBuffer, EHitFlags InOutputFlags, const ChaosInterface::FQueryFilterData &InQueryFilterData, ICollisionQueryFilterCallbackBase &InQueryCallback, const QueryGeometryType &InQueryGeom, const FAABB3 &InQueryGeomWorldBounds, const ChaosInterface::FQueryDebugParams &InDebugParams)
Definition SQVisitor.h:65
Chaos::FAABB3 FAABB3
Definition SQVisitor.h:45
virtual const void * GetQueryPayload() const override
Definition SQVisitor.h:145
static CORE_API const TQuat< double > Identity
Definition Quat.h:63
static CORE_API const TVector< double > ZeroVector
Definition Vector.h:79