Преглед изворни кода

Converting MAX2Babylon to the IGame* interfaces
Fixed skeleton / bones animation export for dude.

Simon Ferquel пре 10 година
родитељ
комит
fd8537f6eb

+ 3 - 0
.gitignore

@@ -113,3 +113,6 @@ UpgradeLog*.XML
 .settings/
 .pydevproject
 
+/Exporters/3ds Max/Max2Babylon.sln.ide
+/Exporters/3ds Max/Max2Babylon.sln.ide
+/Exporters/ExportToBabylon.sln.ide

+ 14 - 1
Exporters/3ds Max/BabylonExport.Entities/BabylonExport.Entities.csproj

@@ -16,6 +16,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <TargetFrameworkProfile />
+    <NuGetPackageImportStamp>a3421fc4</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -36,11 +37,13 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="SharpDX">
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -68,7 +71,17 @@
     <Compile Include="BabylonTexture.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 4 - 0
Exporters/3ds Max/BabylonExport.Entities/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="SharpDX" version="2.6.3" targetFramework="net40" />
+</packages>

+ 14 - 3
Exporters/3ds Max/Max2Babylon/2015/Max2Babylon2015.csproj

@@ -17,6 +17,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <NuGetPackageImportStamp>847376a2</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -46,16 +47,17 @@
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\..\packages\Newtonsoft.Json.6.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <HintPath>..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -217,8 +219,17 @@
       <Name>BabylonExport.Entities</Name>
     </ProjectReference>
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 5 - 0
Exporters/3ds Max/Max2Babylon/2015/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
+  <package id="SharpDX" version="2.6.3" targetFramework="net45" />
+</packages>

+ 5 - 0
Exporters/3ds Max/Max2Babylon/BabylonExportActionItem.cs

@@ -20,6 +20,11 @@ namespace Max2Babylon
 
         public void Close()
         {
+
+            if (form == null)
+            {
+                return;
+            }
             form.Dispose();
             form = null;
         }

+ 52 - 41
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Camera.cs

@@ -6,27 +6,34 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
-        private void ExportCamera(IINode cameraNode, BabylonScene babylonScene)
+        private void ExportCamera(IIGameNode cameraNode, BabylonScene babylonScene)
         {
-            if (cameraNode.GetBoolProperty("babylonjs_noexport"))
+
+            if (cameraNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
-
-            var maxCamera = (cameraNode.ObjectRef as ICameraObject);
+            var gameCamera = cameraNode.IGameObject.AsGameCamera();
+            var initialized = gameCamera.InitializeData;
             var babylonCamera = new BabylonCamera();
 
             RaiseMessage(cameraNode.Name, 1);
             babylonCamera.name = cameraNode.Name;
-            babylonCamera.id = cameraNode.GetGuid().ToString();
-            if (cameraNode.HasParent())
+            babylonCamera.id = cameraNode.MaxNode.GetGuid().ToString();
+            if (cameraNode.NodeParent != null)
             {
-                babylonCamera.parentId = cameraNode.ParentNode.GetGuid().ToString();
+                babylonCamera.parentId = cameraNode.NodeParent.MaxNode.GetGuid().ToString();
             }
 
-            babylonCamera.fov = Tools.ConvertFov(maxCamera.GetFOV(0, Tools.Forever));
-            babylonCamera.minZ = maxCamera.GetEnvRange(0, 0, Tools.Forever);
-            babylonCamera.maxZ = maxCamera.GetEnvRange(0, 1, Tools.Forever);
+            float fov = 0;
+            gameCamera.CameraFOV.GetPropertyValue(ref fov, 0, false);
+            babylonCamera.fov = fov;
+            float minZ = 0;
+            gameCamera.CameraNearClip.GetPropertyValue(ref minZ, 0, false);
+            babylonCamera.minZ = minZ;
+            float maxZ = 0;
+            gameCamera.CameraFarClip.GetPropertyValue(ref maxZ, 0, false);
+            babylonCamera.maxZ = maxZ;
 
             if (babylonCamera.minZ == 0.0f)
             {
@@ -34,53 +41,57 @@ namespace Max2Babylon
             }
 
             // Control
-            babylonCamera.speed = cameraNode.GetFloatProperty("babylonjs_speed", 1.0f);
-            babylonCamera.inertia = cameraNode.GetFloatProperty("babylonjs_inertia", 0.9f);
+            babylonCamera.speed = cameraNode.MaxNode.GetFloatProperty("babylonjs_speed", 1.0f);
+            babylonCamera.inertia = cameraNode.MaxNode.GetFloatProperty("babylonjs_inertia", 0.9f);
 
             // Collisions
-            babylonCamera.checkCollisions = cameraNode.GetBoolProperty("babylonjs_checkcollisions");
-            babylonCamera.applyGravity = cameraNode.GetBoolProperty("babylonjs_applygravity");
-            babylonCamera.ellipsoid = cameraNode.GetVector3Property("babylonjs_ellipsoid");
+            babylonCamera.checkCollisions = cameraNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
+            babylonCamera.applyGravity = cameraNode.MaxNode.GetBoolProperty("babylonjs_applygravity");
+            babylonCamera.ellipsoid = cameraNode.MaxNode.GetVector3Property("babylonjs_ellipsoid");
 
             // Position
-            var wm = cameraNode.GetWorldMatrix(0, cameraNode.HasParent());
-            var position = wm.Trans;
-            babylonCamera.position = position.ToArraySwitched();
+            var wm = cameraNode.GetObjectTM(0);
+            var position = wm.Translation;
+            babylonCamera.position = new float[] { position.X, position.Y, position.Z };
 
             // Target
-            var target = cameraNode.Target;
+            var target = gameCamera.CameraTarget;
             if (target != null)
             {
-                babylonCamera.lockedTargetId = target.GetGuid().ToString();
+                babylonCamera.lockedTargetId = target.MaxNode.GetGuid().ToString();
             }
             else
             {
-                var dir = wm.GetRow(2).MultiplyBy(-1);
-                babylonCamera.target = position.Add(dir).ToArraySwitched();
+                IPoint3 cameraTargetDist = Loader.Global.Point3.Create();
+                gameCamera.CameraTargetDist.GetPropertyValue(cameraTargetDist, 0);
+                var targetPos = position.Add(cameraTargetDist);
+                babylonCamera.target = new float[] { targetPos.X, targetPos.Y, targetPos.Z };
             }
 
-            // Animations
-            var animations = new List<BabylonAnimation>();
-            if (!ExportVector3Controller(cameraNode.TMController.PositionController, "position", animations))
-            {
-                ExportVector3Animation("position", animations, key =>
-                {
-                    var worldMatrix = cameraNode.GetWorldMatrix(key, cameraNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
-                });
-            }
+            // todo : handle animations
+            //// Animations
+            //var animations = new List<BabylonAnimation>();
+            //cameraNode.IGameControl.
+            //if (!ExportVector3Controller(cameraNode.TMController.PositionController, "position", animations))
+            //{
+            //    ExportVector3Animation("position", animations, key =>
+            //    {
+            //        var worldMatrix = cameraNode.GetWorldMatrix(key, cameraNode.HasParent());
+            //        return worldMatrix.Trans.ToArraySwitched();
+            //    });
+            //}
 
-            ExportFloatAnimation("fov", animations, key => new[] {Tools.ConvertFov(maxCamera.GetFOV(key, Tools.Forever))});
+            //ExportFloatAnimation("fov", animations, key => new[] {Tools.ConvertFov(maxCamera.GetFOV(key, Tools.Forever))});
 
-            babylonCamera.animations = animations.ToArray();
+            //babylonCamera.animations = animations.ToArray();
 
-            if (cameraNode.GetBoolProperty("babylonjs_autoanimate"))
-            {
-                babylonCamera.autoAnimate = true;
-                babylonCamera.autoAnimateFrom = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonCamera.autoAnimateTo = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_to");
-                babylonCamera.autoAnimateLoop = cameraNode.GetBoolProperty("babylonjs_autoanimateloop");
-            }
+            //if (cameraNode.GetBoolProperty("babylonjs_autoanimate"))
+            //{
+            //    babylonCamera.autoAnimate = true;
+            //    babylonCamera.autoAnimateFrom = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_from");
+            //    babylonCamera.autoAnimateTo = (int)cameraNode.GetFloatProperty("babylonjs_autoanimate_to");
+            //    babylonCamera.autoAnimateLoop = cameraNode.GetBoolProperty("babylonjs_autoanimateloop");
+            //}
 
             babylonScene.CamerasList.Add(babylonCamera);
         }

+ 74 - 62
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Light.cs

@@ -24,39 +24,44 @@ namespace Max2Babylon
             babylonScene.LightsList.Add(babylonLight);
         }
 
-        private void ExportLight(IINode lightNode, BabylonScene babylonScene)
+        private void ExportLight(IIGameNode lightNode, BabylonScene babylonScene)
         {
-            if (lightNode.GetBoolProperty("babylonjs_noexport"))
+            if (lightNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
 
-            var maxLight = (lightNode.ObjectRef as ILightObject);
+            var gameLight = lightNode.IGameObject.AsGameLight();
             var babylonLight = new BabylonLight();
 
             RaiseMessage(lightNode.Name, 1);
             babylonLight.name = lightNode.Name;
-            babylonLight.id = lightNode.GetGuid().ToString();
+            babylonLight.id = lightNode.MaxNode.GetGuid().ToString();
 
+            var initialized = gameLight.InitializeData;
+          
             // Type
-            var lightState = Loader.Global.LightState.Create();
-            maxLight.EvalLightState(0, Tools.Forever, lightState);
             var directionScale = -1;
 
-            switch (lightState.Type)
+            switch (gameLight.LightType)
             {
-                case LightType.OmniLgt:
+                case Autodesk.Max.IGameLight.LightType.Omni:
                     babylonLight.type = 0;
                     break;
-                case LightType.SpotLgt:
+                case Autodesk.Max.IGameLight.LightType.Fspot:
+                case Autodesk.Max.IGameLight.LightType.Tspot:
                     babylonLight.type = 2;
-                    babylonLight.angle = (float)(maxLight.GetFallsize(0, Tools.Forever) * Math.PI / 180.0f);
+
+                    float fallOff = 0;
+                    gameLight.LightFallOff.GetPropertyValue(ref fallOff, 0, true);
+                    babylonLight.angle = (float)(fallOff* Math.PI / 180.0f);
                     babylonLight.exponent = 1;
                     break;
-                case LightType.DirectLgt:
+                case Autodesk.Max.IGameLight.LightType.Dir:
+                case Autodesk.Max.IGameLight.LightType.Tdir:
                     babylonLight.type = 1;
                     break;
-                case LightType.AmbientLgt:
+                case Autodesk.Max.IGameLight.LightType.Unknown:
                     babylonLight.type = 3;
                     babylonLight.groundColor = new float[] { 0, 0, 0 };
                     directionScale = 1;
@@ -64,11 +69,11 @@ namespace Max2Babylon
             }
 
             // Shadows
-            if (maxLight.ShadowMethod == 1)
+            if (gameLight.CastShadows)
             {
-                if (lightState.Type == LightType.DirectLgt)
+                if (babylonLight.type == 1)
                 {
-                    ExportShadowGenerator(lightNode, babylonScene);
+                    ExportShadowGenerator(lightNode.MaxNode, babylonScene);
                 }
                 else
                 {
@@ -77,28 +82,33 @@ namespace Max2Babylon
             }
 
             // Position
-            var wm = lightNode.GetWorldMatrix(0, false);
-            var position = wm.Trans;
-            babylonLight.position = position.ToArraySwitched();
+            var wm = lightNode.GetWorldTM(0);
+            var position = wm.Translation;
+            babylonLight.position = new float[] { position.X, position.Y, position.Z };
 
             // Direction
-            var target = lightNode.Target;
+            var target = gameLight.LightTarget;
             if (target != null)
             {
-                var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
-                var targetPosition = targetWm.Trans;
+                var targetWm = target.GetWorldTM(0);
+                var targetPosition = targetWm.Translation;
 
                 var direction = targetPosition.Subtract(position);
-                babylonLight.direction = direction.ToArraySwitched();
+                babylonLight.direction = new float[] { direction.X, direction.Y, direction.Z };
             }
             else
             {
-                var dir = wm.GetRow(2).MultiplyBy(directionScale);
-                babylonLight.direction = dir.ToArraySwitched();
+                IMatrix3 rotMatrix = Loader.Global.Matrix3.Create();
+                wm.Rotation.MakeMatrix(rotMatrix, true);
+                IPoint3 p = Loader.Global.Point3.Create(1, 0, 0);
+                var dir = rotMatrix.VectorTransform(p);
+                babylonLight.direction = new float[] { dir.X, dir.Y, dir.Z };
             }
 
-            // Exclusion
+
+            var maxLight = (lightNode.MaxNode.ObjectRef as ILightObject);
             var maxScene = Loader.Core.RootNode;
+            // Exclusion
             var inclusion = maxLight.ExclList.TestFlag(1); //NT_INCLUDE 
             var checkExclusionList = maxLight.ExclList.TestFlag(2); //NT_AFFECT_ILLUM
 
@@ -134,53 +144,55 @@ namespace Max2Babylon
             // Other fields
             babylonLight.intensity = maxLight.GetIntensity(0, Tools.Forever);
 
-            babylonLight.diffuse = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
-            babylonLight.specular = lightState.AffectDiffuse ? maxLight.GetRGBColor(0, Tools.Forever).ToArray() : new float[] { 0, 0, 0 };
+            IPoint3 lightColor = Loader.Global.Point3.Create(0,0,0);
+            gameLight.LightColor.GetPropertyValue(lightColor, 0);
+            babylonLight.diffuse =  new float[] { lightColor.X, lightColor.Y, lightColor.Z };
+            babylonLight.specular = new float[] { lightColor.X, lightColor.Y, lightColor.Z };
 
             if (maxLight.UseAtten)
             {
                 babylonLight.range = maxLight.GetAtten(0, 1, Tools.Forever);
             }
 
-            // Animations
-            var animations = new List<BabylonAnimation>();
-
-            if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations))
-            {
-                ExportVector3Animation("position", animations, key =>
-                {
-                    var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
-                });
-            }
-
-            ExportVector3Animation("direction", animations, key =>
-            {
-                var targetNode = lightNode.Target;
-                if (targetNode != null)
-                {
-                    var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
-                    var targetPosition = targetWm.Trans;
-
-                    var direction = targetPosition.Subtract(position);
-                    return direction.ToArraySwitched();
-                }
+            //// Animations
+            //var animations = new List<BabylonAnimation>();
+
+            //if (!ExportVector3Controller(lightNode.TMController.PositionController, "position", animations))
+            //{
+            //    ExportVector3Animation("position", animations, key =>
+            //    {
+            //        var worldMatrix = lightNode.GetWorldMatrix(key, lightNode.HasParent());
+            //        return worldMatrix.Trans.ToArraySwitched();
+            //    });
+            //}
+
+            //ExportVector3Animation("direction", animations, key =>
+            //{
+            //    var targetNode = lightNode.Target;
+            //    if (targetNode != null)
+            //    {
+            //        var targetWm = target.GetObjTMBeforeWSM(0, Tools.Forever);
+            //        var targetPosition = targetWm.Trans;
+
+            //        var direction = targetPosition.Subtract(position);
+            //        return direction.ToArraySwitched();
+            //    }
                 
-                var dir = wm.GetRow(2).MultiplyBy(directionScale);
-                return dir.ToArraySwitched();
-            });
+            //    var dir = wm.GetRow(2).MultiplyBy(directionScale);
+            //    return dir.ToArraySwitched();
+            //});
 
-            ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });
+            //ExportFloatAnimation("intensity", animations, key => new[] { maxLight.GetIntensity(key, Tools.Forever) });
 
