Giant_Beast_2025/Plugins/MetaXR/Source/MRUtilityKit/Public/MRUtilityKitDistanceMapGenerator.h

198 lines
6.7 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "MRUtilityKit.h"
#include "GameFramework/Actor.h"
#include "MRUtilityKitDistanceMapGenerator.generated.h"
const FName GMRUK_DISTANCE_MAP_ACTOR_TAG = TEXT("DistanceMapActor");
UENUM(BlueprintType)
enum class EMRUKDistanceMapGenerationMode : uint8
{
// Do not generate a distance map
None,
/// Generate distance map only for the free space. E.g. The floor inside the room.
FreeSpace,
/// Generate the distance map only for the occupied space. E.g. outside the room and inside scene objects.
OccupiedSpace,
/// Generate the distance map for free space and occupied space.
AllSpace,
};
/**
* Generates a distance map that can be used in materials to calculate the distance to various objects.
* This can enable interesting effects. With the distance map you can get the distance from scene objects
* or walls in a material shader.
*
* The Jump Flood Algorithm is used to generate the distance map. This is fast enough to regenerate
* every tick.
*
* To capture a distance map after a room has been loaded call CaptureDistanceMap().
* It will return a captured distance map. In case you already called CaptureDistanceMap()
* you can receive the last captured distance map with GetDistanceMap(). No other setup is required.
*
* This class will create procedural meshes for every anchor to create a mask. These meshes have their
* visibility set to scene capture only. That however means that if you place a scene capture component yourself
* that the meshes will show up in your scene capture component. The actors that have the procedural meshes
* attached are tagged with GMRUK_DISTANCE_MAP_ACTOR_TAG. In case you don't want them to show up in your
* scene capture you can hide them by receiving all these actors with the tag GMRUK_DISTANCE_MAP_ACTOR_TAG
* and add these to the scene captures hidden actors.
*/
UCLASS(ClassGroup = MRUtilityKit, meta = (DisplayName = "MR Utility Kit Distance Map Generator"))
class MRUTILITYKIT_API AMRUKDistanceMapGenerator : public AActor
{
GENERATED_BODY()
public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnReady);
UPROPERTY(BlueprintAssignable, Category = "MR Utility Kit")
FOnReady OnReady;
/**
* The mode in which the final distance map should be generated.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
EMRUKDistanceMapGenerationMode DistanceMapGenerationMode = EMRUKDistanceMapGenerationMode::FreeSpace;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class USceneComponent* Root;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class USceneCaptureComponent2D* SceneCapture2D;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
EMRUKSpawnMode SpawnMode = EMRUKSpawnMode::CurrentRoomOnly;
/**
* First render target for jump flood algorithm.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UCanvasRenderTarget2D* RenderTarget1;
/**
* Second render target for jump flood algorithm.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UCanvasRenderTarget2D* RenderTarget2;
/**
* Render target for the final distance map
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UCanvasRenderTarget2D* DistanceMapRenderTarget;
/**
* Material to render a mask that gets used to calculate the distance map.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UMaterialInterface* MaskMaterial;
/**
* Material that executes a pass of the jump flood algorithm.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UMaterialInterface* JFPassMaterial;
/**
* Material to render final distance map
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UMaterialInterface* DistanceMapFreeSpaceMaterial;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UMaterialInterface* DistanceMapOccupiedSpaceMaterial;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
class UMaterialInterface* DistanceMapAllSpaceMaterial;
/**
* Capture the distance map.
* @return The captured distance map.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
UTexture* CaptureDistanceMap();
/**
* Create mask meshes for the given room.
* These mask meshes are needed for the distance map to be rendered. It should only be called once before
* CaptureDistanceMap in case the SpawnMode has been set to None.
* The operation that this function executes is expensive. It only needs to be called after the room has been
* created or updated.
* @param Room The room for which the masked meshes should be created.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
void CreateMaskMeshesForRoom(AMRUKRoom* Room);
/**
* Remove mask meshes for the given room.
* This function should only be executed when SpawnMode is set to None.
* It only needs to be called after a room has been removed.
* @param Room The room for which the masked meshes should be removed.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
void RemoveMaskMeshesFromRoom(AMRUKRoom* Room);
/**
* Return the captured distance map. Be sure to call CaptureDistanceMap() before
* @return The captured distance map.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
UTexture* GetDistanceMap() const;
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
UCanvasRenderTarget2D* GetDistanceMapRenderTarget() const;
/**
* Retrieve the view info from the scene capture. This is useful for re projection of
* the distance map in a material.
* @return The view info.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
FMinimalViewInfo GetSceneCaptureView() const;
public:
AMRUKDistanceMapGenerator();
protected:
void BeginPlay() override;
private:
TMap<AMRUKRoom*, TArray<AActor*>> SpawnedMaskMeshes;
int32 DistanceMapRT = -1;
UPROPERTY()
class UMaterialInstanceDynamic* JFPassMaterialInstance = nullptr;
UPROPERTY()
class UMaterialInstanceDynamic* DistanceMapFreeSpaceMaterialInstance = nullptr;
UPROPERTY()
class UMaterialInstanceDynamic* DistanceMapOccupiedSpaceMaterialInstance = nullptr;
UPROPERTY()
class UMaterialInstanceDynamic* DistanceMapAllSpaceMaterialInstance = nullptr;
UPROPERTY()
UMaterialInterface* SceneObjectMaskMaterial;
UPROPERTY()
UMaterialInterface* FloorMaskMaterial;
void CaptureInitialSceneMask();
void RenderDistanceMap();
UFUNCTION()
void OnRoomCreated(AMRUKRoom* Room);
UFUNCTION()
void OnRoomUpdated(AMRUKRoom* Room);
UFUNCTION()
AActor* CreateMaskMeshOfAnchor(AMRUKAnchor* Anchor);
UFUNCTION()
AActor* UpdateMaskMeshOfAnchor(AMRUKAnchor* Anchor);
};