Files
UnrealEngineUWP/Engine/Source/Runtime/GeometryFramework/Public/Components/BaseDynamicMeshComponent.h
Ryan Schmidt 422c289493 GeometryFramework: add support for configuring color and normal overrides on BaseDynamicMeshComponent & DynamicMeshComponent. This allows the user to configure a DynamicMeshComponent to display vertex colors, group colors, or a (configurable) custom color, as well as facet normals, in the Actor properties.
A new lit vertex color material is added and used if the ModelingComponents module is loaded (to avoid adding a new engine material, if only GeometryFramework is loaded, then the engine-default vertex color material is used). This class-wide vertex color material can be overridden via UBaseDynamicMeshComponent::SetDefaultVertexColorMaterial()

Facet Normals / Flat Shading is now separately configurable, this overrides the normals at the vertexbuffer setup level, so it works independently of material.

Support also added for configuring the wireframe material used for BaseDynamicMeshComponent, and also for setting the wireframe color.

#preflight 62aa2330a40a4dc3a04052c6
#rb tyson.brochu

[CL 20676782 by Ryan Schmidt in ue5-main branch]
2022-06-15 16:49:13 -04:00

515 lines
17 KiB
C++

// 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
};
/**
* Color Override Modes
*/
UENUM()
enum class EDynamicMeshComponentColorOverrideMode : uint8
{
/** No Color Override enabled */
None,
/** Vertex Colors are displayed */
VertexColors,
/** Polygroup Colors are displayed */
Polygroups,
/** Constant Color is displayed */
Constant
};
/**
* 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<void(const UE::Geometry::FDynamicMesh3&)> 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; }
/**
* Constant Color used when Override Color Mode is set to Constant
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "Wireframe Color"))
FLinearColor WireframeColor = FLinearColor(0, 0.5f, 1.f);
//===============================================================================================================
// Built-in Color Rendering Support. When enabled, Color mode will override any assigned Materials.
// VertexColor mode displays vertex colors, Polygroup mode displays mesh polygroups via vertex colors,
// and Constant mode uses ConstantColor as the vertex color. The class-wide DefaultVertexColorMaterial
// is used as the material that displays the vertex colors, and cannot be overridden per-instance
// (the OverrideRenderMaterial can be used to do that)
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "Color Override") )
EDynamicMeshComponentColorOverrideMode ColorMode = EDynamicMeshComponentColorOverrideMode::None;
/**
* Configure the active Color Override
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual void SetColorOverrideMode(EDynamicMeshComponentColorOverrideMode NewMode);
/**
* @return active Color Override mode
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual EDynamicMeshComponentColorOverrideMode GetColorOverrideMode() const { return ColorMode; }
/**
* Constant Color used when Override Color Mode is set to Constant
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "Constant Color", EditCondition = "ColorMode==EDynamicMeshComponentColorOverrideMode::Constant"))
FColor ConstantColor = FColor::White;
/**
* Configure the Color used with Constant Color Override Mode
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual void SetConstantOverrideColor(FColor NewColor);
/**
* @return active Color used for Constant Color Override Mode
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual FColor GetConstantOverrideColor() const { return ConstantColor; }
//===============================================================================================================
// Flat shading support. When enabled, per-triangle normals are computed automatically and used in place
// of the mesh normals. Mesh tangents are not affected.
public:
/**
* Enable use of per-triangle facet normals in place of mesh normals
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dynamic Mesh Component|Rendering", meta = (DisplayName = "Flat Shading") )
bool bEnableFlatShading = false;
/**
* Configure the Color used with Constant Color Override Mode
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual void SetEnableFlatShading(bool bEnable);
/**
* @return active Color used for Constant Color Override Mode
*/
UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component|Rendering")
virtual bool GetFlatShadingEnabled() const { return bEnableFlatShading; }
//===============================================================================================================
// 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<UMaterialInterface> 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<UMaterialInterface> 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<UMaterialInterface*>& OutMaterials, bool bGetDebugMaterials = false) const override;
virtual void SetNumMaterials(int32 NumMaterials);
//~ UObject Interface.
#if WITH_EDITOR
void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
UPROPERTY()
TArray<TObjectPtr<UMaterialInterface>> BaseMaterials;
//===============================================================================================================
// Class-wide Default Materials used for Wireframe and VertexColor display mode.
// These are configured for the Editor when the module loads, defaulting to built-in Engine wireframe and
// vertex color materials.
// Note that the ModelingComponents module in the MeshModelingToolset plugin (usually enabled in the UE Editor)
// will set a new VertexColor material from that plugins Content.
// Client code can further configure these materials as necessary using the static functions below.
public:
/**
* Set the wireframe material used for all BaseDynamicMeshComponent-derived Components
*/
static void SetDefaultWireframeMaterial(UMaterialInterface* Material);
/**
* Set the vertex color material used for all BaseDynamicMeshComponent-derived Components
*/
static void SetDefaultVertexColorMaterial(UMaterialInterface* Material);
protected:
static void InitializeDefaultMaterials();
friend class FGeometryFrameworkModule; // FGeometryFrameworkModule needs to call the above function
static UMaterialInterface* GetDefaultWireframeMaterial_RenderThread();
static UMaterialInterface* GetDefaultVertexColorMaterial_RenderThread();
friend class FBaseDynamicMeshSceneProxy; // FBaseDynamicMeshSceneProxy needs to call these functions...
private:
// these Materials are used by the render thread. Once the engine is running they should not be modified without
// using SetDefaultWireframeMaterial/SetDefaultVertexColorMaterial
static UMaterialInterface* DefaultWireframeMaterial;
static UMaterialInterface* DefaultVertexColorMaterial;
};