-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved binary read and write support #7
Changes from 1 commit
1ba801a
1e8e4cf
7f5b21d
00b432f
3225eb8
cc646fc
bf2e3cb
5344517
214c161
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,13 @@ public static class Interface | |
const uint JSON = 0x4E4F534A; | ||
const uint BIN = 0x004E4942; | ||
|
||
const string EMBEDDEDOCTETSTREAM = "data:application/octet-stream;base64"; | ||
const string EMBEDDEDPNG = "data:image/png;base64"; | ||
const string EMBEDDEDBMP = "data:image/bmp;base64"; | ||
const string EMBEDDEDGIF = "data:image/gif;base64"; | ||
const string EMBEDDEDJPEG = "data:image/jpeg;base64"; | ||
const string EMBEDDEDTIFF = "data:image/tiff;base64"; | ||
|
||
public static Gltf LoadModel(string filePath) | ||
{ | ||
var path = Path.GetFullPath(filePath); | ||
|
@@ -129,6 +136,23 @@ public static Byte[] LoadBinaryBuffer(Stream stream) | |
} | ||
} | ||
|
||
public static Byte[] LoadBinaryBuffer(this Gltf model, string gltfFilePath, int bufferIndex) | ||
{ | ||
var buffer = model.Buffers[bufferIndex]; | ||
|
||
if (buffer.Uri == null) return LoadBinaryBuffer(gltfFilePath); | ||
|
||
if (buffer.Uri.StartsWith("data:application/octet-stream;base64")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you mean to replace this with |
||
{ | ||
var content = buffer.Uri.Substring(EMBEDDEDOCTETSTREAM.Length + 1); | ||
return Convert.FromBase64String(content); | ||
} | ||
|
||
var bufferFilePath = Path.Combine(Path.GetDirectoryName(gltfFilePath), buffer.Uri); | ||
|
||
return File.ReadAllBytes(bufferFilePath); | ||
} | ||
|
||
private static void ReadBinaryHeader(BinaryReader binaryReader) | ||
{ | ||
uint magic = binaryReader.ReadUInt32(); | ||
|
@@ -151,6 +175,39 @@ private static void ReadBinaryHeader(BinaryReader binaryReader) | |
} | ||
} | ||
|
||
public static Stream OpenImageFile(this Gltf model, string gltfFilePath, int imageIndex) | ||
{ | ||
var image = model.Images[imageIndex]; | ||
|
||
if (image.BufferView.HasValue) | ||
{ | ||
var bufferView = model.BufferViews[image.BufferView.Value]; | ||
|
||
var bufferBytes = model.LoadBinaryBuffer(gltfFilePath, bufferView.Buffer); | ||
|
||
return new MemoryStream(bufferBytes, bufferView.ByteOffset, bufferView.ByteLength); | ||
} | ||
|
||
if (image.Uri.StartsWith("data:image/")) | ||
{ | ||
string content = null; | ||
|
||
if (image.Uri.StartsWith(EMBEDDEDPNG)) content = image.Uri.Substring(EMBEDDEDPNG.Length + 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. glTF only support PNG and JPG. None of the other formats are supported, so you don't need the other mime types. |
||
if (image.Uri.StartsWith(EMBEDDEDBMP)) content = image.Uri.Substring(EMBEDDEDBMP.Length + 1); | ||
if (image.Uri.StartsWith(EMBEDDEDGIF)) content = image.Uri.Substring(EMBEDDEDGIF.Length + 1); | ||
if (image.Uri.StartsWith(EMBEDDEDJPEG)) content = image.Uri.Substring(EMBEDDEDJPEG.Length + 1); | ||
if (image.Uri.StartsWith(EMBEDDEDTIFF)) content = image.Uri.Substring(EMBEDDEDTIFF.Length + 1); | ||
|
||
var bytes = Convert.FromBase64String(content); | ||
return new MemoryStream(bytes); | ||
} | ||
else | ||
{ | ||
var imageFilePath = Path.Combine(Path.GetDirectoryName(gltfFilePath), image.Uri); | ||
return File.OpenRead(imageFilePath); | ||
} | ||
} | ||
|
||
public static Gltf DeserializeModel(string fileData) | ||
{ | ||
return JsonConvert.DeserializeObject<Gltf>(fileData); | ||
|
@@ -223,6 +280,8 @@ public static void SaveBinaryModel(this Gltf model, byte[] buffer, BinaryWriter | |
for (int i = 0; i < binPadding; ++i) binaryWriter.Write((Byte)0); | ||
} | ||
|
||
|
||
|
||
} | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend adding the trailing comma to this constant so that you are actually checking for the comma instead of ignoring the character using
+ 1
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okey, I'll do that change.
Btw, detecting embedded images is quite tricky and I'm aware there's room for improvement. For example, I'm sure some people will want to use hardware specific images, like DDS or ASTC , I don't know if there's specific mime types for these formats... in which case, is it possible to find images stored as data:application/octet-stream;base64 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There have been lots of discussions around this already, but the short answer, at least for core glTF 2.0, is that hardware specific textures are not supported. Thus, you don't have to worry about them for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okey then.
About the Interface API, there's a few more methods I would like to add, but I don't know if you think it's too much already...
Usually, when I work with file formats, I try to make everything to work with Streams, certainly, it gets complicated when you have multiple files around. The use case is when you try to load a file from within a ZIP or any other package container (which is quite common to use in videogames)
The idea I had in mind was to replicate the previous methods used to load buffers and images, but using lambdas, so the end user could intercept/inject file accesses to whatever package container is using.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do that in a separate change.