-            babylonLight.animations = animations.ToArray();
+            //babylonLight.animations = animations.ToArray();
 
-            if (lightNode.GetBoolProperty("babylonjs_autoanimate"))
-            {
-                babylonLight.autoAnimate = true;
-                babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to");
-                babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop");
-            }
+            //if (lightNode.GetBoolProperty("babylonjs_autoanimate"))
+            //{
+            //    babylonLight.autoAnimate = true;
+            //    babylonLight.autoAnimateFrom = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_from");
+            //    babylonLight.autoAnimateTo = (int)lightNode.GetFloatProperty("babylonjs_autoanimate_to");
+            //    babylonLight.autoAnimateLoop = lightNode.GetBoolProperty("babylonjs_autoanimateloop");
+            //}
 
             babylonScene.LightsList.Add(babylonLight);
         }

+ 17 - 17
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Material.cs

@@ -7,28 +7,28 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
-        readonly List<IMtl> referencedMaterials = new List<IMtl>();
+        readonly List<IIGameMaterial> referencedMaterials = new List<IIGameMaterial>();
 
-        private void ExportMaterial(IMtl materialNode, BabylonScene babylonScene)
+        private void ExportMaterial(IIGameMaterial materialNode, BabylonScene babylonScene)
         {
-            var name = materialNode.Name;
-            var id = materialNode.GetGuid().ToString();
+            var name = materialNode.MaterialName;
+            var id = materialNode.MaxMaterial.GetGuid().ToString();
 
             RaiseMessage(name, 1);
 
-            if (materialNode.NumSubMtls > 0)
+            if (materialNode.SubMaterialCount > 0)
             {
                 var babylonMultimaterial = new BabylonMultiMaterial { name = name, id = id };
 
                 var guids = new List<string>();
 
-                for (var index = 0; index < materialNode.NumSubMtls; index++)
+                for (var index = 0; index < materialNode.SubMaterialCount; index++)
                 {
-                    var subMat = materialNode.GetSubMtl(index);
+                    var subMat = materialNode.GetSubMaterial(index);
 
                     if (subMat != null)
                     {
-                        guids.Add(subMat.GetGuid().ToString());
+                        guids.Add(subMat.MaxMaterial.GetGuid().ToString());
 
                         if (!referencedMaterials.Contains(subMat))
                         {
@@ -53,19 +53,19 @@ namespace Max2Babylon
             {
                 name = name,
                 id = id,
-                ambient = materialNode.GetAmbient(0, false).ToArray(),
-                diffuse = materialNode.GetDiffuse(0, false).ToArray(),
-                specular = materialNode.GetSpecular(0, false).Scale(materialNode.GetShinStr(0, false)),
-                specularPower = materialNode.GetShininess(0, false) * 256,
+                ambient = materialNode.MaxMaterial.GetAmbient(0, false).ToArray(),
+                diffuse = materialNode.MaxMaterial.GetDiffuse(0, false).ToArray(),
+                specular = materialNode.MaxMaterial.GetSpecular(0, false).Scale(materialNode.MaxMaterial.GetShinStr(0, false)),
+                specularPower = materialNode.MaxMaterial.GetShininess(0, false) * 256,
                 emissive =
-                    materialNode.GetSelfIllumColorOn(0, false)
-                        ? materialNode.GetSelfIllumColor(0, false).ToArray()
-                        : materialNode.GetDiffuse(0, false).Scale(materialNode.GetSelfIllum(0, false)),
-                alpha = 1.0f - materialNode.GetXParency(0, false)
+                    materialNode.MaxMaterial.GetSelfIllumColorOn(0, false)
+                        ? materialNode.MaxMaterial.GetSelfIllumColor(0, false).ToArray()
+                        : materialNode.MaxMaterial.GetDiffuse(0, false).Scale(materialNode.MaxMaterial.GetSelfIllum(0, false)),
+                alpha = 1.0f - materialNode.MaxMaterial.GetXParency(0, false)
             };
 
 
-            var stdMat = materialNode.GetParamBlock(0).Owner as IStdMat2;
+            var stdMat = materialNode.MaxMaterial.GetParamBlock(0).Owner as IStdMat2;
 
             if (stdMat != null)
             {

+ 331 - 231
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -10,156 +10,234 @@ namespace Max2Babylon
     partial class BabylonExporter
     {
         private int bonesCount;
-        private void ExportMesh(IINode meshNode, BabylonScene babylonScene)
+        private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene)
         {
-            if (meshNode.IsInstance())
+            if (meshNode.MaxNode.IsInstance())
             {
                 return;
             }
 
-            if (meshNode.GetBoolProperty("babylonjs_noexport"))
+            if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
             {
                 return;
             }
 
-            if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false))
+            if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false))
             {
                 return;
             }
 
+            var gameMesh = meshNode.IGameObject.AsGameMesh();
+            bool initialized = gameMesh.InitializeData;
+
             var babylonMesh = new BabylonMesh();
-            int vx1, vx2, vx3;
 
             babylonMesh.name = meshNode.Name;
-            babylonMesh.id = meshNode.GetGuid().ToString();
-            if (meshNode.HasParent())
+            babylonMesh.id = meshNode.MaxNode.GetGuid().ToString();
+            if (meshNode.NodeParent != null)
             {
-                babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString();
+                babylonMesh.parentId = meshNode.NodeParent.MaxNode.GetGuid().ToString();
             }
 
             // Misc.
-            babylonMesh.isVisible = meshNode.Renderable == 1;
-            babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable");
-            babylonMesh.receiveShadows = meshNode.RcvShadows == 1;
-            babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox");
-            babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
+            babylonMesh.isVisible = meshNode.MaxNode.Renderable == 1;
+            babylonMesh.pickable = meshNode.MaxNode.GetBoolProperty("babylonjs_checkpickable");
+            babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1;
+            babylonMesh.showBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showboundingbox");
+            babylonMesh.showSubMeshesBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
 
             // Collisions
-            babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions");
-
-            // Skin
-            var skin = GetSkinModifier(meshNode);
+            babylonMesh.checkCollisions = meshNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
 
-            if (skin != null)
+            bool isSkinned = gameMesh.IsObjectSkinned;
+            var skin = gameMesh.IGameSkin;
+            var unskinnedMesh = gameMesh;
+            if (isSkinned)
             {
+                unskinnedMesh = skin.InitialPose;
+                bonesCount = skin.TotalSkinBoneCount;
+                skins.Add(skin);
                 babylonMesh.skeletonId = skins.IndexOf(skin);
-                bonesCount = skin.NumBones;
             }
 
-            // Position / rotation / scaling
-            var wm = Tools.ExtractCoordinates(meshNode, babylonMesh, exportQuaternionsInsteadOfEulers);
 
-            if (wm.Parity)
-            {
-                vx1 = 2;
-                vx2 = 1;
-                vx3 = 0;
-            }
-            else
+            // Position / rotation / scaling
             {
-                vx1 = 0;
-                vx2 = 1;
-                vx3 = 2;
+                var localTM = meshNode.GetLocalTM(0);
+                //var worldTM = meshNode.GetWorldTM(0);
+                //var objTM = meshNode.GetObjectTM(0);
+                var meshTrans = localTM.Translation;
+                var meshRotation = localTM.Rotation;
+                var meshScale = localTM.Scaling;
+                babylonMesh.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
+                float rotx = 0, roty = 0, rotz = 0;
+                unsafe
+                {
+                    meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
+                }
+                babylonMesh.rotation = new float[] { rotx, roty, rotz };
+                //babylonMesh.rotationQuaternion = new float[] { meshRotation.X, meshRotation.Y, meshRotation.Z, meshRotation.W };
+                babylonMesh.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
             }
-
-            // Pivot
-            var pivotMatrix = Tools.Identity;
-            pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
-            Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
-            Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
-            babylonMesh.pivotMatrix = pivotMatrix.ToArray();
+            //// Pivot // something to do with GameMesh ?
+            //meshNode.GetObjectTM
+            //var pivotMatrix = Tools.Identity;
+            //pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
+            //Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
+            //Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
+            //babylonMesh.pivotMatrix = pivotMatrix.ToArray();
 
             // Mesh
-            var objectState = meshNode.EvalWorldState(0, false);
-            var triObject = objectState.Obj.GetMesh();
-            var mesh = triObject != null ? triObject.Mesh : null;
+            
 
             RaiseMessage(meshNode.Name, 1);
-
-            if (mesh != null)
+            
+            if (unskinnedMesh != null && unskinnedMesh.IGameType == Autodesk.Max.IGameObject.ObjectTypes.Mesh && unskinnedMesh.MaxMesh != null)
             {
-                mesh.BuildNormals();
-
-                if (mesh.NumFaces < 1)
+             
+                
+                if (unskinnedMesh.NumberOfFaces < 1)
                 {
                     RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2);
                 }
 
-                if (mesh.NumVerts < 3)
+                if (unskinnedMesh.NumberOfVerts < 3)
                 {
                     RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2);
                 }
 
-                if (mesh.NumVerts >= 65536)
+                if (unskinnedMesh.NumberOfVerts >= 65536)
                 {
                     RaiseWarning(string.Format("Mesh {0} has tmore than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", babylonMesh.name), 2);
                 }
 
                 // Material
-                var mtl = meshNode.Mtl;
+                var mtl = meshNode.NodeMaterial;
                 var multiMatsCount = 1;
 
                 if (mtl != null)
                 {
-                    babylonMesh.materialId = mtl.GetGuid().ToString();
+                    babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString();
 
                     if (!referencedMaterials.Contains(mtl))
                     {
                         referencedMaterials.Add(mtl);
                     }
 
-                    multiMatsCount = Math.Max(mtl.NumSubMtls, 1);
+                    multiMatsCount = Math.Max(mtl.SubMaterialCount, 1);
                 }
 
-                babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever);
+                babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever);
 
                 var vertices = new List<GlobalVertex>();
                 var indices = new List<int>();
