Add Planar Capture System implementation checklist and developer reference
- Created a comprehensive implementation checklist for the Planar Capture System (Systems 136-147) detailing tasks across multiple phases including C++ core, material foundation, Blueprint actors, data assets, integration, and performance testing. - Added a developer reference document outlining the architecture, data flow, state machine, budget enforcement, render target pooling, horror features, integration points, multiplayer networking, performance characteristics, debugging methods, and build order for the capture systems. - Introduced examples of capture surface usage in the Project Void horror game, including specific implementations for mirrors, monitors, portals, and fake windows, along with a checklist for integration tasks.
This commit is contained in:
278
Source/PG_Framework/Public/Capture/BPC_PlanarCapture.h
Normal file
278
Source/PG_Framework/Public/Capture/BPC_PlanarCapture.h
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright Ngonart OU. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — BPC_PlanarCapture (136)
|
||||
// The heart of the Planar Capture System. Attached to any actor that needs
|
||||
// a scene capture — mirrors, portals, monitors, horror surfaces.
|
||||
//
|
||||
// Manages USceneCaptureComponent2D lifetime, render target pool allocation,
|
||||
// camera transform computation per mode, oblique clip plane injection,
|
||||
// show/hide actor lists, quality tier application, frame ring buffer,
|
||||
// and MPC parameter pushes.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Capture/PlanarCaptureCommon.h"
|
||||
#include "BPC_PlanarCapture.generated.h"
|
||||
|
||||
// Forward declarations
|
||||
class USceneCaptureComponent2D;
|
||||
class UTextureRenderTarget2D;
|
||||
class UMaterialInstanceDynamic;
|
||||
class UMaterialParameterCollection;
|
||||
class ASS_PlanarCaptureManager;
|
||||
class ABP_PlanarCaptureActor;
|
||||
|
||||
// ============================================================================
|
||||
// Delegates
|
||||
// ============================================================================
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnCaptureQualityChanged, EPlanarCaptureQualityTier, OldTier, EPlanarCaptureQualityTier, NewTier);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnCaptureInitialized, EPlanarCaptureInitResult, Result);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCaptureRendered);
|
||||
|
||||
/**
|
||||
* BPC_PlanarCapture — Core capture component for mirrors, portals, monitors, etc.
|
||||
*
|
||||
* Owns the USceneCaptureComponent2D lifecycle. All camera math, render target
|
||||
* management, and per-frame capture decisions happen here in C++ for performance.
|
||||
* Designer configuration flows through Blueprint children.
|
||||
*
|
||||
* Multiplayer: Capture is always local-only. Each client renders their own view.
|
||||
* No replication needed. This component only exists on clients.
|
||||
*/
|
||||
UCLASS(Blueprintable, ClassGroup = (Framework), meta = (BlueprintSpawnableComponent))
|
||||
class PG_FRAMEWORK_API UBPC_PlanarCapture : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UBPC_PlanarCapture();
|
||||
|
||||
// ========================================================================
|
||||
// Lifecycle
|
||||
// ========================================================================
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
|
||||
FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
// ========================================================================
|
||||
// Configuration — Set in Blueprint Defaults
|
||||
// ========================================================================
|
||||
|
||||
/** What kind of surface this capture represents. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
EPlanarCaptureMode CaptureMode = EPlanarCaptureMode::Mirror;
|
||||
|
||||
/** Quality profiles per tier (0=Low, 1=Medium, 2=High, 3=Hero). Index maps to EPlanarCaptureQualityTier. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
TArray<FPlanarCaptureQualityProfile> QualityProfiles;
|
||||
|
||||
/** FOV for the capture camera. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
float CaptureFOV = 90.0f;
|
||||
|
||||
/** Maximum view distance for the capture (0 = unlimited). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
float MaxViewDistance = 5000.0f;
|
||||
|
||||
// ========================================================================
|
||||
// Portal Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** For Portal mode: the linked target surface actor. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Portal")
|
||||
TSoftObjectPtr<ABP_PlanarCaptureActor> LinkedTargetSurface;
|
||||
|
||||
// ========================================================================
|
||||
// Monitor Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** For Monitor mode: a fixed camera actor to capture from. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Monitor")
|
||||
TSoftObjectPtr<AActor> FixedCameraActor;
|
||||
|
||||
// ========================================================================
|
||||
// Actor Lists
|
||||
// ========================================================================
|
||||
|
||||
/** Actors to show exclusively in the capture (empty = show all). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorLists")
|
||||
TArray<FPlanarCaptureActorListEntry> ShowOnlyActors;
|
||||
|
||||
/** Actors to hide from the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorLists")
|
||||
TArray<FPlanarCaptureActorListEntry> HiddenActors;
|
||||
|
||||
// ========================================================================
|
||||
// Horror Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** Actor to swap into the ShowOnly list during wrong-reflection events. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Horror")
|
||||
TSoftObjectPtr<AActor> WrongReflectionActor;
|
||||
|
||||
/** Mesh component of the surface plane (for clip plane calculation). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Config")
|
||||
TSoftObjectPtr<UStaticMeshComponent> SurfaceMeshComponent;
|
||||
|
||||
// ========================================================================
|
||||
// Runtime State (Read-Only)
|
||||
// ========================================================================
|
||||
|
||||
/** Current assigned quality tier (set by SS_PlanarCaptureManager). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
|
||||
EPlanarCaptureQualityTier CurrentQualityTier = EPlanarCaptureQualityTier::Off;
|
||||
|
||||
/** Is this capture currently active (capturing frames)? */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
|
||||
bool bIsCapturing = false;
|
||||
|
||||
/** The render target this capture writes to. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
|
||||
TObjectPtr<UTextureRenderTarget2D> CaptureRenderTarget;
|
||||
|
||||
// ========================================================================
|
||||
// Public API — BlueprintCallable
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Initialize the capture component. Allocates render target, creates and
|
||||
* configures the USceneCaptureComponent2D. Called by the owning actor on BeginPlay.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
EPlanarCaptureInitResult InitializeCapture();
|
||||
|
||||
/**
|
||||
* Shut down the capture, release render target back to pool, destroy SceneCaptureComponent2D.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void ShutdownCapture();
|
||||
|
||||
/**
|
||||
* Apply a quality tier profile immediately. Called by SS_PlanarCaptureManager.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void ApplyQualityTier(EPlanarCaptureQualityTier Tier);
|
||||
|
||||
/**
|
||||
* Trigger a single capture frame immediately (bypasses tick interval).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void CaptureNow();
|
||||
|
||||
/**
|
||||
* Swap the ShowOnly actor list to the wrong-reflection actor (horror mode).
|
||||
* Original list is preserved and restored on DeactivateHorrorReflection().
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
|
||||
void ActivateHorrorReflection();
|
||||
|
||||
/**
|
||||
* Restore the original ShowOnly actor list after a horror event.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
|
||||
void DeactivateHorrorReflection();
|
||||
|
||||
/**
|
||||
* Push a frame from the ring buffer into the render target for delayed reflection (horror lag).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Horror")
|
||||
void PushDelayedFrame();
|
||||
|
||||
/**
|
||||
* Set a scripted priority override (0.0 to 1.0). Higher values force higher quality tier.
|
||||
* Example: a scare event elevates a specific mirror to Hero tier.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void SetScriptedPriority(float Priority);
|
||||
|
||||
/**
|
||||
* Push all Material Parameter Collection values for this surface.
|
||||
* Called every frame when capturing, or on event trigger for horror params.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Material")
|
||||
void PushMPCParameters(UMaterialParameterCollection* MPC);
|
||||
|
||||
// ========================================================================
|
||||
// Compute — BlueprintPure
|
||||
// ========================================================================
|
||||
|
||||
/** Compute the capture camera transform for the current mode. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture")
|
||||
FTransform ComputeCaptureCameraTransform(const FTransform& ViewerCameraTransform) const;
|
||||
|
||||
/** Get the current composite quality score. */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture")
|
||||
FPlanarCaptureScore GetCurrentScore() const;
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
|
||||
FOnCaptureQualityChanged OnCaptureQualityChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
|
||||
FOnCaptureInitialized OnCaptureInitialized;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
|
||||
FOnCaptureRendered OnCaptureRendered;
|
||||
|
||||
protected:
|
||||
// ========================================================================
|
||||
// Internal State
|
||||
// ========================================================================
|
||||
|
||||
/** The actual UE5 SceneCaptureComponent2D — created at runtime. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<USceneCaptureComponent2D> SceneCapture;
|
||||
|
||||
/** Cached reference to the manager subsystem. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<ASS_PlanarCaptureManager> CachedManager;
|
||||
|
||||
/** Cached reference to the owning actor. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<ABP_PlanarCaptureActor> CachedOwningActor;
|
||||
|
||||
/** Time accumulator for capture interval throttling. */
|
||||
float TimeSinceLastCapture = 0.0f;
|
||||
|
||||
/** Current quality profile (cached from QualityProfiles[Tier]). */
|
||||
FPlanarCaptureQualityProfile ActiveProfile;
|
||||
|
||||
/** Scripted priority override (0.0 to 1.0). */
|
||||
float ScriptedPriorityOverride = 0.0f;
|
||||
|
||||
/** Ring buffer of render targets for delayed reflection (horror mode). */
|
||||
UPROPERTY()
|
||||
TArray<TObjectPtr<UTextureRenderTarget2D>> FrameRingBuffer;
|
||||
|
||||
/** Current write index into the frame ring buffer. */
|
||||
int32 RingBufferWriteIndex = 0;
|
||||
|
||||
/** Saved ShowOnly list before horror swap. */
|
||||
TArray<TSoftObjectPtr<AActor>> SavedShowOnlyActors;
|
||||
|
||||
// ========================================================================
|
||||
// Internal Methods
|
||||
// ========================================================================
|
||||
|
||||
/** Create and configure the USceneCaptureComponent2D. */
|
||||
void CreateSceneCaptureComponent();
|
||||
|
||||
/** Apply show flags from the active quality profile to the SceneCapture. */
|
||||
void ApplyShowFlags();
|
||||
|
||||
/** Update the ShowOnly and Hidden actor lists on the SceneCapture. */
|
||||
void UpdateActorLists();
|
||||
|
||||
/** Resolve soft references on initialization. */
|
||||
void ResolveSoftReferences();
|
||||
|
||||
/** Compute the surface plane in world space for clip plane and mirror math. */
|
||||
FPlane GetSurfacePlane() const;
|
||||
};
|
||||
170
Source/PG_Framework/Public/Capture/BP_PlanarCaptureActor.h
Normal file
170
Source/PG_Framework/Public/Capture/BP_PlanarCaptureActor.h
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright Ngonart OU. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — BP_PlanarCaptureActor (137)
|
||||
// Placeable actor wrapping a BPC_PlanarCapture component. Owns the surface mesh,
|
||||
// material dynamic instances, and the capture component. Handles overlap/proximity
|
||||
// events feeding into the quality manager. Registers with the global subsystem.
|
||||
//
|
||||
// Blueprint children: BP_Mirror, BP_Portal, BP_Monitor, BP_HorrorMirror, BP_FakeWindow.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Capture/PlanarCaptureCommon.h"
|
||||
#include "BP_PlanarCaptureActor.generated.h"
|
||||
|
||||
class UBPC_PlanarCapture;
|
||||
class UStaticMeshComponent;
|
||||
class UMaterialInstanceDynamic;
|
||||
class UMaterialParameterCollection;
|
||||
class UBoxComponent;
|
||||
|
||||
// Delegates
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlanarCaptureActorModeChanged, EPlanarCaptureMode, NewMode);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPlanarCaptureSurfaceDestroyed, ABP_PlanarCaptureActor*, Surface);
|
||||
|
||||
/**
|
||||
* BP_PlanarCaptureActor — Placeable actor for mirrors, portals, monitors, etc.
|
||||
*
|
||||
* Blueprint children configure the mode, mesh, materials, and capture settings.
|
||||
* This actor is the designer-facing interface — all runtime logic lives in
|
||||
* BPC_PlanarCapture and SS_PlanarCaptureManager.
|
||||
*
|
||||
* Multiplayer: Spawned on all clients. Capture rendering is local-only.
|
||||
* Surface state (destroyed, on/off) may replicate via RepNotify.
|
||||
*/
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class PG_FRAMEWORK_API ABP_PlanarCaptureActor : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ABP_PlanarCaptureActor();
|
||||
|
||||
// ========================================================================
|
||||
// Components
|
||||
// ========================================================================
|
||||
|
||||
/** The surface mesh — a plane, quad, or frame. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
|
||||
TObjectPtr<UStaticMeshComponent> SurfaceMesh;
|
||||
|
||||
/** Proximity trigger volume for quality scoring. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
|
||||
TObjectPtr<UBoxComponent> ProximityTrigger;
|
||||
|
||||
/** The core capture component. */
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Capture|Components")
|
||||
TObjectPtr<UBPC_PlanarCapture> CaptureComponent;
|
||||
|
||||
// ========================================================================
|
||||
// Configuration
|
||||
// ========================================================================
|
||||
|
||||
/** Display name for debug and logging. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
FString SurfaceDisplayName;
|
||||
|
||||
/** Whether this surface starts enabled. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
bool bStartEnabled = true;
|
||||
|
||||
/** Whether this surface can be destroyed (shattered mirror, broken monitor). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Config")
|
||||
bool bDestructible = false;
|
||||
|
||||
/** Material Parameter Collection for global surface parameters. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Capture|Material")
|
||||
TObjectPtr<UMaterialParameterCollection> SurfaceMPC;
|
||||
|
||||
// ========================================================================
|
||||
// Runtime State
|
||||
// ========================================================================
|
||||
|
||||
/** Whether this surface is currently active. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
|
||||
bool bIsActive = false;
|
||||
|
||||
/** Dynamic material instance on the surface mesh. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Runtime")
|
||||
TObjectPtr<UMaterialInstanceDynamic> SurfaceMaterialInstance;
|
||||
|
||||
// ========================================================================
|
||||
// Public API
|
||||
// ========================================================================
|
||||
|
||||
/** Enable the capture surface. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void EnableSurface();
|
||||
|
||||
/** Disable the capture surface (stops rendering, releases budget). */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void DisableSurface();
|
||||
|
||||
/** Set the capture mode at runtime. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void SetCaptureMode(EPlanarCaptureMode NewMode);
|
||||
|
||||
/** Set the surface material at runtime (e.g., swap between clean/dirty mirror). */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void SetSurfaceMaterial(UMaterialInterface* NewMaterial);
|
||||
|
||||
/** Set a single MPC scalar parameter for this surface. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Material")
|
||||
void SetSurfaceMPCParameter(FName ParameterName, float Value);
|
||||
|
||||
/** Destroy the surface (shatter mirror, break monitor). Triggers visual effect. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture")
|
||||
void DestroySurface();
|
||||
|
||||
// ========================================================================
|
||||
// Overrides
|
||||
// ========================================================================
|
||||
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
|
||||
FOnPlanarCaptureActorModeChanged OnModeChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Events")
|
||||
FOnPlanarCaptureSurfaceDestroyed OnSurfaceDestroyed;
|
||||
|
||||
protected:
|
||||
// ========================================================================
|
||||
// Overlap Events (Proximity Trigger)
|
||||
// ========================================================================
|
||||
|
||||
UFUNCTION()
|
||||
void OnProximityBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
|
||||
|
||||
UFUNCTION()
|
||||
void OnProximityEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
|
||||
|
||||
// ========================================================================
|
||||
// RepNotify (multiplayer)
|
||||
// ========================================================================
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_IsActive();
|
||||
|
||||
/** Replicated active state for server-authoritative surface control. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_IsActive)
|
||||
bool bRepIsActive = false;
|
||||
|
||||
// ========================================================================
|
||||
// Internal
|
||||
// ========================================================================
|
||||
|
||||
/** Register with the global manager subsystem. */
|
||||
void RegisterWithManager();
|
||||
|
||||
/** Create the dynamic material instance from the surface mesh material. */
|
||||
void CreateMaterialInstance();
|
||||
};
|
||||
155
Source/PG_Framework/Public/Capture/PlanarCaptureCameraUtils.h
Normal file
155
Source/PG_Framework/Public/Capture/PlanarCaptureCameraUtils.h
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright Ngonart OU. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — PlanarCaptureCameraUtils
|
||||
// Static math library for mirror reflection, portal relative transform,
|
||||
// oblique projection, screen coverage, and visibility computations.
|
||||
// All functions are BlueprintCallable and use UE5's FMatrix/FVector/FPlane types.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "PlanarCaptureCameraUtils.generated.h"
|
||||
|
||||
/**
|
||||
* Static math library for planar capture camera transforms.
|
||||
*
|
||||
* Mirror: reflect the viewer camera across the mirror plane.
|
||||
* Portal: compute the relative transform from source surface to target surface.
|
||||
* All math happens in C++ for performance — Blueprint calls these as pure functions.
|
||||
*/
|
||||
UCLASS()
|
||||
class PG_FRAMEWORK_API UPlanarCaptureCameraUtils : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// ========================================================================
|
||||
// Mirror Reflection Math
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Compute the mirrored camera transform for a planar mirror.
|
||||
* Reflects the viewer's camera position and rotation across the mirror plane.
|
||||
*
|
||||
* @param ViewerCameraTransform World transform of the viewer's camera.
|
||||
* @param MirrorPlaneTransform World transform of the mirror surface (XY plane, Z = normal).
|
||||
* @return The world transform for the SceneCapture camera.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static FTransform ComputeMirroredTransform(
|
||||
const FTransform& ViewerCameraTransform,
|
||||
const FTransform& MirrorPlaneTransform);
|
||||
|
||||
// ========================================================================
|
||||
// Portal Relative Math
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Compute the capture camera transform for a portal.
|
||||
* The viewer's position relative to the source surface is mapped to the
|
||||
* target surface's coordinate space.
|
||||
*
|
||||
* @param ViewerCameraTransform World transform of the viewer's camera.
|
||||
* @param SourceSurfaceTransform World transform of the portal entry surface.
|
||||
* @param TargetSurfaceTransform World transform of the portal exit surface.
|
||||
* @return The world transform for the SceneCapture camera.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static FTransform ComputePortalTransform(
|
||||
const FTransform& ViewerCameraTransform,
|
||||
const FTransform& SourceSurfaceTransform,
|
||||
const FTransform& TargetSurfaceTransform);
|
||||
|
||||
// ========================================================================
|
||||
// Oblique Near-Plane Projection
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Compute an oblique near-clip-plane projection matrix.
|
||||
* Used to prevent geometry behind the portal/mirror surface from clipping
|
||||
* into the capture view.
|
||||
*
|
||||
* @param FOV Horizontal field of view in degrees.
|
||||
* @param AspectRatio Width / Height.
|
||||
* @param NearPlane Near clip distance.
|
||||
* @param FarPlane Far clip distance.
|
||||
* @param ClipPlane World-space plane to clip against.
|
||||
* @param SurfaceTransform Transform of the surface (for converting clip plane to view space).
|
||||
* @return The oblique projection matrix.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static FMatrix ComputeObliqueProjectionMatrix(
|
||||
float FOV,
|
||||
float AspectRatio,
|
||||
float NearPlane,
|
||||
float FarPlane,
|
||||
const FPlane& ClipPlane,
|
||||
const FTransform& SurfaceTransform);
|
||||
|
||||
// ========================================================================
|
||||
// Screen Coverage & Visibility
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Estimate how much of the screen a capture surface occupies (0.0 to 1.0).
|
||||
* Uses the surface's bounding box corners projected to screen-space.
|
||||
*
|
||||
* @param SurfaceBounds Bounding box of the surface mesh in world space.
|
||||
* @param ViewerTransform World transform of the viewer's camera.
|
||||
* @param ViewerFOV Horizontal FOV of the viewer.
|
||||
* @param ScreenWidth Viewport width in pixels.
|
||||
* @param ScreenHeight Viewport height in pixels.
|
||||
* @return Estimated screen coverage ratio (0.0 to 1.0).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static float ComputeScreenCoverage(
|
||||
const FBox& SurfaceBounds,
|
||||
const FTransform& ViewerTransform,
|
||||
float ViewerFOV,
|
||||
int32 ScreenWidth,
|
||||
int32 ScreenHeight);
|
||||
|
||||
/**
|
||||
* Check whether the surface is visible to the viewer's frustum.
|
||||
*
|
||||
* @param SurfaceBounds Bounding box of the surface mesh in world space.
|
||||
* @param ViewerTransform World transform of the viewer's camera.
|
||||
* @param ViewerFOV Horizontal FOV.
|
||||
* @param ViewerAspectRatio Width / Height.
|
||||
* @param ViewerNearPlane Near clip distance.
|
||||
* @param ViewerFarPlane Far clip distance.
|
||||
* @return True if any part of the surface is within the frustum.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static bool IsSurfaceVisibleToViewer(
|
||||
const FBox& SurfaceBounds,
|
||||
const FTransform& ViewerTransform,
|
||||
float ViewerFOV,
|
||||
float ViewerAspectRatio,
|
||||
float ViewerNearPlane,
|
||||
float ViewerFarPlane);
|
||||
|
||||
// ========================================================================
|
||||
// Quality Scoring
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Compute a composite priority score for a capture surface.
|
||||
* Higher score = higher quality tier assignment.
|
||||
* Formula: (ScreenCoverage * 0.5) + (FacingAngle * 0.3) + (DistanceFactor * 0.1) + (ScriptedPriority * 0.1)
|
||||
*
|
||||
* @param ScreenCoverage How much screen real estate the surface occupies.
|
||||
* @param FacingAngle Dot product of viewer forward to surface normal.
|
||||
* @param DistanceToViewer Distance in world units.
|
||||
* @param MaxDistance Distance at which score drops to zero.
|
||||
* @param ScriptedPriority Priority override from gameplay systems (0.0 to 1.0).
|
||||
* @return Composite score (0.0 to 1.0).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|CameraUtils")
|
||||
static float ComputeCompositeScore(
|
||||
float ScreenCoverage,
|
||||
float FacingAngle,
|
||||
float DistanceToViewer,
|
||||
float MaxDistance,
|
||||
float ScriptedPriority);
|
||||
};
|
||||
189
Source/PG_Framework/Public/Capture/PlanarCaptureCommon.h
Normal file
189
Source/PG_Framework/Public/Capture/PlanarCaptureCommon.h
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright Ngonart OU. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — PlanarCaptureCommon
|
||||
// Shared enums, structs, and quality profile definitions for the Planar Capture System.
|
||||
// Used by BPC_PlanarCapture, BP_PlanarCaptureActor, and SS_PlanarCaptureManager.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/TextureRenderTarget2D.h"
|
||||
#include "PlanarCaptureCommon.generated.h"
|
||||
|
||||
// ============================================================================
|
||||
// Enums
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* The mode of the capture surface — determines camera math, rendering behavior,
|
||||
* and material configuration.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EPlanarCaptureMode : uint8
|
||||
{
|
||||
Mirror UMETA(DisplayName = "Mirror"),
|
||||
Portal UMETA(DisplayName = "Portal"),
|
||||
Monitor UMETA(DisplayName = "Monitor / Security Screen"),
|
||||
HorrorMirror UMETA(DisplayName = "Horror Mirror"),
|
||||
HorrorPortal UMETA(DisplayName = "Horror Portal"),
|
||||
FakeWindow UMETA(DisplayName = "Fake Window"),
|
||||
};
|
||||
|
||||
/**
|
||||
* Quality tier for a capture surface. Managed globally by SS_PlanarCaptureManager.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EPlanarCaptureQualityTier : uint8
|
||||
{
|
||||
Off UMETA(DisplayName = "Off — No capture"),
|
||||
Low UMETA(DisplayName = "Low — 256px, 4fps"),
|
||||
Medium UMETA(DisplayName = "Medium — 512px, 15fps"),
|
||||
High UMETA(DisplayName = "High — 1024px, 30fps"),
|
||||
Hero UMETA(DisplayName = "Hero — 2048px, 60fps"),
|
||||
};
|
||||
|
||||
/**
|
||||
* Result codes for capture surface initialization.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EPlanarCaptureInitResult : uint8
|
||||
{
|
||||
Success UMETA(DisplayName = "Success"),
|
||||
NoRenderTargetPool UMETA(DisplayName = "Failed — No Render Target in Pool"),
|
||||
InvalidSurfaceMesh UMETA(DisplayName = "Failed — Invalid Surface Mesh"),
|
||||
BudgetExceeded UMETA(DisplayName = "Failed — Budget Exceeded"),
|
||||
ManagerUnavailable UMETA(DisplayName = "Failed — Manager Unavailable"),
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Structs
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Quality profile — defines render target resolution, capture interval,
|
||||
* and per-feature toggles for a single quality tier.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct PG_FRAMEWORK_API FPlanarCaptureQualityProfile
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Render target resolution (square: 256, 512, 1024, 2048). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Quality")
|
||||
int32 RenderTargetSize = 512;
|
||||
|
||||
/** Minimum interval between captures in seconds (1.0 / FPS). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Quality")
|
||||
float CaptureInterval = 0.0667f; // ~15fps
|
||||
|
||||
/** Shadow rendering mode for the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableShadows = true;
|
||||
|
||||
/** Allow post-process effects in the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnablePostProcess = false;
|
||||
|
||||
/** Allow exponential height fog in the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableFog = false;
|
||||
|
||||
/** Allow bloom in the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableBloom = false;
|
||||
|
||||
/** Allow ambient occlusion in the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableAO = false;
|
||||
|
||||
/** Allow Lumen global illumination in the capture (expensive). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableLumen = false;
|
||||
|
||||
/** Allow motion blur in the capture. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableMotionBlur = false;
|
||||
|
||||
/** Enable oblique near-clip plane (required for portals flush with geometry). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Features")
|
||||
bool bEnableClipPlane = true;
|
||||
|
||||
/** Number of frames to delay the reflection (0 = off, N = horror lag effect). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Horror", meta = (ClampMin = "0", ClampMax = "30"))
|
||||
int32 DelayedFrameCount = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Single entry in a capture surface's ShowOnly or Hidden actor list.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct PG_FRAMEWORK_API FPlanarCaptureActorListEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** The actor to show exclusively or hide. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorList")
|
||||
TSoftObjectPtr<AActor> Actor;
|
||||
|
||||
/** Whether this actor is currently active in the list. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|ActorList")
|
||||
bool bActive = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scoring data for a capture surface — computed each frame by the manager
|
||||
* to determine quality tier assignment.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct PG_FRAMEWORK_API FPlanarCaptureScore
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Distance from viewer to surface in world units. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
float DistanceToViewer = FLT_MAX;
|
||||
|
||||
/** Screen coverage percentage (0.0 to 1.0). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
float ScreenCoverage = 0.0f;
|
||||
|
||||
/** Dot product of viewer forward and surface normal (1.0 = facing, 0.0 = edge-on). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
float FacingAngle = 0.0f;
|
||||
|
||||
/** Whether the surface is within the viewer's frustum. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
bool bInFrustum = false;
|
||||
|
||||
/** Scripted priority override (0.0 to 1.0, from gameplay systems). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
float ScriptedPriority = 0.0f;
|
||||
|
||||
/** Composite score (0.0 to 1.0) — higher = more important. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Capture|Score")
|
||||
float CompositeScore = 0.0f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render target pool entry — managed by SS_PlanarCaptureManager.
|
||||
*/
|
||||
USTRUCT()
|
||||
struct PG_FRAMEWORK_API FPlanarCaptureRenderTargetEntry
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** The allocated render target. */
|
||||
UPROPERTY()
|
||||
TObjectPtr<UTextureRenderTarget2D> RenderTarget = nullptr;
|
||||
|
||||
/** Current size of the render target. */
|
||||
UPROPERTY()
|
||||
int32 CurrentSize = 0;
|
||||
|
||||
/** Whether this entry is currently assigned to a surface. */
|
||||
UPROPERTY()
|
||||
bool bInUse = false;
|
||||
|
||||
/** Which surface currently owns this entry. */
|
||||
UPROPERTY()
|
||||
TWeakObjectPtr<class ABP_PlanarCaptureActor> OwningSurface;
|
||||
};
|
||||
232
Source/PG_Framework/Public/Capture/SS_PlanarCaptureManager.h
Normal file
232
Source/PG_Framework/Public/Capture/SS_PlanarCaptureManager.h
Normal file
@@ -0,0 +1,232 @@
|
||||
// Copyright Ngonart OU. All Rights Reserved.
|
||||
// UE5 Modular Game Framework — SS_PlanarCaptureManager (138)
|
||||
// Global budget manager for all planar capture surfaces in the world.
|
||||
//
|
||||
// One instance per World (World Subsystem). Each frame, scores every registered
|
||||
// capture surface by distance, screen coverage, facing angle, and scripted priority.
|
||||
// Assigns quality tiers across all surfaces respecting a global budget
|
||||
// (max simultaneous high-quality captures, max total render target memory).
|
||||
// Forces idle/disabled state on surfaces outside active rooms/sublevels.
|
||||
//
|
||||
// Also manages the render target pool — allocates, reuses, and resizes RTs
|
||||
// to minimize memory churn.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Subsystems/WorldSubsystem.h"
|
||||
#include "Capture/PlanarCaptureCommon.h"
|
||||
#include "SS_PlanarCaptureManager.generated.h"
|
||||
|
||||
class ABP_PlanarCaptureActor;
|
||||
class UBPC_PlanarCapture;
|
||||
|
||||
// Delegates
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSurfaceRegistered, ABP_PlanarCaptureActor*, Surface, int32, TotalSurfaces);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSurfaceUnregistered, ABP_PlanarCaptureActor*, Surface, int32, TotalSurfaces);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnGlobalQualityCapChanged, EPlanarCaptureQualityTier, NewCap);
|
||||
|
||||
/**
|
||||
* SS_PlanarCaptureManager — Global Planar Capture Budget Manager.
|
||||
*
|
||||
* Manages all ABP_PlanarCaptureActor instances per world. Evaluates priority
|
||||
* and assigns quality tiers to stay within a configurable budget.
|
||||
* Also owns the render target pool to reduce memory allocation overhead.
|
||||
*
|
||||
* Multiplayer: This subsystem exists on both server and clients.
|
||||
* On the server, it tracks surfaces for replication state.
|
||||
* On clients, it drives actual capture rendering.
|
||||
*/
|
||||
UCLASS()
|
||||
class PG_FRAMEWORK_API ASS_PlanarCaptureManager : public UWorldSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ASS_PlanarCaptureManager();
|
||||
|
||||
// ========================================================================
|
||||
// Lifecycle
|
||||
// ========================================================================
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual TStatId GetStatId() const override;
|
||||
|
||||
// ========================================================================
|
||||
// Surface Registry
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Register a capture surface actor with the global manager.
|
||||
* Called by ABP_PlanarCaptureActor::BeginPlay.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
||||
void RegisterSurface(ABP_PlanarCaptureActor* Surface);
|
||||
|
||||
/**
|
||||
* Unregister a capture surface actor. Called on EndPlay.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
||||
void UnregisterSurface(ABP_PlanarCaptureActor* Surface);
|
||||
|
||||
/**
|
||||
* Get all currently registered surfaces.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
||||
TArray<ABP_PlanarCaptureActor*> GetRegisteredSurfaces() const;
|
||||
|
||||
/**
|
||||
* Get the number of registered surfaces.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
||||
int32 GetSurfaceCount() const { return RegisteredSurfaces.Num(); }
|
||||
|
||||
// ========================================================================
|
||||
// Quality Budget Management
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Global quality ceiling — caps all surfaces at this tier regardless of score.
|
||||
* Use this for lower-end hardware targets.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
EPlanarCaptureQualityTier GlobalQualityCap = EPlanarCaptureQualityTier::High;
|
||||
|
||||
/**
|
||||
* Maximum number of simultaneous Hero-tier captures.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
int32 MaxHeroSurfaces = 1;
|
||||
|
||||
/**
|
||||
* Maximum number of simultaneous High-tier captures.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
int32 MaxHighSurfaces = 3;
|
||||
|
||||
/**
|
||||
* Maximum number of simultaneous Medium-tier captures.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
int32 MaxMediumSurfaces = 6;
|
||||
|
||||
/**
|
||||
* Maximum total render target memory in megabytes across all surfaces.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
float MaxTotalRenderTargetMemoryMB = 128.0f;
|
||||
|
||||
/**
|
||||
* Distance at which capture quality drops to Off (world units).
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
float MaxCaptureDistance = 10000.0f;
|
||||
|
||||
/**
|
||||
* Interval between full re-evaluation of all surfaces (seconds).
|
||||
* Individual surfaces check their own interval every frame via their component.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Capture|Manager|Budget")
|
||||
float FullEvaluationInterval = 0.5f;
|
||||
|
||||
// ========================================================================
|
||||
// Render Target Pool
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Request a render target from the pool. Returns nullptr if none available.
|
||||
*/
|
||||
UTextureRenderTarget2D* RequestRenderTarget(int32 Size);
|
||||
|
||||
/**
|
||||
* Release a render target back to the pool.
|
||||
*/
|
||||
void ReleaseRenderTarget(UTextureRenderTarget2D* RenderTarget);
|
||||
|
||||
/**
|
||||
* Get the total memory used by the render target pool (in MB).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
||||
float GetPoolMemoryUsageMB() const;
|
||||
|
||||
// ========================================================================
|
||||
// Query
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Get the nearest capture surface of a given mode to a world location.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Capture|Manager")
|
||||
ABP_PlanarCaptureActor* GetNearestSurfaceOfMode(
|
||||
EPlanarCaptureMode Mode, FVector WorldLocation, float MaxDistance = 0.0f) const;
|
||||
|
||||
/**
|
||||
* Force all surfaces to a specific quality tier (e.g., for cutscenes).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
||||
void ForceAllSurfacesToTier(EPlanarCaptureQualityTier Tier);
|
||||
|
||||
/**
|
||||
* Release the force-tier override and resume normal scoring.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Capture|Manager")
|
||||
void ReleaseForceTier();
|
||||
|
||||
// ========================================================================
|
||||
// Event Dispatchers
|
||||
// ========================================================================
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
||||
FOnSurfaceRegistered OnSurfaceRegistered;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
||||
FOnSurfaceUnregistered OnSurfaceUnregistered;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Capture|Manager|Events")
|
||||
FOnGlobalQualityCapChanged OnGlobalQualityCapChanged;
|
||||
|
||||
protected:
|
||||
// ========================================================================
|
||||
// Internal State
|
||||
// ========================================================================
|
||||
|
||||
/** All registered capture surface actors. */
|
||||
UPROPERTY()
|
||||
TArray<TWeakObjectPtr<ABP_PlanarCaptureActor>> RegisteredSurfaces;
|
||||
|
||||
/** Render target pool. */
|
||||
TArray<FPlanarCaptureRenderTargetEntry> RenderTargetPool;
|
||||
|
||||
/** Time accumulator for full re-evaluation interval. */
|
||||
float TimeSinceLastEvaluation = 0.0f;
|
||||
|
||||
/** Force-tier override — if set, all surfaces use this tier. */
|
||||
TOptional<EPlanarCaptureQualityTier> ForceTierOverride;
|
||||
|
||||
/** Count of surfaces at each tier (tracked for budget enforcement). */
|
||||
TMap<EPlanarCaptureQualityTier, int32> TierAssignmentCounts;
|
||||
|
||||
// ========================================================================
|
||||
// Internal Methods
|
||||
// ========================================================================
|
||||
|
||||
/** Evaluate all registered surfaces and assign quality tiers. */
|
||||
void EvaluateAllSurfaces();
|
||||
|
||||
/**
|
||||
* Score a single surface and determine its quality tier within budget constraints.
|
||||
* @return The assigned tier.
|
||||
*/
|
||||
EPlanarCaptureQualityTier ScoreAndAssignTier(UBPC_PlanarCapture* Capture);
|
||||
|
||||
/** Enforce budget limits — demote lower-priority surfaces if budget exceeded. */
|
||||
void EnforceBudgetLimits();
|
||||
|
||||
/** Create a new render target of the given size. */
|
||||
UTextureRenderTarget2D* CreateRenderTarget(int32 Size);
|
||||
|
||||
/** Get or create a render target for a given size (first checks pool). */
|
||||
UTextureRenderTarget2D* GetOrCreateRenderTarget(int32 Size);
|
||||
};
|
||||
Reference in New Issue
Block a user