123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Threading.Tasks;
- namespace BabylonFileConverter
- {
- public static class BinaryConverter
- {
- public enum DataType { Int32, Float };
- public static void Convert(string srcFilename, string dstPath, Action<string> onMessage, Action<string> onError)
- {
- try
- {
- if (!Directory.Exists(dstPath))
- Directory.CreateDirectory(dstPath);
- string srcPath = Path.GetDirectoryName(srcFilename);
- string dstFilename = Path.Combine(dstPath, Path.GetFileNameWithoutExtension(srcFilename) + ".binary.babylon");
- dynamic scene;
- // Loading
- onMessage("Loading " + srcFilename);
- using (var streamReader = new StreamReader(srcFilename))
- {
- using (var reader = new JsonTextReader(streamReader))
- {
- scene = JObject.Load(reader);
- }
- }
- // Marking scene
- string objName = scene.name;
- if (string.IsNullOrEmpty(objName))
- objName = Path.GetFileNameWithoutExtension(srcFilename);
- var atDot = objName.IndexOf(".incremental");
- if (atDot > 0)
- objName = objName.Substring(0, atDot);
- scene["autoClear"] = true;
- scene["useDelayedTextureLoading"] = true;
- var doNotDelayLoadingForGeometries = new List<string>();
- // Parsing meshes
- var meshes = (JArray)scene.meshes;
- foreach (dynamic mesh in meshes)
- {
- if (mesh.checkCollisions.Value) // Do not delay load collisions object
- {
- if (mesh.geometryId != null)
- doNotDelayLoadingForGeometries.Add(mesh.geometryId.Value);
- continue;
- }
- Extract(srcPath, dstPath, objName, mesh, true);
- }
- // Parsing vertexData
- var geometries = scene.geometries;
- if (geometries != null)
- {
- var vertexData = (JArray)geometries.vertexData;
- foreach (dynamic geometry in vertexData)
- {
- var id = geometry.id.Value;
- if (doNotDelayLoadingForGeometries.Any(g => g == id))
- continue;
- Extract(srcPath, dstPath, objName, geometry, false);
- }
- }
- // Saving
- onMessage("Saving " + dstFilename);
- string json = scene.ToString(Formatting.Indented);
- using (var writer = new StreamWriter(WebUtility.UrlDecode(dstFilename)))
- {
- writer.Write(json);
- }
- }
- catch (Exception ex)
- {
- onError(ex.Message);
- }
- }
- static void Extract(string srcPath, string dstPath, string objName, dynamic meshObj, bool isMesh)
- {
- string dstFilename = meshObj.delayLoadingFile;
- string dstExt = (isMesh ? ".babylonbinarymeshdata" : ".babylonbinarygeometrydata");
- if (!string.IsNullOrEmpty(dstFilename))
- {
- string filename = WebUtility.UrlDecode(Path.Combine(srcPath, (string)meshObj.delayLoadingFile));
- using (var streamReader = new StreamReader(filename))
- {
- using (var reader = new JsonTextReader(streamReader))
- {
- var meshData = JObject.Load(reader);
- meshObj.positions = meshData["positions"];
- meshObj.normals = meshData["normals"];
- meshObj.indices = meshData["indices"];
- meshObj.uvs = meshData["uvs"];
- meshObj.uvs2 = meshData["uvs2"];
- meshObj.colors = meshData["colors"];
- meshObj.matricesIndices = meshData["matricesIndices"];
- meshObj.matricesWeights = meshData["matricesWeights"];
- meshObj.subMeshes = meshData["subMeshes"];
- }
- }
- }
- if (meshObj.positions == null || meshObj.positions.Count == 0
- || meshObj.normals == null || meshObj.normals.Count == 0
- || meshObj.indices == null || meshObj.indices.Count == 0)
- return;
- ComputeBoundingBox(meshObj);
- string meshName = meshObj.name.ToString();
- meshName = meshName.Trim();
- if (meshName.Length > 40)
- meshName = meshName.Substring(0, 40);
- if (isMesh && !string.IsNullOrEmpty(meshName))
- dstFilename = objName + "." + meshName + "." + meshObj.id.ToString() + dstExt;
- else
- dstFilename = objName + meshObj.id.ToString() + dstExt;
- dstFilename = dstFilename.Replace("+", "_").Replace(" ", "_").Replace("/", "_").Replace("\\", "_").Replace(":", "_");
- meshObj.delayLoadingFile = WebUtility.UrlEncode(dstFilename);
- var binaryInfo = new JObject();
- using (var stream = File.Open(WebUtility.UrlDecode(Path.Combine(dstPath, dstFilename)), FileMode.Create))
- {
- var writer = new BinaryWriter(stream);
- if (meshObj.positions != null && meshObj.positions.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.positions.Count;
- attrData["stride"] = 3;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["positionsAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.positions.Count; x++)
- writer.Write((float)meshObj.positions[x]);
- meshObj.positions = null;
- }
- if (meshObj.colors != null && meshObj.colors.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.colors.Count;
- attrData["stride"] = 3;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["colorsAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.colors.Count; x++)
- writer.Write((float)meshObj.colors[x]);
- meshObj["hasColors"] = true;
- meshObj.colors = null;
- }
- if (meshObj.normals != null && meshObj.normals.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.normals.Count;
- attrData["stride"] = 3;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["normalsAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.normals.Count; x++)
- writer.Write((float)meshObj.normals[x]);
- meshObj.normals = null;
- }
- if (meshObj.uvs != null && meshObj.uvs.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.uvs.Count;
- attrData["stride"] = 2;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["uvsAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.uvs.Count; x++)
- writer.Write((float)meshObj.uvs[x]);
- meshObj["hasUVs"] = true;
- meshObj.uvs = null;
- }
- if (meshObj.uvs2 != null && meshObj.uvs2.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.uvs2.Count;
- attrData["stride"] = 2;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["uvs2AttrDesc"] = attrData;
- for (int x = 0; x < meshObj.uvs2.Count; x++)
- writer.Write((float)meshObj.uvs2[x]);
- meshObj["hasUVs2"] = true;
- meshObj.uvs2 = null;
- }
- if (meshObj.indices != null && meshObj.indices.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.indices.Count;
- attrData["stride"] = 1;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Int32;
- binaryInfo["indicesAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.indices.Count; x++)
- writer.Write((int)meshObj.indices[x]);
- meshObj.indices = null;
- }
- if (meshObj.matricesIndices != null && meshObj.matricesIndices.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.matricesIndices.Count;
- attrData["stride"] = 1;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Int32;
- binaryInfo["matricesIndicesAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.matricesIndices.Count; x++)
- writer.Write((int)meshObj.matricesIndices[x]);
- meshObj["hasMatricesIndices"] = true;
- meshObj.matricesIndices = null;
- }
- if (meshObj.matricesWeights != null && meshObj.matricesWeights.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.matricesWeights.Count;
- attrData["stride"] = 2;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Float;
- binaryInfo["matricesWeightsAttrDesc"] = attrData;
- for (int x = 0; x < meshObj.matricesWeights.Count; x++)
- writer.Write((float)meshObj.matricesWeights[x]);
- meshObj["hasMatricesWeights"] = true;
- meshObj.matricesWeights = null;
- }
- if (isMesh && meshObj.subMeshes != null && meshObj.subMeshes.Count > 0)
- {
- var attrData = new JObject();
- attrData["count"] = meshObj.subMeshes.Count;
- attrData["stride"] = 5;
- attrData["offset"] = stream.Length;
- attrData["dataType"] = (int)DataType.Int32;
- binaryInfo["subMeshesAttrDesc"] = attrData;
- var smData = new int[5];
- for (int x = 0; x < meshObj.subMeshes.Count; x++)
- {
- smData[0] = meshObj.subMeshes[x].materialIndex;
- smData[1] = meshObj.subMeshes[x].verticesStart;
- smData[2] = meshObj.subMeshes[x].verticesCount;
- smData[3] = meshObj.subMeshes[x].indexStart;
- smData[4] = meshObj.subMeshes[x].indexCount;
- for (int y = 0; y < smData.Length; y++)
- writer.Write(smData[y]);
- }
- meshObj.subMeshes = null;
- }
- }
- meshObj["_binaryInfo"] = binaryInfo;
- }
- static void ComputeBoundingBox(dynamic meshOrGeometry)
- {
- // Compute bounding boxes
- var positions = ((JArray)meshOrGeometry.positions).Select(v => v.Value<float>()).ToArray();
- var minimum = new[] { float.MaxValue, float.MaxValue, float.MaxValue };
- var maximum = new[] { float.MinValue, float.MinValue, float.MinValue };
- for (var index = 0; index < positions.Length; index += 3)
- {
- var x = positions[index];
- var y = positions[index + 1];
- var z = positions[index + 2];
- if (x < minimum[0])
- {
- minimum[0] = x;
- }
- if (x > maximum[0])
- {
- maximum[0] = x;
- }
- if (y < minimum[1])
- {
- minimum[1] = y;
- }
- if (y > maximum[1])
- {
- maximum[1] = y;
- }
- if (z < minimum[2])
- {
- minimum[2] = z;
- }
- if (z > maximum[2])
- {
- maximum[2] = z;
- }
- }
- meshOrGeometry["boundingBoxMinimum"] = new JArray(minimum);
- meshOrGeometry["boundingBoxMaximum"] = new JArray(maximum);
- }
- }
- }
|