-                var matIDs = new List<int>();
 
-                var hasUV = mesh.NumTVerts > 0;
-                var hasUV2 = mesh.GetNumMapVerts(2) > 0;
-                var hasColor = mesh.NumVertCol > 0;
-                var hasAlpha = mesh.GetNumMapVerts(-2) > 0;
+                var hasUV = unskinnedMesh.NumberOfTexVerts > 0;
+                var hasUV2 = unskinnedMesh.GetNumberOfMapVerts(2) > 0;
+                var hasColor = unskinnedMesh.NumberOfColorVerts > 0;
+                var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0;
 
-                var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices");
+                var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices");
 
-                // Skin
-                IISkinContextData skinContext = null;
-
-                if (skin != null)
-                {
-                    skinContext = skin.GetContextInterface(meshNode);
-                }
+               
 
                 // Compute normals
-                VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
+               // VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
                 List<GlobalVertex>[] verticesAlreadyExported = null;
 
                 if (optimizeVertices)
                 {
-                    verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts];
+                    verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts];
+                }
+
+                var subMeshes = new List<BabylonSubMesh>();
+                var indexStart = 0;
+
+                List<Guid> orderedSubMeshes = new List<Guid>();
+                for(int i=0;i< meshNode.NodeMaterial.SubMaterialCount; ++i)
+                {
+                    orderedSubMeshes.Add(meshNode.NodeMaterial.GetSubMaterial(i).MaxMaterial.GetGuid());
                 }
 
