浏览代码

Fix babylon instanciation
Handle gltf instanciation
Split mesh and abstract mesh exportation

noalak 8 年之前
父节点
当前提交
4505b570e7

+ 3 - 0
Exporters/3ds Max/BabylonExport.Entities/BabylonAbstractMesh.cs

@@ -20,6 +20,9 @@ namespace BabylonExport.Entities
         [DataMember]
         public BabylonActions actions { get; set; }
 
+        // Identifier shared between a mesh and its instances
+        public int idGroupInstance;
+
         public BabylonAbstractMesh()
         {
             position = new[] { 0f, 0f, 0f };

+ 2 - 1
Exporters/3ds Max/GltfExport.Entities/GLTFMesh.cs

@@ -11,6 +11,7 @@ namespace GLTFExport.Entities
         [DataMember(EmitDefaultValue = false)]
         public float[] weights { get; set; }
 
-        public GLTFNode gltfNode;
+        // Identifier shared between a babylon mesh and its instances
+        public int idGroupInstance;
     }
 }

+ 64 - 0
Exporters/3ds Max/Max2Babylon/2017/Exporter/BabylonExporter.GLTFExporter.AbstractMesh.cs

@@ -0,0 +1,64 @@
+using BabylonExport.Entities;
+using GLTFExport.Entities;
+
+namespace Max2Babylon
+{
+    partial class BabylonExporter
+    {
+        private GLTFNode ExportAbstractMesh(BabylonAbstractMesh babylonAbstractMesh, GLTF gltf, GLTFNode gltfParentNode)
+        {
+            RaiseMessage("GLTFExporter.AbstractMesh | Export abstract mesh named: " + babylonAbstractMesh.name, 1);
+
+            // Node
+            var gltfNode = new GLTFNode();
+            gltfNode.name = babylonAbstractMesh.name;
+            gltfNode.index = gltf.NodesList.Count;
+            gltf.NodesList.Add(gltfNode);
+
+            // Hierarchy
+            if (gltfParentNode != null)
+            {
+                RaiseMessage("GLTFExporter.AbstractMesh | Add " + babylonAbstractMesh.name + " as child to " + gltfParentNode.name, 2);
+                gltfParentNode.ChildrenList.Add(gltfNode.index);
+            }
+            else
+            {
+                // It's a root node
+                // Only root nodes are listed in a gltf scene
+                RaiseMessage("GLTFExporter.AbstractMesh | Add " + babylonAbstractMesh.name + " as root node to scene", 2);
+                gltf.scenes[0].NodesList.Add(gltfNode.index);
+            }
+
+            // Transform
+            gltfNode.translation = babylonAbstractMesh.position;
+            // TODO - Choose between this method and the extra root node
+            // Switch from left to right handed coordinate system
+            //gltfNode.translation[0] *= -1;
+            if (babylonAbstractMesh.rotationQuaternion != null)
+            {
+                gltfNode.rotation = babylonAbstractMesh.rotationQuaternion;
+            }
+            else
+            {
+                // Convert rotation vector to quaternion
+                BabylonVector3 rotationVector3 = new BabylonVector3
+                {
+                    X = babylonAbstractMesh.rotation[0],
+                    Y = babylonAbstractMesh.rotation[1],
+                    Z = babylonAbstractMesh.rotation[2]
+                };
+                gltfNode.rotation = rotationVector3.toQuaternionGltf().ToArray();
+            }
+            gltfNode.scale = babylonAbstractMesh.scaling;
+
+            // Mesh
+            var gltfMesh = gltf.MeshesList.Find(_gltfMesh => _gltfMesh.idGroupInstance == babylonAbstractMesh.idGroupInstance);
+            if (gltfMesh != null)
+            {
+                gltfNode.mesh = gltfMesh.index;
+            }
+
+            return gltfNode;
+        }
+    }
+}

+ 4 - 53
Exporters/3ds Max/Max2Babylon/2017/Exporter/BabylonExporter.GLTFExporter.Mesh.cs

