2022-06-01 21:41:57 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "GeometryCollection/GeometryCollectionEngineConversion.h"
# include "AssetRegistry/AssetRegistryModule.h"
# include "AnimationRuntime.h"
# include "Async/ParallelFor.h"
# include "Components/SkeletalMeshComponent.h"
# include "Components/StaticMeshComponent.h"
# include "Engine/Selection.h"
2022-10-26 12:57:32 -04:00
# include "Engine/SkeletalMesh.h"
# include "Engine/SkinnedAssetCommon.h"
2022-06-01 21:41:57 -04:00
# include "Engine/StaticMesh.h"
# include "GameFramework/Actor.h"
2024-04-03 22:22:28 -04:00
# include "GeometryCollection/Facades/CollectionInstancedMeshFacade.h"
# include "GeometryCollection/Facades/CollectionTransformFacade.h"
2022-09-21 11:52:44 -04:00
# include "GeometryCollection/Facades/CollectionTransformSourceFacade.h"
2022-06-01 21:41:57 -04:00
# include "GeometryCollection/GeometryCollection.h"
# include "GeometryCollection/GeometryCollectionActor.h"
# include "GeometryCollection/GeometryCollectionAlgo.h"
# include "GeometryCollection/GeometryCollectionComponent.h"
# include "GeometryCollection/GeometryCollectionClusteringUtility.h"
2024-04-03 22:22:28 -04:00
# include "GeometryCollection/GeometryCollectionEngineUtility.h"
2022-06-01 21:41:57 -04:00
# include "GeometryCollection/GeometryCollectionUtility.h"
2024-04-03 22:22:28 -04:00
# include "GeometryCollectionProxyData.h"
# include "IndexTypes.h"
2022-06-01 21:41:57 -04:00
# include "Logging/LogMacros.h"
2022-12-15 16:01:51 -05:00
# include "MaterialDomain.h"
2022-06-01 21:41:57 -04:00
# include "Materials/Material.h"
# include "MeshDescription.h"
2024-04-03 22:22:28 -04:00
# include "MeshDescriptionBuilder.h"
2023-08-30 20:50:47 -04:00
# include "Misc/ScopedSlowTask.h"
2022-06-01 21:41:57 -04:00
# include "Physics/Experimental/ChaosInterfaceUtils.h"
2022-06-23 17:00:03 -04:00
# include "PhysicsEngine/BodySetup.h"
2024-04-03 22:22:28 -04:00
# include "Rendering/SkeletalMeshRenderData.h"
# include "SkeletalMeshAttributes.h"
# include "StaticMeshAttributes.h"
# include "StaticMeshOperations.h"
2022-08-18 15:37:22 -04:00
# include "VertexConnectedComponents.h"
2024-04-03 22:22:28 -04:00
# include "Util/ColorConstants.h"
2022-06-01 21:41:57 -04:00
DEFINE_LOG_CATEGORY_STATIC ( UGeometryCollectionConversionLogging , Log , All ) ;
2023-08-30 20:50:47 -04:00
# define LOCTEXT_NAMESPACE "GeometryCollectionConversion"
2022-06-01 21:41:57 -04:00
struct FUniqueVertex
{
FVector3f Normal ;
FVector3f Tangent ;
TArray < FVector2f > UVs ;
bool operator = = ( const FUniqueVertex & Other ) const
{
if ( this - > UVs . Num ( ) ! = Other . UVs . Num ( ) )
{
return false ;
}
bool bEquality = true ;
bEquality & = ( this - > Normal = = Other . Normal ) ;
bEquality & = ( this - > Tangent = = Other . Tangent ) ;
for ( int32 UVLayerIdx = 0 ; UVLayerIdx < UVs . Num ( ) ; + + UVLayerIdx )
{
bEquality & = ( this - > UVs [ UVLayerIdx ] = = Other . UVs [ UVLayerIdx ] ) ;
}
return bEquality ;
}
} ;
FORCEINLINE uint32 GetTypeHash ( const FUniqueVertex & UniqueVertex )
{
uint32 VertexHash = GetTypeHash ( UniqueVertex . Normal ) ;
VertexHash = HashCombine ( VertexHash , GetTypeHash ( UniqueVertex . Tangent ) ) ;
for ( int32 UVLayerIdx = 0 ; UVLayerIdx < UniqueVertex . UVs . Num ( ) ; + + UVLayerIdx )
{
VertexHash = HashCombine ( VertexHash , GetTypeHash ( UniqueVertex . UVs [ UVLayerIdx ] ) ) ;
}
return VertexHash ;
}
2023-10-11 18:08:19 -04:00
static bool IsImportableImplicitObjectType ( const Chaos : : FImplicitObject & ImplicitObject )
2022-06-06 21:10:52 -04:00
{
2023-10-11 18:08:19 -04:00
const Chaos : : EImplicitObjectType InnerType = ImplicitObject . GetType ( ) & ( ~ ( Chaos : : ImplicitObjectType : : IsScaled | Chaos : : ImplicitObjectType : : IsInstanced ) ) ;
if ( InnerType = = Chaos : : ImplicitObjectType : : Transformed )
{
const Chaos : : FImplicitObjectTransformed & TransformedImplicitObject = static_cast < const Chaos : : FImplicitObjectTransformed & > ( ImplicitObject ) ;
if ( const Chaos : : FImplicitObject * SubObject = TransformedImplicitObject . GetTransformedObject ( ) )
{
return IsImportableImplicitObjectType ( * SubObject ) ;
}
}
2022-06-06 21:10:52 -04:00
return ( InnerType = = Chaos : : ImplicitObjectType : : Box | | InnerType = = Chaos : : ImplicitObjectType : : Sphere | | InnerType = = Chaos : : ImplicitObjectType : : Capsule | | InnerType = = Chaos : : ImplicitObjectType : : Convex ) ;
}
2022-06-24 12:28:07 -04:00
static FVector GetMeshBuildScale3D ( const UStaticMesh & StaticMesh )
{
# if WITH_EDITOR
const TArray < FStaticMeshSourceModel > & SourceModels = StaticMesh . GetSourceModels ( ) ;
if ( SourceModels . Num ( ) > 0 )
{
return SourceModels [ 0 ] . BuildSettings . BuildScale3D ;
}
# endif
return FVector : : One ( ) ;
}
2022-06-23 17:00:03 -04:00
void FGeometryCollectionEngineConversion : : AppendMeshDescription (
const FMeshDescription * MeshDescription , const FString & Name , int32 MaterialStartIndex , const FTransform & StaticMeshTransform ,
2023-02-11 12:37:57 -05:00
FGeometryCollection * GeometryCollection , UBodySetup * BodySetup , bool ReindexMaterials , bool bAddInternalMaterials , bool bSetInternalFromMaterialIndex )
2022-06-01 21:41:57 -04:00
{
# if WITH_EDITORONLY_DATA
2022-06-23 17:00:03 -04:00
if ( ! MeshDescription )
2022-06-01 21:41:57 -04:00
{
return ;
}
2022-06-23 17:00:03 -04:00
check ( GeometryCollection ) ;
2023-08-30 20:50:47 -04:00
// prepare to tick progress per 100k vertices
const int32 ReportProgressSpacing = 100000 ;
int32 NumVertProgressSteps = int32 ( MeshDescription - > Vertices ( ) . GetArraySize ( ) / ReportProgressSpacing ) ;
FScopedSlowTask AppendMeshDescriptionTask ( 6 + 2 * NumVertProgressSteps , LOCTEXT ( " AppendMeshDescriptionTask " , " Appending Mesh Description Data " ) ) ;
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
// source vertex information
FStaticMeshConstAttributes Attributes ( * MeshDescription ) ;
TArrayView < const FVector3f > SourcePosition = Attributes . GetVertexPositions ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > SourceTangent = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
TArrayView < const float > SourceBinormalSign = Attributes . GetVertexInstanceBinormalSigns ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > SourceNormal = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
TArrayView < const FVector4f > SourceColor = Attributes . GetVertexInstanceColors ( ) . GetRawArray ( ) ;
TVertexInstanceAttributesConstRef < FVector2f > InstanceUVs = Attributes . GetVertexInstanceUVs ( ) ;
const int32 NumUVLayers = InstanceUVs . GetNumChannels ( ) ;
TArray < TArrayView < const FVector2f > > SourceUVArrays ;
SourceUVArrays . SetNum ( NumUVLayers ) ;
for ( int32 UVLayerIdx = 0 ; UVLayerIdx < NumUVLayers ; + + UVLayerIdx )
{
SourceUVArrays [ UVLayerIdx ] = InstanceUVs . GetRawArray ( UVLayerIdx ) ;
}
// target vertex information
TManagedArray < FVector3f > & TargetVertex = GeometryCollection - > Vertex ;
TManagedArray < FVector3f > & TargetTangentU = GeometryCollection - > TangentU ;
TManagedArray < FVector3f > & TargetTangentV = GeometryCollection - > TangentV ;
TManagedArray < FVector3f > & TargetNormal = GeometryCollection - > Normal ;
TManagedArray < FLinearColor > & TargetColor = GeometryCollection - > Color ;
TManagedArray < int32 > & TargetBoneMap = GeometryCollection - > BoneMap ;
TManagedArray < FLinearColor > & TargetBoneColor = GeometryCollection - > BoneColor ;
TManagedArray < FString > & TargetBoneName = GeometryCollection - > BoneName ;
2023-01-25 01:36:28 -05:00
if ( GeometryCollection - > NumUVLayers ( ) < NumUVLayers )
{
GeometryCollection - > SetNumUVLayers ( NumUVLayers ) ;
}
2022-06-23 17:00:03 -04:00
const int32 VertexStart = GeometryCollection - > NumElements ( FGeometryCollection : : VerticesGroup ) ;
int32 VertexCount = 0 ;
FVector Scale = StaticMeshTransform . GetScale3D ( ) ;
// We'll need to re-introduce UV seams, etc. by splitting vertices.
// A new mapping of MeshDescription vertex instances to the split vertices is maintained.
TMap < FVertexInstanceID , int32 > VertexInstanceToGeometryCollectionVertex ;
VertexInstanceToGeometryCollectionVertex . Reserve ( Attributes . GetVertexInstanceNormals ( ) . GetNumElements ( ) ) ;
2023-08-30 20:50:47 -04:00
int32 LastProgress = 0 ;
2022-06-23 17:00:03 -04:00
for ( const FVertexID VertexIndex : MeshDescription - > Vertices ( ) . GetElementIDs ( ) )
2023-08-30 20:50:47 -04:00
{
int32 Progress = int32 ( VertexIndex / ReportProgressSpacing ) ;
if ( Progress > LastProgress )
{
AppendMeshDescriptionTask . EnterProgressFrame ( Progress - LastProgress ) ;
LastProgress = Progress ;
}
2022-06-23 17:00:03 -04:00
TArrayView < const FVertexInstanceID > ReferencingVertexInstances = MeshDescription - > GetVertexVertexInstanceIDs ( VertexIndex ) ;
// Generate per instance hash of splittable attributes.
TMap < FUniqueVertex , TArray < FVertexInstanceID > > SplitVertices ;
for ( const FVertexInstanceID & InstanceID : ReferencingVertexInstances )
{
TArray < FVector2f > SourceUVs ;
SourceUVs . SetNum ( NumUVLayers ) ;
for ( int32 UVLayerIdx = 0 ; UVLayerIdx < NumUVLayers ; + + UVLayerIdx )
{
SourceUVs [ UVLayerIdx ] = SourceUVArrays [ UVLayerIdx ] [ InstanceID ] ;
}
FUniqueVertex UniqueVertex { SourceNormal [ InstanceID ] , SourceTangent [ InstanceID ] , SourceUVs } ;
TArray < FVertexInstanceID > & SplitVertex = SplitVertices . FindOrAdd ( UniqueVertex ) ;
SplitVertex . Add ( InstanceID ) ;
}
int32 CurrentVertex = GeometryCollection - > AddElements ( SplitVertices . Num ( ) , FGeometryCollection : : VerticesGroup ) ;
// Create a new vertex for each split vertex and map the mesh description instance to it.
for ( const TTuple < FUniqueVertex , TArray < FVertexInstanceID > > & SplitVertex : SplitVertices )
{
const TArray < FVertexInstanceID > & InstanceIDs = SplitVertex . Value ;
const FVertexInstanceID & ExemplarInstanceID = InstanceIDs [ 0 ] ;
TargetVertex [ CurrentVertex ] = SourcePosition [ VertexIndex ] * ( FVector3f ) Scale ;
TargetBoneMap [ CurrentVertex ] = GeometryCollection - > NumElements ( FGeometryCollection : : TransformGroup ) ;
TargetNormal [ CurrentVertex ] = SourceNormal [ ExemplarInstanceID ] ;
TargetTangentU [ CurrentVertex ] = SourceTangent [ ExemplarInstanceID ] ;
TargetTangentV [ CurrentVertex ] = ( FVector3f ) SourceBinormalSign [ ExemplarInstanceID ] * FVector3f : : CrossProduct ( TargetNormal [ CurrentVertex ] , TargetTangentU [ CurrentVertex ] ) ;
2023-01-25 01:36:28 -05:00
GeometryCollection : : UV : : SetUVs ( * GeometryCollection , CurrentVertex , SplitVertex . Key . UVs ) ;
2022-06-23 17:00:03 -04:00
if ( SourceColor . Num ( ) > 0 )
{
TargetColor [ CurrentVertex ] = FLinearColor ( SourceColor [ ExemplarInstanceID ] ) ;
}
else
{
TargetColor [ CurrentVertex ] = FLinearColor : : White ;
}
for ( const FVertexInstanceID & InstanceID : InstanceIDs )
{
VertexInstanceToGeometryCollectionVertex . Add ( InstanceID , CurrentVertex ) ;
}
+ + CurrentVertex ;
+ + VertexCount ;
}
}
2023-08-30 20:50:47 -04:00
if ( LastProgress < NumVertProgressSteps )
{
AppendMeshDescriptionTask . EnterProgressFrame ( NumVertProgressSteps - LastProgress ) ;
LastProgress = NumVertProgressSteps ;
}
// enter a progress frame for triangle processing w/ size equivalent to the vertex processing (as a heuristic)
// (note: could instead tick this per 100k triangles as we do with vertices above, if more responsive progress tracking is desired)
AppendMeshDescriptionTask . EnterProgressFrame ( NumVertProgressSteps ) ;
2022-06-23 17:00:03 -04:00
// target triangle indices
TManagedArray < FIntVector > & TargetIndices = GeometryCollection - > Indices ;
TManagedArray < bool > & TargetVisible = GeometryCollection - > Visible ;
TManagedArray < int32 > & TargetMaterialID = GeometryCollection - > MaterialID ;
TManagedArray < int32 > & TargetMaterialIndex = GeometryCollection - > MaterialIndex ;
2023-02-11 12:37:57 -05:00
TManagedArray < bool > & TargetInternal = GeometryCollection - > Internal ;
2022-06-23 17:00:03 -04:00
const int32 IndicesCount = MeshDescription - > Triangles ( ) . Num ( ) ;
const int32 InitialNumIndices = GeometryCollection - > NumElements ( FGeometryCollection : : FacesGroup ) ;
const int32 IndicesStart = GeometryCollection - > AddElements ( IndicesCount , FGeometryCollection : : FacesGroup ) ;
int32 TargetIndex = IndicesStart ;
for ( const int32 TriangleIndex : MeshDescription - > Triangles ( ) . GetElementIDs ( ) )
{
TArrayView < const FVertexInstanceID > TriangleVertices = MeshDescription - > GetTriangleVertexInstances ( TriangleIndex ) ;
TargetIndices [ TargetIndex ] = FIntVector (
VertexInstanceToGeometryCollectionVertex [ TriangleVertices [ 0 ] ] ,
VertexInstanceToGeometryCollectionVertex [ TriangleVertices [ 1 ] ] ,
VertexInstanceToGeometryCollectionVertex [ TriangleVertices [ 2 ] ]
) ;
TargetVisible [ TargetIndex ] = true ;
2023-02-11 12:37:57 -05:00
// bAddInternalMaterials and bSetInternalFromMaterialIndex support the legacy system of odd-numbered materials indicating internal surfaces
// bSetInternalFromMaterialIndex can be used to 'round trip' which faces are internal when using the 'ToMesh' tool to temporarily convert to/from static mesh.
2022-08-18 15:37:22 -04:00
int32 MaterialIndexScale = 1 + int32 ( bAddInternalMaterials ) ;
2023-02-11 12:37:57 -05:00
int32 MaterialSourceID = MeshDescription - > GetTrianglePolygonGroup ( TriangleIndex ) ;
TargetMaterialID [ TargetIndex ] = MaterialStartIndex + ( MaterialSourceID * MaterialIndexScale ) ;
bool bIsInternal = false ;
if ( bSetInternalFromMaterialIndex & & ! bAddInternalMaterials )
{
bIsInternal = ( MaterialSourceID % 2 ) = = 1 ;
}
TargetInternal [ TargetIndex ] = bIsInternal ;
2022-06-23 17:00:03 -04:00
// Is this right?
TargetMaterialIndex [ TargetIndex ] = TargetIndex ;
+ + TargetIndex ;
}
2023-08-30 20:50:47 -04:00
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
// Geometry transform
2023-10-12 14:40:24 -04:00
TManagedArray < FTransform3f > & Transform = GeometryCollection - > Transform ;
2022-06-23 17:00:03 -04:00
int32 TransformIndex1 = GeometryCollection - > AddElements ( 1 , FGeometryCollection : : TransformGroup ) ;
2023-10-12 14:40:24 -04:00
Transform [ TransformIndex1 ] = FTransform3f ( StaticMeshTransform ) ;
Transform [ TransformIndex1 ] . SetScale3D ( FVector3f ( 1.f , 1.f , 1.f ) ) ;
2022-06-23 17:00:03 -04:00
// collisions
if ( BodySetup )
{
2023-07-31 17:46:47 -04:00
TArray < Chaos : : FImplicitObjectPtr > Geoms ;
2022-06-23 17:00:03 -04:00
Chaos : : FShapesArray Shapes ;
FGeometryAddParams CreateGeometryParams ;
CreateGeometryParams . bDoubleSided = false ;
CreateGeometryParams . CollisionData . CollisionFlags . bEnableQueryCollision = true ;
CreateGeometryParams . CollisionData . CollisionFlags . bEnableSimCollisionComplex = false ; // no support for trimesh in destruction
CreateGeometryParams . CollisionData . CollisionFlags . bEnableSimCollisionSimple = true ;
CreateGeometryParams . CollisionTraceType = ECollisionTraceFlag : : CTF_UseSimpleAsComplex ;
CreateGeometryParams . Scale = Scale ;
CreateGeometryParams . LocalTransform = Chaos : : FRigidTransform3 : : Identity ;
CreateGeometryParams . WorldTransform = Chaos : : FRigidTransform3 : : Identity ;
CreateGeometryParams . Geometry = & BodySetup - > AggGeom ;
2023-07-31 17:46:47 -04:00
CreateGeometryParams . TriMeshGeometries = MakeArrayView ( BodySetup - > TriMeshGeometries ) ;
2022-06-23 17:00:03 -04:00
// todo(chaos) : this currently also create the shape array which is unnecessary ,this could be optimized by having a common function to create only the implicits
ChaosInterface : : CreateGeometry ( CreateGeometryParams , Geoms , Shapes ) ;
2023-07-31 17:46:47 -04:00
TManagedArray < Chaos : : FImplicitObjectPtr > & ExternaCollisions = GeometryCollection - > AddAttribute < Chaos : : FImplicitObjectPtr > ( FGeometryCollection : : ExternalCollisionsAttribute , FGeometryCollection : : TransformGroup ) ;
2022-06-23 17:00:03 -04:00
ExternaCollisions [ TransformIndex1 ] = nullptr ;
for ( int32 GeomIndex = 0 ; GeomIndex < Geoms . Num ( ) ; )
{
// make sure we only import box, sphere, capsule or convex
2023-10-11 18:08:19 -04:00
if ( Geoms [ GeomIndex ] & & IsImportableImplicitObjectType ( * Geoms [ GeomIndex ] ) )
2022-06-23 17:00:03 -04:00
{
GeomIndex + + ;
}
else
{
Geoms . RemoveAtSwap ( GeomIndex ) ;
}
}
if ( Geoms . Num ( ) > 0 )
{
2023-07-31 17:46:47 -04:00
ExternaCollisions [ TransformIndex1 ] = MakeImplicitObjectPtr < Chaos : : FImplicitObjectUnion > ( MoveTemp ( Geoms ) ) ;
2022-06-23 17:00:03 -04:00
}
}
// Bone Hierarchy - Added at root with no common parent
TManagedArray < int32 > & Parent = GeometryCollection - > Parent ;
TManagedArray < int32 > & SimulationType = GeometryCollection - > SimulationType ;
Parent [ TransformIndex1 ] = FGeometryCollection : : Invalid ;
SimulationType [ TransformIndex1 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
const FColor RandBoneColor ( FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , 255 ) ;
TargetBoneColor [ TransformIndex1 ] = FLinearColor ( RandBoneColor ) ;
TargetBoneName [ TransformIndex1 ] = Name ;
// GeometryGroup
int GeometryIndex = GeometryCollection - > AddElements ( 1 , FGeometryCollection : : GeometryGroup ) ;
TManagedArray < int32 > & TransformIndex = GeometryCollection - > TransformIndex ;
TManagedArray < FBox > & BoundingBox = GeometryCollection - > BoundingBox ;
TManagedArray < float > & InnerRadius = GeometryCollection - > InnerRadius ;
TManagedArray < float > & OuterRadius = GeometryCollection - > OuterRadius ;
TManagedArray < int32 > & VertexStartArray = GeometryCollection - > VertexStart ;
TManagedArray < int32 > & VertexCountArray = GeometryCollection - > VertexCount ;
TManagedArray < int32 > & FaceStartArray = GeometryCollection - > FaceStart ;
TManagedArray < int32 > & FaceCountArray = GeometryCollection - > FaceCount ;
TransformIndex [ GeometryIndex ] = TargetBoneMap [ VertexStart ] ;
VertexStartArray [ GeometryIndex ] = VertexStart ;
VertexCountArray [ GeometryIndex ] = VertexCount ;
FaceStartArray [ GeometryIndex ] = InitialNumIndices ;
FaceCountArray [ GeometryIndex ] = IndicesCount ;
// TransformGroup
TManagedArray < int32 > & TransformToGeometryIndexArray = GeometryCollection - > TransformToGeometryIndex ;
TransformToGeometryIndexArray [ TransformIndex1 ] = GeometryIndex ;
FVector Center ( 0 ) ;
for ( int32 VertexIndex = VertexStart ; VertexIndex < VertexStart + VertexCount ; VertexIndex + + )
{
Center + = ( FVector ) TargetVertex [ VertexIndex ] ;
}
if ( VertexCount ) Center / = VertexCount ;
2023-08-30 20:50:47 -04:00
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
// Inner/Outer edges, bounding box
BoundingBox [ GeometryIndex ] = FBox ( ForceInitToZero ) ;
InnerRadius [ GeometryIndex ] = FLT_MAX ;
OuterRadius [ GeometryIndex ] = - FLT_MAX ;
for ( int32 VertexIndex = VertexStart ; VertexIndex < VertexStart + VertexCount ; VertexIndex + + )
{
BoundingBox [ GeometryIndex ] + = ( FVector ) TargetVertex [ VertexIndex ] ;
float Delta = ( Center - ( FVector ) TargetVertex [ VertexIndex ] ) . Size ( ) ;
InnerRadius [ GeometryIndex ] = FMath : : Min ( InnerRadius [ GeometryIndex ] , Delta ) ;
OuterRadius [ GeometryIndex ] = FMath : : Max ( OuterRadius [ GeometryIndex ] , Delta ) ;
}
2023-08-30 20:50:47 -04:00
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
// Inner/Outer centroid
for ( int fdx = IndicesStart ; fdx < IndicesStart + IndicesCount ; fdx + + )
{
FVector Centroid ( 0 ) ;
for ( int e = 0 ; e < 3 ; e + + )
{
Centroid + = ( FVector ) TargetVertex [ TargetIndices [ fdx ] [ e ] ] ;
}
Centroid / = 3 ;
float Delta = ( Center - Centroid ) . Size ( ) ;
InnerRadius [ GeometryIndex ] = FMath : : Min ( InnerRadius [ GeometryIndex ] , Delta ) ;
OuterRadius [ GeometryIndex ] = FMath : : Max ( OuterRadius [ GeometryIndex ] , Delta ) ;
}
2023-08-30 20:50:47 -04:00
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
// Inner/Outer edges
for ( int fdx = IndicesStart ; fdx < IndicesStart + IndicesCount ; fdx + + )
{
for ( int e = 0 ; e < 3 ; e + + )
{
int i = e , j = ( e + 1 ) % 3 ;
FVector Edge = ( FVector ) TargetVertex [ TargetIndices [ fdx ] [ i ] ] + 0.5 * FVector ( TargetVertex [ TargetIndices [ fdx ] [ j ] ] - TargetVertex [ TargetIndices [ fdx ] [ i ] ] ) ;
float Delta = ( Center - Edge ) . Size ( ) ;
InnerRadius [ GeometryIndex ] = FMath : : Min ( InnerRadius [ GeometryIndex ] , Delta ) ;
OuterRadius [ GeometryIndex ] = FMath : : Max ( OuterRadius [ GeometryIndex ] , Delta ) ;
}
}
2023-08-30 20:50:47 -04:00
AppendMeshDescriptionTask . EnterProgressFrame ( 1 ) ;
2022-06-23 17:00:03 -04:00
if ( ReindexMaterials ) {
GeometryCollection - > ReindexMaterials ( ) ;
}
# endif //WITH_EDITORONLY_DATA
}
2022-11-10 01:18:48 -05:00
namespace
{
2023-06-15 22:53:53 -04:00
// Based on FStaticMeshOperations::AreNormalsAndTangentsValid but tests if *any* are valid instead of if *all* are valid to avoid forcing a recomputes for any small degen tri
void HasValidNormalsAndTangents ( const FMeshDescription & MeshDescription , bool & bHasValidNormals , bool & bHasValidTangents )
{
bHasValidNormals = false ;
bHasValidTangents = false ;
FStaticMeshConstAttributes Attributes ( MeshDescription ) ;
TArrayView < const FVector3f > VertexInstanceNormals = Attributes . GetVertexInstanceNormals ( ) . GetRawArray ( ) ;
TArrayView < const FVector3f > VertexInstanceTangents = Attributes . GetVertexInstanceTangents ( ) . GetRawArray ( ) ;
for ( const FVertexInstanceID VertexInstanceID : MeshDescription . VertexInstances ( ) . GetElementIDs ( ) )
{
bHasValidNormals | = ( ! VertexInstanceNormals [ VertexInstanceID ] . IsNearlyZero ( ) & & ! VertexInstanceNormals [ VertexInstanceID ] . ContainsNaN ( ) ) ;
bHasValidTangents | = ( ! VertexInstanceTangents [ VertexInstanceID ] . IsNearlyZero ( ) & & ! VertexInstanceTangents [ VertexInstanceID ] . ContainsNaN ( ) ) ;
if ( bHasValidNormals & & bHasValidTangents )
{
break ;
}
}
}
// Note: This is similar to the InitializeAutoGeneratedAttributes ModelingComponents AssetUtils function, in the MeshModelingToolset plugin,
// but we cannot use a plugin function from here, so have our own version. This version forces a recompute if Normals or Tangents are fully invalid,
// even if the corresponding Recompute flag is not set.
void InitializeNormalsAndTangentsIfNeededOrRequested ( FMeshDescription & Mesh , const FMeshBuildSettings * BuildSettings )
2022-11-10 01:18:48 -05:00
{
check ( BuildSettings ) ;
2023-06-15 22:53:53 -04:00
// Recompute according to build settings
bool bShouldRecomputeNormals = BuildSettings - > bRecomputeNormals ;
bool bShouldRecomputeTangents = BuildSettings - > bRecomputeTangents ;
// Also recompute if normals or tangents are fully invalid
// Note: We don't force a recompute if only some elements are invalid as these may just be a degenerate element on a mesh where the normals/tangents should otherwise be preserved.
if ( ! BuildSettings - > bRecomputeNormals | | ! BuildSettings - > bRecomputeTangents )
2022-11-10 01:18:48 -05:00
{
2023-06-15 22:53:53 -04:00
bool bHasValidNormals = false , bHasValidTangents = false ;
HasValidNormalsAndTangents ( Mesh , bHasValidNormals , bHasValidTangents ) ;
bShouldRecomputeNormals | = ! bHasValidNormals ;
bShouldRecomputeTangents | = ! bHasValidTangents ;
}
2022-11-10 01:18:48 -05:00
2023-06-15 22:53:53 -04:00
// run recompute function if either normals or tangents need recompute
if ( bShouldRecomputeNormals | | bShouldRecomputeTangents )
{
FStaticMeshAttributes Attributes ( Mesh ) ;
if ( ! Attributes . GetTriangleNormals ( ) . IsValid ( ) | | ! Attributes . GetTriangleTangents ( ) . IsValid ( ) )
2022-11-10 01:18:48 -05:00
{
2023-06-15 22:53:53 -04:00
// If these attributes don't exist, create them and compute their values for each triangle
FStaticMeshOperations : : ComputeTriangleTangentsAndNormals ( Mesh ) ;
2022-11-10 01:18:48 -05:00
}
2023-06-15 22:53:53 -04:00
EComputeNTBsFlags ComputeNTBsOptions = EComputeNTBsFlags : : BlendOverlappingNormals ;
ComputeNTBsOptions | = ( bShouldRecomputeNormals ) ? EComputeNTBsFlags : : Normals : EComputeNTBsFlags : : None ;
ComputeNTBsOptions | = ( bShouldRecomputeTangents ) ? EComputeNTBsFlags : : Tangents : EComputeNTBsFlags : : None ;
ComputeNTBsOptions | = BuildSettings - > bUseMikkTSpace ? EComputeNTBsFlags : : UseMikkTSpace : EComputeNTBsFlags : : None ;
ComputeNTBsOptions | = BuildSettings - > bComputeWeightedNormals ? EComputeNTBsFlags : : WeightedNTBs : EComputeNTBsFlags : : None ;
ComputeNTBsOptions | = BuildSettings - > bRemoveDegenerates ? EComputeNTBsFlags : : IgnoreDegenerateTriangles : EComputeNTBsFlags : : None ;
FStaticMeshOperations : : ComputeTangentsAndNormals ( Mesh , ComputeNTBsOptions ) ;
2022-11-10 01:18:48 -05:00
}
}
}
2022-06-23 17:00:03 -04:00
FMeshDescription * FGeometryCollectionEngineConversion : : GetMaxResMeshDescriptionWithNormalsAndTangents ( const UStaticMesh * StaticMesh )
{
if ( StaticMesh = = nullptr )
{
return nullptr ;
}
2022-06-01 21:41:57 -04:00
FMeshDescription * MeshDescription = nullptr ;
2022-11-10 01:18:48 -05:00
const FStaticMeshSourceModel * SourceModel = nullptr ;
2022-06-23 17:00:03 -04:00
# if WITH_EDITORONLY_DATA
// Prefer the HiRes description, although this isn't always available.
2022-06-01 21:41:57 -04:00
if ( StaticMesh - > IsHiResMeshDescriptionValid ( ) )
{
MeshDescription = StaticMesh - > GetHiResMeshDescription ( ) ;
2022-11-10 01:18:48 -05:00
SourceModel = & StaticMesh - > GetHiResSourceModel ( ) ;
2022-06-01 21:41:57 -04:00
}
else
{
MeshDescription = StaticMesh - > GetMeshDescription ( 0 ) ;
2022-11-10 01:18:48 -05:00
SourceModel = & StaticMesh - > GetSourceModel ( 0 ) ;
2022-06-01 21:41:57 -04:00
}
2023-06-15 22:53:53 -04:00
InitializeNormalsAndTangentsIfNeededOrRequested ( * MeshDescription , & SourceModel - > BuildSettings ) ;
2022-06-23 17:00:03 -04:00
# endif //WITH_EDITORONLY_DATA
return MeshDescription ;
}
2022-08-11 16:23:50 -04:00
int32 FGeometryCollectionEngineConversion : : AppendMaterials ( const TArray < UMaterialInterface * > & Materials , UGeometryCollection * GeometryCollectionObject , bool bAddInteriorCopy )
2022-06-23 17:00:03 -04:00
{
// for each material, add a reference in our GeometryCollectionObject
const int32 MaterialStart = GeometryCollectionObject - > Materials . Num ( ) ;
const int32 NumMeshMaterials = Materials . Num ( ) ;
GeometryCollectionObject - > Materials . Reserve ( MaterialStart + NumMeshMaterials ) ;
for ( int32 Index = 0 ; Index < NumMeshMaterials ; + + Index )
{
UMaterialInterface * CurrMaterial = Materials [ Index ] ;
// Possible we have a null entry - replace with default
if ( CurrMaterial = = nullptr )
{
CurrMaterial = UMaterial : : GetDefaultMaterial ( MD_Surface ) ;
}
// We add the material twice, once for interior and again for exterior.
GeometryCollectionObject - > Materials . Add ( CurrMaterial ) ;
2022-08-11 16:23:50 -04:00
if ( bAddInteriorCopy )
{
GeometryCollectionObject - > Materials . Add ( CurrMaterial ) ;
}
2022-06-23 17:00:03 -04:00
}
return MaterialStart ;
}
2022-12-02 00:40:18 -05:00
void FGeometryCollectionEngineConversion : : AppendAutoInstanceMeshIndices ( UGeometryCollection * GeometryCollectionObject , int32 FromTransformIndex , const UStaticMesh * StaticMesh , const TArray < UMaterialInterface * > & Materials )
{
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > GeometryCollectionPtr = GeometryCollectionObject - > GetGeometryCollection ( ) ;
if ( GeometryCollectionPtr )
{
using namespace GeometryCollection : : Facades ;
FCollectionInstancedMeshFacade InstancedMeshFacade ( * GeometryCollectionPtr ) ;
const int32 NewNumOfTransforms = GeometryCollectionPtr - > NumElements ( FGeometryCollection : : TransformGroup ) ;
if ( NewNumOfTransforms > FromTransformIndex )
{
// create the schema if necessary
InstancedMeshFacade . DefineSchema ( ) ;
2023-02-24 15:00:49 -05:00
const int32 AutoInstanceMeshIndex = GeometryCollectionObject - > FindOrAddAutoInstanceMesh ( StaticMesh , Materials ) ;
2022-12-02 00:40:18 -05:00
for ( int32 TransformIndex = FromTransformIndex ; TransformIndex < NewNumOfTransforms ; TransformIndex + + )
{
InstancedMeshFacade . SetIndex ( TransformIndex , AutoInstanceMeshIndex ) ;
}
}
}
}
bool FGeometryCollectionEngineConversion : : AppendStaticMesh ( const UStaticMesh * StaticMesh , const TArray < UMaterialInterface * > & Materials ,
2022-08-18 15:37:22 -04:00
const FTransform & StaticMeshTransform , UGeometryCollection * GeometryCollectionObject , bool bReindexMaterials ,
2023-02-11 12:37:57 -05:00
bool bAddInternalMaterials , bool bSplitComponents , bool bSetInternalFromMaterialIndex )
2022-06-23 17:00:03 -04:00
{
# if WITH_EDITORONLY_DATA
int32 StartMaterialIndex = GeometryCollectionObject - > Materials . Num ( ) ;
2022-06-01 21:41:57 -04:00
check ( GeometryCollectionObject ) ;
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > GeometryCollectionPtr = GeometryCollectionObject - > GetGeometryCollection ( ) ;
FGeometryCollection * GeometryCollection = GeometryCollectionPtr . Get ( ) ;
check ( GeometryCollection ) ;
2022-10-21 19:51:57 -04:00
const int32 OriginalNumOfTransforms = GeometryCollection - > NumElements ( FGeometryCollection : : TransformGroup ) ;
2023-02-11 12:37:57 -05:00
if ( AppendStaticMesh ( StaticMesh , StartMaterialIndex , StaticMeshTransform , GeometryCollection , bReindexMaterials , bAddInternalMaterials , bSplitComponents , bSetInternalFromMaterialIndex ) )
2022-06-23 17:00:03 -04:00
{
2022-08-18 15:37:22 -04:00
AppendMaterials ( Materials , GeometryCollectionObject , bAddInternalMaterials ) ;
2022-10-21 19:51:57 -04:00
2022-12-02 00:40:18 -05:00
AppendAutoInstanceMeshIndices ( GeometryCollectionObject , OriginalNumOfTransforms , StaticMesh , Materials ) ;
2022-10-21 19:51:57 -04:00
2022-06-23 17:00:03 -04:00
return true ;
}
# endif //WITH_EDITORONLY_DATA
return false ;
}
2022-08-18 15:37:22 -04:00
bool FGeometryCollectionEngineConversion : : AppendStaticMesh ( const UStaticMesh * StaticMesh , int32 StartMaterialIndex , const FTransform & StaticMeshTransform ,
2023-02-11 12:37:57 -05:00
FGeometryCollection * GeometryCollection , bool bReindexMaterials , bool bAddInternalMaterials , bool bSplitComponents , bool bSetInternalFromMaterialIndex )
2022-06-23 17:00:03 -04:00
{
# if WITH_EDITORONLY_DATA
2023-08-30 20:50:47 -04:00
FScopedSlowTask AppendStaticMeshTask ( bSplitComponents ? 3 : 2 , LOCTEXT ( " AppendStaticMeshTask " , " Appending Static Mesh " ) ) ;
2022-06-24 12:28:07 -04:00
if ( StaticMesh )
2022-06-01 21:41:57 -04:00
{
2023-08-30 20:50:47 -04:00
AppendStaticMeshTask . EnterProgressFrame ( 1 ) ;
2022-06-24 12:28:07 -04:00
FMeshDescription * MeshDescription = GetMaxResMeshDescriptionWithNormalsAndTangents ( StaticMesh ) ;
check ( GeometryCollection ) ;
if ( MeshDescription )
{
const FVector MeshBuildScale3D = GetMeshBuildScale3D ( * StaticMesh ) ;
const FTransform MeshTransform (
StaticMeshTransform . GetRotation ( ) ,
StaticMeshTransform . GetTranslation ( ) ,
StaticMeshTransform . GetScale3D ( ) * MeshBuildScale3D
) ;
2022-08-18 15:37:22 -04:00
if ( bSplitComponents )
{
2023-08-30 20:50:47 -04:00
AppendStaticMeshTask . EnterProgressFrame ( 1 ) ;
2022-08-18 15:37:22 -04:00
int32 MaxVID = MeshDescription - > Vertices ( ) . Num ( ) ;
UE : : Geometry : : FVertexConnectedComponents Components ( MaxVID ) ;
for ( const FTriangleID TriangleID : MeshDescription - > Triangles ( ) . GetElementIDs ( ) )
{
TArrayView < const FVertexID > TriangleIDs = MeshDescription - > GetTriangleVertices ( TriangleID ) ;
Components . ConnectVertices ( TriangleIDs [ 0 ] . GetValue ( ) , TriangleIDs [ 1 ] . GetValue ( ) ) ;
Components . ConnectVertices ( TriangleIDs [ 1 ] . GetValue ( ) , TriangleIDs [ 2 ] . GetValue ( ) ) ;
}
if ( Components . HasMultipleComponents ( MaxVID , 2 ) )
{
// look up vertex positions
TVertexAttributesConstRef < FVector3f > VertexPositions = MeshDescription - > GetVertexPositions ( ) ;
// vertex instance attributes
FStaticMeshConstAttributes Attributes ( * MeshDescription ) ;
TVertexInstanceAttributesConstRef < FVector2f > InstanceUVs = Attributes . GetVertexInstanceUVs ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > InstanceNormals = Attributes . GetVertexInstanceNormals ( ) ;
TVertexInstanceAttributesConstRef < FVector3f > InstanceTangents = Attributes . GetVertexInstanceTangents ( ) ;
TVertexInstanceAttributesConstRef < float > InstanceBiTangentSign = Attributes . GetVertexInstanceBinormalSigns ( ) ;
TVertexInstanceAttributesConstRef < FVector4f > InstanceColors = Attributes . GetVertexInstanceColors ( ) ;
const int NumUVLayers = InstanceUVs . GetNumChannels ( ) ;
TMap < int32 , int32 > Map = Components . MakeComponentMap ( MaxVID , 2 ) ;
int32 NumIslands = Map . Num ( ) ;
TArray < FMeshDescription > Descriptions ;
Descriptions . SetNum ( NumIslands ) ;
TArray < FMeshDescriptionBuilder > Builders ;
Builders . SetNum ( NumIslands ) ;
for ( int32 MeshIdx = 0 ; MeshIdx < NumIslands ; + + MeshIdx )
{
FStaticMeshAttributes MeshAttributes ( Descriptions [ MeshIdx ] ) ;
MeshAttributes . Register ( ) ;
Builders [ MeshIdx ] . SetMeshDescription ( & Descriptions [ MeshIdx ] ) ;
Builders [ MeshIdx ] . SuspendMeshDescriptionIndexing ( ) ;
Builders [ MeshIdx ] . SetNumUVLayers ( NumUVLayers ) ;
}
for ( TPair < int32 , int32 > IDToIdx : Map )
{
int32 ID = IDToIdx . Key ;
int32 Idx = IDToIdx . Value ;
int32 NumVertices = Components . GetComponentSize ( ID ) ;
Builders [ Idx ] . ReserveNewVertices ( NumVertices ) ;
}
TArray < int32 > VertexIDMap ;
VertexIDMap . Init ( INDEX_NONE , MeshDescription - > Vertices ( ) . Num ( ) ) ;
for ( const FVertexID VertexID : MeshDescription - > Vertices ( ) . GetElementIDs ( ) )
{
int32 MeshID = Components . GetComponent ( VertexID . GetValue ( ) ) ;
int32 * MeshIdx = Map . Find ( MeshID ) ;
if ( MeshIdx )
{
FVector Position = ( FVector ) VertexPositions . Get ( VertexID ) ;
VertexIDMap [ VertexID . GetValue ( ) ] = Builders [ * MeshIdx ] . AppendVertex ( Position ) ;
}
}
for ( const FTriangleID TriangleID : MeshDescription - > Triangles ( ) . GetElementIDs ( ) )
{
TArrayView < const FVertexID > TriangleVerts = MeshDescription - > GetTriangleVertices ( TriangleID ) ;
TArrayView < const FVertexInstanceID > SourceInstanceTri = MeshDescription - > GetTriangleVertexInstances ( TriangleID ) ;
int32 MeshID = Components . GetComponent ( TriangleVerts [ 0 ] . GetValue ( ) ) ;
int32 MeshIdx = Map [ MeshID ] ;
FMeshDescriptionBuilder & Builder = Builders [ MeshIdx ] ;
// create new vtx instances for each triangle
FVertexInstanceID DestInstanceTri [ 3 ] ;
for ( int32 j = 0 ; j < 3 ; + + j )
{
const FVertexID TriVertex = VertexIDMap [ TriangleVerts [ j ] . GetValue ( ) ] ;
DestInstanceTri [ j ] = Builder . AppendInstance ( TriVertex ) ;
}
// add the triangle to MeshDescription
FPolygonGroupID MaterialID = MeshDescription - > GetTrianglePolygonGroup ( TriangleID ) ;
FTriangleID NewTriangleID = Builder . AppendTriangle ( DestInstanceTri [ 0 ] , DestInstanceTri [ 1 ] , DestInstanceTri [ 2 ] , MaterialID ) ;
// transfer UVs. Note the Builder sets both the shared and per-instance UVs from this
for ( int32 UVLayer = 0 ; UVLayer < NumUVLayers ; + + UVLayer )
{
FUVID UVIDs [ 3 ] = { FUVID ( - 1 ) , FUVID ( - 1 ) , FUVID ( - 1 ) } ;
for ( int32 j = 0 ; j < 3 ; + + j )
{
FVector2D UV = ( FVector2D ) InstanceUVs . Get ( SourceInstanceTri [ j ] , UVLayer ) ;
UVIDs [ j ] = Builder . AppendUV ( UV , UVLayer ) ;
}
// append the UV triangle - builder takes care of the rest
Builder . AppendUVTriangle ( NewTriangleID , UVIDs [ 0 ] , UVIDs [ 1 ] , UVIDs [ 2 ] , UVLayer ) ;
}
// Set instance attributes: normal/tangent/bitangent frame and color
for ( int32 j = 0 ; j < 3 ; + + j )
{
const FVertexInstanceID SourceInstanceID = SourceInstanceTri [ j ] ;
const FVertexInstanceID DestInstanceID = DestInstanceTri [ j ] ;
FVector TriVertNormal = ( FVector ) InstanceNormals . Get ( SourceInstanceID ) ;
FVector TriVertTangent = ( FVector ) InstanceTangents . Get ( SourceInstanceID ) ;
float BiTangentSign = ( float ) InstanceBiTangentSign . Get ( SourceInstanceID ) ;
Builder . SetInstanceTangentSpace ( DestInstanceID , TriVertNormal , TriVertTangent , BiTangentSign ) ;
FVector4f InstColor = InstanceColors . Get ( SourceInstanceID ) ;
Builder . SetInstanceColor ( DestInstanceID , InstColor ) ;
}
}
for ( int32 MeshIdx = 0 ; MeshIdx < NumIslands ; + + MeshIdx )
{
Builders [ MeshIdx ] . ResumeMeshDescriptionIndexing ( ) ;
}
for ( FMeshDescription & MD : Descriptions )
{
2023-02-11 12:37:57 -05:00
AppendMeshDescription ( & MD , StaticMesh - > GetName ( ) , StartMaterialIndex , MeshTransform , GeometryCollection , StaticMesh - > GetBodySetup ( ) , false , bAddInternalMaterials , bSetInternalFromMaterialIndex ) ;
2022-08-18 15:37:22 -04:00
}
if ( bReindexMaterials )
{
GeometryCollection - > ReindexMaterials ( ) ;
}
return true ;
}
// else only one component -- fall back to just using the original mesh description
}
2023-08-30 20:50:47 -04:00
AppendStaticMeshTask . EnterProgressFrame ( 1 ) ;
2023-02-11 12:37:57 -05:00
AppendMeshDescription ( MeshDescription , StaticMesh - > GetName ( ) , StartMaterialIndex , MeshTransform , GeometryCollection , StaticMesh - > GetBodySetup ( ) , bReindexMaterials , bAddInternalMaterials , bSetInternalFromMaterialIndex ) ;
2022-06-24 12:28:07 -04:00
return true ;
}
2022-06-01 21:41:57 -04:00
}
# endif //WITH_EDITORONLY_DATA
2022-06-23 17:00:03 -04:00
return false ;
2022-06-01 21:41:57 -04:00
}
2022-06-23 17:00:03 -04:00
bool FGeometryCollectionEngineConversion : : AppendGeometryCollection ( const FGeometryCollection * SourceGeometryCollectionPtr , int32 AssetMaterialStart , const FTransform & GeometryCollectionTransform , FGeometryCollection * TargetGeometryCollection , bool bReindexMaterials )
{
if ( SourceGeometryCollectionPtr = = nullptr )
{
return false ;
}
2022-06-01 21:41:57 -04:00
// Assemble offsets and add elements
const int32 VertexCount = SourceGeometryCollectionPtr - > Vertex . Num ( ) ;
const int32 FaceCount = SourceGeometryCollectionPtr - > Indices . Num ( ) ;
const int32 TransformCount = SourceGeometryCollectionPtr - > Transform . Num ( ) ;
const int32 GeometryCount = SourceGeometryCollectionPtr - > TransformIndex . Num ( ) ;
const int32 SectionCount = SourceGeometryCollectionPtr - > Sections . Num ( ) ;
2023-10-12 14:40:24 -04:00
FVector3f Scale = FVector3f ( GeometryCollectionTransform . GetScale3D ( ) ) ;
FTransform3f AppliedTransform = FTransform3f ( GeometryCollectionTransform ) ;
2022-06-01 21:41:57 -04:00
AppliedTransform . RemoveScaling ( ) ;
2022-06-23 17:00:03 -04:00
const int32 VertexStart = TargetGeometryCollection - > AddElements ( VertexCount , FGeometryCollection : : VerticesGroup ) ;
const int32 FaceStart = TargetGeometryCollection - > AddElements ( FaceCount , FGeometryCollection : : FacesGroup ) ;
const int32 TransformStart = TargetGeometryCollection - > AddElements ( TransformCount , FGeometryCollection : : TransformGroup ) ;
const int32 GeometryStart = TargetGeometryCollection - > AddElements ( GeometryCount , FGeometryCollection : : GeometryGroup ) ;
const int32 SectionStart = TargetGeometryCollection - > AddElements ( SectionCount , FGeometryCollection : : MaterialGroup ) ;
2022-06-01 21:41:57 -04:00
// source vertex information
const TManagedArray < FVector3f > & SourceVertex = SourceGeometryCollectionPtr - > Vertex ;
const TManagedArray < FVector3f > & SourceTangentU = SourceGeometryCollectionPtr - > TangentU ;
const TManagedArray < FVector3f > & SourceTangentV = SourceGeometryCollectionPtr - > TangentV ;
const TManagedArray < FVector3f > & SourceNormal = SourceGeometryCollectionPtr - > Normal ;
const TManagedArray < FLinearColor > & SourceColor = SourceGeometryCollectionPtr - > Color ;
const TManagedArray < int32 > & SourceBoneMap = SourceGeometryCollectionPtr - > BoneMap ;
// target vertex information
2022-06-23 17:00:03 -04:00
TManagedArray < FVector3f > & TargetVertex = TargetGeometryCollection - > Vertex ;
TManagedArray < FVector3f > & TargetTangentU = TargetGeometryCollection - > TangentU ;
TManagedArray < FVector3f > & TargetTangentV = TargetGeometryCollection - > TangentV ;
TManagedArray < FVector3f > & TargetNormal = TargetGeometryCollection - > Normal ;
TManagedArray < FLinearColor > & TargetColor = TargetGeometryCollection - > Color ;
TManagedArray < int32 > & TargetBoneMap = TargetGeometryCollection - > BoneMap ;
2022-06-01 21:41:57 -04:00
2023-01-25 01:36:28 -05:00
TargetGeometryCollection - > SetNumUVLayers ( FMath : : Max ( TargetGeometryCollection - > NumUVLayers ( ) , SourceGeometryCollectionPtr - > NumUVLayers ( ) ) ) ;
GeometryCollection : : UV : : FUVLayers TargetUVLayers = GeometryCollection : : UV : : FindActiveUVLayers ( * TargetGeometryCollection ) ;
GeometryCollection : : UV : : FConstUVLayers SourceUVLayers = GeometryCollection : : UV : : FindActiveUVLayers ( * SourceGeometryCollectionPtr ) ;
2022-06-01 21:41:57 -04:00
// append vertices
for ( int32 VertexIndex = 0 ; VertexIndex < VertexCount ; VertexIndex + + )
{
const int32 VertexOffset = VertexStart + VertexIndex ;
TargetVertex [ VertexOffset ] = SourceVertex [ VertexIndex ] * ( FVector3f ) Scale ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
TargetTangentU [ VertexOffset ] = SourceTangentU [ VertexIndex ] ;
TargetTangentV [ VertexOffset ] = SourceTangentV [ VertexIndex ] ;
TargetNormal [ VertexOffset ] = SourceNormal [ VertexIndex ] ;
2023-01-25 01:36:28 -05:00
for ( int32 UVLayer = 0 ; UVLayer < SourceUVLayers . Num ( ) ; + + UVLayer )
{
TargetUVLayers [ UVLayer ] [ VertexOffset ] = SourceUVLayers [ UVLayer ] [ VertexIndex ] ;
}
2022-06-01 21:41:57 -04:00
TargetColor [ VertexOffset ] = SourceColor [ VertexIndex ] ;
TargetBoneMap [ VertexOffset ] = SourceBoneMap [ VertexIndex ] + TransformStart ;
}
// source face information
const TManagedArray < FIntVector > & SourceIndices = SourceGeometryCollectionPtr - > Indices ;
const TManagedArray < bool > & SourceVisible = SourceGeometryCollectionPtr - > Visible ;
const TManagedArray < int32 > & SourceMaterialID = SourceGeometryCollectionPtr - > MaterialID ;
const TManagedArray < int32 > & SourceMaterialIndex = SourceGeometryCollectionPtr - > MaterialIndex ;
2023-02-11 12:37:57 -05:00
const TManagedArray < bool > & SourceInternal = SourceGeometryCollectionPtr - > Internal ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
// target face information
2022-06-23 17:00:03 -04:00
TManagedArray < FIntVector > & TargetIndices = TargetGeometryCollection - > Indices ;
TManagedArray < bool > & TargetVisible = TargetGeometryCollection - > Visible ;
TManagedArray < int32 > & TargetMaterialID = TargetGeometryCollection - > MaterialID ;
TManagedArray < int32 > & TargetMaterialIndex = TargetGeometryCollection - > MaterialIndex ;
2023-02-11 12:37:57 -05:00
TManagedArray < bool > & TargetInternal = TargetGeometryCollection - > Internal ;
2022-06-01 21:41:57 -04:00
// append faces
for ( int32 FaceIndex = 0 ; FaceIndex < FaceCount ; + + FaceIndex )
{
const FIntVector & SourceFace = SourceIndices [ FaceIndex ] ;
const int32 FaceOffset = FaceStart + FaceIndex ;
TargetIndices [ FaceOffset ] = FIntVector (
SourceFace [ 0 ] + VertexStart ,
SourceFace [ 1 ] + VertexStart ,
SourceFace [ 2 ] + VertexStart ) ;
TargetVisible [ FaceOffset ] = SourceVisible [ FaceIndex ] ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
TargetMaterialID [ FaceOffset ] = AssetMaterialStart + SourceMaterialID [ FaceIndex ] ;
TargetMaterialIndex [ FaceOffset ] = FaceOffset ;
2023-02-11 12:37:57 -05:00
TargetInternal [ FaceOffset ] = SourceInternal [ FaceIndex ] ;
2022-06-01 21:41:57 -04:00
}
// source transform information
2023-10-12 14:40:24 -04:00
const TManagedArray < FTransform3f > & SourceTransform = SourceGeometryCollectionPtr - > Transform ;
2022-06-01 21:41:57 -04:00
const TManagedArray < FString > & SourceBoneName = SourceGeometryCollectionPtr - > BoneName ;
const TManagedArray < FLinearColor > & SourceBoneColor = SourceGeometryCollectionPtr - > BoneColor ;
const TManagedArray < int32 > & SourceParent = SourceGeometryCollectionPtr - > Parent ;
const TManagedArray < TSet < int32 > > & SourceChildren = SourceGeometryCollectionPtr - > Children ;
const TManagedArray < int32 > & SourceTransformToGeometryIndex = SourceGeometryCollectionPtr - > TransformToGeometryIndex ;
const TManagedArray < int32 > & SourceSimulationType = SourceGeometryCollectionPtr - > SimulationType ;
const TManagedArray < int32 > & SourceStatusFlags = SourceGeometryCollectionPtr - > StatusFlags ;
const TManagedArray < int32 > & SourceInitialDynamicState = SourceGeometryCollectionPtr - > InitialDynamicState ;
2023-07-31 17:46:47 -04:00
const TManagedArray < Chaos : : FImplicitObjectPtr > * SourceExternalCollisions = SourceGeometryCollectionPtr - > FindAttribute < Chaos : : FImplicitObjectPtr > ( FGeometryCollection : : ExternalCollisionsAttribute , FGeometryCollection : : TransformGroup ) ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
// target transform information
2023-10-12 14:40:24 -04:00
TManagedArray < FTransform3f > & TargetTransform = TargetGeometryCollection - > Transform ;
2022-06-23 17:00:03 -04:00
TManagedArray < FString > & TargetBoneName = TargetGeometryCollection - > BoneName ;
TManagedArray < FLinearColor > & TargetBoneColor = TargetGeometryCollection - > BoneColor ;
TManagedArray < int32 > & TargetParent = TargetGeometryCollection - > Parent ;
TManagedArray < TSet < int32 > > & TargetChildren = TargetGeometryCollection - > Children ;
TManagedArray < int32 > & TargetTransformToGeometryIndex = TargetGeometryCollection - > TransformToGeometryIndex ;
TManagedArray < int32 > & TargetSimulationType = TargetGeometryCollection - > SimulationType ;
TManagedArray < int32 > & TargetStatusFlags = TargetGeometryCollection - > StatusFlags ;
TManagedArray < int32 > & TargetInitialDynamicState = TargetGeometryCollection - > InitialDynamicState ;
2023-07-31 17:46:47 -04:00
TManagedArray < Chaos : : FImplicitObjectPtr > & TargetExternalCollisions = TargetGeometryCollection - > AddAttribute < Chaos : : FImplicitObjectPtr > ( FGeometryCollection : : ExternalCollisionsAttribute , FGeometryCollection : : TransformGroup ) ;
2022-06-01 21:41:57 -04:00
// append transform hierarchy
for ( int32 TransformIndex = 0 ; TransformIndex < TransformCount ; + + TransformIndex )
{
const int32 TransformOffset = TransformStart + TransformIndex ;
// Only apply the transform to the parent node. Child nodes only need scaling applied to translation offsets.
if ( SourceParent [ TransformIndex ] = = INDEX_NONE )
{
TargetTransform [ TransformOffset ] = SourceTransform [ TransformIndex ] * AppliedTransform ;
}
else
{
2023-10-12 14:40:24 -04:00
FTransform3f ScaledTranslation = SourceTransform [ TransformIndex ] ;
2022-06-01 21:41:57 -04:00
ScaledTranslation . ScaleTranslation ( Scale ) ;
TargetTransform [ TransformOffset ] = ScaledTranslation ;
}
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
// #todo Get this Bone name to be unique
TargetBoneName [ TransformOffset ] = SourceBoneName [ TransformIndex ] ;
const FColor RandBoneColor ( FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , 255 ) ;
TargetBoneColor [ TransformOffset ] = FLinearColor ( RandBoneColor ) ;
2022-06-23 17:00:03 -04:00
TargetParent [ TransformOffset ] = ( SourceParent [ TransformIndex ] = = INDEX_NONE ) ? INDEX_NONE : SourceParent [ TransformIndex ] + TransformStart ;
2022-06-01 21:41:57 -04:00
const TSet < int32 > & SourceChildrenSet = SourceChildren [ TransformIndex ] ;
for ( int32 ChildIndex : SourceChildrenSet )
{
TargetChildren [ TransformOffset ] . Add ( ChildIndex + TransformStart ) ;
}
TargetTransformToGeometryIndex [ TransformOffset ] = SourceTransformToGeometryIndex [ TransformIndex ] + GeometryStart ;
TargetSimulationType [ TransformOffset ] = SourceSimulationType [ TransformIndex ] ;
TargetStatusFlags [ TransformOffset ] = SourceStatusFlags [ TransformIndex ] ;
TargetInitialDynamicState [ TransformOffset ] = SourceInitialDynamicState [ TransformIndex ] ;
2022-06-03 23:13:28 -04:00
TargetExternalCollisions [ TransformOffset ] = nullptr ;
if ( SourceExternalCollisions )
{
TargetExternalCollisions [ TransformOffset ] = ( * SourceExternalCollisions ) [ TransformIndex ] ;
}
2022-06-01 21:41:57 -04:00
}
// source geometry information
const TManagedArray < int32 > & SourceTransformIndex = SourceGeometryCollectionPtr - > TransformIndex ;
const TManagedArray < int32 > & SourceVertexStart = SourceGeometryCollectionPtr - > VertexStart ;
const TManagedArray < int32 > & SourceVertexCount = SourceGeometryCollectionPtr - > VertexCount ;
const TManagedArray < int32 > & SourceFaceStart = SourceGeometryCollectionPtr - > FaceStart ;
const TManagedArray < int32 > & SourceFaceCount = SourceGeometryCollectionPtr - > FaceCount ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
// target geometry information
2022-06-23 17:00:03 -04:00
TManagedArray < int32 > & TargetTransformIndex = TargetGeometryCollection - > TransformIndex ;
TManagedArray < FBox > & TargetBoundingBox = TargetGeometryCollection - > BoundingBox ;
TManagedArray < float > & TargetInnerRadius = TargetGeometryCollection - > InnerRadius ;
TManagedArray < float > & TargetOuterRadius = TargetGeometryCollection - > OuterRadius ;
TManagedArray < int32 > & TargetVertexStart = TargetGeometryCollection - > VertexStart ;
TManagedArray < int32 > & TargetVertexCount = TargetGeometryCollection - > VertexCount ;
TManagedArray < int32 > & TargetFaceStart = TargetGeometryCollection - > FaceStart ;
TManagedArray < int32 > & TargetFaceCount = TargetGeometryCollection - > FaceCount ;
2022-06-01 21:41:57 -04:00
// append geometry
for ( int32 GeometryIndex = 0 ; GeometryIndex < GeometryCount ; + + GeometryIndex )
{
const int32 GeometryOffset = GeometryStart + GeometryIndex ;
TargetTransformIndex [ GeometryOffset ] = SourceTransformIndex [ GeometryIndex ] + TransformStart ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
TargetVertexStart [ GeometryOffset ] = SourceVertexStart [ GeometryIndex ] + VertexStart ;
TargetVertexCount [ GeometryOffset ] = SourceVertexCount [ GeometryIndex ] ;
TargetFaceStart [ GeometryOffset ] = SourceFaceStart [ GeometryIndex ] + FaceStart ;
TargetFaceCount [ GeometryOffset ] = SourceFaceCount [ GeometryIndex ] ;
// Find centroid of geometry for inner/outer radius calculations
FVector Center ( 0 ) ;
for ( int32 VertexIndex = TargetVertexStart [ GeometryOffset ] ; VertexIndex < TargetVertexStart [ GeometryOffset ] + TargetVertexCount [ GeometryOffset ] ; + + VertexIndex )
{
Center + = ( FVector ) TargetVertex [ VertexIndex ] ;
}
if ( TargetVertexCount [ GeometryOffset ] ) Center / = TargetVertexCount [ GeometryOffset ] ;
2022-06-23 17:00:03 -04:00
2022-06-01 21:41:57 -04:00
TargetBoundingBox [ GeometryOffset ] = FBox ( ForceInitToZero ) ;
TargetInnerRadius [ GeometryOffset ] = FLT_MAX ;
TargetOuterRadius [ GeometryOffset ] = - FLT_MAX ;
for ( int32 VertexIndex = TargetVertexStart [ GeometryOffset ] ; VertexIndex < TargetVertexStart [ GeometryOffset ] + TargetVertexCount [ GeometryOffset ] ; + + VertexIndex )
{
TargetBoundingBox [ GeometryOffset ] + = ( FVector ) TargetVertex [ VertexIndex ] ;
float Delta = ( Center - ( FVector ) TargetVertex [ VertexIndex ] ) . Size ( ) ;
TargetInnerRadius [ GeometryOffset ] = FMath : : Min ( TargetInnerRadius [ GeometryOffset ] , Delta ) ;
TargetOuterRadius [ GeometryOffset ] = FMath : : Max ( TargetOuterRadius [ GeometryOffset ] , Delta ) ;
}
}
// source material information
const TManagedArray < FGeometryCollectionSection > & SourceSections = SourceGeometryCollectionPtr - > Sections ;
// target material information
2022-06-23 17:00:03 -04:00
TManagedArray < FGeometryCollectionSection > & TargetSections = TargetGeometryCollection - > Sections ;
2022-06-01 21:41:57 -04:00
// append sections
for ( int32 SectionIndex = 0 ; SectionIndex < SectionCount ; + + SectionIndex )
{
int32 SectionOffset = SectionStart + SectionIndex ;
TargetSections [ SectionOffset ] . MaterialID = AssetMaterialStart + SourceSections [ SectionIndex ] . MaterialID ;
TargetSections [ SectionOffset ] . FirstIndex = SourceSections [ SectionIndex ] . FirstIndex + FaceStart * 3 ;
TargetSections [ SectionOffset ] . MinVertexIndex = VertexStart + SourceSections [ SectionIndex ] . MinVertexIndex ;
TargetSections [ SectionOffset ] . NumTriangles = SourceSections [ SectionIndex ] . NumTriangles ;
TargetSections [ SectionOffset ] . MaxVertexIndex = VertexStart + SourceSections [ SectionIndex ] . MaxVertexIndex ;
}
2022-06-23 17:00:03 -04:00
if ( bReindexMaterials )
{
TargetGeometryCollection - > ReindexMaterials ( ) ;
2022-06-01 21:41:57 -04:00
}
2022-06-23 17:00:03 -04:00
return true ;
}
void FGeometryCollectionEngineConversion : : AppendGeometryCollection ( const UGeometryCollection * SourceGeometryCollection , const TArray < UMaterialInterface * > & Materials , const FTransform & GeometryCollectionTransform , UGeometryCollection * TargetGeometryCollectionObject , bool bReindexMaterials )
{
if ( SourceGeometryCollection = = nullptr )
{
return ;
}
const TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > SourceGeometryCollectionPtr = SourceGeometryCollection - > GetGeometryCollection ( ) ;
check ( TargetGeometryCollectionObject ) ;
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > GeometryCollectionPtr = TargetGeometryCollectionObject - > GetGeometryCollection ( ) ;
FGeometryCollection * GeometryCollection = GeometryCollectionPtr . Get ( ) ;
check ( GeometryCollection ) ;
2022-08-11 16:23:50 -04:00
int32 MaterialStart = AppendMaterials ( Materials , TargetGeometryCollectionObject , false ) ;
2022-06-23 17:00:03 -04:00
2022-10-21 19:51:57 -04:00
const int32 TargetTransformStart = GeometryCollectionPtr - > NumElements ( FGeometryCollection : : TransformGroup ) ;
if ( AppendGeometryCollection ( SourceGeometryCollectionPtr . Get ( ) , MaterialStart , GeometryCollectionTransform , GeometryCollection , bReindexMaterials ) )
{
AppendGeometryCollectionInstancedMeshes ( SourceGeometryCollection , TargetGeometryCollectionObject , TargetTransformStart ) ;
}
2022-06-01 21:41:57 -04:00
}
2022-08-18 15:37:22 -04:00
void FGeometryCollectionEngineConversion : : AppendStaticMesh ( const UStaticMesh * StaticMesh , const UStaticMeshComponent * StaticMeshComponent , const FTransform & StaticMeshTransform , UGeometryCollection * GeometryCollectionObject ,
2023-02-11 12:37:57 -05:00
bool ReindexMaterials , bool bAddInternalMaterials , bool bSplitComponents , bool bSetInternalFromMaterialIndex )
2022-06-01 21:41:57 -04:00
{
if ( StaticMesh = = nullptr )
{
return ;
}
TArray < UMaterialInterface * > Materials ;
Materials . Reserve ( StaticMesh - > GetStaticMaterials ( ) . Num ( ) ) ;
for ( int32 Index = 0 ; Index < StaticMesh - > GetStaticMaterials ( ) . Num ( ) ; + + Index )
{
UMaterialInterface * CurrMaterial = StaticMeshComponent ? StaticMeshComponent - > GetMaterial ( Index ) : StaticMesh - > GetMaterial ( Index ) ;
Materials . Add ( CurrMaterial ) ;
}
// Geometry collections usually carry the selection material, which we'll delete before appending
UMaterialInterface * BoneSelectedMaterial = LoadObject < UMaterialInterface > ( nullptr , UGeometryCollection : : GetSelectedMaterialPath ( ) , nullptr , LOAD_None , nullptr ) ;
GeometryCollectionObject - > Materials . Remove ( BoneSelectedMaterial ) ;
Materials . Remove ( BoneSelectedMaterial ) ;
2023-02-11 12:37:57 -05:00
AppendStaticMesh ( StaticMesh , Materials , StaticMeshTransform , GeometryCollectionObject , ReindexMaterials , bAddInternalMaterials , bSplitComponents , bSetInternalFromMaterialIndex ) ;
2022-06-01 21:41:57 -04:00
}
2022-06-23 17:00:03 -04:00
int32 FGeometryCollectionEngineConversion : : AppendGeometryCollectionMaterials ( const UGeometryCollection * SourceGeometryCollection , const UGeometryCollectionComponent * GeometryCollectionComponent , UGeometryCollection * TargetGeometryCollectionObject )
2022-06-01 21:41:57 -04:00
{
2022-06-23 17:00:03 -04:00
check ( SourceGeometryCollection ) ;
check ( GeometryCollectionComponent ) ;
check ( TargetGeometryCollectionObject ) ;
2022-06-01 21:41:57 -04:00
TArray < UMaterialInterface * > Materials ;
Materials . Reserve ( SourceGeometryCollection - > Materials . Num ( ) ) ;
for ( int32 Index = 0 ; Index < SourceGeometryCollection - > Materials . Num ( ) ; + + Index )
{
UMaterialInterface * CurrMaterial = GeometryCollectionComponent ? GeometryCollectionComponent - > GetMaterial ( Index ) : SourceGeometryCollection - > Materials [ Index ] . Get ( ) ;
Materials . Add ( CurrMaterial ) ;
}
// Geometry collections usually carry the selection material, which we'll delete before appending
UMaterialInterface * BoneSelectedMaterial = LoadObject < UMaterialInterface > ( nullptr , UGeometryCollection : : GetSelectedMaterialPath ( ) , nullptr , LOAD_None , nullptr ) ;
TargetGeometryCollectionObject - > Materials . Remove ( BoneSelectedMaterial ) ;
Materials . Remove ( BoneSelectedMaterial ) ;
2022-08-11 16:23:50 -04:00
return AppendMaterials ( Materials , TargetGeometryCollectionObject , false ) ;
2022-06-01 21:41:57 -04:00
}
2022-10-21 19:51:57 -04:00
void FGeometryCollectionEngineConversion : : AppendGeometryCollectionInstancedMeshes ( const UGeometryCollection * SourceGeometryCollectionObject , UGeometryCollection * TargetGeometryCollectionObject , int32 TargetTransformStartIndex )
{
TSharedPtr < const FGeometryCollection , ESPMode : : ThreadSafe > SourceGeometryCollectionPtr = SourceGeometryCollectionObject - > GetGeometryCollection ( ) ;
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > TargetGeometryCollectionPtr = TargetGeometryCollectionObject - > GetGeometryCollection ( ) ;
2022-12-02 00:40:18 -05:00
using namespace GeometryCollection : : Facades ;
2022-10-21 19:51:57 -04:00
if ( SourceGeometryCollectionPtr & & TargetGeometryCollectionPtr )
{
2022-12-02 00:40:18 -05:00
const FCollectionInstancedMeshFacade SourceInstancedMeshFacade ( * SourceGeometryCollectionPtr ) ;
FCollectionInstancedMeshFacade TargetInstancedMeshFacade ( * TargetGeometryCollectionPtr ) ;
2022-10-21 19:51:57 -04:00
2022-12-11 23:12:34 -05:00
if ( SourceInstancedMeshFacade . IsValid ( ) )
2022-12-02 00:40:18 -05:00
{
2022-12-11 23:12:34 -05:00
TargetInstancedMeshFacade . DefineSchema ( ) ;
const int32 NumSourceIndices = SourceInstancedMeshFacade . GetNumIndices ( ) ;
for ( int32 SourceTransformIndex = 0 ; SourceTransformIndex < NumSourceIndices ; SourceTransformIndex + + )
2022-10-21 19:51:57 -04:00
{
2022-12-11 23:12:34 -05:00
int32 TargetInstancedMeshIndex = INDEX_NONE ;
2022-12-02 00:40:18 -05:00
const int32 SourceAutoInstanceIndex = SourceInstancedMeshFacade . GetIndex ( SourceTransformIndex ) ;
if ( SourceAutoInstanceIndex ! = INDEX_NONE )
2022-10-21 19:51:57 -04:00
{
2022-12-02 00:40:18 -05:00
const FGeometryCollectionAutoInstanceMesh & SourceAutoInstanceMesh = SourceGeometryCollectionObject - > GetAutoInstanceMesh ( SourceAutoInstanceIndex ) ;
TargetInstancedMeshIndex = TargetGeometryCollectionObject - > FindOrAddAutoInstanceMesh ( SourceAutoInstanceMesh ) ;
2022-10-21 19:51:57 -04:00
}
2022-12-11 23:12:34 -05:00
const int32 TargetTransformIndex = TargetTransformStartIndex + SourceTransformIndex ;
TargetInstancedMeshFacade . SetIndex ( TargetTransformIndex , TargetInstancedMeshIndex ) ;
2022-10-21 19:51:57 -04:00
}
}
}
}
2022-06-01 21:41:57 -04:00
2022-06-23 17:00:03 -04:00
void FGeometryCollectionEngineConversion : : AppendGeometryCollection ( const UGeometryCollection * SourceGeometryCollection , const UGeometryCollectionComponent * GeometryCollectionComponent , const FTransform & GeometryCollectionTransform , UGeometryCollection * TargetGeometryCollectionObject , bool bReindexMaterials )
{
if ( SourceGeometryCollection = = nullptr )
{
return ;
}
int32 MaterialStartIndex = AppendGeometryCollectionMaterials ( SourceGeometryCollection , GeometryCollectionComponent , TargetGeometryCollectionObject ) ;
const TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > SourceGeometryCollectionPtr = SourceGeometryCollection - > GetGeometryCollection ( ) ;
check ( TargetGeometryCollectionObject ) ;
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > GeometryCollectionPtr = TargetGeometryCollectionObject - > GetGeometryCollection ( ) ;
FGeometryCollection * GeometryCollection = GeometryCollectionPtr . Get ( ) ;
check ( GeometryCollection ) ;
2022-10-21 19:51:57 -04:00
const int32 TargetTransformStart = GeometryCollectionPtr - > NumElements ( FGeometryCollection : : TransformGroup ) ;
if ( AppendGeometryCollection ( SourceGeometryCollectionPtr . Get ( ) , MaterialStartIndex , GeometryCollectionTransform , GeometryCollection , bReindexMaterials ) )
{
AppendGeometryCollectionInstancedMeshes ( SourceGeometryCollection , TargetGeometryCollectionObject , TargetTransformStart ) ;
}
2022-06-23 17:00:03 -04:00
}
2024-04-03 22:22:28 -04:00
bool FGeometryCollectionEngineConversion : : AppendSkeletalMesh ( const USkeletalMesh * InSkeletalMesh , int32 MaterialStartIndex , const FTransform & SkeletalMeshTransform ,
FManagedArrayCollection * InManagedArrayCollection , bool bReindexMaterials )
2022-06-23 17:00:03 -04:00
{
//UE_LOG(UGeometryCollectionConversionLogging, Log, TEXT("FGeometryCollectionEngineConversion::AppendSkeletalMesh()"));
2024-04-03 22:22:28 -04:00
# if WITH_EDITOR
int LODIndex = 0 ;
if ( ! InManagedArrayCollection )
2022-06-23 17:00:03 -04:00
{
return false ;
}
2024-04-03 22:22:28 -04:00
FMeshDescription MeshDescription ;
if ( ! InSkeletalMesh - > CloneMeshDescription ( LODIndex , MeshDescription ) )
2022-06-23 17:00:03 -04:00
{
return false ;
}
2024-04-03 22:22:28 -04:00
FGeometryCollection GeometryCollection ;
// Transform Attributes
TManagedArray < FTransform3f > & LocalSpaceTransform = GeometryCollection . ModifyAttribute < FTransform3f > ( FTransformCollection : : TransformAttribute , FTransformCollection : : TransformGroup ) ;
TManagedArray < int32 > & Parent = GeometryCollection . ModifyAttribute < int32 > ( FTransformCollection : : ParentAttribute , FTransformCollection : : TransformGroup ) ;
2024-04-21 23:27:40 -04:00
TManagedArray < TSet < int32 > > & Children = GeometryCollection . ModifyAttribute < TSet < int32 > > ( FTransformCollection : : ChildrenAttribute , FTransformCollection : : TransformGroup ) ;
2024-04-03 22:22:28 -04:00
TManagedArray < FLinearColor > & BoneColor = GeometryCollection . ModifyAttribute < FLinearColor > ( " BoneColor " , FTransformCollection : : TransformGroup ) ;
TManagedArray < FString > & BoneName = GeometryCollection . ModifyAttribute < FString > ( " BoneName " , FTransformCollection : : TransformGroup ) ;
TManagedArray < int32 > & SimulationType = GeometryCollection . ModifyAttribute < int32 > ( " SimulationType " , FTransformCollection : : TransformGroup ) ;
// Vertices Attributes
TManagedArray < FVector3f > & Vertex = GeometryCollection . ModifyAttribute < FVector3f > ( " Vertex " , FGeometryCollection : : VerticesGroup ) ;
TManagedArray < FVector3f > & Normal = GeometryCollection . ModifyAttribute < FVector3f > ( " Normal " , FGeometryCollection : : VerticesGroup ) ;
TManagedArray < FLinearColor > & Color = GeometryCollection . ModifyAttribute < FLinearColor > ( " Color " , FGeometryCollection : : VerticesGroup ) ;
TManagedArray < FVector3f > & TangentU = GeometryCollection . ModifyAttribute < FVector3f > ( " TangentU " , FGeometryCollection : : VerticesGroup ) ;
TManagedArray < FVector3f > & TangentV = GeometryCollection . ModifyAttribute < FVector3f > ( " TangentV " , FGeometryCollection : : VerticesGroup ) ;
TManagedArray < int32 > & BoneMap = GeometryCollection . ModifyAttribute < int32 > ( " BoneMap " , FGeometryCollection : : VerticesGroup ) ;
// Index Attributes
TManagedArray < FIntVector > & Indices = GeometryCollection . ModifyAttribute < FIntVector > ( " Indices " , FGeometryCollection : : FacesGroup ) ;
TManagedArray < bool > & Visible = GeometryCollection . ModifyAttribute < bool > ( " Visible " , FGeometryCollection : : FacesGroup ) ;
TManagedArray < int32 > & MaterialIndex = GeometryCollection . ModifyAttribute < int32 > ( " MaterialIndex " , FGeometryCollection : : FacesGroup ) ;
TManagedArray < int32 > & MaterialID = GeometryCollection . ModifyAttribute < int32 > ( " MaterialID " , FGeometryCollection : : FacesGroup ) ;
2022-06-23 17:00:03 -04:00
//
2024-04-03 22:22:28 -04:00
// Convert the transform hierarchy
2022-06-23 17:00:03 -04:00
//
2024-03-30 12:25:12 -04:00
int32 RootIndex = INDEX_NONE ;
2024-04-03 22:22:28 -04:00
int32 TransformBaseIndex = INDEX_NONE ;
const USkeleton * Skeleton = InSkeletalMesh - > GetSkeleton ( ) ;
2024-03-30 12:25:12 -04:00
const TArray < FTransform > & RestArray = Skeleton - > GetRefLocalPoses ( ) ;
2024-04-21 23:27:40 -04:00
const FReferenceSkeleton & ReferenceSkeleton = Skeleton - > GetReferenceSkeleton ( ) ;
2024-03-30 12:25:12 -04:00
2024-04-21 23:27:40 -04:00
if ( ReferenceSkeleton . GetNum ( ) )
2022-06-23 17:00:03 -04:00
{
2024-04-21 23:27:40 -04:00
TransformBaseIndex = GeometryCollection . AddElements ( ReferenceSkeleton . GetNum ( ) , FGeometryCollection : : TransformGroup ) ;
2024-04-03 22:22:28 -04:00
RootIndex = TransformBaseIndex ;
2024-03-30 12:25:12 -04:00
2024-04-21 23:27:40 -04:00
for ( int32 BoneIndex = 0 ; BoneIndex < ReferenceSkeleton . GetNum ( ) ; BoneIndex + + )
2024-03-30 12:25:12 -04:00
{
2024-04-03 22:22:28 -04:00
// For validation against the component space position use
2024-04-21 23:27:40 -04:00
// FTransform ComponentSpaceTransform =FAnimationRuntime::GetComponentSpaceTransformRefPose(ReferenceSkeleton, SkeletalBoneMap[BoneIndex]);
2024-04-03 22:22:28 -04:00
LocalSpaceTransform [ TransformBaseIndex + BoneIndex ] = FTransform3f ( RestArray [ BoneIndex ] ) ;
2024-04-21 23:27:40 -04:00
BoneName [ TransformBaseIndex + BoneIndex ] = ReferenceSkeleton . GetRefBoneInfo ( ) [ BoneIndex ] . Name . ToString ( ) ;
Parent [ TransformBaseIndex + BoneIndex ] = ReferenceSkeleton . GetRefBoneInfo ( ) [ BoneIndex ] . ParentIndex ;
TArray < int32 > ChildrenArr ;
if ( ReferenceSkeleton . GetDirectChildBones ( BoneIndex , ChildrenArr ) )
{
Children [ TransformBaseIndex + BoneIndex ] . Append ( ChildrenArr ) ;
}
2024-04-03 22:22:28 -04:00
SimulationType [ TransformBaseIndex + BoneIndex ] = FGeometryCollection : : ESimulationTypes : : FST_None ;
BoneColor [ TransformBaseIndex + BoneIndex ] = FLinearColor : : MakeRandomColor ( ) ;
if ( Parent [ TransformBaseIndex + BoneIndex ] = = INDEX_NONE )
{
RootIndex = TransformBaseIndex + BoneIndex ;
}
2024-03-30 12:25:12 -04:00
}
2022-06-23 17:00:03 -04:00
}
//
2024-04-03 22:22:28 -04:00
// Identify disconnected geoemtry
2022-06-23 17:00:03 -04:00
//
2024-04-03 22:22:28 -04:00
int32 VertexCount = 0 , TriangleCount = 0 ;
TArray < int32 > SourceVertexToComponentMap ; // Map from mesh vertex index to target vertex index
TArray < TArray < FIntVector > > ComponentsSourceIndices ; // Mesh triangle indices of each component.
TArray < TArray < FIntVector2 > > SourceToTargetTriangleMap ; // Mesh triangle index of each triangle in the component.
2024-04-16 18:54:01 -04:00
GeometryCollectionEngineUtility : : GenerateConnectedComponents ( InSkeletalMesh , ComponentsSourceIndices ,
SourceToTargetTriangleMap , SourceVertexToComponentMap , TriangleCount , VertexCount ) ;
2022-06-23 17:00:03 -04:00
2024-04-03 22:22:28 -04:00
//
// Add the Triangles to the Geometry Collection
//.. ensure all component vertices are contigious in the array
//
int NumVertices = GeometryCollection . NumElements ( FGeometryCollection : : VerticesGroup ) ;
int IndicesBaseIndex = GeometryCollection . AddElements ( TriangleCount , FGeometryCollection : : FacesGroup ) ;
int CurrentIndex = IndicesBaseIndex ;
for ( int ComponentIndex = 0 ; ComponentIndex < ComponentsSourceIndices . Num ( ) ; ComponentIndex + + )
2022-06-23 17:00:03 -04:00
{
2024-04-03 22:22:28 -04:00
for ( int32 TriangleIndex = 0 ; TriangleIndex < ComponentsSourceIndices [ ComponentIndex ] . Num ( ) ; TriangleIndex + + )
{
SourceToTargetTriangleMap [ ComponentIndex ] [ TriangleIndex ] [ 1 ] = CurrentIndex ;
FIntVector & Triangle = ComponentsSourceIndices [ ComponentIndex ] [ TriangleIndex ] ;
for ( int k = 0 ; k < 3 ; k + + )
{
Indices [ CurrentIndex ] [ k ] = SourceVertexToComponentMap [ Triangle [ k ] ] + IndicesBaseIndex ;
}
Visible [ CurrentIndex ] = true ;
MaterialID [ CurrentIndex ] = 0 ;
MaterialIndex [ CurrentIndex ] = CurrentIndex ;
CurrentIndex + + ;
}
2022-06-23 17:00:03 -04:00
}
//
// Vertex Attributes
//
2024-04-03 22:22:28 -04:00
int VertexBaseIndex = GeometryCollection . AddElements ( VertexCount , FGeometryCollection : : VerticesGroup ) ;
int NumTargetVertices = GeometryCollection . NumElements ( FGeometryCollection : : VerticesGroup ) ;
2024-03-30 12:25:12 -04:00
2022-06-23 17:00:03 -04:00
//
// Transform Attributes
//
2024-03-30 12:25:12 -04:00
2024-04-03 22:22:28 -04:00
// add transforms for the separated geometry components.
TArray < int32 > ComponentToTransformGroupIndex ;
ComponentToTransformGroupIndex . Init ( INDEX_NONE , ComponentsSourceIndices . Num ( ) ) ;
int32 ComponentTransformBaseIndex = GeometryCollection . AddElements ( ComponentsSourceIndices . Num ( ) , FTransformCollection : : TransformGroup ) ;
for ( int ComponentIndex = 0 ; ComponentIndex < ComponentsSourceIndices . Num ( ) ; ComponentIndex + + )
{
int32 ComponentTransformIndex = ComponentTransformBaseIndex + ComponentIndex ;
Parent [ ComponentTransformIndex ] = RootIndex ;
2024-04-22 22:00:37 -04:00
if ( RootIndex ! = INDEX_NONE )
{
Children [ RootIndex ] . Add ( ComponentTransformIndex ) ;
}
2024-04-03 22:22:28 -04:00
BoneName [ ComponentTransformIndex ] = FString : : Printf ( TEXT ( " %s_Mesh%d " ) , * BoneName [ RootIndex ] , ComponentTransformIndex ) ;
LocalSpaceTransform [ ComponentTransformIndex ] = FTransform3f : : Identity ;
SimulationType [ ComponentTransformIndex ] = FGeometryCollection : : ESimulationTypes : : FST_None ;
BoneColor [ ComponentTransformIndex ] = FLinearColor : : MakeRandomColor ( ) ;
ComponentToTransformGroupIndex [ ComponentIndex ] = ComponentTransformIndex ;
}
2024-03-30 12:25:12 -04:00
TArray < FTransform > ComponentTransform ;
GeometryCollectionAlgo : : GlobalMatrices ( LocalSpaceTransform , Parent , ComponentTransform ) ;
2024-04-16 18:54:01 -04:00
bool bHasVertexColors = false ;
2024-04-03 22:22:28 -04:00
FLinearColor DefaultColor = FLinearColor : : White ;
2024-04-16 18:54:01 -04:00
FSkeletalMeshConstAttributes SkeletalMeshConstAttributes ( MeshDescription ) ;
TVertexInstanceAttributesConstRef < FVector4f > InstanceColors = SkeletalMeshConstAttributes . GetVertexInstanceColors ( ) ;
if ( InstanceColors . IsValid ( ) )
2022-06-23 17:00:03 -04:00
{
2024-04-16 18:54:01 -04:00
bHasVertexColors = true ;
DefaultColor = InstanceColors . GetDefaultValue ( ) ;
2022-06-23 17:00:03 -04:00
}
2024-04-03 22:22:28 -04:00
// @todo(GeometryCollectionConversion) : Add support for UV's, Normals
//const int32 NumUVLayers = VertexBuffers.StaticMeshVertexBuffer.GetNumTexCoords();
//GeometryCollection::UV::SetNumUVLayers(*GeometryCollection, NumUVLayers);
//GeometryCollection::UV::FUVLayers UVLayers = GeometryCollection::UV::FindActiveUVLayers(*GeometryCollection);
TArray < bool > TargetVertexVisited ; TargetVertexVisited . Init ( false , NumTargetVertices ) ;
for ( int ComponentIndex = 0 ; ComponentIndex < ComponentsSourceIndices . Num ( ) ; ComponentIndex + + )
{
for ( int32 TriangleIndex = 0 ; TriangleIndex < ComponentsSourceIndices [ ComponentIndex ] . Num ( ) ; TriangleIndex + + )
{
int32 SourceTriangleIndex = SourceToTargetTriangleMap [ ComponentIndex ] [ TriangleIndex ] [ 0 ] ;
FIntVector & Triangle = ComponentsSourceIndices [ ComponentIndex ] [ TriangleIndex ] ;
for ( int k = 0 ; k < 3 ; k + + )
{
int SourceVertexIndex = Triangle [ k ] ;
if ( ensure ( 0 < = SourceVertexIndex & & SourceVertexIndex < SourceVertexToComponentMap . Num ( ) ) )
{
int TargetVertexIndex = SourceVertexToComponentMap [ SourceVertexIndex ] + VertexBaseIndex ;
if ( ensure ( VertexBaseIndex < = TargetVertexIndex & & TargetVertexIndex < TargetVertexVisited . Num ( ) ) )
{
if ( ! TargetVertexVisited [ TargetVertexIndex ] )
{
// Vertex position
// @todo(Skin Wieghts) : Currently its a static pose in component space.
BoneMap [ TargetVertexIndex ] = ComponentToTransformGroupIndex [ ComponentIndex ] ;
2024-04-16 18:54:01 -04:00
FVector SourceVertex = ( FVector ) MeshDescription . GetVertexPosition ( SourceVertexIndex ) ;
2024-04-03 22:22:28 -04:00
FMatrix M = ComponentTransform [ BoneMap [ TargetVertexIndex ] ] . ToInverseMatrixWithScale ( ) ;
Vertex [ TargetVertexIndex ] = ( FVector4f ) M . TransformPosition ( SourceVertex ) ;
TargetVertexVisited [ TargetVertexIndex ] = true ;
2024-04-16 18:54:01 -04:00
// transfer color
2024-04-04 23:52:30 -04:00
Color [ TargetVertexIndex ] = DefaultColor ;
2024-04-16 18:54:01 -04:00
if ( bHasVertexColors )
2024-04-03 22:22:28 -04:00
{
2024-04-16 18:54:01 -04:00
TArrayView < const FVertexInstanceID > SourceInstanceTri = MeshDescription . GetTriangleVertexInstances ( SourceTriangleIndex ) ;
FVector4f InstColor = InstanceColors [ SourceInstanceTri [ k ] ] ;
UE : : Geometry : : LinearColors : : SRGBToLinear ( InstColor ) ;
Color [ TargetVertexIndex ] = FLinearColor ( InstColor ) ;
2024-04-03 22:22:28 -04:00
}
// @todo(GeometryCollectionConversion) : Add support for UV's, Normals
//TangentU[VertexOffset] = VertexBuffers.StaticMeshVertexBuffer.VertexTangentX(VertexIndex);
//TangentV[VertexOffset] = VertexBuffers.StaticMeshVertexBuffer.VertexTangentY(VertexIndex);
//Normal[VertexOffset] = VertexBuffers.StaticMeshVertexBuffer.VertexTangentZ(VertexIndex);
//for (int32 UVLayerIdx = 0; UVLayerIdx < NumUVLayers; ++UVLayerIdx)
//{
// UVLayers[UVLayerIdx][VertexOffset] = VertexBuffers.StaticMeshVertexBuffer.GetVertexUV(VertexIndex, UVLayerIdx);
//}
}
}
}
}
}
}
2024-04-16 18:54:01 -04:00
2022-06-23 17:00:03 -04:00
// Geometry Group
TArray < int32 > GeometryIndices ;
2024-04-03 22:22:28 -04:00
FGeometryCollection : : DefineGeometrySchema ( GeometryCollection ) ;
GeometryCollectionAlgo : : ContiguousArray ( GeometryIndices , GeometryCollection . NumElements ( FGeometryCollection : : GeometryGroup ) ) ;
GeometryCollection . RemoveDependencyFor ( FGeometryCollection : : GeometryGroup ) ;
GeometryCollection . RemoveElements ( FGeometryCollection : : GeometryGroup , GeometryIndices ) ;
: : GeometryCollection : : AddGeometryProperties ( & GeometryCollection ) ;
2022-06-23 17:00:03 -04:00
2024-04-03 22:22:28 -04:00
GeometryCollection . CopyTo ( InManagedArrayCollection ) ;
2022-06-23 17:00:03 -04:00
return true ;
2024-04-03 22:22:28 -04:00
# else
return false ;
# endif
2022-06-23 17:00:03 -04:00
}
2022-09-21 11:52:44 -04:00
void FGeometryCollectionEngineConversion : : AppendSkeleton ( const USkeleton * InSkeleton , const FTransform & SkeletalMeshTransform , FManagedArrayCollection * InCollection )
{
//UE_LOG(UGeometryCollectionConversionLogging, Log, TEXT("FGeometryCollectionEngineConversion::AppendSkeletalMesh()"));
if ( ! InCollection | | ! InSkeleton )
{
return ;
}
FGeometryCollection : : DefineTransformSchema ( * InCollection ) ;
2022-11-18 10:22:38 -05:00
GeometryCollection : : Facades : : FTransformSource TransformSourceFacade ( * InCollection ) ;
2022-09-21 11:52:44 -04:00
2024-01-17 23:07:14 -05:00
TManagedArray < FTransform3f > & Transform = InCollection - > ModifyAttribute < FTransform3f > ( FTransformCollection : : TransformAttribute , FTransformCollection : : TransformGroup ) ;
2022-09-21 11:52:44 -04:00
TManagedArray < FLinearColor > & BoneColor = InCollection - > ModifyAttribute < FLinearColor > ( " BoneColor " , FTransformCollection : : TransformGroup ) ;
TManagedArray < FString > & BoneName = InCollection - > ModifyAttribute < FString > ( " BoneName " , FTransformCollection : : TransformGroup ) ;
TManagedArray < int32 > & Parent = InCollection - > ModifyAttribute < int32 > ( FTransformCollection : : ParentAttribute , FTransformCollection : : TransformGroup ) ;
TManagedArray < TSet < int32 > > & Child = InCollection - > ModifyAttribute < TSet < int32 > > ( FTransformCollection : : ChildrenAttribute , FTransformCollection : : TransformGroup ) ;
const FReferenceSkeleton & Skeleton = InSkeleton - > GetReferenceSkeleton ( ) ;
int32 NumBones = Skeleton . GetNum ( ) ;
if ( NumBones )
{
const TArray < FTransform > & RestTransform = Skeleton . GetRefBonePose ( ) ;
const TArray < FMeshBoneInfo > & BoneInfo = Skeleton . GetRefBoneInfo ( ) ;
TSet < int32 > Roots ;
int32 TransformBaseIndex = InCollection - > AddElements ( NumBones , FGeometryCollection : : TransformGroup ) ;
for ( int i = 0 , Idx = TransformBaseIndex ; i < NumBones ; i + + , Idx + + )
{
2024-01-17 23:07:14 -05:00
Transform [ Idx ] = FTransform3f ( RestTransform [ i ] ) ;
2022-09-21 11:52:44 -04:00
BoneColor [ Idx ] = FLinearColor ( FColor ( FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , FMath : : Rand ( ) % 100 + 5 , 255 ) ) ;
BoneName [ Idx ] = BoneInfo [ i ] . Name . ToString ( ) ;
Parent [ Idx ] = BoneInfo [ i ] . ParentIndex ;
if ( Parent [ Idx ] ! = INDEX_NONE )
{
Child [ Parent [ Idx ] ] . Add ( Idx ) ;
}
else
{
Roots . Add ( Idx ) ;
}
}
ensure ( Roots . Num ( ) ) ;
2022-11-18 10:22:38 -05:00
TransformSourceFacade . AddTransformSource ( InSkeleton - > GetName ( ) , InSkeleton - > GetGuid ( ) . ToString ( ) , Roots ) ;
2022-09-21 11:52:44 -04:00
}
}
2022-06-23 17:00:03 -04:00
const FSkeletalMeshLODRenderData * FGeometryCollectionEngineConversion : : GetSkeletalMeshLOD ( const USkeletalMesh * SkeletalMesh , int32 LOD )
{
if ( const USkeleton * Skeleton = SkeletalMesh - > GetSkeleton ( ) )
{
if ( const FSkeletalMeshRenderData * SkelMeshRenderData = SkeletalMesh - > GetResourceForRendering ( ) )
{
if ( SkelMeshRenderData - > LODRenderData . IsValidIndex ( LOD ) )
{
return & SkelMeshRenderData - > LODRenderData [ LOD ] ;
}
}
}
return nullptr ;
}
void FGeometryCollectionEngineConversion : : AppendSkeletalMesh ( const USkeletalMesh * SkeletalMesh , const USkeletalMeshComponent * SkeletalMeshComponent , const FTransform & SkeletalMeshTransform , UGeometryCollection * GeometryCollectionObject , bool bReindexMaterials )
2022-06-01 21:41:57 -04:00
{
//UE_LOG(UGeometryCollectionConversionLogging, Log, TEXT("FGeometryCollectionEngineConversion::AppendSkeletalMesh()"));
check ( SkeletalMesh ) ;
if ( GeometryCollectionObject )
{
TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > GeometryCollectionPtr = GeometryCollectionObject - > GetGeometryCollection ( ) ;
if ( FGeometryCollection * GeometryCollection = GeometryCollectionPtr . Get ( ) )
{
2022-06-23 17:00:03 -04:00
int32 MaterialStart = GeometryCollectionObject - > Materials . Num ( ) ;
if ( AppendSkeletalMesh ( SkeletalMesh , MaterialStart , SkeletalMeshTransform , GeometryCollection , bReindexMaterials ) )
2022-06-01 21:41:57 -04:00
{
2022-06-23 17:00:03 -04:00
AppendSkeletalMeshMaterials ( SkeletalMesh , SkeletalMeshComponent , GeometryCollectionObject ) ;
2022-06-01 21:41:57 -04:00
}
}
}
}
2022-06-23 17:00:03 -04:00
int32 FGeometryCollectionEngineConversion : : AppendSkeletalMeshMaterials ( const USkeletalMesh * SkeletalMesh , const USkeletalMeshComponent * SkeletalMeshComponent , UGeometryCollection * GeometryCollectionObject )
{
check ( SkeletalMesh ) ;
check ( SkeletalMeshComponent ) ;
check ( GeometryCollectionObject ) ;
const TArray < FSkeletalMaterial > & SkeletalMeshMaterials = SkeletalMesh - > GetMaterials ( ) ;
int32 CurrIdx = 0 ;
UMaterialInterface * CurrMaterial = SkeletalMeshComponent ? SkeletalMeshComponent - > GetMaterial ( CurrIdx ) : ToRawPtr ( SkeletalMeshMaterials [ CurrIdx ] . MaterialInterface ) ;
int MaterialStart = GeometryCollectionObject - > Materials . Num ( ) ;
while ( CurrMaterial )
{
GeometryCollectionObject - > Materials . Add ( CurrMaterial ) ;
CurrMaterial = SkeletalMeshComponent ? SkeletalMeshComponent - > GetMaterial ( + + CurrIdx ) : ToRawPtr ( SkeletalMeshMaterials [ + + CurrIdx ] . MaterialInterface ) ;
}
return MaterialStart ;
}
2022-11-14 15:56:50 -05:00
void FGeometryCollectionEngineConversion : : AppendGeometryCollectionSource ( const FGeometryCollectionSource & GeometryCollectionSource , FGeometryCollection & GeometryCollectionInOut , TArray < UMaterial * > & MaterialsInOut , bool ReindexMaterials )
2022-10-26 19:04:47 -04:00
{
2023-01-24 13:20:58 -05:00
if ( const UObject * SourceObject = GeometryCollectionSource . SourceGeometryObject . TryLoad ( ) )
2022-10-26 19:04:47 -04:00
{
const int32 StartMaterialIndex = MaterialsInOut . Num ( ) ;
MaterialsInOut . Append ( GeometryCollectionSource . SourceMaterial ) ;
if ( const UStaticMesh * SourceStaticMesh = Cast < UStaticMesh > ( SourceObject ) )
{
2023-02-11 12:37:57 -05:00
bool bLegacyAddInternal = GeometryCollectionSource . bAddInternalMaterials ;
2022-10-26 19:04:47 -04:00
AppendStaticMesh (
SourceStaticMesh ,
StartMaterialIndex ,
GeometryCollectionSource . LocalTransform ,
2022-11-14 15:56:50 -05:00
& GeometryCollectionInOut ,
ReindexMaterials ,
2023-02-11 12:37:57 -05:00
bLegacyAddInternal ,
GeometryCollectionSource . bSplitComponents ,
GeometryCollectionSource . bSetInternalFromMaterialIndex
2022-10-26 19:04:47 -04:00
) ;
}
else if ( const USkeletalMesh * SourceSkeletalMesh = Cast < USkeletalMesh > ( SourceObject ) )
{
AppendSkeletalMesh (
SourceSkeletalMesh ,
StartMaterialIndex ,
GeometryCollectionSource . LocalTransform ,
2022-11-14 15:56:50 -05:00
& GeometryCollectionInOut ,
ReindexMaterials
2022-10-26 19:04:47 -04:00
) ;
}
else if ( const UGeometryCollection * SourceGeometryCollection = Cast < UGeometryCollection > ( SourceObject ) )
{
AppendGeometryCollection (
SourceGeometryCollection - > GetGeometryCollection ( ) . Get ( ) ,
StartMaterialIndex ,
GeometryCollectionSource . LocalTransform ,
2022-11-14 15:56:50 -05:00
& GeometryCollectionInOut ,
ReindexMaterials
2022-10-26 19:04:47 -04:00
) ;
}
}
2023-08-30 20:50:47 -04:00
}
2024-03-14 20:44:48 -04:00
void FGeometryCollectionEngineConversion : : ConvertStaticMeshToGeometryCollection ( const TObjectPtr < UStaticMesh > StaticMesh , FManagedArrayCollection & OutCollection , TArray < TObjectPtr < UMaterial > > & OutMaterials , TArray < FGeometryCollectionAutoInstanceMesh > & OutInstancedMeshes , bool bSetInternalFromMaterialIndex , bool bSplitComponents )
{
# if WITH_EDITORONLY_DATA
if ( UGeometryCollection * NewGeometryCollection = NewObject < UGeometryCollection > ( ) )
{
// If any of the static meshes have Nanite enabled, also enable on the new geometry collection asset for convenience.
NewGeometryCollection - > EnableNanite | = StaticMesh - > IsNaniteEnabled ( ) ;
FTransform ComponentTransform = FTransform : : Identity ;
// Record the contributing source on the asset.
FSoftObjectPath SourceSoftObjectPath ( StaticMesh ) ;
// Materials
TArray < TObjectPtr < UMaterialInterface > > MatArr ;
for ( auto & StaticMaterial : StaticMesh - > GetStaticMaterials ( ) )
{
MatArr . Emplace ( StaticMaterial . MaterialInterface ) ;
}
TArray < TObjectPtr < UMaterialInterface > > SourceMaterials ( MatArr ) ;
// InstanceMeshes
FGeometryCollectionAutoInstanceMesh NewInstanceMesh ;
NewInstanceMesh . Mesh = StaticMesh ;
NewInstanceMesh . Materials = SourceMaterials ;
OutInstancedMeshes . Emplace ( NewInstanceMesh ) ;
2024-04-08 20:44:55 -04:00
bool bAddInternalMaterials = false ;
2024-03-14 20:44:48 -04:00
NewGeometryCollection - > GeometrySource . Emplace ( SourceSoftObjectPath , ComponentTransform , SourceMaterials , bSplitComponents , bSetInternalFromMaterialIndex ) ;
FGeometryCollectionEngineConversion : : AppendStaticMesh ( StaticMesh , SourceMaterials , ComponentTransform , NewGeometryCollection , false , bAddInternalMaterials , bSplitComponents , bSetInternalFromMaterialIndex ) ;
NewGeometryCollection - > InitializeMaterials ( ) ;
// Materials
for ( auto & Material : NewGeometryCollection - > Materials )
{
OutMaterials . Emplace ( Material - > GetMaterial ( ) ) ;
}
TSharedPtr < FGeometryCollection > OutCollectionPtr = NewGeometryCollection - > GetGeometryCollection ( ) ;
OutCollectionPtr - > CopyTo ( & OutCollection ) ;
}
# endif //WITH_EDITORONLY_DATA
}
2024-03-28 10:57:17 -04:00
void FGeometryCollectionEngineConversion : : ConvertGeometryCollectionToGeometryCollection ( const TObjectPtr < UGeometryCollection > InGeometryCollectionAssetPtr , FManagedArrayCollection & OutCollection , TArray < TObjectPtr < UMaterial > > & OutMaterials , TArray < FGeometryCollectionAutoInstanceMesh > & OutInstancedMeshes )
{
if ( InGeometryCollectionAssetPtr )
{
const TSharedPtr < FGeometryCollection , ESPMode : : ThreadSafe > NewGeometryCollectionPtr = InGeometryCollectionAssetPtr - > GetGeometryCollection ( ) ;
// Materials
for ( auto & Material : InGeometryCollectionAssetPtr - > Materials )
{
OutMaterials . Emplace ( Material - > GetMaterial ( ) ) ;
}
// InstanceMeshes
OutInstancedMeshes = InGeometryCollectionAssetPtr - > AutoInstanceMeshes ;
if ( NewGeometryCollectionPtr )
{
NewGeometryCollectionPtr - > CopyTo ( & OutCollection ) ;
}
}
}
2024-04-21 23:27:40 -04:00
void FGeometryCollectionEngineConversion : : ConvertActorToGeometryCollection ( const AActor * Actor , FManagedArrayCollection & OutCollection , TArray < TObjectPtr < UMaterial > > & OutMaterials , TArray < FGeometryCollectionAutoInstanceMesh > & OutInstancedMeshes , const FSkeletalMeshToCollectionConversionParameters & ConversionParameters , bool bSplitComponents )
2024-04-08 20:44:55 -04:00
{
# if WITH_EDITORONLY_DATA
const FTransform ActorTransform ( Actor - > GetTransform ( ) ) ;
if ( UGeometryCollection * NewGeometryCollection = NewObject < UGeometryCollection > ( ) )
{
TInlineComponentArray < UStaticMeshComponent * > StaticMeshComponents ( Actor ) ;
for ( UStaticMeshComponent * StaticMeshComponent : StaticMeshComponents )
{
if ( StaticMeshComponent )
{
if ( const UStaticMesh * ComponentStaticMesh = StaticMeshComponent - > GetStaticMesh ( ) )
{
NewGeometryCollection - > EnableNanite | = ComponentStaticMesh - > IsNaniteEnabled ( ) ;
FTransform ComponentTransform ( StaticMeshComponent - > GetComponentTransform ( ) ) ;
ComponentTransform . SetTranslation ( ( ComponentTransform . GetTranslation ( ) - ActorTransform . GetTranslation ( ) ) ) ;
// Record the contributing source on the asset.
FSoftObjectPath SourceSoftObjectPath ( ComponentStaticMesh ) ;
TArray < TObjectPtr < UMaterialInterface > > SourceMaterials ( StaticMeshComponent - > GetMaterials ( ) ) ;
NewGeometryCollection - > GeometrySource . Emplace ( SourceSoftObjectPath , ComponentTransform , SourceMaterials , bSplitComponents , true /*bSetInternalFromMaterialIndex*/ ) ;
FGeometryCollectionEngineConversion : : AppendStaticMesh ( ComponentStaticMesh , SourceMaterials , ComponentTransform , NewGeometryCollection , false /*bReindexMaterials*/ , false /*bAddInternalMaterials*/ , bSplitComponents , true /*bSetInternalFromMaterialIndex*/ ) ;
}
}
}
TInlineComponentArray < UGeometryCollectionComponent * > GeometryCollectionComponents ( Actor ) ;
for ( UGeometryCollectionComponent * GeometryCollectionComponent : GeometryCollectionComponents )
{
if ( GeometryCollectionComponent )
{
if ( const UGeometryCollection * RestCollection = GeometryCollectionComponent - > GetRestCollection ( ) )
{
NewGeometryCollection - > EnableNanite | = RestCollection - > EnableNanite ;
FTransform ComponentTransform ( GeometryCollectionComponent - > GetComponentTransform ( ) ) ;
ComponentTransform . SetTranslation ( ( ComponentTransform . GetTranslation ( ) - ActorTransform . GetTranslation ( ) ) ) ;
// Record the contributing source on the asset.
FSoftObjectPath SourceSoftObjectPath ( RestCollection ) ;
int32 NumMaterials = GeometryCollectionComponent - > GetNumMaterials ( ) ;
TArray < TObjectPtr < UMaterialInterface > > SourceMaterials ;
SourceMaterials . SetNum ( NumMaterials ) ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < NumMaterials ; + + MaterialIndex )
{
SourceMaterials [ MaterialIndex ] = GeometryCollectionComponent - > GetMaterial ( MaterialIndex ) ;
}
NewGeometryCollection - > GeometrySource . Emplace ( SourceSoftObjectPath , ComponentTransform , SourceMaterials , bSplitComponents , true /*bSetInternalFromMaterialIndex*/ ) ;
FGeometryCollectionEngineConversion : : AppendGeometryCollection ( RestCollection , GeometryCollectionComponent , ComponentTransform , NewGeometryCollection , false /*bReindexMaterials*/ ) ;
}
}
}
NewGeometryCollection - > InitializeMaterials ( ) ;
2024-04-21 23:27:40 -04:00
if ( ConversionParameters . bParentAllBonesUnderNewRoot & & FGeometryCollectionClusteringUtility : : ContainsMultipleRootBones ( NewGeometryCollection - > GetGeometryCollection ( ) . Get ( ) ) )
{
UE_LOG ( UGeometryCollectionConversionLogging , Log , TEXT ( " FGeometryCollectionEngineConversion::ConvertActorToGeometryCollection() - All bones were parented under new root. " ) ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( NewGeometryCollection - > GetGeometryCollection ( ) . Get ( ) , FName ( " root " ) , false ) ;
}
2024-04-08 20:44:55 -04:00
// InstanceMeshes
OutInstancedMeshes . Append ( NewGeometryCollection - > AutoInstanceMeshes ) ;
// Materials
for ( auto & Material : NewGeometryCollection - > Materials )
{
OutMaterials . Emplace ( Material - > GetMaterial ( ) ) ;
}
TSharedPtr < FGeometryCollection > OutCollectionPtr = NewGeometryCollection - > GetGeometryCollection ( ) ;
OutCollectionPtr - > CopyTo ( & OutCollection ) ;
}
# endif //WITH_EDITORONLY_DATA
}
2024-03-14 20:44:48 -04:00
# undef LOCTEXT_NAMESPACE