-                for (var face = 0; face < mesh.NumFaces; face++)
+                var materialIds = unskinnedMesh.ActiveMatIDs;
+                for(int i=0; i< materialIds.Count; ++i)
                 {
-                    indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
-                    matIDs.Add(mesh.Faces[face].MatID % multiMatsCount);
-                    CheckCancelled();
+                    var materialIndexer = new IntPtr(i);
+                    int materialId = materialIds[materialIndexer];
+                    Marshal.FreeHGlobal(materialIndexer);
+                    var materialFaces = unskinnedMesh.GetFacesFromMatID(materialId);
+
+                    var indexCount = 0;
+                    var minVertexIndex = int.MaxValue;
+                    var maxVertexIndex = int.MinValue;
+                    var subMesh = new BabylonSubMesh();
+                    subMesh.indexStart = indexStart;
+                    subMesh.materialIndex = materialId;
+
+
+
+                    for (int j= 0; j<materialFaces.Count; ++j)
+                    {
+                        var faceIndexer = new IntPtr(j);
+                        var face = materialFaces[faceIndexer];
+                      
+                        Marshal.FreeHGlobal(faceIndexer);
+                        var a = CreateGlobalVertex(unskinnedMesh, face, 0, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+                        var b = CreateGlobalVertex(unskinnedMesh, face, 2, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+                        var c = CreateGlobalVertex(unskinnedMesh, face, 1, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
+                        indices.Add(a);
+                        indices.Add(b);
+                        indices.Add(c);
+
+                        if (a < minVertexIndex)
+                        {
+                            minVertexIndex = a;
+                        }
+
+                        if (b < minVertexIndex)
+                        {
+                            minVertexIndex = b;
+                        }
+
+                        if (c < minVertexIndex)
+                        {
+                            minVertexIndex = c;
+                        }
+
+                        if (a > maxVertexIndex)
+                        {
+                            maxVertexIndex = a;
+                        }
+
+                        if (b > maxVertexIndex)
+                        {
+                            maxVertexIndex = b;
+                        }
+
+                        if (c > maxVertexIndex)
+                        {
+                            maxVertexIndex = c;
+                        }
+
+
+                        indexCount += 3;
+                        CheckCancelled();
+                    }
+                    if (indexCount != 0)
+                    {
+
+                        subMesh.indexCount = indexCount;
+                        subMesh.verticesStart = minVertexIndex;
+                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
+
+                        indexStart += indexCount;
+
+                        subMeshes.Add(subMesh);
+                    }
                 }
 
+
+              
                 if (vertices.Count >= 65536)
                 {
                     RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);
@@ -173,15 +251,15 @@ namespace Max2Babylon
                 RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);
 
                 // Buffers
-                babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray();
-                babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray();
+                babylonMesh.positions = vertices.SelectMany(v => new float[] { v.Position.X, v.Position.Y, v.Position.Z }).ToArray();
+                babylonMesh.normals = vertices.SelectMany(v => new float[] { v.Normal.X, v.Normal.Y, v.Normal.Z }).ToArray();
                 if (hasUV)
                 {
-                    babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray();
+                    babylonMesh.uvs = vertices.SelectMany(v => new float[] { v.UV.X, 1-v.UV.Y }).ToArray();
                 }
                 if (hasUV2)
                 {
-                    babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray();
+                    babylonMesh.uvs2 = vertices.SelectMany(v => new float[] { v.UV2.X, 1-v.UV2.Y }).ToArray();
                 }
 
                 if (skin != null)
@@ -196,89 +274,23 @@ namespace Max2Babylon
                     babylonMesh.hasVertexAlpha = hasAlpha;
                 }
 
-                // Submeshes
-                var sortedIndices = new List<int>();
-                var subMeshes = new List<BabylonSubMesh>();
-                var indexStart = 0;
-                for (var index = 0; index < multiMatsCount; index++)
-                {
-                    var subMesh = new BabylonSubMesh();
-                    var indexCount = 0;
-                    var minVertexIndex = int.MaxValue;
-                    var maxVertexIndex = int.MinValue;
-
-                    subMesh.indexStart = indexStart;
-                    subMesh.materialIndex = index;
-
-                    for (var face = 0; face < matIDs.Count; face++)
-                    {
-                        if (matIDs[face] == index)
-                        {
-                            var a = indices[3 * face];
-                            var b = indices[3 * face + 1];
-                            var c = indices[3 * face + 2];
-
-                            sortedIndices.Add(a);
-                            sortedIndices.Add(b);
-                            sortedIndices.Add(c);
-                            indexCount += 3;
-
-                            if (a < minVertexIndex)
-                            {
-                                minVertexIndex = a;
-                            }
-
-                            if (b < minVertexIndex)
-                            {
-                                minVertexIndex = b;
-                            }
-
-                            if (c < minVertexIndex)
-                            {
-                                minVertexIndex = c;
-                            }
-
-                            if (a > maxVertexIndex)
-                            {
-                                maxVertexIndex = a;
-                            }
-
-                            if (b > maxVertexIndex)
-                            {
-                                maxVertexIndex = b;
-                            }
-
-                            if (c > maxVertexIndex)
-                            {
-                                maxVertexIndex = c;
-                            }
-                        }
-                    }
-                    if (indexCount != 0)
-                    {
-
-                        subMesh.indexCount = indexCount;
-                        subMesh.verticesStart = minVertexIndex;
-                        subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
-
-                        indexStart += indexCount;
-
-                        subMeshes.Add(subMesh);
-                    }
-                    CheckCancelled();
-                }
+                
+               
                 babylonMesh.subMeshes = subMeshes.ToArray();
 
 
                 // Buffers - Indices
-                babylonMesh.indices = sortedIndices.ToArray();
+                babylonMesh.indices = indices.ToArray();
 
-                triObject.Dispose();
             }
 
+            // handle instances and animations
+
+
             // Instances
             var tabs = Loader.Global.NodeTab.Create();
-            Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode, tabs);
+            
+            Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs);
             var instances = new List<BabylonAbstractMesh>();
 
             for (var index = 0; index < tabs.Count; index++)
@@ -288,19 +300,38 @@ namespace Max2Babylon
 
                 Marshal.FreeHGlobal(indexer);
 
-                if (meshNode.GetGuid() == tab.GetGuid())
+                if (meshNode.MaxNode.GetGuid() == tab.GetGuid())
+                {
+                    continue;
+                }
+                var instanceGameNode = scene.GetIGameNode(tab);
+                if(instanceGameNode == null)
                 {
                     continue;
                 }
-
                 tab.MarkAsInstance();
 
-                var instance = new BabylonAbstractMesh {name = tab.Name};
-
-                Tools.ExtractCoordinates(tab, instance, exportQuaternionsInsteadOfEulers);
-                var instanceAnimations = new List<BabylonAnimation>();
-                GenerateCoordinatesAnimations(tab, instanceAnimations);
-                instance.animations = instanceAnimations.ToArray();
+                var instance = new BabylonAbstractMesh { name = tab.Name };
+                {
+                    
+                    var localTM = instanceGameNode.GetLocalTM(0);
+                    //var worldTM = meshNode.GetWorldTM(0);
+                    //var objTM = meshNode.GetObjectTM(0);
+                    var meshTrans = localTM.Translation;
+                    var meshRotation = localTM.Rotation;
+                    var meshScale = localTM.Scaling;
+                    instance.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
+                    float rotx = 0, roty = 0, rotz = 0;
+                    unsafe
+                    {
+                        meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
+                    }
+                    instance.rotation = new float[] { rotx, roty, rotz };
+                    instance.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
+                }
+                //var instanceAnimations = new List<BabylonAnimation>();
+                //GenerateCoordinatesAnimations(tab, instanceAnimations);
+                //instance.animations = instanceAnimations.ToArray();
 
                 instances.Add(instance);
             }
@@ -308,100 +339,169 @@ namespace Max2Babylon
             babylonMesh.instances = instances.ToArray();
 
             // Animations
-            var animations = new List<BabylonAnimation>();
-            GenerateCoordinatesAnimations(meshNode, animations);
-            
+            //var animations = new List<BabylonAnimation>();
+            //GenerateCoordinatesAnimations(meshNode, animations);
 
-            if (!ExportFloatController(meshNode.VisController, "visibility", animations))
-            {
-                ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
-            }
 
-            babylonMesh.animations = animations.ToArray();
+            //if (!ExportFloatController(meshNode.VisController, "visibility", animations))
+            //{
+            //    ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
+            //}
+
+            //babylonMesh.animations = animations.ToArray();
 
-            if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1))
+            if (meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimate", 1))
             {
                 babylonMesh.autoAnimate = true;
-                babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from");
-                babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
-                babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
+                babylonMesh.autoAnimateFrom = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
+                babylonMesh.autoAnimateTo = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
+                babylonMesh.autoAnimateLoop = meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
             }
 
             babylonScene.MeshesList.Add(babylonMesh);
         }
 