@@ -10,66 +10,18 @@ namespace Max2Babylon
 {
     partial class BabylonExporter
     {
-        private GLTFNode ExportMesh(BabylonMesh babylonMesh, GLTF gltf, GLTFNode gltfParentNode, BabylonScene babylonScene)
+        private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene babylonScene)
         {
             RaiseMessage("GLTFExporter.Mesh | Export mesh named: " + babylonMesh.name, 1);
 
             // --------------------------
-            // ---------- Node ----------
-            // --------------------------
-
-            RaiseMessage("GLTFExporter.Mesh | Node", 2);
-            // Node
-            var gltfNode = new GLTFNode();
-            gltfNode.name = babylonMesh.name;
-            gltfNode.index = gltf.NodesList.Count;
-            gltf.NodesList.Add(gltfNode);
-
-            // Hierarchy
-            if (gltfParentNode != null)
-            {
-                RaiseMessage("GLTFExporter.Mesh | Add " + babylonMesh.name + " as child to " + gltfParentNode.name, 3);
-                gltfParentNode.ChildrenList.Add(gltfNode.index);
-            }
-            else
-            {
-                // It's a root node
-                // Only root nodes are listed in a gltf scene
-                RaiseMessage("GLTFExporter.Mesh | Add " + babylonMesh.name + " as root node to scene", 3);
-                gltf.scenes[0].NodesList.Add(gltfNode.index);
-            }
-
-            // Transform
-            gltfNode.translation = babylonMesh.position;
-            // TODO - Choose between this method and the extra root node
-            // Switch from left to right handed coordinate system
-            //gltfNode.translation[0] *= -1;
-            if (babylonMesh.rotationQuaternion != null)
-            {
-                gltfNode.rotation = babylonMesh.rotationQuaternion;
-            }
-            else
-            {
-                // Convert rotation vector to quaternion
-                BabylonVector3 rotationVector3 = new BabylonVector3
-                {
-                    X = babylonMesh.rotation[0],
-                    Y = babylonMesh.rotation[1],
-                    Z = babylonMesh.rotation[2]
-                };
-                gltfNode.rotation = rotationVector3.toQuaternionGltf().ToArray();
-            }
-            gltfNode.scale = babylonMesh.scaling;
-
-
-            // --------------------------
             // --- Mesh from babylon ----
             // --------------------------
 
             if (babylonMesh.positions == null)
             {
                 RaiseMessage("GLTFExporter.Mesh | Mesh is a dummy", 2);
-                return gltfNode;
+                return null;
             }
 
             RaiseMessage("GLTFExporter.Mesh | Mesh from babylon", 2);
@@ -137,8 +89,7 @@ namespace Max2Babylon
             var gltfMesh = new GLTFMesh { name = babylonMesh.name };
             gltfMesh.index = gltf.MeshesList.Count;
             gltf.MeshesList.Add(gltfMesh);
-            gltfNode.mesh = gltfMesh.index;
-            gltfMesh.gltfNode = gltfNode;
+            gltfMesh.idGroupInstance = babylonMesh.idGroupInstance;
 
             // Buffer
             var buffer = new GLTFBuffer
@@ -477,7 +428,7 @@ namespace Max2Babylon
                 });
             }
 
-            return gltfNode;
+            return gltfMesh;
         }
 
         private IPoint2 createIPoint2(float[] array, int index)

+ 72 - 36
Exporters/3ds Max/Max2Babylon/2017/Exporter/BabylonExporter.GLTFExporter.cs

