2019-12-27 09:26:59 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-01 20:41:42 -04:00
# pragma once
# include "CoreMinimal.h"
# include "BaseDynamicMeshComponent.h"
# include "MeshConversionOptions.h"
2021-06-22 12:11:21 -04:00
# include "Components/MeshRenderDecomposition.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/MeshTangents.h"
2020-04-18 18:42:59 -04:00
# include "TransformTypes.h"
2021-01-28 01:46:53 -04:00
# include "Async/Future.h"
2021-06-10 18:37:57 -04:00
# include "UDynamicMesh.h"
2021-06-20 18:12:30 -04:00
# include "PhysicsEngine/BodySetup.h"
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
# include "DynamicMeshComponent.generated.h"
2019-10-01 20:41:42 -04:00
// predecl
struct FMeshDescription ;
2021-06-12 14:30:22 -04:00
/** internal FPrimitiveSceneProxy defined in DynamicMeshSceneProxy.h */
class FDynamicMeshSceneProxy ;
2021-06-20 18:12:30 -04:00
class FBaseDynamicMeshSceneProxy ;
2019-10-01 20:41:42 -04:00
2020-11-05 19:18:40 -04:00
/**
2021-06-12 14:30:22 -04:00
* Interface for a render mesh processor . Use this to process the Mesh stored in UDynamicMeshComponent before
2020-11-05 19:18:40 -04:00
* sending it off for rendering .
* NOTE : This is called whenever the Mesh is updated and before rendering , so performance matters .
*/
2021-06-22 12:11:21 -04:00
class GEOMETRYFRAMEWORK_API IRenderMeshPostProcessor
2020-11-05 19:18:40 -04:00
{
public :
virtual ~ IRenderMeshPostProcessor ( ) = default ;
virtual void ProcessMesh ( const FDynamicMesh3 & Mesh , FDynamicMesh3 & OutRenderMesh ) = 0 ;
} ;
2019-10-01 20:41:42 -04:00
2021-06-10 18:37:57 -04:00
/** Render data update hint */
UENUM ( )
enum class EDynamicMeshComponentRenderUpdateMode
{
/** Do not update render data */
NoUpdate = 0 ,
/** Invalidate overlay of internal component, rebuilding all render data */
FullUpdate = 1 ,
/** Attempt to do partial update of render data if possible */
FastUpdate = 2
} ;
2019-10-01 20:41:42 -04:00
/**
2021-06-12 14:30:22 -04:00
* UDynamicMeshComponent is a mesh component similar to UProceduralMeshComponent ,
2021-06-10 18:37:57 -04:00
* except it bases the renderable geometry off an internal UDynamicMesh instance ( which
* encapsulates a FDynamicMesh3 ) .
2019-10-01 20:41:42 -04:00
*
2021-06-10 18:37:57 -04:00
* There is extensive support for partial updates to render buffers , customizing colors ,
* internally decomposing the mesh into separate chunks for more efficient render updates ,
* and support for attaching a ' Postprocessor ' to generate a render mesh on - the - fly
* See comment sections below for details .
2019-10-01 20:41:42 -04:00
*
*/
2021-06-20 18:12:30 -04:00
UCLASS ( hidecategories = ( LOD ) , meta = ( BlueprintSpawnableComponent ) , ClassGroup = Rendering )
2021-06-22 12:11:21 -04:00
class GEOMETRYFRAMEWORK_API UDynamicMeshComponent : public UBaseDynamicMeshComponent , public IInterface_CollisionDataProvider
2019-10-01 20:41:42 -04:00
{
GENERATED_UCLASS_BODY ( )
2021-06-10 18:37:57 -04:00
//===============================================================================================================
2021-06-11 22:42:32 -04:00
// Mesh Access. Usage via GetDynamicMesh() or SetMesh()/ProcessMesh()/EditMesh() is preferred, the GetMesh()
// pointer access exist largely to support existing code from before UDynamicMesh was added.
2019-10-01 20:41:42 -04:00
public :
/**
2021-06-10 18:37:57 -04:00
* @ return pointer to internal mesh
* @ warning avoid usage of this function , access via GetDynamicMesh ( ) instead
2019-10-01 20:41:42 -04:00
*/
2021-06-10 18:37:57 -04:00
virtual FDynamicMesh3 * GetMesh ( ) override { return MeshObject - > GetMeshPtr ( ) ; }
2019-10-01 20:41:42 -04:00
/**
* @ return pointer to internal mesh
2021-06-10 18:37:57 -04:00
* @ warning avoid usage of this function , access via GetDynamicMesh ( ) instead
2019-10-01 20:41:42 -04:00
*/
2021-06-10 18:37:57 -04:00
virtual const FDynamicMesh3 * GetMesh ( ) const override { return MeshObject - > GetMeshPtr ( ) ; }
2019-10-01 20:41:42 -04:00
2020-01-27 20:11:15 -05:00
/**
2021-06-10 18:37:57 -04:00
* @ return the child UDynamicMesh
2020-01-27 20:11:15 -05:00
*/
2021-06-10 18:37:57 -04:00
//UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh Component")
virtual UDynamicMesh * GetDynamicMesh ( ) override { return MeshObject ; }
2020-11-05 19:18:40 -04:00
2019-10-01 20:41:42 -04:00
/**
2021-06-10 18:37:57 -04:00
* Set the child UDynamicMesh . This can be used to ' share ' a UDynamicMesh between Component instances .
* @ warning Currently this is somewhat risky , it is on the caller / clients to make sure that the actual mesh is not being simultaneously modified on multiple threads
2019-10-01 20:41:42 -04:00
*/
2021-06-10 18:37:57 -04:00
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void SetDynamicMesh ( UDynamicMesh * NewMesh ) ;
2019-10-01 20:41:42 -04:00
2021-06-11 22:42:32 -04:00
/**
* initialize the internal mesh from a DynamicMesh
*/
virtual void SetMesh ( UE : : Geometry : : FDynamicMesh3 & & MoveMesh ) override ;
/**
* Allow external code to read the internal mesh .
*/
virtual void ProcessMesh ( TFunctionRef < void ( const UE : : Geometry : : FDynamicMesh3 & ) > ProcessFunc ) const ;
/**
* Allow external code to to edit the internal mesh .
*/
virtual void EditMesh ( TFunctionRef < void ( UE : : Geometry : : FDynamicMesh3 & ) > EditFunc ,
EDynamicMeshComponentRenderUpdateMode UpdateMode = EDynamicMeshComponentRenderUpdateMode : : FullUpdate ) ;
/**
* Apply transform to internal mesh . In some cases this can be more efficient than a general edit .
* @ param bInvert if true , inverse tranform is applied instead of forward transform
*/
2022-01-29 14:37:53 -05:00
virtual void ApplyTransform ( const FTransform3d & Transform , bool bInvert ) override ;
2021-06-11 22:42:32 -04:00
2021-06-10 18:37:57 -04:00
protected :
2020-06-23 18:40:00 -04:00
/**
2021-06-10 18:37:57 -04:00
* Internal FDynamicMesh is stored inside a UDynamicMesh container , which allows it to be
* used from BP , shared with other UObjects , and so on
2020-06-23 18:40:00 -04:00
*/
2021-06-10 18:37:57 -04:00
UPROPERTY ( Instanced )
TObjectPtr < UDynamicMesh > MeshObject ;
2019-10-01 20:41:42 -04:00
2019-12-19 18:07:47 -05:00
2021-06-10 18:37:57 -04:00
//===============================================================================================================
// RenderBuffer Update API. These functions can be used by external code (and internally in some places)
// to tell the Component that the Mesh data has been modified in some way, and that the RenderBuffers in the RenderProxy
// need to be updated (or rebuilt entirely). On large meshes a full rebuild is expensive, so there are quite a few
// variants that can be used to minimize the amount of data updated in different situations.
2019-10-01 20:41:42 -04:00
//
2021-06-10 18:37:57 -04:00
public :
2019-10-01 20:41:42 -04:00
/**
2019-12-19 18:07:47 -05:00
* Call this if you update the mesh via GetMesh ( ) . This will destroy the existing RenderProxy and create a new one .
2019-10-01 20:41:42 -04:00
* @ todo should provide a function that calls a lambda to modify the mesh , and only return const mesh pointer
*/
virtual void NotifyMeshUpdated ( ) override ;
2019-12-19 18:07:47 -05:00
/**
* Call this instead of NotifyMeshUpdated ( ) if you have only updated the vertex colors ( or triangle color function ) .
* This function will update the existing RenderProxy buffers if possible
*/
void FastNotifyColorsUpdated ( ) ;
/**
2020-04-18 18:42:59 -04:00
* Call this instead of NotifyMeshUpdated ( ) if you have only updated the vertex positions ( and possibly some attributes ) .
2019-12-19 18:07:47 -05:00
* This function will update the existing RenderProxy buffers if possible
*/
2020-01-27 20:11:15 -05:00
void FastNotifyPositionsUpdated ( bool bNormals = false , bool bColors = false , bool bUVs = false ) ;
2020-04-18 18:42:59 -04:00
/**
* Call this instead of NotifyMeshUpdated ( ) if you have only updated the vertex attributes ( but not positions ) .
* This function will update the existing RenderProxy buffers if possible , rather than create new ones .
*/
void FastNotifyVertexAttributesUpdated ( bool bNormals , bool bColors , bool bUVs ) ;
/**
* Call this instead of NotifyMeshUpdated ( ) if you have only updated the vertex positions / attributes
* This function will update the existing RenderProxy buffers if possible , rather than create new ones .
*/
void FastNotifyVertexAttributesUpdated ( EMeshRenderAttributeFlags UpdatedAttributes ) ;
2020-01-27 20:11:15 -05:00
/**
* Call this instead of NotifyMeshUpdated ( ) if you have only updated the vertex uvs .
* This function will update the existing RenderProxy buffers if possible
*/
void FastNotifyUVsUpdated ( ) ;
/**
* Call this instead of NotifyMeshUpdated ( ) if you have only updated secondary triangle sorting .
* This function will update the existing buffers if possible , without rebuilding entire RenderProxy .
*/
void FastNotifySecondaryTrianglesChanged ( ) ;
2020-04-18 18:42:59 -04:00
/**
* This function updates vertex positions / attributes of existing SceneProxy render buffers if possible , for the given triangles .
* If a FMeshRenderDecomposition has not been explicitly set , call is forwarded to FastNotifyVertexAttributesUpdated ( )
*/
void FastNotifyTriangleVerticesUpdated ( const TArray < int32 > & Triangles , EMeshRenderAttributeFlags UpdatedAttributes ) ;
/**
* This function updates vertex positions / attributes of existing SceneProxy render buffers if possible , for the given triangles .
* If a FMeshRenderDecomposition has not been explicitly set , call is forwarded to FastNotifyVertexAttributesUpdated ( )
*/
void FastNotifyTriangleVerticesUpdated ( const TSet < int32 > & Triangles , EMeshRenderAttributeFlags UpdatedAttributes ) ;
2021-01-28 01:46:53 -04:00
/**
* If a Decomposition is set on this Component , and everything is currently valid ( proxy / etc ) , precompute the set of
* buffers that will be modified , as well as the bounds of the modified region . These are both computed in parallel .
2021-06-10 18:37:57 -04:00
* Use FastNotifyTriangleVerticesUpdated_ApplyPrecompute ( ) with the returned future to apply this precomputation .
2021-01-28 01:46:53 -04:00
* @ return a future that will ( eventually ) return true if the precompute is OK , and ( immediately ) false if it is not
*/
2021-03-09 19:33:56 -04:00
TFuture < bool > FastNotifyTriangleVerticesUpdated_TryPrecompute ( const TArray < int32 > & Triangles , TArray < int32 > & UpdateSetsOut , UE : : Geometry : : FAxisAlignedBox3d & BoundsOut ) ;
2021-01-28 01:46:53 -04:00
/**
* This function updates vertex positions / attributes of existing SceneProxy render buffers if possible , for the given triangles .
* The assumption is that FastNotifyTriangleVerticesUpdated_TryPrecompute ( ) was used to get the Precompute future , this function
* will Wait ( ) until it is done and then use the UpdateSets and UpdateSetBounds that were computed ( must be the same variables
* passed to FastNotifyTriangleVerticesUpdated_TryPrecompute ) .
* If the Precompute future returns false , then we forward the call to FastNotifyTriangleVerticesUpdated ( ) , which will do more work .
*/
void FastNotifyTriangleVerticesUpdated_ApplyPrecompute ( const TArray < int32 > & Triangles , EMeshRenderAttributeFlags UpdatedAttributes ,
2021-03-09 19:33:56 -04:00
TFuture < bool > & Precompute , const TArray < int32 > & UpdateSets , const UE : : Geometry : : FAxisAlignedBox3d & UpdateSetBounds ) ;
2021-01-28 01:46:53 -04:00
2019-12-19 18:07:47 -05:00
2021-06-10 18:37:57 -04:00
//===============================================================================================================
// Change Support. These changes are primarily used for Undo/Redo, however there is no strict assumption
// about this internally, objects of these change types could also be used to perform more structured editing.
// (Note that these functions simply forward the change events to the child UDynamicMesh, which will
// post a mesh-change event that
//
public :
2019-10-01 20:41:42 -04:00
/**
2021-06-10 18:37:57 -04:00
* Apply a vertex deformation change to the mesh
2019-10-01 20:41:42 -04:00
*/
virtual void ApplyChange ( const FMeshVertexChange * Change , bool bRevert ) override ;
/**
2021-06-10 18:37:57 -04:00
* Apply a general mesh change to the mesh
2019-10-01 20:41:42 -04:00
*/
virtual void ApplyChange ( const FMeshChange * Change , bool bRevert ) override ;
2019-12-19 18:07:47 -05:00
/**
2021-06-10 18:37:57 -04:00
* Apply a mesh replacement change to mesh
2019-12-19 18:07:47 -05:00
*/
virtual void ApplyChange ( const FMeshReplacementChange * Change , bool bRevert ) override ;
2019-10-01 20:41:42 -04:00
/**
2021-06-10 18:37:57 -04:00
* This delegate fires when the mesh has been changed
2019-10-01 20:41:42 -04:00
*/
FSimpleMulticastDelegate OnMeshChanged ;
2020-04-18 18:42:59 -04:00
/**
2021-06-10 18:37:57 -04:00
* This delegate fires when the mesh vertices have been changed via an FMeshVertexChange
2020-04-18 18:42:59 -04:00
*/
2021-06-12 14:30:22 -04:00
DECLARE_MULTICAST_DELEGATE_ThreeParams ( FMeshVerticesModified , UDynamicMeshComponent * , const FMeshVertexChange * , bool ) ;
2020-04-18 18:42:59 -04:00
FMeshVerticesModified OnMeshVerticesChanged ;
2019-10-01 20:41:42 -04:00
/**
2021-06-10 18:37:57 -04:00
* When a FMeshChange or FMeshVertexChange is applied , by default we currently fully invalidate the render proxy . However in certain
* realtime situations ( eg like Sculpting tools ) it can be critical to undo / redo performance to do more optimized render data updates
* ( eg using one of the FastXYZ functions above ) . To allow for that , the full proxy invalidation on change can be ( temporarily ! ) disabled
* using this function .
2019-10-01 20:41:42 -04:00
*/
2021-06-10 18:37:57 -04:00
void SetInvalidateProxyOnChangeEnabled ( bool bEnabled ) ;
2019-10-01 20:41:42 -04:00
2021-06-10 18:37:57 -04:00
/** @return true if InvalidateProxyOnChange is enabled (default) */
bool GetInvalidateProxyOnChangeEnabled ( ) const { return bInvalidateProxyOnChange ; }
2020-04-18 18:42:59 -04:00
2021-06-10 18:37:57 -04:00
protected :
/** If false, we don't completely invalidate the RenderProxy when ApplyChange() is called (assumption is it will be handled elsewhere) */
bool bInvalidateProxyOnChange = true ;
/** Handle for OnMeshObjectChanged which is registered with MeshObject::OnMeshChanged delegate */
FDelegateHandle MeshObjectChangedHandle ;
/** Called whenever internal MeshObject is modified, fires OnMeshChanged and OnMeshVerticesChanged above */
void OnMeshObjectChanged ( UDynamicMesh * ChangedMeshObject , FDynamicMeshChangeInfo ChangeInfo ) ;
2019-10-01 20:41:42 -04:00
2019-12-19 18:07:47 -05:00
2021-06-10 18:37:57 -04:00
//===============================================================================================================
// Support for specifying per-triangle colors as vertex colors. This allows external code to dynamically override
// the vertex colors on the rendered mesh. The lambda that is passed is held for the lifetime of the Component and
// must remain valid. A Material that uses the vertex colors must be applied, otherwise setting this override will
// have no visible effect. If the colors change externally, FastNotifyColorsUpdated() can be used to do the
// minimal vertex buffer updates necessary in the RenderProxy
//
public :
/** Clear an active triangle color function if one exists, and update the mesh */
virtual void SetTriangleColorFunction ( TUniqueFunction < FColor ( const FDynamicMesh3 * , int ) > TriangleColorFuncIn ,
EDynamicMeshComponentRenderUpdateMode UpdateMode = EDynamicMeshComponentRenderUpdateMode : : FastUpdate ) ;
/** Clear an active triangle color function if one exists, and update the mesh */
virtual void ClearTriangleColorFunction ( EDynamicMeshComponentRenderUpdateMode UpdateMode = EDynamicMeshComponentRenderUpdateMode : : FastUpdate ) ;
/** @return true if a triangle color function is configured */
virtual bool HasTriangleColorFunction ( ) ;
protected :
/** If this function is set, we will use these colors instead of vertex colors */
TUniqueFunction < FColor ( const FDynamicMesh3 * , int ) > TriangleColorFunc = nullptr ;
/** This function is passed via lambda to the RenderProxy to be able to access TriangleColorFunc */
FColor GetTriangleColor ( const FDynamicMesh3 * Mesh , int TriangleID ) ;
//===============================================================================================================
// Support for Secondary triangle index buffers. When this is configured, then triangles identified
// by the filtering predicate function will be placed in a second set of RenderBuffers at the SceneProxy level.
// This can be combined with the SecondaryRenderMaterial support in UBaseDynamicMeshComponent to draw
// that triangle set with a different material, to efficiently accomplish UI features like highlighting a
// subset of mesh triangles.
//
public :
2019-12-19 18:07:47 -05:00
/**
* If Secondary triangle buffers are enabled , then we will filter triangles that pass the given predicate
* function into a second index buffer . These triangles will be drawn with the Secondary render material
* that is set in the BaseDynamicMeshComponent . Calling this function invalidates the SceneProxy .
*/
virtual void EnableSecondaryTriangleBuffers ( TUniqueFunction < bool ( const FDynamicMesh3 * , int32 ) > SecondaryTriFilterFunc ) ;
/**
* Disable secondary triangle buffers . This invalidates the SceneProxy .
*/
virtual void DisableSecondaryTriangleBuffers ( ) ;
2021-06-10 18:37:57 -04:00
protected :
TUniqueFunction < bool ( const FDynamicMesh3 * , int32 ) > SecondaryTriFilterFunc = nullptr ;
//===============================================================================================================
// Support for a Render Decomposition, which is basically a segmentation of the mesh triangles into
// subsets which will be turned into separate RenderBuffers in the Render Proxy. If this is configured,
// then various of the FastNotifyXYZUpdated() functions above will only need to rebuild the RenderBuffers
// that include affected triangles. The FMeshRenderDecomposition implementation has various options for
// building decompositions based on material, spatial clustering, etc.
//
public :
2020-04-18 18:42:59 -04:00
/**
2021-06-10 18:37:57 -04:00
* Configure a decomposition of the mesh , which will result in separate render buffers for each
* decomposition triangle group . Invalidates existing SceneProxy .
2020-04-18 18:42:59 -04:00
*/
virtual void SetExternalDecomposition ( TUniquePtr < FMeshRenderDecomposition > Decomposition ) ;
2021-06-10 18:37:57 -04:00
protected :
TUniquePtr < FMeshRenderDecomposition > Decomposition ;
//===============================================================================================================
// IRenderMeshPostProcessor Support. If a RenderMesh Postprocessor is configured, then instead of directly
// passing the internal mesh to the RenderProxy, IRenderMeshPostProcessor::PostProcess is applied to populate
// the internal RenderMesh which is passed instead. This allows things like Displacement or Subdivision to be
// done on-the-fly at the rendering level (which is potentially more efficient).
//
public :
2020-11-05 19:18:40 -04:00
/**
* Add a render mesh processor , to be called before the mesh is sent for rendering .
*/
virtual void SetRenderMeshPostProcessor ( TUniquePtr < IRenderMeshPostProcessor > Processor ) ;
2019-12-19 18:07:47 -05:00
2021-06-10 18:37:57 -04:00
/**
* The SceneProxy should call these functions to get the post - processed RenderMesh . ( See IRenderMeshPostProcessor . )
*/
virtual FDynamicMesh3 * GetRenderMesh ( ) ;
/**
* The SceneProxy should call these functions to get the post - processed RenderMesh . ( See IRenderMeshPostProcessor . )
*/
virtual const FDynamicMesh3 * GetRenderMesh ( ) const ;
protected :
TUniquePtr < IRenderMeshPostProcessor > RenderMeshPostProcessor ;
TUniquePtr < FDynamicMesh3 > RenderMesh ;
//===============================================================================================================
// Support for Component attachment change notifications via delegates. Standard UE
// Actor/Component hierarchy does not generally provide these capabilities, but in some use
// cases (eg procedural mesh Actors) we need to know things like when the Component set inside
// an Actor is modified.
2019-12-19 18:07:47 -05:00
public :
2021-06-10 18:37:57 -04:00
DECLARE_MULTICAST_DELEGATE_TwoParams ( FComponentChildrenChangedDelegate , USceneComponent * , bool ) ;
/**
* The OnChildAttached ( ) and OnChildDetached ( ) implementations ( from USceneComponent API ) broadcast this delegate . This
2021-06-12 14:30:22 -04:00
* allows Actors that have UDynamicMeshComponent ' s to respond to changes in their Component hierarchy .
2021-06-10 18:37:57 -04:00
*/
FComponentChildrenChangedDelegate OnChildAttachmentModified ;
2019-12-19 18:07:47 -05:00
2019-10-01 20:41:42 -04:00
2021-09-15 21:24:22 -04:00
//===============================================================================================================
// Material Set API. DynamicMeshComponent supports changing the Material Set dynamically, even at Runtime.
public :
/**
* Set new list of Materials for the Mesh . Dynamic Mesh Component does not have
* Slot Names , so the size of the Material Set should be the same as the number of
* different Material IDs on the mesh MaterialID attribute
*/
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void ConfigureMaterialSet ( const TArray < UMaterialInterface * > & NewMaterialSet ) ;
/**
* Compute the maximum MaterialID on the DynamicMesh , and ensure that Material Slots match .
* Pass both arguments as false to just do a check .
* @ param bCreateIfMissing if true , add extra ( empty ) Material Slots to match max MaterialID
* @ param bDeleteExtraSlots if true , extra Material Slots beyond max MaterialID are removed
* @ return true if at the end of this function , Material Slot Count = = Max MaterialID
*/
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
bool ValidateMaterialSlots ( bool bCreateIfMissing = true , bool bDeleteExtraSlots = true ) ;
2019-10-01 20:41:42 -04:00
2021-06-11 22:42:32 -04:00
//===============================================================================================================
// Triangle-Vertex Tangents support. The default behavior is to not use Tangents, this will lead to incorrect
// rendering for any material with Normal Maps and some other shaders.
// If TangentsType == EDynamicMeshComponentTangentsMode::ExternallyProvided, the Tangent and Bitangent attributes of
// the FDynamicMesh3 AttributeSet are used at the SceneProxy level, the Component is not involved
// If TangentsType == EDynamicMeshComponentTangentsMode::AutoCalculated, the Tangents are computed internally using
// a fast MikkT approximation via FMeshTangentsf. They will be recomputed when the mesh is modified, however
// they are *not* recomputed when using the Fast Update functions above (in that case InvalidateAutoCalculatedTangents()
// can be used to force recomputation)
2021-06-10 18:37:57 -04:00
//
public :
2021-06-11 22:42:32 -04:00
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void SetTangentsType ( EDynamicMeshComponentTangentsMode NewTangentsType ) ;
2021-06-10 18:37:57 -04:00
2021-06-11 22:42:32 -04:00
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
EDynamicMeshComponentTangentsMode GetTangentsType ( ) const { return TangentsType ; }
2021-06-10 18:37:57 -04:00
2021-06-11 22:42:32 -04:00
/** This function marks the auto tangents as dirty, they will be recomputed before they are used again */
virtual void InvalidateAutoCalculatedTangents ( ) ;
2021-06-10 18:37:57 -04:00
2021-06-11 22:42:32 -04:00
/** @return AutoCalculated Tangent Set, which may require that they be recomputed, or nullptr if not enabled/available */
const UE : : Geometry : : FMeshTangentsf * GetAutoCalculatedTangents ( ) ;
2021-06-10 18:37:57 -04:00
protected :
2021-06-11 22:42:32 -04:00
/** How should Tangents be calculated/handled */
UPROPERTY ( )
EDynamicMeshComponentTangentsMode TangentsType = EDynamicMeshComponentTangentsMode : : NoTangents ;
/** true if AutoCalculatedTangents has been computed for current mesh */
bool bAutoCalculatedTangentsValid = false ;
/** Set of per-triangle-vertex tangents computed for the current mesh. Only valid if bAutoCalculatedTangentsValid == true */
UE : : Geometry : : FMeshTangentsf AutoCalculatedTangents ;
void UpdateAutoCalculatedTangents ( ) ;
2021-06-20 18:12:30 -04:00
//===============================================================================================================
//
// Physics APIs
//
public :
2021-11-04 10:22:38 -04:00
/**
* calls SetComplexAsSimpleCollisionEnabled ( true , true )
*/
2021-09-16 20:16:44 -04:00
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void EnableComplexAsSimpleCollision ( ) ;
2021-11-04 10:22:38 -04:00
/**
* If bEnabled = true , sets bEnableComplexCollision = true and CollisionType = CTF_UseComplexAsSimple
* If bEnabled = true , sets bEnableComplexCollision = false and CollisionType = CTF_UseDefault
* @ param bImmediateUpdate if true , UpdateCollision ( true ) is called
*/
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void SetComplexAsSimpleCollisionEnabled ( bool bEnabled , bool bImmediateUpdate = true ) ;
/**
* Set value of bDeferCollisionUpdates , when enabled , collision is not automatically recomputed each time the mesh changes .
* @ param bImmediateUpdate if true , UpdateCollision ( true ) is called if bEnabled = false , ie to force a collision rebuild
*/
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
void SetDeferredCollisionUpdatesEnabled ( bool bEnabled , bool bImmediateUpdate = true ) ;
2021-06-20 18:12:30 -04:00
virtual bool GetPhysicsTriMeshData ( struct FTriMeshCollisionData * CollisionData , bool InUseAllTriData ) override ;
virtual bool ContainsPhysicsTriMeshData ( bool InUseAllTriData ) const override ;
virtual bool WantsNegXTriMesh ( ) override ;
2021-11-26 16:37:25 -05:00
/** @return current BodySetup for this Component, or nullptr if it does not exist */
virtual const UBodySetup * GetBodySetup ( ) const { return MeshBodySetup ; }
/** @return BodySetup for this Component. A new BodySetup will be created if one does not exist. */
2021-06-20 18:12:30 -04:00
virtual UBodySetup * GetBodySetup ( ) override ;
2021-09-08 21:47:47 -04:00
/**
* Force an update of the Collision / Physics data for this Component .
* @ param bOnlyIfPending only update if a collision update is pending , ie the underlying DynamicMesh changed and bDeferCollisionUpdates is enabled
*/
2021-11-04 10:22:38 -04:00
UFUNCTION ( BlueprintCallable , Category = " Dynamic Mesh Component " )
virtual void UpdateCollision ( bool bOnlyIfPending = true ) ;
2021-09-08 21:47:47 -04:00
2021-06-20 18:12:30 -04:00
/** Type of Collision Geometry to use for this Mesh */
UPROPERTY ( EditAnywhere , BlueprintReadWrite , Category = " Dynamic Mesh Component|Collision " )
TEnumAsByte < enum ECollisionTraceFlag > CollisionType = ECollisionTraceFlag : : CTF_UseSimpleAsComplex ;
2022-03-11 23:38:07 -05:00
/**
* Update the simple collision shapes associated with this mesh component
*
* @ param AggGeom New simple collision shapes to be used
* @ param bUpdateCollision Whether to automatically call UpdateCollision ( ) - - if false , manually call it to register the change with the physics system
*/
virtual void SetSimpleCollisionShapes ( const struct FKAggregateGeom & AggGeom , bool bUpdateCollision ) ;
virtual struct FKAggregateGeom & GetSimpleCollisionShapes ( )
{
return AggGeom ;
}
/**
* Clear the simple collision shapes associated with this mesh component
* @ param bUpdateCollision Whether to automatically call UpdateCollision ( ) - - if false , manually call it to register the change with the physics system
*/
virtual void ClearSimpleCollisionShapes ( bool bUpdateCollision ) ;
/**
* Controls whether the physics cooking should be done off the game thread .
* This should be used when collision geometry doesn ' t have to be immediately up to date ( For example streaming in far away objects )
*/
UPROPERTY ( EditAnywhere , BlueprintReadOnly , Category = " Dynamic Mesh Component|Collision " )
bool bUseAsyncCooking = false ;
2021-09-08 21:47:47 -04:00
/**
* If true , current mesh will be used as Complex Collision source mesh .
* This is independent of the CollisionType setting , ie , even if Complex collision is enabled , if this is false , then the Complex Collision mesh will be empty
*/
2021-06-20 18:12:30 -04:00
UPROPERTY ( EditAnywhere , BlueprintReadWrite , Category = " Dynamic Mesh Component|Collision " ) ;
bool bEnableComplexCollision = false ;
/** If true, updates to the mesh will not result in immediate collision regeneration. Useful when the mesh will be modified multiple times before collision is needed. */
UPROPERTY ( EditAnywhere , BlueprintReadWrite , Category = " Dynamic Mesh Component|Collision " ) ;
bool bDeferCollisionUpdates = false ;
protected :
UPROPERTY ( Instanced )
TObjectPtr < UBodySetup > MeshBodySetup ;
virtual void InvalidatePhysicsData ( ) ;
virtual void RebuildPhysicsData ( ) ;
bool bCollisionUpdatePending = false ;
protected :
//
// standard Component internals, for computing bounds and managing the SceneProxy
//
/** Current local-space bounding box of Mesh */
UE : : Geometry : : FAxisAlignedBox3d LocalBounds ;
/** Recompute LocalBounds from the current Mesh */
void UpdateLocalBounds ( ) ;
2022-03-11 23:38:07 -05:00
//
// Internals for managing collision representation and setup
//
/** Simplified collision representation for the mesh component */
UPROPERTY ( EditAnywhere , Category = BodySetup , meta = ( DisplayName = " Primitives " , NoResetToDefault ) )
struct FKAggregateGeom AggGeom ;
/** Queue for async body setups that are being cooked */
UPROPERTY ( transient )
TArray < TObjectPtr < UBodySetup > > AsyncBodySetupQueue ;
/** Once async physics cook is done, create needed state */
virtual void FinishPhysicsAsyncCook ( bool bSuccess , UBodySetup * FinishedBodySetup ) ;
virtual UBodySetup * CreateBodySetupHelper ( ) ;
/** @return Set new BodySetup for this Component. */
virtual void SetBodySetup ( UBodySetup * NewSetup ) ;
2021-06-20 18:12:30 -04:00
/**
* This is called to tell our RenderProxy about modifications to the material set .
* We need to pass this on for things like material validation in the Editor .
*/
virtual void NotifyMaterialSetUpdated ( ) ;
/**
* If the render proxy is invalidated ( eg by MarkRenderStateDirty ( ) ) , it will be destroyed at the end of
* the frame , but the base SceneProxy pointer is not nulled out immediately . As a result if we call various
* partial - update functions after invalidating the proxy , they may be operating on an invalid proxy .
* So we have to keep track of proxy - valid state ourselves .
*/
bool bProxyValid = false ;
2022-02-14 12:20:58 -05:00
/**
* If true , the render proxy will verify that the mesh batch materials match the contents from
* the component GetUsedMaterials ( ) . Used material verification is prone to races when changing
* materials on this component in quick succession ( for example , SetOverrideRenderMaterial ) . This
* parameter is provided to allow clients to opt out of used material verification for these
* use cases .
*/
bool bProxyVerifyUsedMaterials = true ;
2021-06-20 18:12:30 -04:00
virtual FBaseDynamicMeshSceneProxy * GetBaseSceneProxy ( ) override { return ( FBaseDynamicMeshSceneProxy * ) GetCurrentSceneProxy ( ) ; }
/**
* @ return current render proxy , if valid , otherwise nullptr
*/
FDynamicMeshSceneProxy * GetCurrentSceneProxy ( ) ;
/**
* Fully invalidate all rendering data for this Component . Current Proxy will be discarded , Bounds and possibly Tangents recomputed , etc
*/
void ResetProxy ( ) ;
//~ Begin UPrimitiveComponent Interface.
virtual FPrimitiveSceneProxy * CreateSceneProxy ( ) override ;
//~ USceneComponent Interface.
virtual FBoxSphereBounds CalcBounds ( const FTransform & LocalToWorld ) const override ;
virtual void OnChildAttached ( USceneComponent * ChildComponent ) override ;
virtual void OnChildDetached ( USceneComponent * ChildComponent ) override ;
//~ UObject Interface.
virtual void PostLoad ( ) override ;
2022-03-11 23:38:07 -05:00
virtual void BeginDestroy ( ) override ;
2021-06-20 18:12:30 -04:00
# if WITH_EDITOR
void PostEditChangeProperty ( FPropertyChangedEvent & PropertyChangedEvent ) override ;
# endif
2022-02-14 12:20:58 -05:00
public :
/** Set whether or not to validate mesh batch materials against the component materials. */
void SetSceneProxyVerifyUsedMaterials ( bool bState ) ;
2021-06-20 18:12:30 -04:00
2019-10-01 20:41:42 -04:00
} ;