@@ -120,9 +120,7 @@ private BabylonTexture ExportSpecularTexture(IIGameMaterial materialNode, float[
120120
121121 RaiseMessage ( "Multiply specular color and level textures" , 2 ) ;
122122
123- string nameText = null ;
124-
125- nameText = ( specularColorTexture != null ? Path . GetFileNameWithoutExtension ( specularColorTexture . Map . FullFilePath ) : TextureUtilities . ColorToStringName ( specularColor ) ) +
123+ string nameText = ( specularColorTexture != null ? Path . GetFileNameWithoutExtension ( specularColorTexture . Map . FullFilePath ) : TextureUtilities . ColorToStringName ( specularColor ) ) +
126124 Path . GetFileNameWithoutExtension ( specularLevelTexture . Map . FullFilePath ) + "_specularColor" ;
127125
128126 var textureID = texture . GetGuid ( ) . ToString ( ) ;
@@ -824,12 +822,12 @@ private BabylonTexture ExportEnvironmnentTexture(ITexmap texMap, BabylonScene ba
824822 // -------------------------
825823 // -- Export sub methods ---
826824 // -------------------------
827-
828- private ITexmap _getSpecialTexmap ( ITexmap texMap , out float amount )
825+ private ITexmap _getSpecialTexmap ( ITexmap texMap , out float amount , out IEnumerable < TextureOperation > operations )
829826 {
827+ operations = null ;
828+ amount = 0.0f ;
830829 if ( texMap == null )
831830 {
832- amount = 0.0f ;
833831 return null ;
834832 }
835833
@@ -853,24 +851,8 @@ private ITexmap _getSpecialTexmap(ITexmap texMap, out float amount)
853851 RaiseError ( $ "Only Normal Bump Texture in tangent space are supported.", 2 ) ;
854852 return null ;
855853 }
856- var flipR = block . GetInt ( 7 , 0 , 0 ) ; // Normal texture Red chanel Flip
857- if ( flipR != 0 )
858- {
859- RaiseError ( $ "Only Normal Bump Texture without R flip are supported.", 2 ) ;
860- return null ;
861- }
862- var flipG = block . GetInt ( 8 , 0 , 0 ) ; // Normal texture Green chanel Flip
863- if ( flipG != 0 )
864- {
865- RaiseError ( $ "Only Normal Bump Texture without G flip are supported.", 2 ) ;
866- return null ;
867- }
868- var swapRG = block . GetInt ( 9 , 0 , 0 ) ; // Normal texture swap R and G channels
869- if ( swapRG != 0 )
870- {
871- RaiseError ( $ "Only Normal Bump Texture without R and G swap are supported.", 2 ) ;
872- return null ;
873- }
854+
855+ operations = GetNormalBump3DSMaxOperations ( texMap , block ) ;
874856
875857 var bumpAmount = block . GetFloat ( 1 , 0 , 0 ) ; // Bump texture Mult Spin
876858 var bumpMap = block . GetTexmap ( 3 , 0 , 0 ) ; // Bump texture
@@ -885,11 +867,126 @@ private ITexmap _getSpecialTexmap(ITexmap texMap, out float amount)
885867 }
886868 }
887869
888- amount = 0.0f ;
889870 RaiseError ( $ "Texture type is not supported. Use a Bitmap or Normal Bump map instead.", 2 ) ;
890871 return null ;
891872 }
892873
874+ /// <summary>
875+ /// Create the list of operation to transform the NormalMap, according Max and Babylon attributes
876+ /// </summary>
877+ /// <param name="texMap"></param>
878+ /// <param name="block"></param>
879+ /// <returns></returns>
880+ private IEnumerable < TextureOperation > GetNormalBump3DSMaxOperations ( ITexmap texMap , IIParamBlock2 block )
881+ {
882+ var flipR = block . GetInt ( 7 , 0 , 0 ) ; // Normal texture Red chanel Flip
883+ var flipG = block . GetInt ( 8 , 0 , 0 ) ; // Normal texture Green chanel Flip
884+ var swapRG = block . GetInt ( 9 , 0 , 0 ) ; // Normal texture swap R and G channels
885+
886+ // try to retreive the custom Babylon Attributes
887+ IICustAttribContainer custAtt = texMap . CustAttribContainer ;
888+ if ( custAtt == null )
889+ {
890+ yield break ;
891+ }
892+ var n = custAtt . NumCustAttribs ;
893+ ICustAttrib att = null ;
894+ for ( int i = 0 ; i != n ; i ++ )
895+ {
896+ var tmp = custAtt . GetCustAttrib ( i ) ;
897+ if ( tmp . ClassName == MaterialCustomBabylonAttributeName )
898+ {
899+ att = tmp ;
900+ break ;
901+ }
902+ }
903+
904+ MaxNormalMapParameters parameters = new MaxNormalMapParameters ( ) ;
905+
906+ IIParamBlock2 customBlock = att ? . GetParamBlockByID ( 0 ) ;
907+ if ( customBlock != null )
908+ {
909+ parameters . useMaxTransforms = customBlock . GetInt ( 0 , 0 , 0 ) != 0 ;
910+ parameters . Y = ( NormalMapY ) customBlock . GetInt ( 1 , 0 , 0 ) ;
911+ parameters . Coordinate = ( MapCoordinate ) customBlock . GetInt ( 2 , 0 , 0 ) ;
912+ }
913+
914+ bool mustFlipR = parameters . useMaxTransforms && flipR != 0 ;
915+ bool mustSwapRG = parameters . useMaxTransforms && swapRG != 0 ;
916+
917+ // flip green G = 255-G (individual pixel values into the texture)
918+ bool mustFlipG = parameters . useMaxTransforms && flipG != 0 ;
919+ switch ( parameters . Y )
920+ {
921+ case NormalMapY . positiv :
922+ {
923+ // opengl norm
924+ if ( isBabylonExported )
925+ {
926+ // texture source is OpenGL and babylon is DirectX, so we may flip G.
927+ // May void the Max operation if selected.
928+ mustFlipG = ! mustFlipG ;
929+ }
930+ break ;
931+ }
932+ case NormalMapY . negativ :
933+ {
934+ // directx norm
935+ if ( isGltfExported )
936+ {
937+ // texture source is DirectX and Gltf is OpenGL, so we may flip G.
938+ // May void the Max operation if selected.
939+ mustFlipG = ! mustFlipG ;
940+ }
941+ break ;
942+ }
943+ }
944+
945+ if ( mustFlipR )
946+ {
947+ yield return new FlipChannel ( FlipChannel . ChannelRed ) ;
948+ }
949+ if ( mustFlipG )
950+ {
951+ yield return new FlipChannel ( FlipChannel . ChannelGreen ) ;
952+ }
953+ if ( mustSwapRG )
954+ {
955+ yield return new SwapChannel ( FlipChannel . ChannelRed , FlipChannel . ChannelGreen ) ;
956+ }
957+
958+ // Invert Y coordinate Y = 1-Y (physical row layout into the texture)
959+ bool mustInvertY = false ;
960+
961+ switch ( parameters . Coordinate )
962+ {
963+ case MapCoordinate . right :
964+ {
965+ // opengl norm
966+ if ( isBabylonExported )
967+ {
968+ // texture source is OpenGL and babylon is DirectX, so we may invert Y coordinate.
969+ mustInvertY = true ;
970+ }
971+ break ;
972+ }
973+ case MapCoordinate . left :
974+ {
975+ // directx norm
976+ if ( isGltfExported )
977+ {
978+ // texture source is DirectX and Gltf is OpenGL, so we may invert Y coordinate.
979+ mustInvertY = true ;
980+ }
981+ break ;
982+ }
983+ }
984+ if ( mustInvertY )
985+ {
986+ yield return new InvertY ( ) ;
987+ }
988+ }
989+
893990 private BabylonTexture ExportTexture ( ITexmap texMap , BabylonScene babylonScene , float amount = 1.0f , bool allowCube = false , bool forceAlpha = false )
894991 {
895992 if ( texMap == null )
@@ -900,9 +997,10 @@ private BabylonTexture ExportTexture(ITexmap texMap, BabylonScene babylonScene,
900997 if ( texture == null )
901998 {
902999 float specialAmount ;
903- var specialTexMap = _getSpecialTexmap ( texMap , out specialAmount ) ;
1000+ var specialTexMap = _getSpecialTexmap ( texMap , out specialAmount , out var functions ) ;
9041001 texture = _getBitmapTex ( specialTexMap , false ) ;
9051002 amount *= specialAmount ;
1003+ return ExportBitmapTexture ( texture , babylonScene , amount , allowCube , forceAlpha , functions ) ;
9061004 }
9071005
9081006 return ExportBitmapTexture ( texture , babylonScene , amount , allowCube , forceAlpha ) ;
@@ -914,7 +1012,7 @@ private BabylonTexture ExportDiffuseTexture(ITexmap texMap, BabylonScene babylon
9141012 return ExportBitmapTexture ( texture , babylonScene , amount , allowCube , forceAlpha ) ;
9151013 }
9161014
917- private BabylonTexture ExportBitmapTexture ( IBitmapTex texture , BabylonScene babylonScene , float amount = 1.0f , bool allowCube = false , bool forceAlpha = false )
1015+ private BabylonTexture ExportBitmapTexture ( IBitmapTex texture , BabylonScene babylonScene , float amount = 1.0f , bool allowCube = false , bool forceAlpha = false , IEnumerable < TextureOperation > transforms = null )
9181016 {
9191017 if ( texture == null )
9201018 {
@@ -944,10 +1042,14 @@ private BabylonTexture ExportBitmapTexture(IBitmapTex texture, BabylonScene baby
9441042 return textureMap [ textureID ] ;
9451043 }
9461044 else
947- {
1045+ {
1046+ TextureOperation [ ] operations = transforms != null ? transforms . ToArray ( ) : new TextureOperation [ ] { } ;
1047+ // combine transform to the destination name.
1048+ var operationsCodeStr = operations . Length != 0 ? $ "_{ operations . EncodeName ( ) } " : string . Empty ;
1049+
9481050 var babylonTexture = new BabylonTexture ( textureID )
9491051 {
950- name = Path . GetFileNameWithoutExtension ( texture . MapName ) + "." + validImageFormat
1052+ name = $ " { Path . GetFileNameWithoutExtension ( texture . MapName ) } { operationsCodeStr } . { validImageFormat } "
9511053 } ;
9521054 RaiseMessage ( $ "texture id = { babylonTexture . Id } ", 2 ) ;
9531055
@@ -984,13 +1086,17 @@ private BabylonTexture ExportBitmapTexture(IBitmapTex texture, BabylonScene baby
9841086 if ( isBabylonExported )
9851087 {
9861088 var destPath = Path . Combine ( babylonScene . OutputPath , babylonTexture . name ) ;
987- TextureUtilities . CopyTexture ( sourcePath , destPath , exportParameters . txtQuality , this ) ;
1089+ TextureUtilities . CopyTexture ( sourcePath , operations , destPath , exportParameters . txtQuality , this ) ;
9881090
9891091 // Is cube
9901092 _exportIsCube ( Path . Combine ( babylonScene . OutputPath , babylonTexture . name ) , babylonTexture , allowCube ) ;
9911093 }
9921094 else
9931095 {
1096+ if ( operations . Length != 0 )
1097+ {
1098+ babylonTexture . bitmap = TextureUtilities . GetBitmap ( sourcePath , operations , this ) ;
1099+ }
9941100 babylonTexture . isCube = false ;
9951101 }
9961102 babylonTexture . originalPath = sourcePath ;
0 commit comments