Binary glTF is now part of the glTF2 spec. However, it’s implemented incorrectly, so will be temporarily removed
* Declares a glTF class to handle gltf/glb files
*
* glTF Extensions Support:
- * KHR_binary_glTF: full
* KHR_materials_pbrSpecularGlossiness full
*/
#ifndef GLTF2ASSET_H_INC
#include "./../include/assimp/Compiler/pushpack1.h"
#endif
- //! For the KHR_binary_glTF extension (binary .glb file)
- //! 20-byte header (+ the JSON + a "body" data section)
- struct GLB_Header
- {
- uint8_t magic[4]; //!< Magic number: "glTF"
- uint32_t version; //!< Version number
- uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
- uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
- uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
- } PACK_STRUCT;
-
#ifdef ASSIMP_API
#include "./../include/assimp/Compiler/poppack1.h"
#endif
//! Keeps info about the enabled extensions
struct Extensions
{
- bool KHR_binary_glTF;
bool KHR_materials_pbrSpecularGlossiness;
} extensionsUsed;
}
//! Main function
- void Load(const std::string& file, bool isBinary = false);
-
- //! Enables the "KHR_binary_glTF" extension on the asset
- void SetAsBinary();
+ void Load(const std::string& file);
//! Search for an available name, starting from the given strings
std::string FindUniqueID(const std::string& str, const char* suffix);
{ return mBodyBuffer; }
private:
- void ReadBinaryHeader(IOStream& stream);
-
void ReadExtensionsUsed(Document& doc);
-
IOStream* OpenFile(std::string path, const char* mode, bool absolute = false);
};
inline const char* Buffer::TranslateId(Asset& r, const char* id)
{
- // Compatibility with old spec
- if (r.extensionsUsed.KHR_binary_glTF && strcmp(id, "KHR_binary_glTF") == 0) {
- return "binary_glTF";
- }
-
return id;
}
inline void Image::Read(Value& obj, Asset& r)
{
- // Check for extensions first (to detect binary embedded data)
- if (Value* extensions = FindObject(obj, "extensions")) {
- if (r.extensionsUsed.KHR_binary_glTF) {
- if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) {
-
- width = MemberOrDefault(*ext, "width", 0);
- height = MemberOrDefault(*ext, "height", 0);
-
- ReadMember(*ext, "mimeType", mimeType);
-
- if (Value* bufferViewVal = FindUInt(*ext, "bufferView")) {
- Ref<BufferView> bv = r.bufferViews.Retrieve(bufferViewVal->GetUint());
- if (bv) {
- mDataLength = bv->byteLength;
- mData = new uint8_t[mDataLength];
- memcpy(mData, bv->buffer->GetPointer() + bv->byteOffset, mDataLength);
- }
- }
- }
- }
- }
-
if (!mDataLength) {
if (Value* uri = FindString(obj, "uri")) {
const char* uristr = uri->GetString();
// Asset methods implementation
//
-inline void Asset::ReadBinaryHeader(IOStream& stream)
-{
- GLB_Header header;
- if (stream.Read(&header, sizeof(header), 1) != 1) {
- throw DeadlyImportError("GLTF: Unable to read the file header");
- }
-
- if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) {
- throw DeadlyImportError("GLTF: Invalid binary glTF file");
- }
-
- AI_SWAP4(header.version);
- asset.version = header.version;
- if (header.version != 1) {
- throw DeadlyImportError("GLTF: Unsupported binary glTF version");
- }
-
- AI_SWAP4(header.sceneFormat);
- if (header.sceneFormat != SceneFormat_JSON) {
- throw DeadlyImportError("GLTF: Unsupported binary glTF scene format");
- }
-
- AI_SWAP4(header.length);
- AI_SWAP4(header.sceneLength);
-
- mSceneLength = static_cast<size_t>(header.sceneLength);
-
- mBodyOffset = sizeof(header)+mSceneLength;
- mBodyOffset = (mBodyOffset + 3) & ~3; // Round up to next multiple of 4
-
- mBodyLength = header.length - mBodyOffset;
-}
-
-inline void Asset::Load(const std::string& pFile, bool isBinary)
+inline void Asset::Load(const std::string& pFile)
{
mCurrentAssetDir.clear();
int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
throw DeadlyImportError("GLTF: Could not open file for reading");
}
- // is binary? then read the header
- if (isBinary) {
- SetAsBinary(); // also creates the body buffer
- ReadBinaryHeader(*stream);
- }
- else {
- mSceneLength = stream->FileSize();
- mBodyLength = 0;
- }
-
+ mSceneLength = stream->FileSize();
+ mBodyLength = 0;
// read the scene data
}
}
-inline void Asset::SetAsBinary()
-{
- if (!extensionsUsed.KHR_binary_glTF) {
- extensionsUsed.KHR_binary_glTF = true;
- mBodyBuffer = buffers.Create("binary_glTF");
- mBodyBuffer->MarkAsSpecial();
- }
-}
-
inline void Asset::ReadExtensionsUsed(Document& doc)
{
Value* extsUsed = FindArray(doc, "extensionsUsed");
#define CHECK_EXT(EXT) \
if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
- CHECK_EXT(KHR_binary_glTF);
CHECK_EXT(KHR_materials_pbrSpecularGlossiness);
#undef CHECK_EXT
* Declares a class to write gltf/glb files
*
* glTF Extensions Support:
- * KHR_binary_glTF: full
* KHR_materials_pbrSpecularGlossiness: full
*/
#ifndef GLTF2ASSETWRITER_H_INC
AssetWriter(Asset& asset);
void WriteFile(const char* path);
- void WriteGLBFile(const char* path);
};
}
inline void Write(Value& obj, Image& img, AssetWriter& w)
{
std::string uri;
- if (w.mAsset.extensionsUsed.KHR_binary_glTF && img.bufferView) {
- Value exts, ext;
- exts.SetObject();
- ext.SetObject();
-
- ext.AddMember("bufferView", img.bufferView->index, w.mAl);
-
- if (!img.mimeType.empty())
- ext.AddMember("mimeType", StringRef(img.mimeType), w.mAl);
-
- exts.AddMember("KHR_binary_glTF", ext, w.mAl);
- obj.AddMember("extensions", exts, w.mAl);
- return;
- }
- else if (img.HasData()) {
+ if (img.HasData()) {
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
uri += ";base64,";
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
}
}
- inline void AssetWriter::WriteGLBFile(const char* path)
- {
- std::unique_ptr<IOStream> outfile(mAsset.OpenFile(path, "wb", true));
-
- if (outfile == 0) {
- throw DeadlyExportError("Could not open output file: " + std::string(path));
- }
-
- // we will write the header later, skip its size
- outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
-
- StringBuffer docBuffer;
- Writer<StringBuffer> writer(docBuffer);
- mDoc.Accept(writer);
-
- if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
- throw DeadlyExportError("Failed to write scene data!");
- }
-
- WriteBinaryData(outfile.get(), docBuffer.GetSize());
- }
-
- inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength)
- {
- //
- // write the body data
- //
-
- size_t bodyLength = 0;
- if (Ref<Buffer> b = mAsset.GetBodyBuffer()) {
- bodyLength = b->byteLength;
-
- if (bodyLength > 0) {
- size_t bodyOffset = sizeof(GLB_Header) + sceneLength;
- bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4
-
- outfile->Seek(bodyOffset, aiOrigin_SET);
-
- if (outfile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
- throw DeadlyExportError("Failed to write body data!");
- }
- }
- }
-
- //
- // write the header
- //
-
- GLB_Header header;
- memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
-
- header.version = 2;
- AI_SWAP4(header.version);
-
- header.length = uint32_t(sizeof(header) + sceneLength + bodyLength);
- AI_SWAP4(header.length);
-
- header.sceneLength = uint32_t(sceneLength);
- AI_SWAP4(header.sceneLength);
-
- header.sceneFormat = SceneFormat_JSON;
- AI_SWAP4(header.sceneFormat);
-
- outfile->Seek(0, aiOrigin_SET);
-
- if (outfile->Write(&header, 1, sizeof(header)) != sizeof(header)) {
- throw DeadlyExportError("Failed to write the header!");
- }
- }
-
-
inline void AssetWriter::WriteMetadata()
{
Value asset;
Value exts;
exts.SetArray();
{
- //if (false)
- // exts.PushBack(StringRef("KHR_binary_glTF"), mAl);
-
// This is used to export pbrSpecularGlossiness materials with GLTF 2.
if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
mAsset.reset( new Asset( pIOSystem ) );
- if (isBinary) {
- mAsset->SetAsBinary();
- }
-
ExportMetadata();
ExportMaterials();
AssetWriter writer(*mAsset);
- if (isBinary) {
- writer.WriteGLBFile(filename);
- } else {
- writer.WriteFile(filename);
- }
+ writer.WriteFile(filename);
}
/*
"",
"",
"",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+ aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0,
0,
0,
{
const std::string &extension = GetExtension(pFile);
- if (extension != "gltf") // We currently can't read glTF2 binary files (.glb)
+ if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet
return false;
if (checkSig && pIOHandler) {
glTF2::Asset asset(pIOHandler);
try {
- asset.Load(pFile, extension == "glb");
+ asset.Load(pFile);
std::string version = asset.asset.version;
return !version.empty() && version[0] == '2';
} catch (...) {
// read the asset file
glTF2::Asset asset(pIOHandler);
- asset.Load(pFile, GetExtension(pFile) == "glb");
-
+ asset.Load(pFile);
//
// Copy the data out
//
-
-
ImportEmbeddedTextures(asset);
ImportMaterials(asset);