-        public static void GenerateCoordinatesAnimations(IINode meshNode, List<BabylonAnimation> animations)
-        {
-            if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
-            {
-                ExportVector3Animation("position", animations, key =>
-                {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
-                    return worldMatrix.Trans.ToArraySwitched();
-                });
-            }
-
-            if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
-            {
-                ExportQuaternionAnimation("rotationQuaternion", animations, key =>
-                {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
-
-                    var affineParts = Loader.Global.AffineParts.Create();
-                    Loader.Global.DecompAffine(worldMatrix, affineParts);
-
-                    return affineParts.Q.ToArray();
-                });
-            }
-
-            if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
-            {
-                ExportVector3Animation("scaling", animations, key =>
-                {
-                    var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
-
-                    var affineParts = Loader.Global.AffineParts.Create();
-                    Loader.Global.DecompAffine(worldMatrix, affineParts);
-
-                    return affineParts.K.ToArraySwitched();
-                });
-            }
-        }
-
-        int CreateGlobalVertex(IMesh mesh, int face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, VNormal[] vnorms, List<GlobalVertex>[] verticesAlreadyExported, IISkinContextData skinContextData)
+        //public static void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnimation> animations)
+        //{
+        //    var control = meshNode.IGameControl;
+        //    if (control.IsAnimated(IGameControlType.Tm))
+        //    {
+        //        // combined tm anim
+        //        ExportTMAnimation(control, animations);
+        //    }
+        //    else
+        //    {
+        //        if (control.IsAnimated(IGameControlType.Pos))
+        //        {
+        //            ExportPosAnimation(control, animations);
+        //        }
+        //    }
+        //    //if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
+        //    //{
+        //    //    ExportVector3Animation("position", animations, key =>
+        //    //    {
+        //    //        var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
+        //    //        return worldMatrix.Trans.ToArraySwitched();
+        //    //    });
+        //    //}
+
+        //    //if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
+        //    //{
+        //    //    ExportQuaternionAnimation("rotationQuaternion", animations, key =>
+        //    //    {
+        //    //        var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
+
+        //    //        var affineParts = Loader.Global.AffineParts.Create();
+        //    //        Loader.Global.DecompAffine(worldMatrix, affineParts);
+
+        //    //        return affineParts.Q.ToArray();
+        //    //    });
+        //    //}
+
+        //    //if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
+        //    //{
+        //    //    ExportVector3Animation("scaling", animations, key =>
+        //    //    {
+        //    //        var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
+
+        //    //        var affineParts = Loader.Global.AffineParts.Create();
+        //    //        Loader.Global.DecompAffine(worldMatrix, affineParts);
+
+        //    //        return affineParts.K.ToArraySwitched();
+        //    //    });
+        //    //}
+        //}
+
+        //private static void ExportPosAnimation(IIGameControl control, List<BabylonAnimation> animations)
+        //{
+        //    ITab<IIGameKey> keys = Loader.Global.Tab.Create<IIGameKey>();
+        //    if(control.GetLinearKeys(keys, IGameControlType.Pos))
+        //    {
+        //        if(keys.Count != 0)
+        //        {
+        //            // todo
+
+        //            return;
+        //        }
+        //    }
+
+        //    // full sampling
+        //    if(control.GetFullSampledKeys(keys, Loader.Global.FrameRate, IGameControlType.Pos, false))
+        //    {
+        //        if(keys.Count != 0)
+        //        {
+        //            List<BabylonAnimationKey> babKeys = new List<BabylonAnimationKey>();
+
+        //            for(int i = 0; i < keys.Count; ++i)
+        //            {
+        //                var keyIndexer = new IntPtr(i);
+        //                var key = keys[keyIndexer];
+        //                babKeys.Add(new BabylonAnimationKey {
+        //                frame = key.T /Ticks,
+        //                values = new float[] { key.SampleKey.Pval.X, key.SampleKey.Pval.Y, key.SampleKey.Pval.Z }
+        //                });
+        //            }
+
+        //            var babylonAnimation = new BabylonAnimation
+        //            {
+        //                dataType = BabylonAnimation.DataType.Vector3,
+        //                name = "position animation",
+        //                keys = babKeys.ToArray(),
+        //                framePerSecond = Loader.Global.FrameRate,
+        //                loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
+        //                property = "position",
+                       
+        //            };
+        //            animations.Add(babylonAnimation);
+        //        }
+        //    }
+        //}
+
+        //private static void ExportTMAnimation(IIGameControl control, List<BabylonAnimation> animations)
+        //{
+
+        //}
+
+        int CreateGlobalVertex(IIGameMesh mesh, IFaceEx face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha,  List<GlobalVertex>[] verticesAlreadyExported, IIGameSkin skin)
         {
-            var faceObject = mesh.Faces[face];
-            var vertexIndex = (int)faceObject.V[facePart];
-
+            var vertexIndex = (int)face.Vert[facePart];
+           
             var vertex = new GlobalVertex
             {
                 BaseIndex = vertexIndex,
-                Position = mesh.Verts[vertexIndex],
-                Normal = vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
+                Position = mesh.GetVertex(vertexIndex, true),
+                Normal = mesh.GetNormal((int)face.Norm[facePart], true) //vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
             };
 
             if (hasUV)
             {
-                var tvertexIndex = (int)mesh.TvFace[face].T[facePart];
-                vertex.UV = Loader.Global.Point2.Create(mesh.TVerts[tvertexIndex].X, mesh.TVerts[tvertexIndex].Y);
+                var tvertexIndex = (int)face.TexCoord[facePart];
+                vertex.UV = mesh.GetTexVertex(tvertexIndex);
             }
 
             if (hasUV2)
             {
-                var tvertexIndex = (int)mesh.MapFaces(2)[face].T[facePart];
-                vertex.UV2 = Loader.Global.Point2.Create(mesh.MapVerts(2)[tvertexIndex].X, mesh.MapVerts(2)[tvertexIndex].Y);
+                IPoint3 p = Loader.Global.Point3.Create();
+                var tvertexIndex = mesh.GetMapFaceIndex(2, face.MeshFaceIndex, p.GetNativeHandle());
+                vertex.UV2 = Loader.Global.Point2.Create(p.X, p.Y);
             }
 
             if (hasColor)
             {
-                var vertexColorIndex = (int)mesh.VcFace[face].T[facePart];
-                var vertexColor = mesh.VertCol[vertexColorIndex];
-                var alpha = hasAlpha ? mesh.MapVerts(-2)[vertexColorIndex].X : 1;
+                var vertexColorIndex = (int)face.Color[facePart];
+                var vertexColor = mesh.GetColorVertex(vertexColorIndex);
+                float alpha = 1;
+                if (hasAlpha)
+                {
+                    IPoint3 p = Loader.Global.Point3.Create();
+                    mesh.GetMapFaceIndex(-2, face.MeshFaceIndex, p.GetNativeHandle());
+                    alpha = p.X;
+                }
 
                 vertex.Color = new float[] { vertexColor.X, vertexColor.Y, vertexColor.Z, alpha};
             }
 
-            if (skinContextData != null)
+            if (skin != null)
             {
                 float weight0 = 0;
                 float weight1 = 0;
@@ -410,29 +510,29 @@ namespace Max2Babylon
                 int bone1 = bonesCount;
                 int bone2 = bonesCount;
                 int bone3 = bonesCount;
-                int nbBones = skinContextData.GetNumAssignedBones(vertexIndex);
+                int nbBones = skin.GetNumberOfBones(vertexIndex);
 
                 if (nbBones > 0)
                 {
-                    bone0 = skinContextData.GetAssignedBone(vertexIndex, 0);
-                    weight0 = skinContextData.GetBoneWeight(vertexIndex, 0);
+                    bone0 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 0),false);
+                    weight0 = skin.GetWeight(vertexIndex, 0);
                 }
 
                 if (nbBones > 1)
                 {
-                    bone1 = skinContextData.GetAssignedBone(vertexIndex, 1);
-                    weight1 = skinContextData.GetBoneWeight(vertexIndex, 1);
+                    bone1 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 1), false);
+                    weight1 = skin.GetWeight(vertexIndex, 1);
                 }
 
                 if (nbBones > 2)
                 {
-                    bone2 = skinContextData.GetAssignedBone(vertexIndex, 2);
-                    weight2 = skinContextData.GetBoneWeight(vertexIndex, 2);
+                    bone2 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 2), false);
+                    weight2 = skin.GetWeight(vertexIndex, 2);
                 }
 
                 if (nbBones > 3)
                 {
-                    bone3 = skinContextData.GetAssignedBone(vertexIndex, 3);
+                    bone3 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 3), false);
                 }
 
                 if (nbBones == 0)

+ 240 - 101
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Skeleton.cs

