Files
UnrealEngine/Engine/Source/Runtime/NavigationSystem/Private/NavLinkRenderingComponent.cpp
2025-05-18 13:04:45 +08:00

464 lines
20 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "NavLinkRenderingComponent.h"
#include "EngineGlobals.h"
#include "PrimitiveViewRelevance.h"
#include "PrimitiveSceneProxy.h"
#include "NavigationSystem.h"
#include "Engine/Engine.h"
#include "MaterialShared.h"
#include "Materials/Material.h"
#include "Materials/MaterialRenderProxy.h"
#include "MeshElementCollector.h"
#include "Engine/CollisionProfile.h"
#include "PrimitiveDrawingUtils.h"
#include "AI/Navigation/NavLinkDefinition.h"
#include "NavLinkRenderingProxy.h"
#include "NavLinkHostInterface.h"
#include "NavMesh/RecastNavMesh.h"
#include "SceneView.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(NavLinkRenderingComponent)
//----------------------------------------------------------------------//
// UNavLinkRenderingComponent
//----------------------------------------------------------------------//
UNavLinkRenderingComponent::UNavLinkRenderingComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
// properties
// Allows updating in game, while optimizing rendering for the case that it is not modified
Mobility = EComponentMobility::Stationary;
BodyInstance.SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
bIsEditorOnly = true;
SetGenerateOverlapEvents(false);
}
FBoxSphereBounds UNavLinkRenderingComponent::CalcBounds(const FTransform& InLocalToWorld) const
{
AActor* LinkOwnerActor = GetOwner();
if (LinkOwnerActor != NULL)
{
FBox BoundingBox(ForceInit);
INavLinkHostInterface* LinkOwnerHost = Cast<INavLinkHostInterface>(LinkOwnerActor);
if (LinkOwnerHost != NULL)
{
TArray<TSubclassOf<UNavLinkDefinition> > NavLinkClasses;
TArray<FNavigationLink> SimpleLinks;
TArray<FNavigationSegmentLink> DummySegmentLinks;
if (LinkOwnerHost->GetNavigationLinksClasses(NavLinkClasses))
{
for (int32 NavLinkClassIdx = 0; NavLinkClassIdx < NavLinkClasses.Num(); ++NavLinkClassIdx)
{
if (NavLinkClasses[NavLinkClassIdx] != NULL)
{
const TArray<FNavigationLink>& Links = UNavLinkDefinition::GetLinksDefinition(NavLinkClasses[NavLinkClassIdx]);
for (const auto& Link : Links)
{
BoundingBox += Link.Left;
BoundingBox += Link.Right;
}
}
}
}
if (LinkOwnerHost->GetNavigationLinksArray(SimpleLinks, DummySegmentLinks))
{
for (const auto& Link : SimpleLinks)
{
BoundingBox += Link.Left;
BoundingBox += Link.Right;
}
}
}
// BoundingBox is in actor space. Incorporate provided InLocalToWorld transform via component space.
const FTransform ActorToWorld = LinkOwnerActor->ActorToWorld();
const FTransform WorldToComponent = GetComponentTransform().Inverse();
return FBoxSphereBounds(BoundingBox).TransformBy(ActorToWorld * WorldToComponent * InLocalToWorld);
}
return FBoxSphereBounds(ForceInitToZero);
}
FPrimitiveSceneProxy* UNavLinkRenderingComponent::CreateSceneProxy()
{
return new FNavLinkRenderingProxy(this);
}
#if WITH_EDITOR
bool UNavLinkRenderingComponent::ComponentIsTouchingSelectionBox(const FBox& InSelBBox, const bool bConsiderOnlyBSP, const bool bMustEncompassEntireComponent) const
{
// NavLink rendering components not treated as 'selectable' in editor
return false;
}
bool UNavLinkRenderingComponent::ComponentIsTouchingSelectionFrustum(const FConvexVolume& InFrustum, const bool bConsiderOnlyBSP, const bool bMustEncompassEntireComponent) const
{
// NavLink rendering components not treated as 'selectable' in editor
return false;
}
#endif
//----------------------------------------------------------------------//
// FNavLinkRenderingProxy
//----------------------------------------------------------------------//
FNavLinkRenderingProxy::FNavLinkRenderingProxy(const UPrimitiveComponent* InComponent)
: FPrimitiveSceneProxy(InComponent)
{
LinkOwnerActor = InComponent->GetOwner();
LinkOwnerHost = Cast<INavLinkHostInterface>((UPrimitiveComponent*)InComponent);
if (LinkOwnerHost == nullptr)
{
LinkOwnerHost = Cast<INavLinkHostInterface>(LinkOwnerActor);
}
if (LinkOwnerActor != NULL && LinkOwnerHost != NULL)
{
const FTransform LinkOwnerLocalToWorld = LinkOwnerActor->ActorToWorld();
TArray<TSubclassOf<UNavLinkDefinition> > NavLinkClasses;
LinkOwnerHost->GetNavigationLinksClasses(NavLinkClasses);
for (int32 NavLinkClassIdx = 0; NavLinkClassIdx < NavLinkClasses.Num(); ++NavLinkClassIdx)
{
if (NavLinkClasses[NavLinkClassIdx] != NULL)
{
StorePointLinks(LinkOwnerLocalToWorld, UNavLinkDefinition::GetLinksDefinition(NavLinkClasses[NavLinkClassIdx]));
StoreSegmentLinks(LinkOwnerLocalToWorld, UNavLinkDefinition::GetSegmentLinksDefinition(NavLinkClasses[NavLinkClassIdx]));
}
}
TArray<FNavigationLink> PointLinks;
TArray<FNavigationSegmentLink> SegmentLinks;
if (LinkOwnerHost->GetNavigationLinksArray(PointLinks, SegmentLinks))
{
StorePointLinks(LinkOwnerLocalToWorld, PointLinks);
StoreSegmentLinks(LinkOwnerLocalToWorld, SegmentLinks);
}
}
}
SIZE_T FNavLinkRenderingProxy::GetTypeHash() const
{
static size_t UniquePointer;
return reinterpret_cast<size_t>(&UniquePointer);
}
void FNavLinkRenderingProxy::StorePointLinks(const FTransform& InLocalToWorld, const TArray<FNavigationLink>& LinksArray)
{
OffMeshPointLinks.Reserve(OffMeshPointLinks.Num() + LinksArray.Num());
for (const FNavigationLink& Link : LinksArray)
{
OffMeshPointLinks.Emplace(InLocalToWorld, Link);
}
}
void FNavLinkRenderingProxy::StoreSegmentLinks(const FTransform& InLocalToWorld, const TArray<FNavigationSegmentLink>& LinksArray)
{
OffMeshSegmentLinks.Reserve(OffMeshSegmentLinks.Num() + LinksArray.Num());
for (const FNavigationSegmentLink& Link : LinksArray)
{
OffMeshSegmentLinks.Emplace(InLocalToWorld, Link);
}
}
void FNavLinkRenderingProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
{
if (LinkOwnerActor && LinkOwnerActor->GetWorld())
{
const UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<const UNavigationSystemV1>(LinkOwnerActor->GetWorld());
TArray<float> StepHeights;
uint32 AgentMask = 0;
if (NavSys != NULL)
{
StepHeights.Reserve(NavSys->NavDataSet.Num());
for(int32 DataIndex = 0; DataIndex < NavSys->NavDataSet.Num(); ++DataIndex)
{
const ARecastNavMesh* NavMesh = Cast<const ARecastNavMesh>(NavSys->NavDataSet[DataIndex]);
if (NavMesh != NULL)
{
AgentMask = NavMesh->IsDrawingEnabled() ? AgentMask | (1 << DataIndex) : AgentMask;
#if WITH_RECAST
const float AgentMaxStepHeight = NavMesh->GetAgentMaxStepHeight(ENavigationDataResolution::Default);
if (AgentMaxStepHeight > 0 && NavMesh->IsDrawingEnabled())
{
StepHeights.Add(AgentMaxStepHeight);
}
#endif // WITH_RECAST
}
}
}
static const FColor RadiusColor(150, 160, 150, 48);
FMaterialRenderProxy* const MeshColorInstance = &Collector.AllocateOneFrameResource<FColoredMaterialRenderProxy>(GEngine->DebugMeshMaterial->GetRenderProxy(), RadiusColor);
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
FNavLinkRenderingProxy::GetLinkMeshes(OffMeshPointLinks, OffMeshSegmentLinks, StepHeights, MeshColorInstance, ViewIndex, Collector, AgentMask);
}
}
}
}
void FNavLinkRenderingProxy::GetLinkMeshes(const TArray<FNavLinkDrawing>& OffMeshPointLinks, const TArray<FNavLinkSegmentDrawing>& OffMeshSegmentLinks, TArray<float>& StepHeights, FMaterialRenderProxy* const MeshColorInstance, int32 ViewIndex, FMeshElementCollector& Collector, uint32 AgentMask)
{
static const FColor LinkColor(0,0,166);
static const float LinkArcThickness = 3.f;
static const float LinkArcHeight = 0.4f;
if (StepHeights.Num() == 0)
{
StepHeights.Add(FNavigationSystem::FallbackAgentHeight / 2);
}
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
for (int32 LinkIndex = 0; LinkIndex < OffMeshPointLinks.Num(); ++LinkIndex)
{
const FNavLinkDrawing& Link = OffMeshPointLinks[LinkIndex];
if ((Link.SupportedAgentsBits & AgentMask) == 0)
{
continue;
}
const FVector::FReal RealSegments = FMath::Max(LinkArcHeight * (Link.Right - Link.Left).Size() / 10., 8.);
check(RealSegments >= 0 && RealSegments <= (FVector::FReal)TNumericLimits<uint32>::Max());
const uint32 Segments = static_cast<uint32>(RealSegments);
DrawArc(PDI, Link.Left, Link.Right, LinkArcHeight, Segments, Link.Color, SDPG_World, 3.5f);
const FVector VOffset(0,0,FVector::Dist(Link.Left, Link.Right)*1.333f);
switch (Link.Direction)
{
case ENavLinkDirection::LeftToRight:
DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::RightToLeft:
DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::BothWays:
default:
DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
}
// draw snap-spheres on both ends
if (Link.SnapHeight < 0)
{
for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex)
{
GetCylinderMesh(Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
}
}
else
{
GetCylinderMesh(Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
}
}
static const float SegmentArcHeight = 0.25f;
for (int32 LinkIndex = 0; LinkIndex < OffMeshSegmentLinks.Num(); ++LinkIndex)
{
const FNavLinkSegmentDrawing& Link = OffMeshSegmentLinks[LinkIndex];
if ((Link.SupportedAgentsBits & AgentMask) == 0)
{
continue;
}
const FVector::FReal RealSegmentsStart = FMath::Max(SegmentArcHeight * (Link.RightStart - Link.LeftStart).Size() / 10., 8.);
const FVector::FReal RealSegmentsEnd= FMath::Max(SegmentArcHeight * (Link.RightEnd - Link.LeftEnd).Size() / 10., 8.);
check(RealSegmentsStart >= 0 && RealSegmentsStart <= (FVector::FReal)TNumericLimits<uint32>::Max());
check(RealSegmentsEnd >= 0 && RealSegmentsEnd <= (FVector::FReal)TNumericLimits<uint32>::Max());
const uint32 SegmentsStart = static_cast<uint32>(RealSegmentsStart);
const uint32 SegmentsEnd = static_cast<uint32>(RealSegmentsEnd);
DrawArc(PDI, Link.LeftStart, Link.RightStart, SegmentArcHeight, SegmentsStart, Link.Color, SDPG_World, 3.5f);
DrawArc(PDI, Link.LeftEnd, Link.RightEnd, SegmentArcHeight, SegmentsEnd, Link.Color, SDPG_World, 3.5f);
const FVector VOffset(0,0,FVector::Dist(Link.LeftStart, Link.RightStart)*1.333f);
switch (Link.Direction)
{
case ENavLinkDirection::LeftToRight:
DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::RightToLeft:
DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::BothWays:
default:
DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
}
// draw snap-spheres on both ends
if (Link.SnapHeight < 0)
{
for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex)
{
GetCylinderMesh(Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
}
}
else
{
GetCylinderMesh(Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
GetCylinderMesh(Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World, ViewIndex, Collector);
}
}
}
void FNavLinkRenderingProxy::DrawLinks(FPrimitiveDrawInterface* PDI, TArray<FNavLinkDrawing>& OffMeshPointLinks, TArray<FNavLinkSegmentDrawing>& OffMeshSegmentLinks, TArray<float>& StepHeights, FMaterialRenderProxy* const MeshColorInstance, uint32 AgentMask)
{
static const FColor LinkColor(0,0,166);
static const float LinkArcThickness = 3.f;
static const float LinkArcHeight = 0.4f;
if (StepHeights.Num() == 0)
{
StepHeights.Add(FNavigationSystem::FallbackAgentHeight / 2);
}
for (int32 LinkIndex = 0; LinkIndex < OffMeshPointLinks.Num(); ++LinkIndex)
{
const FNavLinkDrawing& Link = OffMeshPointLinks[LinkIndex];
if ((Link.SupportedAgentsBits & AgentMask) == 0)
{
continue;
}
const FVector::FReal RealSegments = FMath::Max(LinkArcHeight * (Link.Right - Link.Left).Size() / 10., 8.);
check(RealSegments >= 0 && RealSegments <= (FVector::FReal)TNumericLimits<uint32>::Max());
const uint32 Segments = static_cast<uint32>(RealSegments);
DrawArc(PDI, Link.Left, Link.Right, LinkArcHeight, Segments, Link.Color, SDPG_World, 3.5f);
const FVector VOffset(0,0,FVector::Dist(Link.Left, Link.Right)*1.333f);
switch (Link.Direction)
{
case ENavLinkDirection::LeftToRight:
DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::RightToLeft:
DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::BothWays:
default:
DrawArrowHead(PDI, Link.Right, Link.Left+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.Left, Link.Right+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
}
// draw snap-spheres on both ends
if (Link.SnapHeight < 0)
{
for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex)
{
DrawCylinder(PDI, Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
}
}
else
{
DrawCylinder(PDI, Link.Right, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.Left, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
}
}
static const float SegmentArcHeight = 0.25f;
for (int32 LinkIndex = 0; LinkIndex < OffMeshSegmentLinks.Num(); ++LinkIndex)
{
const FNavLinkSegmentDrawing& Link = OffMeshSegmentLinks[LinkIndex];
if ((Link.SupportedAgentsBits & AgentMask) == 0)
{
continue;
}
const FVector::FReal RealSegmentsStart = FMath::Max(SegmentArcHeight * (Link.RightStart - Link.LeftStart).Size() / 10., 8.);
const FVector::FReal RealSegmentsEnd = FMath::Max(SegmentArcHeight * (Link.RightEnd - Link.LeftEnd).Size() / 10., 8.);
check(RealSegmentsStart >= 0 && RealSegmentsStart <= (FVector::FReal)TNumericLimits<uint32>::Max());
check(RealSegmentsEnd >= 0 && RealSegmentsEnd <= (FVector::FReal)TNumericLimits<uint32>::Max());
const uint32 SegmentsStart = static_cast<uint32>(RealSegmentsStart);
const uint32 SegmentsEnd = static_cast<uint32>(RealSegmentsEnd);
DrawArc(PDI, Link.LeftStart, Link.RightStart, SegmentArcHeight, SegmentsStart, Link.Color, SDPG_World, 3.5f);
DrawArc(PDI, Link.LeftEnd, Link.RightEnd, SegmentArcHeight, SegmentsEnd, Link.Color, SDPG_World, 3.5f);
const FVector VOffset(0,0,FVector::Dist(Link.LeftStart, Link.RightStart)*1.333f);
switch (Link.Direction)
{
case ENavLinkDirection::LeftToRight:
DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::RightToLeft:
DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
case ENavLinkDirection::BothWays:
default:
DrawArrowHead(PDI, Link.RightStart, Link.LeftStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.RightEnd, Link.LeftEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftStart, Link.RightStart+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
DrawArrowHead(PDI, Link.LeftEnd, Link.RightEnd+VOffset, 30.f, Link.Color, SDPG_World, 3.5f);
break;
}
// draw snap-spheres on both ends
if (Link.SnapHeight < 0)
{
for (int32 StepHeightIndex = 0; StepHeightIndex < StepHeights.Num(); ++StepHeightIndex)
{
DrawCylinder(PDI, Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, StepHeights[StepHeightIndex], 10, MeshColorInstance, SDPG_World);
}
}
else
{
DrawCylinder(PDI, Link.RightStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.RightEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.LeftStart, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
DrawCylinder(PDI, Link.LeftEnd, FVector(1, 0, 0), FVector(0, 1, 0), FVector(0, 0, 1), Link.SnapRadius, Link.SnapHeight, 10, MeshColorInstance, SDPG_World);
}
}
}
FPrimitiveViewRelevance FNavLinkRenderingProxy::GetViewRelevance(const FSceneView* View) const
{
FPrimitiveViewRelevance Result;
Result.bDrawRelevance = IsShown(View) && IsSelected() && (View && View->Family && View->Family->EngineShowFlags.Navigation);
Result.bDynamicRelevance = true;
// ideally the TranslucencyRelevance should be filled out by the material, here we do it conservative
Result.bSeparateTranslucency = Result.bNormalTranslucency = IsShown(View);
Result.bShadowRelevance = IsShadowCast(View);
Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
return Result;
}
uint32 FNavLinkRenderingProxy::GetMemoryFootprint( void ) const
{
return( sizeof( *this ) + GetAllocatedSize() );
}
uint32 FNavLinkRenderingProxy::GetAllocatedSize( void ) const
{
return IntCastChecked<uint32>(FPrimitiveSceneProxy::GetAllocatedSize() + OffMeshPointLinks.GetAllocatedSize() + OffMeshSegmentLinks.GetAllocatedSize());
}