void FNavMeshPath::DescribeSelfToVisLog(FVisualLogEntry* Snapshot) const { if (IsStringPulled()) { // draw path points only for string pulled paths Super::DescribeSelfToVisLog(Snapshot); } // draw corridor #if WITH_RECAST FVisualLogShapeElement CorridorPoly(EVisualLoggerShapeElement::Polygon); CorridorPoly.SetColor(FColorList::Cyan); CorridorPoly.Category = LogNavigation.GetCategoryName(); CorridorPoly.Points.Reserve(PathCorridor.Num() * 6); const FVector CorridorOffset = NavigationDebugDrawing::PathOffset * 1.25f; int32 NumAreaMark = 1; ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(GetNavigationDataUsed()); NavMesh->BeginBatchQuery(); TArray<FVector> Verts; for (int32 Idx = 0; Idx < PathCorridor.Num(); Idx++) { Verts.Reset(); NavMesh->GetPolyVerts(PathCorridor[Idx], Verts); CorridorPoly.Points.Reset(); CorridorPoly.Points.Append(Verts); Snapshot->ElementsToDraw.Add(CorridorPoly); const uint8 AreaID = NavMesh->GetPolyAreaID(PathCorridor[Idx]); const UClass* AreaClass = NavMesh->GetAreaClass(AreaID); if (AreaClass && AreaClass != UNavigationSystem::GetDefaultWalkableArea()) { FVector CenterPt = FVector::ZeroVector; for (int32 VIdx = 0; VIdx < Verts.Num(); VIdx++) { CenterPt += Verts[VIdx]; } CenterPt /= Verts.Num(); FVisualLogShapeElement AreaMarkElem(EVisualLoggerShapeElement::Segment); AreaMarkElem.SetColor(FColorList::Orange); AreaMarkElem.Category = LogNavigation.GetCategoryName(); AreaMarkElem.Thicknes = 2; AreaMarkElem.Description = AreaClass->GetName(); AreaMarkElem.Points.Add(CenterPt + CorridorOffset); AreaMarkElem.Points.Add(CenterPt + CorridorOffset + FVector(0,0,100.0f + NumAreaMark * 50.0f)); Snapshot->ElementsToDraw.Add(AreaMarkElem); NumAreaMark = (NumAreaMark + 1) % 5; } } NavMesh->FinishBatchQuery(); //Snapshot->ElementsToDraw.Add(CorridorElem); #endif }
void LogPathPartHelper(AActor* LogOwner, FNavMeshPath* NavMeshPath, int32 StartIdx, int32 EndIdx) { #if ENABLE_VISUAL_LOG && WITH_RECAST ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(NavMeshPath->GetNavigationDataUsed()); if (NavMesh == NULL || !NavMeshPath->PathCorridor.IsValidIndex(StartIdx) || !NavMeshPath->PathCorridor.IsValidIndex(EndIdx)) { return; } NavMesh->BeginBatchQuery(); FVector SegmentStart = NavMeshPath->GetPathPoints()[0].Location; FVector SegmentEnd(FVector::ZeroVector); if (StartIdx > 0) { NavMesh->GetPolyCenter(NavMeshPath->PathCorridor[StartIdx], SegmentStart); } for (int32 Idx = StartIdx + 1; Idx < EndIdx; Idx++) { NavMesh->GetPolyCenter(NavMeshPath->PathCorridor[Idx], SegmentEnd); UE_VLOG_SEGMENT_THICK(LogOwner, LogCrowdFollowing, Log, SegmentStart, SegmentEnd, FColor::Yellow, 2, TEXT_EMPTY); SegmentStart = SegmentEnd; } if (EndIdx == (NavMeshPath->PathCorridor.Num() - 1)) { SegmentEnd = NavMeshPath->GetPathPoints()[1].Location; } else { NavMesh->GetPolyCenter(NavMeshPath->PathCorridor[EndIdx], SegmentEnd); } UE_VLOG_SEGMENT_THICK(LogOwner, LogCrowdFollowing, Log, SegmentStart, SegmentEnd, FColor::Yellow, 2, TEXT_EMPTY); NavMesh->FinishBatchQuery(); #endif // ENABLE_VISUAL_LOG && WITH_RECAST }
void UCrowdManager::DrawDebugPath(const dtCrowdAgent* CrowdAgent) const { ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(MyNavData); if (NavMesh == NULL) { return; } NavMesh->BeginBatchQuery(); const dtPolyRef* Path = CrowdAgent->corridor.getPath(); TArray<FVector> Verts; for (int32 Idx = 0; Idx < CrowdAgent->corridor.getPathCount(); Idx++) { Verts.Reset(); NavMesh->GetPolyVerts(Path[Idx], Verts); uint16 PolyFlags = 0; uint16 AreaFlags = 0; NavMesh->GetPolyFlags(Path[Idx], PolyFlags, AreaFlags); const FColor PolyColor = AreaFlags != 1 ? CrowdDebugDrawing::Path : CrowdDebugDrawing::PathSpecial; for (int32 VertIdx = 0; VertIdx < Verts.Num(); VertIdx++) { const FVector Pt0 = Verts[VertIdx]; const FVector Pt1 = Verts[(VertIdx + 1) % Verts.Num()]; DrawDebugLine(GetWorld(), Pt0 + CrowdDebugDrawing::Offset * 0.5f, Pt1 + CrowdDebugDrawing::Offset * 0.5f, PolyColor, false , /*LifeTime*/-1.f, /*DepthPriority*/0 , /*Thickness*/CrowdDebugDrawing::LineThickness); } } NavMesh->FinishBatchQuery(); }
void UGameplayDebuggingComponent::ServerCollectNavmeshData_Implementation(FVector_NetQuantize10 TargetLocation) { #if WITH_RECAST UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld()); ARecastNavMesh* NavData = GetNavData(); if (NavData == NULL) { NavmeshRepData.Empty(); return; } const double Timer1 = FPlatformTime::Seconds(); TArray<int32> Indices; int32 TileX = 0; int32 TileY = 0; const int32 DeltaX[] = { 0, 1, 1, 0, -1, -1, -1, 0, 1 }; const int32 DeltaY[] = { 0, 0, 1, 1, 1, 0, -1, -1, -1 }; NavData->BeginBatchQuery(); // add 3x3 neighborhood of target int32 TargetTileX = 0; int32 TargetTileY = 0; NavData->GetNavMeshTileXY(TargetLocation, TargetTileX, TargetTileY); for (int32 i = 0; i < ARRAY_COUNT(DeltaX); i++) { const int32 NeiX = TargetTileX + DeltaX[i]; const int32 NeiY = TargetTileY + DeltaY[i]; if (FMath::Abs(NeiX - TileX) > 1 || FMath::Abs(NeiY - TileY) > 1) { NavData->GetNavMeshTilesAt(NeiX, NeiY, Indices); } } const FNavDataConfig& NavConfig = NavData->GetConfig(); FColor NavMeshColors[RECAST_MAX_AREAS]; NavMeshColors[RECAST_DEFAULT_AREA] = NavConfig.Color.DWColor() > 0 ? NavConfig.Color : NavMeshRenderColor_RecastMesh; for (uint8 i = 0; i < RECAST_DEFAULT_AREA; ++i) { NavMeshColors[i] = NavData->GetAreaIDColor(i); } TArray<uint8> UncompressedBuffer; FMemoryWriter ArWriter(UncompressedBuffer); int32 NumIndices = Indices.Num(); ArWriter << NumIndices; for (int32 i = 0; i < NumIndices; i++) { FRecastDebugGeometry NavMeshGeometry; NavMeshGeometry.bGatherPolyEdges = false; NavMeshGeometry.bGatherNavMeshEdges = false; NavData->GetDebugGeometry(NavMeshGeometry, Indices[i]); NavMeshDebug::FTileData TileData; const FBox TileBoundingBox = NavData->GetNavMeshTileBounds(Indices[i]); TileData.Location = TileBoundingBox.GetCenter(); for (int32 VertIndex = 0; VertIndex < NavMeshGeometry.MeshVerts.Num(); ++VertIndex) { const NavMeshDebug::FShortVector SV = NavMeshGeometry.MeshVerts[VertIndex] - TileData.Location; TileData.Verts.Add(SV); } for (int32 iArea = 0; iArea < RECAST_MAX_AREAS; iArea++) { const int32 NumTris = NavMeshGeometry.AreaIndices[iArea].Num(); if (NumTris) { NavMeshDebug::FAreaPolys AreaPolys; for (int32 AreaIndicesIndex = 0; AreaIndicesIndex < NavMeshGeometry.AreaIndices[iArea].Num(); ++AreaIndicesIndex) { AreaPolys.Indices.Add(NavMeshGeometry.AreaIndices[iArea][AreaIndicesIndex]); } AreaPolys.Color = NavMeshColors[iArea]; TileData.Areas.Add(AreaPolys); } } TileData.Links.Reserve(NavMeshGeometry.OffMeshLinks.Num()); for (int32 iLink = 0; iLink < NavMeshGeometry.OffMeshLinks.Num(); iLink++) { const FRecastDebugGeometry::FOffMeshLink& SrcLink = NavMeshGeometry.OffMeshLinks[iLink]; NavMeshDebug::FOffMeshLink Link; Link.Left = SrcLink.Left - TileData.Location; Link.Right = SrcLink.Right - TileData.Location; Link.Color = ((SrcLink.Direction && SrcLink.ValidEnds) || (SrcLink.ValidEnds & FRecastDebugGeometry::OMLE_Left)) ? DarkenColor(NavMeshColors[SrcLink.AreaID]) : NavMeshRenderColor_OffMeshConnectionInvalid; Link.PackedFlags.Radius = (int8)SrcLink.Radius; Link.PackedFlags.Direction = SrcLink.Direction; Link.PackedFlags.ValidEnds = SrcLink.ValidEnds; TileData.Links.Add(Link); } ArWriter << TileData; } NavData->FinishBatchQuery(); const double Timer2 = FPlatformTime::Seconds(); const int32 HeaderSize = sizeof(int32); NavmeshRepData.Init(0, HeaderSize + FMath::TruncToInt(1.1f * UncompressedBuffer.Num())); const int32 UncompressedSize = UncompressedBuffer.Num(); int32 CompressedSize = NavmeshRepData.Num() - HeaderSize; uint8* DestBuffer = NavmeshRepData.GetData(); FMemory::Memcpy(DestBuffer, &UncompressedSize, HeaderSize); DestBuffer += HeaderSize; FCompression::CompressMemory((ECompressionFlags)(COMPRESS_ZLIB | COMPRESS_BiasMemory), (void*)DestBuffer, CompressedSize, (void*)UncompressedBuffer.GetData(), UncompressedSize); NavmeshRepData.SetNum(CompressedSize + HeaderSize, false); const double Timer3 = FPlatformTime::Seconds(); UE_LOG(LogGDT, Log, TEXT("Preparing navmesh data: %.1fkB took %.3fms (collect: %.3fms + compress %d%%: %.3fms)"), NavmeshRepData.Num() / 1024.0f, 1000.0f * (Timer3 - Timer1), 1000.0f * (Timer2 - Timer1), FMath::TruncToInt(100.0f * NavmeshRepData.Num() / UncompressedBuffer.Num()), 1000.0f * (Timer3 - Timer2)); #endif if (World && World->GetNetMode() != NM_DedicatedServer) { OnRep_UpdateNavmesh(); } }