private glTFLoader.Schema.Image GetImageFromBitmapText(Bitmap bitmap) { byte[] imageBytes = GetImageBytes(bitmap); var textureBuffer = new glTFLoader.Schema.Buffer(); textureBuffer.Uri = Constants.TextBufferHeader + Convert.ToBase64String(imageBytes); textureBuffer.ByteLength = imageBytes.Length; int textureBufferIdx = dummy.Buffers.AddAndReturnIndex(textureBuffer); // Create bufferviews var textureBufferView = new BufferView() { Buffer = textureBufferIdx, ByteOffset = 0, ByteLength = textureBuffer.ByteLength, }; int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView); return(new glTFLoader.Schema.Image() { BufferView = textureBufferViewIdx, MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png, }); }
private glTFLoader.Schema.Image GetImageFromFileText(string fileName) { byte[] imageBytes = GetImageBytesFromFile(fileName); var textureBuffer = new glTFLoader.Schema.Buffer() { Uri = Constants.TextBufferHeader + Convert.ToBase64String(imageBytes), ByteLength = imageBytes.Length, }; int textureBufferIdx = dummy.Buffers.AddAndReturnIndex(textureBuffer); var textureBufferView = new glTFLoader.Schema.BufferView() { Buffer = textureBufferIdx, ByteOffset = 0, ByteLength = textureBuffer.ByteLength, }; int textureBufferViewIdx = dummy.BufferViews.AddAndReturnIndex(textureBufferView); return(new glTFLoader.Schema.Image() { BufferView = textureBufferViewIdx, MimeType = glTFLoader.Schema.Image.MimeTypeEnum.image_png, }); }
private Gltf InitializeGlTF() { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materialsToAdd = this._materials.Values.ToList(); materialsToAdd.Add(BuiltInMaterials.XAxis); materialsToAdd.Add(BuiltInMaterials.YAxis); materialsToAdd.Add(BuiltInMaterials.ZAxis); materialsToAdd.Add(BuiltInMaterials.Edges); materialsToAdd.Add(BuiltInMaterials.EdgesHighlighted); var materials = gltf.AddMaterials(materialsToAdd); var lines = new List <Vector3>(); foreach (var kvp in this._elements) { var e = kvp.Value; GetRenderDataForElement(e, gltf, materials, lines); } AddLines(100000, lines.ToArray(), gltf, materials[BuiltInMaterials.Edges.Name], null); var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = _buffer.Count(); gltf.Buffers = new[] { buff }; return(gltf); }
private Gltf InitializeGlTF() { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); // root.Matrix = new float[]{1.0f,0.0f,0.0f,0.0f, // 0.0f,0.0f,-1.0f,0.0f, // 0.0f,1.0f,0.0f,0.0f, // 0.0f,0.0f,0.0f,1.0f}; root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materials = new Dictionary <string, int>(); foreach (var kvp in this._materials) { var m = kvp.Value; var mId = gltf.AddMaterial(m.Name, m.Color.Red, m.Color.Green, m.Color.Blue, m.Color.Alpha, m.SpecularFactor, m.GlossinessFactor); materials.Add(m.Name, mId); } foreach (var kvp in this._elements) { var e = kvp.Value; GetRenderDataForElement(e, gltf, materials); } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = _buffer.Count(); gltf.Buffers = new[] { buff }; return(gltf); }
private static void AddMesh(gltf.Gltf gltf, XbimMesher mesh) { gltf.Buffers = new glTFLoader.Schema.Buffer[1]; var buf = new glTFLoader.Schema.Buffer(); gltf.Buffers[0] = buf; gltf.BufferViews = new gltf.BufferView[2]; }
private static Byte[] TryLoadBase64BinaryBufferUnchecked(Schema.Buffer buffer, string prefix) { if (buffer.Uri == null || !buffer.Uri.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { return(null); } var content = buffer.Uri.Substring(prefix.Length); return(Convert.FromBase64String(content)); }
private static Byte[] LoadBinaryBufferUnchecked(Schema.Buffer buffer, Func <string, Byte[]> externalReferenceSolver) { if (buffer.Uri == null) { return(externalReferenceSolver(null)); } if (buffer.Uri.StartsWith(EMBEDDEDOCTETSTREAM)) { var content = buffer.Uri.Substring(EMBEDDEDOCTETSTREAM.Length); return(Convert.FromBase64String(content)); } return(externalReferenceSolver(buffer.Uri)); }
private static byte[] ReadBuffer(glTFLoader.Schema.Buffer buffer) { var match = Regex.Match(buffer.Uri, @"data:application/octet-stream;base64,(?<data>.+)"); if (match.Success) { var base64Data = match.Groups["data"].Value; var binData = Convert.FromBase64String(base64Data); if (binData.Length != buffer.ByteLength) { throw new FormatException("Buffer has wrong length"); } return(binData); } throw new FormatException("Only support inline encoded buffers, not external buffer files."); }
public void WriteDracoBytes(byte[] bytes, out int bufferIndex, out int byteOffset) { if (binary) { byteOffset = (int)binaryBuffer.Count; binaryBuffer.AddRange(bytes); bufferIndex = 0; } else { glTFLoader.Schema.Buffer buffer = new glTFLoader.Schema.Buffer() { Uri = Constants.TextBufferHeader + Convert.ToBase64String(bytes), ByteLength = bytes.Length, }; bufferIndex = dummy.Buffers.AddAndReturnIndex(buffer); byteOffset = 0; } }
internal static void ToGlb(this Solid solid, string path) { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materials = gltf.AddMaterials(new[] { BuiltInMaterials.Default, BuiltInMaterials.Edges, BuiltInMaterials.EdgesHighlighted }); var buffer = new List <byte>(); var mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); gltf.AddTriangleMesh("mesh", buffer, mesh.Vertices.ToArray(), mesh.Normals.ToArray(), mesh.Indices.ToArray(), mesh.VertexColors.ToArray(), mesh.VMin, mesh.VMax, mesh.NMin, mesh.NMax, mesh.CMin, mesh.CMax, mesh.IMin, mesh.IMax, materials[BuiltInMaterials.Default.Name], null, null); var edgeCount = 0; var vertices = new List <Vector3>(); var verticesHighlighted = new List <Vector3>(); foreach (var e in solid.Edges.Values) { if (e.Left.Loop == null || e.Right.Loop == null) { verticesHighlighted.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } else { vertices.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } edgeCount++; } if (vertices.Count > 0) { // Draw standard edges var vBuff = vertices.ToArray().ToArray(); var vCount = vertices.Count; // var indices = Enumerable.Range(0, vCount).Select(i => (ushort)i).ToArray(); var indices = new List <ushort>(); for (var i = 0; i < vertices.Count; i += 2) { indices.Add((ushort)i); indices.Add((ushort)(i + 1)); } var bbox = new BBox3(vertices.ToArray()); gltf.AddLineLoop($"edge_{edgeCount}", buffer, vBuff, indices.ToArray(), bbox.Min.ToArray(), bbox.Max.ToArray(), 0, (ushort)(vCount - 1), materials[BuiltInMaterials.Edges.Name], MeshPrimitive.ModeEnum.LINES, null); } if (verticesHighlighted.Count > 0) { // Draw highlighted edges var vBuff = vertices.ToArray().ToArray(); var vCount = vertices.Count; var indices = new List <ushort>(); for (var i = 0; i < vertices.Count; i += 2) { indices.Add((ushort)i); indices.Add((ushort)(i + 1)); } var bbox = new BBox3(vertices.ToArray()); gltf.AddLineLoop($"edge_{edgeCount}", buffer, vBuff, indices.ToArray(), bbox.Min.ToArray(), bbox.Max.ToArray(), 0, (ushort)(vCount - 1), materials[BuiltInMaterials.EdgesHighlighted.Name], MeshPrimitive.ModeEnum.LINES, null); } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count; gltf.Buffers = new[] { buff }; if (File.Exists(path)) { File.Delete(path); } gltf.SaveBinaryModel(buffer.ToArray(), path); }
private static Gltf InitializeGlTF(Model model, List <byte> buffer) { var sw = new Stopwatch(); sw.Start(); var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; sw.Stop(); Console.WriteLine($"glTF: {sw.Elapsed} elapsed for writing root node."); sw.Reset(); sw.Start(); var materialsToAdd = model.Materials.Values.ToList(); materialsToAdd.Add(BuiltInMaterials.XAxis); materialsToAdd.Add(BuiltInMaterials.YAxis); materialsToAdd.Add(BuiltInMaterials.ZAxis); materialsToAdd.Add(BuiltInMaterials.Edges); materialsToAdd.Add(BuiltInMaterials.EdgesHighlighted); var materials = gltf.AddMaterials(materialsToAdd); sw.Stop(); Console.WriteLine($"glTF: {sw.Elapsed} elapsed for writing materials."); sw.Reset(); sw.Start(); // Lines are stored in a list of lists // according to the max available index size of ushort. var lines = new List <List <Vector3> >() { new List <Vector3>() }; var bufferViews = new List <BufferView>(); var accessors = new List <Accessor>(); var elements = model.Elements.Values.ToArray(); for (var i = 0; i < elements.Length; i++) { var e = elements[i]; GetRenderDataForElement(e, gltf, materials, lines, buffer, bufferViews, accessors); } sw.Stop(); Console.WriteLine($"glTF: {sw.Elapsed} elapsed for getting render data for nodes."); sw.Reset(); sw.Start(); if (lines.Count > 0) { foreach (var lineSet in lines) { if (lineSet.Count > 0) { AddLines(100000, lineSet.ToArray(), gltf, materials[BuiltInMaterials.Edges.Name], buffer, bufferViews, accessors); } } } sw.Stop(); Console.WriteLine($"glTF: {sw.Elapsed} elapsed for writing edges."); sw.Reset(); sw.Start(); var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count(); gltf.Buffers = new[] { buff }; sw.Stop(); Console.WriteLine($"glTF: {sw.Elapsed} elapsed for assigning buffer."); sw.Reset(); gltf.BufferViews = bufferViews.ToArray(); gltf.Accessors = accessors.ToArray(); return(gltf); }
internal static void ToGlb(this Solid solid, string path) { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materials = gltf.AddMaterials(new[] { BuiltInMaterials.Default, BuiltInMaterials.Edges, BuiltInMaterials.EdgesHighlighted }); var buffer = new List <byte>(); var mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); byte[] vertexBuffer; byte[] normalBuffer; byte[] indexBuffer; byte[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); var bufferViews = new List <BufferView>(); var accessors = new List <Accessor>(); gltf.AddTriangleMesh("mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[BuiltInMaterials.Default.Name], cmin, cmax, null, null); var edgeCount = 0; var vertices = new List <Vector3>(); var verticesHighlighted = new List <Vector3>(); foreach (var e in solid.Edges.Values) { if (e.Left.Loop == null || e.Right.Loop == null) { verticesHighlighted.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } else { vertices.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } edgeCount++; } if (vertices.Count > 0) { // Draw standard edges AddLines(100000, vertices.ToArray(), gltf, materials[BuiltInMaterials.Edges.Name], buffer, bufferViews, accessors); } if (verticesHighlighted.Count > 0) { // Draw highlighted edges AddLines(100001, verticesHighlighted.ToArray(), gltf, materials[BuiltInMaterials.EdgesHighlighted.Name], buffer, bufferViews, accessors); } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count; gltf.Buffers = new[] { buff }; gltf.BufferViews = bufferViews.ToArray(); gltf.Accessors = accessors.ToArray(); if (File.Exists(path)) { File.Delete(path); } gltf.SaveBinaryModel(buffer.ToArray(), path); }
static byte[] loadDataUri (GL.Buffer buff) { int idxComa = buff.Uri.IndexOf (",", 5, StringComparison.Ordinal); return Convert.FromBase64String (buff.Uri.Substring (idxComa + 1)); }
private static Gltf InitializeGlTF(Model model, List <byte> buffer, bool drawEdges = false) { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); var rootTransform = new Transform(model.Transform); // Rotate the transform for +Z up. rootTransform.Rotate(new Vector3(1, 0, 0), -90.0); var m = rootTransform.Matrix; root.Matrix = new float[] { (float)m.m11, (float)m.m12, (float)m.m13, 0f, (float)m.m21, (float)m.m22, (float)m.m23, 0f, (float)m.m31, (float)m.m32, (float)m.m33, 0f, (float)m.tx, (float)m.ty, (float)m.tz, 1f }; var nodes = new List <glTFLoader.Schema.Node> { root }; var meshes = new List <glTFLoader.Schema.Mesh>(); gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness", "KHR_materials_unlit", "KHR_lights_punctual" }; var bufferViews = new List <BufferView>(); var accessors = new List <Accessor>(); var materialsToAdd = model.AllElementsOfType <Material>().ToList(); if (drawEdges) { materialsToAdd.Add(BuiltInMaterials.Edges); } var materials = gltf.AddMaterials(materialsToAdd, buffer, bufferViews); var elements = model.Elements.Where(e => { return(e.Value is GeometricElement || e.Value is ElementInstance); }).Select(e => e.Value).ToList(); var lights = model.AllElementsOfType <DirectionalLight>().ToList(); gltf.AddLights(lights, nodes); // Lines are stored in a list of lists // according to the max available index size. var lines = new List <List <Vector3> >(); var currLines = new List <Vector3>(); lines.Add(currLines); var meshElementMap = new Dictionary <Guid, List <int> >(); foreach (var e in elements) { // Check if we'll overrun the index size // for the current line array. If so, // create a new line array. if (currLines.Count * 2 > ushort.MaxValue) { currLines = new List <Vector3>(); lines.Add(currLines); } GetRenderDataForElement(e, gltf, materials, buffer, bufferViews, accessors, meshes, nodes, meshElementMap, currLines, drawEdges); } if (buffer.Count == 0 && lights.Count == 0) { return(null); } if (drawEdges && lines.Count() > 0) { foreach (var lineSet in lines) { if (lineSet.Count == 0) { continue; } AddLines(GetNextId(), lineSet, gltf, materials[BuiltInMaterials.Edges.Name], buffer, bufferViews, accessors, meshes, nodes, false); } } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count; gltf.Buffers = new[] { buff }; gltf.BufferViews = bufferViews.ToArray(); gltf.Accessors = accessors.ToArray(); gltf.Nodes = nodes.ToArray(); if (meshes.Count > 0) { gltf.Meshes = meshes.ToArray(); } return(gltf); }
public Gltf FromBrg(BrgFile brg, Stream bufferStream) { // TODO clear class fields gltf.Asset = new Asset(); gltf.Asset.Version = "2.0"; Scene scene = new Scene(); scene.Nodes = new int[] { 0 }; gltf.Scenes = new[] { scene }; gltf.Scene = 0; Node node = new Node(); node.Mesh = 0; node.Name = "node"; gltf.Nodes = new[] { node }; //FromBrgMesh(brg.Meshes[0]); // Create materials / textures // Create primitives from first brg mesh // TODO: check if there is at least 1 mesh, and 1 face var primitives = (from face in brg.Meshes[0].Faces group face by face.MaterialIndex into faceGroup select new BrgMeshPrimitive(faceGroup.ToList())).ToList(); // Load mesh data glTFLoader.Schema.Mesh mesh = new glTFLoader.Schema.Mesh(); mesh.Primitives = new MeshPrimitive[primitives.Count]; for (int i = 0; i < mesh.Primitives.Length; ++i) { mesh.Primitives[i] = new MeshPrimitive(); } for (int j = 0; j < primitives.Count; ++j) { primitives[j].Serialize(mesh.Primitives[j], brg.Meshes[0], this, bufferStream); } for (int i = 0; i < brg.Meshes[0].MeshAnimations.Count; ++i) { for (int j = 0; j < primitives.Count; ++j) { primitives[j].Serialize(mesh.Primitives[j], (BrgMesh)brg.Meshes[0].MeshAnimations[i], this, bufferStream); } } gltf.Meshes = new[] { mesh }; // Create Animation if (brg.Meshes[0].MeshAnimations.Count > 0) { for (int i = 0; i < mesh.Primitives.Length; ++i) { mesh.Primitives[i].Targets = primitives[i].Targets.ToArray(); } mesh.Weights = new float[brg.Meshes[0].MeshAnimations.Count]; gltf.Animations = new[] { CreateAnimation(brg.Animation, mesh.Weights.Length, bufferStream) }; } // Create buffer stream gltf.BufferViews = bufferViews.ToArray(); gltf.Accessors = accessors.ToArray(); var buffer = new glTFLoader.Schema.Buffer(); gltf.Buffers = new[] { buffer }; buffer.ByteLength = (int)bufferStream.Length; buffer.Uri = "dataBuffer.bin"; return(gltf); }
/// <summary> /// Creates a single buffer and a minimum number of buffer-views to pack all the accessors. /// </summary> private void PackAccessors(GltfFile modelFile, Stream newBufferStream, string outputBufferUri) { var fileData = modelFile.Data; var buffers = fileData.Buffers; var bufferViews = fileData.BufferViews; // TODO: Check sparse accessors // Group accessor by optional target, component-stride and component byte-length // For each group, we need to create a single buffer-view. var accessorGroups = fileData .Accessors .Where(a => a.BufferView.HasValue) .GroupBy(a => (target: bufferViews[a.BufferView.Value].Target, stride: a.GetByteStride(bufferViews) /*, componentByteLength: a.GetComponentByteLength()*/)) .ToDictionary(g => g.Key, g => g.ToArray()); // NOTE: The following select sequence has a side-effect var newBufferViews = accessorGroups .Select((pair, newBufferViewIndex) => { //var ((target, stride, componentByteLength), accessors) = pair; var((target, stride), accessors) = pair; var newBufferViewOffset = (int)newBufferStream.Position; //Debug.Assert(newBufferStream.GetComponentPadding(componentByteLength) == 0); foreach (var accessor in accessors) { var componentByteLength = accessor.GetComponentByteLength(); var accessorPadding = newBufferStream.GetComponentPadding(componentByteLength); newBufferStream.WriteByte(0, accessorPadding); var newAccessorByteOffset = (int)(newBufferStream.Position - newBufferViewOffset); Debug.Assert(accessor.BufferView.HasValue); var bufferView = bufferViews[accessor.BufferView.Value]; var buffer = buffers[bufferView.Buffer]; var data = _bufferFileData[buffer]; var bufferOffset = bufferView.ByteOffset + accessor.ByteOffset; var rowLength = accessor.GetComponentDimension() * componentByteLength; for (int i = 0; i < accessor.Count; ++i) { Debug.Assert(newBufferStream.GetComponentPadding(componentByteLength) == 0); newBufferStream.Write(data, bufferOffset + i * stride, rowLength); Debug.Assert(newBufferStream.GetComponentPadding(componentByteLength) == 0); } // Patch the accessor. accessor.ByteOffset = newAccessorByteOffset; accessor.BufferView = newBufferViewIndex; } var newBufferView = new BufferView { Target = target, ByteOffset = newBufferViewOffset, ByteStride = target == BufferView.TargetEnum.ARRAY_BUFFER ? stride : (int?)null, ByteLength = (int)(newBufferStream.Position - newBufferViewOffset) }; return(newBufferView); }) .ToArray(); var newBuffer = new Buffer { ByteLength = (int)newBufferStream.Length, Uri = outputBufferUri }; fileData.BufferViews = newBufferViews; fileData.Buffers = new[] { newBuffer }; }
private static Byte[] LoadBinaryBufferUnchecked(Schema.Buffer buffer, Func <string, Byte[]> externalReferenceSolver) { return(TryLoadBase64BinaryBufferUnchecked(buffer, EMBEDDEDGLTFBUFFER) ?? TryLoadBase64BinaryBufferUnchecked(buffer, EMBEDDEDOCTETSTREAM) ?? externalReferenceSolver(buffer?.Uri)); }
/// <summary> /// Converts self contained GLB to glTF file and associated textures and data /// </summary> /// <param name="inputFilePath">glTF binary file (.glb) to unpack</param> /// <param name="outputDirectoryPath">Directory where the files will be extracted</param> public static void Unpack(string inputFilePath, string outputDirectoryPath) { if (!File.Exists(inputFilePath)) { throw new ArgumentException("Input file does not exists"); } if (!Directory.Exists(outputDirectoryPath)) { throw new ArgumentException("Ouput directory does not exists"); } string inputFileName = Path.GetFileNameWithoutExtension(inputFilePath); string inputDirectoryPath = Path.GetDirectoryName(inputFilePath); var model = Interface.LoadModel(inputFilePath); glTFLoader.Schema.Buffer binBuffer = null; byte[] binBufferData = null; if (model.Buffers != null && string.IsNullOrEmpty(model.Buffers[0].Uri)) { binBuffer = model.Buffers[0]; binBufferData = model.LoadBinaryBuffer(0, inputFilePath); } var imageBufferViewIndices = new List <int>(); if (model.Images != null) { for (var index = 0; index < model.Images.Length; index++) { var image = model.Images[index]; if (!string.IsNullOrEmpty(image.Uri)) { if (!image.Uri.StartsWith("data:")) { var sourceFilePath = Path.Combine(inputDirectoryPath, image.Uri); var fileName = $"{inputFilePath}_image{index}.bin"; if (File.Exists(sourceFilePath)) { var destinationFilePath = Path.Combine(outputDirectoryPath, fileName); File.Copy(sourceFilePath, destinationFilePath, true); } image.Uri = fileName; } } else if (image.BufferView.HasValue) { var bufferView = model.BufferViews[image.BufferView.Value]; if (bufferView.Buffer == 0) { imageBufferViewIndices.Add(image.BufferView.Value); var fileExtension = image.MimeType == Image.MimeTypeEnum.image_jpeg ? "jpg" : "png"; var fileName = $"{inputFileName}_image{index}.{fileExtension}"; using (var fileStream = File.Create(Path.Combine(outputDirectoryPath, fileName))) { fileStream.Write(binBufferData, bufferView.ByteOffset, bufferView.ByteLength); } image.BufferView = null; image.MimeType = null; image.Uri = fileName; } } } } if (model.BufferViews != null) { var binFileName = $"{inputFileName}.bin"; var binFilePath = Path.Combine(outputDirectoryPath, binFileName); var binByteLength = 0; var indexMap = new Dictionary <int, int>(); var bufferViews = new List <BufferView>(); using (var fileStream = File.Create(binFilePath)) { for (var index = 0; index < model.BufferViews.Length; index++) { if (!imageBufferViewIndices.Any(imageIndex => imageIndex == index)) { var bufferView = model.BufferViews[index]; if (bufferView.Buffer == 0) { fileStream.Align(4); var fileStreamPosition = fileStream.Position; fileStream.Write(binBufferData, bufferView.ByteOffset, bufferView.ByteLength); bufferView.ByteOffset = (int)fileStreamPosition; } var newIndex = bufferViews.Count; if (index != newIndex) { indexMap.Add(index, newIndex); } bufferViews.Add(bufferView); } } binByteLength = (int)fileStream.Length; } model.BufferViews = bufferViews.ToArray(); if (binByteLength == 0) { File.Delete(binFilePath); if (binBuffer != null) { model.Buffers = model.Buffers.Skip(1).ToArray(); foreach (var bufferView in model.BufferViews) { bufferView.Buffer--; } } } else { binBuffer.Uri = binFileName; binBuffer.ByteLength = binByteLength; } if (model.Accessors != null) { foreach (var accessor in model.Accessors) { if (accessor.BufferView.HasValue) { if (indexMap.TryGetValue(accessor.BufferView.Value, out int newIndex)) { accessor.BufferView = newIndex; } } } } } if (model.Buffers != null) { for (var index = 1; index < model.Buffers.Length; index++) { var buffer = model.Buffers[index]; if (!buffer.Uri.StartsWith("data:")) { var sourceFilePath = Path.Combine(inputDirectoryPath, buffer.Uri); var fileName = $"{inputFileName}{index}.bin"; if (File.Exists(sourceFilePath)) { var destinationFilePath = Path.Combine(outputDirectoryPath, fileName); File.Copy(sourceFilePath, destinationFilePath, true); } buffer.Uri = fileName; } } } Interface.SaveModel(model, Path.Combine(outputDirectoryPath, $"{inputFileName}.gltf")); }
private void FromBrgMesh(BrgMesh brgMesh) { Vector3 max = new Vector3(float.MinValue); Vector3 min = new Vector3(float.MaxValue); using (FileStream fs = File.Open("posBuffer.bin", FileMode.Create, FileAccess.Write, FileShare.Read)) using (BinaryWriter writer = new BinaryWriter(fs)) { foreach (Vector3 vec in brgMesh.Vertices) { max.X = Math.Max(max.X, vec.X); max.Y = Math.Max(max.Y, vec.Y); max.Z = Math.Max(max.Z, vec.Z); min.X = Math.Min(min.X, vec.X); min.Y = Math.Min(min.Y, vec.Y); min.Z = Math.Min(min.Z, vec.Z); writer.Write(vec.X); writer.Write(vec.Y); writer.Write(vec.Z); } } glTFLoader.Schema.Buffer posBuffer = new glTFLoader.Schema.Buffer(); posBuffer.ByteLength = brgMesh.Vertices.Count * 12; posBuffer.Uri = "posBuffer.bin"; BufferView posBufferView = new BufferView(); posBufferView.Buffer = 0; posBufferView.ByteLength = posBuffer.ByteLength; posBufferView.ByteOffset = 0; posBufferView.ByteStride = 12; posBufferView.Name = "posBufferView"; posBufferView.Target = BufferView.TargetEnum.ARRAY_BUFFER; Accessor posAccessor = new Accessor(); posAccessor.BufferView = 0; posAccessor.ByteOffset = 0; posAccessor.ComponentType = Accessor.ComponentTypeEnum.FLOAT; posAccessor.Count = brgMesh.Vertices.Count; posAccessor.Max = new[] { max.X, max.Y, max.Z }; posAccessor.Min = new[] { min.X, min.Y, min.Z }; posAccessor.Name = "posBufferViewAccessor"; posAccessor.Type = Accessor.TypeEnum.VEC3; short faceMin = short.MaxValue; short faceMax = short.MinValue; using (FileStream fs = File.Open("indexBuffer.bin", FileMode.Create, FileAccess.Write, FileShare.Read)) using (BinaryWriter writer = new BinaryWriter(fs)) { foreach (var face in brgMesh.Faces) { faceMin = Math.Min(faceMin, face.Indices[0]); faceMin = Math.Min(faceMin, face.Indices[1]); faceMin = Math.Min(faceMin, face.Indices[2]); faceMax = Math.Max(faceMax, face.Indices[0]); faceMax = Math.Max(faceMax, face.Indices[1]); faceMax = Math.Max(faceMax, face.Indices[2]); writer.Write(face.Indices[0]); writer.Write(face.Indices[1]); writer.Write(face.Indices[2]); } } glTFLoader.Schema.Buffer indexBuffer = new glTFLoader.Schema.Buffer(); indexBuffer.ByteLength = brgMesh.Faces.Count * 6; indexBuffer.Uri = "indexBuffer.bin"; BufferView indexBufferView = new BufferView(); indexBufferView.Buffer = 1; indexBufferView.ByteLength = indexBuffer.ByteLength; indexBufferView.ByteOffset = 0; indexBufferView.Name = "indexBufferView"; indexBufferView.Target = BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER; Accessor indexAccessor = new Accessor(); indexAccessor.BufferView = 1; indexAccessor.ByteOffset = 0; indexAccessor.ComponentType = Accessor.ComponentTypeEnum.UNSIGNED_SHORT; indexAccessor.Count = brgMesh.Faces.Count * 3; indexAccessor.Max = new[] { (float)faceMax }; indexAccessor.Min = new[] { (float)faceMin }; indexAccessor.Name = "indexBufferViewAccessor"; indexAccessor.Type = Accessor.TypeEnum.SCALAR; gltf.Buffers = new[] { posBuffer, indexBuffer }; gltf.BufferViews = new[] { posBufferView, indexBufferView }; gltf.Accessors = new[] { posAccessor, indexAccessor }; MeshPrimitive meshPrimitive = new MeshPrimitive(); meshPrimitive.Attributes = new Dictionary <string, int>(); meshPrimitive.Attributes.Add("POSITION", 0); meshPrimitive.Indices = 1; meshPrimitive.Mode = MeshPrimitive.ModeEnum.TRIANGLES; var mesh = new glTFLoader.Schema.Mesh(); mesh.Name = "mesh"; mesh.Primitives = new[] { meshPrimitive }; gltf.Meshes = new[] { mesh }; Node node = new Node(); node.Mesh = 0; node.Name = "node"; gltf.Nodes = new[] { node }; }