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

213 lines
7.5 KiB
C++

// Copyright (c) Meta Platforms, Inc. and affiliates.
#pragma once
#include "MRUtilityKit.h"
#include "MRUtilityKitBPLibrary.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "Tasks/Task.h"
#include "MRUtilityKitDestructibleMesh.generated.h"
/**
* Destructible mesh component. Creates mesh segments for the given geometry.
* The segments will be created async.
* In addition, its possible to define areas that are indestructible.
*/
UCLASS(ClassGroup = MRUtilityKit, Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent, DisplayName = "MR Utility Kit Destructible Mesh Component"))
class MRUTILITYKIT_API UMRUKDestructibleMeshComponent : public UProceduralMeshComponent
{
GENERATED_BODY()
public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnMeshesGenerated);
UMRUKDestructibleMeshComponent(const FObjectInitializer& ObjectInitializer);
UPROPERTY(BlueprintAssignable, Category = "MR Utility Kit")
FOnMeshesGenerated OnMeshesGenerated;
/**
* Material to display on the global mesh
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
UMaterialInterface* GlobalMeshMaterial;
/**
* Area on the top of the mesh that should be indestructible.
* The area is given in centimeters 1.0 == 1 cm.
* -1.0 means no reserved area.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double ReservedTop = -1.0;
/**
* Area on the bottom of the mesh that should be indestructible.
* The area is given in centimeters 1.0 == 1 cm
* -1.0 means no reserved area.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double ReservedBottom = 30.0;
/**
* Segment the given geometry into smaller chunks. For each chunk a procedural mesh component will be spawned and attached to the owning actor.
* @param MeshPositions Positions of the mesh to segment
* @param MeshIndices Indices of the mesh to segment
* @param SegmentationPoints Points to use to determine the segments.
*/
void SegmentMesh(const TArray<FVector>& MeshPositions, const TArray<uint32>& MeshIndices, const TArray<FVector>& SegmentationPoints);
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
private:
UE::Tasks::TTask<TPair<TArray<FMRUKMeshSegment>, FMRUKMeshSegment>> TaskResult;
};
/**
* Actor that constructs a destructible mesh for the given room
* The actor will automatically attach to the global mesh anchor of the given room to take it location and orientation.
*/
UCLASS(ClassGroup = MRUtilityKit, Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent, DisplayName = "MR Utility Kit Destructible Global Mesh"))
class MRUTILITYKIT_API AMRUKDestructibleGlobalMesh : public AActor
{
GENERATED_BODY()
public:
AMRUKDestructibleGlobalMesh();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MR Utility Kit")
UMRUKDestructibleMeshComponent* DestructibleMeshComponent;
/**
* Density of mesh segments on the X axis.
* Increase this value to get smaller cracks in the global mesh.
* Decrease this value to get bigger cracks in the global mesh.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double PointsPerUnitX = 1.0;
/**
* How many segmentation points should be created at a maximum.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
int MaxPointsCount = 256;
/**
* Density of mesh segments on the Y axis.
* Increase this value to get smaller cracks in the global mesh.
* Decrease this value to get bigger cracks in the global mesh.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double PointsPerUnitY = 1.0;
/**
* Create a destructible mesh for the given room. If the global mesh has not yet been loaded
* this function will attempt to load the global mesh from the device.
* @param Room The room
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
void CreateDestructibleMesh(AMRUKRoom* Room = nullptr);
/**
* Remove a segment of the global mesh. Takes care of not removing the reserved global mesh segment.
* @param Mesh The mesh to remove
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
void RemoveGlobalMeshSegment(UPrimitiveComponent* Mesh);
};
/**
* The destructible global mesh spawner allows to spawn (automatically) destructible global meshes
* when new rooms are created.
* A destructible global mesh is a version of the global mesh that can be destructed during runtime.
* The bulk of the work is performed in UDestructibleMeshComponent. It will perform on start a one time
* preprocessing step to segment the given global mesh into smaller chunks. After that the chunks can be used
* during the game and removed (e.g. with ray casts) at any time during the game simulating as if the global
* mesh would crack down. To enhance the visual quality when cracking the (e.g. removing mesh chunks) global mesh
* a particle system could be used. The system allows to define areas that should be non destructible.
*/
UCLASS(ClassGroup = MRUtilityKit, Blueprintable, BlueprintType, meta = (BlueprintSpawnableComponent, DisplayName = "MR Utility Kit Destructible Global Mesh Spawner"))
class MRUTILITYKIT_API AMRUKDestructibleGlobalMeshSpawner : public AActor
{
GENERATED_BODY()
public:
/**
* Whether destructible meshes should be spawned automatically.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
EMRUKSpawnMode SpawnMode = EMRUKSpawnMode::CurrentRoomOnly;
/**
* Material to display on the global mesh
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
UMaterialInterface* GlobalMeshMaterial;
/**
* Density of mesh segments on the X axis.
* Increase this value to get smaller cracks in the global mesh.
* Decrease this value to get bigger cracks in the global mesh.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double PointsPerUnitX = 1.0;
/**
* How many segmentation points should be created at a maximum.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
int MaxPointsCount = 256;
/**
* Density of mesh segments on the Y axis.
* Increase this value to get smaller cracks in the global mesh.
* Decrease this value to get bigger cracks in the global mesh.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double PointsPerUnitY = 1.0;
/**
* Area on the top of the mesh that should be indestructible.
* The area is given in centimeters 1.0 == 1 cm
* -1.0 means no reserved area.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double ReservedTop = -1.0;
/**
* Area on the bottom of the mesh that should be indestructible.
* The area is given in centimeters 1.0 == 1 cm
* -1.0 means no reserved area.
*/
UPROPERTY(EditAnywhere, Category = "MR Utility Kit")
double ReservedBottom = 30.0;
void BeginPlay() override;
/**
* Find the destructible mesh that has been spawned for the given room.
* @param Room Room to look for the destructible mesh
* @return The destructible mesh
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
AMRUKDestructibleGlobalMesh* FindDestructibleMeshForRoom(AMRUKRoom* Room);
/**
* Add new destructible mesh for the given room. A mesh will only get spawned if no
* destructible mesh has been spawned for the room yet.
* @param Room The room.
*/
UFUNCTION(BlueprintCallable, Category = "MR Utility Kit")
AMRUKDestructibleGlobalMesh* AddDestructibleGlobalMesh(AMRUKRoom* Room);
private:
TMap<AMRUKRoom*, AMRUKDestructibleGlobalMesh*> SpawnedMeshes;
UFUNCTION()
void OnRoomCreated(AMRUKRoom* Room);
UFUNCTION()
void OnRoomRemoved(AMRUKRoom* Room);
};