2018-12-17 06:31:16 -05:00
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
2017-06-30 12:21:06 -04:00
# include "MeshMergeUtilities.h"
# include "Engine/MapBuildDataRegistry.h"
# include "Engine/MeshMerging.h"
# include "MaterialOptions.h"
# include "IMaterialBakingModule.h"
# include "Misc/PackageName.h"
# include "MaterialUtilities.h"
# include "Components/SkeletalMeshComponent.h"
# include "Components/SplineMeshComponent.h"
# include "Components/SkinnedMeshComponent.h"
# include "Components/ShapeComponent.h"
# include "SkeletalMeshTypes.h"
# include "SkeletalRenderPublic.h"
# include "UObject/UObjectBaseUtility.h"
# include "UObject/Package.h"
# include "Materials/Material.h"
# include "Misc/ScopedSlowTask.h"
# include "Modules/ModuleManager.h"
# include "HierarchicalLODUtilitiesModule.h"
# include "MeshMergeData.h"
# include "IHierarchicalLODUtilities.h"
# include "Engine/MeshMergeCullingVolume.h"
# include "Landscape.h"
# include "LandscapeProxy.h"
# include "Editor.h"
# include "ProxyGenerationProcessor.h"
# include "Editor/EditorPerProjectUserSettings.h"
# include "ProxyMaterialUtilities.h"
# include "Engine/StaticMesh.h"
# include "PhysicsEngine/ConvexElem.h"
# include "PhysicsEngine/BodySetup.h"
# include "MeshUtilities.h"
# include "ImageUtils.h"
# include "LandscapeHeightfieldCollisionComponent.h"
# include "IMeshReductionManagerModule.h"
2018-02-14 14:13:42 -05:00
# include "IMeshReductionInterfaces.h"
2017-06-30 12:21:06 -04:00
# include "ProxyGenerationProcessor.h"
# include "IMaterialBakingAdapter.h"
# include "StaticMeshComponentAdapter.h"
# include "SkeletalMeshAdapter.h"
# include "StaticMeshAdapter.h"
# include "MeshMergeEditorExtensions.h"
# include "MeshMergeDataTracker.h"
# include "Misc/FileHelper.h"
# include "MeshMergeHelpers.h"
# include "Settings/EditorExperimentalSettings.h"
# include "MaterialBakingStructures.h"
# include "Async/ParallelFor.h"
2018-03-06 13:26:20 -05:00
# include "ScopedTransaction.h"
# include "Components/InstancedStaticMeshComponent.h"
# include "Engine/LODActor.h"
# include "HierarchicalLODVolume.h"
# include "Engine/Selection.h"
# include "MaterialBakingHelpers.h"
# include "IMeshMergeExtension.h"
2019-01-07 05:38:46 -05:00
# include "RawMesh.h"
2019-10-01 20:41:42 -04:00
# include "StaticMeshAttributes.h"
2019-01-07 05:38:46 -05:00
# include "MeshDescriptionOperations.h"
2018-03-06 13:26:20 -05:00
# if WITH_EDITOR
# include "Widgets/Notifications/SNotificationList.h"
# include "Framework/Notifications/NotificationManager.h"
# endif // WITH_EDITOR
2017-06-30 12:21:06 -04:00
# define LOCTEXT_NAMESPACE "MeshMergeUtils"
DEFINE_LOG_CATEGORY ( LogMeshMerging ) ;
FMeshMergeUtilities : : FMeshMergeUtilities ( )
{
2018-05-23 21:04:31 -04:00
Processor = new FProxyGenerationProcessor ( this ) ;
2017-06-30 12:21:06 -04:00
2018-02-14 14:13:42 -05:00
// Add callback for registering editor extensions with Skeletal/Static mesh editor
ModuleLoadedDelegateHandle = FModuleManager : : Get ( ) . OnModulesChanged ( ) . AddStatic ( & FMeshMergeEditorExtensions : : OnModulesChanged ) ;
2017-06-30 12:21:06 -04:00
}
FMeshMergeUtilities : : ~ FMeshMergeUtilities ( )
{
FModuleManager : : Get ( ) . OnModulesChanged ( ) . Remove ( ModuleLoadedDelegateHandle ) ;
FMeshMergeEditorExtensions : : RemoveExtenders ( ) ;
}
void FMeshMergeUtilities : : BakeMaterialsForComponent ( TArray < TWeakObjectPtr < UObject > > & OptionObjects , IMaterialBakingAdapter * Adapter ) const
{
// Try and find material (merge) options from provided set of objects
TWeakObjectPtr < UObject > * MaterialOptionsObject = OptionObjects . FindByPredicate ( [ ] ( TWeakObjectPtr < UObject > Object )
{
return Cast < UMaterialOptions > ( Object . Get ( ) ) ! = nullptr ;
} ) ;
TWeakObjectPtr < UObject > * MaterialMergeOptionsObject = OptionObjects . FindByPredicate ( [ ] ( TWeakObjectPtr < UObject > Object )
{
return Cast < UMaterialMergeOptions > ( Object . Get ( ) ) ! = nullptr ;
} ) ;
UMaterialOptions * MaterialOptions = MaterialOptionsObject ? Cast < UMaterialOptions > ( MaterialOptionsObject - > Get ( ) ) : nullptr ;
checkf ( MaterialOptions , TEXT ( " No valid material options found " ) ) ;
UMaterialMergeOptions * MaterialMergeOptions = MaterialMergeOptionsObject ? Cast < UMaterialMergeOptions > ( MaterialMergeOptionsObject - > Get ( ) ) : nullptr ;
// Mesh / LOD index
2019-01-07 05:38:46 -05:00
TMap < uint32 , FMeshDescription > RawMeshLODs ;
2017-06-30 12:21:06 -04:00
// LOD index, <original section index, unique section index>
TMultiMap < uint32 , TPair < uint32 , uint32 > > UniqueSectionIndexPerLOD ;
// Unique set of sections in mesh
TArray < FSectionInfo > UniqueSections ;
TArray < FSectionInfo > Sections ;
int32 NumLODs = Adapter - > GetNumberOfLODs ( ) ;
// Retrieve raw mesh data and unique sections
for ( int32 LODIndex = 0 ; LODIndex < NumLODs ; + + LODIndex )
{
// Reset section for reuse
Sections . SetNum ( 0 , false ) ;
// Extract raw mesh data
const bool bProcessedLOD = MaterialOptions - > LODIndices . Contains ( LODIndex ) ;
if ( bProcessedLOD )
{
2019-01-07 05:38:46 -05:00
FMeshDescription & RawMesh = RawMeshLODs . Add ( LODIndex ) ;
2019-10-01 20:41:42 -04:00
FStaticMeshAttributes ( RawMesh ) . Register ( ) ;
2017-06-30 12:21:06 -04:00
Adapter - > RetrieveRawMeshData ( LODIndex , RawMesh , MaterialOptions - > bUseMeshData ) ;
}
// Extract sections for given LOD index from the mesh
Adapter - > RetrieveMeshSections ( LODIndex , Sections ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < Sections . Num ( ) ; + + SectionIndex )
{
FSectionInfo & Section = Sections [ SectionIndex ] ;
Section . bProcessed = bProcessedLOD ;
const int32 UniqueIndex = UniqueSections . AddUnique ( Section ) ;
UniqueSectionIndexPerLOD . Add ( LODIndex , TPair < uint32 , uint32 > ( SectionIndex , UniqueIndex ) ) ;
}
}
TArray < UMaterialInterface * > UniqueMaterials ;
TMap < UMaterialInterface * , int32 > MaterialIndices ;
TMultiMap < uint32 , uint32 > SectionToMaterialMap ;
// Populate list of unique materials and store section mappings
for ( int32 SectionIndex = 0 ; SectionIndex < UniqueSections . Num ( ) ; + + SectionIndex )
{
FSectionInfo & Section = UniqueSections [ SectionIndex ] ;
const int32 UniqueIndex = UniqueMaterials . AddUnique ( Section . Material ) ;
SectionToMaterialMap . Add ( UniqueIndex , SectionIndex ) ;
}
2017-09-11 10:43:35 -04:00
TArray < bool > bMaterialUsesVertexData ;
DetermineMaterialVertexDataUsage ( bMaterialUsesVertexData , UniqueMaterials , MaterialOptions ) ;
2017-06-30 12:21:06 -04:00
TArray < FMeshData > GlobalMeshSettings ;
TArray < FMaterialData > GlobalMaterialSettings ;
TMultiMap < uint32 , TPair < uint32 , uint32 > > OutputMaterialsMap ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < UniqueMaterials . Num ( ) ; + + MaterialIndex )
{
UMaterialInterface * Material = UniqueMaterials [ MaterialIndex ] ;
2017-09-11 10:43:35 -04:00
const bool bDoesMaterialUseVertexData = bMaterialUsesVertexData [ MaterialIndex ] ;
2017-06-30 12:21:06 -04:00
// Retrieve all sections using this material
TArray < uint32 > SectionIndices ;
SectionToMaterialMap . MultiFind ( MaterialIndex , SectionIndices ) ;
if ( MaterialOptions - > bUseMeshData )
{
for ( const int32 LODIndex : MaterialOptions - > LODIndices )
{
TArray < TPair < uint32 , uint32 > > IndexPairs ;
UniqueSectionIndexPerLOD . MultiFind ( LODIndex , IndexPairs ) ;
FMeshData MeshSettings ;
2019-01-07 05:38:46 -05:00
MeshSettings . RawMeshDescription = nullptr ;
2017-06-30 12:21:06 -04:00
// Add material indices used for rendering out material
for ( const TPair < uint32 , uint32 > & Pair : IndexPairs )
{
if ( SectionIndices . Contains ( Pair . Value ) )
{
MeshSettings . MaterialIndices . Add ( Pair . Key ) ;
}
}
if ( MeshSettings . MaterialIndices . Num ( ) )
{
// Retrieve raw mesh
2019-01-07 05:38:46 -05:00
MeshSettings . RawMeshDescription = RawMeshLODs . Find ( LODIndex ) ;
//Should not be using mesh data if there is no mesh
check ( MeshSettings . RawMeshDescription ) ;
2017-06-30 12:21:06 -04:00
MeshSettings . TextureCoordinateBox = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
2019-01-07 05:38:46 -05:00
const bool bUseVertexColor = FMeshDescriptionOperations : : HasVertexColor ( * ( MeshSettings . RawMeshDescription ) ) ;
2017-09-11 10:43:35 -04:00
if ( MaterialOptions - > bUseSpecificUVIndex )
{
MeshSettings . TextureCoordinateIndex = MaterialOptions - > TextureCoordinateIndex ;
}
// if you use vertex color, we can't rely on overlapping UV channel, so use light map UV to unwrap UVs
else if ( bUseVertexColor )
{
MeshSettings . TextureCoordinateIndex = Adapter - > LightmapUVIndex ( ) ;
}
else
{
MeshSettings . TextureCoordinateIndex = 0 ;
}
2017-06-30 12:21:06 -04:00
Adapter - > ApplySettings ( LODIndex , MeshSettings ) ;
// In case part of the UVs is not within the 0-1 range try to use the lightmap UVs
2019-01-07 05:38:46 -05:00
const bool bNeedsUniqueUVs = FMeshMergeHelpers : : CheckWrappingUVs ( * ( MeshSettings . RawMeshDescription ) , MeshSettings . TextureCoordinateIndex ) ;
2017-06-30 12:21:06 -04:00
const int32 LightMapUVIndex = Adapter - > LightmapUVIndex ( ) ;
2019-01-07 05:38:46 -05:00
TVertexInstanceAttributesConstRef < FVector2D > VertexInstanceUVs = MeshSettings . RawMeshDescription - > VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
if ( bNeedsUniqueUVs & & MeshSettings . TextureCoordinateIndex ! = LightMapUVIndex & & VertexInstanceUVs . GetNumElements ( ) > 0 & & VertexInstanceUVs . GetNumIndices ( ) > LightMapUVIndex )
2017-06-30 12:21:06 -04:00
{
MeshSettings . TextureCoordinateIndex = LightMapUVIndex ;
}
FMaterialData MaterialSettings ;
MaterialSettings . Material = Material ;
// Add all user defined properties for baking out
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( ! Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
2018-03-27 16:13:55 -04:00
int32 NumTextureCoordinates ;
bool bUsesVertexData ;
Material - > AnalyzeMaterialProperty ( Entry . Property , NumTextureCoordinates , bUsesVertexData ) ;
2017-06-30 12:21:06 -04:00
MaterialSettings . PropertySizes . Add ( Entry . Property , Entry . bUseCustomSize ? Entry . CustomSize : MaterialOptions - > TextureSize ) ;
}
}
// For each original material index add an entry to the corresponding LOD and bake output index
for ( int32 Index : MeshSettings . MaterialIndices )
{
OutputMaterialsMap . Add ( LODIndex , TPair < uint32 , uint32 > ( Index , GlobalMeshSettings . Num ( ) ) ) ;
}
GlobalMeshSettings . Add ( MeshSettings ) ;
GlobalMaterialSettings . Add ( MaterialSettings ) ;
}
}
}
else
{
// If we are not using the mesh data we aren't doing anything special, just bake out uv range
FMeshData MeshSettings ;
for ( int32 LODIndex : MaterialOptions - > LODIndices )
{
TArray < TPair < uint32 , uint32 > > IndexPairs ;
UniqueSectionIndexPerLOD . MultiFind ( LODIndex , IndexPairs ) ;
for ( const TPair < uint32 , uint32 > & Pair : IndexPairs )
{
if ( SectionIndices . Contains ( Pair . Value ) )
{
MeshSettings . MaterialIndices . Add ( Pair . Key ) ;
}
}
}
if ( MeshSettings . MaterialIndices . Num ( ) )
{
2019-01-07 05:38:46 -05:00
MeshSettings . RawMeshDescription = nullptr ;
2017-06-30 12:21:06 -04:00
MeshSettings . TextureCoordinateBox = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
MeshSettings . TextureCoordinateIndex = 0 ;
FMaterialData MaterialSettings ;
MaterialSettings . Material = Material ;
// Add all user defined properties for baking out
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( ! Entry . bUseConstantValue & & Material - > IsPropertyActive ( Entry . Property ) & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
MaterialSettings . PropertySizes . Add ( Entry . Property , Entry . bUseCustomSize ? Entry . CustomSize : MaterialOptions - > TextureSize ) ;
}
}
for ( int32 LODIndex : MaterialOptions - > LODIndices )
{
TArray < TPair < uint32 , uint32 > > IndexPairs ;
UniqueSectionIndexPerLOD . MultiFind ( LODIndex , IndexPairs ) ;
for ( const TPair < uint32 , uint32 > & Pair : IndexPairs )
{
if ( SectionIndices . Contains ( Pair . Value ) )
{
/// For each original material index add an entry to the corresponding LOD and bake output index
OutputMaterialsMap . Add ( LODIndex , TPair < uint32 , uint32 > ( Pair . Key , GlobalMeshSettings . Num ( ) ) ) ;
}
}
}
GlobalMeshSettings . Add ( MeshSettings ) ;
GlobalMaterialSettings . Add ( MaterialSettings ) ;
}
}
}
TArray < FMeshData * > MeshSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMeshSettings . Num ( ) ; + + SettingsIndex )
{
MeshSettingPtrs . Add ( & GlobalMeshSettings [ SettingsIndex ] ) ;
}
TArray < FMaterialData * > MaterialSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMaterialSettings . Num ( ) ; + + SettingsIndex )
{
MaterialSettingPtrs . Add ( & GlobalMaterialSettings [ SettingsIndex ] ) ;
}
TArray < FBakeOutput > BakeOutputs ;
IMaterialBakingModule & Module = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
Module . BakeMaterials ( MaterialSettingPtrs , MeshSettingPtrs , BakeOutputs ) ;
// Append constant properties which did not require baking out
TArray < FColor > ConstantData ;
FIntPoint ConstantSize ( 1 , 1 ) ;
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
ConstantData . SetNum ( 1 , false ) ;
ConstantData [ 0 ] = FColor ( Entry . ConstantValue * 255.0f , Entry . ConstantValue * 255.0f , Entry . ConstantValue * 255.0f ) ;
for ( FBakeOutput & Ouput : BakeOutputs )
{
Ouput . PropertyData . Add ( Entry . Property , ConstantData ) ;
Ouput . PropertySizes . Add ( Entry . Property , ConstantSize ) ;
}
}
}
TArray < UMaterialInterface * > NewMaterials ;
FString PackageName = Adapter - > GetBaseName ( ) ;
const FGuid NameGuid = FGuid : : NewGuid ( ) ;
for ( int32 OutputIndex = 0 ; OutputIndex < BakeOutputs . Num ( ) ; + + OutputIndex )
{
// Create merged material asset
FString MaterialAssetName = TEXT ( " M_ " ) + FPackageName : : GetShortName ( PackageName ) + TEXT ( " _ " ) + MaterialSettingPtrs [ OutputIndex ] - > Material - > GetName ( ) + TEXT ( " _ " ) + NameGuid . ToString ( ) ;
FString MaterialPackageName = FPackageName : : GetLongPackagePath ( PackageName ) + TEXT ( " / " ) + MaterialAssetName ;
FBakeOutput & Output = BakeOutputs [ OutputIndex ] ;
// Optimize output
for ( auto DataPair : Output . PropertyData )
{
FMaterialUtilities : : OptimizeSampleArray ( DataPair . Value , Output . PropertySizes [ DataPair . Key ] ) ;
}
UMaterialInterface * Material = nullptr ;
if ( Adapter - > GetOuter ( ) )
{
Material = FMaterialUtilities : : CreateProxyMaterialAndTextures ( Adapter - > GetOuter ( ) , MaterialAssetName , Output , * MeshSettingPtrs [ OutputIndex ] , * MaterialSettingPtrs [ OutputIndex ] , MaterialOptions ) ;
}
else
{
Material = FMaterialUtilities : : CreateProxyMaterialAndTextures ( MaterialPackageName , MaterialAssetName , Output , * MeshSettingPtrs [ OutputIndex ] , * MaterialSettingPtrs [ OutputIndex ] , MaterialOptions ) ;
}
NewMaterials . Add ( Material ) ;
}
// Retrieve material indices which were not baked out and should still be part of the final asset
TArray < int32 > NonReplaceMaterialIndices ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < NewMaterials . Num ( ) ; + + MaterialIndex )
{
TArray < uint32 > SectionIndices ;
SectionToMaterialMap . MultiFind ( MaterialIndex , SectionIndices ) ;
for ( int32 LODIndex = 0 ; LODIndex < NumLODs ; + + LODIndex )
{
const bool bProcessedLOD = MaterialOptions - > LODIndices . Contains ( LODIndex ) ;
if ( ! bProcessedLOD )
{
TArray < TPair < uint32 , uint32 > > IndexPairs ;
UniqueSectionIndexPerLOD . MultiFind ( LODIndex , IndexPairs ) ;
for ( TPair < uint32 , uint32 > & Pair : IndexPairs )
{
NonReplaceMaterialIndices . AddUnique ( Adapter - > GetMaterialIndex ( LODIndex , Pair . Key ) ) ;
}
}
}
}
// Remap all baked out materials to their new material indices
TMap < uint32 , uint32 > NewMaterialRemap ;
for ( int32 LODIndex : MaterialOptions - > LODIndices )
{
TArray < TPair < uint32 , uint32 > > IndexPairs ;
OutputMaterialsMap . MultiFind ( LODIndex , IndexPairs ) ;
// Key == original section index, Value == unique material index
for ( auto Pair : IndexPairs )
{
int32 SetIndex = Adapter - > GetMaterialIndex ( LODIndex , Pair . Key ) ;
if ( ! NonReplaceMaterialIndices . Contains ( SetIndex ) )
{
Adapter - > SetMaterial ( SetIndex , NewMaterials [ Pair . Value ] ) ;
}
else
{
const FSectionInfo & SectionInfo = UniqueSections [ Pair . Key ] ;
// Check if this material was processed and a new entry already exists
if ( uint32 * ExistingIndex = NewMaterialRemap . Find ( Pair . Value ) )
{
Adapter - > RemapMaterialIndex ( LODIndex , Pair . Key , * ExistingIndex ) ;
}
else
{
// Add new material
const int32 NewMaterialIndex = Adapter - > AddMaterial ( NewMaterials [ Pair . Value ] ) ;
NewMaterialRemap . Add ( Pair . Value , NewMaterialIndex ) ;
Adapter - > RemapMaterialIndex ( LODIndex , Pair . Key , NewMaterialIndex ) ;
}
}
}
}
2017-09-11 10:43:35 -04:00
Adapter - > UpdateUVChannelData ( ) ;
2019-01-07 05:38:46 -05:00
GlobalMeshSettings . Empty ( ) ;
2017-06-30 12:21:06 -04:00
}
void FMeshMergeUtilities : : BakeMaterialsForComponent ( USkeletalMeshComponent * SkeletalMeshComponent ) const
{
// Retrieve settings object
UMaterialOptions * MaterialOptions = DuplicateObject ( GetMutableDefault < UMaterialOptions > ( ) , GetTransientPackage ( ) ) ;
UAssetBakeOptions * AssetOptions = GetMutableDefault < UAssetBakeOptions > ( ) ;
UMaterialMergeOptions * MergeOptions = GetMutableDefault < UMaterialMergeOptions > ( ) ;
TArray < TWeakObjectPtr < UObject > > Objects { MergeOptions , AssetOptions , MaterialOptions } ;
2018-03-06 13:26:20 -05:00
const int32 NumLODs = SkeletalMeshComponent - > SkeletalMesh - > GetLODNum ( ) ;
2017-06-30 12:21:06 -04:00
IMaterialBakingModule & Module = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
if ( ! Module . SetupMaterialBakeSettings ( Objects , NumLODs ) )
{
return ;
}
// Bake out materials for skeletal mesh
FSkeletalMeshComponentAdapter Adapter ( SkeletalMeshComponent ) ;
BakeMaterialsForComponent ( Objects , & Adapter ) ;
SkeletalMeshComponent - > MarkRenderStateDirty ( ) ;
}
void FMeshMergeUtilities : : BakeMaterialsForComponent ( UStaticMeshComponent * StaticMeshComponent ) const
{
// Retrieve settings object
UMaterialOptions * MaterialOptions = DuplicateObject ( GetMutableDefault < UMaterialOptions > ( ) , GetTransientPackage ( ) ) ;
UAssetBakeOptions * AssetOptions = GetMutableDefault < UAssetBakeOptions > ( ) ;
UMaterialMergeOptions * MergeOptions = GetMutableDefault < UMaterialMergeOptions > ( ) ;
TArray < TWeakObjectPtr < UObject > > Objects { MergeOptions , AssetOptions , MaterialOptions } ;
const int32 NumLODs = StaticMeshComponent - > GetStaticMesh ( ) - > GetNumLODs ( ) ;
IMaterialBakingModule & Module = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
if ( ! Module . SetupMaterialBakeSettings ( Objects , NumLODs ) )
{
return ;
}
// Bake out materials for static mesh component
FStaticMeshComponentAdapter Adapter ( StaticMeshComponent ) ;
BakeMaterialsForComponent ( Objects , & Adapter ) ;
StaticMeshComponent - > MarkRenderStateDirty ( ) ;
}
void FMeshMergeUtilities : : BakeMaterialsForMesh ( UStaticMesh * StaticMesh ) const
{
// Retrieve settings object
UMaterialOptions * MaterialOptions = DuplicateObject ( GetMutableDefault < UMaterialOptions > ( ) , GetTransientPackage ( ) ) ;
UAssetBakeOptions * AssetOptions = GetMutableDefault < UAssetBakeOptions > ( ) ;
UMaterialMergeOptions * MergeOptions = GetMutableDefault < UMaterialMergeOptions > ( ) ;
TArray < TWeakObjectPtr < UObject > > Objects { MergeOptions , AssetOptions , MaterialOptions } ;
const int32 NumLODs = StaticMesh - > GetNumLODs ( ) ;
IMaterialBakingModule & Module = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
if ( ! Module . SetupMaterialBakeSettings ( Objects , NumLODs ) )
{
return ;
}
// Bake out materials for static mesh asset
FStaticMeshAdapter Adapter ( StaticMesh ) ;
BakeMaterialsForComponent ( Objects , & Adapter ) ;
}
void FMeshMergeUtilities : : DetermineMaterialVertexDataUsage ( TArray < bool > & InOutMaterialUsesVertexData , const TArray < UMaterialInterface * > & UniqueMaterials , const UMaterialOptions * MaterialOptions ) const
{
2017-09-11 10:43:35 -04:00
InOutMaterialUsesVertexData . SetNum ( UniqueMaterials . Num ( ) ) ;
2017-06-30 12:21:06 -04:00
for ( int32 MaterialIndex = 0 ; MaterialIndex < UniqueMaterials . Num ( ) ; + + MaterialIndex )
{
UMaterialInterface * Material = UniqueMaterials [ MaterialIndex ] ;
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
// Don't have to check a property if the result is going to be constant anyway
2017-09-11 10:43:35 -04:00
if ( ! Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
int32 NumTextureCoordinates ;
bool bUsesVertexData ;
Material - > AnalyzeMaterialProperty ( Entry . Property , NumTextureCoordinates , bUsesVertexData ) ;
if ( bUsesVertexData | | NumTextureCoordinates > 1 )
{
InOutMaterialUsesVertexData [ MaterialIndex ] = true ;
break ;
}
}
}
}
}
void FMeshMergeUtilities : : ConvertOutputToFlatMaterials ( const TArray < FBakeOutput > & BakeOutputs , const TArray < FMaterialData > & MaterialData , TArray < FFlattenMaterial > & FlattenedMaterials ) const
{
for ( int32 OutputIndex = 0 ; OutputIndex < BakeOutputs . Num ( ) ; + + OutputIndex )
{
const FBakeOutput & Output = BakeOutputs [ OutputIndex ] ;
const FMaterialData & MaterialInfo = MaterialData [ OutputIndex ] ;
FFlattenMaterial Material ;
for ( TPair < EMaterialProperty , FIntPoint > SizePair : Output . PropertySizes )
{
EFlattenMaterialProperties OldProperty = NewToOldProperty ( SizePair . Key ) ;
Material . SetPropertySize ( OldProperty , SizePair . Value ) ;
Material . GetPropertySamples ( OldProperty ) . Append ( Output . PropertyData [ SizePair . Key ] ) ;
}
Material . bDitheredLODTransition = MaterialInfo . Material - > IsDitheredLODTransition ( ) ;
Material . BlendMode = BLEND_Opaque ;
Material . bTwoSided = MaterialInfo . Material - > IsTwoSided ( ) ;
Material . EmissiveScale = Output . EmissiveScale ;
FlattenedMaterials . Add ( Material ) ;
}
}
EFlattenMaterialProperties FMeshMergeUtilities : : NewToOldProperty ( int32 NewProperty ) const
{
const EFlattenMaterialProperties Remap [ MP_Refraction ] =
{
EFlattenMaterialProperties : : Emissive ,
EFlattenMaterialProperties : : Opacity ,
EFlattenMaterialProperties : : OpacityMask ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : Diffuse ,
EFlattenMaterialProperties : : Metallic ,
EFlattenMaterialProperties : : Specular ,
EFlattenMaterialProperties : : Roughness ,
EFlattenMaterialProperties : : Normal ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : NumFlattenMaterialProperties ,
EFlattenMaterialProperties : : AmbientOcclusion
} ;
return Remap [ NewProperty ] ;
}
UMaterialOptions * FMeshMergeUtilities : : PopulateMaterialOptions ( const FMaterialProxySettings & MaterialSettings ) const
{
UMaterialOptions * MaterialOptions = DuplicateObject ( GetMutableDefault < UMaterialOptions > ( ) , GetTransientPackage ( ) ) ;
MaterialOptions - > Properties . Empty ( ) ;
MaterialOptions - > TextureSize = MaterialSettings . TextureSize ;
const bool bCustomSizes = MaterialSettings . TextureSizingType = = TextureSizingType_UseManualOverrideTextureSize ;
FPropertyEntry Property ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_BaseColor , Property ) ;
2017-06-30 12:21:06 -04:00
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_Specular , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bSpecularMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_Roughness , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bRoughnessMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_Metallic , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bMetallicMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_Normal , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bNormalMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_Opacity , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bOpacityMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_OpacityMask , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bOpacityMaskMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_EmissiveColor , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bEmissiveMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
PopulatePropertyEntry ( MaterialSettings , MP_AmbientOcclusion , Property ) ;
2017-06-30 12:21:06 -04:00
if ( MaterialSettings . bAmbientOcclusionMap )
MaterialOptions - > Properties . Add ( Property ) ;
2017-09-11 10:43:35 -04:00
2017-06-30 12:21:06 -04:00
return MaterialOptions ;
}
2017-09-11 10:43:35 -04:00
void FMeshMergeUtilities : : PopulatePropertyEntry ( const FMaterialProxySettings & MaterialSettings , EMaterialProperty MaterialProperty , FPropertyEntry & InOutPropertyEntry ) const
{
InOutPropertyEntry . Property = MaterialProperty ;
switch ( MaterialSettings . TextureSizingType )
{
/** Set property output size to unique per-property user set sizes */
case TextureSizingType_UseManualOverrideTextureSize :
{
InOutPropertyEntry . bUseCustomSize = true ;
InOutPropertyEntry . CustomSize = [ MaterialSettings , MaterialProperty ] ( ) - > FIntPoint
{
switch ( MaterialProperty )
{
case MP_BaseColor : return MaterialSettings . DiffuseTextureSize ;
case MP_Specular : return MaterialSettings . SpecularTextureSize ;
case MP_Roughness : return MaterialSettings . RoughnessTextureSize ;
case MP_Metallic : return MaterialSettings . MetallicTextureSize ;
case MP_Normal : return MaterialSettings . NormalTextureSize ;
case MP_Opacity : return MaterialSettings . OpacityTextureSize ;
case MP_OpacityMask : return MaterialSettings . OpacityMaskTextureSize ;
case MP_EmissiveColor : return MaterialSettings . EmissiveTextureSize ;
case MP_AmbientOcclusion : return MaterialSettings . AmbientOcclusionTextureSize ;
default :
{
checkf ( false , TEXT ( " Invalid Material Property " ) ) ;
return FIntPoint ( ) ;
}
}
} ( ) ;
break ;
}
/** Set property output size to biased values off the TextureSize value (Normal at fullres, Diffuse at halfres, and anything else at quarter res */
case TextureSizingType_UseAutomaticBiasedSizes :
{
const FIntPoint FullRes = MaterialSettings . TextureSize ;
const FIntPoint HalfRes = FIntPoint ( FMath : : Max ( 8 , FullRes . X > > 1 ) , FMath : : Max ( 8 , FullRes . Y > > 1 ) ) ;
const FIntPoint QuarterRes = FIntPoint ( FMath : : Max ( 4 , FullRes . X > > 2 ) , FMath : : Max ( 4 , FullRes . Y > > 2 ) ) ;
InOutPropertyEntry . bUseCustomSize = true ;
InOutPropertyEntry . CustomSize = [ FullRes , HalfRes , QuarterRes , MaterialSettings , MaterialProperty ] ( ) - > FIntPoint
{
switch ( MaterialProperty )
{
case MP_Normal : return FullRes ;
case MP_BaseColor : return HalfRes ;
case MP_Specular : return QuarterRes ;
case MP_Roughness : return QuarterRes ;
case MP_Metallic : return QuarterRes ;
case MP_Opacity : return QuarterRes ;
case MP_OpacityMask : return QuarterRes ;
case MP_EmissiveColor : return QuarterRes ;
case MP_AmbientOcclusion : return QuarterRes ;
default :
{
checkf ( false , TEXT ( " Invalid Material Property " ) ) ;
return FIntPoint ( ) ;
}
}
} ( ) ;
break ;
}
/** Set all sizes to TextureSize */
case TextureSizingType_UseSingleTextureSize :
case TextureSizingType_UseSimplygonAutomaticSizing :
{
InOutPropertyEntry . bUseCustomSize = false ;
InOutPropertyEntry . CustomSize = MaterialSettings . TextureSize ;
break ;
}
}
/** Check whether or not a constant value should be used for this property */
InOutPropertyEntry . bUseConstantValue = [ MaterialSettings , MaterialProperty ] ( ) - > bool
{
switch ( MaterialProperty )
{
case MP_BaseColor : return false ;
case MP_Normal : return ! MaterialSettings . bNormalMap ;
case MP_Specular : return ! MaterialSettings . bSpecularMap ;
case MP_Roughness : return ! MaterialSettings . bRoughnessMap ;
case MP_Metallic : return ! MaterialSettings . bMetallicMap ;
case MP_Opacity : return ! MaterialSettings . bOpacityMap ;
case MP_OpacityMask : return ! MaterialSettings . bOpacityMaskMap ;
case MP_EmissiveColor : return ! MaterialSettings . bEmissiveMap ;
case MP_AmbientOcclusion : return ! MaterialSettings . bAmbientOcclusionMap ;
default :
{
checkf ( false , TEXT ( " Invalid Material Property " ) ) ;
return false ;
}
}
} ( ) ;
/** Set the value if a constant value should be used for this property */
InOutPropertyEntry . ConstantValue = [ MaterialSettings , MaterialProperty ] ( ) - > float
{
switch ( MaterialProperty )
{
case MP_BaseColor : return 1.0f ;
case MP_Normal : return 1.0f ;
case MP_Specular : return MaterialSettings . SpecularConstant ;
case MP_Roughness : return MaterialSettings . RoughnessConstant ;
case MP_Metallic : return MaterialSettings . MetallicConstant ;
case MP_Opacity : return MaterialSettings . OpacityConstant ;
case MP_OpacityMask : return MaterialSettings . OpacityMaskConstant ;
case MP_EmissiveColor : return 0.0f ;
case MP_AmbientOcclusion : return MaterialSettings . AmbientOcclusionConstant ;
default :
{
checkf ( false , TEXT ( " Invalid Material Property " ) ) ;
return 1.0f ;
}
}
} ( ) ;
}
2018-05-23 21:04:31 -04:00
void FMeshMergeUtilities : : CopyTextureRect ( const FColor * Src , const FIntPoint & SrcSize , FColor * Dst , const FIntPoint & DstSize , const FIntPoint & DstPos , bool bCopyOnlyMaskedPixels ) const
2017-06-30 12:21:06 -04:00
{
const int32 RowLength = SrcSize . X * sizeof ( FColor ) ;
FColor * RowDst = Dst + DstSize . X * DstPos . Y ;
const FColor * RowSrc = Src ;
2018-05-23 21:04:31 -04:00
if ( bCopyOnlyMaskedPixels )
2017-06-30 12:21:06 -04:00
{
2018-05-23 21:04:31 -04:00
for ( int32 RowIdx = 0 ; RowIdx < SrcSize . Y ; + + RowIdx )
{
for ( int32 ColIdx = 0 ; ColIdx < SrcSize . X ; + + ColIdx )
{
if ( RowSrc [ ColIdx ] ! = FColor : : Magenta )
{
RowDst [ DstPos . X + ColIdx ] = RowSrc [ ColIdx ] ;
}
}
RowDst + = DstSize . X ;
RowSrc + = SrcSize . X ;
}
}
else
{
for ( int32 RowIdx = 0 ; RowIdx < SrcSize . Y ; + + RowIdx )
{
FMemory : : Memcpy ( RowDst + DstPos . X , RowSrc , RowLength ) ;
RowDst + = DstSize . X ;
RowSrc + = SrcSize . X ;
}
2017-06-30 12:21:06 -04:00
}
}
void FMeshMergeUtilities : : SetTextureRect ( const FColor & ColorValue , const FIntPoint & SrcSize , FColor * Dst , const FIntPoint & DstSize , const FIntPoint & DstPos ) const
{
FColor * RowDst = Dst + DstSize . X * DstPos . Y ;
for ( int32 RowIdx = 0 ; RowIdx < SrcSize . Y ; + + RowIdx )
{
for ( int32 ColIdx = 0 ; ColIdx < SrcSize . X ; + + ColIdx )
{
RowDst [ DstPos . X + ColIdx ] = ColorValue ;
}
RowDst + = DstSize . X ;
}
}
FIntPoint FMeshMergeUtilities : : ConditionalImageResize ( const FIntPoint & SrcSize , const FIntPoint & DesiredSize , TArray < FColor > & InOutImage , bool bLinearSpace ) const
{
const int32 NumDesiredSamples = DesiredSize . X * DesiredSize . Y ;
if ( InOutImage . Num ( ) & & InOutImage . Num ( ) ! = NumDesiredSamples )
{
check ( InOutImage . Num ( ) = = SrcSize . X * SrcSize . Y ) ;
TArray < FColor > OutImage ;
if ( NumDesiredSamples > 0 )
{
FImageUtils : : ImageResize ( SrcSize . X , SrcSize . Y , InOutImage , DesiredSize . X , DesiredSize . Y , OutImage , bLinearSpace ) ;
}
Exchange ( InOutImage , OutImage ) ;
return DesiredSize ;
}
return SrcSize ;
}
2018-03-06 13:26:20 -05:00
void FMeshMergeUtilities : : MergeFlattenedMaterials ( TArray < struct FFlattenMaterial > & InMaterialList , int32 InGutter , FFlattenMaterial & OutMergedMaterial , TArray < FUVOffsetScalePair > & OutUVTransforms ) const
2017-06-30 12:21:06 -04:00
{
OutUVTransforms . Reserve ( InMaterialList . Num ( ) ) ;
// Fill output UV transforms with invalid values
for ( auto Material : InMaterialList )
{
// Invalid UV transform
FUVOffsetScalePair UVTransform ;
UVTransform . Key = FVector2D : : ZeroVector ;
UVTransform . Value = FVector2D : : ZeroVector ;
OutUVTransforms . Add ( UVTransform ) ;
}
const int32 AtlasGridSize = FMath : : CeilToInt ( FMath : : Sqrt ( InMaterialList . Num ( ) ) ) ;
OutMergedMaterial . EmissiveScale = FlattenEmissivescale ( InMaterialList ) ;
for ( int32 PropertyIndex = 0 ; PropertyIndex < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + PropertyIndex )
{
const EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) PropertyIndex ;
if ( OutMergedMaterial . ShouldGenerateDataForProperty ( Property ) )
{
const FIntPoint AtlasTextureSize = OutMergedMaterial . GetPropertySize ( Property ) ;
const FIntPoint ExportTextureSize = AtlasTextureSize / AtlasGridSize ;
const int32 AtlasNumSamples = AtlasTextureSize . X * AtlasTextureSize . Y ;
check ( OutMergedMaterial . GetPropertySize ( Property ) = = AtlasTextureSize ) ;
TArray < FColor > & Samples = OutMergedMaterial . GetPropertySamples ( Property ) ;
2018-03-06 13:26:20 -05:00
Samples . SetNumUninitialized ( AtlasNumSamples ) ;
// Fill with magenta (as we will be box blurring this later)
for ( FColor & SampleColor : Samples )
{
SampleColor = FColor ( 255 , 0 , 255 ) ;
}
2017-06-30 12:21:06 -04:00
}
}
int32 AtlasRowIdx = 0 ;
int32 AtlasColIdx = 0 ;
2018-03-06 13:26:20 -05:00
FIntPoint Gutter ( InGutter , InGutter ) ;
FIntPoint DoubleGutter ( InGutter * 2 , InGutter * 2 ) ;
FIntPoint GlobalAtlasTargetPos = Gutter ;
2017-06-30 12:21:06 -04:00
bool bSamplesWritten [ ( uint32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ] ;
FMemory : : Memset ( bSamplesWritten , 0 ) ;
// Used to calculate UV transforms
const FIntPoint GlobalAtlasTextureSize = OutMergedMaterial . GetPropertySize ( EFlattenMaterialProperties : : Diffuse ) ;
2018-03-06 13:26:20 -05:00
const FIntPoint GlobalExportTextureSize = ( GlobalAtlasTextureSize / AtlasGridSize ) - DoubleGutter ;
const FIntPoint GlobalExportEntrySize = ( GlobalAtlasTextureSize / AtlasGridSize ) ;
2017-06-30 12:21:06 -04:00
// Flatten all materials and merge them into one material using texture atlases
for ( int32 MatIdx = 0 ; MatIdx < InMaterialList . Num ( ) ; + + MatIdx )
{
FFlattenMaterial & FlatMaterial = InMaterialList [ MatIdx ] ;
OutMergedMaterial . bTwoSided | = FlatMaterial . bTwoSided ;
OutMergedMaterial . bDitheredLODTransition = FlatMaterial . bDitheredLODTransition ;
2018-03-06 13:26:20 -05:00
2017-06-30 12:21:06 -04:00
for ( int32 PropertyIndex = 0 ; PropertyIndex < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + PropertyIndex )
{
const EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) PropertyIndex ;
2018-03-06 13:26:20 -05:00
const FIntPoint PropertyTextureSize = OutMergedMaterial . GetPropertySize ( Property ) ;
2017-06-30 12:21:06 -04:00
const int32 NumPropertySamples = PropertyTextureSize . X * PropertyTextureSize . Y ;
2018-03-06 13:26:20 -05:00
const FIntPoint PropertyAtlasTextureSize = ( PropertyTextureSize / AtlasGridSize ) - DoubleGutter ;
const FIntPoint PropertyAtlasEntrySize = ( PropertyTextureSize / AtlasGridSize ) ;
const FIntPoint AtlasTargetPos ( ( AtlasColIdx * PropertyAtlasEntrySize . X ) + InGutter , ( AtlasRowIdx * PropertyAtlasEntrySize . Y ) + InGutter ) ;
2017-06-30 12:21:06 -04:00
if ( OutMergedMaterial . ShouldGenerateDataForProperty ( Property ) & & FlatMaterial . DoesPropertyContainData ( Property ) )
{
TArray < FColor > & SourceSamples = FlatMaterial . GetPropertySamples ( Property ) ;
TArray < FColor > & TargetSamples = OutMergedMaterial . GetPropertySamples ( Property ) ;
if ( FlatMaterial . IsPropertyConstant ( Property ) )
{
SetTextureRect ( SourceSamples [ 0 ] , PropertyAtlasTextureSize , TargetSamples . GetData ( ) , PropertyTextureSize , AtlasTargetPos ) ;
}
else
{
FIntPoint PropertySize = FlatMaterial . GetPropertySize ( Property ) ;
PropertySize = ConditionalImageResize ( PropertySize , PropertyAtlasTextureSize , SourceSamples , false ) ;
CopyTextureRect ( SourceSamples . GetData ( ) , PropertyAtlasTextureSize , TargetSamples . GetData ( ) , PropertyTextureSize , AtlasTargetPos ) ;
FlatMaterial . SetPropertySize ( Property , PropertySize ) ;
}
bSamplesWritten [ PropertyIndex ] | = true ;
}
}
check ( OutUVTransforms . IsValidIndex ( MatIdx ) ) ;
2018-03-06 13:26:20 -05:00
// Offset
2017-06-30 12:21:06 -04:00
OutUVTransforms [ MatIdx ] . Key = FVector2D (
( float ) GlobalAtlasTargetPos . X / GlobalAtlasTextureSize . X ,
( float ) GlobalAtlasTargetPos . Y / GlobalAtlasTextureSize . Y ) ;
2018-03-06 13:26:20 -05:00
// Scale
2017-06-30 12:21:06 -04:00
OutUVTransforms [ MatIdx ] . Value = FVector2D (
( float ) GlobalExportTextureSize . X / GlobalAtlasTextureSize . X ,
( float ) GlobalExportTextureSize . Y / GlobalAtlasTextureSize . Y ) ;
AtlasColIdx + + ;
if ( AtlasColIdx > = AtlasGridSize )
{
AtlasColIdx = 0 ;
AtlasRowIdx + + ;
}
2018-03-06 13:26:20 -05:00
GlobalAtlasTargetPos = FIntPoint ( ( AtlasColIdx * GlobalExportEntrySize . X ) + InGutter , ( AtlasRowIdx * GlobalExportEntrySize . Y ) + InGutter ) ;
2017-06-30 12:21:06 -04:00
}
// Check if some properties weren't populated with data (which means we can empty them out)
for ( int32 PropertyIndex = 0 ; PropertyIndex < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + PropertyIndex )
{
2018-03-06 13:26:20 -05:00
EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) PropertyIndex ;
2017-06-30 12:21:06 -04:00
if ( ! bSamplesWritten [ PropertyIndex ] )
2018-03-06 13:26:20 -05:00
{
2017-06-30 12:21:06 -04:00
OutMergedMaterial . GetPropertySamples ( Property ) . Empty ( ) ;
OutMergedMaterial . SetPropertySize ( Property , FIntPoint ( 0 , 0 ) ) ;
}
2018-03-06 13:26:20 -05:00
else
{
// Smear borders
const FIntPoint PropertySize = OutMergedMaterial . GetPropertySize ( Property ) ;
2018-05-23 21:04:31 -04:00
FMaterialBakingHelpers : : PerformUVBorderSmear ( OutMergedMaterial . GetPropertySamples ( Property ) , PropertySize . X , PropertySize . Y ) ;
2018-03-06 13:26:20 -05:00
}
2017-06-30 12:21:06 -04:00
}
}
2018-05-23 21:04:31 -04:00
void FMeshMergeUtilities : : FlattenBinnedMaterials ( TArray < struct FFlattenMaterial > & InMaterialList , const TArray < FBox2D > & InMaterialBoxes , int32 InGutter , bool bCopyOnlyMaskedPixels , FFlattenMaterial & OutMergedMaterial , TArray < FUVOffsetScalePair > & OutUVTransforms ) const
2017-06-30 12:21:06 -04:00
{
OutUVTransforms . AddZeroed ( InMaterialList . Num ( ) ) ;
// Flatten emissive scale across all incoming materials
OutMergedMaterial . EmissiveScale = FlattenEmissivescale ( InMaterialList ) ;
// Merge all material properties
for ( int32 Index = 0 ; Index < ( int32 ) EFlattenMaterialProperties : : NumFlattenMaterialProperties ; + + Index )
{
const EFlattenMaterialProperties Property = ( EFlattenMaterialProperties ) Index ;
const FIntPoint & OutTextureSize = OutMergedMaterial . GetPropertySize ( Property ) ;
if ( OutTextureSize ! = FIntPoint : : ZeroValue )
{
TArray < FColor > & OutSamples = OutMergedMaterial . GetPropertySamples ( Property ) ;
OutSamples . Reserve ( OutTextureSize . X * OutTextureSize . Y ) ;
2018-03-06 13:26:20 -05:00
OutSamples . SetNumUninitialized ( OutTextureSize . X * OutTextureSize . Y ) ;
2017-06-30 12:21:06 -04:00
2018-03-06 13:26:20 -05:00
// Fill with magenta (as we will be box blurring this later)
for ( FColor & SampleColor : OutSamples )
{
SampleColor = FColor ( 255 , 0 , 255 ) ;
}
FVector2D Gutter2D ( ( float ) InGutter , ( float ) InGutter ) ;
2017-06-30 12:21:06 -04:00
bool bMaterialsWritten = false ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < InMaterialList . Num ( ) ; + + MaterialIndex )
{
// Determine output size and offset
FFlattenMaterial & FlatMaterial = InMaterialList [ MaterialIndex ] ;
OutMergedMaterial . bDitheredLODTransition | = FlatMaterial . bDitheredLODTransition ;
OutMergedMaterial . bTwoSided | = FlatMaterial . bTwoSided ;
if ( FlatMaterial . DoesPropertyContainData ( Property ) )
{
const FBox2D MaterialBox = InMaterialBoxes [ MaterialIndex ] ;
const FIntPoint & InputSize = FlatMaterial . GetPropertySize ( Property ) ;
TArray < FColor > & InputSamples = FlatMaterial . GetPropertySamples ( Property ) ;
// Resize material to match output (area) size
2018-03-06 13:26:20 -05:00
FIntPoint OutputSize = FIntPoint ( ( OutTextureSize . X * MaterialBox . GetSize ( ) . X ) - ( InGutter * 2 ) , ( OutTextureSize . Y * MaterialBox . GetSize ( ) . Y ) - ( InGutter * 2 ) ) ;
2017-06-30 12:21:06 -04:00
ConditionalImageResize ( InputSize , OutputSize , InputSamples , false ) ;
// Copy material data to the merged 'atlas' texture
2018-03-06 13:26:20 -05:00
FIntPoint OutputPosition = FIntPoint ( ( OutTextureSize . X * MaterialBox . Min . X ) + InGutter , ( OutTextureSize . Y * MaterialBox . Min . Y ) + InGutter ) ;
2018-05-23 21:04:31 -04:00
CopyTextureRect ( InputSamples . GetData ( ) , OutputSize , OutSamples . GetData ( ) , OutTextureSize , OutputPosition , bCopyOnlyMaskedPixels ) ;
2017-06-30 12:21:06 -04:00
// Set the UV tranforms only once
if ( Index = = 0 )
{
FUVOffsetScalePair & UVTransform = OutUVTransforms [ MaterialIndex ] ;
2018-03-06 13:26:20 -05:00
UVTransform . Key = MaterialBox . Min + ( Gutter2D / FVector2D ( OutTextureSize ) ) ;
UVTransform . Value = MaterialBox . GetSize ( ) - ( ( Gutter2D * 2.0f ) / FVector2D ( OutTextureSize ) ) ;
2017-06-30 12:21:06 -04:00
}
bMaterialsWritten = true ;
}
}
if ( ! bMaterialsWritten )
{
OutSamples . Empty ( ) ;
OutMergedMaterial . SetPropertySize ( Property , FIntPoint ( 0 , 0 ) ) ;
}
2018-03-06 13:26:20 -05:00
else
{
// Smear borders
const FIntPoint PropertySize = OutMergedMaterial . GetPropertySize ( Property ) ;
2018-05-23 21:04:31 -04:00
FMaterialBakingHelpers : : PerformUVBorderSmear ( OutSamples , PropertySize . X , PropertySize . Y ) ;
2018-03-06 13:26:20 -05:00
}
2017-06-30 12:21:06 -04:00
}
}
}
float FMeshMergeUtilities : : FlattenEmissivescale ( TArray < struct FFlattenMaterial > & InMaterialList ) const
{
// Find maximum emissive scaling value across materials
float MaxScale = 0.0f ;
for ( const FFlattenMaterial & Material : InMaterialList )
{
MaxScale = FMath : : Max ( MaxScale , Material . EmissiveScale ) ;
}
// Renormalize samples
const float Multiplier = 1.0f / MaxScale ;
const int32 NumThreads = [ & ] ( )
{
return FPlatformProcess : : SupportsMultithreading ( ) ? FPlatformMisc : : NumberOfCores ( ) : 1 ;
} ( ) ;
const int32 MaterialsPerThread = FMath : : CeilToInt ( ( float ) InMaterialList . Num ( ) / ( float ) NumThreads ) ;
ParallelFor ( NumThreads , [ & InMaterialList , MaterialsPerThread , Multiplier , MaxScale ]
( int32 Index )
{
int32 StartIndex = FMath : : CeilToInt ( ( Index ) * MaterialsPerThread ) ;
const int32 EndIndex = FMath : : Min ( FMath : : CeilToInt ( ( Index + 1 ) * MaterialsPerThread ) , InMaterialList . Num ( ) ) ;
for ( ; StartIndex < EndIndex ; + + StartIndex )
{
FFlattenMaterial & Material = InMaterialList [ StartIndex ] ;
if ( Material . EmissiveScale ! = MaxScale )
{
for ( FColor & Sample : Material . GetPropertySamples ( EFlattenMaterialProperties : : Emissive ) )
{
2019-04-26 09:47:57 -04:00
if ( Sample ! = FColor : : Magenta )
{
Sample . R = Sample . R * Multiplier ;
Sample . G = Sample . G * Multiplier ;
Sample . B = Sample . B * Multiplier ;
Sample . A = Sample . A * Multiplier ;
}
2017-06-30 12:21:06 -04:00
}
}
}
} , NumThreads = = 1 ) ;
return MaxScale ;
}
void FMeshMergeUtilities : : CreateProxyMesh ( const TArray < AActor * > & InActors , const struct FMeshProxySettings & InMeshProxySettings , UPackage * InOuter , const FString & InProxyBasePackageName , const FGuid InGuid , const FCreateProxyDelegate & InProxyCreatedDelegate , const bool bAllowAsync , const float ScreenSize ) const
2018-03-06 13:26:20 -05:00
{
UMaterial * BaseMaterial = LoadObject < UMaterial > ( NULL , TEXT ( " /Engine/EngineMaterials/BaseFlattenMaterial.BaseFlattenMaterial " ) , NULL , LOAD_None , NULL ) ;
check ( BaseMaterial ) ;
CreateProxyMesh ( InActors , InMeshProxySettings , BaseMaterial , InOuter , InProxyBasePackageName , InGuid , InProxyCreatedDelegate , bAllowAsync , ScreenSize ) ;
}
void FMeshMergeUtilities : : CreateProxyMesh ( const TArray < UStaticMeshComponent * > & InStaticMeshComps , const struct FMeshProxySettings & InMeshProxySettings , UPackage * InOuter , const FString & InProxyBasePackageName , const FGuid InGuid , const FCreateProxyDelegate & InProxyCreatedDelegate , const bool bAllowAsync , const float ScreenSize ) const
{
UMaterial * BaseMaterial = LoadObject < UMaterial > ( NULL , TEXT ( " /Engine/EngineMaterials/BaseFlattenMaterial.BaseFlattenMaterial " ) , NULL , LOAD_None , NULL ) ;
check ( BaseMaterial ) ;
CreateProxyMesh ( InStaticMeshComps , InMeshProxySettings , BaseMaterial , InOuter , InProxyBasePackageName , InGuid , InProxyCreatedDelegate , bAllowAsync , ScreenSize ) ;
}
void FMeshMergeUtilities : : CreateProxyMesh ( const TArray < AActor * > & InActors , const struct FMeshProxySettings & InMeshProxySettings , UMaterialInterface * InBaseMaterial , UPackage * InOuter , const FString & InProxyBasePackageName , const FGuid InGuid , const FCreateProxyDelegate & InProxyCreatedDelegate , const bool bAllowAsync /*= false*/ , const float ScreenSize /*= 1.0f*/ ) const
2017-06-30 12:21:06 -04:00
{
// No actors given as input
if ( InActors . Num ( ) = = 0 )
{
UE_LOG ( LogMeshMerging , Log , TEXT ( " No actors specified to generate a proxy mesh for " ) ) ;
return ;
}
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
// Collect components to merge
2017-06-30 12:21:06 -04:00
TArray < UStaticMeshComponent * > ComponentsToMerge ;
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
for ( AActor * Actor : InActors )
2017-06-30 12:21:06 -04:00
{
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
TInlineComponentArray < UStaticMeshComponent * > Components ;
Actor - > GetComponents < UStaticMeshComponent > ( Components ) ;
ComponentsToMerge . Append ( Components ) ;
2017-06-30 12:21:06 -04:00
}
2018-03-06 13:26:20 -05:00
CreateProxyMesh ( ComponentsToMerge , InMeshProxySettings , InBaseMaterial , InOuter , InProxyBasePackageName , InGuid , InProxyCreatedDelegate , bAllowAsync , ScreenSize ) ;
2018-02-14 14:13:42 -05:00
}
2018-03-06 13:26:20 -05:00
void FMeshMergeUtilities : : CreateProxyMesh ( const TArray < UStaticMeshComponent * > & InComponentsToMerge , const struct FMeshProxySettings & InMeshProxySettings , UMaterialInterface * InBaseMaterial ,
2018-02-14 14:13:42 -05:00
UPackage * InOuter , const FString & InProxyBasePackageName , const FGuid InGuid , const FCreateProxyDelegate & InProxyCreatedDelegate , const bool bAllowAsync , const float ScreenSize ) const
{
// The MeshReductionInterface manages the choice mesh reduction plugins, Unreal native vs third party (e.g. Simplygon)
IMeshReductionModule & ReductionModule = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshReductionModule > ( " MeshReductionInterface " ) ;
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
2018-02-14 14:13:42 -05:00
// Error/warning checking for input
if ( ReductionModule . GetMeshMergingInterface ( ) = = nullptr )
{
UE_LOG ( LogMeshMerging , Log , TEXT ( " No automatic mesh merging module available " ) ) ;
return ;
}
// Check that the delegate has a func-ptr bound to it
if ( ! InProxyCreatedDelegate . IsBound ( ) )
{
UE_LOG ( LogMeshMerging , Log , TEXT ( " Invalid (unbound) delegate for returning generated proxy mesh " ) ) ;
return ;
}
2018-03-06 13:26:20 -05:00
TArray < UStaticMeshComponent * > ComponentsToMerge = InComponentsToMerge ;
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
2019-09-26 13:09:15 -04:00
// Remove invalid components
ComponentsToMerge . RemoveAll ( [ ] ( UStaticMeshComponent * Val ) { return Val - > GetStaticMesh ( ) = = nullptr ; } ) ;
2018-03-06 13:26:20 -05:00
2018-02-14 14:13:42 -05:00
// No actors given as input
if ( ComponentsToMerge . Num ( ) = = 0 )
{
UE_LOG ( LogMeshMerging , Log , TEXT ( " No static mesh specified to generate a proxy mesh for " ) ) ;
2019-03-07 11:44:50 -05:00
TArray < UObject * > OutAssetsToSync ;
InProxyCreatedDelegate . ExecuteIfBound ( InGuid , OutAssetsToSync ) ;
2018-02-14 14:13:42 -05:00
return ;
}
// Base asset name for a new assets
// In case outer is null ProxyBasePackageName has to be long package name
if ( InOuter = = nullptr & & FPackageName : : IsShortPackageName ( InProxyBasePackageName ) )
{
UE_LOG ( LogMeshMerging , Warning , TEXT ( " Invalid long package name: '%s'. " ) , * InProxyBasePackageName ) ;
return ;
}
FScopedSlowTask SlowTask ( 100.f , ( LOCTEXT ( " CreateProxyMesh_CreateMesh " , " Creating Mesh Proxy " ) ) ) ;
SlowTask . MakeDialog ( ) ;
2017-06-30 12:21:06 -04:00
TArray < FRawMeshExt > SourceMeshes ;
TMap < FMeshIdAndLOD , TArray < int32 > > GlobalMaterialMap ;
static const int32 ProxyMeshTargetLODLevel = 0 ;
FBoxSphereBounds EstimatedBounds ( ForceInitToZero ) ;
for ( const UStaticMeshComponent * StaticMeshComponent : ComponentsToMerge )
{
EstimatedBounds = EstimatedBounds + StaticMeshComponent - > Bounds ;
}
Copying //UE4/Dev-Enterprise to //UE4/Dev-Main (Source: //UE4/Dev-Enterprise @ 4341740)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 4280523 by Patrick.Boutot
Add option in AjaCustomTimeStep to wait until the frame to be ready. Previously, the frame was there but not yet processed so it was possible that it was not ready by the time we wanted to read it. It won't work with interlaced because the 2 fields are processed at the same time. In interlaced, will get a 30fps behaviour when we actually want a 60fps.
Fix bug that didn't set and reset bIsOwned properly when it was first initialized as not owned.
Change 4280526 by Patrick.Boutot
Add accessor to get the leaf media source or output.
Change 4280624 by Patrick.Boutot
Add timecode acessor to media samples
Change 4280626 by Patrick.Boutot
Rework the timing for AJA Media Player. Previously, we took the timing of the frame. That was a bad idea because if 2 incomings video frames were coming a the same time, you would only show one. Making the buffering system useless.
That affects the Custom Time Step since it was waiting for the interrupt signal and in some behavior we would like the frame to be ready to be used by UE. Same the timecode in the MediaSample because we may not used it to stamps the frame.
Change 4283022 by Patrick.Boutot
[EditorScriptingUtilitites] Check folder names invalid characters separatly from the object's name.
#jira UE-59886, UE-62333
Change 4283112 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Rename TimemanagemenetEditor module names.
Change 4283426 by JeanLuc.Corenthin
Fix crash with FBX file
#jira UE-62501
Change 4284940 by Patrick.Boutot
A widget that let you select a single permutation from a list. It groups the values into categories and removes duplicates inside that category.
Change 4285471 by Patrick.Boutot
Remove MediaFrameworkUtilititesModule dependency to the Settings module at runtime.
Change 4286925 by Patrick.Boutot
[AJA] Add support to read LTC from the reference In.
Add more detail on video format and the device.
MediaSource use the Permutations Selection widget to select his mode and device.
Remove debugging option to trigger an AJA custom time step and timecode provider.
Remove the UYVY pixel option from AJA. It's better do to the conversion on the AJA card that on the GPU.
Change the tooltip and category for some AjaMediaSource properties.
Change 4287026 by Julien.StJean
Modifed the file STimeCodeProviderTab.cpp to fix the position of a SComboButton that wasn't properly place.
Change 4287663 by Jon.Nabozny
Add timecode messages into nDisplay, and sync those between Master and Slave
Change 4287884 by Jon.Nabozny
Create a TimecodeProvider for SystemTime and introduce a notion for DefaultTimecodeProvider in Engine.
Change 4288050 by Jon.Nabozny
Rework the TimeSynchronization implementation for usability and functionality.
Change 4288283 by Jon.Nabozny
Fixed swapped MetaClass and DisplayName options on UEngine::DefaultTimecodeProviderClassName;
Change 4288352 by Jon.Nabozny
Set TimecodeProviderClassName and DefaultTimecodeProviderClassName in BaseEngine.ini
Change 4288378 by Jon.Nabozny
Fixup some issues in TimecodeSynchronizer where code was reset improperly due to multiple unshelves / resolves.
Change 4288394 by Jon.Nabozny
Add TimeSync functionality into LiveLink. Also add test cases for this. This should allow us to easily synchronize multiple LiveLink sources together, as well as synchronize those to anything else using the sync system (Relies on CL-4235417)
Change 4288899 by Patrick.Boutot
Fix initialization order of FMediaIOCorePlayerBase variables
Change 4289157 by Patrick.Boutot
Allow the user to change the source of a capture without stopping the current capture.
[AJA] AjaMediaCapture, add support for UpdateSceneViewport & UpdateRenderTarget
@made by julien.stjean
Change 4291328 by Jon.Nabozny
Report the Skeleton Guid with TimeSyncData and track sync state in LiveLinkTimeSynchronizationSource.
This prevents a crash that can happen if a source is quickly cleared and reset before the next tick of Time Synchronization.
Change 4296294 by Jon.Nabozny
Fixup errors when TimecodeProviderClassName is empty. It's valid to leave this empty.
Change 4297122 by Patrick.Boutot
Media Profile with timecode provider & custom time step
Change 4301855 by Austin.Crismore
Fix for movment scaling and virtual joystick controls. Movement scaling in for truck and dolly is locked to the world xy plane, and virtual joysticks use their own method for movement scaling now.
#jira UE-61762, UE-62187
Change 4301856 by Austin.Crismore
Virtual sequence level controller now listens to on object spawned, so that it can intercept the camera actor and disable attatching to HMD to prevent camera movement that isn't from the level sequence
#jira UE-61766
Change 4301860 by Austin.Crismore
Fix for touch scrubbing. Added default values back in. Added logic to only allow scrubbing when touch focus was off.
#jira UE-61865
Change 4302294 by Jamie.Dale
Added functions to get your the localized spoken and subtitle text from a dialogue wave
Change 4304393 by Jamie.Dale
Added support for BlueprintAssignable properties in Python
Change 4305852 by Jamie.Dale
Removed hard-dependency between EditorScriptingUtilities and PythonScriptPlugin
Backed-out changelist 4259264 and query Python availability based on whether anything is available to handle the command
#jira UE-62318
Change 4308550 by Jamie.Dale
Fixed crash when passing a null world to Python actor iterators
Change 4311867 by Homam.Bahnassi
Revit master material with exposed parameters matching the API when possible.
Change 4314428 by Francis.Hurteau
Made the usage of the bBuildDeveloperTools switch independent of the bCompileAgainstEngine switch.
Changed bBuildDeveloperTools TargetRule in UnrealBuildTool to a nullable to keep the old behavior in case where bBuildDeveloperTools wasn't explicitly set in TargetRules
Change 4315134 by Jamie.Dale
Defer editable text focus selection until mouse-up to allow the user to make an initial selection
#jira UE-58086
Change 4318615 by Johan.Duparc
EditorFactories: consistent return values after asset import.
Change 4322459 by Jamie.Dale
Made SequencerScripting an Editor plugin as it depends on PythonScriptPlugin which is an Editor plugin
This was causing issues at runtime when SequencerScripting was enabled, as it failed to load PythonScriptPlugin (which hadn't been built).
Change 4323341 by Francis.Hurteau
Implement proper message bus protocol version negociation with static nodes
Change 4323733 by Francis.Hurteau
Fix VR Pausing Sequence Scrubbing just setting playback speed to 0.0
Change 4324319 by Jamie.Dale
Exposed transactions to Blueprints
Change 4325847 by Alistair.White
Copying //Tasks/UE4/Private-PixelStreaming@4325566 to Dev-Enterprise-Minimal (//UE4/Dev-Enterprise-Minimal)
This adds the new experimental PixelStreaming plugin to allow streaming of an Unreal client's audio & video stream to a browser through the WebRTC protocol to support new uses for enterprise customers.
Change 4326282 by Simon.Tourangeau
nDisplay native present handler
Change 4326581 by Jamie.Dale
Replacing FDateTime with int64 Ticks value to workaround UE-63485
Change 4326599 by Homam.Bahnassi
Moving texture coords outside UVEdit function to allow using different UV channels.
Change 4333250 by Francis.Hurteau
Small TFuture changes:
* cleans up TFuture::Then with usage of TUniqueFunction
* added TFuture::Reset to invalidate it and remove continuation from a future shared state
Change 4333359 by Homam.Bahnassi
Support scaling and rotating UVs around arbitrary pivot
Change 4333566 by Johan.Duparc
Expose ProxyLOD functionalities to Scripting
#jira UEENT-1788
Change 4333988 by Jamie.Dale
Allow UHT to parse FText default parameter values
INVTEXT, NSLOCTEXT, LOCTABLE, and FText::GetEmpty() are supported. LOCTEXT isn't as it relies on an external macro that is known to C++ but not to UHT (NSLOCTEXT can easily be used instead).
Change 4335020 by Francis.Hurteau
Uncomment MessageBus::Send deprecation notice for 4.21
Update MessageBus Send usage to new API
Change 4335195 by JeanMichel.Dignard
Add a SetLodFromStaticMesh script utility function
#jira UEENT-1789
Change 4335231 by Anousack.Kitisa
Added functions to generate planar, cylindrical, box UV mapping.
#jira UEENT-1598
Change 4335373 by Jamie.Dale
Cleaned up some places creating empty literal texts
Change 4335458 by Jamie.Dale
Allow UHT to parse FText() as an alias of FText::GetEmpty() when processing default values
Change 4335875 by Max.Chen
Sequencer: Clear RF_Transient on pasted tracks/sections
#jira UE-63537
Change 4336497 by Johan.Duparc
ProxyLOD: Fix progress bar issue
- removed duplicated code
- removed duplicated LongTask object
#jira UEENT-1788
Change 4336723 by Jamie.Dale
Ensure that Python generated types create their CDO at the correct point
#jira UE-62895
Change 4340594 by Ben.Marsh
Fix manifest being invalidated when building two enterprise targets in a row. Fixes CIS error.
#jira UE-63644
[CL 4342443 by JeanMichel Dignard in Main branch]
2018-09-04 16:35:02 -04:00
static const float FOVRad = FMath : : DegreesToRadians ( 45.0f ) ;
2017-06-30 12:21:06 -04:00
static const FMatrix ProjectionMatrix = FPerspectiveMatrix ( FOVRad , 1920 , 1080 , 0.01f ) ;
FHierarchicalLODUtilitiesModule & HLODModule = FModuleManager : : LoadModuleChecked < FHierarchicalLODUtilitiesModule > ( " HierarchicalLODUtilities " ) ;
IHierarchicalLODUtilities * Utilities = HLODModule . GetUtilities ( ) ;
float EstimatedDistance = Utilities - > CalculateDrawDistanceFromScreenSize ( EstimatedBounds . SphereRadius , ScreenSize , ProjectionMatrix ) ;
SlowTask . EnterProgressFrame ( 5.0f , LOCTEXT ( " CreateProxyMesh_CollectingMeshes " , " Collecting Input Static Meshes " ) ) ;
// Mesh / LOD index
2019-01-07 05:38:46 -05:00
TMap < uint32 , FMeshDescription * > RawMeshLODs ;
2017-06-30 12:21:06 -04:00
2019-09-20 15:47:52 -04:00
// Copies of mesh data
TArray < FMeshDescription * > MeshDescriptionData ;
2017-06-30 12:21:06 -04:00
2019-08-23 12:08:39 -04:00
// Mesh index, <original section index, unique section index>
TMultiMap < uint32 , TPair < uint32 , uint32 > > MeshSectionToUniqueSection ;
2017-06-30 12:21:06 -04:00
// Unique set of sections in mesh
TArray < FSectionInfo > UniqueSections ;
TArray < FSectionInfo > Sections ;
TMultiMap < uint32 , uint32 > SectionToMesh ;
2017-09-11 10:43:35 -04:00
int32 SummedLightmapPixels = 0 ;
2018-03-06 13:26:20 -05:00
TArray < const UStaticMeshComponent * > ImposterMeshComponents ;
2017-06-30 12:21:06 -04:00
for ( const UStaticMeshComponent * StaticMeshComponent : ComponentsToMerge )
{
2018-03-06 13:26:20 -05:00
int32 NumInstances = 1 ;
if ( StaticMeshComponent - > bUseMaxLODAsImposter )
2017-06-30 12:21:06 -04:00
{
2018-03-06 13:26:20 -05:00
ImposterMeshComponents . Add ( StaticMeshComponent ) ;
2017-06-30 12:21:06 -04:00
}
2018-03-06 13:26:20 -05:00
else
{
const int32 ScreenSizeBasedLODLevel = Utilities - > GetLODLevelForScreenSize ( StaticMeshComponent , Utilities - > CalculateScreenSizeFromDrawDistance ( StaticMeshComponent - > Bounds . SphereRadius , ProjectionMatrix , EstimatedDistance ) ) ;
const int32 LODIndex = InMeshProxySettings . bCalculateCorrectLODModel ? ScreenSizeBasedLODLevel : 0 ;
static const bool bPropagateVertexColours = true ;
2019-01-07 05:38:46 -05:00
// Retrieve mesh data in FMeshDescription form
2019-09-20 15:47:52 -04:00
const int32 MeshIndex = MeshDescriptionData . Add ( new FMeshDescription ( ) ) ;
FMeshDescription & MeshDescription = * MeshDescriptionData [ MeshIndex ] ;
2019-10-01 20:41:42 -04:00
FStaticMeshAttributes ( MeshDescription ) . Register ( ) ;
2019-09-20 15:47:52 -04:00
FMeshMergeHelpers : : RetrieveMesh ( StaticMeshComponent , LODIndex , MeshDescription , bPropagateVertexColours ) ;
2018-03-06 13:26:20 -05:00
// Reset section array for reuse
Sections . SetNum ( 0 , false ) ;
// Extract sections for given LOD index from the mesh
FMeshMergeHelpers : : ExtractSections ( StaticMeshComponent , LODIndex , Sections ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < Sections . Num ( ) ; + + SectionIndex )
{
FSectionInfo & Section = Sections [ SectionIndex ] ;
2019-08-23 12:08:39 -04:00
const int32 UniqueIndex = UniqueSections . AddUnique ( Section ) ;
MeshSectionToUniqueSection . Add ( MeshIndex , TPair < uint32 , uint32 > ( SectionIndex , UniqueIndex ) ) ;
2018-03-06 13:26:20 -05:00
SectionToMesh . Add ( UniqueIndex , MeshIndex ) ;
}
// If the component is an ISMC then we need to duplicate the vertex data
2019-08-23 12:04:04 -04:00
if ( StaticMeshComponent - > IsA < UInstancedStaticMeshComponent > ( ) )
2018-03-06 13:26:20 -05:00
{
const UInstancedStaticMeshComponent * InstancedStaticMeshComponent = Cast < UInstancedStaticMeshComponent > ( StaticMeshComponent ) ;
2019-09-20 15:47:52 -04:00
FMeshMergeHelpers : : ExpandInstances ( InstancedStaticMeshComponent , MeshDescription , Sections ) ;
2018-03-06 13:26:20 -05:00
NumInstances = InstancedStaticMeshComponent - > PerInstanceSMData . Num ( ) ;
}
}
2017-09-11 10:43:35 -04:00
int32 LightMapWidth , LightMapHeight ;
StaticMeshComponent - > GetLightMapResolution ( LightMapWidth , LightMapHeight ) ;
// Make sure we at least have some lightmap space allocated in case the static mesh is set up with invalid input
2018-03-06 13:26:20 -05:00
SummedLightmapPixels + = FMath : : Max ( 16 , LightMapHeight * LightMapWidth * NumInstances ) ;
2017-06-30 12:21:06 -04:00
}
TArray < UMaterialInterface * > UniqueMaterials ;
2019-08-23 12:08:39 -04:00
//Unique material index to unique section index
2017-06-30 12:21:06 -04:00
TMultiMap < uint32 , uint32 > SectionToMaterialMap ;
for ( int32 SectionIndex = 0 ; SectionIndex < UniqueSections . Num ( ) ; + + SectionIndex )
{
FSectionInfo & Section = UniqueSections [ SectionIndex ] ;
const int32 UniqueIndex = UniqueMaterials . AddUnique ( Section . Material ) ;
SectionToMaterialMap . Add ( UniqueIndex , SectionIndex ) ;
}
TArray < FMeshData > GlobalMeshSettings ;
TArray < FMaterialData > GlobalMaterialSettings ;
UMaterialOptions * Options = PopulateMaterialOptions ( InMeshProxySettings . MaterialSettings ) ;
TArray < EMaterialProperty > MaterialProperties ;
2018-02-14 14:13:42 -05:00
for ( const FPropertyEntry & Entry : Options - > Properties )
2017-06-30 12:21:06 -04:00
{
2017-09-11 10:43:35 -04:00
if ( Entry . Property ! = MP_MAX )
{
MaterialProperties . Add ( Entry . Property ) ;
}
2017-06-30 12:21:06 -04:00
}
// Mesh index / ( Mesh relative section index / output index )
TMultiMap < uint32 , TPair < uint32 , uint32 > > OutputMaterialsMap ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < UniqueMaterials . Num ( ) ; + + MaterialIndex )
{
UMaterialInterface * Material = UniqueMaterials [ MaterialIndex ] ;
2019-08-23 12:08:39 -04:00
//Unique section indices
2017-06-30 12:21:06 -04:00
TArray < uint32 > SectionIndices ;
SectionToMaterialMap . MultiFind ( MaterialIndex , SectionIndices ) ;
// Check whether or not this material requires mesh data
int32 NumTexCoords = 0 ;
bool bUseVertexData = false ;
FMaterialUtilities : : AnalyzeMaterial ( Material , MaterialProperties , NumTexCoords , bUseVertexData ) ;
FMaterialData MaterialSettings ;
MaterialSettings . Material = Material ;
for ( const FPropertyEntry & Entry : Options - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( ! Entry . bUseConstantValue & & Material - > IsPropertyActive ( Entry . Property ) & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
MaterialSettings . PropertySizes . Add ( Entry . Property , Entry . bUseCustomSize ? Entry . CustomSize : Options - > TextureSize ) ;
}
}
if ( bUseVertexData | | NumTexCoords ! = 0 )
{
for ( uint32 SectionIndex : SectionIndices )
{
TArray < uint32 > MeshIndices ;
SectionToMesh . MultiFind ( SectionIndex , MeshIndices ) ;
for ( uint32 MeshIndex : MeshIndices )
{
FMeshData MeshSettings ;
2019-09-20 15:47:52 -04:00
// Retrieve mesh description
FMeshDescription * MeshDescription = MeshDescriptionData [ MeshIndex ] ;
2019-01-07 05:38:46 -05:00
MeshSettings . RawMeshDescription = MeshDescription ;
2017-06-30 12:21:06 -04:00
2019-01-07 05:38:46 -05:00
TVertexInstanceAttributesRef < FVector2D > VertexInstanceUVs = MeshSettings . RawMeshDescription - > VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
2017-06-30 12:21:06 -04:00
// If we already have lightmap uvs generated or the lightmap coordinate index != 0 and available we can reuse those instead of having to generate new ones
2019-01-07 05:38:46 -05:00
if ( InMeshProxySettings . bReuseMeshLightmapUVs
2019-07-31 03:40:45 -04:00
& & ( ComponentsToMerge [ MeshIndex ] - > GetStaticMesh ( ) - > GetSourceModel ( 0 ) . BuildSettings . bGenerateLightmapUVs
2019-01-07 05:38:46 -05:00
| | ( ComponentsToMerge [ MeshIndex ] - > GetStaticMesh ( ) - > LightMapCoordinateIndex ! = 0 & & VertexInstanceUVs . GetNumElements ( ) > 0 & & VertexInstanceUVs . GetNumIndices ( ) > ComponentsToMerge [ MeshIndex ] - > GetStaticMesh ( ) - > LightMapCoordinateIndex ) ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
MeshSettings . CustomTextureCoordinates . Reset ( VertexInstanceUVs . GetNumElements ( ) ) ;
int32 LightMapCoordinateIndex = ComponentsToMerge [ MeshIndex ] - > GetStaticMesh ( ) - > LightMapCoordinateIndex ;
for ( const FVertexInstanceID VertexInstanceID : MeshSettings . RawMeshDescription - > VertexInstances ( ) . GetElementIDs ( ) )
{
MeshSettings . CustomTextureCoordinates . Add ( VertexInstanceUVs . Get ( VertexInstanceID , LightMapCoordinateIndex ) ) ;
}
2017-06-30 12:21:06 -04:00
ScaleTextureCoordinatesToBox ( FBox2D ( FVector2D : : ZeroVector , FVector2D ( 1 , 1 ) ) , MeshSettings . CustomTextureCoordinates ) ;
}
else
{
// Generate unique UVs for mesh (should only be done if needed)
2019-01-07 05:38:46 -05:00
FMeshDescriptionOperations : : GenerateUniqueUVsForStaticMesh ( * MeshDescription , Options - > TextureSize . GetMax ( ) , false , MeshSettings . CustomTextureCoordinates ) ;
2017-06-30 12:21:06 -04:00
ScaleTextureCoordinatesToBox ( FBox2D ( FVector2D : : ZeroVector , FVector2D ( 1 , 1 ) ) , MeshSettings . CustomTextureCoordinates ) ;
}
MeshSettings . TextureCoordinateBox = FBox2D ( MeshSettings . CustomTextureCoordinates ) ;
// Section index is a unique one so we need to map it to the mesh's equivalent(s)
2019-08-23 12:08:39 -04:00
TArray < TPair < uint32 , uint32 > > SectionToUniqueSectionIndices ;
MeshSectionToUniqueSection . MultiFind ( MeshIndex , SectionToUniqueSectionIndices ) ;
for ( const TPair < uint32 , uint32 > IndexPair : SectionToUniqueSectionIndices )
2017-06-30 12:21:06 -04:00
{
2019-08-23 12:08:39 -04:00
if ( IndexPair . Value = = SectionIndex )
2017-06-30 12:21:06 -04:00
{
2019-08-23 12:08:39 -04:00
MeshSettings . MaterialIndices . Add ( IndexPair . Key ) ;
OutputMaterialsMap . Add ( MeshIndex , TPair < uint32 , uint32 > ( IndexPair . Key , GlobalMeshSettings . Num ( ) ) ) ;
2017-06-30 12:21:06 -04:00
}
}
// Retrieve lightmap for usage of lightmap data
const UStaticMeshComponent * StaticMeshComponent = ComponentsToMerge [ MeshIndex ] ;
if ( StaticMeshComponent - > LODData . IsValidIndex ( 0 ) )
{
const FStaticMeshComponentLODInfo & ComponentLODInfo = StaticMeshComponent - > LODData [ 0 ] ;
const FMeshMapBuildData * MeshMapBuildData = StaticMeshComponent - > GetMeshMapBuildData ( ComponentLODInfo ) ;
if ( MeshMapBuildData )
{
MeshSettings . LightMap = MeshMapBuildData - > LightMap ;
MeshSettings . LightMapIndex = StaticMeshComponent - > GetStaticMesh ( ) - > LightMapCoordinateIndex ;
}
}
GlobalMeshSettings . Add ( MeshSettings ) ;
GlobalMaterialSettings . Add ( MaterialSettings ) ;
}
}
}
else
{
// Add simple bake entry
FMeshData MeshSettings ;
2019-01-07 05:38:46 -05:00
MeshSettings . RawMeshDescription = nullptr ;
2017-06-30 12:21:06 -04:00
MeshSettings . TextureCoordinateBox = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
MeshSettings . TextureCoordinateIndex = 0 ;
// For each original material index add an entry to the corresponding LOD and bake output index
for ( uint32 SectionIndex : SectionIndices )
{
TArray < uint32 > MeshIndices ;
SectionToMesh . MultiFind ( SectionIndex , MeshIndices ) ;
for ( uint32 MeshIndex : MeshIndices )
{
2019-08-23 12:08:39 -04:00
TArray < TPair < uint32 , uint32 > > SectionToUniqueSectionIndices ;
MeshSectionToUniqueSection . MultiFind ( MeshIndex , SectionToUniqueSectionIndices ) ;
for ( const TPair < uint32 , uint32 > IndexPair : SectionToUniqueSectionIndices )
2017-06-30 12:21:06 -04:00
{
2019-08-23 12:08:39 -04:00
if ( IndexPair . Value = = SectionIndex )
2017-06-30 12:21:06 -04:00
{
2019-08-23 12:08:39 -04:00
OutputMaterialsMap . Add ( MeshIndex , TPair < uint32 , uint32 > ( IndexPair . Key , GlobalMeshSettings . Num ( ) ) ) ;
2017-06-30 12:21:06 -04:00
}
}
}
}
GlobalMeshSettings . Add ( MeshSettings ) ;
GlobalMaterialSettings . Add ( MaterialSettings ) ;
}
}
2018-02-14 14:13:42 -05:00
TArray < FFlattenMaterial > FlattenedMaterials ;
IMaterialBakingModule & MaterialBakingModule = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
2017-06-30 12:21:06 -04:00
2018-02-14 14:13:42 -05:00
auto MaterialFlattenLambda =
2019-09-20 15:47:52 -04:00
[ this , & Options , & GlobalMeshSettings , & GlobalMaterialSettings , & MeshDescriptionData , & OutputMaterialsMap , & MaterialBakingModule ] ( TArray < FFlattenMaterial > & FlattenedMaterialArray )
2017-06-30 12:21:06 -04:00
{
2018-02-14 14:13:42 -05:00
TArray < FMeshData * > MeshSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMeshSettings . Num ( ) ; + + SettingsIndex )
2017-06-30 12:21:06 -04:00
{
2018-02-14 14:13:42 -05:00
MeshSettingPtrs . Add ( & GlobalMeshSettings [ SettingsIndex ] ) ;
}
TArray < FMaterialData * > MaterialSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMaterialSettings . Num ( ) ; + + SettingsIndex )
{
MaterialSettingPtrs . Add ( & GlobalMaterialSettings [ SettingsIndex ] ) ;
}
TArray < FBakeOutput > BakeOutputs ;
MaterialBakingModule . BakeMaterials ( MaterialSettingPtrs , MeshSettingPtrs , BakeOutputs ) ;
// Append constant properties ?
TArray < FColor > ConstantData ;
FIntPoint ConstantSize ( 1 , 1 ) ;
for ( const FPropertyEntry & Entry : Options - > Properties )
{
if ( Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
2018-02-14 14:13:42 -05:00
ConstantData . SetNum ( 1 , false ) ;
ConstantData [ 0 ] = FColor ( Entry . ConstantValue * 255.0f , Entry . ConstantValue * 255.0f , Entry . ConstantValue * 255.0f ) ;
for ( FBakeOutput & Ouput : BakeOutputs )
{
Ouput . PropertyData . Add ( Entry . Property , ConstantData ) ;
Ouput . PropertySizes . Add ( Entry . Property , ConstantSize ) ;
}
2017-06-30 12:21:06 -04:00
}
}
2018-02-14 14:13:42 -05:00
ConvertOutputToFlatMaterials ( BakeOutputs , GlobalMaterialSettings , FlattenedMaterialArray ) ;
2017-06-30 12:21:06 -04:00
2018-02-14 14:13:42 -05:00
// Now have the baked out material data, need to have a map or actually remap the raw mesh data to baked material indices
2019-09-20 15:47:52 -04:00
for ( int32 MeshIndex = 0 ; MeshIndex < MeshDescriptionData . Num ( ) ; + + MeshIndex )
2017-06-30 12:21:06 -04:00
{
2019-09-20 15:47:52 -04:00
FMeshDescription & MeshDescription = * MeshDescriptionData [ MeshIndex ] ;
2017-06-30 12:21:06 -04:00
2018-02-14 14:13:42 -05:00
TArray < TPair < uint32 , uint32 > > SectionAndOutputIndices ;
OutputMaterialsMap . MultiFind ( MeshIndex , SectionAndOutputIndices ) ;
TArray < int32 > Remap ;
// Reorder loops
for ( const TPair < uint32 , uint32 > & IndexPair : SectionAndOutputIndices )
2017-06-30 12:21:06 -04:00
{
2019-08-23 12:08:39 -04:00
const int32 SectionIndex = IndexPair . Key ;
2018-02-14 14:13:42 -05:00
const int32 NewIndex = IndexPair . Value ;
if ( Remap . Num ( ) < ( SectionIndex + 1 ) )
{
Remap . SetNum ( SectionIndex + 1 ) ;
}
Remap [ SectionIndex ] = NewIndex ;
2017-06-30 12:21:06 -04:00
}
2019-01-07 05:38:46 -05:00
TMap < FPolygonGroupID , FPolygonGroupID > RemapPolygonGroup ;
2019-09-20 15:47:52 -04:00
for ( const FPolygonGroupID & PolygonGroupID : MeshDescription . PolygonGroups ( ) . GetElementIDs ( ) )
2018-02-14 14:13:42 -05:00
{
2019-01-07 05:38:46 -05:00
checkf ( Remap . IsValidIndex ( PolygonGroupID . GetValue ( ) ) , TEXT ( " Missing material bake output index entry for mesh(section) " ) ) ;
int32 RemapID = Remap [ PolygonGroupID . GetValue ( ) ] ;
RemapPolygonGroup . Add ( PolygonGroupID , FPolygonGroupID ( RemapID ) ) ;
}
2019-09-20 15:47:52 -04:00
FMeshDescriptionOperations : : RemapPolygonGroups ( MeshDescription , RemapPolygonGroup ) ;
2017-06-30 12:21:06 -04:00
}
2018-02-14 14:13:42 -05:00
} ;
2017-06-30 12:21:06 -04:00
2019-01-22 16:07:31 -05:00
// Landscape culling. NB these are temporary copies of the culling data and should be deleted after use.
2019-01-07 05:38:46 -05:00
TArray < FMeshDescription * > CullingRawMeshes ;
2017-06-30 12:21:06 -04:00
if ( InMeshProxySettings . bUseLandscapeCulling )
{
SlowTask . EnterProgressFrame ( 5.0f , LOCTEXT ( " CreateProxyMesh_LandscapeCulling " , " Applying Landscape Culling " ) ) ;
2018-02-14 14:13:42 -05:00
UWorld * InWorld = ComponentsToMerge [ 0 ] - > GetWorld ( ) ;
2017-06-30 12:21:06 -04:00
FMeshMergeHelpers : : RetrieveCullingLandscapeAndVolumes ( InWorld , EstimatedBounds , InMeshProxySettings . LandscapeCullingPrecision , CullingRawMeshes ) ;
}
// Allocate merge complete data
FMergeCompleteData * Data = new FMergeCompleteData ( ) ;
Data - > InOuter = InOuter ;
Data - > InProxySettings = InMeshProxySettings ;
Data - > ProxyBasePackageName = InProxyBasePackageName ;
Data - > CallbackDelegate = InProxyCreatedDelegate ;
2018-03-06 13:26:20 -05:00
Data - > ImposterComponents = ImposterMeshComponents ;
2018-05-23 21:04:31 -04:00
Data - > StaticMeshComponents = ComponentsToMerge ;
Data - > StaticMeshComponents . RemoveAll ( [ & ] ( UStaticMeshComponent * Component ) { return ImposterMeshComponents . Contains ( Component ) ; } ) ;
2018-03-06 13:26:20 -05:00
Data - > BaseMaterial = InBaseMaterial ;
2017-06-30 12:21:06 -04:00
2017-09-11 10:43:35 -04:00
// Lightmap resolution
if ( InMeshProxySettings . bComputeLightMapResolution )
{
Data - > InProxySettings . LightMapResolution = FMath : : CeilToInt ( FMath : : Sqrt ( SummedLightmapPixels ) ) ;
}
2017-06-30 12:21:06 -04:00
// Add this proxy job to map
Processor - > AddProxyJob ( InGuid , Data ) ;
// We are only using LOD level 0 (ProxyMeshTargetLODLevel)
TArray < FMeshMergeData > MergeDataEntries ;
2019-09-20 15:47:52 -04:00
for ( int32 Index = 0 ; Index < MeshDescriptionData . Num ( ) ; + + Index )
2017-06-30 12:21:06 -04:00
{
FMeshMergeData MergeData ;
MergeData . SourceStaticMesh = ComponentsToMerge [ Index ] - > GetStaticMesh ( ) ;
2019-09-20 15:47:52 -04:00
MergeData . RawMesh = MeshDescriptionData [ Index ] ;
2018-02-14 14:13:42 -05:00
MergeData . bIsClippingMesh = false ;
2017-06-30 12:21:06 -04:00
FMeshMergeHelpers : : CalculateTextureCoordinateBoundsForRawMesh ( * MergeData . RawMesh , MergeData . TexCoordBounds ) ;
2018-02-14 14:13:42 -05:00
2017-06-30 12:21:06 -04:00
FMeshData * MeshData = GlobalMeshSettings . FindByPredicate ( [ & ] ( const FMeshData & Entry )
{
2019-01-07 05:38:46 -05:00
return Entry . RawMeshDescription = = MergeData . RawMesh & & ( Entry . CustomTextureCoordinates . Num ( ) | | Entry . TextureCoordinateIndex ! = 0 ) ;
2017-06-30 12:21:06 -04:00
} ) ;
if ( MeshData )
{
if ( MeshData - > CustomTextureCoordinates . Num ( ) )
{
MergeData . NewUVs = MeshData - > CustomTextureCoordinates ;
}
else
{
2019-01-07 05:38:46 -05:00
TVertexInstanceAttributesRef < FVector2D > VertexInstanceUVs = MeshData - > RawMeshDescription - > VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
MergeData . NewUVs . Reset ( MeshData - > RawMeshDescription - > VertexInstances ( ) . Num ( ) ) ;
for ( const FVertexInstanceID VertexInstanceID : MeshData - > RawMeshDescription - > VertexInstances ( ) . GetElementIDs ( ) )
{
MergeData . NewUVs . Add ( VertexInstanceUVs . Get ( VertexInstanceID , MeshData - > TextureCoordinateIndex ) ) ;
}
2017-06-30 12:21:06 -04:00
}
MergeData . TexCoordBounds [ 0 ] = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
}
MergeDataEntries . Add ( MergeData ) ;
}
// Populate landscape clipping geometry
2019-01-07 05:38:46 -05:00
for ( FMeshDescription * RawMesh : CullingRawMeshes )
2017-06-30 12:21:06 -04:00
{
FMeshMergeData ClipData ;
ClipData . bIsClippingMesh = true ;
ClipData . RawMesh = RawMesh ;
MergeDataEntries . Add ( ClipData ) ;
}
SlowTask . EnterProgressFrame ( 50.0f , LOCTEXT ( " CreateProxyMesh_GenerateProxy " , " Generating Proxy Mesh " ) ) ;
2018-02-14 14:13:42 -05:00
2017-06-30 12:21:06 -04:00
// Choose Simplygon Swarm (if available) or local proxy lod method
if ( ReductionModule . GetDistributedMeshMergingInterface ( ) ! = nullptr & & GetDefault < UEditorPerProjectUserSettings > ( ) - > bUseSimplygonSwarm & & bAllowAsync )
{
2018-02-14 14:13:42 -05:00
MaterialFlattenLambda ( FlattenedMaterials ) ;
2017-06-30 12:21:06 -04:00
ReductionModule . GetDistributedMeshMergingInterface ( ) - > ProxyLOD ( MergeDataEntries , Data - > InProxySettings , FlattenedMaterials , InGuid ) ;
}
else
{
2018-02-14 14:13:42 -05:00
IMeshMerging * MeshMerging = ReductionModule . GetMeshMergingInterface ( ) ;
// Register the Material Flattening code if parallel execution is supported, otherwise directly run it.
if ( MeshMerging - > bSupportsParallelMaterialBake ( ) )
{
MeshMerging - > BakeMaterialsDelegate . BindLambda ( MaterialFlattenLambda ) ;
}
else
{
MaterialFlattenLambda ( FlattenedMaterials ) ;
}
MeshMerging - > ProxyLOD ( MergeDataEntries , Data - > InProxySettings , FlattenedMaterials , InGuid ) ;
2017-06-30 12:21:06 -04:00
Processor - > Tick ( 0 ) ; // make sure caller gets merging results
}
2019-01-22 16:07:31 -05:00
// Clean up the CullingRawMeshes
for ( FMeshDescription * RawMesh : CullingRawMeshes )
{
delete RawMesh ;
}
2019-09-20 15:47:52 -04:00
// Clean up the MeshDescriptionData
for ( FMeshDescription * MeshDescription : MeshDescriptionData )
{
delete MeshDescription ;
}
2017-06-30 12:21:06 -04:00
}
2019-01-22 16:07:31 -05:00
2018-03-06 13:26:20 -05:00
bool FMeshMergeUtilities : : IsValidBaseMaterial ( const UMaterialInterface * InBaseMaterial , bool bShowToaster ) const
{
2018-05-23 21:04:31 -04:00
if ( InBaseMaterial ! = nullptr )
2018-03-06 13:26:20 -05:00
{
TArray < FGuid > ParameterIds ;
TArray < FString > MissingParameters ;
auto NameCheckLambda = [ & MissingParameters ] ( const TArray < FMaterialParameterInfo > & InCheck , const TArray < FName > & InRequired )
{
for ( const FName & Name : InRequired )
{
if ( ! InCheck . ContainsByPredicate ( [ Name ] ( const FMaterialParameterInfo & ParamInfo ) { return ( ParamInfo . Name = = Name ) ; } ) )
{
MissingParameters . Add ( Name . ToString ( ) ) ;
}
}
} ;
TArray < FMaterialParameterInfo > TextureParameterInfos ;
TArray < FName > RequiredTextureNames = { TEXT ( " DiffuseTexture " ) , TEXT ( " NormalTexture " ) , TEXT ( " PackedTexture " ) , TEXT ( " MetallicTexture " ) , TEXT ( " SpecularTexture " ) , TEXT ( " RoughnessTexture " ) , TEXT ( " EmissiveTexture " ) , TEXT ( " OpacityTexture " ) , TEXT ( " OpacityMaskTexture " ) , TEXT ( " AmbientOcclusionTexture " ) } ;
2018-05-23 21:04:31 -04:00
InBaseMaterial - > GetAllTextureParameterInfo ( TextureParameterInfos , ParameterIds ) ;
2018-03-06 13:26:20 -05:00
NameCheckLambda ( TextureParameterInfos , RequiredTextureNames ) ;
TArray < FMaterialParameterInfo > ScalarParameterInfos ;
TArray < FName > RequiredScalarNames = { TEXT ( " MetallicConst " ) , TEXT ( " SpecularConst " ) , TEXT ( " RoughnessConst " ) , TEXT ( " OpacityConst " ) , TEXT ( " OpacityMaskConst " ) , TEXT ( " AmbientOcclusionConst " ) , TEXT ( " EmissiveScale " ) } ;
2018-05-23 21:04:31 -04:00
InBaseMaterial - > GetAllScalarParameterInfo ( ScalarParameterInfos , ParameterIds ) ;
2018-03-06 13:26:20 -05:00
NameCheckLambda ( ScalarParameterInfos , RequiredScalarNames ) ;
TArray < FMaterialParameterInfo > VectorParameterInfos ;
TArray < FName > RequiredVectorNames = { TEXT ( " DiffuseConst " ) , TEXT ( " EmissiveConst " ) } ;
2018-05-23 21:04:31 -04:00
InBaseMaterial - > GetAllVectorParameterInfo ( VectorParameterInfos , ParameterIds ) ;
2018-03-06 13:26:20 -05:00
NameCheckLambda ( VectorParameterInfos , RequiredVectorNames ) ;
TArray < FMaterialParameterInfo > StaticSwitchParameterInfos ;
TArray < FName > RequiredSwitchNames = { TEXT ( " UseDiffuse " ) , TEXT ( " PackMetallic " ) , TEXT ( " PackSpecular " ) , TEXT ( " PackRoughness " ) , TEXT ( " UseMetallic " ) , TEXT ( " UseSpecular " ) , TEXT ( " UseRoughness " ) , TEXT ( " UseEmissive " ) , TEXT ( " UseOpacity " ) , TEXT ( " UseOpacityMask " ) , TEXT ( " UseAmbientOcclusion " ) } ;
2018-05-23 21:04:31 -04:00
InBaseMaterial - > GetAllStaticSwitchParameterInfo ( StaticSwitchParameterInfos , ParameterIds ) ;
2018-03-06 13:26:20 -05:00
NameCheckLambda ( StaticSwitchParameterInfos , RequiredSwitchNames ) ;
if ( MissingParameters . Num ( ) > 0 )
{
FString MissingNamesString ;
for ( const FString & Name : MissingParameters )
{
if ( ! MissingNamesString . IsEmpty ( ) )
{
MissingNamesString + = " , " ;
MissingNamesString + = Name ;
}
else
{
MissingNamesString + = Name ;
}
}
# if WITH_EDITOR
if ( bShowToaster )
{
FFormatNamedArguments Arguments ;
Arguments . Add ( TEXT ( " MaterialName " ) , FText : : FromString ( InBaseMaterial - > GetName ( ) ) ) ;
FText ErrorMessage = FText : : Format ( LOCTEXT ( " UHierarchicalLODSettings_PostEditChangeProperty " , " Material {MaterialName} is missing required Material Parameters (check log for details) " ) , Arguments ) ;
FNotificationInfo Info ( ErrorMessage ) ;
Info . ExpireDuration = 5.0f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
}
UE_LOG ( LogMeshMerging , Error , TEXT ( " Material %s is missing required Material Parameters %s, resetting to default. " ) , * InBaseMaterial - > GetName ( ) , * MissingNamesString ) ;
# endif // WITH_EDITOR
return false ;
}
else
{
return true ;
}
}
return false ;
}
void FMeshMergeUtilities : : RegisterExtension ( IMeshMergeExtension * InExtension )
{
MeshMergeExtensions . Add ( InExtension ) ;
}
void FMeshMergeUtilities : : UnregisterExtension ( IMeshMergeExtension * InExtension )
{
MeshMergeExtensions . Remove ( InExtension ) ;
}
2019-01-07 05:38:46 -05:00
bool RetrieveRawMeshData ( FMeshMergeDataTracker & DataTracker
, const int32 ComponentIndex
, const int32 LODIndex
, UStaticMeshComponent * Component
, const bool bPropagateMeshData
, TArray < FSectionInfo > & Sections
, FStaticMeshComponentAdapter & Adapter
, const bool bMergeMaterialData
, const FMeshMergingSettings & InSettings )
{
// Retrieve raw mesh data
FMeshDescription & RawMesh = DataTracker . AddAndRetrieveRawMesh ( ComponentIndex , LODIndex , Component - > GetStaticMesh ( ) ) ;
Adapter . RetrieveRawMeshData ( LODIndex , RawMesh , bPropagateMeshData ) ;
// Reset section for reuse
Sections . SetNum ( 0 , false ) ;
// Extract sections for given LOD index from the mesh
Adapter . RetrieveMeshSections ( LODIndex , Sections ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < Sections . Num ( ) ; + + SectionIndex )
{
const FSectionInfo & Section = Sections [ SectionIndex ] ;
// Unique section index for remapping
const int32 UniqueIndex = DataTracker . AddSection ( Section ) ;
// Store of original to unique section index entry for this component + LOD index
2019-09-20 15:47:52 -04:00
DataTracker . AddSectionRemapping ( ComponentIndex , LODIndex , SectionIndex , UniqueIndex ) ;
2019-01-07 05:38:46 -05:00
DataTracker . AddMaterialSlotName ( Section . Material , Section . MaterialSlotName ) ;
if ( ! bMergeMaterialData )
{
FMeshDescriptionOperations : : SwapPolygonPolygonGroup ( RawMesh , UniqueIndex , Section . StartIndex , Section . EndIndex , false ) ;
}
}
//Compact the PolygonGroupID to make sure it follow the section index
FElementIDRemappings RemapInformation ;
RawMesh . Compact ( RemapInformation ) ;
// If the component is an ISMC then we need to duplicate the vertex data
2019-08-23 12:04:04 -04:00
if ( Component - > IsA < UInstancedStaticMeshComponent > ( ) )
2019-01-07 05:38:46 -05:00
{
const UInstancedStaticMeshComponent * InstancedStaticMeshComponent = Cast < UInstancedStaticMeshComponent > ( Component ) ;
FMeshMergeHelpers : : ExpandInstances ( InstancedStaticMeshComponent , RawMesh , Sections ) ;
}
if ( InSettings . bUseLandscapeCulling )
{
FMeshMergeHelpers : : CullTrianglesFromVolumesAndUnderLandscapes ( Component - > GetWorld ( ) , Adapter . GetBounds ( ) , RawMesh ) ;
}
// If the valid became invalid during retrieval remove it again
const bool bValidMesh = RawMesh . VertexInstances ( ) . Num ( ) > 0 ;
if ( ! bValidMesh )
{
DataTracker . RemoveRawMesh ( ComponentIndex , LODIndex ) ;
}
else if ( Component - > GetStaticMesh ( ) ! = nullptr )
{
// If the mesh is valid at this point, record the lightmap UV so we have a record for use later
DataTracker . AddLightmapChannelRecord ( ComponentIndex , LODIndex , Component - > GetStaticMesh ( ) - > LightMapCoordinateIndex ) ;
}
return bValidMesh ;
}
2018-03-06 13:26:20 -05:00
void FMeshMergeUtilities : : MergeComponentsToStaticMesh ( const TArray < UPrimitiveComponent * > & ComponentsToMerge , UWorld * World , const FMeshMergingSettings & InSettings , UMaterialInterface * InBaseMaterial , UPackage * InOuter , const FString & InBasePackageName , TArray < UObject * > & OutAssetsToSync , FVector & OutMergedActorLocation , const float ScreenSize , bool bSilent /*= false*/ ) const
2017-06-30 12:21:06 -04:00
{
2019-10-04 13:11:45 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FMeshMergeUtilities : : MergeComponentsToStaticMesh ) ;
2017-06-30 12:21:06 -04:00
// Use first mesh for naming and pivot
bool bFirstMesh = true ;
FString MergedAssetPackageName ;
FVector MergedAssetPivot ;
2018-03-06 13:26:20 -05:00
2017-06-30 12:21:06 -04:00
TArray < UStaticMeshComponent * > StaticMeshComponentsToMerge ;
2018-03-06 13:26:20 -05:00
TArray < const UStaticMeshComponent * > ImposterComponents ;
2017-06-30 12:21:06 -04:00
for ( int32 MeshId = 0 ; MeshId < ComponentsToMerge . Num ( ) ; + + MeshId )
{
UStaticMeshComponent * MeshComponent = Cast < UStaticMeshComponent > ( ComponentsToMerge [ MeshId ] ) ;
if ( MeshComponent )
{
2018-03-06 13:26:20 -05:00
if ( MeshComponent - > bUseMaxLODAsImposter & & InSettings . bIncludeImposters )
{
ImposterComponents . Add ( MeshComponent ) ;
}
else
{
StaticMeshComponentsToMerge . Add ( MeshComponent ) ;
2019-08-21 09:52:37 -04:00
}
2017-06-30 12:21:06 -04:00
2019-08-21 09:52:37 -04:00
// Save the pivot and asset package name of the first mesh, will later be used for creating merged mesh asset
if ( bFirstMesh )
{
// Mesh component pivot point
MergedAssetPivot = InSettings . bPivotPointAtZero ? FVector : : ZeroVector : MeshComponent - > GetComponentTransform ( ) . GetLocation ( ) ;
2017-06-30 12:21:06 -04:00
2019-08-21 09:52:37 -04:00
// Source mesh asset package name
MergedAssetPackageName = MeshComponent - > GetStaticMesh ( ) - > GetOutermost ( ) - > GetName ( ) ;
bFirstMesh = false ;
2017-06-30 12:21:06 -04:00
}
}
}
// Nothing to do if no StaticMeshComponents
2018-03-06 13:26:20 -05:00
if ( StaticMeshComponentsToMerge . Num ( ) = = 0 & & ImposterComponents . Num ( ) = = 0 )
2017-06-30 12:21:06 -04:00
{
return ;
}
FMeshMergeDataTracker DataTracker ;
const bool bMergeAllLODs = InSettings . LODSelectionType = = EMeshLODSelectionType : : AllLODs ;
const bool bMergeMaterialData = InSettings . bMergeMaterials & & InSettings . LODSelectionType ! = EMeshLODSelectionType : : AllLODs ;
const bool bPropagateMeshData = InSettings . bBakeVertexDataToMesh | | ( bMergeMaterialData & & InSettings . bUseVertexDataForBakingMaterial ) ;
TArray < FStaticMeshComponentAdapter > Adapters ;
TArray < FSectionInfo > Sections ;
if ( bMergeAllLODs )
{
for ( int32 ComponentIndex = 0 ; ComponentIndex < StaticMeshComponentsToMerge . Num ( ) ; + + ComponentIndex )
{
UStaticMeshComponent * Component = StaticMeshComponentsToMerge [ ComponentIndex ] ;
Adapters . Add ( FStaticMeshComponentAdapter ( Component ) ) ;
FStaticMeshComponentAdapter & Adapter = Adapters . Last ( ) ;
2017-09-11 10:43:35 -04:00
if ( InSettings . bComputedLightMapResolution )
{
int32 LightMapHeight , LightMapWidth ;
if ( Component - > GetLightMapResolution ( LightMapWidth , LightMapHeight ) )
{
DataTracker . AddLightMapPixels ( LightMapWidth * LightMapHeight ) ;
}
}
2018-03-06 13:26:20 -05:00
const int32 NumLODs = [ & ] ( )
{
const int32 NumberOfLODsAvailable = Adapter . GetNumberOfLODs ( ) ;
if ( Component - > bUseMaxLODAsImposter )
{
return InSettings . bIncludeImposters ? NumberOfLODsAvailable : NumberOfLODsAvailable - 1 ;
}
return NumberOfLODsAvailable ;
} ( ) ;
2017-06-30 12:21:06 -04:00
for ( int32 LODIndex = 0 ; LODIndex < NumLODs ; + + LODIndex )
{
2019-01-07 05:38:46 -05:00
if ( ! RetrieveRawMeshData ( DataTracker
, ComponentIndex
, LODIndex
, Component
, bPropagateMeshData
, Sections
, Adapter
, false
, InSettings ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
//If the rawmesh was not retrieve properly break the loop
2017-06-30 12:21:06 -04:00
break ;
}
DataTracker . AddLODIndex ( LODIndex ) ;
}
}
}
else
{
// Retrieve HLOD module for calculating LOD index from screen size
FHierarchicalLODUtilitiesModule & Module = FModuleManager : : LoadModuleChecked < FHierarchicalLODUtilitiesModule > ( " HierarchicalLODUtilities " ) ;
IHierarchicalLODUtilities * Utilities = Module . GetUtilities ( ) ;
// Adding LOD 0 for merged mesh output
DataTracker . AddLODIndex ( 0 ) ;
// Retrieve mesh and section data for each component
2018-03-06 13:26:20 -05:00
for ( int32 ComponentIndex = 0 ; ComponentIndex < StaticMeshComponentsToMerge . Num ( ) ; + + ComponentIndex )
2017-06-30 12:21:06 -04:00
{
// Create material merge adapter for this component
UStaticMeshComponent * Component = StaticMeshComponentsToMerge [ ComponentIndex ] ;
Adapters . Add ( FStaticMeshComponentAdapter ( Component ) ) ;
FStaticMeshComponentAdapter & Adapter = Adapters . Last ( ) ;
// Determine LOD to use for merging, either user specified or calculated index and ensure we clamp to the maximum LOD index for this adapter
const int32 LODIndex = [ & ] ( )
{
2019-05-30 10:37:45 -04:00
int32 LowestDetailLOD = Adapter . GetNumberOfLODs ( ) - 1 ;
if ( Component - > bUseMaxLODAsImposter & & ! InSettings . bIncludeImposters )
{
LowestDetailLOD = FMath : : Max ( 0 , LowestDetailLOD - 1 ) ;
}
2018-03-06 13:26:20 -05:00
switch ( InSettings . LODSelectionType )
2017-06-30 12:21:06 -04:00
{
2018-03-06 13:26:20 -05:00
case EMeshLODSelectionType : : SpecificLOD :
2019-05-30 10:37:45 -04:00
return FMath : : Min ( LowestDetailLOD , InSettings . SpecificLOD ) ;
2018-03-06 13:26:20 -05:00
case EMeshLODSelectionType : : CalculateLOD :
2019-05-30 10:37:45 -04:00
return FMath : : Min ( LowestDetailLOD , Utilities - > GetLODLevelForScreenSize ( Component , FMath : : Clamp ( ScreenSize , 0.0f , 1.0f ) ) ) ;
2018-03-06 13:26:20 -05:00
case EMeshLODSelectionType : : LowestDetailLOD :
2019-05-30 10:37:45 -04:00
default :
return LowestDetailLOD ;
2017-06-30 12:21:06 -04:00
}
} ( ) ;
2019-01-07 05:38:46 -05:00
RetrieveRawMeshData ( DataTracker
, ComponentIndex
, LODIndex
, Component
, bPropagateMeshData
, Sections
, Adapter
, bMergeMaterialData
, InSettings ) ;
2017-06-30 12:21:06 -04:00
}
}
DataTracker . ProcessRawMeshes ( ) ;
// Retrieve physics data
UBodySetup * BodySetupSource = nullptr ;
TArray < FKAggregateGeom > PhysicsGeometry ;
if ( InSettings . bMergePhysicsData )
{
ExtractPhysicsDataFromComponents ( ComponentsToMerge , PhysicsGeometry , BodySetupSource ) ;
}
// Find all unique materials and remap section to unique materials
TArray < UMaterialInterface * > UniqueMaterials ;
TMap < UMaterialInterface * , int32 > MaterialIndices ;
2018-03-06 13:26:20 -05:00
TMap < UMaterialInterface * , UMaterialInterface * > CollapsedMaterialMap ;
2017-06-30 12:21:06 -04:00
for ( int32 SectionIndex = 0 ; SectionIndex < DataTracker . NumberOfUniqueSections ( ) ; + + SectionIndex )
{
// Unique index for material
2018-03-06 13:26:20 -05:00
UMaterialInterface * MaterialInterface = DataTracker . GetMaterialForSectionIndex ( SectionIndex ) ;
int32 UniqueIndex = UniqueMaterials . IndexOfByPredicate ( [ & InSettings , MaterialInterface ] ( const UMaterialInterface * InMaterialInterface )
{
// Perform an optional custom comparison if we are trying to collapse material instances
if ( InSettings . bMergeEquivalentMaterials )
{
return FMaterialKey ( MaterialInterface ) = = FMaterialKey ( InMaterialInterface ) ;
}
return MaterialInterface = = InMaterialInterface ;
} ) ;
if ( UniqueIndex = = INDEX_NONE )
{
UniqueIndex = UniqueMaterials . Add ( MaterialInterface ) ;
}
// Update map to 'collapsed' materials
CollapsedMaterialMap . Add ( MaterialInterface , UniqueMaterials [ UniqueIndex ] ) ;
2017-06-30 12:21:06 -04:00
}
// For each unique material calculate how 'important' they are
TArray < float > MaterialImportanceValues ;
FMaterialUtilities : : DetermineMaterialImportance ( UniqueMaterials , MaterialImportanceValues ) ;
2019-07-22 08:22:52 -04:00
TMultiMap < FMeshLODKey , MaterialRemapPair > OutputMaterialsMap ;
// The UV channel to use for the flattened material
int32 MergedMatUVChannel = INDEX_NONE ;
UMaterialInterface * MergedMaterial = nullptr ;
2017-06-30 12:21:06 -04:00
// If the user wants to merge materials into a single one
2019-08-21 09:52:37 -04:00
if ( bMergeMaterialData & & UniqueMaterials . Num ( ) ! = 0 )
2017-06-30 12:21:06 -04:00
{
UMaterialOptions * MaterialOptions = PopulateMaterialOptions ( InSettings . MaterialSettings ) ;
// Check each material to see if the shader actually uses vertex data and collect flags
TArray < bool > bMaterialUsesVertexData ;
DetermineMaterialVertexDataUsage ( bMaterialUsesVertexData , UniqueMaterials , MaterialOptions ) ;
TArray < FMeshData > GlobalMeshSettings ;
TArray < FMaterialData > GlobalMaterialSettings ;
TArray < float > SectionMaterialImportanceValues ;
TMap < EMaterialProperty , FIntPoint > PropertySizes ;
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( ! Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
PropertySizes . Add ( Entry . Property , Entry . bUseCustomSize ? Entry . CustomSize : MaterialOptions - > TextureSize ) ;
}
}
TMap < UMaterialInterface * , int32 > MaterialToDefaultMeshData ;
2019-09-20 15:47:52 -04:00
// If we are generating a single LOD and want to merge materials we can utilize texture space better by generating unique UVs
// for the merged mesh and baking out materials using those UVs
const bool bGloballyRemapUVs = ! bMergeAllLODs & & ! InSettings . bReuseMeshLightmapUVs ;
2017-06-30 12:21:06 -04:00
for ( TConstRawMeshIterator RawMeshIterator = DataTracker . GetConstRawMeshIterator ( ) ; RawMeshIterator ; + + RawMeshIterator )
{
const FMeshLODKey & Key = RawMeshIterator . Key ( ) ;
2019-01-07 05:38:46 -05:00
const FMeshDescription & RawMesh = RawMeshIterator . Value ( ) ;
2017-06-30 12:21:06 -04:00
const bool bRequiresUniqueUVs = DataTracker . DoesMeshLODRequireUniqueUVs ( Key ) ;
2018-03-06 13:26:20 -05:00
UStaticMeshComponent * Component = StaticMeshComponentsToMerge [ Key . GetMeshIndex ( ) ] ;
2017-06-30 12:21:06 -04:00
// Retrieve all sections and materials for key
TArray < SectionRemapPair > SectionRemapPairs ;
DataTracker . GetMappingsForMeshLOD ( Key , SectionRemapPairs ) ;
// Contains unique materials used for this key, and the accompanying section index which point to the material
TMap < UMaterialInterface * , TArray < int32 > > MaterialAndSectionIndices ;
for ( const SectionRemapPair & RemapPair : SectionRemapPairs )
{
const int32 UniqueIndex = RemapPair . Value ;
const int32 SectionIndex = RemapPair . Key ;
2018-03-06 13:26:20 -05:00
TArray < int32 > & SectionIndices = MaterialAndSectionIndices . FindOrAdd ( CollapsedMaterialMap . FindChecked ( DataTracker . GetMaterialForSectionIndex ( UniqueIndex ) ) ) ;
2017-06-30 12:21:06 -04:00
SectionIndices . Add ( SectionIndex ) ;
}
// Cache unique texture coordinates
TArray < FVector2D > UniqueTextureCoordinates ;
for ( TPair < UMaterialInterface * , TArray < int32 > > & MaterialSectionIndexPair : MaterialAndSectionIndices )
{
UMaterialInterface * Material = MaterialSectionIndexPair . Key ;
const int32 MaterialIndex = UniqueMaterials . IndexOfByKey ( Material ) ;
const TArray < int32 > & SectionIndices = MaterialSectionIndexPair . Value ;
const bool bDoesMaterialUseVertexData = bMaterialUsesVertexData [ MaterialIndex ] ;
FMaterialData MaterialData ;
2018-03-06 13:26:20 -05:00
MaterialData . Material = CollapsedMaterialMap . FindChecked ( Material ) ;
2017-06-30 12:21:06 -04:00
MaterialData . PropertySizes = PropertySizes ;
FMeshData MeshData ;
2018-03-06 13:26:20 -05:00
MeshData . Mesh = Key . GetMesh ( ) ;
MeshData . VertexColorHash = Key . GetVertexColorHash ( ) ;
MeshData . bMirrored = Component - > GetComponentTransform ( ) . GetDeterminant ( ) < 0.0f ;
2017-06-30 12:21:06 -04:00
int32 MeshDataIndex = 0 ;
2019-09-20 15:47:52 -04:00
if ( InSettings . bCreateMergedMaterial | | bGloballyRemapUVs | | ( InSettings . bUseVertexDataForBakingMaterial & & ( bDoesMaterialUseVertexData | | bRequiresUniqueUVs ) ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
MeshData . RawMeshDescription = DataTracker . GetRawMeshPtr ( Key ) ;
2017-09-11 10:43:35 -04:00
// if it has vertex color/*WedgetColors.Num()*/, it should also use light map UV index
// we can't do this for all meshes, but only for the mesh that has vertex color.
2019-01-07 05:38:46 -05:00
if ( bRequiresUniqueUVs | | MeshData . RawMeshDescription - > VertexInstances ( ) . Num ( ) > 0 )
2017-06-30 12:21:06 -04:00
{
// Check if there are lightmap uvs available?
const int32 LightMapUVIndex = StaticMeshComponentsToMerge [ Key . GetMeshIndex ( ) ] - > GetStaticMesh ( ) - > LightMapCoordinateIndex ;
2019-01-07 05:38:46 -05:00
TVertexInstanceAttributesRef < FVector2D > VertexInstanceUVs = MeshData . RawMeshDescription - > VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
if ( InSettings . bReuseMeshLightmapUVs & & VertexInstanceUVs . GetNumElements ( ) > 0 & & VertexInstanceUVs . GetNumIndices ( ) > LightMapUVIndex )
2017-06-30 12:21:06 -04:00
{
MeshData . TextureCoordinateIndex = LightMapUVIndex ;
}
else
{
if ( ! UniqueTextureCoordinates . Num ( ) )
{
2019-01-07 05:38:46 -05:00
FMeshDescriptionOperations : : GenerateUniqueUVsForStaticMesh ( * MeshData . RawMeshDescription , MaterialOptions - > TextureSize . GetMax ( ) , false , UniqueTextureCoordinates ) ;
2017-06-30 12:21:06 -04:00
ScaleTextureCoordinatesToBox ( FBox2D ( FVector2D : : ZeroVector , FVector2D ( 1 , 1 ) ) , UniqueTextureCoordinates ) ;
}
MeshData . CustomTextureCoordinates = UniqueTextureCoordinates ;
}
}
MeshData . TextureCoordinateBox = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
MeshData . MaterialIndices = SectionIndices ;
MeshDataIndex = GlobalMeshSettings . Num ( ) ;
Adapters [ Key . GetMeshIndex ( ) ] . ApplySettings ( Key . GetLODIndex ( ) , MeshData ) ;
2018-03-06 13:26:20 -05:00
int32 ExistingMeshDataIndex = INDEX_NONE ;
auto MaterialsAreEquivalent = [ & InSettings ] ( const UMaterialInterface * Material0 , const UMaterialInterface * Material1 )
{
if ( InSettings . bMergeEquivalentMaterials )
{
return FMaterialKey ( Material0 ) = = FMaterialKey ( Material1 ) ;
}
else
{
return Material0 = = Material1 ;
}
} ;
// Find any existing materials
for ( int32 GlobalMaterialSettingsIndex = 0 ; GlobalMaterialSettingsIndex < GlobalMaterialSettings . Num ( ) ; + + GlobalMaterialSettingsIndex )
{
const FMaterialData & ExistingMaterialData = GlobalMaterialSettings [ GlobalMaterialSettingsIndex ] ;
// Compare materials (note this assumes property sizes match!)
if ( MaterialsAreEquivalent ( ExistingMaterialData . Material , MaterialData . Material ) )
{
// materials match, so check the corresponding mesh data
const FMeshData & ExistingMeshData = GlobalMeshSettings [ GlobalMaterialSettingsIndex ] ;
bool bMatchesMesh = ( ExistingMeshData . Mesh = = MeshData . Mesh & &
ExistingMeshData . MaterialIndices = = MeshData . MaterialIndices & &
ExistingMeshData . bMirrored = = MeshData . bMirrored & &
ExistingMeshData . VertexColorHash = = MeshData . VertexColorHash ) ;
if ( bMatchesMesh )
{
MeshDataIndex = ExistingMeshDataIndex = GlobalMaterialSettingsIndex ;
break ;
}
}
}
if ( ExistingMeshDataIndex = = INDEX_NONE )
{
GlobalMeshSettings . Add ( MeshData ) ;
GlobalMaterialSettings . Add ( MaterialData ) ;
SectionMaterialImportanceValues . Add ( MaterialImportanceValues [ MaterialIndex ] ) ;
}
2017-06-30 12:21:06 -04:00
}
else
{
2019-01-07 05:38:46 -05:00
MeshData . RawMeshDescription = nullptr ;
2017-06-30 12:21:06 -04:00
MeshData . TextureCoordinateBox = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
// This prevents baking out the same material multiple times, which would be wasteful when it does not use vertex data anyway
const bool bPreviouslyAdded = MaterialToDefaultMeshData . Contains ( Material ) ;
int32 & DefaultMeshDataIndex = MaterialToDefaultMeshData . FindOrAdd ( Material ) ;
if ( ! bPreviouslyAdded )
{
DefaultMeshDataIndex = GlobalMeshSettings . Num ( ) ;
GlobalMeshSettings . Add ( MeshData ) ;
GlobalMaterialSettings . Add ( MaterialData ) ;
2018-02-14 14:13:42 -05:00
SectionMaterialImportanceValues . Add ( MaterialImportanceValues [ MaterialIndex ] ) ;
2017-06-30 12:21:06 -04:00
}
MeshDataIndex = DefaultMeshDataIndex ;
}
for ( const uint32 & OriginalSectionIndex : SectionIndices )
{
OutputMaterialsMap . Add ( Key , MaterialRemapPair ( OriginalSectionIndex , MeshDataIndex ) ) ;
}
}
}
TArray < FMeshData * > MeshSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMeshSettings . Num ( ) ; + + SettingsIndex )
{
MeshSettingPtrs . Add ( & GlobalMeshSettings [ SettingsIndex ] ) ;
}
TArray < FMaterialData * > MaterialSettingPtrs ;
for ( int32 SettingsIndex = 0 ; SettingsIndex < GlobalMaterialSettings . Num ( ) ; + + SettingsIndex )
{
MaterialSettingPtrs . Add ( & GlobalMaterialSettings [ SettingsIndex ] ) ;
}
2018-05-23 21:04:31 -04:00
if ( bGloballyRemapUVs )
{
2019-01-07 05:38:46 -05:00
TArray < FMeshDescription > MergedRawMeshes ;
2018-05-23 21:04:31 -04:00
CreateMergedRawMeshes ( DataTracker , InSettings , StaticMeshComponentsToMerge , UniqueMaterials , CollapsedMaterialMap , OutputMaterialsMap , false , false , MergedAssetPivot , MergedRawMeshes ) ;
// Create texture coords for the merged mesh
TArray < FVector2D > GlobalTextureCoordinates ;
2019-01-07 05:38:46 -05:00
FMeshDescriptionOperations : : GenerateUniqueUVsForStaticMesh ( MergedRawMeshes [ 0 ] , MaterialOptions - > TextureSize . GetMax ( ) , true , GlobalTextureCoordinates ) ;
2018-05-23 21:04:31 -04:00
ScaleTextureCoordinatesToBox ( FBox2D ( FVector2D : : ZeroVector , FVector2D ( 1 , 1 ) ) , GlobalTextureCoordinates ) ;
// copy UVs back to the un-merged mesh's custom texture coords
// iterate the raw meshes in the same way as when we combined the mesh above in CreateMergedRawMeshes()
int32 GlobalUVIndex = 0 ;
for ( TConstRawMeshIterator RawMeshIterator = DataTracker . GetConstRawMeshIterator ( ) ; RawMeshIterator ; + + RawMeshIterator )
{
const FMeshLODKey & Key = RawMeshIterator . Key ( ) ;
2019-01-07 05:38:46 -05:00
const FMeshDescription & RawMesh = RawMeshIterator . Value ( ) ;
2018-05-23 21:04:31 -04:00
// Build a local array for this raw mesh
TArray < FVector2D > UniqueTextureCoordinates ;
2019-01-07 05:38:46 -05:00
UniqueTextureCoordinates . SetNumUninitialized ( RawMesh . VertexInstances ( ) . Num ( ) ) ;
2018-05-23 21:04:31 -04:00
for ( FVector2D & UniqueTextureCoordinate : UniqueTextureCoordinates )
{
UniqueTextureCoordinate = GlobalTextureCoordinates [ GlobalUVIndex + + ] ;
}
// copy to mesh data
for ( FMeshData & MeshData : GlobalMeshSettings )
{
2019-01-07 05:38:46 -05:00
if ( MeshData . RawMeshDescription = = & RawMesh )
2018-05-23 21:04:31 -04:00
{
MeshData . CustomTextureCoordinates = UniqueTextureCoordinates ;
}
}
}
// Dont smear borders as we will copy back non-pink pixels
for ( FMaterialData & MaterialData : GlobalMaterialSettings )
{
MaterialData . bPerformBorderSmear = false ;
}
}
2017-06-30 12:21:06 -04:00
TArray < FBakeOutput > BakeOutputs ;
IMaterialBakingModule & Module = FModuleManager : : Get ( ) . LoadModuleChecked < IMaterialBakingModule > ( " MaterialBaking " ) ;
Module . BakeMaterials ( MaterialSettingPtrs , MeshSettingPtrs , BakeOutputs ) ;
// Append constant properties ?
TArray < FColor > ConstantData ;
FIntPoint ConstantSize ( 1 , 1 ) ;
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( Entry . bUseConstantValue & & Entry . Property ! = MP_MAX )
2017-06-30 12:21:06 -04:00
{
ConstantData . SetNum ( 1 , false ) ;
ConstantData [ 0 ] = FLinearColor ( Entry . ConstantValue , Entry . ConstantValue , Entry . ConstantValue ) . ToFColor ( true ) ;
for ( FBakeOutput & Ouput : BakeOutputs )
{
Ouput . PropertyData . Add ( Entry . Property , ConstantData ) ;
Ouput . PropertySizes . Add ( Entry . Property , ConstantSize ) ;
}
}
}
TArray < FFlattenMaterial > FlattenedMaterials ;
ConvertOutputToFlatMaterials ( BakeOutputs , GlobalMaterialSettings , FlattenedMaterials ) ;
2018-05-23 21:04:31 -04:00
if ( ! bGloballyRemapUVs )
2017-06-30 12:21:06 -04:00
{
2018-05-23 21:04:31 -04:00
// Try to optimize materials where possible
for ( FFlattenMaterial & InMaterial : FlattenedMaterials )
{
FMaterialUtilities : : OptimizeFlattenMaterial ( InMaterial ) ;
}
2017-06-30 12:21:06 -04:00
}
FFlattenMaterial OutMaterial ;
for ( const FPropertyEntry & Entry : MaterialOptions - > Properties )
{
2017-09-11 10:43:35 -04:00
if ( Entry . Property ! = MP_MAX )
{
EFlattenMaterialProperties OldProperty = NewToOldProperty ( Entry . Property ) ;
OutMaterial . SetPropertySize ( OldProperty , Entry . bUseCustomSize ? Entry . CustomSize : MaterialOptions - > TextureSize ) ;
}
2017-06-30 12:21:06 -04:00
}
TArray < FUVOffsetScalePair > UVTransforms ;
2018-05-23 21:04:31 -04:00
if ( bGloballyRemapUVs )
2017-06-30 12:21:06 -04:00
{
2018-05-23 21:04:31 -04:00
// If we have globally remapped UVs we copy non-pink pixels over the dest texture rather than
// copying sub-charts
2017-06-30 12:21:06 -04:00
TArray < FBox2D > MaterialBoxes ;
2018-05-23 21:04:31 -04:00
MaterialBoxes . SetNumUninitialized ( GlobalMaterialSettings . Num ( ) ) ;
for ( FBox2D & Box2D : MaterialBoxes )
{
Box2D = FBox2D ( FVector2D ( 0.0f , 0.0f ) , FVector2D ( 1.0f , 1.0f ) ) ;
}
FlattenBinnedMaterials ( FlattenedMaterials , MaterialBoxes , 0 , true , OutMaterial , UVTransforms ) ;
2017-06-30 12:21:06 -04:00
}
else
{
2018-05-23 21:04:31 -04:00
/** Reweighting */
float TotalValue = 0.0f ;
for ( const float & Value : SectionMaterialImportanceValues )
{
TotalValue + = Value ;
}
float Multiplier = 1.0f / TotalValue ;
for ( float & Value : SectionMaterialImportanceValues )
{
Value * = Multiplier ;
}
/** End reweighting */
if ( InSettings . bUseTextureBinning )
{
TArray < FBox2D > MaterialBoxes ;
FMaterialUtilities : : GeneratedBinnedTextureSquares ( FVector2D ( 1.0f , 1.0f ) , SectionMaterialImportanceValues , MaterialBoxes ) ;
FlattenBinnedMaterials ( FlattenedMaterials , MaterialBoxes , InSettings . GutterSize , false , OutMaterial , UVTransforms ) ;
}
else
{
MergeFlattenedMaterials ( FlattenedMaterials , InSettings . GutterSize , OutMaterial , UVTransforms ) ;
}
2017-06-30 12:21:06 -04:00
}
2018-05-23 21:04:31 -04:00
2019-07-22 08:22:52 -04:00
// Compute UV channel to use for the merged material
if ( InSettings . bCreateMergedMaterial )
{
for ( TConstRawMeshIterator Iterator = DataTracker . GetConstRawMeshIterator ( ) ; Iterator ; + + Iterator )
{
const FMeshDescription & RawMesh = Iterator . Value ( ) ;
if ( RawMesh . Vertices ( ) . Num ( ) )
{
const TVertexInstanceAttributesRef < const FVector2D > VertexInstanceUVs = RawMesh . VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
MergedMatUVChannel = FMath : : Max ( MergedMatUVChannel , VertexInstanceUVs . GetNumIndices ( ) ) ;
}
}
}
2017-06-30 12:21:06 -04:00
// Adjust UVs
2018-03-06 13:26:20 -05:00
for ( int32 ComponentIndex = 0 ; ComponentIndex < StaticMeshComponentsToMerge . Num ( ) ; + + ComponentIndex )
2017-06-30 12:21:06 -04:00
{
2017-09-11 10:43:35 -04:00
TArray < uint32 > ProcessedMaterials ;
2017-06-30 12:21:06 -04:00
for ( TPair < FMeshLODKey , MaterialRemapPair > & MappingPair : OutputMaterialsMap )
{
2017-09-11 10:43:35 -04:00
if ( MappingPair . Key . GetMeshIndex ( ) = = ComponentIndex & & ! ProcessedMaterials . Contains ( MappingPair . Value . Key ) )
2017-06-30 12:21:06 -04:00
{
// Retrieve raw mesh data for this component and lod pair
2019-01-07 05:38:46 -05:00
FMeshDescription * RawMesh = DataTracker . GetRawMeshPtr ( MappingPair . Key ) ;
2017-06-30 12:21:06 -04:00
2018-03-06 13:26:20 -05:00
FMeshData & MeshData = GlobalMeshSettings [ MappingPair . Value . Value ] ;
2017-06-30 12:21:06 -04:00
const FUVOffsetScalePair & UVTransform = UVTransforms [ MappingPair . Value . Value ] ;
const uint32 MaterialIndex = MappingPair . Value . Key ;
2017-09-11 10:43:35 -04:00
ProcessedMaterials . Add ( MaterialIndex ) ;
2019-01-07 05:38:46 -05:00
if ( RawMesh - > Vertices ( ) . Num ( ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
TVertexInstanceAttributesRef < FVector2D > VertexInstanceUVs = RawMesh - > VertexInstanceAttributes ( ) . GetAttributesRef < FVector2D > ( MeshAttribute : : VertexInstance : : TextureCoordinate ) ;
int32 NumUVChannel = FMath : : Min ( VertexInstanceUVs . GetNumIndices ( ) , ( int32 ) MAX_MESH_TEXTURE_COORDS ) ;
for ( int32 UVChannelIdx = 0 ; UVChannelIdx < NumUVChannel ; + + UVChannelIdx )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
int32 VertexIndex = 0 ;
for ( FVertexInstanceID VertexInstanceID : RawMesh - > VertexInstances ( ) . GetElementIDs ( ) )
2018-03-06 13:26:20 -05:00
{
2019-01-07 05:38:46 -05:00
FVector2D UV = VertexInstanceUVs . Get ( VertexInstanceID , UVChannelIdx ) ;
2019-07-22 08:22:52 -04:00
if ( UVChannelIdx = = 0 & & ! InSettings . bCreateMergedMaterial )
2018-03-06 13:26:20 -05:00
{
2019-01-07 05:38:46 -05:00
if ( MeshData . CustomTextureCoordinates . Num ( ) )
{
UV = MeshData . CustomTextureCoordinates [ VertexIndex ] ;
}
else if ( MeshData . TextureCoordinateIndex ! = 0 )
{
check ( MeshData . TextureCoordinateIndex < NumUVChannel ) ;
UV = VertexInstanceUVs . Get ( VertexInstanceID , MeshData . TextureCoordinateIndex ) ;
}
2018-03-06 13:26:20 -05:00
}
2019-01-07 05:38:46 -05:00
const TArray < FPolygonID > & Polygons = RawMesh - > GetVertexInstanceConnectedPolygons ( VertexInstanceID ) ;
for ( FPolygonID PolygonID : Polygons )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
FPolygonGroupID PolygonGroupID = RawMesh - > GetPolygonPolygonGroup ( PolygonID ) ;
if ( PolygonGroupID . GetValue ( ) = = MaterialIndex )
2017-06-30 12:21:06 -04:00
{
if ( UVTransform . Value ! = FVector2D : : ZeroVector )
{
2019-01-07 05:38:46 -05:00
VertexInstanceUVs . Set ( VertexInstanceID , UVChannelIdx , UV * UVTransform . Value + UVTransform . Key ) ;
break ;
2017-06-30 12:21:06 -04:00
}
}
}
2019-01-07 05:38:46 -05:00
VertexIndex + + ;
2017-06-30 12:21:06 -04:00
}
}
2019-07-22 08:22:52 -04:00
if ( InSettings . bCreateMergedMaterial )
{
VertexInstanceUVs . SetNumIndices ( MergedMatUVChannel + 1 ) ;
int32 VertexIndex = 0 ;
for ( FVertexInstanceID VertexInstanceID : RawMesh - > VertexInstances ( ) . GetElementIDs ( ) )
{
FVector2D UV = MeshData . CustomTextureCoordinates [ VertexIndex ] ;
VertexInstanceUVs . Set ( VertexInstanceID , MergedMatUVChannel , UV * UVTransform . Value + UVTransform . Key ) ;
VertexIndex + + ;
}
}
2017-06-30 12:21:06 -04:00
}
}
}
}
for ( TRawMeshIterator Iterator = DataTracker . GetRawMeshIterator ( ) ; Iterator ; + + Iterator )
{
2019-01-07 05:38:46 -05:00
FMeshDescription & RawMesh = Iterator . Value ( ) ;
2017-06-30 12:21:06 -04:00
// Reset material indexes
2019-01-07 05:38:46 -05:00
TMap < FPolygonGroupID , FPolygonGroupID > RemapPolygonGroups ;
for ( FPolygonGroupID PolygonGroupID : RawMesh . PolygonGroups ( ) . GetElementIDs ( ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
RemapPolygonGroups . Add ( PolygonGroupID , FPolygonGroupID ( 0 ) ) ;
2017-06-30 12:21:06 -04:00
}
2019-01-07 05:38:46 -05:00
FMeshDescriptionOperations : : RemapPolygonGroups ( RawMesh , RemapPolygonGroups ) ;
2017-06-30 12:21:06 -04:00
}
2019-07-22 08:22:52 -04:00
OutMaterial . UVChannel = MergedMatUVChannel ;
MergedMaterial = CreateProxyMaterial ( InBasePackageName , MergedAssetPackageName , InBaseMaterial , InOuter , InSettings , OutMaterial , OutAssetsToSync ) ;
if ( ! InSettings . bCreateMergedMaterial )
{
UniqueMaterials . Empty ( 1 ) ;
UniqueMaterials . Add ( MergedMaterial ) ;
FSectionInfo NewSection ;
NewSection . Material = MergedMaterial ;
NewSection . EnabledProperties . Add ( GET_MEMBER_NAME_CHECKED ( FStaticMeshSection , bCastShadow ) ) ;
DataTracker . AddBakedMaterialSection ( NewSection ) ;
}
2018-03-06 13:26:20 -05:00
for ( IMeshMergeExtension * Extension : MeshMergeExtensions )
{
Extension - > OnCreatedProxyMaterial ( StaticMeshComponentsToMerge , MergedMaterial ) ;
}
2017-06-30 12:21:06 -04:00
}
2019-01-07 05:38:46 -05:00
TArray < FMeshDescription > MergedRawMeshes ;
2019-07-22 08:22:52 -04:00
CreateMergedRawMeshes ( DataTracker , InSettings , StaticMeshComponentsToMerge , UniqueMaterials , CollapsedMaterialMap , OutputMaterialsMap , bMergeAllLODs , bMergeMaterialData & & ! InSettings . bCreateMergedMaterial , MergedAssetPivot , MergedRawMeshes ) ;
2018-03-06 13:26:20 -05:00
2017-06-30 12:21:06 -04:00
// Populate mesh section map
FMeshSectionInfoMap SectionInfoMap ;
for ( TConstLODIndexIterator Iterator = DataTracker . GetLODIndexIterator ( ) ; Iterator ; + + Iterator )
{
const int32 LODIndex = * Iterator ;
TArray < uint32 > UniqueMaterialIndices ;
2019-01-07 05:38:46 -05:00
const FMeshDescription & TargetRawMesh = MergedRawMeshes [ LODIndex ] ;
uint32 MaterialIndex = 0 ;
for ( FPolygonGroupID PolygonGroupID : TargetRawMesh . PolygonGroups ( ) . GetElementIDs ( ) )
2017-06-30 12:21:06 -04:00
{
2019-01-07 05:38:46 -05:00
//Skip empty group
if ( TargetRawMesh . GetPolygonGroupPolygons ( PolygonGroupID ) . Num ( ) > 0 )
{
if ( PolygonGroupID . GetValue ( ) < DataTracker . NumberOfUniqueSections ( ) )
{
UniqueMaterialIndices . AddUnique ( PolygonGroupID . GetValue ( ) ) ;
}
else
{
UniqueMaterialIndices . AddUnique ( MaterialIndex ) ;
}
MaterialIndex + + ;
}
2017-06-30 12:21:06 -04:00
}
2018-04-05 09:26:01 -04:00
UniqueMaterialIndices . Sort ( ) ;
2017-06-30 12:21:06 -04:00
for ( int32 Index = 0 ; Index < UniqueMaterialIndices . Num ( ) ; + + Index )
{
const int32 SectionIndex = UniqueMaterialIndices [ Index ] ;
const FSectionInfo & StoredSectionInfo = DataTracker . GetSection ( SectionIndex ) ;
FMeshSectionInfo SectionInfo ;
SectionInfo . bCastShadow = StoredSectionInfo . EnabledProperties . Contains ( GET_MEMBER_NAME_CHECKED ( FMeshSectionInfo , bCastShadow ) ) ;
SectionInfo . bEnableCollision = StoredSectionInfo . EnabledProperties . Contains ( GET_MEMBER_NAME_CHECKED ( FMeshSectionInfo , bEnableCollision ) ) ;
SectionInfo . MaterialIndex = UniqueMaterials . IndexOfByKey ( StoredSectionInfo . Material ) ;
SectionInfoMap . Set ( LODIndex , Index , SectionInfo ) ;
}
}
2019-07-22 08:22:52 -04:00
if ( InSettings . bCreateMergedMaterial )
{
OutputMaterialsMap . Reset ( ) ;
}
2017-06-30 12:21:06 -04:00
// Transform physics primitives to merged mesh pivot
if ( InSettings . bMergePhysicsData & & ! MergedAssetPivot . IsZero ( ) )
{
FTransform PivotTM ( - MergedAssetPivot ) ;
for ( FKAggregateGeom & Geometry : PhysicsGeometry )
{
Copying //UE4/Dev-Physics to //UE4/Dev-Main (Source: //UE4/Dev-Physics @ 4242698)
#rb none
#lockdown Nick.Penwarden
============================
MAJOR FEATURES & CHANGES
============================
Change 4023283 by Michael.Lentine
Fix memory leak.
Change 4024243 by Michael.Lentine
Add debugging output code from github #4533.
#jira ue-55764
Change 4026362 by Michael.Lentine
Merged github #3704.
#jira ue-463394
Change 4026545 by Michael.Lentine
Fix ordering of collision settings changed callback
#jira ue-50475
Change 4026609 by Michael.Lentine
Fix crash in destruction for when world is not valid
#jira ue-53989
Change 4026786 by Michael.Lentine
Merging github #4632 to fix memory leak.
#jira ue-57255
Change 4027293 by Michael.Lentine
Integrate github #4338.
#jira ue-53497
Change 4033517 by Michael.Lentine
Fix collision body creation for spline merging.
#jira ue-53956
Change 4039750 by Michael.Lentine
Add basic error message if cooking fails.
Change 4040210 by Michael.Lentine
Check for nullptr
Change 4098887 by Michael.Lentine
Fix warnings.
Change 4103511 by Michael.Lentine
Prevent crash when BodyInstance is invalid.
Change 4117826 by Michael.Lentine
Fix check for body being fixed.
Change 4122307 by Benn.Gallagher
PS4/clang build fixes
Change 4124479 by Benn.Gallagher
Fix non-portable filename used as an include (Linux editor build CIS error)
Change 4125450 by Benn.Gallagher
Fixup Ocean
Change 4127210 by Michael.Lentine
Update the PreviousBoneTransforms array when setting transforms in DestructibleComponent
#jira ue-58813
Change 4127309 by Benn.Gallagher
Fix Win32 shipping builds
Change 4134570 by Michael.Lentine
Missed fixes for WITH_UEPHYSICS.
Change 4134585 by Michael.Lentine
Missed a few more files.
Change 4134670 by Michael.Lentine
Update formatting.
Change 4134671 by Michael.Lentine
More formatting.
Change 4150615 by Benn.Gallagher
Moved immediate mode into engine, as it is now depended on by the physics engine.
Change 4150680 by Benn.Gallagher
Missed file
Change 4150980 by Benn.Gallagher
Rename kinematic target for immediate mode to avoid ambiguous symbols in engine
Change 4151400 by Brice.Criswell
Apeiron
Levelset initilization issue.
----
Change 4157880 by Benn.Gallagher
More fixing unresolved template specialisations for FN editor.
Change 4159128 by Michael.Lentine
Compile fixes
Change 4159786 by Brice.Criswell
Apeiron
Levelset curvature initialization fix, clamps out of bounds phi values to phi[i].
------
Change 4160382 by Michael.Lentine
Fix node initialization
Change 4160463 by Brice.Criswell
Apeiron
Levelset index fix.
----
Change 4161425 by Benn.Gallagher
Added package, class and struct redirects for moving immediate physics into engine.
Change 4164195 by Brice.Criswell
GeometryCollection : Code review updates
- Removed typedef for GeometryCollection::ManagedArray<T>
- Renamed Enumerations to begin with E prefix, retyped to be uint8.
- Removed EArrayScoipe::FScopeNone, now defautls to FScopeShared
- Formatted type modifiers to follow UE4 coding standard.
- Derived the ManagedArrayBase from FNonCopyable
- Disabled TManagedArrays copy constructor and assignment operator.
- Converted most accessors on GeometryCollection to TSharedRef.
- Added .inl style definitions to simplify the management of the ManagedArrayTypes
-----
Change 4164235 by Brice.Criswell
GeometryCollection : Added New Files
- Added the ManagedArrayTypes files.
----
Change 4164309 by Brice.Criswell
GeometryCollection :
Moved the initialization of the RigidBodyIdArray and CenterOfMassArray into the WITH_APEIRON definition.
-----
Change 4166133 by Brice.Criswell
GeometryCollection
Added GeometryCollectionEdit class to protect access to the rest and dynamic collections.
-----
Change 4171540 by Michael.Lentine
Fix reset
#robomerge destruction
Change 4171912 by Michael.Lentine
Rename BVHParticles
#robomerge destruction
Change 4172445 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4172623 by Brice.Criswell
GeometryCollection
Debugging ToString to inspect the GeometryCollection
----
Change 4172711 by Michael.Lentine
Add Immediate Path to Geometry Collection
Change 4172778 by Michael.Lentine
Update LL Interface to use Simulation type.
#robomerge destruction
Change 4172780 by Michael.Lentine
Missed files
#robomerge destruction
Change 4173238 by Benn.Gallagher
Missed file from last checkin
Change 4173554 by Benn.Gallagher
Few extra changes for const correctness and actor counts
Change 4174153 by Benn.Gallagher
Fixed non-unity build issue from Geom Collection.
Change 4175355 by Brice.Criswell
GeometryCollection
Separated the GeometryCollection from USE_APEIRON flag.
-----
Change 4175533 by Brice.Criswell
GeometryCollection
Defaulting Aperion to off.
-----
Change 4175761 by Michael.Lentine
Fix collisions.
Change 4177105 by Benn.Gallagher
Another geom collection CIS fix when running without PCHs
Change 4177796 by Brice.Criswell
GeometryCollection
- Added parenting function to manage the BoneHierarchy Array
- Split collection along yz-plane.
-----
Change 4177989 by Brice.Criswell
GeometryCollection
- Moved Hierarchy and Transform array elements into base class TransformCollection
- Renamed ParticleGroup to TransformGroup.
-----
Change 4178826 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4178840 by Brice.Criswell
Geometry Collection
Removed FORCEINLINE from GeometryCollectionEdit.GetRestCollection
----
Change 4179493 by Brice.Criswell
GeometryCollection
New icons.
-----
Change 4182428 by Brice.Criswell
Build Configuration
Apeiron configuration.
- Modified bCompileApeiron to enable the compilation of the Apeiron plugin.
- Added bUseApeiron to enable Apeiron in the physics interfaces.
Changed PhysScene_Apeiron to enable when bCompileApeiron is enabled.
Disabled the GeometryCollection* Plugins in the build.
-------
Change 4185886 by Brice.Criswell
GeometryCollection
Renaming TransformGroup.
---
Change 4186389 by michael.lentine
Don't create in parallel for immediate mode.
Change 4186457 by michael.lentine
Hack to prevent crashing when Visible is nullptr.
Change 4198872 by Brice.Criswell
Apeiron
Clustering changes
- Clustering based on hierarchy's defined within the Geometry Collection
-----
Change 4199861 by Brice.Criswell
GeometryCollection
Disable Apeiron in the Collection.
------
Change 4200089 by Brice.Criswell
GeometryCollection
Updated to enable Apeiron in the GeometryCollection when the bCompileAperion flag is enabled in the UnrealBuildTool.
---
Change 4200333 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
-----
Change 4202231 by Michael.Lentine
Disable collisions between adjacent bodies connected by a joint. This typically would be specified by an artist but classic PhysX always does this uncondintionally so our clients are used to this.
Change 4202748 by Michael.Lentine
Fix 2015 compile.
Change 4204528 by Michael.Lentine
Disable Apeiron.
Change 4206396 by Michael.Lentine
Fix 2015 build. Static cast apparently is not an accetible conversion from uint32 to bool.
#robomerge destruction
Change 4206604 by Michael.Lentine
Fix for using ccd and kinematic.
#jira UE-61694
#robomerge destruction
Change 4206711 by mason.seay
Refreshed Set Angular Drive nodes to clear out orphan pins
Change 4207286 by Brice.Criswell
GeometryCollection
Transform hierarchy evaluation within BoneHierarchy of the Collection.
Parenting operations are implemented on an updated morphology using :
ParentTransforms(UGeometryCollection* GeometryCollection, const int32 InsertAtIndex, const TArray<int32>& SelectedBones);
To parent a new transform:
int32 RootIndex << within len( TransformGroup ) or -1 for a non-parented node.
int32 BoneIndex = Collection->AddElements(1, UGeometryCollection::TransformGroup);
GeometryCollectionAlgo::ParentTransform(Collection, RootIndex, BoneIndex);
Transform[BoneIndex] = <some transform within local space of the RootIndex>
Default collections have all geometry not parented. The function EnsureSingleRoot was added to guarantee that the collection has at least one parent node.
FGeometryCollectionCommands::EnsureSinglRoot(UGeometryCollection* RestCollection)
Then matrices relative to the collections root are calculated using:
GlobalMatrices(UGeometryCollection* GeometryCollection, TArray<FTransform> & Transforms);
Added Damage Threshold to GeometryCollectionActor
------
Change 4208039 by Brice.Criswell
GeometryCollection
Fix for static include failure.
---
Change 4208170 by Brice.Criswell
GeometryCache
SplitAlongYZ to support multiple levels and orientations.
---
Change 4208174 by Michael.Lentine
Avoid shadow warnings and switch logs to verbose instead of warnings.
#robomerge destruction
Change 4210255 by Benn.Gallagher
Static analysis fixes
Change 4210394 by Michael.Lentine
Use correct particle type for updateconstraints.
Change 4211153 by Brice.Criswell
Apeiron
Exposing friction and coefficient of restitution to the actor.
-----
Change 4213034 by michael.lentine
Rename bounding volume
Change 4216783 by Michael.Lentine
Committing cooking fix to Dev-Physics in order to get smoke tests running.
Change 4218078 by Benn.Gallagher
Fixed memory and TLS slot leak caused by previous change to physics scene cleanup while cooking
#jira UE-61633
Change 4219206 by Michael.Lentine
Use the adaptor to get the rotation.
#jira ue-61748
Change 4220469 by Benn.Gallagher
Fixed overlaps re-triggering on movement due to bad transform chaining from component to phys actor to shape
#jira UE-61703
Change 4220538 by Benn.Gallagher
Fixed PhysX errors when setting global transforms of kinematic and static objects.
#jira none
Change 4222138 by Michael.Lentine
Update use of Vulkan on android.
Change 4222139 by Michael.Lentine
Update OculusHMD plugin to use correct vulkan search path.
Change 4225740 by Michael.Lentine
Integrate changes to update rotation and mass.
Change 4225928 by michael.lentine
Use more accurate collision point.
Change 4226560 by michael.lentine
Enable contact graph
Change 4227397 by Michael.Lentine
If we don't have a global scene we need to not detect collisions.
#robomerge destruction
Change 4227410 by Michael.Lentine
Missing include
#robomerge destruction
Change 4228107 by Michael.Lentine
Integrate static contact changes.
Change 4228612 by michael.lentine
Use more correct thresholding.
Change 4228734 by Benn.Gallagher
Getting LLImmediate high level stood up and simulating
Implementation is incomplete, only what is required to get simple scenes simulating under immediate mode
Change 4228748 by Benn.Gallagher
Missed file from checkin
Change 4228885 by Ori.Cohen
Added base physics interface class to help provide default behavior and easily chain functionality together
Change 4228992 by Ori.Cohen
Fix cis
Change 4229921 by Benn.Gallagher
Fixed contact pre-filter performance regression
Change 4230825 by Benn.Gallagher
Moved WIP physics interfaces to Experimental/ folders
Change 4230853 by Benn.Gallagher
Fixup includes after moving WIP physics interfaces
Change 4231414 by Michael.Lentine
Use global namespace to avoid mac compile errors.
#jira ue-62137
[CL 4242847 by Michael Lentine in Main branch]
2018-07-31 02:23:26 -04:00
FMeshMergeHelpers : : TransformPhysicsGeometry ( PivotTM , false , Geometry ) ;
2017-06-30 12:21:06 -04:00
}
}
// Compute target lightmap channel for each LOD, by looking at the first empty UV channel
const int32 LightMapUVChannel = [ & ] ( )
{
if ( InSettings . bGenerateLightMapUV )
{
const int32 TempChannel = DataTracker . GetAvailableLightMapUVChannel ( ) ;
if ( TempChannel ! = INDEX_NONE )
{
return TempChannel ;
}
else
{
// Output warning message
UE_LOG ( LogMeshMerging , Log , TEXT ( " Failed to find available lightmap uv channel " ) ) ;
}
}
return 0 ;
} ( ) ;
//
//Create merged mesh asset
//
{
FString AssetName ;
FString PackageName ;
if ( InBasePackageName . IsEmpty ( ) )
{
AssetName = TEXT ( " SM_MERGED_ " ) + FPackageName : : GetShortName ( MergedAssetPackageName ) ;
PackageName = FPackageName : : GetLongPackagePath ( MergedAssetPackageName ) + TEXT ( " / " ) + AssetName ;
}
else
{
AssetName = FPackageName : : GetShortName ( InBasePackageName ) ;
PackageName = InBasePackageName ;
}
UPackage * Package = InOuter ;
if ( Package = = nullptr )
{
Package = CreatePackage ( NULL , * PackageName ) ;
check ( Package ) ;
Package - > FullyLoad ( ) ;
Package - > Modify ( ) ;
}
2018-05-23 21:04:31 -04:00
FStaticMeshComponentRecreateRenderStateContext RecreateRenderStateContext ( FindObject < UStaticMesh > ( Package , * AssetName ) ) ;
2017-06-30 12:21:06 -04:00
UStaticMesh * StaticMesh = NewObject < UStaticMesh > ( Package , * AssetName , RF_Public | RF_Standalone ) ;
StaticMesh - > InitResources ( ) ;
FString OutputPath = StaticMesh - > GetPathName ( ) ;
// make sure it has a new lighting guid
StaticMesh - > LightingGuid = FGuid : : NewGuid ( ) ;
if ( InSettings . bGenerateLightMapUV )
{
StaticMesh - > LightMapResolution = InSettings . TargetLightMapResolution ;
StaticMesh - > LightMapCoordinateIndex = LightMapUVChannel ;
}
2019-08-21 09:52:37 -04:00
const bool bContainsImposters = ImposterComponents . Num ( ) > 0 ;
2018-03-06 13:26:20 -05:00
TArray < UMaterialInterface * > ImposterMaterials ;
2018-05-23 21:04:31 -04:00
FBox ImposterBounds ( EForceInit : : ForceInit ) ;
2017-06-30 12:21:06 -04:00
for ( int32 LODIndex = 0 ; LODIndex < MergedRawMeshes . Num ( ) ; + + LODIndex )
2019-01-07 05:38:46 -05:00
{
FMeshDescription & MergedMeshLOD = MergedRawMeshes [ LODIndex ] ;
2019-08-21 09:52:37 -04:00
if ( MergedMeshLOD . Vertices ( ) . Num ( ) > 0 | | bContainsImposters )
2017-06-30 12:21:06 -04:00
{
2018-03-05 10:06:09 -05:00
FStaticMeshSourceModel & SrcModel = StaticMesh - > AddSourceModel ( ) ;
2019-08-22 22:43:55 -04:00
2017-06-30 12:21:06 -04:00
// Don't allow the engine to recalculate normals
2018-03-05 10:06:09 -05:00
SrcModel . BuildSettings . bRecomputeNormals = false ;
SrcModel . BuildSettings . bRecomputeTangents = false ;
SrcModel . BuildSettings . bRemoveDegenerates = false ;
SrcModel . BuildSettings . bUseHighPrecisionTangentBasis = false ;
SrcModel . BuildSettings . bUseFullPrecisionUVs = false ;
SrcModel . BuildSettings . bGenerateLightmapUVs = InSettings . bGenerateLightMapUV ;
SrcModel . BuildSettings . MinLightmapResolution = InSettings . bComputedLightMapResolution ? DataTracker . GetLightMapDimension ( ) : InSettings . TargetLightMapResolution ;
SrcModel . BuildSettings . SrcLightmapIndex = 0 ;
SrcModel . BuildSettings . DstLightmapIndex = LightMapUVChannel ;
2018-05-23 21:04:31 -04:00
if ( ! InSettings . bAllowDistanceField )
{
SrcModel . BuildSettings . DistanceFieldResolutionScale = 0.0f ;
}
2017-06-30 12:21:06 -04:00
2018-03-06 13:26:20 -05:00
if ( bContainsImposters )
{
// Merge imposter meshes to rawmesh
2018-05-23 21:04:31 -04:00
FMeshMergeHelpers : : MergeImpostersToRawMesh ( ImposterComponents , MergedMeshLOD , MergedAssetPivot , UniqueMaterials . Num ( ) , ImposterMaterials ) ;
const FTransform PivotTransform = FTransform ( MergedAssetPivot ) ;
for ( const UStaticMeshComponent * Component : ImposterComponents )
{
if ( Component - > GetStaticMesh ( ) )
{
ImposterBounds + = Component - > GetStaticMesh ( ) - > GetBoundingBox ( ) . TransformBy ( Component - > GetComponentToWorld ( ) . GetRelativeTransform ( PivotTransform ) ) ;
}
}
2018-03-06 13:26:20 -05:00
}
2019-08-22 22:43:55 -04:00
2019-10-01 20:41:42 -04:00
FMeshDescription * MeshDescription = StaticMesh - > CreateMeshDescription ( LODIndex , MergedMeshLOD ) ;
2019-01-07 05:38:46 -05:00
StaticMesh - > CommitMeshDescription ( LODIndex ) ;
2017-06-30 12:21:06 -04:00
}
}
2018-04-03 18:35:54 -04:00
auto IsMaterialImportedNameUnique = [ & StaticMesh ] ( FName ImportedMaterialSlotName )
{
for ( const FStaticMaterial & StaticMaterial : StaticMesh - > StaticMaterials )
{
# if WITH_EDITOR
if ( StaticMaterial . ImportedMaterialSlotName = = ImportedMaterialSlotName )
# else
if ( StaticMaterial . MaterialSlotName = = ImportedMaterialSlotName )
# endif
{
return false ;
}
}
return true ;
} ;
2017-06-30 12:21:06 -04:00
for ( UMaterialInterface * Material : UniqueMaterials )
{
if ( Material & & ( ! Material - > IsAsset ( ) & & InOuter ! = GetTransientPackage ( ) ) )
{
Material = nullptr ; // do not save non-asset materials
}
2018-04-03 18:35:54 -04:00
//Make sure we have unique slot name here
FName MaterialSlotName = DataTracker . GetMaterialSlotName ( Material ) ;
int32 Counter = 1 ;
while ( ! IsMaterialImportedNameUnique ( MaterialSlotName ) )
{
MaterialSlotName = * ( DataTracker . GetMaterialSlotName ( Material ) . ToString ( ) + TEXT ( " _ " ) + FString : : FromInt ( Counter + + ) ) ;
}
StaticMesh - > StaticMaterials . Add ( FStaticMaterial ( Material , MaterialSlotName ) ) ;
2017-06-30 12:21:06 -04:00
}
2018-03-06 13:26:20 -05:00
for ( UMaterialInterface * ImposterMaterial : ImposterMaterials )
{
2018-04-03 18:35:54 -04:00
//Make sure we have unique slot name here
FName MaterialSlotName = ImposterMaterial - > GetFName ( ) ;
int32 Counter = 1 ;
while ( ! IsMaterialImportedNameUnique ( MaterialSlotName ) )
{
MaterialSlotName = * ( ImposterMaterial - > GetName ( ) + TEXT ( " _ " ) + FString : : FromInt ( Counter + + ) ) ;
}
StaticMesh - > StaticMaterials . Add ( FStaticMaterial ( ImposterMaterial , MaterialSlotName ) ) ;
2018-03-06 13:26:20 -05:00
}
2017-06-30 12:21:06 -04:00
if ( InSettings . bMergePhysicsData )
{
StaticMesh - > CreateBodySetup ( ) ;
if ( BodySetupSource )
{
StaticMesh - > BodySetup - > CopyBodyPropertiesFrom ( BodySetupSource ) ;
}
StaticMesh - > BodySetup - > AggGeom = FKAggregateGeom ( ) ;
// Copy collision from the source meshes
for ( const FKAggregateGeom & Geom : PhysicsGeometry )
{
StaticMesh - > BodySetup - > AddCollisionFrom ( Geom ) ;
}
// Bake rotation into verts of convex hulls, so they scale correctly after rotation
for ( FKConvexElem & ConvexElem : StaticMesh - > BodySetup - > AggGeom . ConvexElems )
{
ConvexElem . BakeTransformToVerts ( ) ;
}
}
2019-07-31 03:40:45 -04:00
StaticMesh - > GetSectionInfoMap ( ) . CopyFrom ( SectionInfoMap ) ;
StaticMesh - > GetOriginalSectionInfoMap ( ) . CopyFrom ( SectionInfoMap ) ;
2017-06-30 12:21:06 -04:00
//Set the Imported version before calling the build
StaticMesh - > ImportVersion = EImportStaticMeshVersion : : LastVersion ;
2017-09-11 10:43:35 -04:00
StaticMesh - > LightMapResolution = InSettings . bComputedLightMapResolution ? DataTracker . GetLightMapDimension ( ) : InSettings . TargetLightMapResolution ;
2017-06-30 12:21:06 -04:00
2019-05-15 09:30:49 -04:00
# if WITH_EDITOR
//If we are running the automation test
if ( GIsAutomationTesting )
{
StaticMesh - > BuildCacheAutomationTestGuid = FGuid : : NewGuid ( ) ;
}
# endif
2017-06-30 12:21:06 -04:00
StaticMesh - > Build ( bSilent ) ;
2018-05-23 21:04:31 -04:00
if ( ImposterBounds . IsValid )
{
const FBox StaticMeshBox = StaticMesh - > GetBoundingBox ( ) ;
const FBox CombinedBox = StaticMeshBox + ImposterBounds ;
StaticMesh - > PositiveBoundsExtension = ( CombinedBox . Max - StaticMeshBox . Max ) ;
StaticMesh - > NegativeBoundsExtension = ( StaticMeshBox . Min - CombinedBox . Min ) ;
StaticMesh - > CalculateExtendedBounds ( ) ;
}
2017-06-30 12:21:06 -04:00
StaticMesh - > PostEditChange ( ) ;
2019-07-22 08:22:52 -04:00
if ( InSettings . bCreateMergedMaterial )
{
//Make sure we have unique slot name here
FName MaterialSlotName = MergedMaterial - > GetFName ( ) ;
int32 Counter = 1 ;
while ( ! IsMaterialImportedNameUnique ( MaterialSlotName ) )
{
MaterialSlotName = * ( MergedMaterial - > GetName ( ) + TEXT ( " _ " ) + FString : : FromInt ( Counter + + ) ) ;
}
StaticMesh - > StaticMaterials . Add ( FStaticMaterial ( MergedMaterial , MaterialSlotName ) ) ;
StaticMesh - > UpdateUVChannelData ( false ) ;
}
2017-06-30 12:21:06 -04:00
OutAssetsToSync . Add ( StaticMesh ) ;
OutMergedActorLocation = MergedAssetPivot ;
}
2018-05-23 21:04:31 -04:00
}
2017-06-30 12:21:06 -04:00
2019-05-30 10:37:45 -04:00
void FMeshMergeUtilities : : ExtractImposterToRawMesh ( const UStaticMeshComponent * InImposterComponent , FMeshDescription & InImposterMesh ) const
{
check ( InImposterComponent - > bUseMaxLODAsImposter ) ;
FMeshMergeHelpers : : ExtractImposterToRawMesh ( InImposterComponent , InImposterMesh ) ;
}
2019-01-07 05:38:46 -05:00
void FMeshMergeUtilities : : CreateMergedRawMeshes ( FMeshMergeDataTracker & InDataTracker , const FMeshMergingSettings & InSettings , const TArray < UStaticMeshComponent * > & InStaticMeshComponentsToMerge , const TArray < UMaterialInterface * > & InUniqueMaterials , const TMap < UMaterialInterface * , UMaterialInterface * > & InCollapsedMaterialMap , const TMultiMap < FMeshLODKey , MaterialRemapPair > & InOutputMaterialsMap , bool bInMergeAllLODs , bool bInMergeMaterialData , const FVector & InMergedAssetPivot , TArray < FMeshDescription > & OutMergedRawMeshes ) const
2018-05-23 21:04:31 -04:00
{
2019-10-04 13:11:45 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FMeshMergeUtilities : : CreateMergedRawMeshes )
2018-05-23 21:04:31 -04:00
if ( bInMergeAllLODs )
{
OutMergedRawMeshes . AddDefaulted ( InDataTracker . GetNumLODsForMergedMesh ( ) ) ;
for ( TConstLODIndexIterator Iterator = InDataTracker . GetLODIndexIterator ( ) ; Iterator ; + + Iterator )
{
// Find meshes for each lod
const int32 LODIndex = * Iterator ;
2019-01-07 05:38:46 -05:00
FMeshDescription & MergedMesh = OutMergedRawMeshes [ LODIndex ] ;
2019-10-01 20:41:42 -04:00
FStaticMeshAttributes ( MergedMesh ) . Register ( ) ;
2019-01-07 05:38:46 -05:00
2018-05-23 21:04:31 -04:00
for ( int32 ComponentIndex = 0 ; ComponentIndex < InStaticMeshComponentsToMerge . Num ( ) ; + + ComponentIndex )
{
int32 RetrievedLODIndex = LODIndex ;
2019-01-07 05:38:46 -05:00
FMeshDescription * RawMeshPtr = InDataTracker . TryFindRawMeshForLOD ( ComponentIndex , RetrievedLODIndex ) ;
2018-05-23 21:04:31 -04:00
if ( RawMeshPtr ! = nullptr )
{
2019-01-07 05:38:46 -05:00
InDataTracker . AddComponentToWedgeMapping ( ComponentIndex , LODIndex , MergedMesh . VertexInstances ( ) . Num ( ) ) ;
2018-05-23 21:04:31 -04:00
2019-01-07 05:38:46 -05:00
FMeshDescriptionOperations : : FAppendSettings AppendSettings ;
AppendSettings . PolygonGroupsDelegate = FAppendPolygonGroupsDelegate : : CreateLambda ( [ & bInMergeMaterialData , & InDataTracker , & InOutputMaterialsMap , & ComponentIndex , & LODIndex ] ( const FMeshDescription & SourceMesh , FMeshDescription & TargetMesh , PolygonGroupMap & RemapPolygonGroups )
{
TPolygonGroupAttributesConstRef < FName > SourceImportedMaterialSlotNames = SourceMesh . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
TPolygonGroupAttributesRef < FName > TargetImportedMaterialSlotNames = TargetMesh . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
//Copy the polygon group
if ( bInMergeMaterialData )
{
FPolygonGroupID PolygonGroupID ( 0 ) ;
if ( ! TargetMesh . PolygonGroups ( ) . IsValid ( PolygonGroupID ) )
{
TargetMesh . CreatePolygonGroupWithID ( PolygonGroupID ) ;
TargetImportedMaterialSlotNames [ PolygonGroupID ] = SourceMesh . PolygonGroups ( ) . IsValid ( PolygonGroupID ) ? SourceImportedMaterialSlotNames [ PolygonGroupID ] : FName ( TEXT ( " DefaultMaterialName " ) ) ;
}
for ( FPolygonGroupID SourcePolygonGroupID : SourceMesh . PolygonGroups ( ) . GetElementIDs ( ) )
{
RemapPolygonGroups . Add ( SourcePolygonGroupID , PolygonGroupID ) ;
}
}
else
{
TArray < SectionRemapPair > SectionMappings ;
InDataTracker . GetMappingsForMeshLOD ( FMeshLODKey ( ComponentIndex , LODIndex ) , SectionMappings ) ;
for ( FPolygonGroupID SourcePolygonGroupID : SourceMesh . PolygonGroups ( ) . GetElementIDs ( ) )
{
// First map from original section index to unique material index
int32 UniqueIndex = INDEX_NONE ;
// then map to the output material map, if any
if ( InOutputMaterialsMap . Num ( ) > 0 )
{
TArray < MaterialRemapPair > MaterialMappings ;
InOutputMaterialsMap . MultiFind ( FMeshLODKey ( ComponentIndex , LODIndex ) , MaterialMappings ) ;
for ( MaterialRemapPair & Pair : MaterialMappings )
{
if ( Pair . Key = = SourcePolygonGroupID . GetValue ( ) )
{
UniqueIndex = Pair . Value ;
break ;
}
}
// Note that at this point UniqueIndex is NOT a material index, but a unique section index!
}
2019-03-25 14:06:35 -04:00
if ( UniqueIndex = = INDEX_NONE )
2019-01-07 05:38:46 -05:00
{
UniqueIndex = SourcePolygonGroupID . GetValue ( ) ;
}
FPolygonGroupID TargetPolygonGroupID ( UniqueIndex ) ;
if ( ! TargetMesh . PolygonGroups ( ) . IsValid ( TargetPolygonGroupID ) )
{
while ( TargetMesh . PolygonGroups ( ) . Num ( ) < = UniqueIndex )
{
TargetPolygonGroupID = TargetMesh . CreatePolygonGroup ( ) ;
}
check ( TargetPolygonGroupID . GetValue ( ) = = UniqueIndex ) ;
TargetImportedMaterialSlotNames [ TargetPolygonGroupID ] = SourceImportedMaterialSlotNames [ SourcePolygonGroupID ] ;
}
RemapPolygonGroups . Add ( SourcePolygonGroupID , TargetPolygonGroupID ) ;
}
}
} ) ;
AppendSettings . bMergeVertexColor = InSettings . bBakeVertexDataToMesh ;
AppendSettings . MergedAssetPivot = InMergedAssetPivot ;
FMeshDescriptionOperations : : AppendMeshDescription ( * RawMeshPtr , MergedMesh , AppendSettings ) ;
}
}
2019-03-07 11:58:41 -05:00
//Cleanup the empty material to avoid empty section later
TArray < FPolygonGroupID > PolygonGroupToRemove ;
for ( FPolygonGroupID PolygonGroupID : MergedMesh . PolygonGroups ( ) . GetElementIDs ( ) )
{
if ( MergedMesh . GetPolygonGroupPolygons ( PolygonGroupID ) . Num ( ) < 1 )
{
PolygonGroupToRemove . Add ( PolygonGroupID ) ;
}
}
for ( FPolygonGroupID PolygonGroupID : PolygonGroupToRemove )
{
MergedMesh . DeletePolygonGroup ( PolygonGroupID ) ;
}
2019-01-07 05:38:46 -05:00
}
}
else
{
2019-10-01 20:41:42 -04:00
FMeshDescription & MergedMesh = OutMergedRawMeshes . AddDefaulted_GetRef ( ) ;
FStaticMeshAttributes ( MergedMesh ) . Register ( ) ;
2019-01-07 05:38:46 -05:00
for ( int32 ComponentIndex = 0 ; ComponentIndex < InStaticMeshComponentsToMerge . Num ( ) ; + + ComponentIndex )
{
int32 LODIndex = 0 ;
FMeshDescription * RawMeshPtr = InDataTracker . FindRawMeshAndLODIndex ( ComponentIndex , LODIndex ) ;
if ( RawMeshPtr ! = nullptr )
{
FMeshDescription & RawMesh = * RawMeshPtr ;
const int32 TargetLODIndex = 0 ;
InDataTracker . AddComponentToWedgeMapping ( ComponentIndex , TargetLODIndex , MergedMesh . VertexInstances ( ) . Num ( ) ) ;
FMeshDescriptionOperations : : FAppendSettings AppendSettings ;
AppendSettings . PolygonGroupsDelegate = FAppendPolygonGroupsDelegate : : CreateLambda ( [ & bInMergeMaterialData , & InDataTracker , & InOutputMaterialsMap , & ComponentIndex , & LODIndex ] ( const FMeshDescription & SourceMesh , FMeshDescription & TargetMesh , PolygonGroupMap & RemapPolygonGroups )
{
TPolygonGroupAttributesConstRef < FName > SourceImportedMaterialSlotNames = SourceMesh . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
TPolygonGroupAttributesRef < FName > TargetImportedMaterialSlotNames = TargetMesh . PolygonGroupAttributes ( ) . GetAttributesRef < FName > ( MeshAttribute : : PolygonGroup : : ImportedMaterialSlotName ) ;
//Copy the polygon group
2018-05-23 21:04:31 -04:00
if ( bInMergeMaterialData )
{
2019-01-07 05:38:46 -05:00
FPolygonGroupID PolygonGroupID ( 0 ) ;
if ( ! TargetMesh . PolygonGroups ( ) . IsValid ( PolygonGroupID ) )
{
TargetMesh . CreatePolygonGroupWithID ( PolygonGroupID ) ;
TargetImportedMaterialSlotNames [ PolygonGroupID ] = SourceMesh . PolygonGroups ( ) . IsValid ( PolygonGroupID ) ? SourceImportedMaterialSlotNames [ PolygonGroupID ] : FName ( TEXT ( " DefaultMaterialName " ) ) ;
}
for ( FPolygonGroupID SourcePolygonGroupID : SourceMesh . PolygonGroups ( ) . GetElementIDs ( ) )
{
RemapPolygonGroups . Add ( SourcePolygonGroupID , PolygonGroupID ) ;
}
2018-05-23 21:04:31 -04:00
}
else
{
TArray < SectionRemapPair > SectionMappings ;
InDataTracker . GetMappingsForMeshLOD ( FMeshLODKey ( ComponentIndex , LODIndex ) , SectionMappings ) ;
2019-01-07 05:38:46 -05:00
for ( FPolygonGroupID SourcePolygonGroupID : SourceMesh . PolygonGroups ( ) . GetElementIDs ( ) )
2018-05-23 21:04:31 -04:00
{
// First map from original section index to unique material index
int32 UniqueIndex = INDEX_NONE ;
// then map to the output material map, if any
2019-01-07 05:38:46 -05:00
if ( InOutputMaterialsMap . Num ( ) > 0 )
2018-05-23 21:04:31 -04:00
{
TArray < MaterialRemapPair > MaterialMappings ;
InOutputMaterialsMap . MultiFind ( FMeshLODKey ( ComponentIndex , LODIndex ) , MaterialMappings ) ;
2019-01-07 05:38:46 -05:00
for ( MaterialRemapPair & Pair : MaterialMappings )
2018-05-23 21:04:31 -04:00
{
2019-01-07 05:38:46 -05:00
if ( Pair . Key = = SourcePolygonGroupID . GetValue ( ) )
2018-05-23 21:04:31 -04:00
{
UniqueIndex = Pair . Value ;
break ;
}
}
// Note that at this point UniqueIndex is NOT a material index, but a unique section index!
}
2019-03-25 14:06:35 -04:00
2019-05-06 11:32:24 -04:00
//Fallback
2019-03-25 14:06:35 -04:00
if ( UniqueIndex = = INDEX_NONE )
2018-05-23 21:04:31 -04:00
{
2019-01-07 05:38:46 -05:00
UniqueIndex = SourcePolygonGroupID . GetValue ( ) ;
2018-05-23 21:04:31 -04:00
}
2019-05-06 11:32:24 -04:00
2019-01-07 05:38:46 -05:00
FPolygonGroupID TargetPolygonGroupID ( UniqueIndex ) ;
if ( ! TargetMesh . PolygonGroups ( ) . IsValid ( TargetPolygonGroupID ) )
2018-05-23 21:04:31 -04:00
{
2019-01-07 05:38:46 -05:00
while ( TargetMesh . PolygonGroups ( ) . Num ( ) < = UniqueIndex )
2018-05-23 21:04:31 -04:00
{
2019-01-07 05:38:46 -05:00
TargetPolygonGroupID = TargetMesh . CreatePolygonGroup ( ) ;
2018-05-23 21:04:31 -04:00
}
2019-01-07 05:38:46 -05:00
check ( TargetPolygonGroupID . GetValue ( ) = = UniqueIndex ) ;
TargetImportedMaterialSlotNames [ TargetPolygonGroupID ] = SourceImportedMaterialSlotNames [ SourcePolygonGroupID ] ;
2018-05-23 21:04:31 -04:00
}
2019-01-07 05:38:46 -05:00
RemapPolygonGroups . Add ( SourcePolygonGroupID , TargetPolygonGroupID ) ;
2018-05-23 21:04:31 -04:00
}
}
2019-01-07 05:38:46 -05:00
} ) ;
AppendSettings . bMergeVertexColor = InSettings . bBakeVertexDataToMesh ;
AppendSettings . MergedAssetPivot = InMergedAssetPivot ;
FMeshDescriptionOperations : : AppendMeshDescription ( * RawMeshPtr , MergedMesh , AppendSettings ) ;
2018-05-23 21:04:31 -04:00
}
}
}
for ( IMeshMergeExtension * Extension : MeshMergeExtensions )
{
Extension - > OnCreatedMergedRawMeshes ( InStaticMeshComponentsToMerge , InDataTracker , OutMergedRawMeshes ) ;
}
2017-06-30 12:21:06 -04:00
}
2018-03-06 13:26:20 -05:00
void FMeshMergeUtilities : : MergeComponentsToInstances ( const TArray < UPrimitiveComponent * > & ComponentsToMerge , UWorld * World , ULevel * Level , const FMeshInstancingSettings & InSettings , bool bActuallyMerge /*= true*/ , FText * OutResultsText /*= nullptr*/ ) const
{
auto HasInstanceVertexColors = [ ] ( UStaticMeshComponent * StaticMeshComponent )
{
for ( const FStaticMeshComponentLODInfo & CurrentLODInfo : StaticMeshComponent - > LODData )
{
if ( CurrentLODInfo . OverrideVertexColors ! = nullptr | | CurrentLODInfo . PaintedVertices . Num ( ) > 0 )
{
return true ;
}
}
2017-06-30 12:21:06 -04:00
2018-03-06 13:26:20 -05:00
return false ;
} ;
// Gather valid components
TArray < UStaticMeshComponent * > ValidComponents ;
for ( UPrimitiveComponent * ComponentToMerge : ComponentsToMerge )
{
if ( UStaticMeshComponent * StaticMeshComponent = Cast < UStaticMeshComponent > ( ComponentToMerge ) )
{
// Dont harvest from 'destination' actors
if ( StaticMeshComponent - > GetOwner ( ) - > GetClass ( ) ! = InSettings . ActorClassToUse . Get ( ) )
{
if ( ! InSettings . bSkipMeshesWithVertexColors | | ! HasInstanceVertexColors ( StaticMeshComponent ) )
{
ValidComponents . Add ( StaticMeshComponent ) ;
}
}
}
}
if ( OutResultsText ! = nullptr )
{
* OutResultsText = LOCTEXT ( " InstanceMergePredictedResultsNone " , " The current settings will not result in any instanced meshes being created " ) ;
}
if ( ValidComponents . Num ( ) > 0 )
{
/** Helper struct representing a spawned ISMC */
struct FComponentEntry
{
FComponentEntry ( UStaticMeshComponent * InComponent )
{
StaticMesh = InComponent - > GetStaticMesh ( ) ;
InComponent - > GetUsedMaterials ( Materials ) ;
bReverseCulling = InComponent - > GetComponentTransform ( ) . ToMatrixWithScale ( ) . Determinant ( ) < 0.0f ;
CollisionProfileName = InComponent - > GetCollisionProfileName ( ) ;
CollisionEnabled = InComponent - > GetCollisionEnabled ( ) ;
OriginalComponents . Add ( InComponent ) ;
}
bool operator = = ( const FComponentEntry & InOther ) const
{
return
StaticMesh = = InOther . StaticMesh & &
Materials = = InOther . Materials & &
bReverseCulling = = InOther . bReverseCulling & &
CollisionProfileName = = InOther . CollisionProfileName & &
CollisionEnabled = = InOther . CollisionEnabled ;
}
UStaticMesh * StaticMesh ;
TArray < UMaterialInterface * > Materials ;
TArray < UStaticMeshComponent * > OriginalComponents ;
FName CollisionProfileName ;
bool bReverseCulling ;
ECollisionEnabled : : Type CollisionEnabled ;
} ;
/** Helper struct representing a spawned ISMC-containing actor */
struct FActorEntry
{
FActorEntry ( UStaticMeshComponent * InComponent , ULevel * InLevel )
: MergedActor ( nullptr )
{
// intersect with HLOD volumes if we have a level
if ( InLevel )
{
for ( AActor * Actor : InLevel - > Actors )
{
if ( AHierarchicalLODVolume * HierarchicalLODVolume = Cast < AHierarchicalLODVolume > ( Actor ) )
{
FBox BoundingBox = InComponent - > Bounds . GetBox ( ) ;
FBox VolumeBox = HierarchicalLODVolume - > GetComponentsBoundingBox ( true ) ;
if ( VolumeBox . IsInside ( BoundingBox ) | | ( HierarchicalLODVolume - > bIncludeOverlappingActors & & VolumeBox . Intersect ( BoundingBox ) ) )
{
HLODVolume = HierarchicalLODVolume ;
break ;
}
}
}
}
}
bool operator = = ( const FActorEntry & InOther ) const
{
return HLODVolume = = InOther . HLODVolume ;
}
AActor * MergedActor ;
AHierarchicalLODVolume * HLODVolume ;
TArray < FComponentEntry > ComponentEntries ;
} ;
// Gather a list of components to merge
TArray < FActorEntry > ActorEntries ;
for ( UStaticMeshComponent * StaticMeshComponent : ValidComponents )
{
int32 ActorEntryIndex = ActorEntries . AddUnique ( FActorEntry ( StaticMeshComponent , InSettings . bUseHLODVolumes ? Level : nullptr ) ) ;
FActorEntry & ActorEntry = ActorEntries [ ActorEntryIndex ] ;
FComponentEntry ComponentEntry ( StaticMeshComponent ) ;
if ( FComponentEntry * ExistingComponentEntry = ActorEntry . ComponentEntries . FindByKey ( ComponentEntry ) )
{
ExistingComponentEntry - > OriginalComponents . Add ( StaticMeshComponent ) ;
}
else
{
ActorEntry . ComponentEntries . Add ( ComponentEntry ) ;
}
}
// Filter by component count
for ( FActorEntry & ActorEntry : ActorEntries )
{
ActorEntry . ComponentEntries = ActorEntry . ComponentEntries . FilterByPredicate ( [ & InSettings ] ( const FComponentEntry & InEntry )
{
return InEntry . OriginalComponents . Num ( ) > = InSettings . InstanceReplacementThreshold ;
} ) ;
}
// Remove any empty actor entries
ActorEntries . RemoveAll ( [ ] ( const FActorEntry & ActorEntry ) { return ActorEntry . ComponentEntries . Num ( ) = = 0 ; } ) ;
int32 TotalComponentCount = 0 ;
TArray < AActor * > ActorsToCleanUp ;
for ( FActorEntry & ActorEntry : ActorEntries )
{
for ( const FComponentEntry & ComponentEntry : ActorEntry . ComponentEntries )
{
TotalComponentCount + + ;
for ( UStaticMeshComponent * OriginalComponent : ComponentEntry . OriginalComponents )
{
if ( AActor * OriginalActor = OriginalComponent - > GetOwner ( ) )
{
ActorsToCleanUp . AddUnique ( OriginalActor ) ;
}
}
}
}
if ( ActorEntries . Num ( ) > 0 )
{
if ( OutResultsText ! = nullptr )
{
* OutResultsText = FText : : Format ( LOCTEXT ( " InstanceMergePredictedResults " , " The current settings will result in {0} instanced static mesh components ({1} actors will be replaced) " ) , FText : : AsNumber ( TotalComponentCount ) , FText : : AsNumber ( ActorsToCleanUp . Num ( ) ) ) ;
}
if ( bActuallyMerge )
{
// Create our actors
const FScopedTransaction Transaction ( LOCTEXT ( " PlaceInstancedActors " , " Place Instanced Actor(s) " )) ;
Level - > Modify ( ) ;
FActorSpawnParameters Params ;
Params . OverrideLevel = Level ;
// We now have the set of component data we want to apply
for ( FActorEntry & ActorEntry : ActorEntries )
{
ActorEntry . MergedActor = World - > SpawnActor < AActor > ( InSettings . ActorClassToUse . Get ( ) , Params ) ;
for ( const FComponentEntry & ComponentEntry : ActorEntry . ComponentEntries )
{
2019-06-07 11:22:52 -04:00
UInstancedStaticMeshComponent * NewComponent = nullptr ;
NewComponent = ( UInstancedStaticMeshComponent * ) ActorEntry . MergedActor - > FindComponentByClass ( InSettings . ISMComponentToUse . Get ( ) ) ;
if ( NewComponent & & NewComponent - > PerInstanceSMData . Num ( ) > 0 )
2018-03-06 13:26:20 -05:00
{
2019-06-07 11:22:52 -04:00
NewComponent = nullptr ;
}
if ( NewComponent = = nullptr )
{
NewComponent = NewObject < UInstancedStaticMeshComponent > ( ActorEntry . MergedActor , InSettings . ISMComponentToUse . Get ( ) ) ;
2018-03-06 13:26:20 -05:00
2019-06-07 11:22:52 -04:00
if ( ActorEntry . MergedActor - > GetRootComponent ( ) )
2018-03-06 13:26:20 -05:00
{
// Attach to root if we already have one
2019-06-07 11:22:52 -04:00
NewComponent - > AttachToComponent ( ActorEntry . MergedActor - > GetRootComponent ( ) , FAttachmentTransformRules : : KeepRelativeTransform ) ;
2018-03-06 13:26:20 -05:00
}
else
{
// Make a new root if we dont have a root already
2019-06-07 11:22:52 -04:00
ActorEntry . MergedActor - > SetRootComponent ( NewComponent ) ;
2018-03-06 13:26:20 -05:00
}
// Take 'instanced' ownership so it persists with this actor
2019-06-07 11:22:52 -04:00
ActorEntry . MergedActor - > RemoveOwnedComponent ( NewComponent ) ;
2018-03-06 13:26:20 -05:00
NewComponent - > CreationMethod = EComponentCreationMethod : : Instance ;
2019-06-07 11:22:52 -04:00
ActorEntry . MergedActor - > AddOwnedComponent ( NewComponent ) ;
}
2018-03-06 13:26:20 -05:00
NewComponent - > SetStaticMesh ( ComponentEntry . StaticMesh ) ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < ComponentEntry . Materials . Num ( ) ; + + MaterialIndex )
{
NewComponent - > SetMaterial ( MaterialIndex , ComponentEntry . Materials [ MaterialIndex ] ) ;
}
NewComponent - > SetReverseCulling ( ComponentEntry . bReverseCulling ) ;
NewComponent - > SetCollisionProfileName ( ComponentEntry . CollisionProfileName ) ;
NewComponent - > SetCollisionEnabled ( ComponentEntry . CollisionEnabled ) ;
NewComponent - > SetMobility ( EComponentMobility : : Static ) ;
for ( UStaticMeshComponent * OriginalComponent : ComponentEntry . OriginalComponents )
{
NewComponent - > AddInstance ( OriginalComponent - > GetComponentTransform ( ) ) ;
}
NewComponent - > RegisterComponent ( ) ;
}
World - > UpdateCullDistanceVolumes ( ActorEntry . MergedActor ) ;
}
// Now clean up our original actors
for ( AActor * ActorToCleanUp : ActorsToCleanUp )
{
if ( InSettings . MeshReplacementMethod = = EMeshInstancingReplacementMethod : : RemoveOriginalActors )
{
ActorToCleanUp - > Destroy ( ) ;
}
else if ( InSettings . MeshReplacementMethod = = EMeshInstancingReplacementMethod : : KeepOriginalActorsAsEditorOnly )
{
ActorToCleanUp - > Modify ( ) ;
ActorToCleanUp - > bIsEditorOnlyActor = true ;
2019-09-29 16:49:10 -04:00
ActorToCleanUp - > SetHidden ( true ) ;
2018-03-06 13:26:20 -05:00
ActorToCleanUp - > bHiddenEd = true ;
ActorToCleanUp - > SetIsTemporarilyHiddenInEditor ( true ) ;
}
}
// pop a toast allowing selection
auto SelectActorsLambda = [ ActorEntries ] ( )
{
GEditor - > GetSelectedActors ( ) - > Modify ( ) ;
GEditor - > GetSelectedActors ( ) - > BeginBatchSelectOperation ( ) ;
GEditor - > SelectNone ( false , true , false ) ;
for ( const FActorEntry & ActorEntry : ActorEntries )
{
GEditor - > SelectActor ( ActorEntry . MergedActor , true , false , true ) ;
}
GEditor - > GetSelectedActors ( ) - > EndBatchSelectOperation ( ) ;
} ;
FNotificationInfo NotificationInfo ( FText : : Format ( LOCTEXT ( " CreatedInstancedActorsMessage " , " Created {0} Instanced Actor(s) " ), FText::AsNumber(ActorEntries.Num()))) ;
NotificationInfo . Hyperlink = FSimpleDelegate : : CreateLambda ( SelectActorsLambda ) ;
NotificationInfo . HyperlinkText = LOCTEXT ( " SelectActorsHyperlink " , " Select Actors " ) ;
NotificationInfo . ExpireDuration = 5.0f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( NotificationInfo ) ;
}
}
}
}
UMaterialInterface * FMeshMergeUtilities : : CreateProxyMaterial ( const FString & InBasePackageName , FString MergedAssetPackageName , UMaterialInterface * InBaseMaterial , UPackage * InOuter , const FMeshMergingSettings & InSettings , FFlattenMaterial OutMaterial , TArray < UObject * > & OutAssetsToSync ) const
2017-06-30 12:21:06 -04:00
{
// Create merged material asset
FString MaterialAssetName ;
FString MaterialPackageName ;
if ( InBasePackageName . IsEmpty ( ) )
{
2019-01-18 11:39:35 -05:00
MaterialAssetName = FPackageName : : GetShortName ( MergedAssetPackageName ) ;
2019-03-07 11:44:46 -05:00
MaterialPackageName = FPackageName : : GetLongPackagePath ( MergedAssetPackageName ) + TEXT ( " / " ) ;
2017-06-30 12:21:06 -04:00
}
else
{
2019-01-18 11:39:35 -05:00
MaterialAssetName = FPackageName : : GetShortName ( InBasePackageName ) ;
2019-03-07 11:44:46 -05:00
MaterialPackageName = FPackageName : : GetLongPackagePath ( InBasePackageName ) + TEXT ( " / " ) ;
2017-06-30 12:21:06 -04:00
}
UPackage * MaterialPackage = InOuter ;
if ( MaterialPackage = = nullptr )
{
2019-03-07 11:44:46 -05:00
MaterialPackage = CreatePackage ( nullptr , * ( MaterialPackageName + MaterialAssetName ) ) ;
2017-06-30 12:21:06 -04:00
check ( MaterialPackage ) ;
MaterialPackage - > FullyLoad ( ) ;
MaterialPackage - > Modify ( ) ;
}
2019-01-18 11:39:35 -05:00
UMaterialInstanceConstant * MergedMaterial = ProxyMaterialUtilities : : CreateProxyMaterialInstance ( MaterialPackage , InSettings . MaterialSettings , InBaseMaterial , OutMaterial , MaterialPackageName , MaterialAssetName , OutAssetsToSync ) ;
2017-06-30 12:21:06 -04:00
// Set material static lighting usage flag if project has static lighting enabled
static const auto AllowStaticLightingVar = IConsoleManager : : Get ( ) . FindTConsoleVariableDataInt ( TEXT ( " r.AllowStaticLighting " ) ) ;
const bool bAllowStaticLighting = ( ! AllowStaticLightingVar | | AllowStaticLightingVar - > GetValueOnGameThread ( ) ! = 0 ) ;
if ( bAllowStaticLighting )
{
MergedMaterial - > CheckMaterialUsage ( MATUSAGE_StaticLighting ) ;
}
return MergedMaterial ;
}
void FMeshMergeUtilities : : ExtractPhysicsDataFromComponents ( const TArray < UPrimitiveComponent * > & ComponentsToMerge , TArray < FKAggregateGeom > & InOutPhysicsGeometry , UBodySetup * & OutBodySetupSource ) const
{
InOutPhysicsGeometry . AddDefaulted ( ComponentsToMerge . Num ( ) ) ;
for ( int32 ComponentIndex = 0 ; ComponentIndex < ComponentsToMerge . Num ( ) ; + + ComponentIndex )
{
UPrimitiveComponent * PrimComp = ComponentsToMerge [ ComponentIndex ] ;
UBodySetup * BodySetup = nullptr ;
FTransform ComponentToWorld = FTransform : : Identity ;
if ( UStaticMeshComponent * StaticMeshComp = Cast < UStaticMeshComponent > ( PrimComp ) )
{
UStaticMesh * SrcMesh = StaticMeshComp - > GetStaticMesh ( ) ;
if ( SrcMesh )
{
BodySetup = SrcMesh - > BodySetup ;
}
ComponentToWorld = StaticMeshComp - > GetComponentToWorld ( ) ;
}
else if ( UShapeComponent * ShapeComp = Cast < UShapeComponent > ( PrimComp ) )
{
BodySetup = ShapeComp - > GetBodySetup ( ) ;
ComponentToWorld = ShapeComp - > GetComponentToWorld ( ) ;
}
Copying //UE4/Dev-Physics to //UE4/Dev-Main (Source: //UE4/Dev-Physics @ 4242698)
#rb none
#lockdown Nick.Penwarden
============================
MAJOR FEATURES & CHANGES
============================
Change 4023283 by Michael.Lentine
Fix memory leak.
Change 4024243 by Michael.Lentine
Add debugging output code from github #4533.
#jira ue-55764
Change 4026362 by Michael.Lentine
Merged github #3704.
#jira ue-463394
Change 4026545 by Michael.Lentine
Fix ordering of collision settings changed callback
#jira ue-50475
Change 4026609 by Michael.Lentine
Fix crash in destruction for when world is not valid
#jira ue-53989
Change 4026786 by Michael.Lentine
Merging github #4632 to fix memory leak.
#jira ue-57255
Change 4027293 by Michael.Lentine
Integrate github #4338.
#jira ue-53497
Change 4033517 by Michael.Lentine
Fix collision body creation for spline merging.
#jira ue-53956
Change 4039750 by Michael.Lentine
Add basic error message if cooking fails.
Change 4040210 by Michael.Lentine
Check for nullptr
Change 4098887 by Michael.Lentine
Fix warnings.
Change 4103511 by Michael.Lentine
Prevent crash when BodyInstance is invalid.
Change 4117826 by Michael.Lentine
Fix check for body being fixed.
Change 4122307 by Benn.Gallagher
PS4/clang build fixes
Change 4124479 by Benn.Gallagher
Fix non-portable filename used as an include (Linux editor build CIS error)
Change 4125450 by Benn.Gallagher
Fixup Ocean
Change 4127210 by Michael.Lentine
Update the PreviousBoneTransforms array when setting transforms in DestructibleComponent
#jira ue-58813
Change 4127309 by Benn.Gallagher
Fix Win32 shipping builds
Change 4134570 by Michael.Lentine
Missed fixes for WITH_UEPHYSICS.
Change 4134585 by Michael.Lentine
Missed a few more files.
Change 4134670 by Michael.Lentine
Update formatting.
Change 4134671 by Michael.Lentine
More formatting.
Change 4150615 by Benn.Gallagher
Moved immediate mode into engine, as it is now depended on by the physics engine.
Change 4150680 by Benn.Gallagher
Missed file
Change 4150980 by Benn.Gallagher
Rename kinematic target for immediate mode to avoid ambiguous symbols in engine
Change 4151400 by Brice.Criswell
Apeiron
Levelset initilization issue.
----
Change 4157880 by Benn.Gallagher
More fixing unresolved template specialisations for FN editor.
Change 4159128 by Michael.Lentine
Compile fixes
Change 4159786 by Brice.Criswell
Apeiron
Levelset curvature initialization fix, clamps out of bounds phi values to phi[i].
------
Change 4160382 by Michael.Lentine
Fix node initialization
Change 4160463 by Brice.Criswell
Apeiron
Levelset index fix.
----
Change 4161425 by Benn.Gallagher
Added package, class and struct redirects for moving immediate physics into engine.
Change 4164195 by Brice.Criswell
GeometryCollection : Code review updates
- Removed typedef for GeometryCollection::ManagedArray<T>
- Renamed Enumerations to begin with E prefix, retyped to be uint8.
- Removed EArrayScoipe::FScopeNone, now defautls to FScopeShared
- Formatted type modifiers to follow UE4 coding standard.
- Derived the ManagedArrayBase from FNonCopyable
- Disabled TManagedArrays copy constructor and assignment operator.
- Converted most accessors on GeometryCollection to TSharedRef.
- Added .inl style definitions to simplify the management of the ManagedArrayTypes
-----
Change 4164235 by Brice.Criswell
GeometryCollection : Added New Files
- Added the ManagedArrayTypes files.
----
Change 4164309 by Brice.Criswell
GeometryCollection :
Moved the initialization of the RigidBodyIdArray and CenterOfMassArray into the WITH_APEIRON definition.
-----
Change 4166133 by Brice.Criswell
GeometryCollection
Added GeometryCollectionEdit class to protect access to the rest and dynamic collections.
-----
Change 4171540 by Michael.Lentine
Fix reset
#robomerge destruction
Change 4171912 by Michael.Lentine
Rename BVHParticles
#robomerge destruction
Change 4172445 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4172623 by Brice.Criswell
GeometryCollection
Debugging ToString to inspect the GeometryCollection
----
Change 4172711 by Michael.Lentine
Add Immediate Path to Geometry Collection
Change 4172778 by Michael.Lentine
Update LL Interface to use Simulation type.
#robomerge destruction
Change 4172780 by Michael.Lentine
Missed files
#robomerge destruction
Change 4173238 by Benn.Gallagher
Missed file from last checkin
Change 4173554 by Benn.Gallagher
Few extra changes for const correctness and actor counts
Change 4174153 by Benn.Gallagher
Fixed non-unity build issue from Geom Collection.
Change 4175355 by Brice.Criswell
GeometryCollection
Separated the GeometryCollection from USE_APEIRON flag.
-----
Change 4175533 by Brice.Criswell
GeometryCollection
Defaulting Aperion to off.
-----
Change 4175761 by Michael.Lentine
Fix collisions.
Change 4177105 by Benn.Gallagher
Another geom collection CIS fix when running without PCHs
Change 4177796 by Brice.Criswell
GeometryCollection
- Added parenting function to manage the BoneHierarchy Array
- Split collection along yz-plane.
-----
Change 4177989 by Brice.Criswell
GeometryCollection
- Moved Hierarchy and Transform array elements into base class TransformCollection
- Renamed ParticleGroup to TransformGroup.
-----
Change 4178826 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4178840 by Brice.Criswell
Geometry Collection
Removed FORCEINLINE from GeometryCollectionEdit.GetRestCollection
----
Change 4179493 by Brice.Criswell
GeometryCollection
New icons.
-----
Change 4182428 by Brice.Criswell
Build Configuration
Apeiron configuration.
- Modified bCompileApeiron to enable the compilation of the Apeiron plugin.
- Added bUseApeiron to enable Apeiron in the physics interfaces.
Changed PhysScene_Apeiron to enable when bCompileApeiron is enabled.
Disabled the GeometryCollection* Plugins in the build.
-------
Change 4185886 by Brice.Criswell
GeometryCollection
Renaming TransformGroup.
---
Change 4186389 by michael.lentine
Don't create in parallel for immediate mode.
Change 4186457 by michael.lentine
Hack to prevent crashing when Visible is nullptr.
Change 4198872 by Brice.Criswell
Apeiron
Clustering changes
- Clustering based on hierarchy's defined within the Geometry Collection
-----
Change 4199861 by Brice.Criswell
GeometryCollection
Disable Apeiron in the Collection.
------
Change 4200089 by Brice.Criswell
GeometryCollection
Updated to enable Apeiron in the GeometryCollection when the bCompileAperion flag is enabled in the UnrealBuildTool.
---
Change 4200333 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
-----
Change 4202231 by Michael.Lentine
Disable collisions between adjacent bodies connected by a joint. This typically would be specified by an artist but classic PhysX always does this uncondintionally so our clients are used to this.
Change 4202748 by Michael.Lentine
Fix 2015 compile.
Change 4204528 by Michael.Lentine
Disable Apeiron.
Change 4206396 by Michael.Lentine
Fix 2015 build. Static cast apparently is not an accetible conversion from uint32 to bool.
#robomerge destruction
Change 4206604 by Michael.Lentine
Fix for using ccd and kinematic.
#jira UE-61694
#robomerge destruction
Change 4206711 by mason.seay
Refreshed Set Angular Drive nodes to clear out orphan pins
Change 4207286 by Brice.Criswell
GeometryCollection
Transform hierarchy evaluation within BoneHierarchy of the Collection.
Parenting operations are implemented on an updated morphology using :
ParentTransforms(UGeometryCollection* GeometryCollection, const int32 InsertAtIndex, const TArray<int32>& SelectedBones);
To parent a new transform:
int32 RootIndex << within len( TransformGroup ) or -1 for a non-parented node.
int32 BoneIndex = Collection->AddElements(1, UGeometryCollection::TransformGroup);
GeometryCollectionAlgo::ParentTransform(Collection, RootIndex, BoneIndex);
Transform[BoneIndex] = <some transform within local space of the RootIndex>
Default collections have all geometry not parented. The function EnsureSingleRoot was added to guarantee that the collection has at least one parent node.
FGeometryCollectionCommands::EnsureSinglRoot(UGeometryCollection* RestCollection)
Then matrices relative to the collections root are calculated using:
GlobalMatrices(UGeometryCollection* GeometryCollection, TArray<FTransform> & Transforms);
Added Damage Threshold to GeometryCollectionActor
------
Change 4208039 by Brice.Criswell
GeometryCollection
Fix for static include failure.
---
Change 4208170 by Brice.Criswell
GeometryCache
SplitAlongYZ to support multiple levels and orientations.
---
Change 4208174 by Michael.Lentine
Avoid shadow warnings and switch logs to verbose instead of warnings.
#robomerge destruction
Change 4210255 by Benn.Gallagher
Static analysis fixes
Change 4210394 by Michael.Lentine
Use correct particle type for updateconstraints.
Change 4211153 by Brice.Criswell
Apeiron
Exposing friction and coefficient of restitution to the actor.
-----
Change 4213034 by michael.lentine
Rename bounding volume
Change 4216783 by Michael.Lentine
Committing cooking fix to Dev-Physics in order to get smoke tests running.
Change 4218078 by Benn.Gallagher
Fixed memory and TLS slot leak caused by previous change to physics scene cleanup while cooking
#jira UE-61633
Change 4219206 by Michael.Lentine
Use the adaptor to get the rotation.
#jira ue-61748
Change 4220469 by Benn.Gallagher
Fixed overlaps re-triggering on movement due to bad transform chaining from component to phys actor to shape
#jira UE-61703
Change 4220538 by Benn.Gallagher
Fixed PhysX errors when setting global transforms of kinematic and static objects.
#jira none
Change 4222138 by Michael.Lentine
Update use of Vulkan on android.
Change 4222139 by Michael.Lentine
Update OculusHMD plugin to use correct vulkan search path.
Change 4225740 by Michael.Lentine
Integrate changes to update rotation and mass.
Change 4225928 by michael.lentine
Use more accurate collision point.
Change 4226560 by michael.lentine
Enable contact graph
Change 4227397 by Michael.Lentine
If we don't have a global scene we need to not detect collisions.
#robomerge destruction
Change 4227410 by Michael.Lentine
Missing include
#robomerge destruction
Change 4228107 by Michael.Lentine
Integrate static contact changes.
Change 4228612 by michael.lentine
Use more correct thresholding.
Change 4228734 by Benn.Gallagher
Getting LLImmediate high level stood up and simulating
Implementation is incomplete, only what is required to get simple scenes simulating under immediate mode
Change 4228748 by Benn.Gallagher
Missed file from checkin
Change 4228885 by Ori.Cohen
Added base physics interface class to help provide default behavior and easily chain functionality together
Change 4228992 by Ori.Cohen
Fix cis
Change 4229921 by Benn.Gallagher
Fixed contact pre-filter performance regression
Change 4230825 by Benn.Gallagher
Moved WIP physics interfaces to Experimental/ folders
Change 4230853 by Benn.Gallagher
Fixup includes after moving WIP physics interfaces
Change 4231414 by Michael.Lentine
Use global namespace to avoid mac compile errors.
#jira ue-62137
[CL 4242847 by Michael Lentine in Main branch]
2018-07-31 02:23:26 -04:00
USplineMeshComponent * SplineMeshComponent = Cast < USplineMeshComponent > ( PrimComp ) ;
FMeshMergeHelpers : : ExtractPhysicsGeometry ( BodySetup , ComponentToWorld , SplineMeshComponent ! = nullptr , InOutPhysicsGeometry [ ComponentIndex ] ) ;
if ( SplineMeshComponent )
2017-06-30 12:21:06 -04:00
{
FMeshMergeHelpers : : PropagateSplineDeformationToPhysicsGeometry ( SplineMeshComponent , InOutPhysicsGeometry [ ComponentIndex ] ) ;
}
// We will use first valid BodySetup as a source of physics settings
if ( OutBodySetupSource = = nullptr )
{
OutBodySetupSource = BodySetup ;
}
}
}
void FMeshMergeUtilities : : ScaleTextureCoordinatesToBox ( const FBox2D & Box , TArray < FVector2D > & InOutTextureCoordinates ) const
{
const FBox2D CoordinateBox ( InOutTextureCoordinates ) ;
const FVector2D CoordinateRange = CoordinateBox . GetSize ( ) ;
const FVector2D Offset = CoordinateBox . Min + Box . Min ;
const FVector2D Scale = Box . GetSize ( ) / CoordinateRange ;
for ( FVector2D & Coordinate : InOutTextureCoordinates )
{
Coordinate = ( Coordinate - Offset ) * Scale ;
}
}
Copying //UE4/Dev-Physics to //UE4/Dev-Main (Source: //UE4/Dev-Physics @ 4242698)
#rb none
#lockdown Nick.Penwarden
============================
MAJOR FEATURES & CHANGES
============================
Change 4023283 by Michael.Lentine
Fix memory leak.
Change 4024243 by Michael.Lentine
Add debugging output code from github #4533.
#jira ue-55764
Change 4026362 by Michael.Lentine
Merged github #3704.
#jira ue-463394
Change 4026545 by Michael.Lentine
Fix ordering of collision settings changed callback
#jira ue-50475
Change 4026609 by Michael.Lentine
Fix crash in destruction for when world is not valid
#jira ue-53989
Change 4026786 by Michael.Lentine
Merging github #4632 to fix memory leak.
#jira ue-57255
Change 4027293 by Michael.Lentine
Integrate github #4338.
#jira ue-53497
Change 4033517 by Michael.Lentine
Fix collision body creation for spline merging.
#jira ue-53956
Change 4039750 by Michael.Lentine
Add basic error message if cooking fails.
Change 4040210 by Michael.Lentine
Check for nullptr
Change 4098887 by Michael.Lentine
Fix warnings.
Change 4103511 by Michael.Lentine
Prevent crash when BodyInstance is invalid.
Change 4117826 by Michael.Lentine
Fix check for body being fixed.
Change 4122307 by Benn.Gallagher
PS4/clang build fixes
Change 4124479 by Benn.Gallagher
Fix non-portable filename used as an include (Linux editor build CIS error)
Change 4125450 by Benn.Gallagher
Fixup Ocean
Change 4127210 by Michael.Lentine
Update the PreviousBoneTransforms array when setting transforms in DestructibleComponent
#jira ue-58813
Change 4127309 by Benn.Gallagher
Fix Win32 shipping builds
Change 4134570 by Michael.Lentine
Missed fixes for WITH_UEPHYSICS.
Change 4134585 by Michael.Lentine
Missed a few more files.
Change 4134670 by Michael.Lentine
Update formatting.
Change 4134671 by Michael.Lentine
More formatting.
Change 4150615 by Benn.Gallagher
Moved immediate mode into engine, as it is now depended on by the physics engine.
Change 4150680 by Benn.Gallagher
Missed file
Change 4150980 by Benn.Gallagher
Rename kinematic target for immediate mode to avoid ambiguous symbols in engine
Change 4151400 by Brice.Criswell
Apeiron
Levelset initilization issue.
----
Change 4157880 by Benn.Gallagher
More fixing unresolved template specialisations for FN editor.
Change 4159128 by Michael.Lentine
Compile fixes
Change 4159786 by Brice.Criswell
Apeiron
Levelset curvature initialization fix, clamps out of bounds phi values to phi[i].
------
Change 4160382 by Michael.Lentine
Fix node initialization
Change 4160463 by Brice.Criswell
Apeiron
Levelset index fix.
----
Change 4161425 by Benn.Gallagher
Added package, class and struct redirects for moving immediate physics into engine.
Change 4164195 by Brice.Criswell
GeometryCollection : Code review updates
- Removed typedef for GeometryCollection::ManagedArray<T>
- Renamed Enumerations to begin with E prefix, retyped to be uint8.
- Removed EArrayScoipe::FScopeNone, now defautls to FScopeShared
- Formatted type modifiers to follow UE4 coding standard.
- Derived the ManagedArrayBase from FNonCopyable
- Disabled TManagedArrays copy constructor and assignment operator.
- Converted most accessors on GeometryCollection to TSharedRef.
- Added .inl style definitions to simplify the management of the ManagedArrayTypes
-----
Change 4164235 by Brice.Criswell
GeometryCollection : Added New Files
- Added the ManagedArrayTypes files.
----
Change 4164309 by Brice.Criswell
GeometryCollection :
Moved the initialization of the RigidBodyIdArray and CenterOfMassArray into the WITH_APEIRON definition.
-----
Change 4166133 by Brice.Criswell
GeometryCollection
Added GeometryCollectionEdit class to protect access to the rest and dynamic collections.
-----
Change 4171540 by Michael.Lentine
Fix reset
#robomerge destruction
Change 4171912 by Michael.Lentine
Rename BVHParticles
#robomerge destruction
Change 4172445 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4172623 by Brice.Criswell
GeometryCollection
Debugging ToString to inspect the GeometryCollection
----
Change 4172711 by Michael.Lentine
Add Immediate Path to Geometry Collection
Change 4172778 by Michael.Lentine
Update LL Interface to use Simulation type.
#robomerge destruction
Change 4172780 by Michael.Lentine
Missed files
#robomerge destruction
Change 4173238 by Benn.Gallagher
Missed file from last checkin
Change 4173554 by Benn.Gallagher
Few extra changes for const correctness and actor counts
Change 4174153 by Benn.Gallagher
Fixed non-unity build issue from Geom Collection.
Change 4175355 by Brice.Criswell
GeometryCollection
Separated the GeometryCollection from USE_APEIRON flag.
-----
Change 4175533 by Brice.Criswell
GeometryCollection
Defaulting Aperion to off.
-----
Change 4175761 by Michael.Lentine
Fix collisions.
Change 4177105 by Benn.Gallagher
Another geom collection CIS fix when running without PCHs
Change 4177796 by Brice.Criswell
GeometryCollection
- Added parenting function to manage the BoneHierarchy Array
- Split collection along yz-plane.
-----
Change 4177989 by Brice.Criswell
GeometryCollection
- Moved Hierarchy and Transform array elements into base class TransformCollection
- Renamed ParticleGroup to TransformGroup.
-----
Change 4178826 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
----
Change 4178840 by Brice.Criswell
Geometry Collection
Removed FORCEINLINE from GeometryCollectionEdit.GetRestCollection
----
Change 4179493 by Brice.Criswell
GeometryCollection
New icons.
-----
Change 4182428 by Brice.Criswell
Build Configuration
Apeiron configuration.
- Modified bCompileApeiron to enable the compilation of the Apeiron plugin.
- Added bUseApeiron to enable Apeiron in the physics interfaces.
Changed PhysScene_Apeiron to enable when bCompileApeiron is enabled.
Disabled the GeometryCollection* Plugins in the build.
-------
Change 4185886 by Brice.Criswell
GeometryCollection
Renaming TransformGroup.
---
Change 4186389 by michael.lentine
Don't create in parallel for immediate mode.
Change 4186457 by michael.lentine
Hack to prevent crashing when Visible is nullptr.
Change 4198872 by Brice.Criswell
Apeiron
Clustering changes
- Clustering based on hierarchy's defined within the Geometry Collection
-----
Change 4199861 by Brice.Criswell
GeometryCollection
Disable Apeiron in the Collection.
------
Change 4200089 by Brice.Criswell
GeometryCollection
Updated to enable Apeiron in the GeometryCollection when the bCompileAperion flag is enabled in the UnrealBuildTool.
---
Change 4200333 by Brice.Criswell
Copying //UE4/Dev-Destruction to Dev-Physics (//UE4/Dev-Physics)
-----
Change 4202231 by Michael.Lentine
Disable collisions between adjacent bodies connected by a joint. This typically would be specified by an artist but classic PhysX always does this uncondintionally so our clients are used to this.
Change 4202748 by Michael.Lentine
Fix 2015 compile.
Change 4204528 by Michael.Lentine
Disable Apeiron.
Change 4206396 by Michael.Lentine
Fix 2015 build. Static cast apparently is not an accetible conversion from uint32 to bool.
#robomerge destruction
Change 4206604 by Michael.Lentine
Fix for using ccd and kinematic.
#jira UE-61694
#robomerge destruction
Change 4206711 by mason.seay
Refreshed Set Angular Drive nodes to clear out orphan pins
Change 4207286 by Brice.Criswell
GeometryCollection
Transform hierarchy evaluation within BoneHierarchy of the Collection.
Parenting operations are implemented on an updated morphology using :
ParentTransforms(UGeometryCollection* GeometryCollection, const int32 InsertAtIndex, const TArray<int32>& SelectedBones);
To parent a new transform:
int32 RootIndex << within len( TransformGroup ) or -1 for a non-parented node.
int32 BoneIndex = Collection->AddElements(1, UGeometryCollection::TransformGroup);
GeometryCollectionAlgo::ParentTransform(Collection, RootIndex, BoneIndex);
Transform[BoneIndex] = <some transform within local space of the RootIndex>
Default collections have all geometry not parented. The function EnsureSingleRoot was added to guarantee that the collection has at least one parent node.
FGeometryCollectionCommands::EnsureSinglRoot(UGeometryCollection* RestCollection)
Then matrices relative to the collections root are calculated using:
GlobalMatrices(UGeometryCollection* GeometryCollection, TArray<FTransform> & Transforms);
Added Damage Threshold to GeometryCollectionActor
------
Change 4208039 by Brice.Criswell
GeometryCollection
Fix for static include failure.
---
Change 4208170 by Brice.Criswell
GeometryCache
SplitAlongYZ to support multiple levels and orientations.
---
Change 4208174 by Michael.Lentine
Avoid shadow warnings and switch logs to verbose instead of warnings.
#robomerge destruction
Change 4210255 by Benn.Gallagher
Static analysis fixes
Change 4210394 by Michael.Lentine
Use correct particle type for updateconstraints.
Change 4211153 by Brice.Criswell
Apeiron
Exposing friction and coefficient of restitution to the actor.
-----
Change 4213034 by michael.lentine
Rename bounding volume
Change 4216783 by Michael.Lentine
Committing cooking fix to Dev-Physics in order to get smoke tests running.
Change 4218078 by Benn.Gallagher
Fixed memory and TLS slot leak caused by previous change to physics scene cleanup while cooking
#jira UE-61633
Change 4219206 by Michael.Lentine
Use the adaptor to get the rotation.
#jira ue-61748
Change 4220469 by Benn.Gallagher
Fixed overlaps re-triggering on movement due to bad transform chaining from component to phys actor to shape
#jira UE-61703
Change 4220538 by Benn.Gallagher
Fixed PhysX errors when setting global transforms of kinematic and static objects.
#jira none
Change 4222138 by Michael.Lentine
Update use of Vulkan on android.
Change 4222139 by Michael.Lentine
Update OculusHMD plugin to use correct vulkan search path.
Change 4225740 by Michael.Lentine
Integrate changes to update rotation and mass.
Change 4225928 by michael.lentine
Use more accurate collision point.
Change 4226560 by michael.lentine
Enable contact graph
Change 4227397 by Michael.Lentine
If we don't have a global scene we need to not detect collisions.
#robomerge destruction
Change 4227410 by Michael.Lentine
Missing include
#robomerge destruction
Change 4228107 by Michael.Lentine
Integrate static contact changes.
Change 4228612 by michael.lentine
Use more correct thresholding.
Change 4228734 by Benn.Gallagher
Getting LLImmediate high level stood up and simulating
Implementation is incomplete, only what is required to get simple scenes simulating under immediate mode
Change 4228748 by Benn.Gallagher
Missed file from checkin
Change 4228885 by Ori.Cohen
Added base physics interface class to help provide default behavior and easily chain functionality together
Change 4228992 by Ori.Cohen
Fix cis
Change 4229921 by Benn.Gallagher
Fixed contact pre-filter performance regression
Change 4230825 by Benn.Gallagher
Moved WIP physics interfaces to Experimental/ folders
Change 4230853 by Benn.Gallagher
Fixup includes after moving WIP physics interfaces
Change 4231414 by Michael.Lentine
Use global namespace to avoid mac compile errors.
#jira ue-62137
[CL 4242847 by Michael Lentine in Main branch]
2018-07-31 02:23:26 -04:00
# undef LOCTEXT_NAMESPACE // "MeshMergeUtils"