BabylonExporter.GLTFExporter.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. using BabylonExport.Entities;
  2. using GLTFExport.Entities;
  3. using Newtonsoft.Json;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.IO;
  7. using System.Text;
  8. using Color = System.Drawing.Color;
  9. namespace Max2Babylon
  10. {
  11. internal partial class BabylonExporter
  12. {
  13. public void ExportGltf(BabylonScene babylonScene, string outputFile, bool generateBinary)
  14. {
  15. RaiseMessage("GLTFExporter | Export outputFile=" + outputFile + " generateBinary=" + generateBinary);
  16. RaiseMessage("GLTFExporter | Exportation started", Color.Blue);
  17. ReportProgressChanged(0);
  18. var gltf = new GLTF(Path.GetDirectoryName(outputFile));
  19. // Asset
  20. gltf.asset = new GLTFAsset
  21. {
  22. version = "2.0",
  23. generator = "Babylon2Gltf2017",
  24. copyright = "2017 (c) BabylonJS"
  25. // no minVersion
  26. };
  27. // Scene
  28. gltf.scene = 0;
  29. // Scenes
  30. GLTFScene scene = new GLTFScene();
  31. GLTFScene[] scenes = { scene };
  32. gltf.scenes = scenes;
  33. // Materials
  34. RaiseMessage("GLTFExporter | Exporting materials");
  35. ReportProgressChanged(10);
  36. var babylonMaterials = babylonScene.MaterialsList;
  37. babylonMaterials.ForEach((babylonMaterial) =>
  38. {
  39. ExportMaterial(babylonMaterial, gltf);
  40. CheckCancelled();
  41. });
  42. // TODO - Handle multimaterials
  43. RaiseMessage(string.Format("GLTFExporter | Total: {0}", gltf.MaterialsList.Count /*+ glTF.MultiMaterialsList.Count*/), Color.Gray, 1);
  44. // Nodes
  45. List<BabylonNode> babylonNodes = new List<BabylonNode>();
  46. babylonNodes.AddRange(babylonScene.meshes);
  47. babylonNodes.AddRange(babylonScene.lights);
  48. babylonNodes.AddRange(babylonScene.cameras);
  49. // Root nodes
  50. RaiseMessage("GLTFExporter | Exporting root nodes");
  51. List<BabylonNode> babylonRootNodes = babylonNodes.FindAll(node => node.parentId == null);
  52. var progressionStep = 80.0f / babylonRootNodes.Count;
  53. var progression = 20.0f;
  54. ReportProgressChanged((int)progression);
  55. babylonRootNodes.ForEach(babylonNode =>
  56. {
  57. exportNodeRec(babylonNode, gltf, babylonScene);
  58. progression += progressionStep;
  59. ReportProgressChanged((int)progression);
  60. CheckCancelled();
  61. });
  62. // Output
  63. RaiseMessage("GLTFExporter | Saving to output file");
  64. // Cast lists to arrays
  65. gltf.Prepare();
  66. var jsonSerializer = JsonSerializer.Create(new JsonSerializerSettings()); // Standard serializer, not the optimized one
  67. var sb = new StringBuilder();
  68. var sw = new StringWriter(sb, CultureInfo.InvariantCulture);
  69. using (var jsonWriter = new JsonTextWriter(sw))
  70. {
  71. jsonWriter.Formatting = Formatting.None;
  72. jsonSerializer.Serialize(jsonWriter, gltf);
  73. }
  74. string outputGltfFile = Path.ChangeExtension(outputFile, "gltf");
  75. File.WriteAllText(outputGltfFile, sb.ToString());
  76. // Binary
  77. if (generateBinary)
  78. {
  79. // TODO - Export glTF data to binary format .glb
  80. RaiseError("GLTFExporter | TODO - Generating binary files");
  81. }
  82. ReportProgressChanged(100);
  83. }
  84. private void exportNodeRec(BabylonNode babylonNode, GLTF gltf, BabylonScene babylonScene, GLTFNode gltfParentNode = null)
  85. {
  86. GLTFNode gltfNode = null;
  87. if (babylonNode.GetType() == typeof(BabylonMesh))
  88. {
  89. GLTFMesh gltfMesh = ExportMesh(babylonNode as BabylonMesh, gltf, gltfParentNode);
  90. if (gltfMesh != null)
  91. {
  92. gltfNode = gltfMesh.gltfNode;
  93. }
  94. }
  95. else if (babylonNode.GetType() == typeof(BabylonCamera))
  96. {
  97. // TODO - Export camera nodes
  98. RaiseError($"TODO - Export camera node named {babylonNode.name}", 1);
  99. }
  100. else if (babylonNode.GetType() == typeof(BabylonLight))
  101. {
  102. // TODO - Export light nodes as empty nodes (no lights in glTF 2.0 core)
  103. RaiseError($"TODO - Export light node named {babylonNode.name}", 1);
  104. RaiseWarning($"GLTFExporter.Node | Light named {babylonNode.name} has children but lights are not exported with glTF 2.0 core version. An empty node is used instead.", 1);
  105. }
  106. else
  107. {
  108. RaiseError($"Node named {babylonNode.name} as no exporter", 1);
  109. }
  110. CheckCancelled();
  111. // If parent is exported successfully...
  112. if (gltfNode != null)
  113. {
  114. // ...export its children
  115. List<BabylonNode> babylonDescendants = getDescendants(babylonNode, babylonScene);
  116. babylonDescendants.ForEach(descendant => exportNodeRec(descendant, gltf, babylonScene, gltfNode));
  117. }
  118. }
  119. private List<BabylonNode> getDescendants(BabylonNode babylonNode, BabylonScene babylonScene)
  120. {
  121. List<BabylonNode> babylonNodes = new List<BabylonNode>();
  122. babylonNodes.AddRange(babylonScene.meshes);
  123. babylonNodes.AddRange(babylonScene.lights);
  124. babylonNodes.AddRange(babylonScene.cameras);
  125. return babylonNodes.FindAll(node => node.parentId == babylonNode.id);
  126. }
  127. }
  128. }