@@ -1,122 +1,157 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using Autodesk.Max;
 using BabylonExport.Entities;
 using SharpDX;
 
 namespace Max2Babylon
 {
+    internal class BonePoseInfo
+    {
+        public IGMatrix AbsoluteTransform { get; set; }
+        public IGMatrix LocalTransform { get; set; }
+    }
     partial class BabylonExporter
     {
-        readonly List<IISkin> skins = new List<IISkin>();
-
-        IISkin GetSkinModifier(IINode node)
+        readonly List<IIGameSkin> skins = new List<IIGameSkin>();
+
+        //IISkin GetSkinModifier(IINode node, out IModifier skinModifier)
+        //{
+        //    skinModifier = null;
+        //    var obj = node.ObjectRef;
+
+        //    if (obj.SuperClassID != SClass_ID.GenDerivob)
+        //    {
+        //        return null;
+        //    }
+
+        //    var derivedObject = obj as IIDerivedObject;
+
+        //    if (derivedObject == null)
+        //    {
+        //        return null;
+        //    }
+
+        //    for (var index = 0; index < derivedObject.NumModifiers; index++)
+        //    {
+        //        var modifier = derivedObject.GetModifier(index);
+
+        //        if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
+        //        {
+        //            var skin = modifier.GetInterface((InterfaceID)0x00010000) as IISkin;
+
+        //            if (!skins.Contains(skin))
+        //            {
+        //                skins.Add(skin);
+        //            }
+        //            skinModifier = modifier;
+        //            return skin;
+        //        }
+        //    }
+
+
+        //    return null;
+        //}
+
+
+        //float[] GetBoneBindPoseLocalMatrix(IISkin skin, IINode bone, bool hasParent)
+        //{
+        //    var matrix = Loader.Global.Matrix3.Create();
+        //    var result = skin.GetBoneInitTM(bone, matrix, false);
+        //    if (!hasParent)
+        //    {
+        //        return matrix.ToArray();
+        //    }
+        //    else
+        //    {
+        //        var parentInverse = Loader.Global.Matrix3.Create();
+
+        //        result = skin.GetBoneInitTM(bone.ParentNode, matrix, false);
+        //        parentInverse.Invert();
+        //        return matrix.Multiply(parentInverse).ToArray();
+        //    }
+
+        //}
+        //float[] GetBoneMatrixForFrame(IINode bone, int frame, bool hasParent)
+        //{
+        //    //            var nodeTM2 = bone.GetNodeTM(frame, Tools.Forever);
+        //    //            var parent = bone.ParentNode;
+
+        //    //            if (!hasParent)
+        //    //            {
+        //    //                parent = bone;
+        //    //            }
+        //    //            else
+        //    //            {
+        //    //                parent = bone.ParentNode;
+        //    //            }
+        //    //            var inverseParentTM = parent.GetNodeTM(frame, Tools.Forever);
+        //    //            inverseParentTM.Invert();
+        //    //            var localTransform = nodeTM2.Multiply(inverseParentTM);
+        //    //            var vLocalPos = localTransform.Trans;
+        //    //            var parts = Loader.Global.AffineParts.Create();
+        //    //            Loader.Global.DecompAffine(localTransform, parts);
+        //    //            IPoint3 eulerAngs = Loader.Global.Point3.Create();
+        //    //#if MAX2015
+        //    //            var eulerAngsPtr = eulerAngs.NativePointer;
+        //    //#else
+        //    //            var eulerAngsPtr = eulerAngs.Handle;
+        //    //#endif
+        //    //            //Loader.Global.QuatToEuler(parts.Q, eulerAngsPtr);
+
+        //    //            return ( Matrix.RotationQuaternion(new Quaternion(parts.Q.X, parts.Q.Y, parts.Q.Z, parts.Q.W))*Matrix.Translation(vLocalPos.X, vLocalPos.Z, vLocalPos.Y)).ToArray();
+        //    return Matrix.Identity.ToArray();
+        //}
+
+        private void ExportSkin(IIGameSkin skin, BabylonScene babylonScene)
         {
-            var obj = node.ObjectRef;
-
-            if (obj.SuperClassID != SClass_ID.GenDerivob)
-            {
-                return null;
-            }
+            var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
+            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
 
-            var derivedObject = obj as IIDerivedObject;
+            RaiseMessage(babylonSkeleton.name, 1);
+            IGMatrix skinInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+            skin.GetInitSkinTM(skinInitMatrix);
 
-            if (derivedObject == null)
+            var bones = new List<BabylonBone>();
+            var gameBones = new List<IIGameNode>();
+            var boneIds = new List<int>();
+            var bindPoseInfos = new List<BonePoseInfo>();
+            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
             {
-                return null;
+                var gameBone = skin.GetIGameBone(index, false);
+                gameBones.Add(skin.GetIGameBone(index, false));
+                boneIds.Add(gameBone.NodeID);
+                bones.Add(new BabylonBone { index = index, name = gameBone.Name });
+                IGMatrix boneInitMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
+                skin.GetInitBoneTM(gameBone, boneInitMatrix);
+                bindPoseInfos.Add(new BonePoseInfo { AbsoluteTransform = boneInitMatrix });
             }
-
-            for (var index = 0; index < derivedObject.NumModifiers; index++)
+            // fix hierarchy an generate animation keys
+            for (var index = 0; index < skin.TotalSkinBoneCount; index++)
             {
-                var modifier = derivedObject.GetModifier(index);
-
-                if (modifier.ClassID.PartA == 9815843 && modifier.ClassID.PartB == 87654) // Skin
+                var gameBone = gameBones[index];
+                var parent = gameBone.NodeParent;
+                var babBone = bones[index];
+                if (parent != null)
                 {
-                    var skin = modifier.GetInterface((InterfaceID)0x00010000) as IISkin;
-
-                    if (!skins.Contains(skin))
-                    {
-                        skins.Add(skin);                        
-                    }
-
-                    return skin;
+                    babBone.parentBoneIndex = boneIds.IndexOf(parent.NodeID);
                 }
-            }
-
-
-            return null;
-        }
-
-        float[] GetBoneMatrix(IISkin skin, IINode bone, int t, bool hasParent)
-        {
-            var maxMatrix = bone.GetWorldMatrix(t, hasParent);
-
-            //var initialMatrix = Loader.Global.Matrix3.Create();
-            //skin.GetBoneInitTM(bone, initialMatrix, false);
-
-            //initialMatrix.Invert();
-
-            //maxMatrix = maxMatrix.MultiplyBy(initialMatrix);
-
-            //if (!hasParent)
-            //{
-            //    initialMatrix = Loader.Global.Matrix3.Create();
-            //    skin.GetSkinInitTM(bone, initialMatrix, false);
-
-            //    initialMatrix.Invert();
-
-            //    maxMatrix = maxMatrix.MultiplyBy(initialMatrix);
-            //}
-
-            maxMatrix.NoScale();
-
-            var trans = maxMatrix.Trans;
-
-            var parts = Loader.Global.AffineParts.Create();
-            Loader.Global.DecompAffine(maxMatrix, parts);
-
-            var rotationQuaternion = new Quaternion(parts.Q.X, parts.Q.Z, parts.Q.Y, parts.Q.W);
-
-            var matrix = Matrix.RotationQuaternion(rotationQuaternion) * Matrix.Translation(trans.X, trans.Z, trans.Y);
-
-            return matrix.ToArray();
-        }
-
-        private void ExportSkin(IISkin skin, BabylonScene babylonScene)
-        {
-            var babylonSkeleton = new BabylonSkeleton {id = skins.IndexOf(skin)};
-            babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
-
-            RaiseMessage(babylonSkeleton.name, 1);
-
-            var bones = new List<BabylonBone>();
-
-            for (var index = 0; index < skin.NumBones; index++)
-            {
-                var bone = new BabylonBone {name = skin.GetBoneName(index), index = index};
-
-                var maxBone = skin.GetBone(index);
-                var parentNode = maxBone.ParentNode;
-
-                if (parentNode != null)
+                if(babBone.parentBoneIndex == -1)
                 {
-                    for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
-                    {
-                        if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
-                        {
-                            bone.parentBoneIndex = recurseIndex;
-                            break;
-                        }
-                    }
+                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply( skinInitMatrix.Inverse);
+                }
+                else
+                {
+                    var parentBindPoseInfos = bindPoseInfos[babBone.parentBoneIndex];
+                    bindPoseInfos[index].LocalTransform = bindPoseInfos[index].AbsoluteTransform.Multiply(parentBindPoseInfos.AbsoluteTransform.Inverse);
                 }
-                var hasParent = bone.parentBoneIndex != -1;
-                bone.matrix = GetBoneMatrix(skin, maxBone, 0, hasParent);
+                babBone.matrix = bindPoseInfos[index].LocalTransform.ToArray();
 
-                // Animation
                 var babylonAnimation = new BabylonAnimation
                 {
-                    name = bone.name + "Animation", 
-                    property = "_matrix", 
-                    dataType = BabylonAnimation.DataType.Matrix, 
+                    name = gameBone.Name + "Animation",
+                    property = "_matrix",
+                    dataType = BabylonAnimation.DataType.Matrix,
                     loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
                     framePerSecond = Loader.Global.FrameRate
                 };
@@ -128,7 +163,7 @@ namespace Max2Babylon
                 var keys = new List<BabylonAnimationKey>();
                 for (var key = start; key <= end; key += Ticks)
                 {
-                    var current = GetBoneMatrix(skin, maxBone, key, hasParent);
+                    var current = gameBone.GetLocalTM(key).ToArray();
 
                     if (key == start || key == end || !(previous.IsEqualTo(current)))
                     {
@@ -143,14 +178,118 @@ namespace Max2Babylon
                 }
 
                 babylonAnimation.keys = keys.ToArray();
-                bone.animation = babylonAnimation;
+                babBone.animation = babylonAnimation;
 
-                bones.Add(bone);
             }
 
+            //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);
+
             babylonSkeleton.bones = bones.ToArray();
 
             babylonScene.SkeletonsList.Add(babylonSkeleton);
         }
+
+        //private void ExportSkin(IISkin skin, BabylonScene babylonScene)
+        //{
+
+        //    var babylonSkeleton = new BabylonSkeleton { id = skins.IndexOf(skin) };
+        //    babylonSkeleton.name = "skeleton #" + babylonSkeleton.id;
+
+        //    RaiseMessage(babylonSkeleton.name, 1);
+
+        //    var bones = new List<BabylonBone>();
+
+        //    for (var index = 0; index < skin.NumBones; index++)
+        //    {
+        //        var bone = new BabylonBone { name = skin.GetBoneName(index), index = index };
+
+        //        var maxBone = skin.GetBone(index);
+        //        var parentNode = maxBone.ParentNode;
+
+        //        if (parentNode != null)
+        //        {
+        //            for (var recurseIndex = 0; recurseIndex < index; recurseIndex++)
+        //            {
+        //                if (skin.GetBone(recurseIndex).GetGuid() == parentNode.GetGuid())
+        //                {
+        //                    bone.parentBoneIndex = recurseIndex;
+        //                    break;
+        //                }
+        //            }
+        //        }
+        //        var hasParent = bone.parentBoneIndex != -1;
+        //        var currentBoneNeutralMatrix = GetBoneBindPoseLocalMatrix(skin, maxBone, hasParent);
+        //        bone.matrix = currentBoneNeutralMatrix;
+
+        //        // Animation
+        //        var babylonAnimation = new BabylonAnimation
+        //        {
+        //            name = bone.name + "Animation",
+        //            property = "_matrix",
+        //            dataType = BabylonAnimation.DataType.Matrix,
+        //            loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
+        //            framePerSecond = Loader.Global.FrameRate
+        //        };
+
+        //        var start = Loader.Core.AnimRange.Start;
+        //        var end = Loader.Core.AnimRange.End;
+
+        //        float[] previous = null;
+        //        var keys = new List<BabylonAnimationKey>();
+        //        for (var key = start; key <= end; key += Ticks)
+        //        {
+        //            var current = GetBoneMatrixForFrame(maxBone, key, hasParent);
+
+        //            if (key == start || key == end || !(previous.IsEqualTo(current)))
+        //            {
+        //                keys.Add(new BabylonAnimationKey
+        //                {
+        //                    frame = key / Ticks,
+        //                    values = current
+        //                });
+        //            }
+
+        //            previous = current;
+        //        }
+
+        //        babylonAnimation.keys = keys.ToArray();
+        //        bone.animation = babylonAnimation;
+
+        //        bones.Add(bone);
+        //    }
+        //    //FixupHierarchy(Loader.Core.RootNode, skin.GetBone(0), bones);
+
+        //    babylonSkeleton.bones = bones.ToArray();
+
+        //    babylonScene.SkeletonsList.Add(babylonSkeleton);
+        //}
+
+        //private void FixupHierarchy(IINode sceneRoot, IINode skeletonRoot, List<BabylonBone> bones)
+        //{
+        //    var skeletonTransforms = new NodeTransforms(skeletonRoot, 0);
+        //    var sceneRootTransforms = new NodeTransforms(sceneRoot, 0);
+        //    var skelAbs = skeletonTransforms.AbsoluteTransform;
+        //    var invSceneAbs = sceneRootTransforms.AbsoluteTransform;
+        //    invSceneAbs.Invert();
+        //    var skelAbsInvSceneAbs = skelAbs.Multiply(invSceneAbs);
+        //    var invSkelLocalTransform = skeletonTransforms.LocalTransform;
+        //    invSkelLocalTransform.Invert();
+        //    var skelAbsInvSceneAbsXinvSkelLocalTransform = skelAbsInvSceneAbs.Multiply(invSkelLocalTransform);
+        //    bones[0].matrix = skelAbsInvSceneAbs.ToArray();
+        //    var matskelAbsInvSceneAbsXinvSkelLocalTransform = new Matrix(skelAbsInvSceneAbsXinvSkelLocalTransform.ToArray());
+        //    foreach (var b in bones)
+        //    {
+        //        var oldTransform = new Matrix(b.matrix);
+        //        b.matrix = (oldTransform * matskelAbsInvSceneAbsXinvSkelLocalTransform).ToArray();
+        //        foreach(var frame in b.animation.keys)
+        //        {
+
+        //            var oldTransform2 = new Matrix(frame.values);
+        //            frame.values = (oldTransform2 * matskelAbsInvSceneAbsXinvSkelLocalTransform).ToArray();
+        //        }
+        //    }
+
+
+        //}
     }
 }

+ 33 - 29
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.cs

@@ -11,6 +11,7 @@ using Autodesk.Max;
 using BabylonExport.Entities;
 using Newtonsoft.Json;
 using Color = System.Drawing.Color;
+using System.Runtime.InteropServices;
 
 namespace Max2Babylon
 {
@@ -79,11 +80,18 @@ namespace Max2Babylon
 
         public async Task ExportAsync(string outputFile, bool generateManifest, bool onlySelected, Form callerForm)
         {
+            var gameConversionManger = Loader.Global.ConversionManager;
+            gameConversionManger.CoordSystem = Autodesk.Max.IGameConversionManager.CoordSystem.D3d;
+
+            var gameScene = Loader.Global.IGameInterface;
+            gameScene.InitialiseIGame(onlySelected);
+            gameScene.SetStaticFrame(0);
+
             IsCancelled = false;
             RaiseMessage("Exportation started", Color.Blue);
             ReportProgressChanged(0);
             var babylonScene = new BabylonScene(Path.GetDirectoryName(outputFile));
-            var maxScene = Loader.Core.RootNode;
+            var rawScene = Loader.Core.RootNode;
             alreadyExportedTextures.Clear();
 
             if (!Directory.Exists(babylonScene.OutputPath))
@@ -114,19 +122,19 @@ namespace Max2Babylon
             babylonScene.clearColor = Loader.Core.GetBackGround(0, Tools.Forever).ToArray();
             babylonScene.ambientColor = Loader.Core.GetAmbient(0, Tools.Forever).ToArray();
 
-            babylonScene.gravity = maxScene.GetVector3Property("babylonjs_gravity");
-            exportQuaternionsInsteadOfEulers = maxScene.GetBoolProperty("babylonjs_exportquaternions", 1);
+            babylonScene.gravity = rawScene.GetVector3Property("babylonjs_gravity");
+            exportQuaternionsInsteadOfEulers = rawScene.GetBoolProperty("babylonjs_exportquaternions", 1);
 
             // Cameras
             BabylonCamera mainCamera = null;
 
             RaiseMessage("Exporting cameras");
-            foreach (var cameraNode in maxScene.NodesListBySuperClass(SClass_ID.Camera))
+            var camerasTab = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Camera);
+            for(int ix = 0; ix < camerasTab.Count; ++ix)
             {
-                if (onlySelected && !cameraNode.Selected)
-                {
-                    continue;
-                }
+                var indexer = new IntPtr(ix);
+                var cameraNode = camerasTab[indexer];
+                Marshal.FreeHGlobal(indexer);
                 ExportCamera(cameraNode, babylonScene);
 
                 if (mainCamera == null && babylonScene.CamerasList.Count > 0)
@@ -137,6 +145,7 @@ namespace Max2Babylon
                 }
             }
 
+
             if (mainCamera == null)
             {
                 RaiseWarning("No camera defined", 1);
@@ -165,8 +174,8 @@ namespace Max2Babylon
 
                         if (mainCamera != null)
                         {
-                            babylonScene.fogStart = mainCamera.minZ*fog.GetNear(0);
-                            babylonScene.fogEnd = mainCamera.maxZ*fog.GetFar(0);
+                            babylonScene.fogStart = mainCamera.minZ * fog.GetNear(0);
+                            babylonScene.fogEnd = mainCamera.maxZ * fog.GetFar(0);
                         }
                     }
                 }
