2019-12-27 09:26:59 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
# include "Components/DynamicMeshComponent.h"
2019-10-01 20:41:42 -04:00
# include "PrimitiveSceneProxy.h"
# include "MaterialShared.h"
# include "Engine/CollisionProfile.h"
2022-10-26 12:57:32 -04:00
# include "Engine/World.h"
2019-10-01 20:41:42 -04:00
# include "Materials/Material.h"
2020-04-18 18:42:59 -04:00
# include "Async/Async.h"
2021-06-20 18:12:30 -04:00
# include "Engine/CollisionProfile.h"
2019-10-01 20:41:42 -04:00
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/DynamicMeshAttributeSet.h"
# include "DynamicMesh/MeshNormals.h"
2019-10-01 20:41:42 -04:00
# include "MeshDescriptionToDynamicMesh.h"
2022-06-15 16:49:13 -04:00
# include "Util/ColorConstants.h"
2019-10-01 20:41:42 -04:00
# include "Changes/MeshVertexChange.h"
# include "Changes/MeshChange.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/MeshTransforms.h"
2019-10-01 20:41:42 -04:00
2023-07-18 10:07:19 -04:00
# include "UObject/UE5ReleaseStreamObjectVersion.h"
2019-10-01 20:41:42 -04:00
// default proxy for this component
2021-06-12 14:30:22 -04:00
# include "Components/DynamicMeshSceneProxy.h"
2019-10-01 20:41:42 -04:00
2022-09-24 13:57:58 -04:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(DynamicMeshComponent)
2021-03-09 19:33:56 -04:00
using namespace UE : : Geometry ;
2019-10-01 20:41:42 -04:00
2021-01-28 01:46:53 -04:00
namespace
{
// probably should be something defined for the whole tool framework...
# if WITH_EDITOR
2021-06-12 14:30:22 -04:00
static EAsyncExecution DynamicMeshComponentAsyncExecTarget = EAsyncExecution : : LargeThreadPool ;
2021-01-28 01:46:53 -04:00
# else
2021-06-12 14:30:22 -04:00
static EAsyncExecution DynamicMeshComponentAsyncExecTarget = EAsyncExecution : : ThreadPool ;
2021-01-28 01:46:53 -04:00
# endif
}
2019-10-01 20:41:42 -04:00
2022-06-20 22:42:51 -04:00
namespace UELocal
{
static EMeshRenderAttributeFlags ConvertChangeFlagsToUpdateFlags ( EDynamicMeshAttributeChangeFlags ChangeFlags )
{
EMeshRenderAttributeFlags UpdateFlags = EMeshRenderAttributeFlags : : None ;
if ( ( ChangeFlags & EDynamicMeshAttributeChangeFlags : : VertexPositions ) ! = EDynamicMeshAttributeChangeFlags : : Unknown )
{
UpdateFlags | = EMeshRenderAttributeFlags : : Positions ;
}
if ( ( ChangeFlags & EDynamicMeshAttributeChangeFlags : : NormalsTangents ) ! = EDynamicMeshAttributeChangeFlags : : Unknown )
{
UpdateFlags | = EMeshRenderAttributeFlags : : VertexNormals ;
}
if ( ( ChangeFlags & EDynamicMeshAttributeChangeFlags : : VertexColors ) ! = EDynamicMeshAttributeChangeFlags : : Unknown )
{
UpdateFlags | = EMeshRenderAttributeFlags : : VertexColors ;
}
if ( ( ChangeFlags & EDynamicMeshAttributeChangeFlags : : UVs ) ! = EDynamicMeshAttributeChangeFlags : : Unknown )
{
UpdateFlags | = EMeshRenderAttributeFlags : : VertexUVs ;
}
return UpdateFlags ;
}
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
UDynamicMeshComponent : : UDynamicMeshComponent ( const FObjectInitializer & ObjectInitializer )
2019-10-01 20:41:42 -04:00
: Super ( ObjectInitializer )
{
PrimaryComponentTick . bCanEverTick = false ;
SetCollisionProfileName ( UCollisionProfile : : NoCollision_ProfileName ) ;
2021-06-10 18:37:57 -04:00
MeshObject = CreateDefaultSubobject < UDynamicMesh > ( TEXT ( " DynamicMesh " ) ) ;
//MeshObject->SetFlags(RF_Transactional);
2021-06-12 14:30:22 -04:00
MeshObjectChangedHandle = MeshObject - > OnMeshChanged ( ) . AddUObject ( this , & UDynamicMeshComponent : : OnMeshObjectChanged ) ;
2021-06-10 18:37:57 -04:00
2021-06-11 22:42:32 -04:00
ResetProxy ( ) ;
2021-06-10 18:37:57 -04:00
}
2023-07-18 10:07:19 -04:00
void UDynamicMeshComponent : : Serialize ( FArchive & Ar )
{
Super : : Serialize ( Ar ) ;
Ar . UsingCustomVersion ( FUE5ReleaseStreamObjectVersion : : GUID ) ;
}
2021-06-10 18:37:57 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : PostLoad ( )
2021-06-10 18:37:57 -04:00
{
Super : : PostLoad ( ) ;
2023-07-18 10:07:19 -04:00
const int32 UE5ReleaseStreamObjectVersion = GetLinkerCustomVersion ( FUE5ReleaseStreamObjectVersion : : GUID ) ;
if ( UE5ReleaseStreamObjectVersion < FUE5ReleaseStreamObjectVersion : : DynamicMeshComponentsDefaultUseExternalTangents )
{
// Set the old default value
if ( TangentsType = = EDynamicMeshComponentTangentsMode : : Default )
{
TangentsType = EDynamicMeshComponentTangentsMode : : NoTangents ;
}
}
2023-01-11 20:55:38 -05:00
// The intention here is that MeshObject is never nullptr, however we cannot guarantee this as a subclass
// may have set it to null, and/or some type of serialization issue has caused it to fail to save/load.
// Avoid immediate crashes by creating a new UDynamicMesh here in such cases
if ( ensure ( MeshObject ! = nullptr ) = = false )
{
MeshObject = NewObject < UDynamicMesh > ( this , TEXT ( " DynamicMesh " ) ) ;
}
2021-06-12 14:30:22 -04:00
MeshObjectChangedHandle = MeshObject - > OnMeshChanged ( ) . AddUObject ( this , & UDynamicMeshComponent : : OnMeshObjectChanged ) ;
2021-06-10 18:37:57 -04:00
ResetProxy ( ) ;
2021-06-20 18:12:30 -04:00
2021-09-13 14:56:25 -04:00
// This is a fixup for existing UDynamicMeshComponents that did not have the correct flags
// on the Instanced UBodySetup, these flags are now set in GetBodySetup() on new instances
if ( MeshBodySetup & & IsTemplate ( ) )
{
MeshBodySetup - > SetFlags ( RF_Public | RF_ArchetypeObject ) ;
}
2021-06-20 18:12:30 -04:00
// make sure BodySetup is created
GetBodySetup ( ) ;
2019-10-01 20:41:42 -04:00
}
2021-06-20 18:12:30 -04:00
# if WITH_EDITOR
void UDynamicMeshComponent : : PostEditChangeProperty ( FPropertyChangedEvent & PropertyChangedEvent )
{
Super : : PostEditChangeProperty ( PropertyChangedEvent ) ;
const FName PropName = PropertyChangedEvent . GetPropertyName ( ) ;
2023-07-18 10:07:19 -04:00
if ( PropName = = GET_MEMBER_NAME_CHECKED ( UDynamicMeshComponent , TangentsType ) )
{
InvalidateAutoCalculatedTangents ( ) ;
}
else if ( ( PropName = = GET_MEMBER_NAME_CHECKED ( UDynamicMeshComponent , bEnableComplexCollision ) ) | |
2021-06-20 18:12:30 -04:00
( PropName = = GET_MEMBER_NAME_CHECKED ( UDynamicMeshComponent , CollisionType ) ) | |
( PropName = = GET_MEMBER_NAME_CHECKED ( UDynamicMeshComponent , bDeferCollisionUpdates ) ) )
{
if ( bDeferCollisionUpdates )
{
InvalidatePhysicsData ( ) ;
}
else
{
RebuildPhysicsData ( ) ;
}
}
}
# endif
2021-06-11 22:42:32 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetMesh ( UE : : Geometry : : FDynamicMesh3 & & MoveMesh )
2021-06-11 22:42:32 -04:00
{
2023-11-28 09:50:36 -05:00
if ( ensureMsgf ( IsEditable ( ) , TEXT ( " Attempted to modify the internal mesh of a UDynamicMeshComponent that is not editable " ) ) )
{
MeshObject - > SetMesh ( MoveTemp ( MoveMesh ) ) ;
}
2021-06-11 22:42:32 -04:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ProcessMesh (
2021-06-11 22:42:32 -04:00
TFunctionRef < void ( const UE : : Geometry : : FDynamicMesh3 & ) > ProcessFunc ) const
{
MeshObject - > ProcessMesh ( ProcessFunc ) ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : EditMesh ( TFunctionRef < void ( UE : : Geometry : : FDynamicMesh3 & ) > EditFunc ,
2021-06-11 22:42:32 -04:00
EDynamicMeshComponentRenderUpdateMode UpdateMode )
{
2023-11-28 09:50:36 -05:00
if ( ensureMsgf ( IsEditable ( ) , TEXT ( " Attempted to modify the internal mesh of a UDynamicMeshComponent that is not editable " ) ) )
2021-06-11 22:42:32 -04:00
{
2023-11-28 09:50:36 -05:00
MeshObject - > EditMesh ( EditFunc ) ;
if ( UpdateMode ! = EDynamicMeshComponentRenderUpdateMode : : NoUpdate )
{
NotifyMeshUpdated ( ) ;
}
2021-06-11 22:42:32 -04:00
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetRenderMeshPostProcessor ( TUniquePtr < IRenderMeshPostProcessor > Processor )
2021-06-11 22:42:32 -04:00
{
RenderMeshPostProcessor = MoveTemp ( Processor ) ;
if ( RenderMeshPostProcessor )
{
if ( ! RenderMesh )
{
RenderMesh = MakeUnique < FDynamicMesh3 > ( * GetMesh ( ) ) ;
}
}
else
{
// No post processor, no render mesh
RenderMesh = nullptr ;
}
}
2021-06-12 14:30:22 -04:00
FDynamicMesh3 * UDynamicMeshComponent : : GetRenderMesh ( )
2020-11-05 19:18:40 -04:00
{
if ( RenderMeshPostProcessor & & RenderMesh )
{
return RenderMesh . Get ( ) ;
}
else
{
2021-06-10 18:37:57 -04:00
return GetMesh ( ) ;
2020-11-05 19:18:40 -04:00
}
}
2021-06-12 14:30:22 -04:00
const FDynamicMesh3 * UDynamicMeshComponent : : GetRenderMesh ( ) const
2020-11-05 19:18:40 -04:00
{
if ( RenderMeshPostProcessor & & RenderMesh )
{
return RenderMesh . Get ( ) ;
}
else
{
2021-06-10 18:37:57 -04:00
return GetMesh ( ) ;
2020-11-05 19:18:40 -04:00
}
}
2019-10-01 20:41:42 -04:00
2020-06-23 18:40:00 -04:00
2022-01-29 14:37:53 -05:00
void UDynamicMeshComponent : : ApplyTransform ( const FTransform3d & Transform , bool bInvert )
2020-04-18 18:42:59 -04:00
{
2023-11-28 09:50:36 -05:00
if ( ensureMsgf ( IsEditable ( ) , TEXT ( " Attempted to modify the internal mesh of a UDynamicMeshComponent that is not editable " ) ) )
2020-04-18 18:42:59 -04:00
{
2023-11-28 09:50:36 -05:00
MeshObject - > EditMesh ( [ & ] ( FDynamicMesh3 & EditMesh )
2019-10-01 20:41:42 -04:00
{
2023-11-28 09:50:36 -05:00
if ( bInvert )
{
MeshTransforms : : ApplyTransformInverse ( EditMesh , Transform , true ) ;
}
else
{
MeshTransforms : : ApplyTransform ( EditMesh , Transform , true ) ;
}
} , EDynamicMeshChangeType : : DeformationEdit ) ;
}
2019-10-01 20:41:42 -04:00
}
2021-09-15 21:24:22 -04:00
bool UDynamicMeshComponent : : ValidateMaterialSlots ( bool bCreateIfMissing , bool bDeleteExtraSlots )
{
int32 MaxMeshMaterialID = 0 ;
MeshObject - > ProcessMesh ( [ & ] ( const FDynamicMesh3 & EditMesh )
{
if ( EditMesh . HasAttributes ( ) & & EditMesh . Attributes ( ) - > HasMaterialID ( ) & & EditMesh . Attributes ( ) - > GetMaterialID ( ) ! = nullptr )
{
const FDynamicMeshMaterialAttribute * MaterialIDs = EditMesh . Attributes ( ) - > GetMaterialID ( ) ;
for ( int TriangleID : EditMesh . TriangleIndicesItr ( ) )
{
MaxMeshMaterialID = FMath : : Max ( MaxMeshMaterialID , MaterialIDs - > GetValue ( TriangleID ) ) ;
}
}
} ) ;
int32 NumRequiredMaterials = MaxMeshMaterialID + 1 ;
int32 NumMaterials = GetNumMaterials ( ) ;
if ( bCreateIfMissing & & NumMaterials < NumRequiredMaterials )
{
for ( int32 k = NumMaterials ; k < NumRequiredMaterials ; + + k )
{
SetMaterial ( k , nullptr ) ;
}
}
NumMaterials = GetNumMaterials ( ) ;
if ( bDeleteExtraSlots & & NumMaterials > NumRequiredMaterials )
{
SetNumMaterials ( NumRequiredMaterials ) ;
}
NumMaterials = GetNumMaterials ( ) ;
return ( NumMaterials = = NumRequiredMaterials ) ;
}
void UDynamicMeshComponent : : ConfigureMaterialSet ( const TArray < UMaterialInterface * > & NewMaterialSet )
{
for ( int k = 0 ; k < NewMaterialSet . Num ( ) ; + + k )
{
SetMaterial ( k , NewMaterialSet [ k ] ) ;
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetTangentsType ( EDynamicMeshComponentTangentsMode NewTangentsType )
2021-06-11 22:42:32 -04:00
{
if ( NewTangentsType ! = TangentsType )
{
TangentsType = NewTangentsType ;
InvalidateAutoCalculatedTangents ( ) ;
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : InvalidateAutoCalculatedTangents ( )
2021-06-11 22:42:32 -04:00
{
bAutoCalculatedTangentsValid = false ;
}
2021-06-12 14:30:22 -04:00
const UE : : Geometry : : FMeshTangentsf * UDynamicMeshComponent : : GetAutoCalculatedTangents ( )
2021-06-11 22:42:32 -04:00
{
2023-07-18 10:07:19 -04:00
if ( GetTangentsType ( ) = = EDynamicMeshComponentTangentsMode : : AutoCalculated & & GetDynamicMesh ( ) - > GetMeshRef ( ) . HasAttributes ( ) )
2021-06-11 22:42:32 -04:00
{
UpdateAutoCalculatedTangents ( ) ;
return ( bAutoCalculatedTangentsValid ) ? & AutoCalculatedTangents : nullptr ;
}
return nullptr ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : UpdateAutoCalculatedTangents ( )
2021-06-11 22:42:32 -04:00
{
2023-07-18 10:07:19 -04:00
if ( GetTangentsType ( ) = = EDynamicMeshComponentTangentsMode : : AutoCalculated & & bAutoCalculatedTangentsValid = = false )
2021-06-11 22:42:32 -04:00
{
GetDynamicMesh ( ) - > ProcessMesh ( [ & ] ( const FDynamicMesh3 & Mesh )
{
2021-09-08 21:47:47 -04:00
if ( Mesh . HasAttributes ( ) )
{
const FDynamicMeshUVOverlay * UVOverlay = Mesh . Attributes ( ) - > PrimaryUV ( ) ;
const FDynamicMeshNormalOverlay * NormalOverlay = Mesh . Attributes ( ) - > PrimaryNormals ( ) ;
if ( UVOverlay & & NormalOverlay )
{
AutoCalculatedTangents . SetMesh ( & Mesh ) ;
AutoCalculatedTangents . ComputeTriVertexTangents ( NormalOverlay , UVOverlay , FComputeTangentsOptions ( ) ) ;
AutoCalculatedTangents . SetMesh ( nullptr ) ;
2024-02-16 15:30:49 -05:00
bAutoCalculatedTangentsValid = true ;
2021-09-08 21:47:47 -04:00
}
}
2021-06-11 22:42:32 -04:00
} ) ;
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : UpdateLocalBounds ( )
2019-10-01 20:41:42 -04:00
{
2021-06-10 18:37:57 -04:00
LocalBounds = GetMesh ( ) - > GetBounds ( true ) ;
if ( LocalBounds . MaxDim ( ) < = 0 )
{
2021-10-05 13:22:31 -04:00
// If bbox is empty, set a very small bbox to avoid log spam/etc in other engine systems.
// The check used is generally IsNearlyZero(), which defaults to KINDA_SMALL_NUMBER, so set
// a slightly larger box here to be above that threshold
LocalBounds = FAxisAlignedBox3d ( FVector3d : : Zero ( ) , ( double ) ( KINDA_SMALL_NUMBER + SMALL_NUMBER ) ) ;
2021-06-10 18:37:57 -04:00
}
2019-10-01 20:41:42 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * UDynamicMeshComponent : : GetCurrentSceneProxy ( )
2021-06-10 18:37:57 -04:00
{
if ( bProxyValid )
{
2021-06-12 14:30:22 -04:00
return ( FDynamicMeshSceneProxy * ) SceneProxy ;
2021-06-10 18:37:57 -04:00
}
return nullptr ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ResetProxy ( )
2019-10-01 20:41:42 -04:00
{
2020-12-03 17:40:22 -04:00
bProxyValid = false ;
2021-06-11 22:42:32 -04:00
InvalidateAutoCalculatedTangents ( ) ;
2020-12-03 17:40:22 -04:00
2019-10-01 20:41:42 -04:00
// Need to recreate scene proxy to send it over
MarkRenderStateDirty ( ) ;
2021-06-10 18:37:57 -04:00
UpdateLocalBounds ( ) ;
2019-10-01 20:41:42 -04:00
UpdateBounds ( ) ;
2021-06-10 18:37:57 -04:00
// this seems speculative, ie we may not actually have a mesh update, but we currently ResetProxy() in lots
// of places where that is what it means
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2019-10-01 20:41:42 -04:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : NotifyMeshUpdated ( )
2020-11-05 19:18:40 -04:00
{
if ( RenderMeshPostProcessor )
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-11-05 19:18:40 -04:00
}
ResetProxy ( ) ;
}
2023-06-15 22:53:04 -04:00
void UDynamicMeshComponent : : NotifyMeshModified ( )
{
NotifyMeshUpdated ( ) ;
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyColorsUpdated ( )
2019-10-01 20:41:42 -04:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-11-05 19:18:40 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( Proxy )
2019-10-01 20:41:42 -04:00
{
2021-06-10 18:37:57 -04:00
if ( HasTriangleColorFunction ( ) & & Proxy - > bUsePerTriangleColor = = false )
2019-12-19 18:07:47 -05:00
{
Proxy - > bUsePerTriangleColor = true ;
Proxy - > PerTriangleColorFunc = [ this ] ( const FDynamicMesh3 * MeshIn , int TriangleID ) { return GetTriangleColor ( MeshIn , TriangleID ) ; } ;
}
2021-06-10 18:37:57 -04:00
else if ( ! HasTriangleColorFunction ( ) & & Proxy - > bUsePerTriangleColor = = true )
2019-12-19 18:07:47 -05:00
{
Proxy - > bUsePerTriangleColor = false ;
Proxy - > PerTriangleColorFunc = nullptr ;
}
2023-05-17 11:12:48 -04:00
if ( HasVertexColorRemappingFunction ( ) & & Proxy - > bApplyVertexColorRemapping = = false )
{
Proxy - > bApplyVertexColorRemapping = true ;
Proxy - > VertexColorRemappingFunc = [ this ] ( FVector4f & Color ) { RemapVertexColor ( Color ) ; } ;
}
else if ( ! HasVertexColorRemappingFunction ( ) & & Proxy - > bApplyVertexColorRemapping = = true )
{
Proxy - > bApplyVertexColorRemapping = false ;
Proxy - > VertexColorRemappingFunc = nullptr ;
}
2020-01-27 20:11:15 -05:00
Proxy - > FastUpdateVertices ( false , false , true , false ) ;
2019-12-19 18:07:47 -05:00
//MarkRenderDynamicDataDirty();
2019-10-01 20:41:42 -04:00
}
else
{
2020-11-05 19:18:40 -04:00
ResetProxy ( ) ;
2019-10-01 20:41:42 -04:00
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyPositionsUpdated ( bool bNormals , bool bColors , bool bUVs )
2019-10-01 20:41:42 -04:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-11-05 19:18:40 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( Proxy )
2019-10-01 20:41:42 -04:00
{
2021-01-28 01:46:53 -04:00
// calculate bounds while we are updating vertices
TFuture < void > UpdateBoundsCalc ;
2021-06-12 14:30:22 -04:00
UpdateBoundsCalc = Async ( DynamicMeshComponentAsyncExecTarget , [ this ] ( )
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastPositionsUpdate_AsyncBoundsUpdate ) ;
2021-06-10 18:37:57 -04:00
UpdateLocalBounds ( ) ;
2021-01-28 01:46:53 -04:00
} ) ;
2020-01-27 20:11:15 -05:00
GetCurrentSceneProxy ( ) - > FastUpdateVertices ( true , bNormals , bColors , bUVs ) ;
2021-06-10 18:37:57 -04:00
2019-12-19 18:07:47 -05:00
//MarkRenderDynamicDataDirty();
MarkRenderTransformDirty ( ) ;
2021-01-28 01:46:53 -04:00
UpdateBoundsCalc . Wait ( ) ;
2019-12-19 18:07:47 -05:00
UpdateBounds ( ) ;
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2019-10-01 20:41:42 -04:00
}
else
{
2020-11-05 19:18:40 -04:00
ResetProxy ( ) ;
2019-10-01 20:41:42 -04:00
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyVertexAttributesUpdated ( bool bNormals , bool bColors , bool bUVs )
2020-01-27 20:11:15 -05:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-11-05 19:18:40 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( Proxy & & ensure ( bNormals | | bColors | | bUVs ) )
2020-01-27 20:11:15 -05:00
{
2020-04-18 18:42:59 -04:00
GetCurrentSceneProxy ( ) - > FastUpdateVertices ( false , bNormals , bColors , bUVs ) ;
2020-01-27 20:11:15 -05:00
//MarkRenderDynamicDataDirty();
2020-04-18 18:42:59 -04:00
//MarkRenderTransformDirty();
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-01-27 20:11:15 -05:00
}
else
{
2020-11-05 19:18:40 -04:00
ResetProxy ( ) ;
2020-01-27 20:11:15 -05:00
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyVertexAttributesUpdated ( EMeshRenderAttributeFlags UpdatedAttributes )
2020-04-18 18:42:59 -04:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-11-05 19:18:40 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( Proxy & & ensure ( UpdatedAttributes ! = EMeshRenderAttributeFlags : : None ) )
2020-04-18 18:42:59 -04:00
{
bool bPositions = ( UpdatedAttributes & EMeshRenderAttributeFlags : : Positions ) ! = EMeshRenderAttributeFlags : : None ;
2021-01-28 01:46:53 -04:00
// calculate bounds while we are updating vertices
TFuture < void > UpdateBoundsCalc ;
if ( bPositions )
{
2021-06-12 14:30:22 -04:00
UpdateBoundsCalc = Async ( DynamicMeshComponentAsyncExecTarget , [ this ] ( )
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexAttribUpdate_AsyncBoundsUpdate ) ;
2021-06-10 18:37:57 -04:00
UpdateLocalBounds ( ) ;
2021-01-28 01:46:53 -04:00
} ) ;
}
2020-04-18 18:42:59 -04:00
GetCurrentSceneProxy ( ) - > FastUpdateVertices ( bPositions ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexNormals ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexColors ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexUVs ) ! = EMeshRenderAttributeFlags : : None ) ;
if ( bPositions )
{
MarkRenderTransformDirty ( ) ;
2021-01-28 01:46:53 -04:00
UpdateBoundsCalc . Wait ( ) ;
2020-04-18 18:42:59 -04:00
UpdateBounds ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-04-18 18:42:59 -04:00
}
else
{
2020-11-05 19:18:40 -04:00
ResetProxy ( ) ;
2020-04-18 18:42:59 -04:00
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyUVsUpdated ( )
2020-04-18 18:42:59 -04:00
{
2020-04-20 16:42:20 -04:00
FastNotifyVertexAttributesUpdated ( EMeshRenderAttributeFlags : : VertexUVs ) ;
2020-04-18 18:42:59 -04:00
}
2023-06-15 22:53:04 -04:00
void UDynamicMeshComponent : : NotifyMeshVertexAttributesModified ( bool bPositions , bool bNormals , bool bUVs , bool bColors )
{
EMeshRenderAttributeFlags Flags = EMeshRenderAttributeFlags : : None ;
if ( bPositions )
{
Flags | = EMeshRenderAttributeFlags : : Positions ;
}
if ( bNormals )
{
Flags | = EMeshRenderAttributeFlags : : VertexNormals ;
}
if ( bUVs )
{
Flags | = EMeshRenderAttributeFlags : : VertexUVs ;
}
if ( bColors )
{
Flags | = EMeshRenderAttributeFlags : : VertexColors ;
}
if ( Flags = = EMeshRenderAttributeFlags : : None )
{
return ;
}
FastNotifyVertexAttributesUpdated ( Flags ) ;
}
2020-01-27 20:11:15 -05:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifySecondaryTrianglesChanged ( )
2020-01-27 20:11:15 -05:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-11-05 19:18:40 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( Proxy )
2020-01-27 20:11:15 -05:00
{
GetCurrentSceneProxy ( ) - > FastUpdateAllIndexBuffers ( ) ;
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-01-27 20:11:15 -05:00
}
else
{
2020-11-05 19:18:40 -04:00
ResetProxy ( ) ;
2020-01-27 20:11:15 -05:00
}
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyTriangleVerticesUpdated ( const TArray < int32 > & Triangles , EMeshRenderAttributeFlags UpdatedAttributes )
2020-04-18 18:42:59 -04:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-04-18 18:42:59 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-01-24 16:05:21 -04:00
bool bUpdateSecondarySort = ( SecondaryTriFilterFunc ) & &
( ( UpdatedAttributes & EMeshRenderAttributeFlags : : SecondaryIndexBuffers ) ! = EMeshRenderAttributeFlags : : None ) ;
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( ! Proxy )
2020-11-05 19:18:40 -04:00
{
ResetProxy ( ) ;
2020-04-18 18:42:59 -04:00
}
else if ( ! Decomposition )
{
FastNotifyVertexAttributesUpdated ( UpdatedAttributes ) ;
2021-01-24 16:05:21 -04:00
if ( bUpdateSecondarySort )
{
Proxy - > FastUpdateAllIndexBuffers ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-04-18 18:42:59 -04:00
}
else
{
2021-01-28 01:46:53 -04:00
// compute list of sets to update
2020-04-18 18:42:59 -04:00
TArray < int32 > UpdatedSets ;
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_FindSets ) ;
for ( int32 tid : Triangles )
{
int32 SetID = Decomposition - > GetGroupForTriangle ( tid ) ;
UpdatedSets . AddUnique ( SetID ) ;
}
2020-04-18 18:42:59 -04:00
}
bool bPositions = ( UpdatedAttributes & EMeshRenderAttributeFlags : : Positions ) ! = EMeshRenderAttributeFlags : : None ;
2021-01-28 01:46:53 -04:00
// calculate bounds while we are updating vertices
TFuture < void > UpdateBoundsCalc ;
if ( bPositions )
{
2021-06-12 14:30:22 -04:00
UpdateBoundsCalc = Async ( DynamicMeshComponentAsyncExecTarget , [ this ] ( )
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_AsyncBoundsUpdate ) ;
2021-06-10 18:37:57 -04:00
UpdateLocalBounds ( ) ;
2021-01-28 01:46:53 -04:00
} ) ;
}
// update the render buffers
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_ApplyUpdate ) ;
Proxy - > FastUpdateVertices ( UpdatedSets , bPositions ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexNormals ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexColors ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexUVs ) ! = EMeshRenderAttributeFlags : : None ) ;
}
2020-04-18 18:42:59 -04:00
2021-01-24 16:05:21 -04:00
if ( bUpdateSecondarySort )
{
Proxy - > FastUpdateIndexBuffers ( UpdatedSets ) ;
}
2020-04-18 18:42:59 -04:00
if ( bPositions )
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_FinalPositionsUpdate ) ;
2020-04-18 18:42:59 -04:00
MarkRenderTransformDirty ( ) ;
2021-01-28 01:46:53 -04:00
UpdateBoundsCalc . Wait ( ) ;
2020-04-18 18:42:59 -04:00
UpdateBounds ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-04-18 18:42:59 -04:00
}
}
2021-01-28 01:46:53 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyTriangleVerticesUpdated ( const TSet < int32 > & Triangles , EMeshRenderAttributeFlags UpdatedAttributes )
2020-04-18 18:42:59 -04:00
{
2020-12-03 17:40:22 -04:00
// should not be using fast paths if we have to run mesh postprocessor
if ( ensure ( ! RenderMeshPostProcessor ) = = false )
2020-04-18 18:42:59 -04:00
{
2021-06-10 18:37:57 -04:00
RenderMeshPostProcessor - > ProcessMesh ( * GetMesh ( ) , * RenderMesh ) ;
2020-12-03 17:40:22 -04:00
ResetProxy ( ) ;
return ;
2020-11-05 19:18:40 -04:00
}
2021-01-24 16:05:21 -04:00
bool bUpdateSecondarySort = ( SecondaryTriFilterFunc ) & &
( ( UpdatedAttributes & EMeshRenderAttributeFlags : : SecondaryIndexBuffers ) ! = EMeshRenderAttributeFlags : : None ) ;
2020-11-05 19:18:40 -04:00
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2020-12-03 17:40:22 -04:00
if ( ! Proxy )
2020-11-05 19:18:40 -04:00
{
ResetProxy ( ) ;
2020-04-18 18:42:59 -04:00
}
else if ( ! Decomposition )
{
FastNotifyVertexAttributesUpdated ( UpdatedAttributes ) ;
2021-01-24 16:05:21 -04:00
if ( bUpdateSecondarySort )
{
Proxy - > FastUpdateAllIndexBuffers ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-04-18 18:42:59 -04:00
}
else
{
2021-01-28 01:46:53 -04:00
// compute list of sets to update
2020-04-18 18:42:59 -04:00
TArray < int32 > UpdatedSets ;
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_FindSets ) ;
for ( int32 tid : Triangles )
{
int32 SetID = Decomposition - > GetGroupForTriangle ( tid ) ;
UpdatedSets . AddUnique ( SetID ) ;
}
2020-04-18 18:42:59 -04:00
}
bool bPositions = ( UpdatedAttributes & EMeshRenderAttributeFlags : : Positions ) ! = EMeshRenderAttributeFlags : : None ;
// calculate bounds while we are updating vertices
TFuture < void > UpdateBoundsCalc ;
if ( bPositions )
{
2021-06-12 14:30:22 -04:00
UpdateBoundsCalc = Async ( DynamicMeshComponentAsyncExecTarget , [ this ] ( )
2020-04-18 18:42:59 -04:00
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_AsyncBoundsUpdate ) ;
2021-06-10 18:37:57 -04:00
UpdateLocalBounds ( ) ;
2020-04-18 18:42:59 -04:00
} ) ;
}
2021-01-28 01:46:53 -04:00
// update the render buffers
2021-01-24 16:05:21 -04:00
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_ApplyUpdate ) ;
Proxy - > FastUpdateVertices ( UpdatedSets , bPositions ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexNormals ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexColors ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexUVs ) ! = EMeshRenderAttributeFlags : : None ) ;
2021-01-24 16:05:21 -04:00
}
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_UpdateIndexBuffers ) ;
if ( bUpdateSecondarySort )
{
Proxy - > FastUpdateIndexBuffers ( UpdatedSets ) ;
}
}
// finish up, have to wait for background bounds recalculation here
2020-04-18 18:42:59 -04:00
if ( bPositions )
{
2021-01-28 01:46:53 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_FinalPositionsUpdate ) ;
2020-04-18 18:42:59 -04:00
MarkRenderTransformDirty ( ) ;
UpdateBoundsCalc . Wait ( ) ;
UpdateBounds ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2020-04-18 18:42:59 -04:00
}
}
2021-01-28 01:46:53 -04:00
/**
* Compute the combined bounding - box of the Triangles array in parallel , by computing
* partial boxes for subsets of this array , and then combining those boxes .
* TODO : this should move to a pulbic utility function , and possibly the block - based ParallelFor
* should be refactored out into something more general , as this pattern is useful in many places . . .
*/
static FAxisAlignedBox3d ParallelComputeROIBounds ( const FDynamicMesh3 & Mesh , const TArray < int32 > & Triangles )
{
FAxisAlignedBox3d FinalBounds = FAxisAlignedBox3d : : Empty ( ) ;
FCriticalSection FinalBoundsLock ;
int32 N = Triangles . Num ( ) ;
constexpr int32 BlockSize = 4096 ;
int32 Blocks = ( N / BlockSize ) + 1 ;
ParallelFor ( Blocks , [ & ] ( int bi )
{
FAxisAlignedBox3d BlockBounds = FAxisAlignedBox3d : : Empty ( ) ;
for ( int32 k = 0 ; k < BlockSize ; + + k )
{
int32 i = bi * BlockSize + k ;
if ( i < N )
{
int32 tid = Triangles [ i ] ;
const FIndex3i & TriV = Mesh . GetTriangleRef ( tid ) ;
BlockBounds . Contain ( Mesh . GetVertexRef ( TriV . A ) ) ;
BlockBounds . Contain ( Mesh . GetVertexRef ( TriV . B ) ) ;
BlockBounds . Contain ( Mesh . GetVertexRef ( TriV . C ) ) ;
}
}
FinalBoundsLock . Lock ( ) ;
FinalBounds . Contain ( BlockBounds ) ;
FinalBoundsLock . Unlock ( ) ;
} ) ;
return FinalBounds ;
}
2021-06-12 14:30:22 -04:00
TFuture < bool > UDynamicMeshComponent : : FastNotifyTriangleVerticesUpdated_TryPrecompute (
2021-01-28 01:46:53 -04:00
const TArray < int32 > & Triangles ,
TArray < int32 > & UpdateSetsOut ,
FAxisAlignedBox3d & BoundsOut )
{
if ( ( ! ! RenderMeshPostProcessor ) | | ( GetCurrentSceneProxy ( ) = = nullptr ) | | ( ! Decomposition ) )
{
// is there a simpler way to do this? cannot seem to just make a TFuture<bool>...
2021-06-12 14:30:22 -04:00
return Async ( DynamicMeshComponentAsyncExecTarget , [ ] ( ) { return false ; } ) ;
2021-01-28 01:46:53 -04:00
}
2021-06-12 14:30:22 -04:00
return Async ( DynamicMeshComponentAsyncExecTarget , [ this , & Triangles , & UpdateSetsOut , & BoundsOut ] ( )
2021-01-28 01:46:53 -04:00
{
2021-06-12 14:30:22 -04:00
TFuture < void > ComputeBounds = Async ( DynamicMeshComponentAsyncExecTarget , [ this , & BoundsOut , & Triangles ] ( )
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdatePrecomp_CalcBounds ) ;
2021-06-10 18:37:57 -04:00
BoundsOut = ParallelComputeROIBounds ( * GetMesh ( ) , Triangles ) ;
2021-01-28 01:46:53 -04:00
} ) ;
2021-06-12 14:30:22 -04:00
TFuture < void > ComputeSets = Async ( DynamicMeshComponentAsyncExecTarget , [ this , & UpdateSetsOut , & Triangles ] ( )
2021-01-28 01:46:53 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdatePrecomp_FindSets ) ;
2021-01-28 20:32:26 -04:00
int32 NumBuffers = Decomposition - > Num ( ) ;
TArray < std : : atomic < bool > > BufferFlags ;
BufferFlags . SetNum ( NumBuffers ) ;
for ( int32 k = 0 ; k < NumBuffers ; + + k )
2021-01-28 01:46:53 -04:00
{
2021-01-28 20:32:26 -04:00
BufferFlags [ k ] = false ;
2021-01-28 01:46:53 -04:00
}
2021-01-28 20:32:26 -04:00
ParallelFor ( Triangles . Num ( ) , [ & ] ( int32 k )
{
int32 SetID = Decomposition - > GetGroupForTriangle ( Triangles [ k ] ) ;
BufferFlags [ SetID ] = true ;
} ) ;
UpdateSetsOut . Reset ( ) ;
for ( int32 k = 0 ; k < NumBuffers ; + + k )
{
if ( BufferFlags [ k ] )
{
UpdateSetsOut . Add ( k ) ;
}
}
2021-01-28 01:46:53 -04:00
} ) ;
ComputeSets . Wait ( ) ;
ComputeBounds . Wait ( ) ;
2021-06-10 18:37:57 -04:00
2021-01-28 01:46:53 -04:00
return true ;
} ) ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : FastNotifyTriangleVerticesUpdated_ApplyPrecompute (
2021-01-28 01:46:53 -04:00
const TArray < int32 > & Triangles ,
EMeshRenderAttributeFlags UpdatedAttributes ,
TFuture < bool > & Precompute ,
const TArray < int32 > & UpdateSets ,
const FAxisAlignedBox3d & UpdateSetBounds )
{
Precompute . Wait ( ) ;
bool bPrecomputeOK = Precompute . Get ( ) ;
if ( bPrecomputeOK = = false | | GetCurrentSceneProxy ( ) = = nullptr )
{
FastNotifyTriangleVerticesUpdated ( Triangles , UpdatedAttributes ) ;
return ;
}
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) ;
2021-01-28 01:46:53 -04:00
bool bPositions = ( UpdatedAttributes & EMeshRenderAttributeFlags : : Positions ) ! = EMeshRenderAttributeFlags : : None ;
bool bUpdateSecondarySort = ( SecondaryTriFilterFunc ) & &
( ( UpdatedAttributes & EMeshRenderAttributeFlags : : SecondaryIndexBuffers ) ! = EMeshRenderAttributeFlags : : None ) ;
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_ApplyUpdate ) ;
Proxy - > FastUpdateVertices ( UpdateSets , bPositions ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexNormals ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexColors ) ! = EMeshRenderAttributeFlags : : None ,
( UpdatedAttributes & EMeshRenderAttributeFlags : : VertexUVs ) ! = EMeshRenderAttributeFlags : : None ) ;
}
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_UpdateIndexBuffers ) ;
if ( bUpdateSecondarySort )
{
Proxy - > FastUpdateIndexBuffers ( UpdateSets ) ;
}
}
if ( bPositions )
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SimpleDynamicMeshComponent_FastVertexUpdate_FinalPositionsUpdate ) ;
MarkRenderTransformDirty ( ) ;
LocalBounds . Contain ( UpdateSetBounds ) ;
UpdateBounds ( ) ;
}
2021-06-10 18:37:57 -04:00
GetDynamicMesh ( ) - > PostRealtimeUpdate ( ) ;
2021-01-28 01:46:53 -04:00
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
FPrimitiveSceneProxy * UDynamicMeshComponent : : CreateSceneProxy ( )
2019-10-01 20:41:42 -04:00
{
2020-12-03 17:40:22 -04:00
// if this is not always the case, we have made incorrect assumptions
ensure ( GetCurrentSceneProxy ( ) = = nullptr ) ;
2019-12-19 18:07:47 -05:00
2021-06-12 14:30:22 -04:00
FDynamicMeshSceneProxy * NewProxy = nullptr ;
2021-06-10 18:37:57 -04:00
if ( GetMesh ( ) - > TriangleCount ( ) > 0 )
2019-10-01 20:41:42 -04:00
{
2021-06-12 14:30:22 -04:00
NewProxy = new FDynamicMeshSceneProxy ( this ) ;
2019-10-01 20:41:42 -04:00
if ( TriangleColorFunc )
{
2019-12-19 18:07:47 -05:00
NewProxy - > bUsePerTriangleColor = true ;
NewProxy - > PerTriangleColorFunc = [ this ] ( const FDynamicMesh3 * MeshIn , int TriangleID ) { return GetTriangleColor ( MeshIn , TriangleID ) ; } ;
2019-10-01 20:41:42 -04:00
}
2022-06-15 16:49:13 -04:00
else if ( GetColorOverrideMode ( ) = = EDynamicMeshComponentColorOverrideMode : : Polygroups )
{
NewProxy - > bUsePerTriangleColor = true ;
NewProxy - > PerTriangleColorFunc = [ this ] ( const FDynamicMesh3 * MeshIn , int TriangleID ) { return GetGroupColor ( MeshIn , TriangleID ) ; } ;
}
2019-10-01 20:41:42 -04:00
2023-05-17 11:12:48 -04:00
if ( HasVertexColorRemappingFunction ( ) )
{
NewProxy - > bApplyVertexColorRemapping = true ;
NewProxy - > VertexColorRemappingFunc = [ this ] ( FVector4f & Color ) { RemapVertexColor ( Color ) ; } ;
}
2019-12-19 18:07:47 -05:00
if ( SecondaryTriFilterFunc )
{
NewProxy - > bUseSecondaryTriBuffers = true ;
NewProxy - > SecondaryTriFilterFunc = [ this ] ( const FDynamicMesh3 * MeshIn , int32 TriangleID )
{
return ( SecondaryTriFilterFunc ) ? SecondaryTriFilterFunc ( MeshIn , TriangleID ) : false ;
} ;
}
2020-04-18 18:42:59 -04:00
if ( Decomposition )
{
NewProxy - > InitializeFromDecomposition ( Decomposition ) ;
}
else
{
NewProxy - > Initialize ( ) ;
}
2022-02-14 12:20:58 -05:00
NewProxy - > SetVerifyUsedMaterials ( bProxyVerifyUsedMaterials ) ;
2019-10-01 20:41:42 -04:00
}
2020-12-03 17:40:22 -04:00
bProxyValid = true ;
2019-12-19 18:07:47 -05:00
return NewProxy ;
2019-10-01 20:41:42 -04:00
}
2019-12-19 18:07:47 -05:00
2020-12-03 17:40:22 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : NotifyMaterialSetUpdated ( )
2019-10-01 20:41:42 -04:00
{
2019-12-19 18:07:47 -05:00
if ( GetCurrentSceneProxy ( ) ! = nullptr )
{
GetCurrentSceneProxy ( ) - > UpdatedReferencedMaterials ( ) ;
}
2019-10-01 20:41:42 -04:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetTriangleColorFunction (
2021-06-10 18:37:57 -04:00
TUniqueFunction < FColor ( const FDynamicMesh3 * , int ) > TriangleColorFuncIn ,
EDynamicMeshComponentRenderUpdateMode UpdateMode )
{
TriangleColorFunc = MoveTemp ( TriangleColorFuncIn ) ;
if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FastUpdate )
{
FastNotifyColorsUpdated ( ) ;
}
else if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FullUpdate )
{
NotifyMeshUpdated ( ) ;
}
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ClearTriangleColorFunction ( EDynamicMeshComponentRenderUpdateMode UpdateMode )
2021-06-10 18:37:57 -04:00
{
if ( TriangleColorFunc )
{
TriangleColorFunc = nullptr ;
if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FastUpdate )
{
FastNotifyColorsUpdated ( ) ;
}
else if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FullUpdate )
{
NotifyMeshUpdated ( ) ;
}
}
}
2021-06-12 14:30:22 -04:00
bool UDynamicMeshComponent : : HasTriangleColorFunction ( )
2021-06-10 18:37:57 -04:00
{
return ! ! TriangleColorFunc ;
}
2019-12-19 18:07:47 -05:00
2023-05-17 11:12:48 -04:00
void UDynamicMeshComponent : : SetVertexColorRemappingFunction (
TUniqueFunction < void ( FVector4f & ) > ColorMapFuncIn ,
EDynamicMeshComponentRenderUpdateMode UpdateMode )
{
VertexColorMappingFunc = MoveTemp ( ColorMapFuncIn ) ;
if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FastUpdate )
{
FastNotifyColorsUpdated ( ) ;
}
else if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FullUpdate )
{
NotifyMeshUpdated ( ) ;
}
}
void UDynamicMeshComponent : : ClearVertexColorRemappingFunction ( EDynamicMeshComponentRenderUpdateMode UpdateMode )
{
if ( VertexColorMappingFunc )
{
VertexColorMappingFunc = nullptr ;
if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FastUpdate )
{
FastNotifyColorsUpdated ( ) ;
}
else if ( UpdateMode = = EDynamicMeshComponentRenderUpdateMode : : FullUpdate )
{
NotifyMeshUpdated ( ) ;
}
}
}
bool UDynamicMeshComponent : : HasVertexColorRemappingFunction ( )
{
return ! ! VertexColorMappingFunc ;
}
void UDynamicMeshComponent : : RemapVertexColor ( FVector4f & VertexColorInOut )
{
if ( VertexColorMappingFunc )
{
VertexColorMappingFunc ( VertexColorInOut ) ;
}
}
2019-12-19 18:07:47 -05:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : EnableSecondaryTriangleBuffers ( TUniqueFunction < bool ( const FDynamicMesh3 * , int32 ) > SecondaryTriFilterFuncIn )
2019-12-19 18:07:47 -05:00
{
SecondaryTriFilterFunc = MoveTemp ( SecondaryTriFilterFuncIn ) ;
NotifyMeshUpdated ( ) ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : DisableSecondaryTriangleBuffers ( )
2019-12-19 18:07:47 -05:00
{
SecondaryTriFilterFunc = nullptr ;
NotifyMeshUpdated ( ) ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetExternalDecomposition ( TUniquePtr < FMeshRenderDecomposition > DecompositionIn )
2020-04-18 18:42:59 -04:00
{
2022-08-24 16:13:55 -04:00
ensure ( DecompositionIn - > Num ( ) > 0 ) ;
2020-04-18 18:42:59 -04:00
Decomposition = MoveTemp ( DecompositionIn ) ;
NotifyMeshUpdated ( ) ;
}
2019-12-19 18:07:47 -05:00
2021-06-12 14:30:22 -04:00
FColor UDynamicMeshComponent : : GetTriangleColor ( const FDynamicMesh3 * MeshIn , int TriangleID )
2019-10-01 20:41:42 -04:00
{
if ( TriangleColorFunc )
{
2019-11-09 21:49:15 -05:00
return TriangleColorFunc ( MeshIn , TriangleID ) ;
2019-10-01 20:41:42 -04:00
}
else
{
return ( TriangleID % 2 = = 0 ) ? FColor : : Red : FColor : : White ;
}
}
2022-06-15 16:49:13 -04:00
FColor UDynamicMeshComponent : : GetGroupColor ( const FDynamicMesh3 * Mesh , int TriangleID ) const
{
int32 GroupID = Mesh - > HasTriangleGroups ( ) ? Mesh - > GetTriangleGroup ( TriangleID ) : 0 ;
return UE : : Geometry : : LinearColors : : SelectFColor ( GroupID ) ;
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
FBoxSphereBounds UDynamicMeshComponent : : CalcBounds ( const FTransform & LocalToWorld ) const
2019-10-01 20:41:42 -04:00
{
2019-12-19 18:07:47 -05:00
// can get a tighter box by calculating in world space, but we care more about performance
FBox LocalBoundingBox = ( FBox ) LocalBounds ;
FBoxSphereBounds Ret ( LocalBoundingBox . TransformBy ( LocalToWorld ) ) ;
Ret . BoxExtent * = BoundsScale ;
Ret . SphereRadius * = BoundsScale ;
return Ret ;
2019-10-01 20:41:42 -04:00
}
2021-06-10 18:37:57 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetInvalidateProxyOnChangeEnabled ( bool bEnabled )
2019-10-01 20:41:42 -04:00
{
2021-06-10 18:37:57 -04:00
bInvalidateProxyOnChange = bEnabled ;
2019-10-01 20:41:42 -04:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ApplyChange ( const FMeshVertexChange * Change , bool bRevert )
2021-06-10 18:37:57 -04:00
{
// will fire UDynamicMesh::MeshChangedEvent, which will call OnMeshObjectChanged() below to invalidate proxy, fire change events, etc
MeshObject - > ApplyChange ( Change , bRevert ) ;
}
2019-10-01 20:41:42 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ApplyChange ( const FMeshChange * Change , bool bRevert )
2019-10-01 20:41:42 -04:00
{
2021-06-10 18:37:57 -04:00
// will fire UDynamicMesh::MeshChangedEvent, which will call OnMeshObjectChanged() below to invalidate proxy, fire change events, etc
MeshObject - > ApplyChange ( Change , bRevert ) ;
2019-12-19 18:07:47 -05:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : ApplyChange ( const FMeshReplacementChange * Change , bool bRevert )
2019-12-19 18:07:47 -05:00
{
2021-06-10 18:37:57 -04:00
// will fire UDynamicMesh::MeshChangedEvent, which will call OnMeshObjectChanged() below to invalidate proxy, fire change events, etc
MeshObject - > ApplyChange ( Change , bRevert ) ;
}
2019-12-19 18:07:47 -05:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : OnMeshObjectChanged ( UDynamicMesh * ChangedMeshObject , FDynamicMeshChangeInfo ChangeInfo )
2021-06-10 18:37:57 -04:00
{
bool bIsFChange = (
ChangeInfo . Type = = EDynamicMeshChangeType : : MeshChange
| | ChangeInfo . Type = = EDynamicMeshChangeType : : MeshVertexChange
| | ChangeInfo . Type = = EDynamicMeshChangeType : : MeshReplacementChange ) ;
if ( bIsFChange )
{
if ( bInvalidateProxyOnChange )
{
NotifyMeshUpdated ( ) ;
}
OnMeshChanged . Broadcast ( ) ;
if ( ChangeInfo . Type = = EDynamicMeshChangeType : : MeshVertexChange )
{
OnMeshVerticesChanged . Broadcast ( this , ChangeInfo . VertexChange , ChangeInfo . bIsRevertChange ) ;
}
}
else
2020-04-18 18:42:59 -04:00
{
2022-06-20 22:42:51 -04:00
if ( ChangeInfo . Type = = EDynamicMeshChangeType : : DeformationEdit )
{
// if ChangeType is a vertex deformation, we can do a fast-update of the vertex buffers
// without fully rebuilding the SceneProxy
EMeshRenderAttributeFlags UpdateFlags = UELocal : : ConvertChangeFlagsToUpdateFlags ( ChangeInfo . Flags ) ;
FastNotifyVertexAttributesUpdated ( UpdateFlags ) ;
}
else
{
NotifyMeshUpdated ( ) ;
}
2021-06-10 18:37:57 -04:00
OnMeshChanged . Broadcast ( ) ;
2020-04-18 18:42:59 -04:00
}
2021-06-20 18:12:30 -04:00
// Rebuild body setup. Should this be deferred until proxy creation? Sometimes multiple changes are emitted...
// todo: can possibly skip this in some change situations, eg if only changing attributes
2022-06-28 14:14:26 -04:00
if ( bDeferCollisionUpdates | | bTransientDeferCollisionUpdates )
2021-06-20 18:12:30 -04:00
{
InvalidatePhysicsData ( ) ;
}
else
{
RebuildPhysicsData ( ) ;
}
2021-06-10 18:37:57 -04:00
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : SetDynamicMesh ( UDynamicMesh * NewMesh )
2021-06-10 18:37:57 -04:00
{
if ( ensure ( NewMesh ) = = false )
{
return ;
}
if ( ensure ( MeshObject ) )
{
MeshObject - > OnMeshChanged ( ) . Remove ( MeshObjectChangedHandle ) ;
}
2023-06-15 22:53:04 -04:00
// set Outer of NewMesh to be this Component, ie transfer ownership. This is done via "renaming", which is
// a bit odd, so the flags prevent some standard "renaming" behaviors from happening
NewMesh - > Rename ( nullptr , this , REN_DontCreateRedirectors | REN_ForceNoResetLoaders ) ;
2021-06-10 18:37:57 -04:00
MeshObject = NewMesh ;
2021-06-12 14:30:22 -04:00
MeshObjectChangedHandle = MeshObject - > OnMeshChanged ( ) . AddUObject ( this , & UDynamicMeshComponent : : OnMeshObjectChanged ) ;
2021-06-10 18:37:57 -04:00
NotifyMeshUpdated ( ) ;
2019-12-19 18:07:47 -05:00
OnMeshChanged . Broadcast ( ) ;
2021-06-20 18:12:30 -04:00
// Rebuild physics data
2022-06-28 14:14:26 -04:00
if ( bDeferCollisionUpdates | | bTransientDeferCollisionUpdates )
2021-06-20 18:12:30 -04:00
{
InvalidatePhysicsData ( ) ;
}
else
{
RebuildPhysicsData ( ) ;
}
2019-12-19 18:07:47 -05:00
}
2021-06-10 18:37:57 -04:00
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : OnChildAttached ( USceneComponent * ChildComponent )
2021-06-10 18:37:57 -04:00
{
Super : : OnChildAttached ( ChildComponent ) ;
OnChildAttachmentModified . Broadcast ( ChildComponent , true ) ;
}
2021-06-12 14:30:22 -04:00
void UDynamicMeshComponent : : OnChildDetached ( USceneComponent * ChildComponent )
2021-06-10 18:37:57 -04:00
{
Super : : OnChildDetached ( ChildComponent ) ;
OnChildAttachmentModified . Broadcast ( ChildComponent , false ) ;
}
2021-06-20 18:12:30 -04:00
bool UDynamicMeshComponent : : GetPhysicsTriMeshData ( struct FTriMeshCollisionData * CollisionData , bool InUseAllTriData )
{
// todo: support UPhysicsSettings::Get()->bSupportUVFromHitResults
// this is something we currently assume, if you hit this ensure, we made a mistake
ensure ( bEnableComplexCollision ) ;
ProcessMesh ( [ & ] ( const FDynamicMesh3 & Mesh )
{
2024-03-25 17:25:33 -04:00
const FDynamicMeshMaterialAttribute * MaterialAttrib = Mesh . HasAttributes ( ) & & Mesh . Attributes ( ) - > HasMaterialID ( ) ? Mesh . Attributes ( ) - > GetMaterialID ( ) : nullptr ;
2021-06-20 18:12:30 -04:00
TArray < int32 > VertexMap ;
bool bIsSparseV = ! Mesh . IsCompactV ( ) ;
if ( bIsSparseV )
{
VertexMap . SetNum ( Mesh . MaxVertexID ( ) ) ;
}
// copy vertices
CollisionData - > Vertices . Reserve ( Mesh . VertexCount ( ) ) ;
for ( int32 vid : Mesh . VertexIndicesItr ( ) )
{
2022-02-02 07:59:31 -05:00
int32 Index = CollisionData - > Vertices . Add ( ( FVector3f ) Mesh . GetVertex ( vid ) ) ;
2021-06-20 18:12:30 -04:00
if ( bIsSparseV )
{
VertexMap [ vid ] = Index ;
}
else
{
check ( vid = = Index ) ;
}
}
// copy triangles
CollisionData - > Indices . Reserve ( Mesh . TriangleCount ( ) ) ;
CollisionData - > MaterialIndices . Reserve ( Mesh . TriangleCount ( ) ) ;
for ( int32 tid : Mesh . TriangleIndicesItr ( ) )
{
FIndex3i Tri = Mesh . GetTriangle ( tid ) ;
FTriIndices Triangle ;
Triangle . v0 = ( bIsSparseV ) ? VertexMap [ Tri . A ] : Tri . A ;
Triangle . v1 = ( bIsSparseV ) ? VertexMap [ Tri . B ] : Tri . B ;
Triangle . v2 = ( bIsSparseV ) ? VertexMap [ Tri . C ] : Tri . C ;
2022-09-09 10:37:31 -04:00
// Filter out triangles which will cause physics system to emit degenerate-geometry warnings.
// These checks reproduce tests in Chaos::CleanTrimesh
const FVector3f & A = CollisionData - > Vertices [ Triangle . v0 ] ;
const FVector3f & B = CollisionData - > Vertices [ Triangle . v1 ] ;
const FVector3f & C = CollisionData - > Vertices [ Triangle . v2 ] ;
if ( A = = B | | A = = C | | B = = C )
{
continue ;
}
// anything that fails the first check should also fail this, but Chaos does both so doing the same here...
const float SquaredArea = FVector3f : : CrossProduct ( A - B , A - C ) . SizeSquared ( ) ;
if ( SquaredArea < UE_SMALL_NUMBER )
{
continue ;
}
2021-06-20 18:12:30 -04:00
CollisionData - > Indices . Add ( Triangle ) ;
2024-03-25 17:25:33 -04:00
int32 MaterialID = MaterialAttrib ? MaterialAttrib - > GetValue ( tid ) : 0 ;
CollisionData - > MaterialIndices . Add ( MaterialID ) ;
2021-06-20 18:12:30 -04:00
}
CollisionData - > bFlipNormals = true ;
CollisionData - > bDeformableMesh = true ;
CollisionData - > bFastCook = true ;
} ) ;
return true ;
}
bool UDynamicMeshComponent : : ContainsPhysicsTriMeshData ( bool InUseAllTriData ) const
{
return bEnableComplexCollision & & ( ( MeshObject ! = nullptr ) ? ( MeshObject - > GetTriangleCount ( ) > 0 ) : false ) ;
}
bool UDynamicMeshComponent : : WantsNegXTriMesh ( )
{
return true ;
}
2022-03-11 23:38:07 -05:00
UBodySetup * UDynamicMeshComponent : : CreateBodySetupHelper ( )
{
UBodySetup * NewBodySetup = nullptr ;
{
FGCScopeGuard Scope ;
// Below flags are copied from UProceduralMeshComponent::CreateBodySetupHelper(). Without these flags, DynamicMeshComponents inside
// a DynamicMeshActor BP will result on a GLEO error after loading and modifying a saved Level (but *not* on the initial save)
// The UBodySetup in a template needs to be public since the property is Instanced and thus is the archetype of the instance meaning there is a direct reference
NewBodySetup = NewObject < UBodySetup > ( this , NAME_None , ( IsTemplate ( ) ? RF_Public | RF_ArchetypeObject : RF_NoFlags ) ) ;
}
NewBodySetup - > BodySetupGuid = FGuid : : NewGuid ( ) ;
NewBodySetup - > bGenerateMirroredCollision = false ;
NewBodySetup - > CollisionTraceFlag = this - > CollisionType ;
NewBodySetup - > DefaultInstance . SetCollisionProfileName ( UCollisionProfile : : BlockAll_ProfileName ) ;
NewBodySetup - > bSupportUVsAndFaceRemap = false ; /* bSupportPhysicalMaterialMasks; */
return NewBodySetup ;
}
2021-06-20 18:12:30 -04:00
UBodySetup * UDynamicMeshComponent : : GetBodySetup ( )
{
if ( MeshBodySetup = = nullptr )
{
2022-03-11 23:38:07 -05:00
UBodySetup * NewBodySetup = CreateBodySetupHelper ( ) ;
2021-06-20 18:12:30 -04:00
SetBodySetup ( NewBodySetup ) ;
}
return MeshBodySetup ;
}
void UDynamicMeshComponent : : SetBodySetup ( UBodySetup * NewSetup )
{
if ( ensure ( NewSetup ) )
{
MeshBodySetup = NewSetup ;
}
}
2022-03-11 23:38:07 -05:00
void UDynamicMeshComponent : : SetSimpleCollisionShapes ( const struct FKAggregateGeom & AggGeomIn , bool bUpdateCollision )
{
AggGeom = AggGeomIn ;
if ( bUpdateCollision )
{
UpdateCollision ( false ) ;
}
}
void UDynamicMeshComponent : : ClearSimpleCollisionShapes ( bool bUpdateCollision )
{
AggGeom . EmptyElements ( ) ;
if ( bUpdateCollision )
{
UpdateCollision ( false ) ;
}
}
2021-06-20 18:12:30 -04:00
void UDynamicMeshComponent : : InvalidatePhysicsData ( )
{
if ( GetBodySetup ( ) )
{
GetBodySetup ( ) - > InvalidatePhysicsData ( ) ;
bCollisionUpdatePending = true ;
}
}
void UDynamicMeshComponent : : RebuildPhysicsData ( )
{
2022-03-11 23:38:07 -05:00
UWorld * World = GetWorld ( ) ;
const bool bUseAsyncCook = World & & World - > IsGameWorld ( ) & & bUseAsyncCooking ;
UBodySetup * BodySetup = nullptr ;
if ( bUseAsyncCook )
{
// Abort all previous ones still standing
for ( UBodySetup * OldBody : AsyncBodySetupQueue )
{
OldBody - > AbortPhysicsMeshAsyncCreation ( ) ;
}
BodySetup = CreateBodySetupHelper ( ) ;
if ( BodySetup )
{
AsyncBodySetupQueue . Add ( BodySetup ) ;
}
}
else
{
AsyncBodySetupQueue . Empty ( ) ; // If for some reason we modified the async at runtime, just clear any pending async body setups
BodySetup = GetBodySetup ( ) ;
}
if ( ! BodySetup )
{
return ;
}
BodySetup - > CollisionTraceFlag = this - > CollisionType ;
// Note: Directly assigning AggGeom wouldn't do some important-looking cleanup (clearing pointers on convex elements)
// so we RemoveSimpleCollision then AddCollisionFrom instead
BodySetup - > RemoveSimpleCollision ( ) ;
BodySetup - > AddCollisionFrom ( this - > AggGeom ) ;
if ( bUseAsyncCook )
{
BodySetup - > CreatePhysicsMeshesAsync ( FOnAsyncPhysicsCookFinished : : CreateUObject ( this , & UDynamicMeshComponent : : FinishPhysicsAsyncCook , BodySetup ) ) ;
}
else
2021-06-20 18:12:30 -04:00
{
// New GUID as collision has changed
BodySetup - > BodySetupGuid = FGuid : : NewGuid ( ) ;
// Also we want cooked data for this
BodySetup - > bHasCookedCollisionData = true ;
BodySetup - > InvalidatePhysicsData ( ) ;
BodySetup - > CreatePhysicsMeshes ( ) ;
RecreatePhysicsState ( ) ;
bCollisionUpdatePending = false ;
}
}
2022-03-11 23:38:07 -05:00
void UDynamicMeshComponent : : FinishPhysicsAsyncCook ( bool bSuccess , UBodySetup * FinishedBodySetup )
{
TArray < UBodySetup * > NewQueue ;
NewQueue . Reserve ( AsyncBodySetupQueue . Num ( ) ) ;
int32 FoundIdx ;
if ( AsyncBodySetupQueue . Find ( FinishedBodySetup , FoundIdx ) )
{
// Note: currently no-cook-needed is reported identically to cook failed.
// Checking AggGeom.GetElemCount() here is a hack to distinguish the no-cook-needed case
// TODO: remove this hack to distinguish the no-cook-needed case when/if that is no longer identical to the cook failed case
if ( bSuccess | | FinishedBodySetup - > AggGeom . GetElementCount ( ) > 0 )
{
// The new body was found in the array meaning it's newer, so use it
MeshBodySetup = FinishedBodySetup ;
RecreatePhysicsState ( ) ;
// remove any async body setups that were requested before this one
for ( int32 AsyncIdx = FoundIdx + 1 ; AsyncIdx < AsyncBodySetupQueue . Num ( ) ; + + AsyncIdx )
{
NewQueue . Add ( AsyncBodySetupQueue [ AsyncIdx ] ) ;
}
AsyncBodySetupQueue = NewQueue ;
}
else
{
AsyncBodySetupQueue . RemoveAt ( FoundIdx ) ;
}
}
}
2021-06-20 18:12:30 -04:00
void UDynamicMeshComponent : : UpdateCollision ( bool bOnlyIfPending )
{
if ( bOnlyIfPending = = false | | bCollisionUpdatePending )
{
RebuildPhysicsData ( ) ;
}
2021-09-16 20:16:44 -04:00
}
2022-03-11 23:38:07 -05:00
void UDynamicMeshComponent : : BeginDestroy ( )
{
Super : : BeginDestroy ( ) ;
AggGeom . FreeRenderInfo ( ) ;
}
2021-09-16 20:16:44 -04:00
void UDynamicMeshComponent : : EnableComplexAsSimpleCollision ( )
{
2021-11-04 10:22:38 -04:00
SetComplexAsSimpleCollisionEnabled ( true , true ) ;
}
void UDynamicMeshComponent : : SetComplexAsSimpleCollisionEnabled ( bool bEnabled , bool bImmediateUpdate )
{
bool bModified = false ;
if ( bEnabled )
{
if ( bEnableComplexCollision = = false )
{
bEnableComplexCollision = true ;
bModified = true ;
}
if ( CollisionType ! = ECollisionTraceFlag : : CTF_UseComplexAsSimple )
{
CollisionType = ECollisionTraceFlag : : CTF_UseComplexAsSimple ;
bModified = true ;
}
}
else
{
if ( bEnableComplexCollision = = true )
{
bEnableComplexCollision = false ;
bModified = true ;
}
if ( CollisionType = = ECollisionTraceFlag : : CTF_UseComplexAsSimple )
{
CollisionType = ECollisionTraceFlag : : CTF_UseDefault ;
bModified = true ;
}
}
if ( bModified )
{
InvalidatePhysicsData ( ) ;
}
if ( bImmediateUpdate )
{
UpdateCollision ( true ) ;
}
}
void UDynamicMeshComponent : : SetDeferredCollisionUpdatesEnabled ( bool bEnabled , bool bImmediateUpdate )
{
if ( bDeferCollisionUpdates ! = bEnabled )
{
bDeferCollisionUpdates = bEnabled ;
if ( bEnabled = = false & & bImmediateUpdate )
{
UpdateCollision ( true ) ;
}
}
}
2022-02-14 12:20:58 -05:00
2022-06-28 14:14:26 -04:00
void UDynamicMeshComponent : : SetTransientDeferCollisionUpdates ( bool bEnabled )
{
2022-07-15 17:53:52 -04:00
bTransientDeferCollisionUpdates = bEnabled ;
2022-06-28 14:14:26 -04:00
}
2022-02-14 12:20:58 -05:00
void UDynamicMeshComponent : : SetSceneProxyVerifyUsedMaterials ( bool bState )
{
bProxyVerifyUsedMaterials = bState ;
if ( FDynamicMeshSceneProxy * Proxy = GetCurrentSceneProxy ( ) )
{
Proxy - > SetVerifyUsedMaterials ( bState ) ;
}
}
2022-09-24 13:57:58 -04:00