Files
UnrealEngine/Engine/Source/Runtime/GeometryFramework/Public/Components/BaseDynamicMeshSceneProxy.h
2025-05-18 13:04:45 +08:00

379 lines
13 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "PrimitiveSceneProxy.h"
#include "MeshRenderBufferSet.h"
#include "PrimitiveViewRelevance.h"
#include "DynamicMeshBuilder.h"
#include "Components/BaseDynamicMeshComponent.h"
#include "RayTracingGeometry.h"
#include "Templates/PimplPtr.h"
#include "Util/ProgressCancel.h"
#include "DistanceFieldAtlas.h"
#include "PhysicsEngine/AggregateGeom.h"
using UE::Geometry::FDynamicMesh3;
using UE::Geometry::FDynamicMeshAttributeSet;
using UE::Geometry::FDynamicMeshUVOverlay;
using UE::Geometry::FDynamicMeshNormalOverlay;
using UE::Geometry::FDynamicMeshColorOverlay;
using UE::Geometry::FDynamicMeshMaterialAttribute;
class FDynamicPrimitiveUniformBuffer;
class FMaterialRenderProxy;
class UMaterialInterface;
class FCardRepresentationData;
/**
* FBaseDynamicMeshSceneProxy is an abstract base class for a Render Proxy
* for a UBaseDynamicMeshComponent, where the assumption is that mesh data
* will be stored in FMeshRenderBufferSet instances
*/
class FBaseDynamicMeshSceneProxy : public FPrimitiveSceneProxy
{
using FIndex2i = UE::Geometry::FIndex2i;
using FIndex3i = UE::Geometry::FIndex3i;
public:
UBaseDynamicMeshComponent* ParentBaseComponent;
/**
* Utility to initialize and update the mesh render buffers from a mesh with overlays
* and holds all the settings required.
*/
FMeshRenderBufferSetConversionUtil MeshRenderBufferSetConverter;
protected:
// Set of currently-allocated RenderBuffers. We own these pointers and must clean them up.
// Must guard access with AllocatedSetsLock!!
TSet<FMeshRenderBufferSet*> AllocatedBufferSets;
// use to control access to AllocatedBufferSets
FCriticalSection AllocatedSetsLock;
// control raytracing support
bool bEnableRaytracing = false;
// Allow view-mode overrides.
bool bEnableViewModeOverrides = true;
// whether to try to use the static draw instead of dynamic draw path; note we may still use the dynamic path if collision or vertex color rendering is enabled
bool bPreferStaticDrawPath = false;
public:
GEOMETRYFRAMEWORK_API FBaseDynamicMeshSceneProxy(UBaseDynamicMeshComponent* Component);
GEOMETRYFRAMEWORK_API virtual ~FBaseDynamicMeshSceneProxy();
//
// FBaseDynamicMeshSceneProxy API - subclasses must implement these functions
//
/**
* Return set of active renderbuffers. Must be implemented by subclass.
* This is the set of render buffers that will be drawn by GetDynamicMeshElements
*/
virtual void GetActiveRenderBufferSets(TArray<FMeshRenderBufferSet*>& Buffers) const = 0;
//
// RenderBuffer management
//
/**
* Allocates a set of render buffers. FPrimitiveSceneProxy will keep track of these
* buffers and destroy them on destruction.
*/
GEOMETRYFRAMEWORK_API virtual FMeshRenderBufferSet* AllocateNewRenderBufferSet();
/**
* Explicitly release a set of RenderBuffers
*/
GEOMETRYFRAMEWORK_API virtual void ReleaseRenderBufferSet(FMeshRenderBufferSet* BufferSet);
/**
* Initialize rendering buffers from given attribute overlays.
* Creates three vertices per triangle, IE no shared vertices in buffers.
*/
template<typename TriangleEnumerable>
void InitializeBuffersFromOverlays(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh,
int NumTriangles, const TriangleEnumerable& Enumerable,
const FDynamicMeshUVOverlay* UVOverlay,
const FDynamicMeshNormalOverlay* NormalOverlay,
const FDynamicMeshColorOverlay* ColorOverlay,
TFunctionRef<void(int, int, int, const FVector3f&, FVector3f&, FVector3f&)> TangentsFunc,
bool bTrackTriangles = false,
bool bParallel = false)
{
MeshRenderBufferSetConverter.InitializeBuffersFromOverlays(RenderBuffers, Mesh, NumTriangles, Enumerable, UVOverlay, NormalOverlay, ColorOverlay, TangentsFunc, bTrackTriangles, bParallel);
}
/**
* Initialize rendering buffers from given attribute overlays.
* Creates three vertices per triangle, IE no shared vertices in buffers.
*/
template<typename TriangleEnumerable, typename UVOverlayListAllocator>
void InitializeBuffersFromOverlays(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh,
int NumTriangles, const TriangleEnumerable& Enumerable,
const TArray<const FDynamicMeshUVOverlay*, UVOverlayListAllocator>& UVOverlays,
const FDynamicMeshNormalOverlay* NormalOverlay,
const FDynamicMeshColorOverlay* ColorOverlay,
TFunctionRef<void(int, int, int, const FVector3f&, FVector3f&, FVector3f&)> TangentsFunc,
bool bTrackTriangles = false,
bool bParallel = false)
{
MeshRenderBufferSetConverter.InitializeBuffersFromOverlays(RenderBuffers, Mesh, NumTriangles, Enumerable, UVOverlays, NormalOverlay, ColorOverlay, TangentsFunc, bTrackTriangles, bParallel);
}
/**
* Filter the triangles in a FMeshRenderBufferSet into the SecondaryIndexBuffer.
* Requires that RenderBuffers->Triangles has been initialized.
* @param bDuplicate if set, then primary IndexBuffer is unmodified and SecondaryIndexBuffer contains duplicates. Otherwise triangles are sorted via predicate into either primary or secondary.
*/
void UpdateSecondaryTriangleBuffer(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh,
bool bDuplicate)
{
MeshRenderBufferSetConverter.UpdateSecondaryTriangleBuffer(RenderBuffers, Mesh, bDuplicate);
}
/**
* RecomputeRenderBufferTriangleIndexSets re-sorts the existing set of triangles in a FMeshRenderBufferSet
* into primary and secondary index buffers. Note that UploadIndexBufferUpdate() must be called
* after this function!
*/
void RecomputeRenderBufferTriangleIndexSets(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh)
{
MeshRenderBufferSetConverter.RecomputeRenderBufferTriangleIndexSets(RenderBuffers, Mesh);
}
/**
* Update vertex positions/normals/colors of an existing set of render buffers.
* Assumes that buffers were created with unshared vertices, ie three vertices per triangle, eg by InitializeBuffersFromOverlays()
*/
template<typename TriangleEnumerable>
void UpdateVertexBuffersFromOverlays(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh,
int NumTriangles, const TriangleEnumerable& Enumerable,
const FDynamicMeshNormalOverlay* NormalOverlay,
const FDynamicMeshColorOverlay* ColorOverlay,
TFunctionRef<void(int, int, int, const FVector3f&, FVector3f&, FVector3f&)> TangentsFunc,
bool bUpdatePositions = true,
bool bUpdateNormals = false,
bool bUpdateColors = false)
{
MeshRenderBufferSetConverter.UpdateVertexBuffersFromOverlays(RenderBuffers, Mesh, NumTriangles, Enumerable, NormalOverlay, ColorOverlay, TangentsFunc, bUpdatePositions, bUpdateNormals, bUpdateColors);
}
/**
* Update vertex uvs of an existing set of render buffers.
* Assumes that buffers were created with unshared vertices, ie three vertices per triangle, eg by InitializeBuffersFromOverlays()
*/
template<typename TriangleEnumerable, typename UVOverlayListAllocator>
void UpdateVertexUVBufferFromOverlays(
FMeshRenderBufferSet* RenderBuffers,
const FDynamicMesh3* Mesh,
int32 NumTriangles, const TriangleEnumerable& Enumerable,
const TArray<const FDynamicMeshUVOverlay*, UVOverlayListAllocator>& UVOverlays)
{
MeshRenderBufferSetConverter.UpdateVertexUVBufferFromOverlays(RenderBuffers, Mesh, NumTriangles, Enumerable, UVOverlays);
}
/**
* @return number of active materials
*/
GEOMETRYFRAMEWORK_API virtual int32 GetNumMaterials() const;
/**
* Safe GetMaterial function that will never return nullptr
*/
GEOMETRYFRAMEWORK_API virtual UMaterialInterface* GetMaterial(int32 k) const;
/**
* Set whether or not to validate mesh batch materials against the component materials.
*/
void SetVerifyUsedMaterials(const bool bState)
{
bVerifyUsedMaterials = bState;
}
/**
* This needs to be called if the set of active materials changes, otherwise
* the check in FPrimitiveSceneProxy::VerifyUsedMaterial() will fail if an override
* material is set, if materials change, etc, etc
*/
GEOMETRYFRAMEWORK_API virtual void UpdatedReferencedMaterials();
//
// FBaseDynamicMeshSceneProxy implementation
//
/**
* If EngineShowFlags request vertex color rendering, returns the appropriate vertex color override material's render proxy. Otherwise returns nullptr.
*/
GEOMETRYFRAMEWORK_API static FMaterialRenderProxy* GetEngineVertexColorMaterialProxy(FMeshElementCollector& Collector, const FEngineShowFlags& EngineShowFlags, bool bProxyIsSelected, bool bIsHovered);
/**
* Render set of active RenderBuffers returned by GetActiveRenderBufferSets
*/
GEOMETRYFRAMEWORK_API virtual void GetDynamicMeshElements(
const TArray<const FSceneView*>& Views,
const FSceneViewFamily& ViewFamily,
uint32 VisibilityMap,
FMeshElementCollector& Collector) const override;
protected:
/**
* Helper called by GetDynamicMeshElements to process collision debug drawing
*/
GEOMETRYFRAMEWORK_API virtual void GetCollisionDynamicMeshElements(TArray<FMeshRenderBufferSet*>& Buffers,
const FEngineShowFlags& EngineShowFlags, bool bDrawCollisionView, bool bDrawSimpleCollision, bool bDrawComplexCollision,
bool bProxyIsSelected,
const TArray<const FSceneView*>& Views, uint32 VisibilityMap,
FMeshElementCollector& Collector) const;
public:
GEOMETRYFRAMEWORK_API virtual void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) override;
// Whether to allow use of the static draw path. If false, the dynamic draw path will be used instead.
GEOMETRYFRAMEWORK_API virtual bool AllowStaticDrawPath(const FSceneView* View) const;
/**
* Draw a single-frame FMeshBatch for a FMeshRenderBufferSet
*/
GEOMETRYFRAMEWORK_API virtual void DrawBatch(FMeshElementCollector& Collector,
const FMeshRenderBufferSet& RenderBuffers,
const FDynamicMeshIndexBuffer32& IndexBuffer,
FMaterialRenderProxy* UseMaterial,
bool bWireframe,
ESceneDepthPriorityGroup DepthPriority,
int ViewIndex,
FDynamicPrimitiveUniformBuffer& DynamicPrimitiveUniformBuffer) const;
// Like FStaticMeshSceneProxy, only override CreateHitProxies in editor, where component may have CreateMeshHitProxy
#if WITH_EDITOR
GEOMETRYFRAMEWORK_API virtual HHitProxy* CreateHitProxies(UPrimitiveComponent* Component, TArray<TRefCountPtr<HHitProxy> >& OutHitProxies) override;
GEOMETRYFRAMEWORK_API virtual HHitProxy* CreateHitProxies(IPrimitiveComponent* ComponentInterface, TArray<TRefCountPtr<HHitProxy> >& OutHitProxies) override;
#endif // WITH_EDITOR
//
// Raytracing APIs
//
#if RHI_RAYTRACING
GEOMETRYFRAMEWORK_API virtual bool IsRayTracingRelevant() const override;
GEOMETRYFRAMEWORK_API virtual bool HasRayTracingRepresentation() const override;
GEOMETRYFRAMEWORK_API virtual void GetDynamicRayTracingInstances(FRayTracingInstanceCollector& Collector) override;
/**
* Draw a single-frame raytracing FMeshBatch for a FMeshRenderBufferSet
*/
GEOMETRYFRAMEWORK_API virtual void DrawRayTracingBatch(
FRayTracingInstanceCollector& Collector,
const FMeshRenderBufferSet& RenderBuffers,
const FDynamicMeshIndexBuffer32& IndexBuffer,
FRayTracingGeometry& RayTracingGeometry,
FMaterialRenderProxy* UseMaterialProxy,
ESceneDepthPriorityGroup DepthPriority,
FDynamicPrimitiveUniformBuffer& DynamicPrimitiveUniformBuffer) const;
#endif // RHI_RAYTRACING
//
// Lumen APIs
//
public:
GEOMETRYFRAMEWORK_API virtual const FCardRepresentationData* GetMeshCardRepresentation() const override;
protected:
TPimplPtr<FCardRepresentationData> MeshCards;
UE_DEPRECATED(5.6, "Use MeshCards.IsValid() instead")
bool bMeshCardsValid = false;
// Helper to set lumen cards
void UpdateLumenCardsFromBounds();
protected:
UE_DEPRECATED(5.6, "Distance field support is deprecated for dynamic mesh components")
TSharedPtr<FDistanceFieldVolumeData> DistanceField;
UE_DEPRECATED(5.6, "Distance field support is deprecated for dynamic mesh components")
bool bDistanceFieldValid = false;
public:
UE_DEPRECATED(5.6, "Distance field support is deprecated for dynamic mesh components")
static TUniquePtr<FDistanceFieldVolumeData> ComputeDistanceFieldForMesh(
const FDynamicMesh3& Mesh,
FProgressCancel& Progress,
float DistanceFieldResolutionScale = 1.0,
bool bGenerateAsIfTwoSided = false );
UE_DEPRECATED(5.6, "Distance field support is deprecated for dynamic mesh components")
GEOMETRYFRAMEWORK_API void SetNewDistanceField(TSharedPtr<FDistanceFieldVolumeData> NewDistanceField, bool bInInitialize);
public:
// Set the collision data to use for debug drawing, or do nothing if debug drawing is not enabled
GEOMETRYFRAMEWORK_API void SetCollisionData();
#if UE_ENABLE_DEBUG_DRAWING
private:
// If debug drawing is enabled, we store collision data here so that collision shapes can be rendered when requested by showflags
bool bOwnerIsNull = true;
/** Whether the collision data has been set up for rendering */
bool bHasCollisionData = false;
/** Whether a complex collision mesh is available */
bool bHasComplexMeshData = false;
/** Collision trace flags */
ECollisionTraceFlag CollisionTraceFlag;
/** Collision Response of this component */
FCollisionResponseContainer CollisionResponse;
/** Cached AggGeom holding the collision shapes to render */
FKAggregateGeom CachedAggGeom;
// Control access to collision data for debug rendering
mutable FCriticalSection CachedCollisionLock;
#endif
GEOMETRYFRAMEWORK_API bool IsCollisionView(const FEngineShowFlags& EngineShowFlags, bool& bDrawSimpleCollision, bool& bDrawComplexCollision) const;
};