// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Components/MeshComponent.h" #include "InteractiveToolObjects.h" #include "Changes/MeshVertexChange.h" #include "Changes/MeshChange.h" #include "Changes/MeshReplacementChange.h" #include "MeshConversionOptions.h" #include "DynamicMesh/DynamicMesh3.h" // todo replace with predeclaration (lots of fallout) #include "UDynamicMesh.h" #include "BaseDynamicMeshComponent.generated.h" // predecl struct FMeshDescription; class FMeshVertexChange; class FMeshChange; class FBaseDynamicMeshSceneProxy; using UE::Geometry::FDynamicMesh3; /** * EMeshRenderAttributeFlags is used to identify different mesh rendering attributes, for things * like fast-update functions */ enum class EMeshRenderAttributeFlags : uint8 { None = 0, Positions = 1, VertexColors = 1<<1, VertexNormals = 1<<2, VertexUVs = 1<<3, SecondaryIndexBuffers = 1<<4, AllVertexAttribs = Positions | VertexColors | VertexNormals | VertexUVs }; ENUM_CLASS_FLAGS(EMeshRenderAttributeFlags); /** * Tangent calculation modes */ UENUM() enum class EDynamicMeshComponentTangentsMode : uint8 { /** Tangents are not used/available, proceed accordingly (eg generate arbitrary orthogonal basis) */ NoTangents, /** Tangents will be automatically calculated on demand. Note that mesh changes due to tangents calculation will *not* be broadcast via MeshChange events! */ AutoCalculated, /** Tangents are externally provided via the FDynamicMesh3 AttributeSet */ ExternallyProvided }; /** * UBaseDynamicMeshComponent is a base interface for a UMeshComponent based on a UDynamicMesh. */ UCLASS(Abstract, hidecategories = (LOD), ClassGroup = Rendering) class GEOMETRYFRAMEWORK_API UBaseDynamicMeshComponent : public UMeshComponent, public IToolFrameworkComponent, public IMeshVertexCommandChangeTarget, public IMeshCommandChangeTarget, public IMeshReplacementCommandChangeTarget { GENERATED_UCLASS_BODY() //=============================================================================================================== // UBaseDynamicMeshComponent API. Subclasses must implement these functions // public: /** * initialize the internal mesh from a DynamicMesh */ virtual void SetMesh(UE::Geometry::FDynamicMesh3&& MoveMesh) { unimplemented(); } /** * @return pointer to internal mesh * @warning avoid usage of this function, access via GetDynamicMesh() instead */ virtual FDynamicMesh3* GetMesh() { unimplemented(); return nullptr; } /** * @return pointer to internal mesh */ virtual const FDynamicMesh3* GetMesh() const { unimplemented(); return nullptr; } /** * Allow external code to read the internal mesh. */ virtual void ProcessMesh(TFunctionRef ProcessFunc) const { unimplemented(); } /** * @return the child UDynamicMesh */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual UDynamicMesh* GetDynamicMesh() { unimplemented(); return nullptr; } /** * Call this if you update the mesh via GetMesh() * @todo should provide a function that calls a lambda to modify the mesh, and only return const mesh pointer */ virtual void NotifyMeshUpdated() { unimplemented(); } /** * Apply a vertex deformation change to the internal mesh (implements IMeshVertexCommandChangeTarget) */ virtual void ApplyChange(const FMeshVertexChange* Change, bool bRevert) override { unimplemented(); } /** * Apply a general mesh change to the internal mesh (implements IMeshCommandChangeTarget) */ virtual void ApplyChange(const FMeshChange* Change, bool bRevert) override { unimplemented(); } /** * Apply a full mesh replacement change to the internal mesh (implements IMeshReplacementCommandChangeTarget) */ virtual void ApplyChange(const FMeshReplacementChange* Change, bool bRevert) override { unimplemented(); } /** * Apply a transform to the mesh */ virtual void ApplyTransform(const FTransform3d& Transform, bool bInvert) { unimplemented(); } protected: /** * Subclass must implement this to return scene proxy if available, or nullptr */ virtual FBaseDynamicMeshSceneProxy* GetBaseSceneProxy() { unimplemented(); return nullptr; } /** * Subclass must implement this to notify allocated proxies of updated materials */ virtual void NotifyMaterialSetUpdated() { unimplemented(); } //=============================================================================================================== // Built-in Wireframe-on-Shaded Rendering support. The wireframe looks terrible but this is a convenient // way to enable/disable it. // public: /** * If true, render the Wireframe on top of the Shaded Mesh */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "Wireframe Overlay") ) bool bExplicitShowWireframe = false; /** * Configure whether wireframe rendering is enabled or not */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetEnableWireframeRenderPass(bool bEnable) { bExplicitShowWireframe = bEnable; } /** * @return true if wireframe rendering pass is enabled */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool GetEnableWireframeRenderPass() const { return bExplicitShowWireframe; } //=============================================================================================================== // API for changing Rendering settings. Although some of these settings are available publicly // on the Component (in some cases as public members), generally changing them requires more complex // Rendering invalidation. // public: UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetShadowsEnabled(bool bEnabled); UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool GetShadowsEnabled() const { return CastShadow; } UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetViewModeOverridesEnabled(bool bEnabled); UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool GetViewModeOverridesEnabled() const { return bEnableViewModeOverrides; } public: /** * This flag controls whether Editor View Mode Overrides are enabled for this mesh. For example, this controls hidden-line removal on the wireframe * in Wireframe View Mode, and whether the normal map will be disabled in Lighting-Only View Mode, as well as various other things. * Use SetViewModeOverridesEnabled() to control this setting in Blueprints/C++. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "View Mode Overrides") ) bool bEnableViewModeOverrides = true; //=============================================================================================================== // Override rendering material support. If an Override material is set, then it // will be used during drawing of all mesh buffers except Secondary buffers. // public: /** * Set an active override render material. This should replace all materials during rendering. */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetOverrideRenderMaterial(UMaterialInterface* Material); /** * Clear any active override render material */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void ClearOverrideRenderMaterial(); /** * @return true if an override render material is currently enabled for the given MaterialIndex */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool HasOverrideRenderMaterial(int k) const { return OverrideRenderMaterial != nullptr; } /** * @return active override render material for the given MaterialIndex */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual UMaterialInterface* GetOverrideRenderMaterial(int MaterialIndex) const { return OverrideRenderMaterial; } protected: UPROPERTY() TObjectPtr OverrideRenderMaterial = nullptr; //=============================================================================================================== // Secondary Render Buffers support. This requires implementation in subclasses. It allows // a subset of the mesh triangles to be moved to a separate set of render buffers, which // can then have a separate material (eg to highlight faces), or be shown/hidden independently. // public: /** * Set an active secondary render material. */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetSecondaryRenderMaterial(UMaterialInterface* Material); /** * Clear any active secondary render material */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void ClearSecondaryRenderMaterial(); /** * @return true if a secondary render material is set */ virtual bool HasSecondaryRenderMaterial() const { return SecondaryRenderMaterial != nullptr; } /** * @return active secondary render material */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual UMaterialInterface* GetSecondaryRenderMaterial() const { return SecondaryRenderMaterial; } /** * Show/Hide the secondary triangle buffers. Does not invalidate SceneProxy. */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetSecondaryBuffersVisibility(bool bSetVisible); /** * @return true if secondary buffers are currently set to be visible */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool GetSecondaryBuffersVisibility() const; protected: UPROPERTY() TObjectPtr SecondaryRenderMaterial = nullptr; bool bDrawSecondaryBuffers = true; //=============================================================================================================== // Raytracing support. Must be enabled for various rendering effects. // However, note that in actual "dynamic" contexts (ie where the mesh is changing every frame), // enabling Raytracing support has additional renderthread performance costs and does // not currently support partial updates in the SceneProxy. public: /** * Enable/disable Raytracing support on this Mesh, if Raytracing is currently enabled in the Project Settings. * Use SetEnableRaytracing() to configure this flag in Blueprints/C++. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering") bool bEnableRaytracing = true; /** * Enable/Disable raytracing support. This is an expensive call as it flushes * the rendering queue and forces an immediate rebuild of the SceneProxy. */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual void SetEnableRaytracing(bool bSetEnabled); /** * @return true if raytracing support is currently enabled */ UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component") virtual bool GetEnableRaytracing() const; protected: virtual void OnRenderingStateChanged(bool bForceImmedateRebuild); //=============================================================================================================== // Standard Component interfaces // public: // UMeshComponent Interface. virtual int32 GetNumMaterials() const override; virtual UMaterialInterface* GetMaterial(int32 ElementIndex) const override; virtual FMaterialRelevance GetMaterialRelevance(ERHIFeatureLevel::Type InFeatureLevel) const override; virtual void SetMaterial(int32 ElementIndex, UMaterialInterface* Material) override; virtual void GetUsedMaterials(TArray& OutMaterials, bool bGetDebugMaterials = false) const override; virtual void SetNumMaterials(int32 NumMaterials); //~ UObject Interface. #if WITH_EDITOR void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; #endif UPROPERTY() TArray> BaseMaterials; };