@@ -175,26 +184,22 @@ namespace Max2Babylon
             // Meshes
             ReportProgressChanged(10);
             RaiseMessage("Exporting meshes");
-            var meshes = maxScene.NodesListBySuperClasses(new[] { SClass_ID.Geomobject, SClass_ID.Helper });
-            var progressionStep = 80.0f / meshes.Count();
+            var meshes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Mesh);
+            var progressionStep = 80.0f / meshes.Count;
             var progression = 10.0f;
-            foreach (var meshNode in meshes)
+            for (int ix = 0; ix < meshes.Count; ++ix)
             {
-                if (onlySelected && !meshNode.Selected)
-                {
-                    continue;
-                }
+                var indexer = new IntPtr(ix);
+                var meshNode = meshes[indexer];
+                Marshal.FreeHGlobal(indexer);
+                ExportMesh(gameScene, meshNode, babylonScene);
 
-                Tools.PreparePipeline(meshNode, true);
-                ExportMesh(meshNode, babylonScene);
-                Tools.PreparePipeline(meshNode, false);
 
-                progression += progressionStep;
                 ReportProgressChanged((int)progression);
 
                 CheckCancelled();
             }
-            RaiseMessage(string.Format("Total: {0}", babylonScene.MeshesList.Count), Color.Gray, 1);
+
 
             // Materials
             RaiseMessage("Exporting materials");
