void UEnvQueryGenerator_ProjectedPoints::StoreNavPoints(const TArray<FNavLocation>& Points, FEnvQueryInstance& QueryInstance) const { const int32 InitialElementsCount = QueryInstance.Items.Num(); QueryInstance.ReserveItemData(InitialElementsCount + Points.Num()); for (int32 Idx = 0; Idx < Points.Num(); Idx++) { // store using default function to handle creating new data entry QueryInstance.AddItemData<UEnvQueryItemType_Point>(Points[Idx]); } FEnvQueryOptionInstance& OptionInstance = QueryInstance.Options[QueryInstance.OptionIndex]; OptionInstance.bHasNavLocations = (ProjectionData.TraceMode == EEnvQueryTrace::Navigation); }
void UEnvQueryGenerator_PathingGrid::GenerateItems(FEnvQueryInstance& QueryInstance) const { #if WITH_RECAST const ARecastNavMesh* NavMesh = FEQSHelpers::FindNavMeshForQuery(QueryInstance); if (NavMesh == NULL) { return; } float PathDistanceValue = 0.0f; float DensityValue = 0.0f; bool bFromContextValue = true; if (!QueryInstance.GetParamValue(MaxPathDistance, PathDistanceValue, TEXT("MaxPathDistance")) || !QueryInstance.GetParamValue(Density, DensityValue, TEXT("Density")) || !QueryInstance.GetParamValue(PathFromContext, bFromContextValue, TEXT("PathFromContext"))) { return; } const int32 ItemCount = FPlatformMath::TruncToInt((PathDistanceValue * 2.0f / DensityValue) + 1); const int32 ItemCountHalf = ItemCount / 2; TArray<FVector> ContextLocations; QueryInstance.PrepareContext(GenerateAround, ContextLocations); QueryInstance.ReserveItemData(ItemCountHalf * ItemCountHalf * ContextLocations.Num()); TArray<NavNodeRef> NavNodeRefs; NavMesh->BeginBatchQuery(); int32 DataOffset = 0; for (int32 ContextIndex = 0; ContextIndex < ContextLocations.Num(); ContextIndex++) { // find all node refs in pathing distance FBox AllowedBounds; NavNodeRefs.Reset(); FindNodeRefsInPathDistance(NavMesh, ContextLocations[ContextIndex], PathDistanceValue, bFromContextValue, NavNodeRefs, AllowedBounds); // cast 2D grid on generated node refs for (int32 IndexX = 0; IndexX < ItemCount; ++IndexX) { for (int32 IndexY = 0; IndexY < ItemCount; ++IndexY) { const FVector TestPoint = ContextLocations[ContextIndex] - FVector(DensityValue * (IndexX - ItemCountHalf), DensityValue * (IndexY - ItemCountHalf), 0); if (!AllowedBounds.IsInsideXY(TestPoint)) { continue; } // trace line on navmesh, and process all hits with collected node refs TArray<FNavLocation> Hits; NavMesh->ProjectPointMulti(TestPoint, Hits, FVector::ZeroVector, AllowedBounds.Min.Z, AllowedBounds.Max.Z); for (int32 HitIndex = 0; HitIndex < Hits.Num(); HitIndex++) { if (IsNavLocationInPathDistance(NavMesh, Hits[HitIndex], NavNodeRefs)) { // store generated point QueryInstance.AddItemData<UEnvQueryItemType_Point>(Hits[HitIndex].Location); } } } } } NavMesh->FinishBatchQuery(); #endif // WITH_RECAST }