@@ -13,14 +13,22 @@ namespace Max2Babylon
     internal partial class BabylonExporter
     {
         List<BabylonMaterial> babylonMaterialsToExport;
-        GLTFNode gltfRootNode;
+
+        private List<BabylonNode> babylonNodes;
 
         public void ExportGltf(BabylonScene babylonScene, string outputFile, bool generateBinary)
         {
             RaiseMessage("GLTFExporter | Export outputFile=" + outputFile + " generateBinary=" + generateBinary);
             RaiseMessage("GLTFExporter | Exportation started", Color.Blue);
 
-            ReportProgressChanged(0);
+            float progressionStep;
+            var progression = 0.0f;
+            ReportProgressChanged((int)progression);
+
+            // Initialization
+            initBabylonNodes(babylonScene);
+            babylonMaterialsToExport = new List<BabylonMaterial>();
+
             var gltf = new GLTF(Path.GetDirectoryName(outputFile));
 
             // Asset
@@ -40,16 +48,23 @@ namespace Max2Babylon
             GLTFScene[] scenes = { scene };
             gltf.scenes = scenes;
 
-            // Nodes
-            List<BabylonNode> babylonNodes = getNodes(babylonScene);
+            // Meshes
+            RaiseMessage("GLTFExporter | Exporting meshes");
+            progression = 10.0f;
+            ReportProgressChanged((int)progression);
+            progressionStep = 40.0f / babylonScene.meshes.Length;
+            foreach (var babylonMesh in babylonScene.meshes)
+            {
+                ExportMesh(babylonMesh, gltf, babylonScene);
+                progression += progressionStep;
+                ReportProgressChanged((int)progression);
+                CheckCancelled();
+            }
 
             // Root nodes
             RaiseMessage("GLTFExporter | Exporting nodes");
             List<BabylonNode> babylonRootNodes = babylonNodes.FindAll(node => node.parentId == null);
-            var progressionStep = 80.0f / babylonRootNodes.Count;
-            var progression = 10.0f;
-            ReportProgressChanged((int)progression);
-            babylonMaterialsToExport = new List<BabylonMaterial>();
+            progressionStep = 40.0f / babylonRootNodes.Count;
             babylonRootNodes.ForEach(babylonNode =>
             {
                 exportNodeRec(babylonNode, gltf, babylonScene);
@@ -60,15 +75,17 @@ namespace Max2Babylon
 
             // TODO - Choose between this method and the reverse of X axis
             // Switch from left to right handed coordinate system
+            RaiseMessage("GLTFExporter | Exporting root node");
             var tmpNodesList = new List<int>(scene.NodesList);
             var rootNode = new BabylonMesh
             {
                 name = "root",
                 rotation = new float[] { 0, (float)Math.PI, 0 },
-                scaling = new float[] { 1, 1, -1 }
+                scaling = new float[] { 1, 1, -1 },
+                idGroupInstance = -1
             };
             scene.NodesList.Clear();
-            gltfRootNode = ExportMesh(rootNode as BabylonMesh, gltf, null, babylonScene);
+            GLTFNode gltfRootNode = ExportAbstractMesh(rootNode, gltf, null);
             gltfRootNode.ChildrenList.AddRange(tmpNodesList);
 
             // Materials
@@ -108,19 +125,56 @@ namespace Max2Babylon
             ReportProgressChanged(100);
         }
 
+        private List<BabylonNode> initBabylonNodes(BabylonScene babylonScene)
+        {
+            babylonNodes = new List<BabylonNode>();
+            if (babylonScene.meshes != null)
+            {
+                int idGroupInstance = 0;
+                foreach (var babylonMesh in babylonScene.meshes)
+                {
+                    var babylonAbstractMeshes = new List<BabylonAbstractMesh>();
+                    babylonAbstractMeshes.Add(babylonMesh);
+                    if (babylonMesh.instances != null)
+                    {
+                        babylonAbstractMeshes.AddRange(babylonMesh.instances);
+                    }
+
+                    // Add mesh and instances to node list
+                    babylonNodes.AddRange(babylonAbstractMeshes);
+
+                    // Tag mesh and instances with an identifier
+                    babylonAbstractMeshes.ForEach(babylonAbstractMesh => babylonAbstractMesh.idGroupInstance = idGroupInstance);
+
+                    idGroupInstance++;
+                }
+            }
+            if (babylonScene.lights != null)
+            {
+                babylonNodes.AddRange(babylonScene.lights);
+            }
+            if (babylonScene.cameras != null)
+            {
+                babylonNodes.AddRange(babylonScene.cameras);
+            }
+            return babylonNodes;
+        }
+
         private void exportNodeRec(BabylonNode babylonNode, GLTF gltf, BabylonScene babylonScene, GLTFNode gltfParentNode = null)
         {
-            GLTFNode gltfNode = null; 
-            if (babylonNode.GetType() == typeof(BabylonMesh))
+            GLTFNode gltfNode = null;
+            var type = babylonNode.GetType();
+            if (type == typeof(BabylonAbstractMesh) ||
+                type.IsSubclassOf(typeof(BabylonAbstractMesh)))
             {
-                gltfNode = ExportMesh(babylonNode as BabylonMesh, gltf, gltfParentNode, babylonScene);
+                gltfNode = ExportAbstractMesh(babylonNode as BabylonAbstractMesh, gltf, gltfParentNode);
             }
-            else if (babylonNode.GetType() == typeof(BabylonCamera))
+            else if (type == typeof(BabylonCamera))
             {
                 GLTFCamera gltfCamera = ExportCamera(babylonNode as BabylonCamera, gltf, gltfParentNode);
                 gltfNode = gltfCamera.gltfNode;
             }
-            else if (babylonNode.GetType() == typeof(BabylonLight))
+            else if (type == typeof(BabylonLight))
             {
                 if (isNodeRelevantToExport(babylonNode, babylonScene))
                 {
@@ -140,7 +194,7 @@ namespace Max2Babylon
 
             CheckCancelled();
 
-            // If parent is exported successfully...
+            // If node is exported successfully...
             if (gltfNode != null)
             {
                 // ...export its children
@@ -149,27 +203,8 @@ namespace Max2Babylon
             }
         }
 
-        private List<BabylonNode> getNodes(BabylonScene babylonScene)
-        {
-            List<BabylonNode> babylonNodes = new List<BabylonNode>();
-            if (babylonScene.meshes != null)
-            {
-                babylonNodes.AddRange(babylonScene.meshes);
-            }
-            if (babylonScene.lights != null)
-            {
-                babylonNodes.AddRange(babylonScene.lights);
-            }
-            if (babylonScene.cameras != null)
-            {
-                babylonNodes.AddRange(babylonScene.cameras);
-            }
-            return babylonNodes;
-        }
-
         private List<BabylonNode> getDescendants(BabylonNode babylonNode, BabylonScene babylonScene)
         {
-            List<BabylonNode> babylonNodes = getNodes(babylonScene);
             return babylonNodes.FindAll(node => node.parentId == babylonNode.id);
         }
 
@@ -179,7 +214,8 @@ namespace Max2Babylon
         private bool isNodeRelevantToExport(BabylonNode babylonNode, BabylonScene babylonScene)
         {
             var type = babylonNode.GetType();
-            if (type == typeof(BabylonMesh) ||
+            if (type == typeof(BabylonAbstractMesh) ||
+                type.IsSubclassOf(typeof(BabylonAbstractMesh)) ||
                 type == typeof(BabylonCamera))
             {
                 return true;

+ 1 - 0
Exporters/3ds Max/Max2Babylon/2017/Max2Babylon2017.csproj

@@ -194,6 +194,7 @@
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.Light.cs" />
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.Material.cs" />
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.Camera.cs" />
+    <Compile Include="Exporter\BabylonExporter.GLTFExporter.AbstractMesh.cs" />
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.Texture.cs" />
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.Mesh.cs" />
     <Compile Include="Exporter\BabylonExporter.GLTFExporter.cs" />

+ 5 - 1
Exporters/3ds Max/Max2Babylon/Exporter/BabylonExporter.Mesh.cs

@@ -67,7 +67,9 @@ namespace Max2Babylon
 
                 // Check if this mesh has already been exported
                 BabylonMesh babylonMasterMesh = null;
-                for (var index = 0; index < tabs.Count; index++)
+                var index = 0;
+                while (babylonMasterMesh == null &&
+                       index < tabs.Count)
                 {
 #if MAX2017
                     var indexer = index;
@@ -82,6 +84,8 @@ namespace Max2Babylon
                                // Mesh is not a dummy
                                _babylonMesh.isDummy == false;
                     });
+
+                    index++;
                 }
 
                 if (babylonMasterMesh != null)