bool FWorldTileModel::ShouldBeVisible(FBox EditableArea) const { // Always loaded levels always visible if (IsAlwaysLoaded() || IsRootTile()) { return true; } FBox LevelBBox = GetLevelBounds(); // Visible if level has no valid bounds if (!LevelBBox.IsValid) { return true; } // Visible if level bounds inside editable area if (EditableArea.IsInsideXY(LevelBBox)) { return true; } // Visible if level bounds bigger than editable area and intersects that area if ((LevelBBox.GetExtent().X >= EditableArea.GetExtent().X || LevelBBox.GetExtent().Y >= EditableArea.GetExtent().Y) && LevelBBox.IntersectXY(EditableArea)) { return true; } return false; }
/** Prepares for multithreaded generation of VolumeDistanceField. */ void FStaticLightingSystem::BeginCalculateVolumeDistanceField() { DistanceFieldVolumeBounds = Scene.ImportanceBoundingBox; if (DistanceFieldVolumeBounds.GetVolume() < KINDA_SMALL_NUMBER) { DistanceFieldVolumeBounds = AggregateMesh.GetBounds(); } FBox UnclampedDistanceFieldVolumeBounds = DistanceFieldVolumeBounds; FVector4 DoubleExtent = UnclampedDistanceFieldVolumeBounds.GetExtent() * 2; DoubleExtent.X = DoubleExtent.X - FMath::Fmod(DoubleExtent.X, VolumeDistanceFieldSettings.VoxelSize) + VolumeDistanceFieldSettings.VoxelSize; DoubleExtent.Y = DoubleExtent.Y - FMath::Fmod(DoubleExtent.Y, VolumeDistanceFieldSettings.VoxelSize) + VolumeDistanceFieldSettings.VoxelSize; DoubleExtent.Z = DoubleExtent.Z - FMath::Fmod(DoubleExtent.Z, VolumeDistanceFieldSettings.VoxelSize) + VolumeDistanceFieldSettings.VoxelSize; // Round the max up to the next step boundary UnclampedDistanceFieldVolumeBounds.Max = UnclampedDistanceFieldVolumeBounds.Min + DoubleExtent; const FVector4 VolumeSizes = UnclampedDistanceFieldVolumeBounds.GetExtent() * 2.0f / VolumeDistanceFieldSettings.VoxelSize; VolumeSizeX = FMath::Trunc(VolumeSizes.X + DELTA); VolumeSizeY = FMath::Trunc(VolumeSizes.Y + DELTA); VolumeSizeZ = FMath::Trunc(VolumeSizes.Z + DELTA); // Use a float to avoid 32 bit integer overflow with large volumes const float NumVoxels = VolumeSizeX * VolumeSizeY * VolumeSizeZ; if (NumVoxels > VolumeDistanceFieldSettings.MaxVoxels) { const int32 OldSizeX = VolumeSizeX; const int32 OldSizeY = VolumeSizeY; const int32 OldSizeZ = VolumeSizeZ; const float SingleDimensionScale = FMath::Pow(NumVoxels / VolumeDistanceFieldSettings.MaxVoxels, 1.0f / 3.0f); DistanceFieldVoxelSize = VolumeDistanceFieldSettings.VoxelSize * SingleDimensionScale; DoubleExtent = DistanceFieldVolumeBounds.GetExtent() * 2; DoubleExtent.X = DoubleExtent.X - FMath::Fmod(DoubleExtent.X, DistanceFieldVoxelSize) + DistanceFieldVoxelSize; DoubleExtent.Y = DoubleExtent.Y - FMath::Fmod(DoubleExtent.Y, DistanceFieldVoxelSize) + DistanceFieldVoxelSize; DoubleExtent.Z = DoubleExtent.Z - FMath::Fmod(DoubleExtent.Z, DistanceFieldVoxelSize) + DistanceFieldVoxelSize; // Round the max up to the next step boundary with the clamped voxel size DistanceFieldVolumeBounds.Max = DistanceFieldVolumeBounds.Min + DoubleExtent; const FVector4 ClampedVolumeSizes = DistanceFieldVolumeBounds.GetExtent() * 2.0f / DistanceFieldVoxelSize; VolumeSizeX = FMath::Trunc(ClampedVolumeSizes.X + DELTA); VolumeSizeY = FMath::Trunc(ClampedVolumeSizes.Y + DELTA); VolumeSizeZ = FMath::Trunc(ClampedVolumeSizes.Z + DELTA); LogSolverMessage(FString::Printf(TEXT("CalculateVolumeDistanceField %ux%ux%u, clamped to %ux%ux%u"), OldSizeX, OldSizeY, OldSizeZ, VolumeSizeX, VolumeSizeY, VolumeSizeZ)); } else { DistanceFieldVolumeBounds = UnclampedDistanceFieldVolumeBounds; DistanceFieldVoxelSize = VolumeDistanceFieldSettings.VoxelSize; LogSolverMessage(FString::Printf(TEXT("CalculateVolumeDistanceField %ux%ux%u"), VolumeSizeX, VolumeSizeY, VolumeSizeZ)); } VolumeDistanceField.Empty(VolumeSizeX * VolumeSizeY * VolumeSizeZ); VolumeDistanceField.AddZeroed(VolumeSizeX * VolumeSizeY * VolumeSizeZ); FPlatformAtomics::InterlockedExchange(&NumOutstandingVolumeDataLayers, VolumeSizeZ); }
void ATheHUD::DrawHUD() { // Canvas is only initialized here. Super::DrawHUD(); InitWidgets(); RenderPortrait(); // Render the minimap, only if the floor is present FBox box = Game->flycam->floor->GetBox(); FVector lookPt = box.GetCenter(); RenderScreen( rendererMinimap, lookPt, box.GetExtent().GetMax(), FVector( 0, 0, -1 ) ); ui->SetSize( FVector2D( Canvas->SizeX, Canvas->SizeY ) ); ui->Update( Game->gm->T ); // Ticked here, in case reflow is needed ui->render(); // Overlay the lines for the minimap's view. vector< FVector2D > pts = ui->gameChrome->rightPanel->minimap->pts; for( int i = 0; i < pts.size()-1; i++ ) { Canvas->K2_DrawLine( pts[i], pts[i+1], 2.f, FLinearColor::Green ); } if( pts.size() > 1 ) { Canvas->K2_DrawLine( pts[ pts.size()-1 ], pts[ 0 ], 2.f, FLinearColor::Green ); } }
void ASpacePartioner::Initialize(const float& inExtent, const bool& inDrawDebugInfo) { bInitialized = true; bDrawDebugInfo = inDrawDebugInfo; // The Extent is very similar to the radius of a circle FVector min = FVector(-inExtent, -inExtent, -inExtent); FVector max = FVector(inExtent, inExtent, inExtent); FBox NewBounds = FBox(min, max); OctreeData = new FSimpleOctree(NewBounds.GetCenter(), NewBounds.GetExtent().GetMax()); // const FVector & InOrigin, float InExtent }
void AStrategyHUD::DrawHealthBar(AActor* ForActor, float HealthPercentage, int32 BarHeight, int32 OffsetY) const { FBox BB = ForActor->GetComponentsBoundingBox(); FVector Center = BB.GetCenter(); FVector Extent = BB.GetExtent(); FVector2D Center2D = FVector2D(Canvas->Project(FVector(Center.X,Center.Y,Center.Z + Extent.Z))); float ActorExtent = 40; if (Cast<APawn>(ForActor) != NULL) { AStrategyChar* StrategyChar = Cast<AStrategyChar>(ForActor); if( ( StrategyChar != NULL ) && ( StrategyChar->GetCapsuleComponent() != NULL ) ) { ActorExtent = StrategyChar->GetCapsuleComponent()->GetScaledCapsuleRadius(); } } else if (Cast<AStrategyBuilding>(ForActor) != NULL) { Center2D = FVector2D(Canvas->Project(ForActor->GetActorLocation())); ActorExtent = 60; } FVector Pos1 = Canvas->Project(FVector(Center.X,Center.Y - ActorExtent*2, Center.Z + Extent.Z)); FVector Pos2 = Canvas->Project(FVector(Center.X,Center.Y + ActorExtent*2, Center.Z + Extent.Z)); float HealthBarLength = (Pos2-Pos1).Size2D(); AStrategyPlayerController* MyPC = GetPlayerController(); IStrategyTeamInterface* ActorTeam = Cast<IStrategyTeamInterface>(ForActor); UTexture2D* HealthBarTexture = EnemyTeamHPTexture; if (ActorTeam != NULL && MyPC != NULL && ActorTeam->GetTeamNum() == MyPC->GetTeamNum()) { HealthBarTexture = PlayerTeamHPTexture; } float X = Center2D.X - HealthBarLength/2; float Y = Center2D.Y + OffsetY; FCanvasTileItem TileItem( FVector2D( X, Y ), HealthBarTexture->Resource, FVector2D( HealthBarLength * HealthPercentage, BarHeight ), FLinearColor::White ); TileItem.BlendMode = SE_BLEND_Translucent; TileItem.UV1 = FVector2D(HealthPercentage, 1.0f); Canvas->DrawItem( TileItem ); //Fill the rest of health with gray gradient texture X = Center2D.X-HealthBarLength/2 + HealthBarLength * HealthPercentage; Y = Center2D.Y + OffsetY; TileItem.Position = FVector2D( X, Y ); TileItem.Texture = BarFillTexture->Resource; TileItem.UV1 = FVector2D(1.0f, 1.0f); TileItem.Size = FVector2D( HealthBarLength * (1.0f - HealthPercentage), BarHeight ); TileItem.SetColor(FLinearColor(0.5f, 0.5f, 0.5f, 0.5f)); Canvas->DrawItem( TileItem ); }
FBox FWorldTileModel::GetLevelBounds() const { // Level local bounding box FBox Bounds = TileDetails->Bounds; if (Bounds.IsValid) { // Current level position in the world FVector LevelPosition(GetLevelCurrentPosition(), 0.f); FVector LevelExtent = Bounds.GetExtent(); // Calculate bounding box in world space Bounds.Min = LevelPosition - LevelExtent; Bounds.Max = LevelPosition + LevelExtent; } return Bounds; }
FPhATEdPreviewViewportClient::FPhATEdPreviewViewportClient(TWeakPtr<FPhAT> InPhAT, TSharedPtr<FPhATSharedData> Data, const TSharedRef<SPhATPreviewViewport>& InPhATPreviewViewport) : FEditorViewportClient(nullptr, &Data->PreviewScene, StaticCastSharedRef<SEditorViewport>(InPhATPreviewViewport)) , PhATPtr(InPhAT) , SharedData(Data) , MinPrimSize(0.5f) , PhAT_TranslateSpeed(0.25f) , PhAT_RotateSpeed(1.0 * (PI / 180.0)) , PhAT_LightRotSpeed(0.22f) , SimGrabCheckDistance(5000.0f) , SimHoldDistanceChangeDelta(20.0f) , SimMinHoldDistance(10.0f) , SimGrabMoveSpeed(1.0f) { check(PhATPtr.IsValid()); ModeTools->SetWidgetMode(FWidget::EWidgetMode::WM_Translate); ModeTools->SetCoordSystem(COORD_Local); bAllowedToMoveCamera = true; // Setup defaults for the common draw helper. DrawHelper.bDrawPivot = false; DrawHelper.bDrawWorldBox = false; DrawHelper.bDrawKillZ = false; DrawHelper.GridColorAxis = FColor(80,80,80); DrawHelper.GridColorMajor = FColor(72,72,72); DrawHelper.GridColorMinor = FColor(64,64,64); DrawHelper.PerspectiveGridSize = 32767; PhATFont = GEngine->GetSmallFont(); check(PhATFont); EngineShowFlags.DisableAdvancedFeatures(); EngineShowFlags.SetSeparateTranslucency(true); EngineShowFlags.SetCompositeEditorPrimitives(true); // Get actors asset collision bounding box, and move actor so its not intersection the floor plane at Z = 0. FBox CollBox = SharedData->PhysicsAsset->CalcAABB(SharedData->EditorSkelComp, SharedData->EditorSkelComp->ComponentToWorld); FVector SkelCompLocation = FVector(0, 0, -CollBox.Min.Z + SharedData->EditorSimOptions->FloorGap); SharedData->EditorSkelComp->SetAbsolute(true, true, true); SharedData->EditorSkelComp->SetRelativeLocation(SkelCompLocation); SharedData->ResetTM = SharedData->EditorSkelComp->GetComponentToWorld(); // Get new bounding box and set view based on that. CollBox = SharedData->PhysicsAsset->CalcAABB(SharedData->EditorSkelComp, SharedData->EditorSkelComp->ComponentToWorld); FVector CollBoxExtent = CollBox.GetExtent(); // Take into account internal mesh translation/rotation/scaling etc. FTransform LocalToWorld = SharedData->EditorSkelComp->ComponentToWorld; FSphere WorldSphere = SharedData->EditorSkelMesh->GetImportedBounds().GetSphere().TransformBy(LocalToWorld); CollBoxExtent = CollBox.GetExtent(); if (CollBoxExtent.X > CollBoxExtent.Y) { SetViewLocation( FVector(WorldSphere.Center.X, WorldSphere.Center.Y - 1.5*WorldSphere.W, WorldSphere.Center.Z) ); SetViewRotation( EditorViewportDefs::DefaultPerspectiveViewRotation ); } else { SetViewLocation( FVector(WorldSphere.Center.X - 1.5*WorldSphere.W, WorldSphere.Center.Y, WorldSphere.Center.Z) ); SetViewRotation( FRotator::ZeroRotator ); } SetViewLocationForOrbiting(FVector::ZeroVector); SetViewModes(VMI_Lit, VMI_Lit); SetCameraSpeedSetting(3); bUsingOrbitCamera = true; if (!FPhAT::IsPIERunning()) { SetRealtime(true); } }
void FVertexSnappingImpl::GetActorsInsideBox( const FBox& Box, UWorld* World, TArray<FSnapActor>& OutActorsInBox, const TSet< TWeakObjectPtr<AActor> >& ActorsToIgnore, const FSceneView* View ) { for( FActorIterator It(World); It; ++It ) { AActor* Actor = *It; // Ignore the builder brush, hidden actors and forcefully ignored actors (actors being moved) if( Actor != World->GetDefaultBrush() && It->IsHiddenEd() == false && !ActorsToIgnore.Contains( Actor ) ) { const bool bNonColliding = true; FBox ActorBoundingBox = Actor->GetComponentsBoundingBox(true); // Actors must be within the bounding box and within the view frustum if( Box.Intersect( ActorBoundingBox ) && View->ViewFrustum.IntersectBox( ActorBoundingBox.GetCenter(), ActorBoundingBox.GetExtent() ) ) { OutActorsInBox.Add( FSnapActor( Actor, Box ) ); } } } }
static void UpdatePlanarReflectionContents_RenderThread( FRHICommandListImmediate& RHICmdList, FSceneRenderer* MainSceneRenderer, FSceneRenderer* SceneRenderer, const FPlanarReflectionSceneProxy* SceneProxy, FRenderTarget* RenderTarget, FTexture* RenderTargetTexture, const FPlane& MirrorPlane, const FName OwnerName, const FResolveParams& ResolveParams, bool bUseSceneColorTexture) { QUICK_SCOPE_CYCLE_COUNTER(STAT_RenderPlanarReflection); FBox PlanarReflectionBounds = SceneProxy->WorldBounds; bool bIsInAnyFrustum = false; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (View.ViewFrustum.IntersectBox(PlanarReflectionBounds.GetCenter(), PlanarReflectionBounds.GetExtent())) { bIsInAnyFrustum = true; break; } } if (bIsInAnyFrustum) { bool bIsVisibleInAnyView = true; for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; FSceneViewState* ViewState = View.ViewState; if (ViewState) { FIndividualOcclusionHistory& OcclusionHistory = ViewState->PlanarReflectionOcclusionHistories.FindOrAdd(SceneProxy->PlanarReflectionId); // +1 to buffered frames because the query is submitted late into the main frame, but read at the beginning of a reflection capture frame const int32 NumBufferedFrames = FOcclusionQueryHelpers::GetNumBufferedFrames() + 1; // +1 to frame counter because we are operating before the main view's InitViews, which is where OcclusionFrameCounter is incremented uint32 OcclusionFrameCounter = ViewState->OcclusionFrameCounter + 1; FRenderQueryRHIRef& PastQuery = OcclusionHistory.GetPastQuery(OcclusionFrameCounter, NumBufferedFrames); if (IsValidRef(PastQuery)) { uint64 NumSamples = 0; QUICK_SCOPE_CYCLE_COUNTER(STAT_PlanarReflectionOcclusionQueryResults); if (RHIGetRenderQueryResult(PastQuery.GetReference(), NumSamples, true)) { bIsVisibleInAnyView = NumSamples > 0; if (bIsVisibleInAnyView) { break; } } } } } if (bIsVisibleInAnyView) { FMemMark MemStackMark(FMemStack::Get()); // update any resources that needed a deferred update FDeferredUpdateResource::UpdateResources(RHICmdList); { #if WANTS_DRAW_MESH_EVENTS FString EventName; OwnerName.ToString(EventName); SCOPED_DRAW_EVENTF(RHICmdList, SceneCapture, TEXT("PlanarReflection %s"), *EventName); #else SCOPED_DRAW_EVENT(RHICmdList, UpdatePlanarReflectionContent_RenderThread); #endif const FRenderTarget* Target = SceneRenderer->ViewFamily.RenderTarget; SetRenderTarget(RHICmdList, Target->GetRenderTargetTexture(), NULL, true); // Note: relying on GBuffer SceneColor alpha being cleared to 1 in the main scene rendering check(GetSceneColorClearAlpha() == 1.0f); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 1), false, (float)ERHIZBuffer::FarPlane, false, 0, FIntRect()); // Reflection view late update if (SceneRenderer->Views.Num() > 1) { const FMirrorMatrix MirrorMatrix(MirrorPlane); for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& ReflectionViewToUpdate = SceneRenderer->Views[ViewIndex]; const FViewInfo& UpdatedParentView = MainSceneRenderer->Views[ViewIndex]; ReflectionViewToUpdate.UpdatePlanarReflectionViewMatrix(UpdatedParentView, MirrorMatrix); } } // Render the scene normally { SCOPED_DRAW_EVENT(RHICmdList, RenderScene); SceneRenderer->Render(RHICmdList); } for (int32 ViewIndex = 0; ViewIndex < SceneRenderer->Views.Num(); ++ViewIndex) { FViewInfo& View = SceneRenderer->Views[ViewIndex]; if (MainSceneRenderer->Scene->GetShadingPath() == EShadingPath::Deferred) { PrefilterPlanarReflection<true>(RHICmdList, View, SceneProxy, Target); } else { PrefilterPlanarReflection<false>(RHICmdList, View, SceneProxy, Target); } } RHICmdList.CopyToResolveTarget(RenderTarget->GetRenderTargetTexture(), RenderTargetTexture->TextureRHI, false, ResolveParams); } FSceneRenderer::WaitForTasksClearSnapshotsAndDeleteSceneRenderer(RHICmdList, SceneRenderer); } } }
void FLogVisualizer::UpdateCameraPosition(FName RowName, int32 ItemIndes) { const FVisualLoggerDBRow& DBRow = FVisualLoggerDatabase::Get().GetRowByName(RowName); auto &Entries = DBRow.GetItems(); if (DBRow.GetCurrentItemIndex() == INDEX_NONE || Entries.IsValidIndex(DBRow.GetCurrentItemIndex()) == false) { return; } UWorld* World = GetWorld(); FVector CurrentLocation = Entries[DBRow.GetCurrentItemIndex()].Entry.Location; FVector Extent(150); bool bFoundActor = false; FName OwnerName = Entries[DBRow.GetCurrentItemIndex()].OwnerName; for (FActorIterator It(World); It; ++It) { AActor* Actor = *It; if (Actor->GetFName() == OwnerName) { FVector Orgin; Actor->GetActorBounds(false, Orgin, Extent); bFoundActor = true; break; } } const float DefaultCameraDistance = ULogVisualizerSettings::StaticClass()->GetDefaultObject<ULogVisualizerSettings>()->DefaultCameraDistance; Extent = Extent.SizeSquared() < FMath::Square(DefaultCameraDistance) ? FVector(DefaultCameraDistance) : Extent; #if WITH_EDITOR UEditorEngine *EEngine = Cast<UEditorEngine>(GEngine); if (GIsEditor && EEngine != NULL) { for (auto ViewportClient : EEngine->AllViewportClients) { ViewportClient->FocusViewportOnBox(FBox::BuildAABB(CurrentLocation, Extent)); } } else if (AVisualLoggerCameraController::IsEnabled(World) && AVisualLoggerCameraController::Instance.IsValid() && AVisualLoggerCameraController::Instance->GetSpectatorPawn()) { ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(AVisualLoggerCameraController::Instance->Player); if (LocalPlayer && LocalPlayer->ViewportClient && LocalPlayer->ViewportClient->Viewport) { FViewport* Viewport = LocalPlayer->ViewportClient->Viewport; FBox BoundingBox = FBox::BuildAABB(CurrentLocation, Extent); const FVector Position = BoundingBox.GetCenter(); float Radius = BoundingBox.GetExtent().Size(); FViewportCameraTransform ViewTransform; ViewTransform.TransitionToLocation(Position, nullptr, true); float NewOrthoZoom; const float AspectRatio = 1.777777f; CA_SUPPRESS(6326); uint32 MinAxisSize = (AspectRatio > 1.0f) ? Viewport->GetSizeXY().Y : Viewport->GetSizeXY().X; float Zoom = Radius / (MinAxisSize / 2.0f); NewOrthoZoom = Zoom * (Viewport->GetSizeXY().X*15.0f); NewOrthoZoom = FMath::Clamp<float>(NewOrthoZoom, 250, MAX_FLT); ViewTransform.SetOrthoZoom(NewOrthoZoom); AVisualLoggerCameraController::Instance->GetSpectatorPawn()->TeleportTo(ViewTransform.GetLocation(), ViewTransform.GetRotation(), false, true); } } #endif }
/** * Returns an array of visibility data for the given view position, or NULL if none exists. * The data bits are indexed by VisibilityId of each primitive in the scene. * This method decompresses data if necessary and caches it based on the bucket and chunk index in the view state. */ const uint8* FSceneViewState::GetPrecomputedVisibilityData(FViewInfo& View, const FScene* Scene) { const uint8* PrecomputedVisibilityData = NULL; if (Scene->PrecomputedVisibilityHandler && GAllowPrecomputedVisibility && View.Family->EngineShowFlags.PrecomputedVisibility) { const FPrecomputedVisibilityHandler& Handler = *Scene->PrecomputedVisibilityHandler; FViewElementPDI VisibilityCellsPDI(&View, NULL); // Draw visibility cell bounds for debugging if enabled if ((GShowPrecomputedVisibilityCells || View.Family->EngineShowFlags.PrecomputedVisibilityCells) && !GShowRelevantPrecomputedVisibilityCells) { for (int32 BucketIndex = 0; BucketIndex < Handler.PrecomputedVisibilityCellBuckets.Num(); BucketIndex++) { for (int32 CellIndex = 0; CellIndex < Handler.PrecomputedVisibilityCellBuckets[BucketIndex].Cells.Num(); CellIndex++) { const FPrecomputedVisibilityCell& CurrentCell = Handler.PrecomputedVisibilityCellBuckets[BucketIndex].Cells[CellIndex]; // Construct the cell's bounds const FBox CellBounds(CurrentCell.Min, CurrentCell.Min + FVector(Handler.PrecomputedVisibilityCellSizeXY, Handler.PrecomputedVisibilityCellSizeXY, Handler.PrecomputedVisibilityCellSizeZ)); if (View.ViewFrustum.IntersectBox(CellBounds.GetCenter(), CellBounds.GetExtent())) { DrawWireBox(&VisibilityCellsPDI, CellBounds, FColor(50, 50, 255), SDPG_World); } } } } // Calculate the bucket that ViewOrigin falls into // Cells are hashed into buckets to reduce search time const float FloatOffsetX = (View.ViewMatrices.ViewOrigin.X - Handler.PrecomputedVisibilityCellBucketOriginXY.X) / Handler.PrecomputedVisibilityCellSizeXY; // FMath::TruncToInt rounds toward 0, we want to always round down const int32 BucketIndexX = FMath::Abs((FMath::TruncToInt(FloatOffsetX) - (FloatOffsetX < 0.0f ? 1 : 0)) / Handler.PrecomputedVisibilityCellBucketSizeXY % Handler.PrecomputedVisibilityNumCellBuckets); const float FloatOffsetY = (View.ViewMatrices.ViewOrigin.Y -Handler.PrecomputedVisibilityCellBucketOriginXY.Y) / Handler.PrecomputedVisibilityCellSizeXY; const int32 BucketIndexY = FMath::Abs((FMath::TruncToInt(FloatOffsetY) - (FloatOffsetY < 0.0f ? 1 : 0)) / Handler.PrecomputedVisibilityCellBucketSizeXY % Handler.PrecomputedVisibilityNumCellBuckets); const int32 PrecomputedVisibilityBucketIndex = BucketIndexY * Handler.PrecomputedVisibilityCellBucketSizeXY + BucketIndexX; check(PrecomputedVisibilityBucketIndex < Handler.PrecomputedVisibilityCellBuckets.Num()); const FPrecomputedVisibilityBucket& CurrentBucket = Handler.PrecomputedVisibilityCellBuckets[PrecomputedVisibilityBucketIndex]; for (int32 CellIndex = 0; CellIndex < CurrentBucket.Cells.Num(); CellIndex++) { const FPrecomputedVisibilityCell& CurrentCell = CurrentBucket.Cells[CellIndex]; // Construct the cell's bounds const FBox CellBounds(CurrentCell.Min, CurrentCell.Min + FVector(Handler.PrecomputedVisibilityCellSizeXY, Handler.PrecomputedVisibilityCellSizeXY, Handler.PrecomputedVisibilityCellSizeZ)); // Check if ViewOrigin is inside the current cell if (CellBounds.IsInside(View.ViewMatrices.ViewOrigin)) { // Reuse a cached decompressed chunk if possible if (CachedVisibilityChunk && CachedVisibilityHandlerId == Scene->PrecomputedVisibilityHandler->GetId() && CachedVisibilityBucketIndex == PrecomputedVisibilityBucketIndex && CachedVisibilityChunkIndex == CurrentCell.ChunkIndex) { checkSlow(CachedVisibilityChunk->Num() >= CurrentCell.DataOffset + CurrentBucket.CellDataSize); PrecomputedVisibilityData = &(*CachedVisibilityChunk)[CurrentCell.DataOffset]; } else { const FCompressedVisibilityChunk& CompressedChunk = Handler.PrecomputedVisibilityCellBuckets[PrecomputedVisibilityBucketIndex].CellDataChunks[CurrentCell.ChunkIndex]; CachedVisibilityBucketIndex = PrecomputedVisibilityBucketIndex; CachedVisibilityChunkIndex = CurrentCell.ChunkIndex; CachedVisibilityHandlerId = Scene->PrecomputedVisibilityHandler->GetId(); if (CompressedChunk.bCompressed) { // Decompress the needed visibility data chunk DecompressedVisibilityChunk.Reset(); DecompressedVisibilityChunk.AddUninitialized(CompressedChunk.UncompressedSize); verify(FCompression::UncompressMemory( COMPRESS_ZLIB, DecompressedVisibilityChunk.GetData(), CompressedChunk.UncompressedSize, CompressedChunk.Data.GetData(), CompressedChunk.Data.Num())); CachedVisibilityChunk = &DecompressedVisibilityChunk; } else { CachedVisibilityChunk = &CompressedChunk.Data; } checkSlow(CachedVisibilityChunk->Num() >= CurrentCell.DataOffset + CurrentBucket.CellDataSize); // Return a pointer to the cell containing ViewOrigin's decompressed visibility data PrecomputedVisibilityData = &(*CachedVisibilityChunk)[CurrentCell.DataOffset]; } if (GShowRelevantPrecomputedVisibilityCells) { // Draw the currently used visibility cell with green wireframe for debugging DrawWireBox(&VisibilityCellsPDI, CellBounds, FColor(50, 255, 50), SDPG_Foreground); } else { break; } } else if (GShowRelevantPrecomputedVisibilityCells) { // Draw all cells in the current visibility bucket as blue wireframe DrawWireBox(&VisibilityCellsPDI, CellBounds, FColor(50, 50, 255), SDPG_World); } } } return PrecomputedVisibilityData; }
void ASpacePartioner::Initialize(const FBox& inNewBounds, const bool& inDrawDebugInfo) { bInitialized = true; bDrawDebugInfo = inDrawDebugInfo; OctreeData = new FSimpleOctree(inNewBounds.GetCenter(), inNewBounds.GetExtent().GetMax()); // const FVector & InOrigin, float InExtent }
void AGameplayDebuggerReplicator::DrawDebugData(class UCanvas* Canvas, class APlayerController* PC, bool bHideMenu) { #if ENABLED_GAMEPLAY_DEBUGGER if (!LocalPlayerOwner && IsActorTickEnabled()) { return; } const bool bAllowToDraw = Canvas && Canvas->SceneView && (Canvas->SceneView->ViewActor == LocalPlayerOwner->AcknowledgedPawn || Canvas->SceneView->ViewActor == LocalPlayerOwner->GetPawnOrSpectator()); if (!bAllowToDraw) { // check for spectator debug camera during debug camera if (DebugCameraController.IsValid() == false || Canvas->SceneView->ViewActor->GetInstigatorController() != DebugCameraController.Get()) { return; } } const float DebugInfoStartX = UGameplayDebuggerModuleSettings::StaticClass()->GetDefaultObject<UGameplayDebuggerModuleSettings>()->DebugInfoStart.X; const float DebugInfoStartY = UGameplayDebuggerModuleSettings::StaticClass()->GetDefaultObject<UGameplayDebuggerModuleSettings>()->DebugInfoStart.Y; const FVector SelectedActorLoc = LastSelectedActorToDebug ? LastSelectedActorToDebug->GetActorLocation() + FVector(0, 0, LastSelectedActorToDebug->GetSimpleCollisionHalfHeight()) : DebugTools::InvalidLocation; UGameplayDebuggerHelper::FPrintContext DefaultContext(GEngine->GetSmallFont(), Canvas, DebugInfoStartX, DebugInfoStartY); DefaultContext.FontRenderInfo.bEnableShadow = true; const bool bDrawFullData = SelectedActorLoc != DebugTools::InvalidLocation; const FVector ScreenLoc = SelectedActorLoc != DebugTools::InvalidLocation ? UGameplayDebuggerHelper::ProjectLocation(DefaultContext, SelectedActorLoc) : FVector::ZeroVector; UGameplayDebuggerHelper::FPrintContext OverHeadContext(GEngine->GetSmallFont(), Canvas, ScreenLoc.X, ScreenLoc.Y); UGameplayDebuggerHelper::SetOverHeadContext(OverHeadContext); UGameplayDebuggerHelper::SetDefaultContext(DefaultContext); if (DefaultContext.Canvas != nullptr) { float XL, YL; const FString ToolName = FString::Printf(TEXT("Gameplay Debugger [Timestamp: %05.03f]"), GetWorld()->TimeSeconds); UGameplayDebuggerHelper::CalulateStringSize(DefaultContext, nullptr, ToolName, XL, YL); UGameplayDebuggerHelper::PrintString(DefaultContext, FColorList::White, ToolName, DefaultContext.Canvas->ClipX / 2.0f - XL / 2.0f, 0); } if (!bHideMenu) { DrawMenu(DefaultContext, OverHeadContext); } TMap<FString, TArray<UGameplayDebuggerBaseObject*> > CategoryToClasses; for (UGameplayDebuggerBaseObject* Obj : ReplicatedObjects) { if (Obj) { FString Category = Obj->GetCategoryName(); CategoryToClasses.FindOrAdd(Category).Add(Obj); } } CategoryToClasses.KeySort(TLess<FString>()); for (auto It(CategoryToClasses.CreateIterator()); It; ++It) { const FGameplayDebuggerCategorySettings* Element = Categories.FindByPredicate([&](const FGameplayDebuggerCategorySettings& C){ return It.Key() == C.CategoryName; }); if (Element == nullptr || Element->bPIE == false) { continue; } UGameplayDebuggerHelper::PrintString(UGameplayDebuggerHelper::GetDefaultContext(), FString::Printf(TEXT("\n{R=0,G=255,B=0,A=255}%s\n"), *It.Key())); TArray<UGameplayDebuggerBaseObject*>& CurrentObjects = It.Value(); for (UGameplayDebuggerBaseObject* Obj : CurrentObjects) { Obj->DrawCollectedData(LocalPlayerOwner, LastSelectedActorToDebug); } } const IConsoleVariable* cvarHighlightSelectedActor = IConsoleManager::Get().FindConsoleVariable(TEXT("ai.gd.HighlightSelectedActor")); const bool bHighlightSelectedActor = !cvarHighlightSelectedActor || cvarHighlightSelectedActor->GetInt(); if (LastSelectedActorToDebug && bHighlightSelectedActor) { FBox ComponentsBoundingBox = LastSelectedActorToDebug->GetComponentsBoundingBox(false); DrawDebugBox(GetWorld(), ComponentsBoundingBox.GetCenter(), ComponentsBoundingBox.GetExtent(), FColor::Red, false); DrawDebugSolidBox(GetWorld(), ComponentsBoundingBox.GetCenter(), ComponentsBoundingBox.GetExtent(), FColor::Red.WithAlpha(25)); } #endif }
void AHUD::GetActorsInSelectionRectangle(TSubclassOf<class AActor> ClassFilter, const FVector2D& FirstPoint, const FVector2D& SecondPoint, TArray<AActor*>& OutActors, bool bIncludeNonCollidingComponents, bool bActorMustBeFullyEnclosed) { // Because this is a HUD function it is likely to get called each tick, // so make sure any previous contents of the out actor array have been cleared! OutActors.Reset(); //Create Selection Rectangle from Points FBox2D SelectionRectangle(0); //This method ensures that an appropriate rectangle is generated, // no matter what the coordinates of first and second point actually are. SelectionRectangle += FirstPoint; SelectionRectangle += SecondPoint; //The Actor Bounds Point Mapping const FVector BoundsPointMapping[8] = { FVector(1, 1, 1), FVector(1, 1, -1), FVector(1, -1, 1), FVector(1, -1, -1), FVector(-1, 1, 1), FVector(-1, 1, -1), FVector(-1, -1, 1), FVector(-1, -1, -1) }; //~~~ //For Each Actor of the Class Filter Type for (TActorIterator<AActor> Itr(GetWorld(), ClassFilter); Itr; ++Itr) { AActor* EachActor = *Itr; //Get Actor Bounds //casting to base class, checked by template in the .h const FBox EachActorBounds = Cast<AActor>(EachActor)->GetComponentsBoundingBox(bIncludeNonCollidingComponents); /* All Components? */ //Center const FVector BoxCenter = EachActorBounds.GetCenter(); //Extents const FVector BoxExtents = EachActorBounds.GetExtent(); // Build 2D bounding box of actor in screen space FBox2D ActorBox2D(0); for (uint8 BoundsPointItr = 0; BoundsPointItr < 8; BoundsPointItr++) { // Project vert into screen space. const FVector ProjectedWorldLocation = Project(BoxCenter + (BoundsPointMapping[BoundsPointItr] * BoxExtents)); // Add to 2D bounding box ActorBox2D += FVector2D(ProjectedWorldLocation.X, ProjectedWorldLocation.Y); } //Selection Box must fully enclose the Projected Actor Bounds if (bActorMustBeFullyEnclosed) { if(SelectionRectangle.IsInside(ActorBox2D)) { OutActors.Add(Cast<AActor>(EachActor)); } } //Partial Intersection with Projected Actor Bounds else { if (SelectionRectangle.Intersect(ActorBox2D)) { OutActors.Add(Cast<AActor>(EachActor)); } } } }