2019-12-26 23:01:54 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-04 13:11:45 -04:00
# include "DatasmithMaxSceneParser.h"
# include "DatasmithMaxAttributes.h"
# include "DatasmithMaxSceneExporter.h"
# include "DatasmithMaxProgressManager.h"
# include "DatasmithMaxLogger.h"
# include "DatasmithMaxWriter.h"
# include "Misc/Paths.h"
# include "Algo/Find.h"
2022-05-17 01:38:58 -04:00
# include "Windows/AllowWindowsPlatformTypes.h"
2019-10-04 13:11:45 -04:00
# if WITH_ITOO_INTERFACE
# pragma warning( push )
# pragma warning( disable: 4238 )
//#include "itoo/forestitreesinterface.h"
# include "itreesinterface.H"
# pragma warning( pop )
# include "ircinterface.H"
# endif // WITH_ITOO_INTERFACE
MAX_INCLUDES_START
# include "lslights.h"
# include "xref/iXrefObj.h"
MAX_INCLUDES_END
const TArray < FString , TInlineAllocator < 4 > > FDatasmithMaxSceneParser : : CollisionNodesPrefixes = { TEXT ( " UBX " ) , TEXT ( " UCX " ) , TEXT ( " UCP " ) , TEXT ( " USP " ) } ;
class FMaxRendereableNode : public FNoncopyable
{
public :
FMaxRendereableNode ( INode * InNode , EMaxEntityType EntityType ) ;
FMaxRendereableNode ( INode * InNode , EMaxEntityType EntityType , const TOptional < FDatasmithMaxStaticMeshAttributes > & InStaticMeshAttributes ) ;
INode * Node ;
EMaxExporterInstanceMode Instancemode ;
EMaxTriMode Triangulatemode ;
EMaxEntityType Entitytype ;
INodeTab Instances ;
//if 0 faces this becomes false
bool bIsReadyToExport ;
//This is used for railclone
TUniquePtr < Mesh > MaxMesh ;
//This is used for the forest pack. It allow to use a different node for the static mesh export
INode * CustomMeshNode ;
//This is used only for the UnrealHISM
int32 MeshIndex ;
TUniquePtr < TArray < Matrix3 > > InstancesTransformPtr ;
//used for the mesh export when the datasmith attribute modifier is present
TOptional < FDatasmithMaxStaticMeshAttributes > StaticMeshAttributes ;
private :
void SetTriangulateMode ( ) ;
} ;
//***************************************************************************
// IInstanceMgr::GetInstanceMgr()->GetInstances() functions is finding
2021-06-10 13:13:24 -04:00
// any object references. This function collects actual instances :)
// returns whether multiple instances are found
2019-10-04 13:11:45 -04:00
//***************************************************************************
2021-06-10 13:13:24 -04:00
bool FDatasmithMaxSceneParser : : GetActualInstances ( INode * pINode , INodeTab * OnlyInstance )
2019-10-04 13:11:45 -04:00
{
2021-06-10 13:13:24 -04:00
check ( pINode ) ;
check ( OnlyInstance ) ;
2019-10-04 13:11:45 -04:00
Object * Obj = pINode - > GetObjOrWSMRef ( ) ;
INodeTab InstanceAndRef ;
if ( IInstanceMgr : : GetInstanceMgr ( ) - > GetInstances ( * pINode , InstanceAndRef ) < 2 )
{
OnlyInstance - > AppendNode ( pINode ) ;
return false ;
}
for ( int k = 0 ; k < InstanceAndRef . Count ( ) ; k + + )
{
if ( Obj = = InstanceAndRef [ k ] - > GetObjOrWSMRef ( ) )
{
OnlyInstance - > AppendNode ( InstanceAndRef [ k ] ) ;
}
}
2021-06-10 13:13:24 -04:00
return OnlyInstance - > Count ( ) > = 2 ;
2019-10-04 13:11:45 -04:00
}
EMaxLightClass FDatasmithMaxSceneParser : : GetLightClass ( INode * Node )
{
EMaxLightClass LightClass = EMaxLightClass : : Unknown ;
ObjectState ObjState = Node - > EvalWorldState ( 0 ) ;
if ( ObjState . obj - > SuperClassID ( ) = = LIGHT_CLASS_ID )
{
LightObject * Light = ( LightObject * ) ObjState . obj ;
if ( Light ! = nullptr )
{
Class_ID ClassID = Light - > ClassID ( ) ;
if ( ClassID = = THEAOMNICLASS )
{
LightClass = EMaxLightClass : : TheaLightOmni ;
}
else if ( ClassID = = THEASPOTCLASS )
{
LightClass = EMaxLightClass : : TheaLightSpot ;
}
else if ( ClassID = = THEAIESCLASS )
{
LightClass = EMaxLightClass : : TheaLightIES ;
}
else if ( ClassID = = THEAPLANECLASS )
{
LightClass = EMaxLightClass : : TheaLightPlane ;
}
else if ( ClassID = = REGULARSPOTACLASS | | ClassID = = REGULARSPOTBCLASS )
{
LightClass = EMaxLightClass : : SpotLight ;
}
else if ( ClassID = = REGULARDIRECTACLASS | | ClassID = = REGULARDIRECTBCLASS )
{
LightClass = EMaxLightClass : : DirectLight ;
INode * ParentNode = Node - > GetParentNode ( ) ;
if ( ParentNode )
{
ObjectState ParentObjectState = ParentNode - > EvalWorldState ( 0 ) ;
if ( ParentObjectState . obj & & ParentObjectState . obj - > ClassID ( ) = = DAYLIGHTASSEMBLYCLASS )
{
LightClass = EMaxLightClass : : SunEquivalent ;
}
}
}
else if ( ClassID = = REGULAROMNICLASS )
{
LightClass = EMaxLightClass : : OmniLight ;
}
else if ( Light - > IsSubClassOf ( LIGHTSCAPE_LIGHT_CLASS ) )
{
LightClass = EMaxLightClass : : PhotometricLight ;
}
else if ( ClassID = = PHOTOPLANEACLASS | | ClassID = = PHOTOPLANEBCLASS )
{
LightClass = EMaxLightClass : : PhotoplaneLight ;
}
else if ( ClassID = = VRAYLIGHTIESCLASS )
{
LightClass = EMaxLightClass : : VRayLightIES ;
}
else if ( ClassID = = VRAYLIGHTCLASS )
{
LightClass = EMaxLightClass : : VRayLight ;
}
else if ( ClassID = = CORONALIGHTCLASS )
{
LightClass = EMaxLightClass : : CoronaLight ;
}
else if ( ClassID = = ARNOLDLIGHTCLASS )
{
LightClass = EMaxLightClass : : ArnoldLight ;
}
else if ( ClassID = = SUNLIGHTACLASS | |
ClassID = = SUNLIGHTBCLASS | |
ClassID = = VRAYSUNCLASS | |
ClassID = = SUNPOSITIONERCLASS | |
ClassID = = CORONASUNCLASS | |
ClassID = = CORONASUNCLASSB )
{
LightClass = EMaxLightClass : : SunEquivalent ;
}
else if ( ClassID = = SKYLIGHTCLASS | |
ClassID = = IESSKYLIGHTCLASS | |
ClassID = = MRSKYLIGHTCLASS )
{
LightClass = EMaxLightClass : : SkyEquivalent ;
}
else if ( ClassID = = MRPORTALLIGHTCLASS )
{
LightClass = EMaxLightClass : : SkyPortal ;
}
}
}
if ( LightClass = = EMaxLightClass : : Unknown )
{
DatasmithMaxLogger : : Get ( ) . AddUnsupportedLight ( Node ) ;
}
return LightClass ;
}
bool FDatasmithMaxSceneParser : : CanBeTriMesh ( Object * Obj )
{
if ( Obj = = NULL )
{
return false ;
}
int CanConvertToTri = Obj - > CanConvertToType ( Class_ID ( TRIOBJ_CLASS_ID , 0 ) ) ;
if ( CanConvertToTri = = 0 )
{
return false ;
}
TriObject * Tri = ( TriObject * ) Obj - > ConvertToType ( GetCOREInterface ( ) - > GetTime ( ) , Class_ID ( TRIOBJ_CLASS_ID , 0 ) ) ;
if ( Tri = = NULL )
{
return false ;
}
bool bResult = true ;
if ( Tri - > GetMesh ( ) . getNumFaces ( ) = = 0 )
{
bResult = false ;
}
if ( Obj ! = Tri )
{
Tri - > DeleteMe ( ) ;
}
return bResult ;
}
bool FDatasmithMaxSceneParser : : HasCollisionName ( INode * Node )
{
FString NodeName = Node - > GetName ( ) ;
FString LeftString , RightString ;
if ( NodeName . Split ( TEXT ( " _ " ) , & LeftString , & RightString ) )
{
if ( CollisionNodesPrefixes . Find ( LeftString ) ! = INDEX_NONE )
{
return true ;
}
}
return false ;
}
FMaxRendereableNode : : FMaxRendereableNode ( INode * InNode , EMaxEntityType Mode )
: Node ( InNode )
, Instancemode ( EMaxExporterInstanceMode : : NotInstanced )
, Triangulatemode ( EMaxTriMode : : TriNotChecked )
, Entitytype ( Mode )
, Instances ( )
, bIsReadyToExport ( true )
, MaxMesh ( nullptr )
, CustomMeshNode ( nullptr )
, MeshIndex ( - 1 )
, InstancesTransformPtr ( )
, StaticMeshAttributes ( )
{
SetTriangulateMode ( ) ;
}
FMaxRendereableNode : : FMaxRendereableNode ( INode * InNode , EMaxEntityType EntityType , const TOptional < FDatasmithMaxStaticMeshAttributes > & InStaticMeshAttributes )
: Node ( InNode )
, Instancemode ( EMaxExporterInstanceMode : : NotInstanced )
, Triangulatemode ( EMaxTriMode : : TriNotChecked )
, Entitytype ( EntityType )
, Instances ( )
, bIsReadyToExport ( true )
, MaxMesh ( nullptr )
, CustomMeshNode ( nullptr )
, MeshIndex ( - 1 )
, InstancesTransformPtr ( )
, StaticMeshAttributes ( InStaticMeshAttributes )
{
SetTriangulateMode ( ) ;
}
void FMaxRendereableNode : : SetTriangulateMode ( )
{
if ( Entitytype = = EMaxEntityType : : Geometry )
{
if ( Node )
{
Object * Obj = Node - > EvalWorldState ( 0 ) . obj ;
if ( FDatasmithMaxSceneParser : : CanBeTriMesh ( Obj ) )
{
Triangulatemode = EMaxTriMode : : TriEnabled ;
}
else
{
Triangulatemode = EMaxTriMode : : TriDisabled ;
}
}
}
}
FDatasmithMaxSceneParser : : FDatasmithMaxSceneParser ( )
{
Status = 1 ;
bOnlySelection = false ;
}
FDatasmithMaxSceneParser : : ~ FDatasmithMaxSceneParser ( )
{
}
DWORD WINAPI DummyFunction ( LPVOID Arg )
{
return ( 0 ) ;
}
void FDatasmithMaxSceneParser : : ParseCurrentScene ( bool bSelectedOnly , TSharedPtr < FDatasmithMaxProgressManager > & ProgressManager )
{
bOnlySelection = bSelectedOnly ;
RenderableNodes . Empty ( ) ;
Materials . Empty ( ) ;
MaterialNames . Empty ( ) ;
EncounteredMaterials . Empty ( ) ;
EncounteredTextures . Empty ( ) ;
Textures . Empty ( ) ;
if ( bSelectedOnly = = false & & GetCOREInterface ( ) - > GetUseEnvironmentMap ( ) )
{
TexEnum ( GetCOREInterface ( ) - > GetEnvironmentMap ( ) ) ; //environment is not associated to any Node
}
ProgressManager - > SetProgressStart ( 0 ) ;
ProgressManager - > SetProgressEnd ( 100 ) ;
ProgressManager - > SetMainMessage ( TEXT ( " Parsing scene objects " ) ) ;
NodeEnum ( GetCOREInterface ( ) - > GetRootNode ( ) , bSelectedOnly , ProgressManager ) ;
NodeEnumInstanceClean ( ) ;
}
int FDatasmithMaxSceneParser : : GetRendereableNodesCount ( )
{
return ( int ) RenderableNodes . Num ( ) ;
}
EMaxEntityType FDatasmithMaxSceneParser : : GetEntityType ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . Entitytype ;
}
INode * FDatasmithMaxSceneParser : : GetNode ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . Node ;
}
INode * FDatasmithMaxSceneParser : : GetCustomMeshNode ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . CustomMeshNode ;
}
Mesh * FDatasmithMaxSceneParser : : GetMaxMesh ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . MaxMesh . Get ( ) ;
}
int32 FDatasmithMaxSceneParser : : GetRailCloneMeshIndex ( int NodeIndex ) const
{
return RenderableNodes [ NodeIndex ] . MeshIndex ;
}
TArray < Matrix3 > * FDatasmithMaxSceneParser : : GetInstancesTransform ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . InstancesTransformPtr . Get ( ) ;
}
const TOptional < FDatasmithMaxStaticMeshAttributes > & FDatasmithMaxSceneParser : : GetDatasmithStaticMeshAttributes ( int NodeIndex ) const
{
return RenderableNodes [ NodeIndex ] . StaticMeshAttributes ;
}
EMaxExporterInstanceMode FDatasmithMaxSceneParser : : GetInstanceMode ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . Instancemode ;
}
INodeTab FDatasmithMaxSceneParser : : GetInstances ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . Instances ;
}
bool FDatasmithMaxSceneParser : : GetReadyToExport ( int NodeIndex )
{
return RenderableNodes [ NodeIndex ] . bIsReadyToExport ;
}
void FDatasmithMaxSceneParser : : SetReadyToExport ( int NodeIndex , bool ready )
{
RenderableNodes [ NodeIndex ] . bIsReadyToExport = ready ;
}
int FDatasmithMaxSceneParser : : GetMaterialsCount ( )
{
return ( int ) Materials . Num ( ) ;
}
Mtl * FDatasmithMaxSceneParser : : GetMaterial ( int MaterialIndex )
{
return Materials [ MaterialIndex ] ;
}
void FDatasmithMaxSceneParser : : RestoreMaterialNames ( )
{
for ( int i = 0 ; i < MaterialNames . Num ( ) ; i + + )
{
Materials [ i ] - > SetName ( * MaterialNames [ i ] ) ;
}
}
int FDatasmithMaxSceneParser : : GetTexturesCount ( )
{
return ( int ) Textures . Num ( ) ;
}
Texmap * FDatasmithMaxSceneParser : : GetTexture ( int TextureIndex )
{
return Textures [ TextureIndex ] ;
}
void FDatasmithMaxSceneParser : : MaterialEnum ( Mtl * Material , bool bAddMaterial )
{
if ( Material = = NULL )
{
return ;
}
if ( EncounteredMaterials . Contains ( Material ) )
{
return ;
}
if ( FDatasmithMaxMatHelper : : GetMaterialClass ( Material ) = = EDSMaterialType : : XRefMat )
{
MaterialEnum ( FDatasmithMaxMatHelper : : GetRenderedXRefMaterial ( Material ) , true ) ;
}
else if ( FDatasmithMaxMatHelper : : GetMaterialClass ( Material ) = = EDSMaterialType : : MultiMat )
{
for ( int i = 0 ; i < Material - > NumSubMtls ( ) ; i + + )
{
MaterialEnum ( Material - > GetSubMtl ( i ) , true ) ;
}
}
else
{
if ( bAddMaterial )
{
int DuplicateCount = 0 ;
FString ProposedName = Material - > GetName ( ) . data ( ) ;
MaterialNames . Add ( * ProposedName ) ;
FDatasmithUtils : : SanitizeNameInplace ( ProposedName ) ;
for ( int i = 0 ; i < Materials . Num ( ) ; i + + )
{
if ( ProposedName = = FDatasmithUtils : : SanitizeName ( Materials [ i ] - > GetName ( ) . data ( ) ) )
{
DuplicateCount + + ;
ProposedName = FDatasmithUtils : : SanitizeName ( Material - > GetName ( ) . data ( ) ) + TEXT ( " _( " ) + FString : : FromInt ( DuplicateCount ) + TEXT ( " ) " ) ;
}
}
Material - > SetName ( * ProposedName ) ;
EncounteredMaterials . Add ( Material ) ;
Materials . Add ( Material ) ;
}
2020-09-24 00:43:27 -04:00
bool bAddRecursively = Material - > ClassID ( ) = = THEARANDOMCLASS | | Material - > ClassID ( ) = = VRAYBLENDMATCLASS | | Material - > ClassID ( ) = = CORONALAYERMATCLASS ;
2019-10-04 13:11:45 -04:00
for ( int i = 0 ; i < Material - > NumSubMtls ( ) ; i + + )
{
MaterialEnum ( Material - > GetSubMtl ( i ) , bAddRecursively ) ;
}
for ( int i = 0 ; i < Material - > NumSubTexmaps ( ) ; i + + )
{
Texmap * SubTexture = Material - > GetSubTexmap ( i ) ;
if ( SubTexture ! = NULL )
{
TexEnum ( SubTexture ) ;
}
}
}
}
void FDatasmithMaxSceneParser : : LightTexEnum ( INode * Node )
{
ObjectState ObjState = Node - > EvalWorldState ( 0 ) ;
LightObject * Light = ( LightObject * ) ObjState . obj ;
if ( Light = = NULL )
{
return ;
}
int NumParamBlocks = Light - > NumParamBlocks ( ) ;
for ( int j = 0 ; j < NumParamBlocks ; j + + )
{
IParamBlock2 * ParamBlock2 = Light - > GetParamBlockByID ( ( short ) j ) ;
if ( ParamBlock2 )
{
ParamBlockDesc2 * ParamBlockDesc = ParamBlock2 - > GetDesc ( ) ;
if ( ParamBlockDesc ! = NULL )
{
for ( int i = 0 ; i < ParamBlockDesc - > count ; i + + )
{
const ParamDef & ParamDefinition = ParamBlockDesc - > paramdefs [ i ] ;
if ( FCString : : Stricmp ( ParamDefinition . int_name , TEXT ( " texmap " ) ) = = 0 )
{
Texmap * Texture = ParamBlock2 - > GetTexmap ( ParamDefinition . ID , GetCOREInterface ( ) - > GetTime ( ) ) ;
if ( Texture ! = NULL )
{
TexEnum ( Texture ) ;
}
}
}
}
2020-02-17 14:07:50 -05:00
ParamBlock2 - > ReleaseDesc ( ) ;
2019-10-04 13:11:45 -04:00
}
}
}
void FDatasmithMaxSceneParser : : TexEnum ( Texmap * Texture )
{
if ( Texture = = NULL )
{
return ;
}
if ( EncounteredTextures . Contains ( Texture ) )
{
return ;
}
EncounteredTextures . Add ( Texture ) ;
Textures . Add ( Texture ) ;
for ( int i = 0 ; i < Texture - > NumSubTexmaps ( ) ; i + + )
{
Texmap * SubTexture = Texture - > GetSubTexmap ( i ) ;
if ( SubTexture ! = NULL )
{
TexEnum ( SubTexture ) ;
}
}
}
void FDatasmithMaxSceneParser : : NodeEnum ( INode * Node , bool bSelectedOnly , TSharedPtr < FDatasmithMaxProgressManager > & ProgressManager )
{
// nodes comming from XRef Scenes/Objects could be null
if ( Node = = NULL )
{
return ;
}
// Is the Node hidden?
BOOL bIsNodeHidden = Node - > IsNodeHidden ( TRUE ) ;
if ( bIsNodeHidden = = false )
{
for ( int XRefChild = 0 ; XRefChild < Node - > GetXRefFileCount ( ) ; + + XRefChild )
{
FString Path = FDatasmithMaxSceneExporter : : GetActualPath ( Node - > GetXRefFile ( XRefChild ) . GetFileName ( ) ) ;
if ( FPaths : : FileExists ( Path ) = = false )
{
FString Error = FString ( " XRefScene file \" " ) + FPaths : : GetCleanFilename ( * Path ) + FString ( " \" cannot be found " ) ;
DatasmithMaxLogger : : Get ( ) . AddMissingAssetError ( * Error ) ;
}
else
{
NodeEnum ( Node - > GetXRefTree ( XRefChild ) , bSelectedOnly , ProgressManager ) ;
}
}
}
// Get the ObjectState.
// The ObjectState is the structure Other flows up the pipeline.
// It contains a matrix, a material index, some flags for channels,
// and a pointer to the object in the pipeline.
ObjectState ObjState = Node - > EvalWorldState ( 0 ) ;
if ( ObjState . obj = = NULL )
{
int NumChildren = Node - > NumberOfChildren ( ) ;
2021-06-10 13:13:24 -04:00
int LastDisplayedProgress = - 1 ;
2019-10-04 13:11:45 -04:00
for ( int ChildIndex = 0 ; ChildIndex < NumChildren ; + + ChildIndex )
{
2021-06-10 13:13:24 -04:00
int Progress = ( ChildIndex * 100 ) / NumChildren ;
if ( Progress ! = LastDisplayedProgress )
{
LastDisplayedProgress = Progress ;
FString Msg = FString : : Printf ( TEXT ( " %d%% " ) , Progress ) . Left ( 255 ) ;
// Show progress bar without the Cancel button
ProgressManager - > ProgressEvent ( Progress * 0.01f , * Msg ) ;
}
2019-10-04 13:11:45 -04:00
NodeEnum ( Node - > GetChildNode ( ChildIndex ) , bSelectedOnly , ProgressManager ) ;
}
return ;
}
if ( bIsNodeHidden = = false )
{
if ( ObjState . obj - > ClassID ( ) = = XREFOBJ_CLASS_ID )
{
//max2017 and newer versions allow developers to get the file, with previous versions you only can retrieve the active one
# ifdef MAX_RELEASE_R19
FString Path = FDatasmithMaxSceneExporter : : GetActualPath ( ( ( IXRefObject8 * ) ObjState . obj ) - > GetFile ( FALSE ) . GetFileName ( ) ) ;
# else
FString Path = FDatasmithMaxSceneExporter : : GetActualPath ( ( ( IXRefObject8 * ) ObjState . obj ) - > GetActiveFile ( ) . GetFileName ( ) ) ;
# endif
if ( FPaths : : FileExists ( Path ) = = false )
{
FString Error = FString ( " XRefObj file \" " ) + FPaths : : GetCleanFilename ( * Path ) + FString ( " \" cannot be found " ) ;
DatasmithMaxLogger : : Get ( ) . AddMissingAssetError ( * Error ) ;
bIsNodeHidden = true ;
}
}
}
// Examine the superclass ID in order to figure out what kind
// of object we are dealing with.
if ( ( ! bSelectedOnly | | Node - > Selected ( ) ! = 0 ) & & bIsNodeHidden = = false )
{
switch ( ObjState . obj - > SuperClassID ( ) )
{
case CAMERA_CLASS_ID :
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Camera ) ;
break ;
}
case LIGHT_CLASS_ID :
{
EMaxLightClass lightClass = GetLightClass ( Node ) ;
if ( lightClass ! = EMaxLightClass : : Unknown )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Light ) ;
LightTexEnum ( Node ) ;
}
break ;
}
case SHAPE_CLASS_ID :
{
if ( ! ObjState . obj - > IsRenderable ( ) | | ! Node - > Renderable ( ) )
{
if ( Node - > NumberOfChildren ( ) > 0 )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
}
break ;
}
RenderableNodes . Emplace ( Node , EMaxEntityType : : Geometry ) ;
MaterialEnum ( Node - > GetMtl ( ) , true ) ;
break ;
}
case GEOMOBJECT_CLASS_ID :
{
Class_ID ClassID = ObjState . obj - > ClassID ( ) ;
if ( ClassID = = Class_ID ( TARGET_CLASS_ID , 0x0 ) )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
}
else if ( ! ObjState . obj - > IsRenderable ( ) | | ! Node - > Renderable ( ) )
{
if ( Node - > NumberOfChildren ( ) > 0 )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
}
}
else if ( ClassID = = VRAYPLANE_CLASS_ID | |
ClassID = = VRAYFUR_CLASS_ID | |
ClassID = = VRAYSPHERE_CLASS_ID | |
ClassID = = MENTALPROXY_CLASS_ID | |
ClassID = = PFLOWEVENT_CLASS_ID | |
ClassID = = POPULATE_CLASS_ID )
{
if ( Node - > NumberOfChildren ( ) > 0 )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
}
}
else if ( ClassID = = ITOOFOREST_CLASS_ID )
{
ParseForestNode ( Node ) ;
}
else if ( ClassID = = RAILCLONE_CLASS_ID )
{
ParseRailcloneNode ( Node ) ;
}
else if ( ! HasCollisionName ( Node ) )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Geometry , FDatasmithMaxStaticMeshAttributes : : ExtractStaticMeshAttributes ( Node ) ) ;
const FMaxRendereableNode & RenderedNode = RenderableNodes . Last ( ) ;
if ( RenderedNode . StaticMeshAttributes & & RenderedNode . StaticMeshAttributes - > GetCustomCollisonNode ( ) )
{
ToBeRemovedFromRenderableNodes . Add ( RenderedNode . StaticMeshAttributes - > GetCustomCollisonNode ( ) ) ;
}
if ( ! RenderedNode . StaticMeshAttributes | | RenderedNode . StaticMeshAttributes - > GetExportMode ( ) = = EStaticMeshExportMode : : Default )
{
MaterialEnum ( Node - > GetMtl ( ) , true ) ;
}
}
break ;
}
case HELPER_CLASS_ID :
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
break ;
}
default :
{
if ( Node - > NumberOfChildren ( ) > 0 )
{
RenderableNodes . Emplace ( Node , EMaxEntityType : : Dummy ) ;
}
break ;
}
}
}
// For each child of this Node, we recurse into ourselves
// until no more children are found.
for ( int ChildIndex = 0 ; ChildIndex < Node - > NumberOfChildren ( ) ; ChildIndex + + )
{
NodeEnum ( Node - > GetChildNode ( ChildIndex ) , bSelectedOnly , ProgressManager ) ;
}
}
void FDatasmithMaxSceneParser : : NodeEnumInstanceClean ( )
{
for ( int CurrentNode = 0 ; CurrentNode < RenderableNodes . Num ( ) ; + + CurrentNode )
{
FMaxRendereableNode & RenderableNode = RenderableNodes [ CurrentNode ] ;
if ( RenderableNode . Instancemode ! = EMaxExporterInstanceMode : : UnrealHISM )
{
if ( GetActualInstances ( RenderableNode . Node , & RenderableNode . Instances ) )
{
RenderableNode . Instancemode = EMaxExporterInstanceMode : : InstanceMaster ;
// Remove duplicated Instances nodes from the RenderableNodes without preserving the order.
// The RenderableNodes order only affects the order of the StaticMeshes and ActorMeshes in the .udatasmith file
for ( int32 h = RenderableNodes . Num ( ) - 1 ; h > CurrentNode ; - - h )
{
if ( RenderableNode . Instances . Contains ( RenderableNodes [ h ] . Node ) )
{
2021-06-10 13:13:24 -04:00
bool bAllowShrink = false ; // As we keep references on elements of this array, we cannot allow a realloc.
RenderableNodes . RemoveAtSwap ( h , 1 , bAllowShrink ) ;
2019-10-04 13:11:45 -04:00
}
}
}
else
{
RenderableNode . Instancemode = EMaxExporterInstanceMode : : NotInstanced ;
}
}
if ( ToBeRemovedFromRenderableNodes . Contains ( RenderableNode . Node ) )
{
if ( RenderableNode . StaticMeshAttributes )
{
FString Error = FString ( TEXT ( " The datasmith attributes aren't supported for a collision mesh. ( " ) ) + FString ( ( TCHAR * ) RenderableNode . Node - > GetName ( ) ) + FString ( " ) " ) ;
DatasmithMaxLogger : : Get ( ) . AddGeneralError ( * Error ) ;
}
RenderableNodes . RemoveAtSwap ( CurrentNode ) ;
// We don't want to jump over the node that was swap in the place of the removed node
- - CurrentNode ;
continue ;
}
}
}
# if WITH_ITOO_INTERFACE
void FDatasmithMaxSceneParser : : ParseForestNode ( INode * ForestNode )
{
TimeValue CurrentTime = GetCOREInterface ( ) - > GetTime ( ) ;
ITreesInterface * ITrees = GetTreesInterface ( ForestNode - > GetObjectRef ( ) ) ;
ITrees - > IForestRenderBegin ( CurrentTime ) ;
TMap < int , FMaxRendereableNode * > AlreadyAddedSpec ;
int NumInstances ;
TForestInstance * ForestInstance = ( TForestInstance * ) ITrees - > IForestGetRenderNodes ( NumInstances ) ;
ulong ForestHandle = ForestNode - > GetHandle ( ) ;
FString ForestName = ForestNode - > GetName ( ) ;
Matrix3 ForestMatrix = ForestNode - > GetNodeTM ( CurrentTime ) ;
if ( ForestInstance & & NumInstances )
{
for ( int i = 0 ; i < NumInstances ; i + + , ForestInstance + + )
{
if ( ForestInstance - > node ! = NULL )
{
int VirtualMaster = ITrees - > IForestGetSpecID ( i ) ;
if ( ! AlreadyAddedSpec . Find ( VirtualMaster ) )
{
RenderableNodes . Emplace ( ForestNode , EMaxEntityType : : Geometry , FDatasmithMaxStaticMeshAttributes : : ExtractStaticMeshAttributes ( ForestInstance - > node ) ) ;
RenderableNodes . Last ( ) . Instancemode = EMaxExporterInstanceMode : : UnrealHISM ;
RenderableNodes . Last ( ) . bIsReadyToExport = true ;
RenderableNodes . Last ( ) . InstancesTransformPtr = MakeUnique < TArray < Matrix3 > > ( ) ;
AlreadyAddedSpec . Add ( VirtualMaster , & RenderableNodes . Last ( ) ) ;
RenderableNodes . Last ( ) . MeshIndex = AlreadyAddedSpec . Num ( ) ;
RenderableNodes . Last ( ) . CustomMeshNode = ForestInstance - > node ;
MaterialEnum ( ForestInstance - > node - > GetMtl ( ) , true ) ;
}
AlreadyAddedSpec [ VirtualMaster ] - > InstancesTransformPtr - > Emplace ( ForestInstance - > tm ) ;
}
}
}
ITrees - > IForestClearRenderNodes ( ) ;
ITrees - > IForestRenderEnd ( CurrentTime ) ;
}
void FDatasmithMaxSceneParser : : ParseRailcloneNode ( INode * RailCloneNode )
{
2021-09-08 16:42:26 -04:00
if ( RailCloneNode = = nullptr )
{
return ;
}
2019-10-04 13:11:45 -04:00
TimeValue CurrentTime = GetCOREInterface ( ) - > GetTime ( ) ;
IRCStaticInterface * RCStaticInterface = GetRCStaticInterface ( ) ;
if ( ! RCStaticInterface )
{
return ;
}
RCStaticInterface - > IRCRegisterEngine ( ) ;
IRCInterface * RCInterface = GetRCInterface ( RailCloneNode - > GetObjectRef ( ) ) ;
if ( ! RCInterface )
{
return ;
}
RCInterface - > IRCRenderBegin ( CurrentTime ) ;
int NumInstances ;
TRCInstance * RCInstance = ( TRCInstance * ) RCInterface - > IRCGetInstances ( NumInstances ) ;
if ( RCInstance & & NumInstances > 0 )
{
MaterialEnum ( RailCloneNode - > GetMtl ( ) , true ) ;
2021-09-08 16:42:26 -04:00
int32 NextMeshIndex = 0 ;
TMap < Mesh * , int32 > RenderableNodeIndicesMap ;
2019-10-04 13:11:45 -04:00
for ( int j = 0 ; j < NumInstances ; j + + , RCInstance + + )
{
if ( RCInstance & & RCInstance - > mesh )
{
2021-09-08 16:42:26 -04:00
if ( int32 * RenderableNodeIndexPtr = RenderableNodeIndicesMap . Find ( RCInstance - > mesh ) )
2019-10-04 13:11:45 -04:00
{
2021-09-08 16:42:26 -04:00
RenderableNodes [ * RenderableNodeIndexPtr ] . InstancesTransformPtr - > Emplace ( RCInstance - > tm ) ;
2019-10-04 13:11:45 -04:00
}
2021-09-08 16:42:26 -04:00
else
2019-10-04 13:11:45 -04:00
{
2021-09-08 16:42:26 -04:00
RenderableNodeIndicesMap . Add ( RCInstance - > mesh , RenderableNodes . Num ( ) ) ;
FMaxRendereableNode & RenderableNode = RenderableNodes . Emplace_GetRef ( RailCloneNode , EMaxEntityType : : Geometry ) ;
RenderableNode . Instancemode = EMaxExporterInstanceMode : : UnrealHISM ;
RenderableNode . bIsReadyToExport = true ;
RenderableNode . MaxMesh = MakeUnique < Mesh > ( * RCInstance - > mesh ) ;
RenderableNode . MeshIndex = NextMeshIndex + + ;
RenderableNode . InstancesTransformPtr = MakeUnique < TArray < Matrix3 > > ( ) ;
2021-10-27 15:14:40 -04:00
RenderableNode . InstancesTransformPtr - > Emplace ( RCInstance - > tm ) ;
2019-10-04 13:11:45 -04:00
}
}
}
}
RCInterface - > IRCClearInstances ( ) ;
RCInterface - > IRCClearMeshes ( ) ;
RCInterface - > IRCRenderEnd ( CurrentTime ) ;
}
# else // WITH_ITOO_INTERFACE
void FDatasmithMaxSceneParser : : ParseForestNode ( INode * ) { }
void FDatasmithMaxSceneParser : : ParseRailcloneNode ( INode * ) { }
# endif // WITH_ITOO_INTERFACE
# include "Windows/HideWindowsPlatformTypes.h"