2020-06-23 18:40:00 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "BakeMeshAttributeMapsTool.h"
# include "InteractiveToolManager.h"
# include "ToolBuilderUtil.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/DynamicMesh3.h"
# include "DynamicMesh/DynamicMeshAttributeSet.h"
# include "DynamicMesh/MeshTransforms.h"
2020-06-23 18:40:00 -04:00
# include "MeshDescriptionToDynamicMesh.h"
2021-05-26 17:14:57 -04:00
# include "Sampling/MeshNormalMapEvaluator.h"
# include "Sampling/MeshOcclusionMapEvaluator.h"
# include "Sampling/MeshCurvatureMapEvaluator.h"
# include "Sampling/MeshPropertyMapEvaluator.h"
# include "Sampling/MeshResampleImageEvaluator.h"
2020-06-23 18:40:00 -04:00
# include "ImageUtils.h"
2021-07-20 15:48:13 -04:00
# include "AssetUtils/Texture2DUtil.h"
2020-06-23 18:40:00 -04:00
2021-11-02 13:58:07 -04:00
# include "EngineAnalytics.h"
2021-02-23 18:03:26 -04:00
# include "TargetInterfaces/MaterialProvider.h"
# include "TargetInterfaces/MeshDescriptionProvider.h"
# include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
# include "TargetInterfaces/StaticMeshBackedTarget.h"
2021-10-18 15:59:42 -04:00
# include "TargetInterfaces/SkeletalMeshBackedTarget.h"
2021-02-23 18:03:26 -04:00
# include "ToolTargetManager.h"
2020-08-11 01:36:57 -04:00
// required to pass UStaticMesh asset so we can save at same location
2021-10-18 15:59:42 -04:00
# include "Engine/StaticMesh.h"
# include "Engine/SkeletalMesh.h"
# include "Components/StaticMeshComponent.h"
# include "Components/SkeletalMeshComponent.h"
# include "Components/DynamicMeshComponent.h"
2020-08-11 01:36:57 -04:00
2021-03-09 19:33:56 -04:00
using namespace UE : : Geometry ;
2020-06-23 18:40:00 -04:00
2021-03-09 19:33:56 -04:00
# define LOCTEXT_NAMESPACE "UBakeMeshAttributeMapsTool"
2020-06-23 18:40:00 -04:00
2021-06-03 15:29:38 -04:00
2020-06-23 18:40:00 -04:00
/*
* ToolBuilder
*/
2021-02-23 18:03:26 -04:00
const FToolTargetTypeRequirements & UBakeMeshAttributeMapsToolBuilder : : GetTargetRequirements ( ) const
{
static FToolTargetTypeRequirements TypeRequirements ( {
UMeshDescriptionProvider : : StaticClass ( ) ,
UPrimitiveComponentBackedTarget : : StaticClass ( ) ,
UMaterialProvider : : StaticClass ( )
} ) ;
return TypeRequirements ;
}
2020-06-23 18:40:00 -04:00
bool UBakeMeshAttributeMapsToolBuilder : : CanBuildTool ( const FToolBuilderState & SceneState ) const
{
2021-09-07 19:06:34 -04:00
const int32 NumTargets = SceneState . TargetManager - > CountSelectedAndTargetable ( SceneState , GetTargetRequirements ( ) ) ;
2021-10-18 15:59:42 -04:00
if ( NumTargets = = 1 | | NumTargets = = 2 )
{
bool bValidTargets = true ;
SceneState . TargetManager - > EnumerateSelectedAndTargetableComponents ( SceneState , GetTargetRequirements ( ) ,
[ & bValidTargets ] ( UActorComponent * Component )
{
UStaticMeshComponent * StaticMesh = Cast < UStaticMeshComponent > ( Component ) ;
USkeletalMeshComponent * SkeletalMesh = Cast < USkeletalMeshComponent > ( Component ) ;
UDynamicMeshComponent * DynMesh = Cast < UDynamicMeshComponent > ( Component ) ;
bValidTargets = bValidTargets & & ( StaticMesh | | SkeletalMesh | | DynMesh ) ;
} ) ;
return bValidTargets ;
}
return false ;
2020-06-23 18:40:00 -04:00
}
2021-11-23 09:42:40 -05:00
UMultiSelectionMeshEditingTool * UBakeMeshAttributeMapsToolBuilder : : CreateNewTool ( const FToolBuilderState & SceneState ) const
2020-06-23 18:40:00 -04:00
{
2021-11-23 09:42:40 -05:00
return NewObject < UBakeMeshAttributeMapsTool > ( SceneState . ToolManager ) ;
2020-06-23 18:40:00 -04:00
}
2021-10-21 10:53:58 -04:00
const TArray < FString > & UBakeMeshAttributeMapsToolProperties : : GetMapPreviewNamesFunc ( )
{
return MapPreviewNamesList ;
}
2021-04-12 17:10:46 -04:00
/*
* Operators
*/
2020-09-01 14:07:48 -04:00
2021-06-03 15:29:38 -04:00
class FMeshMapBakerOp : public TGenericDataOperator < FMeshMapBaker >
2021-04-12 17:10:46 -04:00
{
public :
2021-08-31 15:23:35 -04:00
using ImagePtr = TSharedPtr < UE : : Geometry : : TImageBuilder < FVector4f > , ESPMode : : ThreadSafe > ;
2021-06-03 15:29:38 -04:00
// General bake settings
2021-05-17 16:01:01 -04:00
TSharedPtr < UE : : Geometry : : FDynamicMesh3 , ESPMode : : ThreadSafe > DetailMesh ;
TSharedPtr < UE : : Geometry : : FDynamicMeshAABBTree3 , ESPMode : : ThreadSafe > DetailSpatial ;
2021-08-31 15:23:35 -04:00
TSharedPtr < UE : : Geometry : : TMeshTangents < double > , ESPMode : : ThreadSafe > DetailMeshTangents ;
2022-01-31 12:52:55 -05:00
UE : : Geometry : : FDynamicMesh3 * BaseMesh = nullptr ;
2021-05-17 16:01:01 -04:00
TUniquePtr < UE : : Geometry : : FMeshMapBaker > Baker ;
2021-11-24 12:49:18 -05:00
UBakeMeshAttributeMapsTool : : FBakeSettings BakeSettings ;
2021-06-03 15:29:38 -04:00
TSharedPtr < UE : : Geometry : : TMeshTangents < double > , ESPMode : : ThreadSafe > BaseMeshTangents ;
2022-01-31 12:52:55 -05:00
TSharedPtr < TArray < int32 > , ESPMode : : ThreadSafe > BaseMeshUVCharts ;
2022-03-25 13:52:51 -04:00
bool bIsBakeToSelf = false ;
2022-04-12 18:19:08 -04:00
ImagePtr SampleFilterMask ;
2021-05-17 16:01:01 -04:00
2021-06-03 15:29:38 -04:00
// Map Type settings
EBakeMapType Maps ;
2021-07-13 13:40:52 -04:00
FNormalMapSettings NormalSettings ;
FOcclusionMapSettings OcclusionSettings ;
FCurvatureMapSettings CurvatureSettings ;
FMeshPropertyMapSettings PropertySettings ;
2021-11-24 12:49:18 -05:00
FTexture2DSettings TextureSettings ;
FTexture2DSettings MultiTextureSettings ;
2021-06-03 15:29:38 -04:00
2021-08-31 15:23:35 -04:00
// NormalMap settings
ImagePtr DetailMeshNormalMap ;
int32 DetailMeshNormalUVLayer = 0 ;
2022-02-18 15:34:48 -05:00
IMeshBakerDetailSampler : : EBakeDetailNormalSpace DetailMeshNormalSpace = IMeshBakerDetailSampler : : EBakeDetailNormalSpace : : Tangent ;
2021-08-31 15:23:35 -04:00
2021-06-03 15:29:38 -04:00
// Texture2DImage & MultiTexture settings
ImagePtr TextureImage ;
2021-11-18 14:37:34 -05:00
TArray < ImagePtr > MaterialIDTextures ;
2021-06-03 15:29:38 -04:00
// Begin TGenericDataOperator interface
2021-04-12 17:10:46 -04:00
virtual void CalculateResult ( FProgressCancel * Progress ) override
{
2021-05-17 16:01:01 -04:00
Baker = MakeUnique < FMeshMapBaker > ( ) ;
Baker - > CancelF = [ Progress ] ( ) {
2021-04-12 17:10:46 -04:00
return Progress & & Progress - > Cancelled ( ) ;
} ;
2021-05-17 16:01:01 -04:00
Baker - > SetTargetMesh ( BaseMesh ) ;
2021-11-24 12:49:18 -05:00
Baker - > SetTargetMeshUVLayer ( BakeSettings . TargetUVLayer ) ;
Baker - > SetDimensions ( BakeSettings . Dimensions ) ;
Baker - > SetProjectionDistance ( BakeSettings . ProjectionDistance ) ;
Baker - > SetSamplesPerPixel ( BakeSettings . SamplesPerPixel ) ;
2022-01-31 12:52:55 -05:00
Baker - > SetTargetMeshUVCharts ( BaseMeshUVCharts . Get ( ) ) ;
2021-05-17 16:01:01 -04:00
Baker - > SetTargetMeshTangents ( BaseMeshTangents ) ;
2022-03-25 13:52:51 -04:00
if ( bIsBakeToSelf )
{
Baker - > SetCorrespondenceStrategy ( FMeshBaseBaker : : ECorrespondenceStrategy : : Identity ) ;
}
2022-04-12 18:19:08 -04:00
if ( SampleFilterMask )
{
Baker - > SampleFilterF = [ this ] ( const FVector2i & ImageCoords , const FVector2d & UV , int32 TriID )
{
2022-04-13 21:13:17 -04:00
const FVector4f Mask = SampleFilterMask - > BilinearSampleUV < float > ( UV , FVector4f : : One ( ) ) ;
return ( Mask . X + Mask . Y + Mask . Z ) / 3 ;
2022-04-12 18:19:08 -04:00
} ;
}
2021-09-07 19:06:34 -04:00
FMeshBakerDynamicMeshSampler DetailSampler ( DetailMesh . Get ( ) , DetailSpatial . Get ( ) , DetailMeshTangents . Get ( ) ) ;
Baker - > SetDetailSampler ( & DetailSampler ) ;
2021-06-03 15:29:38 -04:00
2021-11-26 21:57:52 -05:00
// Occlusion evaluator is shared by both AmbientOcclusion and BentNormal.
// Only initialize it once. OcclusionType is initialized to None. Callers
// must manually update the OcclusionType.
auto InitOcclusionEval = [ this ] ( TSharedPtr < FMeshOcclusionMapEvaluator > & Eval )
{
if ( ! Eval )
{
Eval = MakeShared < FMeshOcclusionMapEvaluator > ( ) ;
Eval - > OcclusionType = EMeshOcclusionMapType : : None ;
Eval - > NumOcclusionRays = OcclusionSettings . OcclusionRays ;
Eval - > MaxDistance = OcclusionSettings . MaxDistance ;
Eval - > SpreadAngle = OcclusionSettings . SpreadAngle ;
Eval - > BiasAngleDeg = OcclusionSettings . BiasAngle ;
Baker - > AddEvaluator ( Eval ) ;
}
} ;
TSharedPtr < FMeshOcclusionMapEvaluator > OcclusionEval ;
for ( const EBakeMapType MapType : ENUM_EBAKEMAPTYPE_ALL )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
switch ( BakeSettings . BakeMapTypes & MapType )
2021-06-03 15:29:38 -04:00
{
2021-10-21 10:53:58 -04:00
case EBakeMapType : : TangentSpaceNormal :
2021-06-03 15:29:38 -04:00
{
TSharedPtr < FMeshNormalMapEvaluator , ESPMode : : ThreadSafe > NormalEval = MakeShared < FMeshNormalMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
2022-02-18 15:34:48 -05:00
DetailSampler . SetNormalTextureMap ( DetailMesh . Get ( ) , IMeshBakerDetailSampler : : FBakeDetailNormalTexture ( DetailMeshNormalMap . Get ( ) , DetailMeshNormalUVLayer , DetailMeshNormalSpace ) ) ;
2021-09-15 20:13:36 -04:00
Baker - > AddEvaluator ( NormalEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
case EBakeMapType : : AmbientOcclusion :
{
2021-11-26 21:57:52 -05:00
InitOcclusionEval ( OcclusionEval ) ;
2022-01-06 16:44:09 +00:00
OcclusionEval - > OcclusionType | = EMeshOcclusionMapType : : AmbientOcclusion ;
break ;
2021-11-26 21:57:52 -05:00
}
case EBakeMapType : : BentNormal :
{
InitOcclusionEval ( OcclusionEval ) ;
OcclusionEval - > OcclusionType | = EMeshOcclusionMapType : : BentNormal ;
2022-01-06 16:44:09 +00:00
break ;
2021-06-03 15:29:38 -04:00
}
case EBakeMapType : : Curvature :
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshCurvatureMapEvaluator , ESPMode : : ThreadSafe > CurvatureEval = MakeShared < FMeshCurvatureMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
CurvatureEval - > RangeScale = FMathd : : Clamp ( CurvatureSettings . RangeMultiplier , 0.0001 , 1000.0 ) ;
CurvatureEval - > MinRangeScale = FMathd : : Clamp ( CurvatureSettings . MinRangeMultiplier , 0.0 , 1.0 ) ;
CurvatureEval - > UseCurvatureType = ( FMeshCurvatureMapEvaluator : : ECurvatureType ) CurvatureSettings . CurvatureType ;
CurvatureEval - > UseColorMode = ( FMeshCurvatureMapEvaluator : : EColorMode ) CurvatureSettings . ColorMode ;
CurvatureEval - > UseClampMode = ( FMeshCurvatureMapEvaluator : : EClampMode ) CurvatureSettings . ClampMode ;
Baker - > AddEvaluator ( CurvatureEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
2021-10-21 10:53:58 -04:00
case EBakeMapType : : ObjectSpaceNormal :
2021-06-03 15:29:38 -04:00
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > PropertyEval = MakeShared < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
PropertyEval - > Property = EMeshPropertyMapType : : Normal ;
2022-02-18 15:34:48 -05:00
DetailSampler . SetNormalTextureMap ( DetailMesh . Get ( ) , IMeshBakerDetailSampler : : FBakeDetailNormalTexture ( DetailMeshNormalMap . Get ( ) , DetailMeshNormalUVLayer , DetailMeshNormalSpace ) ) ;
2021-09-15 20:13:36 -04:00
Baker - > AddEvaluator ( PropertyEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
2021-10-21 10:53:58 -04:00
case EBakeMapType : : FaceNormal :
2021-06-03 15:29:38 -04:00
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > PropertyEval = MakeShared < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
PropertyEval - > Property = EMeshPropertyMapType : : FacetNormal ;
Baker - > AddEvaluator ( PropertyEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
2021-10-21 10:53:58 -04:00
case EBakeMapType : : Position :
2021-06-03 15:29:38 -04:00
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > PropertyEval = MakeShared < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
PropertyEval - > Property = EMeshPropertyMapType : : Position ;
Baker - > AddEvaluator ( PropertyEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
case EBakeMapType : : MaterialID :
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > PropertyEval = MakeShared < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
PropertyEval - > Property = EMeshPropertyMapType : : MaterialID ;
Baker - > AddEvaluator ( PropertyEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
2021-10-21 10:53:58 -04:00
case EBakeMapType : : VertexColor :
2021-07-13 13:40:52 -04:00
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > PropertyEval = MakeShared < FMeshPropertyMapEvaluator , ESPMode : : ThreadSafe > ( ) ;
PropertyEval - > Property = EMeshPropertyMapType : : VertexColor ;
Baker - > AddEvaluator ( PropertyEval ) ;
2021-07-13 13:40:52 -04:00
break ;
}
2021-10-21 10:53:58 -04:00
case EBakeMapType : : Texture :
2021-06-03 15:29:38 -04:00
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshResampleImageEvaluator , ESPMode : : ThreadSafe > TextureEval = MakeShared < FMeshResampleImageEvaluator , ESPMode : : ThreadSafe > ( ) ;
2021-11-24 19:19:10 -05:00
DetailSampler . SetTextureMap ( DetailMesh . Get ( ) , IMeshBakerDetailSampler : : FBakeDetailTexture ( TextureImage . Get ( ) , TextureSettings . UVLayer ) ) ;
2021-09-15 20:13:36 -04:00
Baker - > AddEvaluator ( TextureEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
case EBakeMapType : : MultiTexture :
{
2021-09-15 20:13:36 -04:00
TSharedPtr < FMeshMultiResampleImageEvaluator , ESPMode : : ThreadSafe > TextureEval = MakeShared < FMeshMultiResampleImageEvaluator , ESPMode : : ThreadSafe > ( ) ;
2021-11-24 12:49:18 -05:00
TextureEval - > DetailUVLayer = MultiTextureSettings . UVLayer ;
2021-11-18 14:37:34 -05:00
TextureEval - > MultiTextures = MaterialIDTextures ;
2021-09-15 20:13:36 -04:00
Baker - > AddEvaluator ( TextureEval ) ;
2021-06-03 15:29:38 -04:00
break ;
}
default :
break ;
}
}
2021-04-12 17:10:46 -04:00
Baker - > Bake ( ) ;
SetResult ( MoveTemp ( Baker ) ) ;
}
2021-06-03 15:29:38 -04:00
// End TGenericDataOperator interface
2021-04-30 17:04:37 -04:00
} ;
2020-06-23 18:40:00 -04:00
/*
* Tool
*/
void UBakeMeshAttributeMapsTool : : Setup ( )
{
2021-11-08 21:54:53 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE ( UBakeMeshAttributeMapsTool : : Setup ) ;
2021-09-13 17:51:19 -04:00
Super : : Setup ( ) ;
2020-06-23 18:40:00 -04:00
2021-08-24 09:24:57 -04:00
// Initialize preview mesh
2021-02-23 18:03:26 -04:00
bIsBakeToSelf = ( Targets . Num ( ) = = 1 ) ;
2020-09-01 14:07:48 -04:00
2021-08-24 09:24:57 -04:00
PreviewMesh - > ProcessMesh ( [ this ] ( const FDynamicMesh3 & Mesh )
{
2021-11-24 12:49:18 -05:00
TargetMesh . Copy ( Mesh ) ;
TargetSpatial . SetMesh ( & TargetMesh , true ) ;
TargetMeshTangents = MakeShared < FMeshTangentsd , ESPMode : : ThreadSafe > ( & TargetMesh ) ;
TargetMeshTangents - > CopyTriVertexTangents ( Mesh ) ;
2021-08-24 09:24:57 -04:00
} ) ;
2021-11-18 14:37:34 -05:00
UToolTarget * Target = Targets [ 0 ] ;
2021-08-31 15:23:35 -04:00
UToolTarget * DetailTarget = Targets [ bIsBakeToSelf ? 0 : 1 ] ;
2021-11-18 14:37:34 -05:00
// Setup tool property sets
2021-08-31 15:23:35 -04:00
2021-11-30 16:34:23 -05:00
Settings = NewObject < UBakeMeshAttributeMapsToolProperties > ( this ) ;
Settings - > RestoreProperties ( this ) ;
AddToolPropertySource ( Settings ) ;
Settings - > WatchProperty ( Settings - > MapTypes , [ this ] ( int32 ) { OpState | = EBakeOpState : : Evaluate ; UpdateOnModeChange ( ) ; } ) ;
Settings - > WatchProperty ( Settings - > MapPreview , [ this ] ( FString ) { UpdateVisualization ( ) ; GetToolManager ( ) - > PostInvalidation ( ) ; } ) ;
Settings - > WatchProperty ( Settings - > Resolution , [ this ] ( EBakeTextureResolution ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
Settings - > WatchProperty ( Settings - > BitDepth , [ this ] ( EBakeTextureBitDepth ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
Settings - > WatchProperty ( Settings - > SamplesPerPixel , [ this ] ( EBakeTextureSamplesPerPixel ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2022-04-12 18:19:08 -04:00
Settings - > WatchProperty ( Settings - > SampleFilterMask , [ this ] ( UTexture2D * ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2021-11-30 16:34:23 -05:00
2021-11-24 19:19:10 -05:00
InputMeshSettings = NewObject < UBakeInputMeshProperties > ( this ) ;
InputMeshSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( InputMeshSettings ) ;
SetToolPropertySourceEnabled ( InputMeshSettings , true ) ;
InputMeshSettings - > bHasTargetUVLayer = true ;
InputMeshSettings - > bHasSourceNormalMap = true ;
InputMeshSettings - > TargetStaticMesh = GetStaticMeshTarget ( Target ) ;
InputMeshSettings - > TargetSkeletalMesh = GetSkeletalMeshTarget ( Target ) ;
InputMeshSettings - > TargetDynamicMesh = GetDynamicMeshTarget ( Target ) ;
InputMeshSettings - > SourceStaticMesh = ! bIsBakeToSelf ? GetStaticMeshTarget ( DetailTarget ) : nullptr ;
InputMeshSettings - > SourceSkeletalMesh = ! bIsBakeToSelf ? GetSkeletalMeshTarget ( DetailTarget ) : nullptr ;
InputMeshSettings - > SourceDynamicMesh = ! bIsBakeToSelf ? GetDynamicMeshTarget ( DetailTarget ) : nullptr ;
InputMeshSettings - > SourceNormalMap = nullptr ;
UpdateUVLayerNames ( InputMeshSettings - > TargetUVLayer , InputMeshSettings - > TargetUVLayerNamesList , TargetMesh ) ;
2022-01-04 09:23:02 -05:00
InputMeshSettings - > WatchProperty ( InputMeshSettings - > bHideSourceMesh , [ this ] ( bool bState ) { SetSourceObjectVisible ( ! bState ) ; } ) ;
2021-11-24 19:19:10 -05:00
InputMeshSettings - > WatchProperty ( InputMeshSettings - > TargetUVLayer , [ this ] ( FString ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
InputMeshSettings - > WatchProperty ( InputMeshSettings - > ProjectionDistance , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
InputMeshSettings - > WatchProperty ( InputMeshSettings - > bProjectionInWorldSpace , [ this ] ( bool ) { OpState | = EBakeOpState : : EvaluateDetailMesh ; } ) ;
InputMeshSettings - > WatchProperty ( InputMeshSettings - > SourceNormalMapUVLayer , [ this ] ( FString ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
InputMeshSettings - > WatchProperty ( InputMeshSettings - > SourceNormalMap , [ this ] ( UTexture2D * )
2021-08-31 15:23:35 -04:00
{
// Only invalidate detail mesh if we need to recompute tangents.
2022-02-18 15:34:48 -05:00
if ( ! DetailMeshTangents & & InputMeshSettings - > SourceNormalSpace = = EBakeNormalSpace : : Tangent )
{
OpState | = EBakeOpState : : EvaluateDetailMesh ;
}
OpState | = EBakeOpState : : Evaluate ;
} ) ;
InputMeshSettings - > WatchProperty ( InputMeshSettings - > SourceNormalSpace , [ this ] ( EBakeNormalSpace Space )
{
if ( ! DetailMeshTangents & & Space = = EBakeNormalSpace : : Tangent )
2021-08-31 15:23:35 -04:00
{
2021-11-03 21:48:49 -04:00
OpState | = EBakeOpState : : EvaluateDetailMesh ;
2021-08-31 15:23:35 -04:00
}
2021-11-23 16:20:05 -05:00
OpState | = EBakeOpState : : Evaluate ;
2021-08-31 15:23:35 -04:00
} ) ;
2022-01-04 09:23:02 -05:00
SetSourceObjectVisible ( ! InputMeshSettings - > bHideSourceMesh ) ;
2021-11-18 14:37:34 -05:00
2021-11-30 16:34:23 -05:00
ResultSettings = NewObject < UBakeMeshAttributeMapsResultToolProperties > ( this ) ;
ResultSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( ResultSettings ) ;
SetToolPropertySourceEnabled ( ResultSettings , true ) ;
2021-08-24 09:24:57 -04:00
2020-06-23 18:40:00 -04:00
2021-11-24 12:49:18 -05:00
OcclusionSettings = NewObject < UBakeOcclusionMapToolProperties > ( this ) ;
OcclusionSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( OcclusionSettings ) ;
SetToolPropertySourceEnabled ( OcclusionSettings , false ) ;
OcclusionSettings - > WatchProperty ( OcclusionSettings - > OcclusionRays , [ this ] ( int32 ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
OcclusionSettings - > WatchProperty ( OcclusionSettings - > MaxDistance , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
OcclusionSettings - > WatchProperty ( OcclusionSettings - > SpreadAngle , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
OcclusionSettings - > WatchProperty ( OcclusionSettings - > BiasAngle , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2020-09-01 14:07:48 -04:00
2021-11-24 12:49:18 -05:00
CurvatureSettings = NewObject < UBakeCurvatureMapToolProperties > ( this ) ;
CurvatureSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( CurvatureSettings ) ;
SetToolPropertySourceEnabled ( CurvatureSettings , false ) ;
CurvatureSettings - > WatchProperty ( CurvatureSettings - > ColorRangeMultiplier , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
CurvatureSettings - > WatchProperty ( CurvatureSettings - > MinRangeMultiplier , [ this ] ( float ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
CurvatureSettings - > WatchProperty ( CurvatureSettings - > CurvatureType , [ this ] ( EBakeCurvatureTypeMode ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
CurvatureSettings - > WatchProperty ( CurvatureSettings - > ColorMapping , [ this ] ( EBakeCurvatureColorMode ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
CurvatureSettings - > WatchProperty ( CurvatureSettings - > Clamping , [ this ] ( EBakeCurvatureClampMode ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2020-09-01 14:07:48 -04:00
2021-11-24 12:49:18 -05:00
TextureSettings = NewObject < UBakeTexture2DProperties > ( this ) ;
TextureSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( TextureSettings ) ;
SetToolPropertySourceEnabled ( TextureSettings , false ) ;
2021-11-26 09:39:26 -05:00
TextureSettings - > WatchProperty ( TextureSettings - > UVLayer , [ this ] ( FString ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2021-11-24 12:49:18 -05:00
TextureSettings - > WatchProperty ( TextureSettings - > SourceTexture , [ this ] ( UTexture2D * ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2020-09-01 14:07:48 -04:00
2021-11-24 12:49:18 -05:00
MultiTextureSettings = NewObject < UBakeMultiTexture2DProperties > ( this ) ;
MultiTextureSettings - > RestoreProperties ( this ) ;
AddToolPropertySource ( MultiTextureSettings ) ;
SetToolPropertySourceEnabled ( MultiTextureSettings , false ) ;
2021-04-30 17:04:37 -04:00
2021-11-24 12:49:18 -05:00
auto SetDirtyCallback = [ this ] ( decltype ( MultiTextureSettings - > MaterialIDSourceTextures ) ) { OpState | = EBakeOpState : : Evaluate ; } ;
auto NotEqualsCallback = [ ] ( const decltype ( MultiTextureSettings - > MaterialIDSourceTextures ) & A , const decltype ( MultiTextureSettings - > MaterialIDSourceTextures ) & B ) - > bool { return A ! = B ; } ;
MultiTextureSettings - > WatchProperty ( MultiTextureSettings - > MaterialIDSourceTextures , SetDirtyCallback , NotEqualsCallback ) ;
2021-11-26 09:39:26 -05:00
MultiTextureSettings - > WatchProperty ( MultiTextureSettings - > UVLayer , [ this ] ( FString ) { OpState | = EBakeOpState : : Evaluate ; } ) ;
2021-11-24 12:49:18 -05:00
UpdateMultiTextureMaterialIDs ( DetailTarget , MultiTextureSettings - > AllSourceTextures , MultiTextureSettings - > MaterialIDSourceTextures ) ;
2020-06-23 18:40:00 -04:00
2021-06-03 15:29:38 -04:00
UpdateOnModeChange ( ) ;
2020-06-23 18:40:00 -04:00
2021-11-02 13:58:07 -04:00
UpdateDetailMesh ( ) ;
2020-06-23 18:40:00 -04:00
2021-02-08 17:02:09 -04:00
SetToolDisplayName ( LOCTEXT ( " ToolName " , " Bake Textures " ) ) ;
2020-06-23 18:40:00 -04:00
GetToolManager ( ) - > DisplayMessage (
2021-02-08 17:02:09 -04:00
LOCTEXT ( " OnStartTool " , " Bake Maps. Select Bake Mesh (LowPoly) first, then (optionally) Detail Mesh second. Texture Assets will be created on Accept. " ) ,
2020-06-23 18:40:00 -04:00
EToolMessageLevel : : UserNotification ) ;
2021-09-13 17:51:19 -04:00
2021-11-02 13:58:07 -04:00
PostSetup ( ) ;
2020-06-23 18:40:00 -04:00
}
2020-09-01 14:07:48 -04:00
bool UBakeMeshAttributeMapsTool : : CanAccept ( ) const
{
2021-11-18 14:37:34 -05:00
const bool bValidOp = ( OpState & EBakeOpState : : Invalid ) ! = EBakeOpState : : Invalid ;
bool bCanAccept = bValidOp & & Compute ? Compute - > HaveValidResult ( ) : false ;
2021-04-12 17:10:46 -04:00
if ( bCanAccept )
2021-04-08 14:32:07 -04:00
{
2021-06-03 15:29:38 -04:00
// Allow Accept if all non-None types have valid results.
2021-11-30 16:34:23 -05:00
for ( const TTuple < EBakeMapType , TObjectPtr < UTexture2D > > & Result : ResultSettings - > Result )
2021-04-12 17:10:46 -04:00
{
2021-10-21 10:53:58 -04:00
bCanAccept = bCanAccept & & Result . Get < 1 > ( ) ;
2021-04-12 17:10:46 -04:00
}
2021-04-08 14:32:07 -04:00
}
return bCanAccept ;
2020-09-01 14:07:48 -04:00
}
2021-05-17 16:01:01 -04:00
TUniquePtr < UE : : Geometry : : TGenericDataOperator < FMeshMapBaker > > UBakeMeshAttributeMapsTool : : MakeNewOperator ( )
2021-04-12 17:10:46 -04:00
{
2021-06-03 15:29:38 -04:00
TUniquePtr < FMeshMapBakerOp > Op = MakeUnique < FMeshMapBakerOp > ( ) ;
Op - > DetailMesh = DetailMesh ;
Op - > DetailSpatial = DetailSpatial ;
2021-11-24 12:49:18 -05:00
Op - > BaseMesh = & TargetMesh ;
Op - > BakeSettings = CachedBakeSettings ;
2022-01-31 12:52:55 -05:00
Op - > BaseMeshUVCharts = TargetMeshUVCharts ;
2022-03-25 13:52:51 -04:00
Op - > bIsBakeToSelf = bIsBakeToSelf ;
2022-04-12 18:19:08 -04:00
Op - > SampleFilterMask = CachedSampleFilterMask ;
2021-05-17 16:01:01 -04:00
2021-10-21 10:53:58 -04:00
constexpr EBakeMapType RequiresTangents = EBakeMapType : : TangentSpaceNormal | EBakeMapType : : BentNormal ;
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & RequiresTangents ) )
2021-04-12 17:10:46 -04:00
{
2021-11-24 12:49:18 -05:00
Op - > BaseMeshTangents = TargetMeshTangents ;
2021-04-12 17:10:46 -04:00
}
2021-06-03 15:29:38 -04:00
2021-08-31 15:23:35 -04:00
if ( CachedDetailNormalMap )
{
Op - > DetailMeshTangents = DetailMeshTangents ;
Op - > DetailMeshNormalMap = CachedDetailNormalMap ;
Op - > DetailMeshNormalUVLayer = CachedDetailMeshSettings . UVLayer ;
2022-02-18 15:34:48 -05:00
Op - > DetailMeshNormalSpace = CachedDetailMeshSettings . NormalSpace = = EBakeNormalSpace : : Tangent ?
IMeshBakerDetailSampler : : EBakeDetailNormalSpace : : Tangent : IMeshBakerDetailSampler : : EBakeDetailNormalSpace : : Object ;
2021-08-31 15:23:35 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : TangentSpaceNormal ) )
2021-04-12 17:10:46 -04:00
{
2021-06-03 15:29:38 -04:00
Op - > NormalSettings = CachedNormalMapSettings ;
2021-04-12 17:10:46 -04:00
}
2021-06-03 15:29:38 -04:00
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : AmbientOcclusion ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : BentNormal ) )
2021-04-12 17:10:46 -04:00
{
2021-06-03 15:29:38 -04:00
Op - > OcclusionSettings = CachedOcclusionMapSettings ;
2021-04-12 17:10:46 -04:00
}
2021-06-03 15:29:38 -04:00
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Curvature ) )
2021-04-12 17:10:46 -04:00
{
2021-06-03 15:29:38 -04:00
Op - > CurvatureSettings = CachedCurvatureMapSettings ;
2021-04-12 17:10:46 -04:00
}
2021-06-03 15:29:38 -04:00
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : ObjectSpaceNormal ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : FaceNormal ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Position ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : MaterialID ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : VertexColor ) )
2021-04-12 17:10:46 -04:00
{
2021-06-03 15:29:38 -04:00
Op - > PropertySettings = CachedMeshPropertyMapSettings ;
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Texture ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
Op - > TextureSettings = CachedTexture2DSettings ;
2021-04-12 17:10:46 -04:00
Op - > TextureImage = CachedTextureImage ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : MultiTexture ) )
2021-06-03 15:29:38 -04:00
{
2021-11-26 09:39:26 -05:00
Op - > MultiTextureSettings = CachedMultiTexture2DSettings ;
2021-11-18 14:37:34 -05:00
Op - > MaterialIDTextures = CachedMultiTextures ;
2021-04-30 17:04:37 -04:00
}
2021-06-03 15:29:38 -04:00
return Op ;
2021-04-12 17:10:46 -04:00
}
2022-01-28 18:40:54 -05:00
void UBakeMeshAttributeMapsTool : : OnShutdown ( EToolShutdownType ShutdownType )
2020-06-23 18:40:00 -04:00
{
2021-11-08 21:54:53 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE ( UBakeMeshAttributeMapsTool : : Shutdown ) ;
2022-01-28 18:40:54 -05:00
Super : : OnShutdown ( ShutdownType ) ;
2021-09-13 17:51:19 -04:00
2020-06-23 18:40:00 -04:00
Settings - > SaveProperties ( this ) ;
2021-11-24 19:19:10 -05:00
InputMeshSettings - > SaveProperties ( this ) ;
2021-11-24 12:49:18 -05:00
OcclusionSettings - > SaveProperties ( this ) ;
CurvatureSettings - > SaveProperties ( this ) ;
TextureSettings - > SaveProperties ( this ) ;
MultiTextureSettings - > SaveProperties ( this ) ;
2020-06-23 18:40:00 -04:00
2022-01-04 09:23:02 -05:00
SetSourceObjectVisible ( true ) ;
2021-04-12 17:10:46 -04:00
if ( Compute )
{
Compute - > Shutdown ( ) ;
}
2021-09-13 17:51:19 -04:00
if ( ShutdownType = = EToolShutdownType : : Accept )
2020-06-23 18:40:00 -04:00
{
2021-10-18 15:59:42 -04:00
// Check if we have a source asset to identify a location to store the texture assets.
IStaticMeshBackedTarget * StaticMeshTarget = Cast < IStaticMeshBackedTarget > ( Targets [ 0 ] ) ;
UObject * SourceAsset = StaticMeshTarget ? StaticMeshTarget - > GetStaticMesh ( ) : nullptr ;
if ( ! SourceAsset )
{
// Check if our target is a Skeletal Mesh Asset
ISkeletalMeshBackedTarget * SkeletalMeshTarget = Cast < ISkeletalMeshBackedTarget > ( Targets [ 0 ] ) ;
SourceAsset = SkeletalMeshTarget ? SkeletalMeshTarget - > GetSkeletalMesh ( ) : nullptr ;
}
const UPrimitiveComponent * SourceComponent = UE : : ToolTarget : : GetTargetComponent ( Targets [ 0 ] ) ;
2021-11-30 16:34:23 -05:00
CreateTextureAssets ( ResultSettings - > Result , SourceComponent - > GetWorld ( ) , SourceAsset ) ;
2020-06-23 18:40:00 -04:00
}
}
2021-12-13 13:43:18 -05:00
bool UBakeMeshAttributeMapsTool : : ValidDetailMeshTangents ( )
{
if ( ! DetailMesh )
{
return false ;
}
if ( bCheckDetailMeshTangents )
{
bValidDetailMeshTangents = FDynamicMeshTangents ( DetailMesh . Get ( ) ) . HasValidTangents ( true ) ;
bCheckDetailMeshTangents = false ;
}
return bValidDetailMeshTangents ;
}
2020-09-01 14:07:48 -04:00
void UBakeMeshAttributeMapsTool : : UpdateDetailMesh ( )
2020-06-23 18:40:00 -04:00
{
2021-06-11 22:42:32 -04:00
UToolTarget * DetailTarget = Targets [ bIsBakeToSelf ? 0 : 1 ] ;
2021-11-24 19:19:10 -05:00
const bool bWantMeshTangents = ( InputMeshSettings - > SourceNormalMap ! = nullptr ) ;
2021-08-31 15:23:35 -04:00
DetailMesh = MakeShared < FDynamicMesh3 , ESPMode : : ThreadSafe > ( UE : : ToolTarget : : GetDynamicMeshCopy ( DetailTarget , bWantMeshTangents ) ) ;
2021-02-23 18:03:26 -04:00
2021-11-24 19:19:10 -05:00
if ( InputMeshSettings - > bProjectionInWorldSpace & & bIsBakeToSelf = = false )
2020-09-01 14:07:48 -04:00
{
2022-01-29 14:37:53 -05:00
const FTransformSRT3d DetailToWorld = UE : : ToolTarget : : GetLocalToWorldTransform ( DetailTarget ) ;
2020-09-01 14:07:48 -04:00
MeshTransforms : : ApplyTransform ( * DetailMesh , DetailToWorld ) ;
2022-01-29 14:37:53 -05:00
const FTransformSRT3d WorldToBase = UE : : ToolTarget : : GetLocalToWorldTransform ( Targets [ 0 ] ) ;
2022-05-12 12:08:26 -04:00
MeshTransforms : : ApplyTransformInverse ( * DetailMesh , WorldToBase ) ;
2020-09-01 14:07:48 -04:00
}
2021-11-02 13:58:07 -04:00
2021-02-17 11:50:23 -04:00
DetailSpatial = MakeShared < FDynamicMeshAABBTree3 , ESPMode : : ThreadSafe > ( ) ;
2020-09-01 14:07:48 -04:00
DetailSpatial - > SetMesh ( DetailMesh . Get ( ) , true ) ;
2021-08-31 15:23:35 -04:00
// Extract tangents if a DetailMesh normal map was provided.
if ( bWantMeshTangents )
{
DetailMeshTangents = MakeShared < FMeshTangentsd , ESPMode : : ThreadSafe > ( DetailMesh . Get ( ) ) ;
DetailMeshTangents - > CopyTriVertexTangents ( * DetailMesh ) ;
}
else
{
DetailMeshTangents = nullptr ;
}
2021-11-24 19:19:10 -05:00
UpdateUVLayerNames ( InputMeshSettings - > SourceNormalMapUVLayer , InputMeshSettings - > SourceUVLayerNamesList , * DetailMesh ) ;
2021-11-26 09:39:26 -05:00
UpdateUVLayerNames ( TextureSettings - > UVLayer , TextureSettings - > UVLayerNamesList , * DetailMesh ) ;
UpdateUVLayerNames ( MultiTextureSettings - > UVLayer , MultiTextureSettings - > UVLayerNamesList , * DetailMesh ) ;
2021-04-30 17:04:37 -04:00
2021-11-03 21:48:49 -04:00
// Clear detail mesh evaluation flag and mark evaluation.
OpState & = ~ EBakeOpState : : EvaluateDetailMesh ;
OpState | = EBakeOpState : : Evaluate ;
2021-11-24 12:49:18 -05:00
CachedBakeSettings = FBakeSettings ( ) ;
2020-09-01 14:07:48 -04:00
DetailMeshTimestamp + + ;
2020-06-23 18:40:00 -04:00
}
void UBakeMeshAttributeMapsTool : : UpdateResult ( )
{
2021-11-03 21:48:49 -04:00
if ( static_cast < bool > ( OpState & EBakeOpState : : EvaluateDetailMesh ) )
2020-09-01 14:07:48 -04:00
{
UpdateDetailMesh ( ) ;
}
2021-11-03 21:48:49 -04:00
if ( OpState = = EBakeOpState : : Clean )
2020-06-23 18:40:00 -04:00
{
return ;
}
2020-09-01 14:07:48 -04:00
// clear warning (ugh)
GetToolManager ( ) - > DisplayMessage ( FText ( ) , EToolMessageLevel : : UserWarning ) ;
2020-06-23 18:40:00 -04:00
int32 ImageSize = ( int32 ) Settings - > Resolution ;
FImageDimensions Dimensions ( ImageSize , ImageSize ) ;
2021-11-24 12:49:18 -05:00
FBakeSettings BakeSettings ;
BakeSettings . Dimensions = Dimensions ;
BakeSettings . BitDepth = Settings - > BitDepth ;
2021-11-24 19:19:10 -05:00
BakeSettings . TargetUVLayer = InputMeshSettings - > TargetUVLayerNamesList . IndexOfByKey ( InputMeshSettings - > TargetUVLayer ) ;
2021-11-24 12:49:18 -05:00
BakeSettings . DetailTimestamp = this - > DetailMeshTimestamp ;
2021-11-24 19:19:10 -05:00
BakeSettings . ProjectionDistance = InputMeshSettings - > ProjectionDistance ;
2021-11-24 12:49:18 -05:00
BakeSettings . SamplesPerPixel = ( int32 ) Settings - > SamplesPerPixel ;
2021-11-24 19:19:10 -05:00
BakeSettings . bProjectionInWorldSpace = InputMeshSettings - > bProjectionInWorldSpace ;
2020-06-23 18:40:00 -04:00
2021-11-02 13:58:07 -04:00
// Record the original map types and process the raw bitfield which may add
// additional targets.
2021-11-24 12:49:18 -05:00
BakeSettings . SourceBakeMapTypes = static_cast < EBakeMapType > ( Settings - > MapTypes ) ;
BakeSettings . BakeMapTypes = GetMapTypes ( Settings - > MapTypes ) ;
2021-06-03 15:29:38 -04:00
2021-04-12 17:10:46 -04:00
// update bake cache settings
2021-11-24 12:49:18 -05:00
if ( ! ( CachedBakeSettings = = BakeSettings ) )
2020-06-23 18:40:00 -04:00
{
2021-11-24 12:49:18 -05:00
CachedBakeSettings = BakeSettings ;
2020-11-17 22:32:38 -04:00
CachedNormalMapSettings = FNormalMapSettings ( ) ;
CachedOcclusionMapSettings = FOcclusionMapSettings ( ) ;
CachedCurvatureMapSettings = FCurvatureMapSettings ( ) ;
CachedMeshPropertyMapSettings = FMeshPropertyMapSettings ( ) ;
2021-11-24 12:49:18 -05:00
CachedTexture2DSettings = FTexture2DSettings ( ) ;
CachedMultiTexture2DSettings = FTexture2DSettings ( ) ;
2020-06-23 18:40:00 -04:00
}
2021-06-03 15:29:38 -04:00
// Clear our invalid bitflag to check again for valid inputs.
2021-11-03 21:48:49 -04:00
OpState & = ~ EBakeOpState : : Invalid ;
2021-06-03 15:29:38 -04:00
2021-12-13 13:43:18 -05:00
OpState | = UpdateResult_TargetMeshTangents ( CachedBakeSettings . BakeMapTypes ) ;
2021-08-31 15:23:35 -04:00
OpState | = UpdateResult_DetailNormalMap ( ) ;
2022-04-12 18:19:08 -04:00
OpState | = UpdateResult_SampleFilterMask ( Settings - > SampleFilterMask ) ;
2021-06-03 15:29:38 -04:00
// Update map type settings
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : TangentSpaceNormal ) )
2020-06-23 18:40:00 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_Normal ( CachedBakeSettings . Dimensions ) ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : AmbientOcclusion ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : BentNormal ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_Occlusion ( CachedBakeSettings . Dimensions ) ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Curvature ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_Curvature ( CachedBakeSettings . Dimensions ) ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : ObjectSpaceNormal ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : FaceNormal ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Position ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : MaterialID ) | |
( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : VertexColor ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_MeshProperty ( CachedBakeSettings . Dimensions ) ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : Texture ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_Texture2DImage ( CachedBakeSettings . Dimensions , DetailMesh . Get ( ) ) ;
2021-06-03 15:29:38 -04:00
}
2021-11-24 12:49:18 -05:00
if ( ( bool ) ( CachedBakeSettings . BakeMapTypes & EBakeMapType : : MultiTexture ) )
2021-06-03 15:29:38 -04:00
{
2021-11-24 12:49:18 -05:00
OpState | = UpdateResult_MultiTexture ( CachedBakeSettings . Dimensions , DetailMesh . Get ( ) ) ;
2020-06-23 18:40:00 -04:00
}
2021-04-12 17:10:46 -04:00
// Early exit if op input parameters are invalid.
2021-06-03 15:29:38 -04:00
if ( ( bool ) ( OpState & EBakeOpState : : Invalid ) )
2021-04-12 17:10:46 -04:00
{
2021-10-19 15:13:28 -04:00
InvalidateResults ( ) ;
2021-04-12 17:10:46 -04:00
return ;
}
2020-06-23 18:40:00 -04:00
2021-04-12 17:10:46 -04:00
// This should be the only point of compute invalidation to
// minimize synchronization issues.
2021-11-02 13:58:07 -04:00
InvalidateCompute ( ) ;
2020-06-23 18:40:00 -04:00
}
2021-12-13 13:43:18 -05:00
EBakeOpState UBakeMeshAttributeMapsTool : : UpdateResult_DetailMeshTangents ( EBakeMapType BakeType )
{
EBakeOpState ResultState = EBakeOpState : : Clean ;
const bool bNeedDetailMeshTangents = ( bool ) ( BakeType & ( EBakeMapType : : TangentSpaceNormal | EBakeMapType : : BentNormal ) ) ;
if ( bNeedDetailMeshTangents & & ! ValidDetailMeshTangents ( ) )
{
GetToolManager ( ) - > DisplayMessage ( LOCTEXT ( " InvalidSourceTangentsWarning " , " The Source Mesh does not have valid tangents. " ) , EToolMessageLevel : : UserWarning ) ;
ResultState = EBakeOpState : : Invalid ;
}
return ResultState ;
}
2021-08-31 15:23:35 -04:00
EBakeOpState UBakeMeshAttributeMapsTool : : UpdateResult_DetailNormalMap ( )
{
2021-11-03 21:48:49 -04:00
EBakeOpState ResultState = EBakeOpState : : Clean ;
2021-11-23 15:50:32 -05:00
2021-11-24 19:19:10 -05:00
const int DetailUVLayer = InputMeshSettings - > SourceUVLayerNamesList . IndexOfByKey ( InputMeshSettings - > SourceNormalMapUVLayer ) ;
2021-11-23 15:50:32 -05:00
const FDynamicMeshUVOverlay * UVOverlay = DetailMesh - > Attributes ( ) - > GetUVLayer ( DetailUVLayer ) ;
2021-08-31 15:23:35 -04:00
if ( UVOverlay = = nullptr )
{
2021-12-13 13:43:18 -05:00
GetToolManager ( ) - > DisplayMessage ( LOCTEXT ( " InvalidUVWarning " , " The Source Mesh does not have the selected UV layer " ) , EToolMessageLevel : : UserWarning ) ;
2021-08-31 15:23:35 -04:00
return EBakeOpState : : Invalid ;
}
2021-12-13 13:43:18 -05:00
if ( UTexture2D * DetailMeshNormalMap = InputMeshSettings - > SourceNormalMap )
2021-08-31 15:23:35 -04:00
{
CachedDetailNormalMap = MakeShared < UE : : Geometry : : TImageBuilder < FVector4f > , ESPMode : : ThreadSafe > ( ) ;
if ( ! UE : : AssetUtils : : ReadTexture ( DetailMeshNormalMap , * CachedDetailNormalMap , bPreferPlatformData ) )
{
// Report the failed texture read as a warning, but permit the bake to continue.
2021-12-13 13:43:18 -05:00
GetToolManager ( ) - > DisplayMessage ( LOCTEXT ( " CannotReadTextureWarning " , " Cannot read from the source normal map texture " ) , EToolMessageLevel : : UserWarning ) ;
2021-08-31 15:23:35 -04:00
}
2021-12-13 13:43:18 -05:00
// Validate detail mesh tangents for detail normal map
ResultState | = UpdateResult_DetailMeshTangents ( CachedBakeSettings . BakeMapTypes ) ;
2021-08-31 15:23:35 -04:00
}
else
{
CachedDetailNormalMap = nullptr ;
}
FDetailMeshSettings DetailMeshSettings ;
2021-11-23 15:50:32 -05:00
DetailMeshSettings . UVLayer = DetailUVLayer ;
2022-02-18 15:34:48 -05:00
DetailMeshSettings . NormalSpace = InputMeshSettings - > SourceNormalSpace ;
2021-08-31 15:23:35 -04:00
if ( ! ( CachedDetailMeshSettings = = DetailMeshSettings ) )
{
CachedDetailMeshSettings = DetailMeshSettings ;
2021-12-13 13:43:18 -05:00
ResultState | = EBakeOpState : : Evaluate ;
2021-08-31 15:23:35 -04:00
}
return ResultState ;
}
2020-06-23 18:40:00 -04:00
void UBakeMeshAttributeMapsTool : : UpdateVisualization ( )
{
2021-08-24 09:24:57 -04:00
PreviewMesh - > SetOverrideRenderMaterial ( PreviewMaterial ) ;
2021-06-03 15:29:38 -04:00
2021-10-21 10:53:58 -04:00
// Populate Settings->Result from CachedMaps
for ( const TTuple < EBakeMapType , TObjectPtr < UTexture2D > > & Map : CachedMaps )
2020-06-23 18:40:00 -04:00
{
2021-11-30 16:34:23 -05:00
if ( ResultSettings - > Result . Contains ( Map . Get < 0 > ( ) ) )
2021-10-21 10:53:58 -04:00
{
2021-11-30 16:34:23 -05:00
ResultSettings - > Result [ Map . Get < 0 > ( ) ] = Map . Get < 1 > ( ) ;
2021-10-21 10:53:58 -04:00
}
2021-06-03 15:29:38 -04:00
}
2021-11-30 16:34:23 -05:00
UpdatePreview ( Settings - > MapPreview , Settings - > MapPreviewNamesMap ) ;
2020-09-01 14:07:48 -04:00
}
void UBakeMeshAttributeMapsTool : : UpdateOnModeChange ( )
{
2021-11-30 16:34:23 -05:00
OnMapTypesUpdated (
static_cast < EBakeMapType > ( Settings - > MapTypes ) ,
ResultSettings - > Result ,
Settings - > MapPreview ,
Settings - > MapPreviewNamesList ,
Settings - > MapPreviewNamesMap ) ;
2021-10-21 10:53:58 -04:00
// Update tool property sets.
2021-11-24 12:49:18 -05:00
SetToolPropertySourceEnabled ( OcclusionSettings , false ) ;
SetToolPropertySourceEnabled ( CurvatureSettings , false ) ;
SetToolPropertySourceEnabled ( TextureSettings , false ) ;
SetToolPropertySourceEnabled ( MultiTextureSettings , false ) ;
2020-09-01 14:07:48 -04:00
2021-11-26 21:57:52 -05:00
for ( const EBakeMapType MapType : ENUM_EBAKEMAPTYPE_ALL )
2020-06-23 18:40:00 -04:00
{
2021-06-03 15:29:38 -04:00
switch ( ( EBakeMapType ) Settings - > MapTypes & MapType )
{
2021-10-21 10:53:58 -04:00
case EBakeMapType : : TangentSpaceNormal :
2021-06-03 15:29:38 -04:00
break ;
case EBakeMapType : : AmbientOcclusion :
case EBakeMapType : : BentNormal :
2021-11-24 12:49:18 -05:00
SetToolPropertySourceEnabled ( OcclusionSettings , true ) ;
2021-06-03 15:29:38 -04:00
break ;
case EBakeMapType : : Curvature :
2021-11-24 12:49:18 -05:00
SetToolPropertySourceEnabled ( CurvatureSettings , true ) ;
2021-06-03 15:29:38 -04:00
break ;
2021-10-21 10:53:58 -04:00
case EBakeMapType : : ObjectSpaceNormal :
case EBakeMapType : : FaceNormal :
case EBakeMapType : : Position :
2021-06-03 15:29:38 -04:00
case EBakeMapType : : MaterialID :
2021-10-21 10:53:58 -04:00
case EBakeMapType : : VertexColor :
2021-06-03 15:29:38 -04:00
break ;
2021-10-21 10:53:58 -04:00
case EBakeMapType : : Texture :
2021-11-24 12:49:18 -05:00
SetToolPropertySourceEnabled ( TextureSettings , true ) ;
2021-06-03 15:29:38 -04:00
break ;
case EBakeMapType : : MultiTexture :
2021-11-24 12:49:18 -05:00
SetToolPropertySourceEnabled ( MultiTextureSettings , true ) ;
2021-06-03 15:29:38 -04:00
break ;
default :
break ;
}
2020-06-23 18:40:00 -04:00
}
2021-10-19 15:13:28 -04:00
}
void UBakeMeshAttributeMapsTool : : InvalidateResults ( )
{
2021-11-30 16:34:23 -05:00
for ( TTuple < EBakeMapType , TObjectPtr < UTexture2D > > & Result : ResultSettings - > Result )
2021-10-21 10:53:58 -04:00
{
Result . Get < 1 > ( ) = nullptr ;
}
2020-06-23 18:40:00 -04:00
}
2021-11-02 13:58:07 -04:00
void UBakeMeshAttributeMapsTool : : GatherAnalytics ( FBakeAnalytics : : FMeshSettings & Data )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2021-11-24 12:49:18 -05:00
Data . NumTargetMeshTris = TargetMesh . TriangleCount ( ) ;
2021-11-02 13:58:07 -04:00
Data . NumDetailMesh = 1 ;
Data . NumDetailMeshTris = DetailMesh - > TriangleCount ( ) ;
}
}
2021-10-19 15:13:28 -04:00
2020-06-23 18:40:00 -04:00
# undef LOCTEXT_NAMESPACE