Files
UnrealEngine/Engine/Plugins/Enterprise/DatasmithCADImporter/Source/WireInterface/Private/WireInterfaceImpl.cpp
2025-05-18 13:04:45 +08:00

2299 lines
85 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "WireInterfaceImpl.h"
#include "Modules/ModuleManager.h"
#ifdef USE_OPENMODEL
#include "CADOptions.h"
#include "Containers/List.h"
#include "DatasmithImportOptions.h"
#include "DatasmithPayload.h"
#include "DatasmithSceneFactory.h"
#include "DatasmithUtils.h"
#include "GenericPlatform/GenericPlatformTLS.h"
#include "HAL/ConsoleManager.h"
#include "IDatasmithSceneElements.h"
#include "Misc/FileHelper.h"
#include "Misc/Paths.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "Utility/DatasmithMeshHelper.h"
#include "StaticMeshDescription.h"
#include "StaticMeshOperations.h"
#include "AliasModelToCADKernelConverter.h"
#include "AliasModelToTechSoftConverter.h" // requires Techsoft as public dependency
#include "CADInterfacesModule.h"
#if PLATFORM_WINDOWS
#include "Windows/AllowWindowsPlatformTypes.h"
#endif
#include <AlChannel.h>
#include <AlDagNode.h>
#include <AlGroupNode.h>
#include <AlLayer.h>
#include <AlLinkItem.h>
#include <AlList.h>
#include <AlMesh.h>
#include <AlMeshNode.h>
#include <AlPersistentID.h>
#include <AlRetrieveOptions.h>
#include <AlSet.h>
#include <AlSetMember.h>
#include <AlShader.h>
#include <AlShadingFieldItem.h>
#include <AlShell.h>
#include <AlShellNode.h>
#include <AlSurface.h>
#include <AlSurfaceNode.h>
#include <AlTesselate.h>
#include <AlTrimRegion.h>
#include <AlTM.h>
#include <AlUniverse.h>
#if PLATFORM_WINDOWS
#include "Windows/HideWindowsPlatformTypes.h"
#endif
#define LOCTEXT_NAMESPACE "WireInterface"
#define WRONG_VERSION_TEXT "Unsupported version of Alias detected. Please upgrade to Alias 2021.3 (or later version)."
#define TRACK_MESHELEMENT 0
#define MAKE_VISIBLE 0
#if MAKE_VISIBLE
#include "CompGeom/FitOrientedBox3.h"
#endif
namespace UE_DATASMITHWIRETRANSLATOR_NAMESPACE
{
#if TRACK_MESHELEMENT
//static const FString ToTrack(TEXT("shell_30181"));
//static const FString ToTrack(TEXT("Blend_srf_1395"));
//static const FString ToTrack(TEXT("M0047942"));
//static const FString ToTrack(TEXT("C5_31495_surf")); // G6
static const FString ToTrack(TEXT("Object__TRANSFORM_copy_2_surf")); // refrigerator
void MakeMeshVisible(FMeshDescription& MeshDescription);
#endif
#if WIRE_MEMORY_CHECK
int32 AllocatedObjects = 0;
int32 MaxAllocatedObjects = 0;
TSet<AlDagNode*> DagNodeSet;
TSet<AlObject*> ObjectSet;
#endif
static const FColor DefaultColor = FColor(200, 200, 200);
const uint64 LibAliasNext_Version = 0xffffffffffffffffull;
const uint64 LibAlias2025_0_0_Version = 8725724278030572;
const uint64 LibAlias2024_1_0_Version = 8444253596292024;
const uint64 LibAlias2023_1_0_Version = 8162778619576619;
const uint64 LibAlias2023_0_0_Version = 8162774324609149;
const uint64 LibAlias2022_2_0_Version = 7881307937833405;
const uint64 LibAlias2022_1_0_Version = 7881303642865885;
const uint64 LibAlias2022_0_1_Version = 7881299347964005;
const uint64 LibAlias2021_3_2_Version = 7599833027117059;
const uint64 LibAlias2021_3_1_Version = 7599824433840131;
const uint64 LibAlias2021_3_0_Version = 7599824424206339;
const uint64 LibAlias2021_Version = 7599824377020416;
const uint64 LibAlias2020_Version = 7318349414924288;
const uint64 LibAlias2019_Version = 5000000000000000;
#if defined(OPEN_MODEL_2020)
const uint64 LibAliasVersionMin = LibAlias2019_Version;
const uint64 LibAliasVersionMax = LibAlias2021_3_0_Version;
const FString AliasSdkVersion = TEXT("2020");
#elif defined(OPEN_MODEL_2021_3)
const uint64 LibAliasVersionMin = LibAlias2021_3_0_Version;
const uint64 LibAliasVersionMax = LibAlias2022_0_1_Version;
const FString AliasSdkVersion = TEXT("2021.3");
#elif defined(OPEN_MODEL_2022)
const uint64 LibAliasVersionMin = LibAlias2022_0_1_Version;
const uint64 LibAliasVersionMax = LibAlias2022_1_0_Version;
const FString AliasSdkVersion = TEXT("2022");
#elif defined(OPEN_MODEL_2022_1)
const uint64 LibAliasVersionMin = LibAlias2022_1_0_Version;
const uint64 LibAliasVersionMax = LibAlias2022_2_0_Version;
const FString AliasSdkVersion = TEXT("2022.1");
#elif defined(OPEN_MODEL_2022_2)
const uint64 LibAliasVersionMin = LibAlias2022_2_0_Version;
const uint64 LibAliasVersionMax = LibAlias2023_0_0_Version;
const FString AliasSdkVersion = TEXT("2022.2");
#elif defined(OPEN_MODEL_2023_0)
const uint64 LibAliasVersionMin = LibAlias2023_0_0_Version;
const uint64 LibAliasVersionMax = LibAlias2023_1_0_Version;
const FString AliasSdkVersion = TEXT("2023.0");
#elif defined(OPEN_MODEL_2023_1)
const uint64 LibAliasVersionMin = LibAlias2023_1_0_Version;
const uint64 LibAliasVersionMax = LibAlias2024_1_0_Version;
const FString AliasSdkVersion = TEXT("2023.1");
#elif defined(OPEN_MODEL_2024_1)
const uint64 LibAliasVersionMin = LibAlias2024_1_0_Version;
const uint64 LibAliasVersionMax = LibAlias2025_0_0_Version;
const FString AliasSdkVersion = TEXT("2024.1");
#elif defined(OPEN_MODEL_2025_0)
const uint64 LibAliasVersionMin = LibAlias2025_0_0_Version;
const uint64 LibAliasVersionMax = LibAliasNext_Version;
const FString AliasSdkVersion = TEXT("2025.0");
#endif
// Alias material management (to allow sew of BReps of different materials):
// To be compatible with "Retessellate" function, Alias material management as to be the same than CAD (TechSoft) import.
// As a reminder: the name and slot of UE Material from CAD is based on CAD material/color data i.e. RGBA Color components => "UE Material slot" (int32) and "UE Material name" (FString = FString::FromInt("UE Material slot"))
// UE Material Label is free.
//
// During Retessellate step, Color/Material of each CAD Faces are known, so "UE Material slot" can be deduced.
//
// For Alias import:
// Alias BRep is exported in CAD modeler (CADKernel, TechSoft, ...)
// Material is build in UE,
// From an Alias Material, a unique Color is generated.
// This Color is associated to the BRep Shell/face in the CAD modeler
// The name and slot of the associated UE Material is defined from this color
// So at the retessellate step, nothing changes from the CAD Retessellate process
//
// The unique Color of an Alias Material is defined as follows:
// TypeHash(Alias Material Name) => uint24 == 3 uint8 => RGB components of the color
FColor CreateShaderColorFromShaderName(const FString& ShaderName)
{
const uint32 ShaderHash = FCrc::Strihash_DEPRECATED(*ShaderName);
const uint32 Red = (ShaderHash & 0xff000000) >> 24;
const uint32 Green = (ShaderHash & 0x00ff0000) >> 16;
const uint32 Blue = (ShaderHash & 0x0000ff00) >> 8;
return FColor(Red, Green, Blue);
}
int32 CreateShaderId(const FColor& ShaderColor)
{
return FMath::Abs((int32)GetTypeHash(ShaderColor));
}
uint32 GetSceneFileHash(const FString& FullPath, const FString& FileName)
{
FFileStatData FileStatData = IFileManager::Get().GetStatData(*FullPath);
int64 FileSize = FileStatData.FileSize;
FDateTime ModificationTime = FileStatData.ModificationTime;
uint32 FileHash = GetTypeHash(FileName);
FileHash = HashCombine(FileHash, GetTypeHash(FileSize));
FileHash = HashCombine(FileHash, GetTypeHash(ModificationTime));
return FileHash;
}
bool GetConsoleBoolValue(const TCHAR* CVarName, bool bDefault)
{
const IConsoleVariable* ConsoleVariable = IConsoleManager::Get().FindConsoleVariable(CVarName);
return ConsoleVariable ? ConsoleVariable->GetBool() : bDefault;
}
bool FWireTranslatorImpl::Initialize(const TCHAR* InSceneFullName)
{
if (InSceneFullName)
{
statusCode Status = AlUniverse::initialize();
if (Status != sSuccess && Status != sAlreadyCreated)
{
UE_LOG(LogWireInterface, Error, TEXT("Cannot initialize OpenModel SDK. Import is aborted."));
return false;
}
const TStringConversion Result = StringCast<ANSICHAR>(InSceneFullName);
char OpenModelVersion[10];
if (bool(AlUniverse::isWireFile(Result.Get(), OpenModelVersion)))
{
SceneFullPath = InSceneFullName;
SceneVersion = StringCast<TCHAR>(OpenModelVersion).Get();
}
else
{
UE_LOG(LogWireInterface, Error, TEXT("Cannot load %s with the selected OpenModel SDK."), InSceneFullName);
return false;
}
}
return true;
}
FWireTranslatorImpl::~FWireTranslatorImpl()
{
if (bSceneLoaded)
{
FLayerContainer::Reset();
MeshElementToParametricNode.Reset();
MeshElementToMeshNode.Reset();
MeshElementToBodyNode.Reset();
MeshElementToPatchMesh.Reset();
EncounteredNodes.Reset();
#if WIRE_MEMORY_CHECK
if (!ensure(AllocatedObjects == 0))
{
for (AlObject* Object : ObjectSet)
{
if (AlIsValid(Object))
{
AlObjectType Type = Object->type();
printf(">>> %d\n", Type);
}
else
{
ensure(false);
}
}
}
#endif
}
bSceneLoaded = false;
}
void FWireTranslatorImpl::SetImportSettings(const FWireSettings& Settings)
{
WireSettings = Settings;
WireSettings.bUseCADKernel = !CADLibrary::FImportParameters::bGDisableCADKernelTessellation;
if (CADModelConverter)
{
CADModelConverter->SetImportParameters(Settings.ChordTolerance, Settings.MaxEdgeLength, Settings.NormalTolerance, (CADLibrary::EStitchingTechnique)Settings.StitchingTechnique);
}
}
// Wire file parsing
bool FWireTranslatorImpl::Load(TSharedPtr<IDatasmithScene> InScene)
{
UE_LOG(LogWireInterface, Display, TEXT("CAD translation [%s]."), *SceneFullPath);
UE_LOG(LogWireInterface, Display, TEXT(" - File version: Alias %s"), *SceneVersion);
UE_LOG(LogWireInterface, Display, TEXT(" - Parsing Library: Alias %s"), *AliasSdkVersion);
UE_LOG(LogWireInterface, Display, TEXT(" - Tessellation Library: %s"), WireSettings.bUseCADKernel ? TEXT("CADKernel") : TEXT("TechSoft"));
UE_LOG(LogWireInterface, Display, TEXT(" - Translation parameters:"));
UE_LOG(LogWireInterface, Display, TEXT(" - Merge By Group: %s"), WireSettings.bMergeGeometryByGroup ? TEXT("True") : TEXT("False"));
UE_LOG(LogWireInterface, Display, TEXT(" - Layer As actor: %s"), WireSettings.bUseLayerAsActor ? TEXT("True") : TEXT("False"));
UE_LOG(LogWireInterface, Display, TEXT(" - Tessellation parameters:"));
UE_LOG(LogWireInterface, Display, TEXT(" - ChordTolerance: %lf"), WireSettings.ChordTolerance);
UE_LOG(LogWireInterface, Display, TEXT(" - MaxEdgeLength: %lf"), WireSettings.MaxEdgeLength);
UE_LOG(LogWireInterface, Display, TEXT(" - MaxNormalAngle: %lf"), WireSettings.NormalTolerance);
FString StitchingTechnique;
switch (WireSettings.StitchingTechnique)
{
case EDatasmithCADStitchingTechnique::StitchingHeal:
StitchingTechnique = TEXT("Heal");
break;
case EDatasmithCADStitchingTechnique::StitchingSew:
StitchingTechnique = TEXT("Sew");
break;
default:
StitchingTechnique = TEXT("None");
break;
}
UE_LOG(LogWireInterface, Display, TEXT(" - StitchingTechnique: %s"), *StitchingTechnique);
UE_LOG(LogWireInterface, Display, TEXT(" - GeometricTolerance: %lf"), WireSettings.GetGeometricTolerance());
UE_LOG(LogWireInterface, Display, TEXT(" - Stitching Tolerance: %lf"), WireSettings.GetStitchingTolerance());
// #wire_import: TODO - Revisit stitching extension when using CADKernel
//if (WireSettings.bUseCADKernel)
//{
// UE_LOG(LogWireInterface, Display, TEXT(" - Stitching Options:"));
// UE_LOG(LogWireInterface, Display, TEXT(" - ForceSew: %s"), CADLibrary::FImportParameters::bGStitchingForceSew ? TEXT("True") : TEXT("False"));
// UE_LOG(LogWireInterface, Display, TEXT(" - RemoveThinFaces: %s"), CADLibrary::FImportParameters::bGStitchingRemoveThinFaces ? TEXT("True") : TEXT("False"));
// UE_LOG(LogWireInterface, Display, TEXT(" - RemoveDuplicatedFaces: %s"), CADLibrary::FImportParameters::bGStitchingRemoveDuplicatedFaces ? TEXT("True") : TEXT("False"));
// UE_LOG(LogWireInterface, Display, TEXT(" - ForceFactor: %f"), CADLibrary::FImportParameters::GStitchingForceFactor);
//}
DatasmithScene = InScene;
const FString AliasProductVersion = FString::Printf(TEXT("Alias %s"), *AliasSdkVersion);
DatasmithScene->SetHost(TEXT("Alias"));
DatasmithScene->SetVendor(TEXT("Autodesk"));
DatasmithScene->SetProductName(TEXT("Alias Tools"));
DatasmithScene->SetExporterSDKVersion(*AliasSdkVersion);
DatasmithScene->SetProductVersion(*AliasProductVersion);
WireSettings.bAliasUseNative = GetConsoleBoolValue(TEXT("ds.Wiretranslator.UseNative"), false);
if (!WireSettings.bAliasUseNative)
{
CADLibrary::FImportParameters ImportParameters;
if (CADLibrary::FImportParameters::bGDisableCADKernelTessellation)
{
CADModelConverter = MakeShared<FAliasModelToTechSoftConverter>(ImportParameters);
}
else
{
CADModelConverter = MakeShared<FAliasModelToCADKernelConverter>(WireSettings, ImportParameters);
}
}
else
{
// Merge by group when using Alias' tessellator
WireSettings.bMergeGeometryByGroup = false;
}
// Initialize Alias.
statusCode Status = AlUniverse::initialize();
if (Status != sSuccess && Status != sAlreadyCreated)
{
UE_LOG(LogWireInterface, Error, TEXT("Cannot initialize OpenModel SDK. Import is aborted."));
return false;
}
if (AlUniverse::retrieve(TCHAR_TO_UTF8(*SceneFullPath)) != sSuccess)
{
return false;
}
AlRetrieveOptions options;
AlUniverse::retrieveOptions(options);
bSceneLoaded = true;
return TraverseModel();
}
bool FWireTranslatorImpl::TraverseModel()
{
#if WIRE_MEMORY_CHECK
AllocatedObjects = 0;
MaxAllocatedObjects = 0;
ObjectSet.Reset();
DagNodeSet.Reset();
#endif
FAlDagNodePtr DagNode = FindOrAddDagNode(AlUniverse::firstDagNode());
while (DagNode)
{
TSharedPtr<IDatasmithActorElement> ActorElement = TraverseDag(DagNode);
if (ActorElement)
{
DatasmithScene->AddActor(ActorElement);
}
DagNode = FindOrAddDagNode(DagNode->nextNode());
}
TAlObjectPtr<AlSet> Set(AlUniverse::firstSet());
statusCode Status = Set ? sSuccess : sFailure;
while (Status == sSuccess)
{
// #wire_import: Add an actor to represent the set.
TAlObjectPtr<AlSetMember> SetMember(Set->firstMember());
statusCode MemberStatus = SetMember ? sSuccess : sFailure;
while (MemberStatus == sSuccess)
{
FAlDagNodePtr DagNodeInSet(SetMember->object() ? SetMember->object()->asDagNodePtr() : nullptr);
if (DagNodeInSet)
{
TSharedPtr<IDatasmithActorElement> ActorElement = TraverseDag(DagNodeInSet);
if (ActorElement)
{
DatasmithScene->AddActor(ActorElement);
}
}
MemberStatus = SetMember->nextSetMemberD();
}
Status = Set->nextSetD();
}
return true;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::TraverseDag(const FAlDagNodePtr& RootNode)
{
if (RootNode.IsAGroup())
{
return WireSettings.bMergeGeometryByGroup ? ProcessGroupNode(RootNode) : TraverseGroupNode(RootNode);
}
else if (RootNode.HasGeometry())
{
return ProcessGeometryNode(RootNode);
}
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::TraverseGroupNode(const FAlDagNodePtr& GroupNode, const TAlObjectPtr<AlLayer>& ParentLayer)
{
if (!GroupNode.IsAGroup())
{
return TSharedPtr<IDatasmithActorElement>();
}
TArray<FAlDagNodePtr> Children;
FAlDagNodePtr ChildNode = FindOrAddDagNode(GroupNode->asGroupNodePtr()->childNode());
while (ChildNode)
{
Children.Add(ChildNode);
ChildNode = FindOrAddDagNode(ChildNode->nextNode());
}
const int32 ChildrenCount = Children.Num();
if (ChildrenCount == 0)
{
return TSharedPtr<IDatasmithActorElement>();
}
TArray<TSharedPtr<IDatasmithActorElement>> ChildActors;
ChildActors.Reserve(ChildrenCount);
TAlObjectPtr<AlLayer> GroupLayer = FLayerContainer::FindOrAdd(GroupNode->layer());
for (FAlDagNodePtr& Child : Children)
{
if (TSharedPtr<IDatasmithActorElement> ActorElement = TraverseGroupNode(Child, GroupLayer))
{
ChildActors.Emplace(MoveTemp(ActorElement));
}
else if (Child.IsAMesh() || Child.IsASurface())
{
if (TSharedPtr<IDatasmithActorElement> ChildActorElement = ProcessGeometryNode(Child, ParentLayer))
{
ChildActors.Emplace(MoveTemp(ChildActorElement));
}
}
}
if (ChildActors.Num() == 0)
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithActorElement> ActorElement = FDatasmithSceneFactory::CreateActor(*GroupNode.GetUniqueID(GROUPNODE_TYPE));
if (!ActorElement.IsValid())
{
return ActorElement;
}
FString Label = GroupNode.GetName();
ActorElement->SetLabel(Label.Len() > 0 ? *Label : TEXT("UnnamedGroup"));
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(GroupLayer, CsvLayerString))
{
ActorElement->SetLayer(*CsvLayerString);
}
GroupNode.SetActorTransform(*ActorElement);
for (TSharedPtr<IDatasmithActorElement>& ChildActor : ChildActors)
{
if (OpenModelUtils::ActorHasContent(ChildActor))
{
ActorElement->AddChild(ChildActor);
}
}
if (WireSettings.bUseLayerAsActor && GroupLayer != ParentLayer)
{
if (OpenModelUtils::ActorHasContent(ActorElement))
{
if (TSharedPtr<IDatasmithActorElement> LayerActor = FindOrAddLayerActor(GroupLayer))
{
LayerActor->AddChild(ActorElement);
}
}
return TSharedPtr<IDatasmithActorElement>();
}
return ActorElement;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::ProcessGroupNode(const FAlDagNodePtr& GroupNode, const TAlObjectPtr<AlLayer>& ParentLayer)
{
if (!GroupNode.IsAGroup())
{
return TSharedPtr<IDatasmithActorElement>();
}
TArray<FAlDagNodePtr> Children;
FAlDagNodePtr ChildNode = FindOrAddDagNode(GroupNode->asGroupNodePtr()->childNode());
while (ChildNode)
{
Children.Add(ChildNode);
AlDagNode* NextNode = ChildNode->nextNode();
#if WIRE_MEMORY_CHECK
ensure(NextNode != ChildNode.Get());
#endif
ChildNode = FindOrAddDagNode(NextNode);
}
const int32 ChildrenCount = Children.Num();
if (ChildrenCount == 0)
{
return TSharedPtr<IDatasmithActorElement>();
}
TArray<TSharedPtr<IDatasmithActorElement>> ChildActors;
ChildActors.Reserve(ChildrenCount);
TAlObjectPtr<AlLayer> GroupLayer = FLayerContainer::FindOrAdd(GroupNode->layer());
TSharedPtr<FBodyNode> BodyNode = MakeShared<FBodyNode>(GroupNode.GetName() + TEXT("_surf"), GroupLayer, ChildrenCount);
TSharedPtr<FPatchMesh> PatchMesh = MakeShared<FPatchMesh>(GroupNode.GetName() + TEXT("_mesh"), GroupLayer, ChildrenCount);
for(FAlDagNodePtr& Child : Children)
{
if (TSharedPtr<IDatasmithActorElement> ActorElement = ProcessGroupNode(Child, GroupLayer))
{
ChildActors.Emplace(MoveTemp(ActorElement));
}
else if (Child.IsAMesh())
{
PatchMesh->AddMeshNode(Child);
}
else if (Child.IsASurface() || Child.IsAShell())
{
BodyNode->AddNode(Child);
}
}
if (ChildActors.IsEmpty() && !BodyNode->Initialize() && !PatchMesh->Initialize())
{
return TSharedPtr<IDatasmithActorElement>();
}
if (TSharedPtr<IDatasmithActorElement> ActorElement = ProcessBodyNode(BodyNode, GroupNode, GroupLayer))
{
if (OpenModelUtils::ActorHasContent(ActorElement))
{
ChildActors.Emplace(MoveTemp(ActorElement));
}
}
if (TSharedPtr<IDatasmithActorElement> ActorElement = ProcessPatchMesh(PatchMesh, GroupNode, GroupLayer))
{
if (OpenModelUtils::ActorHasContent(ActorElement))
{
ChildActors.Emplace(MoveTemp(ActorElement));
}
}
if (ChildActors.Num() == 0)
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithActorElement> ActorElement;
if (WireSettings.bMergeGeometryByGroup && ChildActors.Num() == 1)
{
ActorElement = ChildActors[0];
}
else
{
ActorElement = FDatasmithSceneFactory::CreateActor(*GroupNode.GetUniqueID(GROUPNODE_TYPE));
}
if (!ActorElement.IsValid())
{
return ActorElement;
}
FString Label = GroupNode.GetName();
ActorElement->SetLabel(Label.Len() > 0 ? *Label : TEXT("UnnamedGroup"));
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(GroupLayer, CsvLayerString))
{
ActorElement->SetLayer(*CsvLayerString);
}
if (WireSettings.bMergeGeometryByGroup && ChildActors.Num() > 1)
{
GroupNode.SetActorTransform(*ActorElement);
for (TSharedPtr<IDatasmithActorElement>& ChildActor : ChildActors)
{
if (OpenModelUtils::ActorHasContent(ChildActor))
{
ActorElement->AddChild(ChildActor);
}
}
}
if (WireSettings.bUseLayerAsActor && GroupLayer != ParentLayer)
{
if (OpenModelUtils::ActorHasContent(ActorElement))
{
if (TSharedPtr<IDatasmithActorElement> LayerActor = FindOrAddLayerActor(GroupLayer))
{
LayerActor->AddChild(ActorElement);
}
}
return TSharedPtr<IDatasmithActorElement>();
}
return ActorElement;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::ProcessGeometryNode(const FAlDagNodePtr& GeomNode, const TAlObjectPtr<AlLayer>& ParentLayer)
{
const TAlObjectPtr<AlLayer>& Layer = GeomNode.GetLayer();
if (Layer && Layer->invisible())
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FindOrAddMeshElement(GeomNode);
if (!MeshElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithMeshActorElement> ActorElement = FDatasmithSceneFactory::CreateMeshActor(*GeomNode.GetUniqueID(MESHNODE_TYPE));
if (!ActorElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
FString Label = GeomNode.GetName();
ActorElement->SetLabel(Label.Len() > 0 ? *Label : TEXT("NoName"));
ActorElement->SetStaticMeshPathName(MeshElement->GetName());
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(Layer, CsvLayerString))
{
ActorElement->SetLayer(*CsvLayerString);
}
GeomNode.SetActorTransform(*ActorElement);
if (WireSettings.bUseLayerAsActor && Layer != ParentLayer)
{
if (TSharedPtr<IDatasmithActorElement> LayerActor = FindOrAddLayerActor(Layer))
{
LayerActor->AddChild(ActorElement);
return TSharedPtr<IDatasmithActorElement>();
}
ensureWire(false);
}
return ActorElement;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::ProcessBodyNode(TSharedPtr<FBodyNode>& BodyNode, const FAlDagNodePtr& GroupNode, const TAlObjectPtr<AlLayer>& ParentLayer)
{
if (!BodyNode->HasContent())
{
return TSharedPtr<IDatasmithActorElement>();
}
FAlDagNodePtr Singleton;
if (BodyNode->GetSingleContent(Singleton))
{
return ProcessGeometryNode(Singleton, ParentLayer);
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FindOrAddMeshElement(BodyNode);
if (!MeshElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithMeshActorElement> ActorElement = FDatasmithSceneFactory::CreateMeshActor(*BodyNode->GetUniqueID());
if (!ActorElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
FString Label = BodyNode->GetName();
ActorElement->SetLabel(Label.Len() > 0 ? *Label : TEXT("NoName"));
ActorElement->SetStaticMeshPathName(MeshElement->GetName());
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(BodyNode->GetLayer(), CsvLayerString))
{
ActorElement->SetLayer(*CsvLayerString);
}
if (BodyNode->GetLayer() && !BodyNode->GetLayer()->isSymmetric())
{
GroupNode.SetActorTransform(*ActorElement);
}
if (WireSettings.bUseLayerAsActor && BodyNode->GetLayer() != ParentLayer)
{
if (TSharedPtr<IDatasmithActorElement> LayerActor = FindOrAddLayerActor(BodyNode->GetLayer()))
{
LayerActor->AddChild(ActorElement);
return TSharedPtr<IDatasmithActorElement>();
}
ensureWire(false);
}
return ActorElement;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::ProcessPatchMesh(TSharedPtr<FPatchMesh>& PatchMesh, const FAlDagNodePtr& GroupNode, const TAlObjectPtr<AlLayer>& ParentLayer)
{
if (!PatchMesh->HasContent())
{
return TSharedPtr<IDatasmithActorElement>();
}
if (!GroupNode.IsVisible())
{
return TSharedPtr<IDatasmithActorElement>();
}
FAlDagNodePtr Singleton;
if (PatchMesh->GetSingleContent(Singleton))
{
return ProcessGeometryNode(Singleton, ParentLayer);
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FindOrAddMeshElement(PatchMesh);
if (!MeshElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithMeshActorElement> ActorElement = FDatasmithSceneFactory::CreateMeshActor(*PatchMesh->GetUniqueID());
if (!ActorElement.IsValid())
{
return TSharedPtr<IDatasmithActorElement>();
}
FString Label = PatchMesh->GetName();
ActorElement->SetLabel(Label.Len() > 0 ? *Label : TEXT("NoName"));
ActorElement->SetStaticMeshPathName(MeshElement->GetName());
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(PatchMesh->GetLayer(), CsvLayerString))
{
ActorElement->SetLayer(*CsvLayerString);
}
GroupNode.SetActorTransform(*ActorElement);
if (WireSettings.bUseLayerAsActor && PatchMesh->GetLayer() != ParentLayer)
{
if (TSharedPtr<IDatasmithActorElement> LayerActor = FindOrAddLayerActor(PatchMesh->GetLayer()))
{
LayerActor->AddChild(ActorElement);
return TSharedPtr<IDatasmithActorElement>();
}
ensureWire(false);
}
return ActorElement;
}
TSharedPtr<IDatasmithMeshElement> FWireTranslatorImpl::FindOrAddMeshElement(const FAlDagNodePtr& GeomNode)
{
// Look if geometry has not been already processed, return it if found
if (TSharedPtr<IDatasmithMeshElement>* MeshElementPtr = GeomNodeToMeshElement.Find(GeomNode.GetHash()))
{
return *MeshElementPtr;
}
if (!GeomNode.HasGeometry())
{
// #wire_import: Log an error
return TSharedPtr<IDatasmithMeshElement>();
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FDatasmithSceneFactory::CreateMesh(*GeomNode.GetUniqueID(MESH_TYPE));
MeshElement->SetLabel(*GeomNode.GetName());
MeshElement->SetLightmapSourceUV(-1);
#if TRACK_MESHELEMENT
{
if (!ToTrack.Equals(MeshElement->GetLabel()))
{
return TSharedPtr<IDatasmithMeshElement>();
}
}
#endif
auto ApplyMaterial = [this, &MeshElement](const TAlObjectPtr<AlShader>& Shader, int32 SlotIndex)
{
if (TSharedPtr<IDatasmithBaseMaterialElement> MaterialElement = this->FindOrAddMaterial(Shader))
{
MeshElement->SetMaterial(MaterialElement->GetName(), SlotIndex);
}
};
TAlObjectPtr<AlShell> Shell;
if (GeomNode.GetShell(Shell))
{
TAlObjectPtr<AlShader> Shader(Shell->firstShader());
int32 SlotIndex = 0;
while (Shader)
{
ApplyMaterial(Shader, SlotIndex++);
Shader = Shell->nextShader(Shader.Get());
}
// #wire_import: Check There are as many shaders as trim regions
MeshElementToParametricNode.Add(MeshElement, GeomNode);
}
else
{
TAlObjectPtr<AlSurface> Surface;
if (GeomNode.GetSurface(Surface))
{
// #wire_import: Check for trim regions
ApplyMaterial(Surface->firstShader(), 0);
MeshElementToParametricNode.Add(MeshElement, GeomNode);
}
else
{
TAlObjectPtr<AlMesh> Mesh;
if (GeomNode.GetMesh(Mesh))
{
ApplyMaterial(Mesh->firstShader(), 0);
MeshElementToMeshNode.Add(MeshElement, GeomNode);
}
else
{
// #wire_import: Log an error
return TSharedPtr<IDatasmithMeshElement>();
}
}
}
DatasmithScene->AddMesh(MeshElement);
GeomNodeToMeshElement.Add(GeomNode.GetHash(), MeshElement);
return MeshElement;
}
TSharedPtr<IDatasmithMeshElement> FWireTranslatorImpl::FindOrAddMeshElement(TSharedPtr<FBodyNode>& BodyNode)
{
// Look if geometry has not been already processed, return it if found
if (TSharedPtr<IDatasmithMeshElement>* MeshElementPtr = BodyNodeToMeshElement.Find(BodyNode->GetHash()))
{
return *MeshElementPtr;
}
if (!BodyNode->HasContent())
{
// #wire_import: Log an error
return TSharedPtr<IDatasmithMeshElement>();
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FDatasmithSceneFactory::CreateMesh(*BodyNode->GetUniqueID());
MeshElement->SetLabel(*BodyNode->GetName());
MeshElement->SetLightmapSourceUV(-1);
#if TRACK_MESHELEMENT
{
if (!ToTrack.Equals(MeshElement->GetLabel()))
{
return TSharedPtr<IDatasmithMeshElement>();
}
}
#endif
auto ApplyMaterial = [this, &MeshElement](int32 SlotIndex, const TAlObjectPtr<AlShader>& Shader)
{
if (TSharedPtr<IDatasmithBaseMaterialElement> MaterialElement = this->FindOrAddMaterial(Shader))
{
MeshElement->SetMaterial(MaterialElement->GetName(), SlotIndex);
}
};
BodyNode->IterateOnSlotIndices(ApplyMaterial);
DatasmithScene->AddMesh(MeshElement);
BodyNodeToMeshElement.Add(BodyNode->GetHash(), MeshElement);
MeshElementToBodyNode.Add(MeshElement, BodyNode);
return MeshElement;
}
TSharedPtr<IDatasmithMeshElement> FWireTranslatorImpl::FindOrAddMeshElement(TSharedPtr<FPatchMesh>& PatchMesh)
{
// Look if geometry has not been already processed, return it if found
if (TSharedPtr<IDatasmithMeshElement>* MeshElementPtr = PatchMeshToMeshElement.Find(PatchMesh->GetHash()))
{
return *MeshElementPtr;
}
if (!PatchMesh->HasContent())
{
// #wire_import: Log an error
return TSharedPtr<IDatasmithMeshElement>();
}
TSharedPtr<IDatasmithMeshElement> MeshElement = FDatasmithSceneFactory::CreateMesh(*PatchMesh->GetUniqueID());
MeshElement->SetLabel(*PatchMesh->GetName());
MeshElement->SetLightmapSourceUV(-1);
#if TRACK_MESHELEMENT
{
if (!ToTrack.Equals(MeshElement->GetLabel()))
{
return TSharedPtr<IDatasmithMeshElement>();
}
}
#endif
auto ApplyMaterial = [this, &MeshElement](const TAlObjectPtr<AlShader>& Shader, int32 SlotIndex)
{
if (TSharedPtr<IDatasmithBaseMaterialElement> MaterialElement = this->FindOrAddMaterial(Shader))
{
MeshElement->SetMaterial(MaterialElement->GetName(), SlotIndex);
}
};
int32 SlotIndex = 0;
PatchMesh->IterateOnMeshNodes([&ApplyMaterial, &SlotIndex](const FAlDagNodePtr& MeshNode)
{
TAlObjectPtr<AlMesh> Mesh;
if (MeshNode.GetMesh(Mesh))
{
ApplyMaterial(Mesh->firstShader(), SlotIndex++);
}
});
DatasmithScene->AddMesh(MeshElement);
BodyNodeToMeshElement.Add(PatchMesh->GetHash(), MeshElement);
MeshElementToPatchMesh.Add(MeshElement, PatchMesh);
return MeshElement;
}
TSharedPtr<IDatasmithActorElement> FWireTranslatorImpl::FindOrAddLayerActor(const TAlObjectPtr<AlLayer>& Layer)
{
if (!WireSettings.bUseLayerAsActor || !Layer || Layer.GetName().IsEmpty())
{
return TSharedPtr<IDatasmithActorElement>();
}
TSharedPtr<IDatasmithActorElement>* LayerActorPtr = LayerToActor.Find(Layer.GetHash());
if (LayerActorPtr)
{
return *LayerActorPtr;
}
TSharedPtr<IDatasmithActorElement> ParentLayerActor;
TAlObjectPtr<AlLayer> ParentLayer = FLayerContainer::FindOrAdd(Layer->parentLayer());
if (ParentLayer)
{
ParentLayerActor = FindOrAddLayerActor(ParentLayer);
}
TSharedPtr<IDatasmithActorElement> LayerActor = FDatasmithSceneFactory::CreateActor(*Layer.GetUniqueID(LAYER_TYPE));
FString LayerName = Layer.GetName();
LayerActor->SetLabel(*LayerName);
FString CsvLayerString;
if (OpenModelUtils::GetCsvLayerString(Layer, CsvLayerString))
{
LayerActor->SetLayer(*CsvLayerString);
}
if (ParentLayerActor)
{
ParentLayerActor->AddChild(LayerActor);
}
else
{
DatasmithScene->AddActor(LayerActor);
}
LayerToActor.Add(Layer.GetHash(), LayerActor);
return LayerActor;
}
// Geometry retrieval
bool FWireTranslatorImpl::LoadStaticMesh(const TSharedPtr<IDatasmithMeshElement> MeshElement, FDatasmithMeshElementPayload& OutMeshPayload, const FDatasmithTessellationOptions& InTessellationOptions)
{
CADLibrary::FMeshParameters MeshParameters;
#if WIRE_MEMORY_CHECK
int32 PrevAllocatedObjects = AllocatedObjects;
#endif
if (TOptional<FMeshDescription> Mesh = GetMeshDescription(MeshElement, MeshParameters))
{
#if TRACK_MESHELEMENT
FMeshDescription& MeshDescription = OutMeshPayload.LodMeshes.Add_GetRef(MoveTemp(Mesh.GetValue()));
MakeMeshVisible(MeshDescription);
#else
OutMeshPayload.LodMeshes.Add(MoveTemp(Mesh.GetValue()));
#endif
const TCHAR* MeshFilename = MeshElement->GetFile();
if (!WireSettings.bAliasUseNative && FPaths::FileExists(MeshFilename))
{
CADModelConverter->AddSurfaceDataForMesh(MeshFilename, MeshParameters, InTessellationOptions, OutMeshPayload);
// Remove the file because it is temporary since caching is disabled.
if (!CADLibrary::FImportParameters::bGEnableCADCache)
{
IFileManager::Get().Delete(MeshFilename);
}
}
#if WIRE_MEMORY_CHECK
ensure(PrevAllocatedObjects == AllocatedObjects);
#endif
return true;
}
return false;
}
TOptional<FMeshDescription> FWireTranslatorImpl::GetMeshDescription(TSharedPtr<IDatasmithMeshElement> MeshElement, CADLibrary::FMeshParameters& OutMeshParameters)
{
if (WireSettings.bAliasUseNative)
{
if (FAlDagNodePtr* GeomNodePtr = MeshElementToParametricNode.Find(MeshElement))
{
FAlDagNodePtr& GeomNode = *GeomNodePtr;
// #wire_import: Check whether parametric geometry with symmetry keeps the symmetry
// #wire_import: the best way, should be to don't have to apply inverse global transform to the generated mesh
FAlDagNodePtr MeshNode = OpenModelUtils::TesselateDagLeaf(*GeomNode, ETesselatorType::Fast, WireSettings.ChordTolerance);
TAlObjectPtr<AlMesh> Mesh;
if (MeshNode.GetMesh(Mesh))
{
AlMatrix4x4 AlMatrix;
GeomNode->inverseGlobalTransformationMatrix(AlMatrix);
Mesh->transform(AlMatrix);
// Get the meshes from the dag nodes. Note that removing the mesh's DAG.
// will also removes the meshes, so we have to do it later.
return GetMeshDescriptionFromMeshNode(MeshNode, MeshElement, OutMeshParameters);
}
}
if (FAlDagNodePtr* MeshNodePtr = MeshElementToMeshNode.Find(MeshElement))
{
FAlDagNodePtr MeshNode = *MeshNodePtr;
if (MeshNode)
{
return GetMeshDescriptionFromMeshNode(MeshNode, MeshElement, OutMeshParameters);
}
}
return TOptional<FMeshDescription>();
}
if (TSharedPtr<FBodyNode>* BodyNodePtr = MeshElementToBodyNode.Find(MeshElement))
{
return GetMeshDescriptionFromBodyNode(*BodyNodePtr, MeshElement, OutMeshParameters);
}
if (FAlDagNodePtr* GeomNodePtr = MeshElementToParametricNode.Find(MeshElement))
{
return GetMeshDescriptionFromParametricNode(*GeomNodePtr, MeshElement, OutMeshParameters);
}
if (TSharedPtr<FPatchMesh>* PatchMeshPtr = MeshElementToPatchMesh.Find(MeshElement))
{
return GetMeshDescriptionFromPatchMesh(*PatchMeshPtr, MeshElement, OutMeshParameters);
}
if (FAlDagNodePtr* MeshNodePtr = MeshElementToMeshNode.Find(MeshElement))
{
return GetMeshDescriptionFromMeshNode(*MeshNodePtr, MeshElement, OutMeshParameters);
}
return TOptional<FMeshDescription>();
}
TOptional<FMeshDescription> FWireTranslatorImpl::GetMeshDescriptionFromBodyNode(TSharedPtr<FBodyNode>& BodyNode, TSharedPtr<IDatasmithMeshElement> MeshElement, CADLibrary::FMeshParameters& OutMeshParameters)
{
OutMeshParameters = OpenModelUtils::GetMeshParameters(BodyNode->GetLayer());
TSharedPtr<CADLibrary::ICADModelConverter> ModelConverter = GetModelConverter();
ModelConverter->InitializeProcess();
EAliasObjectReference ObjectReference = EAliasObjectReference::LocalReference;
if (OutMeshParameters.bIsSymmetric)
{
// All actors of a Alias symmetric layer are defined in the world Reference i.e. they have identity transform. So Mesh actor has to be defined in the world reference.
ObjectReference = EAliasObjectReference::WorldReference;
}
else if (WireSettings.bMergeGeometryByGroup)
{
// In the case of StitchingSew, AlDagNode children of a GroupNode are merged together. To be merged, they have to be defined in the reference of parent GroupNode.
ObjectReference = EAliasObjectReference::ParentReference;
}
const FBodyNodeGeometry BodyNodeGeometry( (int32)ECADModelGeometryType::BodyNode, ObjectReference, BodyNode);
ModelConverter->AddGeometry(BodyNodeGeometry);
ModelConverter->RepairTopology();
ModelConverter->SaveModel(*OutputPath, MeshElement);
FMeshDescription MeshDescription;
DatasmithMeshHelper::PrepareAttributeForStaticMesh(MeshDescription);
if (ModelConverter->Tessellate(OutMeshParameters, MeshDescription))
{
return TOptional<FMeshDescription>(MoveTemp(MeshDescription));
}
const TCHAR* StaticMeshLabel = MeshElement->GetLabel();
const TCHAR* StaticMeshName = MeshElement->GetName();
UE_LOG(LogWireInterface, Warning, TEXT("Failed to generate the mesh of \"%s\" (%s) StaticMesh."), StaticMeshLabel, StaticMeshName);
return TOptional<FMeshDescription>();
}
TOptional<FMeshDescription> FWireTranslatorImpl::GetMeshDescriptionFromPatchMesh(TSharedPtr<FPatchMesh>& PatchMesh, TSharedPtr<IDatasmithMeshElement> MeshElement, CADLibrary::FMeshParameters& OutMeshParameters)
{
OutMeshParameters = OpenModelUtils::GetMeshParameters(PatchMesh->GetLayer());
FMeshDescription MeshDescription;
DatasmithMeshHelper::PrepareAttributeForStaticMesh(MeshDescription);
MeshDescription.Empty();
constexpr bool bMerge = true;
int32 SlotIndex = 0;
PatchMesh->IterateOnMeshNodes([&](const FAlDagNodePtr& MeshNode)
{
TAlObjectPtr<AlMesh> Mesh;
if (MeshNode.GetMesh(Mesh))
{
AlMatrix4x4 AlMatrix;
if (OutMeshParameters.bIsSymmetric)
{
MeshNode->globalTransformationMatrix(AlMatrix);
}
else
{
MeshNode->localTransformationMatrix(AlMatrix);
}
Mesh->transform(AlMatrix);
const FString SlotMaterialName = DatasmithMeshHelper::DefaultSlotName(SlotIndex++).ToString();
OpenModelUtils::TransferAlMeshToMeshDescription(*Mesh, *SlotMaterialName, MeshDescription, OutMeshParameters, bMerge);
}
});
// Build edge meta data
FStaticMeshOperations::DetermineEdgeHardnessesFromVertexInstanceNormals(MeshDescription);
return MoveTemp(MeshDescription);
}
// #wire_import: AlSurfaceNode can have trim regions. This should be handle at this stage
TOptional<FMeshDescription> FWireTranslatorImpl::GetMeshDescriptionFromParametricNode(const FAlDagNodePtr& DagNode, TSharedPtr<IDatasmithMeshElement> MeshElement, CADLibrary::FMeshParameters& OutMeshParameters)
{
OutMeshParameters = OpenModelUtils::GetMeshParameters(DagNode.GetLayer());
TSharedPtr<CADLibrary::ICADModelConverter> ModelConverter = GetModelConverter();
ModelConverter->InitializeProcess();
EAliasObjectReference ObjectReference = EAliasObjectReference::LocalReference;
// All geometry are processed in world space if layers are converted to actors
// All actors of a Alias symmetric layer are defined in the world Reference
// i.e. they have identity transform. So Mesh actor has to be defined in the world reference.
if (OutMeshParameters.bIsSymmetric)
{
ObjectReference = EAliasObjectReference::WorldReference;
}
ensureWire(MeshElement->GetMaterialSlotCount() == 1);
const FDagNodeGeometry DagNodeGeometry( (int32)ECADModelGeometryType::DagNode, ObjectReference, DagNode );
if (!ModelConverter->AddGeometry(DagNodeGeometry))
{
return TOptional<FMeshDescription>();
}
ModelConverter->RepairTopology();
ModelConverter->SaveModel(*OutputPath, MeshElement);
FMeshDescription MeshDescription;
DatasmithMeshHelper::PrepareAttributeForStaticMesh(MeshDescription);
OutMeshParameters = DagNode.GetMeshParameters();
if (ModelConverter->Tessellate(OutMeshParameters, MeshDescription))
{
return TOptional<FMeshDescription>(MoveTemp(MeshDescription));
}
const TCHAR* StaticMeshLabel = MeshElement->GetLabel();
const TCHAR* StaticMeshName = MeshElement->GetName();
UE_LOG(LogWireInterface, Warning, TEXT("Failed to generate the mesh of \"%s\" (%s) StaticMesh."), StaticMeshLabel, StaticMeshName);
return TOptional<FMeshDescription>();
}
TOptional<FMeshDescription> FWireTranslatorImpl::GetMeshDescriptionFromMeshNode(const FAlDagNodePtr& MeshNode, TSharedPtr<IDatasmithMeshElement> MeshElement, CADLibrary::FMeshParameters& OutMeshParameters)
{
if (!MeshNode)
{
return TOptional<FMeshDescription>();
}
TAlObjectPtr<AlMesh> Mesh;
if (!MeshNode.GetMesh(Mesh))
{
return TOptional<FMeshDescription>();
}
OutMeshParameters = MeshNode.GetMeshParameters();
if (OutMeshParameters.bIsSymmetric)
{
AlMatrix4x4 AlGlobalMatrix;
MeshNode->globalTransformationMatrix(AlGlobalMatrix);
Mesh->transform(AlGlobalMatrix);
}
FMeshDescription MeshDescription;
DatasmithMeshHelper::PrepareAttributeForStaticMesh(MeshDescription);
const bool bMerge = false;
OpenModelUtils::TransferAlMeshToMeshDescription(*Mesh, TEXT("0"), MeshDescription, OutMeshParameters, bMerge);
// Build edge meta data
FStaticMeshOperations::DetermineEdgeHardnessesFromVertexInstanceNormals(MeshDescription);
return MoveTemp(MeshDescription);
}
TSharedPtr<CADLibrary::ICADModelConverter> FWireTranslatorImpl::GetModelConverter() const
{
TSharedPtr<CADLibrary::ICADModelConverter> ModelConverter;
CADLibrary::FImportParameters ImportParameters;
if (CADLibrary::FImportParameters::bGDisableCADKernelTessellation)
{
ModelConverter = MakeShared<FAliasModelToTechSoftConverter>(ImportParameters);
}
else
{
ModelConverter = MakeShared<FAliasModelToCADKernelConverter>(WireSettings, ImportParameters);
}
if (ModelConverter)
{
ModelConverter->SetImportParameters(WireSettings.ChordTolerance, WireSettings.MaxEdgeLength, WireSettings.NormalTolerance, (CADLibrary::EStitchingTechnique)WireSettings.StitchingTechnique);
}
return ModelConverter;
}
// Material creation
TSharedPtr<IDatasmithBaseMaterialElement> FWireTranslatorImpl::FindOrAddMaterial(const TAlObjectPtr<AlShader>& Shader)
{
const FString ShaderName = Shader.GetName();
if (TSharedPtr<IDatasmithBaseMaterialElement>* MaterialElementPtr = ShaderNameToMaterial.Find(ShaderName))
{
return *MaterialElementPtr;
}
const FString ShaderModelName = Shader->shadingModel();
TSharedPtr<IDatasmithUEPbrMaterialElement> MaterialElement = FDatasmithSceneFactory::CreateUEPbrMaterial(*Shader.GetUniqueID(SHADER_TYPE));
MaterialElement->SetLabel(*ShaderName);
if (ShaderModelName.Equals(TEXT("BLINN")))
{
AddAlBlinnParameters(Shader, MaterialElement);
}
else if (ShaderModelName.Equals(TEXT("LAMBERT")))
{
AddAlLambertParameters(Shader, MaterialElement);
}
else if (ShaderModelName.Equals(TEXT("LIGHTSOURCE")))
{
AddAlLightSourceParameters(Shader, MaterialElement);
}
else if (ShaderModelName.Equals(TEXT("PHONG")))
{
AddAlPhongParameters(Shader, MaterialElement);
}
DatasmithScene->AddMaterial(MaterialElement);
ShaderNameToMaterial.Add(*ShaderName, MaterialElement);
return MaterialElement;
}
bool FWireTranslatorImpl::GetCommonParameters(int32 Field, double Value, FColor& Color, FColor& TransparencyColor, FColor& IncandescenceColor, double GlowIntensity)
{
switch (AlShadingFields(Field))
{
case AlShadingFields::kFLD_SHADING_COMMON_COLOR_R:
Color.R = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_COLOR_G:
Color.G = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_COLOR_B:
Color.B = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_INCANDESCENCE_R:
IncandescenceColor.R = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_INCANDESCENCE_G:
IncandescenceColor.G = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_INCANDESCENCE_B:
IncandescenceColor.B = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_TRANSPARENCY_R:
TransparencyColor.R = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_TRANSPARENCY_G:
TransparencyColor.G = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_TRANSPARENCY_B:
TransparencyColor.B = (uint8)Value;
return true;
case AlShadingFields::kFLD_SHADING_COMMON_GLOW_INTENSITY:
GlowIntensity = Value;
return true;
default:
return false;
}
}
void FWireTranslatorImpl::AddAlBlinnParameters(const TAlObjectPtr<AlShader>& Shader, TSharedPtr<IDatasmithUEPbrMaterialElement> MaterialElement)
{
// Default values for a Blinn material
FColor Color(145, 148, 153);
FColor TransparencyColor(0, 0, 0);
FColor IncandescenceColor(0, 0, 0);
FColor SpecularColor(38, 38, 38);
double Diffuse = 1.0;
double GlowIntensity = 0.0;
double Gloss = 0.8;
double Eccentricity = 0.35;
double Specularity = 1.0;
double Reflectivity = 0.5;
double SpecularRolloff = 0.5;
AlList* List = Shader->fields();
for (AlShadingFieldItem* Item = static_cast<AlShadingFieldItem*>(List->first()); Item; Item = Item->nextField())
{
double Value = 0.0f;
statusCode ErrorCode = Shader->parameter(Item->field(), Value);
if (ErrorCode != 0)
{
continue;
}
if (GetCommonParameters(Item->field(), Value, Color, TransparencyColor, IncandescenceColor, GlowIntensity))
{
continue;
}
switch (Item->field())
{
case AlShadingFields::kFLD_SHADING_BLINN_DIFFUSE:
Diffuse = Value;
break;
case AlShadingFields::kFLD_SHADING_BLINN_GLOSS_:
Gloss = Value;
break;
case AlShadingFields::kFLD_SHADING_BLINN_SPECULAR_R:
SpecularColor.R = (uint8)(255.f * Value);
break;
case AlShadingFields::kFLD_SHADING_BLINN_SPECULAR_G:
SpecularColor.G = (uint8)(255.f * Value);;
break;
case AlShadingFields::kFLD_SHADING_BLINN_SPECULAR_B:
SpecularColor.B = (uint8)(255.f * Value);;
break;
case AlShadingFields::kFLD_SHADING_BLINN_SPECULARITY_:
Specularity = Value;
break;
case AlShadingFields::kFLD_SHADING_BLINN_SPECULAR_ROLLOFF:
SpecularRolloff = Value;
break;
case AlShadingFields::kFLD_SHADING_BLINN_ECCENTRICITY:
Eccentricity = Value;
break;
case AlShadingFields::kFLD_SHADING_BLINN_REFLECTIVITY:
Reflectivity = Value;
break;
}
}
bool bIsTransparent = IsTransparent(TransparencyColor);
// Construct parameter expressions
IDatasmithMaterialExpressionScalar* DiffuseExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseExpression->GetScalar() = Diffuse;
DiffuseExpression->SetName(TEXT("Diffuse"));
IDatasmithMaterialExpressionScalar* GlossExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlossExpression->GetScalar() = Gloss;
GlossExpression->SetName(TEXT("Gloss"));
IDatasmithMaterialExpressionColor* SpecularColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
SpecularColorExpression->SetName(TEXT("SpecularColor"));
SpecularColorExpression->GetColor() = FLinearColor::FromSRGBColor(SpecularColor);
IDatasmithMaterialExpressionScalar* SpecularityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
SpecularityExpression->GetScalar() = Specularity * 0.3;
SpecularityExpression->SetName(TEXT("Specularity"));
IDatasmithMaterialExpressionScalar* SpecularRolloffExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
SpecularRolloffExpression->GetScalar() = SpecularRolloff;
SpecularRolloffExpression->SetName(TEXT("SpecularRolloff"));
IDatasmithMaterialExpressionScalar* EccentricityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
EccentricityExpression->GetScalar() = Eccentricity;
EccentricityExpression->SetName(TEXT("Eccentricity"));
IDatasmithMaterialExpressionScalar* ReflectivityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ReflectivityExpression->GetScalar() = Reflectivity;
ReflectivityExpression->SetName(TEXT("Reflectivity"));
IDatasmithMaterialExpressionColor* ColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
ColorExpression->SetName(TEXT("Color"));
ColorExpression->GetColor() = FLinearColor::FromSRGBColor(Color);
IDatasmithMaterialExpressionColor* IncandescenceColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
IncandescenceColorExpression->SetName(TEXT("IncandescenceColor"));
IncandescenceColorExpression->GetColor() = FLinearColor::FromSRGBColor(IncandescenceColor);
IDatasmithMaterialExpressionColor* TransparencyColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
TransparencyColorExpression->SetName(TEXT("TransparencyColor"));
TransparencyColorExpression->GetColor() = FLinearColor::FromSRGBColor(TransparencyColor);
IDatasmithMaterialExpressionScalar* GlowIntensityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlowIntensityExpression->GetScalar() = GlowIntensity;
GlowIntensityExpression->SetName(TEXT("GlowIntensity"));
// Create aux expressions
IDatasmithMaterialExpressionGeneric* ColorSpecLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ColorSpecLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* ColorSpecLerpValue = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ColorSpecLerpValue->GetScalar() = 0.96f;
IDatasmithMaterialExpressionGeneric* ColorMetallicLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ColorMetallicLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionGeneric* DiffuseLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
DiffuseLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* DiffuseLerpA = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpA->GetScalar() = 0.04f;
IDatasmithMaterialExpressionScalar* DiffuseLerpB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpB->GetScalar() = 1.0f;
IDatasmithMaterialExpressionGeneric* BaseColorMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* BaseColorAdd = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorAdd->SetExpressionName(TEXT("Add"));
IDatasmithMaterialExpressionGeneric* BaseColorTransparencyMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorTransparencyMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceScaleMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceScaleMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionScalar* IncandescenceScale = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
IncandescenceScale->GetScalar() = 100.0f;
IDatasmithMaterialExpressionGeneric* EccentricityMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
EccentricityMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* EccentricityOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
EccentricityOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionGeneric* RoughnessOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
RoughnessOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionScalar* FresnelExponent = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
FresnelExponent->GetScalar() = 4.0f;
IDatasmithMaterialExpressionFunctionCall* FresnelFunc = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionFunctionCall>();
FresnelFunc->SetFunctionPathName(TEXT("/Engine/Functions/Engine_MaterialFunctions02/Fresnel_Function.Fresnel_Function"));
IDatasmithMaterialExpressionGeneric* FresnelLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
FresnelLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* FresnelLerpA = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
FresnelLerpA->GetScalar() = 1.0f;
IDatasmithMaterialExpressionScalar* SpecularPowerExp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
SpecularPowerExp->GetScalar() = 0.5f;
IDatasmithMaterialExpressionGeneric* Power = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
Power->SetExpressionName(TEXT("Power"));
IDatasmithMaterialExpressionGeneric* FresnelMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
FresnelMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* TransparencyOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
TransparencyOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionFunctionCall* BreakFloat3 = nullptr;
IDatasmithMaterialExpressionGeneric* AddRG = nullptr;
IDatasmithMaterialExpressionGeneric* AddRGB = nullptr;
IDatasmithMaterialExpressionGeneric* Divide = nullptr;
IDatasmithMaterialExpressionScalar* DivideConstant = nullptr;
if (bIsTransparent)
{
BreakFloat3 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionFunctionCall>();
BreakFloat3->SetFunctionPathName(TEXT("/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakFloat3Components.BreakFloat3Components"));
AddRG = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRG->SetExpressionName(TEXT("Add"));
AddRGB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRGB->SetExpressionName(TEXT("Add"));
Divide = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
Divide->SetExpressionName(TEXT("Divide"));
DivideConstant = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DivideConstant->GetScalar() = 3.0f;
}
// Connect expressions
SpecularColorExpression->ConnectExpression(*ColorSpecLerp->GetInput(0));
ColorExpression->ConnectExpression(*ColorSpecLerp->GetInput(1));
ColorSpecLerpValue->ConnectExpression(*ColorSpecLerp->GetInput(2));
ColorExpression->ConnectExpression(*ColorMetallicLerp->GetInput(0));
ColorSpecLerp->ConnectExpression(*ColorMetallicLerp->GetInput(1));
GlossExpression->ConnectExpression(*ColorMetallicLerp->GetInput(2));
DiffuseLerpA->ConnectExpression(*DiffuseLerp->GetInput(0));
DiffuseLerpB->ConnectExpression(*DiffuseLerp->GetInput(1));
DiffuseExpression->ConnectExpression(*DiffuseLerp->GetInput(2));
ColorMetallicLerp->ConnectExpression(*BaseColorMultiply->GetInput(0));
DiffuseLerp->ConnectExpression(*BaseColorMultiply->GetInput(1));
BaseColorMultiply->ConnectExpression(*BaseColorAdd->GetInput(0));
IncandescenceColorExpression->ConnectExpression(*BaseColorAdd->GetInput(1));
BaseColorAdd->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(0));
TransparencyOneMinus->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(1));
GlowIntensityExpression->ConnectExpression(*IncandescenceScaleMultiply->GetInput(0));
IncandescenceScale->ConnectExpression(*IncandescenceScaleMultiply->GetInput(1));
BaseColorTransparencyMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(0));
IncandescenceScaleMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(1));
EccentricityExpression->ConnectExpression(*EccentricityOneMinus->GetInput(0));
EccentricityOneMinus->ConnectExpression(*EccentricityMultiply->GetInput(0));
SpecularityExpression->ConnectExpression(*EccentricityMultiply->GetInput(1));
EccentricityMultiply->ConnectExpression(*RoughnessOneMinus->GetInput(0));
FresnelExponent->ConnectExpression(*FresnelFunc->GetInput(3));
SpecularRolloffExpression->ConnectExpression(*Power->GetInput(0));
SpecularPowerExp->ConnectExpression(*Power->GetInput(1));
FresnelLerpA->ConnectExpression(*FresnelLerp->GetInput(0));
FresnelFunc->ConnectExpression(*FresnelLerp->GetInput(1));
Power->ConnectExpression(*FresnelLerp->GetInput(2));
FresnelLerp->ConnectExpression(*FresnelMultiply->GetInput(0));
ReflectivityExpression->ConnectExpression(*FresnelMultiply->GetInput(1));
TransparencyColorExpression->ConnectExpression(*TransparencyOneMinus->GetInput(0));
if (bIsTransparent)
{
TransparencyOneMinus->ConnectExpression(*BreakFloat3->GetInput(0));
BreakFloat3->ConnectExpression(*AddRG->GetInput(0), 0);
BreakFloat3->ConnectExpression(*AddRG->GetInput(1), 1);
AddRG->ConnectExpression(*AddRGB->GetInput(0));
BreakFloat3->ConnectExpression(*AddRGB->GetInput(1), 2);
AddRGB->ConnectExpression(*Divide->GetInput(0));
DivideConstant->ConnectExpression(*Divide->GetInput(1));
}
// Connect material outputs
MaterialElement->GetBaseColor().SetExpression(BaseColorTransparencyMultiply);
MaterialElement->GetMetallic().SetExpression(GlossExpression);
MaterialElement->GetSpecular().SetExpression(FresnelMultiply);
MaterialElement->GetRoughness().SetExpression(RoughnessOneMinus);
MaterialElement->GetEmissiveColor().SetExpression(IncandescenceMultiply);
if (bIsTransparent)
{
MaterialElement->GetOpacity().SetExpression(Divide);
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasBlinnTransparent"));
}
else
{
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasBlinn"));
}
}
void FWireTranslatorImpl::AddAlLambertParameters(const TAlObjectPtr<AlShader>& Shader, TSharedPtr<IDatasmithUEPbrMaterialElement> MaterialElement)
{
// Default values for a Lambert material
FColor Color(145, 148, 153);
FColor TransparencyColor(0, 0, 0);
FColor IncandescenceColor(0, 0, 0);
double Diffuse = 1.0;
double GlowIntensity = 0.0;
AlList* List = Shader->fields();
for (AlShadingFieldItem* Item = static_cast<AlShadingFieldItem*>(List->first()); Item; Item = Item->nextField())
{
double Value = 0.0f;
statusCode ErrorCode = Shader->parameter(Item->field(), Value);
if (ErrorCode != 0)
{
continue;
}
if (GetCommonParameters(Item->field(), Value, Color, TransparencyColor, IncandescenceColor, GlowIntensity))
{
continue;
}
switch (Item->field())
{
case AlShadingFields::kFLD_SHADING_LAMBERT_DIFFUSE:
Diffuse = Value;
break;
}
}
bool bIsTransparent = IsTransparent(TransparencyColor);
// Construct parameter expressions
IDatasmithMaterialExpressionScalar* DiffuseExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseExpression->GetScalar() = Diffuse;
DiffuseExpression->SetName(TEXT("Diffuse"));
IDatasmithMaterialExpressionColor* ColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
ColorExpression->SetName(TEXT("Color"));
ColorExpression->GetColor() = FLinearColor::FromSRGBColor(Color);
IDatasmithMaterialExpressionColor* IncandescenceColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
IncandescenceColorExpression->SetName(TEXT("IncandescenceColor"));
IncandescenceColorExpression->GetColor() = FLinearColor::FromSRGBColor(IncandescenceColor);
IDatasmithMaterialExpressionColor* TransparencyColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
TransparencyColorExpression->SetName(TEXT("TransparencyColor"));
TransparencyColorExpression->GetColor() = FLinearColor::FromSRGBColor(TransparencyColor);
IDatasmithMaterialExpressionScalar* GlowIntensityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlowIntensityExpression->GetScalar() = GlowIntensity;
GlowIntensityExpression->SetName(TEXT("GlowIntensity"));
// Create aux expressions
IDatasmithMaterialExpressionGeneric* DiffuseLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
DiffuseLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* DiffuseLerpA = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpA->GetScalar() = 0.04f;
IDatasmithMaterialExpressionScalar* DiffuseLerpB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpB->GetScalar() = 1.0f;
IDatasmithMaterialExpressionGeneric* BaseColorMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* BaseColorAdd = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorAdd->SetExpressionName(TEXT("Add"));
IDatasmithMaterialExpressionGeneric* BaseColorTransparencyMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorTransparencyMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceScaleMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceScaleMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionScalar* IncandescenceScale = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
IncandescenceScale->GetScalar() = 100.0f;
IDatasmithMaterialExpressionGeneric* TransparencyOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
TransparencyOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionFunctionCall* BreakFloat3 = nullptr;
IDatasmithMaterialExpressionGeneric* AddRG = nullptr;
IDatasmithMaterialExpressionGeneric* AddRGB = nullptr;
IDatasmithMaterialExpressionGeneric* Divide = nullptr;
IDatasmithMaterialExpressionScalar* DivideConstant = nullptr;
if (bIsTransparent)
{
BreakFloat3 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionFunctionCall>();
BreakFloat3->SetFunctionPathName(TEXT("/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakFloat3Components.BreakFloat3Components"));
AddRG = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRG->SetExpressionName(TEXT("Add"));
AddRGB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRGB->SetExpressionName(TEXT("Add"));
Divide = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
Divide->SetExpressionName(TEXT("Divide"));
DivideConstant = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DivideConstant->GetScalar() = 3.0f;
}
// Connect expressions
DiffuseLerpA->ConnectExpression(*DiffuseLerp->GetInput(0));
DiffuseLerpB->ConnectExpression(*DiffuseLerp->GetInput(1));
DiffuseExpression->ConnectExpression(*DiffuseLerp->GetInput(2));
ColorExpression->ConnectExpression(*BaseColorMultiply->GetInput(0));
DiffuseLerp->ConnectExpression(*BaseColorMultiply->GetInput(1));
BaseColorMultiply->ConnectExpression(*BaseColorAdd->GetInput(0));
IncandescenceColorExpression->ConnectExpression(*BaseColorAdd->GetInput(1));
BaseColorAdd->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(0));
TransparencyOneMinus->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(1));
GlowIntensityExpression->ConnectExpression(*IncandescenceScaleMultiply->GetInput(0));
IncandescenceScale->ConnectExpression(*IncandescenceScaleMultiply->GetInput(1));
BaseColorTransparencyMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(0));
IncandescenceScaleMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(1));
TransparencyColorExpression->ConnectExpression(*TransparencyOneMinus->GetInput(0));
if (bIsTransparent)
{
TransparencyOneMinus->ConnectExpression(*BreakFloat3->GetInput(0));
BreakFloat3->ConnectExpression(*AddRG->GetInput(0), 0);
BreakFloat3->ConnectExpression(*AddRG->GetInput(1), 1);
AddRG->ConnectExpression(*AddRGB->GetInput(0));
BreakFloat3->ConnectExpression(*AddRGB->GetInput(1), 2);
AddRGB->ConnectExpression(*Divide->GetInput(0));
DivideConstant->ConnectExpression(*Divide->GetInput(1));
}
// Connect material outputs
MaterialElement->GetBaseColor().SetExpression(BaseColorTransparencyMultiply);
MaterialElement->GetEmissiveColor().SetExpression(IncandescenceMultiply);
if (bIsTransparent)
{
MaterialElement->GetOpacity().SetExpression(Divide);
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasLambertTransparent"));
}
else {
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasLambert"));
}
}
void FWireTranslatorImpl::AddAlLightSourceParameters(const TAlObjectPtr<AlShader>& Shader, TSharedPtr<IDatasmithUEPbrMaterialElement> MaterialElement)
{
// Default values for a LightSource material
FColor Color(145, 148, 153);
FColor TransparencyColor(0, 0, 0);
FColor IncandescenceColor(0, 0, 0);
double GlowIntensity = 0.0;
AlList* List = Shader->fields();
for (AlShadingFieldItem* Item = static_cast<AlShadingFieldItem*>(List->first()); Item; Item = Item->nextField())
{
double Value = 0.0f;
statusCode ErrorCode = Shader->parameter(Item->field(), Value);
if (ErrorCode != 0)
{
continue;
}
GetCommonParameters(Item->field(), Value, Color, TransparencyColor, IncandescenceColor, GlowIntensity);
}
bool bIsTransparent = IsTransparent(TransparencyColor);
// Construct parameter expressions
IDatasmithMaterialExpressionColor* ColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
ColorExpression->SetName(TEXT("Color"));
ColorExpression->GetColor() = FLinearColor::FromSRGBColor(Color);
IDatasmithMaterialExpressionColor* IncandescenceColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
IncandescenceColorExpression->SetName(TEXT("IncandescenceColor"));
IncandescenceColorExpression->GetColor() = FLinearColor::FromSRGBColor(IncandescenceColor);
IDatasmithMaterialExpressionColor* TransparencyColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
TransparencyColorExpression->SetName(TEXT("TransparencyColor"));
TransparencyColorExpression->GetColor() = FLinearColor::FromSRGBColor(TransparencyColor);
IDatasmithMaterialExpressionScalar* GlowIntensityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlowIntensityExpression->GetScalar() = GlowIntensity;
GlowIntensityExpression->SetName(TEXT("GlowIntensity"));
// Create aux expressions
IDatasmithMaterialExpressionGeneric* BaseColorAdd = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorAdd->SetExpressionName(TEXT("Add"));
IDatasmithMaterialExpressionGeneric* BaseColorTransparencyMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorTransparencyMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceScaleMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceScaleMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionScalar* IncandescenceScale = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
IncandescenceScale->GetScalar() = 100.0f;
IDatasmithMaterialExpressionGeneric* TransparencyOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
TransparencyOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionFunctionCall* BreakFloat3 = nullptr;
IDatasmithMaterialExpressionGeneric* AddRG = nullptr;
IDatasmithMaterialExpressionGeneric* AddRGB = nullptr;
IDatasmithMaterialExpressionGeneric* Divide = nullptr;
IDatasmithMaterialExpressionScalar* DivideConstant = nullptr;
if (bIsTransparent)
{
BreakFloat3 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionFunctionCall>();
BreakFloat3->SetFunctionPathName(TEXT("/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakFloat3Components.BreakFloat3Components"));
AddRG = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRG->SetExpressionName(TEXT("Add"));
AddRGB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRGB->SetExpressionName(TEXT("Add"));
Divide = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
Divide->SetExpressionName(TEXT("Divide"));
DivideConstant = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DivideConstant->GetScalar() = 3.0f;
}
// Connect expressions
ColorExpression->ConnectExpression(*BaseColorAdd->GetInput(0));
IncandescenceColorExpression->ConnectExpression(*BaseColorAdd->GetInput(1));
BaseColorAdd->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(0));
TransparencyOneMinus->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(1));
GlowIntensityExpression->ConnectExpression(*IncandescenceScaleMultiply->GetInput(0));
IncandescenceScale->ConnectExpression(*IncandescenceScaleMultiply->GetInput(1));
BaseColorTransparencyMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(0));
IncandescenceScaleMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(1));
TransparencyColorExpression->ConnectExpression(*TransparencyOneMinus->GetInput(0));
if (bIsTransparent)
{
TransparencyOneMinus->ConnectExpression(*BreakFloat3->GetInput(0));
BreakFloat3->ConnectExpression(*AddRG->GetInput(0), 0);
BreakFloat3->ConnectExpression(*AddRG->GetInput(1), 1);
AddRG->ConnectExpression(*AddRGB->GetInput(0));
BreakFloat3->ConnectExpression(*AddRGB->GetInput(1), 2);
AddRGB->ConnectExpression(*Divide->GetInput(0));
DivideConstant->ConnectExpression(*Divide->GetInput(1));
}
// Connect material outputs
MaterialElement->GetBaseColor().SetExpression(BaseColorTransparencyMultiply);
MaterialElement->GetEmissiveColor().SetExpression(IncandescenceMultiply);
if (bIsTransparent)
{
MaterialElement->GetOpacity().SetExpression(Divide);
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasLightSourceTransparent"));
}
else {
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasLightSource"));
}
}
void FWireTranslatorImpl::AddAlPhongParameters(const TAlObjectPtr<AlShader>& Shader, TSharedPtr<IDatasmithUEPbrMaterialElement> MaterialElement)
{
// Default values for a Phong material
FColor Color(145, 148, 153);
FColor TransparencyColor(0, 0, 0);
FColor IncandescenceColor(0, 0, 0);
FColor SpecularColor(38, 38, 38);
double Diffuse = 1.0;
double GlowIntensity = 0.0;
double Gloss = 0.8;
double Shinyness = 20.0;
double Specularity = 1.0;
double Reflectivity = 0.5;
AlList* List = Shader->fields();
for (AlShadingFieldItem* Item = static_cast<AlShadingFieldItem*>(List->first()); Item; Item = Item->nextField())
{
double Value = 0.0f;
statusCode ErrorCode = Shader->parameter(Item->field(), Value);
if (ErrorCode != 0)
{
continue;
}
if (GetCommonParameters(Item->field(), Value, Color, TransparencyColor, IncandescenceColor, GlowIntensity))
{
continue;
}
switch (Item->field())
{
case AlShadingFields::kFLD_SHADING_PHONG_DIFFUSE:
Diffuse = Value;
break;
case AlShadingFields::kFLD_SHADING_PHONG_GLOSS_:
Gloss = Value;
break;
case AlShadingFields::kFLD_SHADING_PHONG_SPECULAR_R:
SpecularColor.R = (uint8)(255.f * Value);;
break;
case AlShadingFields::kFLD_SHADING_PHONG_SPECULAR_G:
SpecularColor.G = (uint8)(255.f * Value);;
break;
case AlShadingFields::kFLD_SHADING_PHONG_SPECULAR_B:
SpecularColor.B = (uint8)(255.f * Value);;
break;
case AlShadingFields::kFLD_SHADING_PHONG_SPECULARITY_:
Specularity = Value;
break;
case AlShadingFields::kFLD_SHADING_PHONG_SHINYNESS:
Shinyness = Value;
break;
case AlShadingFields::kFLD_SHADING_PHONG_REFLECTIVITY:
Reflectivity = Value;
break;
}
}
bool bIsTransparent = IsTransparent(TransparencyColor);
// Construct parameter expressions
IDatasmithMaterialExpressionScalar* DiffuseExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseExpression->GetScalar() = Diffuse;
DiffuseExpression->SetName(TEXT("Diffuse"));
IDatasmithMaterialExpressionScalar* GlossExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlossExpression->GetScalar() = Gloss;
GlossExpression->SetName(TEXT("Gloss"));
IDatasmithMaterialExpressionColor* SpecularColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
SpecularColorExpression->SetName(TEXT("SpecularColor"));
SpecularColorExpression->GetColor() = FLinearColor::FromSRGBColor(SpecularColor);
IDatasmithMaterialExpressionScalar* SpecularityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
SpecularityExpression->GetScalar() = Specularity * 0.3;
SpecularityExpression->SetName(TEXT("Specularity"));
IDatasmithMaterialExpressionScalar* ShinynessExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ShinynessExpression->GetScalar() = Shinyness;
ShinynessExpression->SetName(TEXT("Shinyness"));
IDatasmithMaterialExpressionScalar* ReflectivityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ReflectivityExpression->GetScalar() = Reflectivity;
ReflectivityExpression->SetName(TEXT("Reflectivity"));
IDatasmithMaterialExpressionColor* ColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
ColorExpression->SetName(TEXT("Color"));
ColorExpression->GetColor() = FLinearColor::FromSRGBColor(Color);
IDatasmithMaterialExpressionColor* IncandescenceColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
IncandescenceColorExpression->SetName(TEXT("IncandescenceColor"));
IncandescenceColorExpression->GetColor() = FLinearColor::FromSRGBColor(IncandescenceColor);
IDatasmithMaterialExpressionColor* TransparencyColorExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionColor>();
TransparencyColorExpression->SetName(TEXT("TransparencyColor"));
TransparencyColorExpression->GetColor() = FLinearColor::FromSRGBColor(TransparencyColor);
IDatasmithMaterialExpressionScalar* GlowIntensityExpression = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
GlowIntensityExpression->GetScalar() = GlowIntensity;
GlowIntensityExpression->SetName(TEXT("GlowIntensity"));
// Create aux expressions
IDatasmithMaterialExpressionGeneric* ColorSpecLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ColorSpecLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* ColorSpecLerpValue = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ColorSpecLerpValue->GetScalar() = 0.96f;
IDatasmithMaterialExpressionGeneric* ColorMetallicLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ColorMetallicLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionGeneric* DiffuseLerp = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
DiffuseLerp->SetExpressionName(TEXT("LinearInterpolate"));
IDatasmithMaterialExpressionScalar* DiffuseLerpA = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpA->GetScalar() = 0.04f;
IDatasmithMaterialExpressionScalar* DiffuseLerpB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DiffuseLerpB->GetScalar() = 1.0f;
IDatasmithMaterialExpressionGeneric* BaseColorMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* BaseColorAdd = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorAdd->SetExpressionName(TEXT("Add"));
IDatasmithMaterialExpressionGeneric* BaseColorTransparencyMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
BaseColorTransparencyMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* IncandescenceScaleMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
IncandescenceScaleMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionScalar* IncandescenceScale = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
IncandescenceScale->GetScalar() = 100.0f;
IDatasmithMaterialExpressionGeneric* ShinynessSubtract = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ShinynessSubtract->SetExpressionName(TEXT("Subtract"));
IDatasmithMaterialExpressionScalar* ShinynessSubtract2 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ShinynessSubtract2->GetScalar() = 2.0f;
IDatasmithMaterialExpressionGeneric* ShinynessDivide = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
ShinynessDivide->SetExpressionName(TEXT("Divide"));
IDatasmithMaterialExpressionScalar* ShinynessDivide98 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
ShinynessDivide98->GetScalar() = 98.0f;
IDatasmithMaterialExpressionGeneric* SpecularityMultiply = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
SpecularityMultiply->SetExpressionName(TEXT("Multiply"));
IDatasmithMaterialExpressionGeneric* RoughnessOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
RoughnessOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionGeneric* TransparencyOneMinus = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
TransparencyOneMinus->SetExpressionName(TEXT("OneMinus"));
IDatasmithMaterialExpressionFunctionCall* BreakFloat3 = nullptr;
IDatasmithMaterialExpressionGeneric* AddRG = nullptr;
IDatasmithMaterialExpressionGeneric* AddRGB = nullptr;
IDatasmithMaterialExpressionGeneric* Divide = nullptr;
IDatasmithMaterialExpressionScalar* DivideConstant = nullptr;
if (bIsTransparent)
{
BreakFloat3 = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionFunctionCall>();
BreakFloat3->SetFunctionPathName(TEXT("/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakFloat3Components.BreakFloat3Components"));
AddRG = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRG->SetExpressionName(TEXT("Add"));
AddRGB = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
AddRGB->SetExpressionName(TEXT("Add"));
Divide = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionGeneric>();
Divide->SetExpressionName(TEXT("Divide"));
DivideConstant = MaterialElement->AddMaterialExpression<IDatasmithMaterialExpressionScalar>();
DivideConstant->GetScalar() = 3.0f;
}
// Connect expressions
SpecularColorExpression->ConnectExpression(*ColorSpecLerp->GetInput(0));
ColorExpression->ConnectExpression(*ColorSpecLerp->GetInput(1));
ColorSpecLerpValue->ConnectExpression(*ColorSpecLerp->GetInput(2));
ColorExpression->ConnectExpression(*ColorMetallicLerp->GetInput(0));
ColorSpecLerp->ConnectExpression(*ColorMetallicLerp->GetInput(1));
GlossExpression->ConnectExpression(*ColorMetallicLerp->GetInput(2));
DiffuseLerpA->ConnectExpression(*DiffuseLerp->GetInput(0));
DiffuseLerpB->ConnectExpression(*DiffuseLerp->GetInput(1));
DiffuseExpression->ConnectExpression(*DiffuseLerp->GetInput(2));
ColorMetallicLerp->ConnectExpression(*BaseColorMultiply->GetInput(0));
DiffuseLerp->ConnectExpression(*BaseColorMultiply->GetInput(1));
BaseColorMultiply->ConnectExpression(*BaseColorAdd->GetInput(0));
IncandescenceColorExpression->ConnectExpression(*BaseColorAdd->GetInput(1));
BaseColorAdd->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(0));
TransparencyOneMinus->ConnectExpression(*BaseColorTransparencyMultiply->GetInput(1));
GlowIntensityExpression->ConnectExpression(*IncandescenceScaleMultiply->GetInput(0));
IncandescenceScale->ConnectExpression(*IncandescenceScaleMultiply->GetInput(1));
BaseColorTransparencyMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(0));
IncandescenceScaleMultiply->ConnectExpression(*IncandescenceMultiply->GetInput(1));
ShinynessExpression->ConnectExpression(*ShinynessSubtract->GetInput(0));
ShinynessSubtract2->ConnectExpression(*ShinynessSubtract->GetInput(1));
ShinynessSubtract->ConnectExpression(*ShinynessDivide->GetInput(0));
ShinynessDivide98->ConnectExpression(*ShinynessDivide->GetInput(1));
ShinynessDivide->ConnectExpression(*SpecularityMultiply->GetInput(0));
SpecularityExpression->ConnectExpression(*SpecularityMultiply->GetInput(1));
SpecularityMultiply->ConnectExpression(*RoughnessOneMinus->GetInput(0));
TransparencyColorExpression->ConnectExpression(*TransparencyOneMinus->GetInput(0));
if (bIsTransparent)
{
TransparencyOneMinus->ConnectExpression(*BreakFloat3->GetInput(0));
BreakFloat3->ConnectExpression(*AddRG->GetInput(0), 0);
BreakFloat3->ConnectExpression(*AddRG->GetInput(1), 1);
AddRG->ConnectExpression(*AddRGB->GetInput(0));
BreakFloat3->ConnectExpression(*AddRGB->GetInput(1), 2);
AddRGB->ConnectExpression(*Divide->GetInput(0));
DivideConstant->ConnectExpression(*Divide->GetInput(1));
}
// Connect material outputs
MaterialElement->GetBaseColor().SetExpression(BaseColorTransparencyMultiply);
MaterialElement->GetMetallic().SetExpression(GlossExpression);
MaterialElement->GetSpecular().SetExpression(ReflectivityExpression);
MaterialElement->GetRoughness().SetExpression(RoughnessOneMinus);
MaterialElement->GetEmissiveColor().SetExpression(IncandescenceMultiply);
if (bIsTransparent)
{
MaterialElement->GetOpacity().SetExpression(Divide);
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasPhongTransparent"));
}
else {
MaterialElement->SetParentLabel(TEXT("M_DatasmithAliasPhong"));
}
}
class FWireInterfaceModule : public IModuleInterface
{
public:
virtual void StartupModule() override
{
uint64 AliasVersion = IWireInterface::GetRequiredAliasVersion();
#ifdef OPEN_MODEL_2020
// Check installed version of Alias Tools because binaries before 2021.3 are not compatible with Alias 2022
if (LibAlias2020_Version < AliasVersion && AliasVersion < LibAlias2021_Version)
{
static const bool bIsDisplay = []() -> bool
{
UE_LOG(LogWireInterface, Warning, TEXT(WRONG_VERSION_TEXT));
return true;
}();
return;
}
#endif
if (LibAliasVersionMin <= AliasVersion && AliasVersion < LibAliasVersionMax)
{
auto MakeInterfaceFunc = []() -> TSharedPtr<IWireInterface>
{
return MakeShared<FWireTranslatorImpl>();
};
IWireInterface::RegisterInterface(UE_OPENMODEL_MAJOR_VERSION, UE_OPENMODEL_MAJOR_VERSION, MoveTemp(MakeInterfaceFunc));
}
}
virtual void ShutdownModule() override
{
#if WIRE_MEMORY_CHECK
// #wire_import: Need to investigate why this is crashing when enabled.
if (bool(AlUniverse::isInitialized()))
{
AlUniverse::deleteAll();
}
#endif
}
};
#if TRACK_MESHELEMENT
#pragma optimize("", off)
void MakeMeshVisible(FMeshDescription& MeshDescription)
{
#if MAKE_VISIBLE
using namespace UE::Geometry;
TVertexAttributesRef<FVector3f> VertexPositions = MeshDescription.GetVertexPositions();
TArrayView<FVector3f> Positions = VertexPositions.GetRawArray();
TOrientedBox3<float> OBox = FitOrientedBox3Points<float>(Positions);
FVertexArray& Vertices = MeshDescription.Vertices();
const TMatrix3<float> Matrix = OBox.Frame.Rotation.ToRotationMatrix();
constexpr float MinSize = 1.f;
constexpr float MaxSize = 20.f;
const float ScaleX = OBox.Extents.X < MinSize ? 20.f / OBox.Extents.X : OBox.Extents.X > MaxSize ? MaxSize / OBox.Extents.X : 10.f;
const float ScaleY = OBox.Extents.Y < MinSize ? 20.f / OBox.Extents.Y : OBox.Extents.Y > MaxSize ? MaxSize / OBox.Extents.Y : 10.f;
const float ScaleZ = OBox.Extents.Z < MinSize ? 20.f / OBox.Extents.Z : OBox.Extents.Z > MaxSize ? MaxSize / OBox.Extents.Z : 10.f;
UE_LOG(LogWireInterface, Warning, TEXT("Scaling factor: %.3f %.3f %.3f"), ScaleX, ScaleY, ScaleZ);
const FVector3f AxisX = OBox.AxisX();
const FVector3f AxisY = OBox.AxisY();
const FVector3f AxisZ = OBox.AxisZ();
for (const FVertexID& VertexID : MeshDescription.Vertices().GetElementIDs())
{
FVector3f P = VertexPositions[VertexID] - OBox.Frame.Origin;
VertexPositions[VertexID] = ((P | AxisX) * ScaleX) * AxisX + ((P | AxisY) * ScaleY) * AxisY + ((P | AxisZ) * ScaleZ) * AxisZ;
}
#endif
}
#endif
} // namespace
#undef LOCTEXT_NAMESPACE // "DatasmithWireTranslator"
#else // USE_OPENMODEL
namespace UE_DATASMITHWIRETRANSLATOR_NAMESPACE
{
class FWireInterfaceModule : public IModuleInterface
{
public:
virtual void StartupModule() override
{
}
virtual void ShutdownModule() override
{
}
};
}
#endif
// need this macro wrapper to expand the UE_DATASMITHWIRETRANSLATOR_MODULE_NAME macro and not create symbols with "UE_DATASMITHWIRETRANSLATOR_MODULE_NAME" in the token
#define IMPLEMENT_MODULE_WRAPPER(ModuleName) IMPLEMENT_MODULE(UE_DATASMITHWIRETRANSLATOR_NAMESPACE::FWireInterfaceModule, ModuleName);
IMPLEMENT_MODULE_WRAPPER(UE_DATASMITHWIRETRANSLATOR_MODULE_NAME)