@@ -208,15 +213,13 @@ namespace Max2Babylon
 
             // Lights
             RaiseMessage("Exporting lights");
-            foreach (var lightNode in maxScene.NodesListBySuperClass(SClass_ID.Light))
+            var lightNodes = gameScene.GetIGameNodeByType(Autodesk.Max.IGameObject.ObjectTypes.Light);
+            for(var i=0;i< lightNodes.Count; ++i)
             {
-                if (onlySelected && !lightNode.Selected)
-                {
-                    continue;
-                }
-                ExportLight(lightNode, babylonScene);
+                ExportLight(lightNodes[new IntPtr(i)], babylonScene);
                 CheckCancelled();
             }
+          
 
             if (babylonScene.LightsList.Count == 0)
             {
@@ -236,7 +239,6 @@ namespace Max2Babylon
                 foreach (var skin in skins)
                 {
                     ExportSkin(skin, babylonScene);
-                    skin.Dispose();
                 }
             }
 
@@ -267,5 +269,7 @@ namespace Max2Babylon
             watch.Stop();
             RaiseMessage(string.Format("Exportation done in {0:0.00}s", watch.ElapsedMilliseconds / 1000.0), Color.Blue);
         }
+
+        
     }
 }

+ 16 - 5
Exporters/3ds Max/Max2Babylon/Max2Babylon.csproj

@@ -17,6 +17,7 @@
     <SccAuxPath>SAK</SccAuxPath>
     <SccProvider>SAK</SccProvider>
     <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <NuGetPackageImportStamp>eeea6a2c</NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -44,18 +45,18 @@
       <HintPath>Refs\Autodesk.Max.dll</HintPath>
       <Private>False</Private>
     </Reference>
-    <Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
-      <SpecificVersion>False</SpecificVersion>
-      <HintPath>Refs\Newtonsoft.Json.dll</HintPath>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="SharpDX, Version=2.4.2.0, Culture=neutral, PublicKeyToken=627a3d6d1956f55a, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\BabylonExport.Core\Refs\SharpDX.dll</HintPath>
+      <HintPath>$(SharpDXPackageBinDir)\SharpDX.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -125,7 +126,7 @@
     <Compile Include="Forms\Vector3Control.Designer.cs">
       <DependentUpon>Vector3Control.cs</DependentUpon>
     </Compile>
-    <Compile Include="Tools\VNormal.cs" /> 
+    <Compile Include="Tools\VNormal.cs" />
     <Compile Include="Tools\WebServer.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -161,7 +162,17 @@
       <Name>BabylonExport.Entities</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\packages\SharpDX.2.6.3\build\SharpDX.targets" Condition="Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" />
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\packages\SharpDX.2.6.3\build\SharpDX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SharpDX.2.6.3\build\SharpDX.targets'))" />
+  </Target>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 92 - 2
Exporters/3ds Max/Max2Babylon/Tools/Tools.cs

@@ -7,11 +7,61 @@ using System.Windows.Forms;
 using Autodesk.Max;
 using BabylonExport.Entities;
 using SharpDX;
+using System.Reflection;
 
 namespace Max2Babylon
 {
     public static class Tools
     {
+        public static IntPtr GetNativeHandle(this INativeObject obj)
+        {
+#if MAX2015
+            return obj.NativePointer;
+#else
+            return obj.Handle;
+#endif
+
+        }
+        static Assembly GetWrappersAssembly()
+        {
+            return Assembly.Load("Autodesk.Max.Wrappers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
+        }
+        public static IIGameCamera AsGameCamera(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameCamera");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameCamera)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
+        public static IIGameMesh AsGameMesh(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameMesh");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameMesh)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
+        public static IIGameLight AsGameLight(this IIGameObject obj)
+        {
+            var type = GetWrappersAssembly().GetType("Autodesk.Max.Wrappers.IGameLight");
+            var constructor = type.GetConstructors()[0];
+            // var pointerType = GetWrappersAssembly().GetType("IGameCamera");
+            unsafe
+            {
+                var voidPtr = obj.GetNativeHandle().ToPointer();
+                return (IIGameLight)constructor.Invoke(new object[] { obj.GetNativeHandle(), false });
+            }
+        }
+
         public const float Epsilon = 0.001f;
 
         public static IPoint3 XAxis { get { return Loader.Global.Point3.Create(1, 0, 0); } }
@@ -27,6 +77,7 @@ namespace Max2Babylon
         public static IMatrix3 Identity { get { return Loader.Global.Matrix3.Create(XAxis, YAxis, ZAxis, Origin); } }
 
 
+
         public static Vector3 ToEulerAngles(this IQuat q)
         {
             // Store the Euler angles in radians
@@ -63,7 +114,23 @@ namespace Max2Babylon
 
             return pitchYawRoll;
         }
-
+        public static float[] ToArray(this IGMatrix gmat)
+        {
+            //float eulX =0,  eulY=0,  eulZ=0;
+            //unsafe
+            //{
+            //    gmat.Rotation.GetEuler( new IntPtr(&eulX), new IntPtr(&eulY), new IntPtr(&eulZ));
+            //}
+            //return (Matrix.Scaling(gmat.Scaling.X, gmat.Scaling.Y, gmat.Scaling.Z) * Matrix.RotationYawPitchRoll(eulY, eulX, eulZ) * Matrix.Translation(gmat.Translation.X, gmat.Translation.Y, gmat.Translation.Z)).ToArray();
+            var r0 = gmat.GetRow(0);
+            var r1 = gmat.GetRow(1);
+            var r2 = gmat.GetRow(2);
+            var r3 = gmat.GetRow(3);
+            return new float[] {r0.X, r0.Y, r0.Z, r0.W,
+            r1.X, r1.Y,r1.Z, r1.W,
+            r2.X, r2.Y,r2.Z, r2.W,
+            r3.X, r3.Y,r3.Z, r3.W,};
+        }
         public static void PreparePipeline(IINode node, bool deactivate)
         {
             var obj = node.ObjectRef;
@@ -145,6 +212,7 @@ namespace Max2Babylon
 
         public static float[] ToArray(this IMatrix3 value)
         {
+
             var row0 = value.GetRow(0).ToArraySwitched();
             var row1 = value.GetRow(1).ToArraySwitched();
             var row2 = value.GetRow(2).ToArraySwitched();
@@ -356,7 +424,29 @@ namespace Max2Babylon
 
             return obj.ConvertToType(0, triObjectClassId) as ITriObject;
         }
-
+        public static bool IsAlmostEqualTo(this float[] current, float[] other, float epsilon)
+        {
+            if (current == null && other == null)
+            {
+                return true;
+            }
+            if (current == null || other == null)
+            {
+                return false;
+            }
+            if (current.Length != other.Length)
+            {
+                return false;
+            }
+            for (var i = 0; i < current.Length; ++i)
+            {
+                if (Math.Abs(current[i] - other[i]) > epsilon)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
         public static bool IsAlmostEqualTo(this IPoint4 current, IPoint4 other, float epsilon)
         {
             if (Math.Abs(current.X - other.X) > epsilon)

+ 15 - 3
Exporters/3ds Max/Max2Babylon/Tools/WebServer.cs

@@ -84,7 +84,7 @@ namespace Max2Babylon
 
         public static string SceneFilename { get; set; }
         public static string SceneFolder { get; set; }
-
+        static Random r = new Random();
         static void Listen()
         {
             try
@@ -98,14 +98,26 @@ namespace Max2Babylon
                     context.Response.AddHeader("Cache-Control", "no-cache");
                     if (string.IsNullOrEmpty(url.LocalPath) || url.LocalPath == "/")
                     {
-                        var responseText = HtmlResponseText.Replace("###SCENE###", SceneFilename);
+
+                        var responseText = HtmlResponseText.Replace("###SCENE###", SceneFilename+"?once="+r.Next());
                         WriteResponse(context, responseText);
                     }
                     else
                     {
                         try
                         {
-                            var buffer = File.ReadAllBytes(Path.Combine(SceneFolder, HttpUtility.UrlDecode(url.PathAndQuery.Substring(1))));
+                            var path = Path.Combine(SceneFolder, HttpUtility.UrlDecode(url.PathAndQuery.Substring(1)));
+                            var questionMarkIndex = path.IndexOf("?");
+                            if (questionMarkIndex != -1)
+                            {
+                                path = path.Substring(0, questionMarkIndex);
+                            }
+                            var hashIndex = path.IndexOf("#");
+                            if (hashIndex != -1)
+                            {
+                                path = path.Substring(0, hashIndex);
+                            }
+                            var buffer = File.ReadAllBytes(path);
                             WriteResponse(context, buffer);
                         }
                         catch

+ 5 - 0
Exporters/3ds Max/Max2Babylon/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="6.0.6" targetFramework="net45" />
+  <package id="SharpDX" version="2.6.3" targetFramework="net45" />
+</packages>