From 3c827f29f652f102dc620d3c4f283db4d38cec4b Mon Sep 17 00:00:00 2001 From: johnmaf Date: Mon, 19 Sep 2016 17:44:38 -0400 Subject: [PATCH 1/2] Export glTF buffers as separate .bin files --- code/glTFAsset.h | 3 ++ code/glTFAssetWriter.h | 1 + code/glTFAssetWriter.inl | 70 +++++++++++++++++++++++++--------------- code/glTFExporter.cpp | 24 ++++++++------ 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 6d5ac1a71..022774779 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -489,6 +489,9 @@ namespace glTF bool IsSpecial() const { return mIsSpecial; } + std::string GetURI() + { return std::string(this->id) + ".bin"; } + static const char* TranslateId(Asset& r, const char* id); }; diff --git a/code/glTFAssetWriter.h b/code/glTFAssetWriter.h index 370d2c0ab..4d2d3c919 100644 --- a/code/glTFAssetWriter.h +++ b/code/glTFAssetWriter.h @@ -79,6 +79,7 @@ public: AssetWriter(Asset& asset); void WriteFile(const char* path); + void WriteGLBFile(const char* path); }; } diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 415db6714..6302ab3c3 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -94,9 +94,6 @@ namespace glTF { inline void Write(Value& obj, Buffer& b, AssetWriter& w) { - std::string dataURI = "data:application/octet-stream;base64,"; - Util::EncodeBase64(b.GetPointer(), b.byteLength, dataURI); - const char* type; switch (b.type) { case Buffer::Type_text: @@ -107,7 +104,7 @@ namespace glTF { obj.AddMember("byteLength", static_cast(b.byteLength), w.mAl); obj.AddMember("type", StringRef(type), w.mAl); - obj.AddMember("uri", Value(dataURI, w.mAl).Move(), w.mAl); + obj.AddMember("uri", Value(b.GetURI(), w.mAl).Move(), w.mAl); } inline void Write(Value& obj, BufferView& bv, AssetWriter& w) @@ -328,39 +325,61 @@ namespace glTF { inline void AssetWriter::WriteFile(const char* path) { - bool isBinary = mAsset.extensionsUsed.KHR_binary_glTF; + std::unique_ptr jsonOutFile(mAsset.OpenFile(path, "wt", true)); - std::unique_ptr outfile - (mAsset.OpenFile(path, isBinary ? "wb" : "wt", true)); + if (jsonOutFile == 0) { + throw DeadlyExportError("Could not open output file: " + std::string(path)); + } + + StringBuffer docBuffer; + + PrettyWriter writer(docBuffer); + mDoc.Accept(writer); + + if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { + throw DeadlyExportError("Failed to write scene data!"); + } + + // Write buffer data to separate .bin files + for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) { + Ref b = mAsset.buffers.Get(i); + + std::string binPath = b->GetURI(); + + std::unique_ptr binOutFile(mAsset.OpenFile(binPath, "wb", true)); + + if (binOutFile == 0) { + throw DeadlyExportError("Could not open output file: " + binPath); + } + + if (b->byteLength > 0) { + if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) { + throw DeadlyExportError("Failed to write binary file: " + binPath); + } + } + } + } + + inline void AssetWriter::WriteGLBFile(const char* path) + { + std::unique_ptr outfile(mAsset.OpenFile(path, "wb", true)); if (outfile == 0) { throw DeadlyExportError("Could not open output file: " + std::string(path)); } - if (isBinary) { - // we will write the header later, skip its size - outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); - } + // we will write the header later, skip its size + outfile->Seek(sizeof(GLB_Header), aiOrigin_SET); StringBuffer docBuffer; - - bool pretty = true; - if (!isBinary && pretty) { - PrettyWriter writer(docBuffer); - mDoc.Accept(writer); - } - else { - Writer writer(docBuffer); - mDoc.Accept(writer); - } + Writer writer(docBuffer); + mDoc.Accept(writer); if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { - throw DeadlyExportError("Failed to write scene data!"); + throw DeadlyExportError("Failed to write scene data!"); } - if (isBinary) { - WriteBinaryData(outfile.get(), docBuffer.GetSize()); - } + WriteBinaryData(outfile.get(), docBuffer.GetSize()); } inline void AssetWriter::WriteBinaryData(IOStream* outfile, size_t sceneLength) @@ -385,7 +404,6 @@ namespace glTF { } } - // // write the header // diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index e333272be..e2681d0f1 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -137,9 +137,13 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc ExportScene(); - glTF::AssetWriter writer(*mAsset); - writer.WriteFile(filename); + + if (isBinary) { + writer.WriteGLBFile(filename); + } else { + writer.WriteFile(filename); + } } @@ -267,6 +271,15 @@ void glTFExporter::ExportMaterials() void glTFExporter::ExportMeshes() { + std::string fname = std::string(mFilename); + std::string bufferIdPrefix = fname.substr(0, fname.find(".")); + std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str()); + + Ref b = mAsset->GetBodyBuffer(); + if (!b) { + b = mAsset->buffers.Create(bufferId); + } + for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) { const aiMesh* aim = mScene->mMeshes[i]; @@ -277,13 +290,6 @@ void glTFExporter::ExportMeshes() p.material = mAsset->materials.Get(aim->mMaterialIndex); - std::string bufferId = mAsset->FindUniqueID(meshId, "buffer"); - - Ref b = mAsset->GetBodyBuffer(); - if (!b) { - b = mAsset->buffers.Create(bufferId); - } - Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if (v) p.attributes.position.push_back(v); From 3052f35824eb98f3a26ed89a9215622a41343025 Mon Sep 17 00:00:00 2001 From: johnmaf Date: Tue, 20 Sep 2016 14:15:42 -0400 Subject: [PATCH 2/2] glTF: move mesh splitting to constructor to cover GLB --- code/glTFExporter.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 45877c8a9..708570577 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -80,20 +80,9 @@ namespace Assimp { // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp void ExportSceneGLTF(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) { - aiScene* sceneCopy_tmp; - SceneCombiner::CopyScene(&sceneCopy_tmp, pScene); - std::unique_ptr sceneCopy(sceneCopy_tmp); - - SplitLargeMeshesProcess_Triangle tri_splitter; - tri_splitter.SetLimit(0xffff); - tri_splitter.Execute(sceneCopy.get()); - - SplitLargeMeshesProcess_Vertex vert_splitter; - vert_splitter.SetLimit(0xffff); - vert_splitter.Execute(sceneCopy.get()); // invoke the exporter - glTFExporter exporter(pFile, pIOSystem, sceneCopy.get(), pProperties, false); + glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, false); } // ------------------------------------------------------------------------------------------------ @@ -112,9 +101,22 @@ glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiSc const ExportProperties* pProperties, bool isBinary) : mFilename(filename) , mIOSystem(pIOSystem) - , mScene(pScene) , mProperties(pProperties) { + aiScene* sceneCopy_tmp; + SceneCombiner::CopyScene(&sceneCopy_tmp, pScene); + std::unique_ptr sceneCopy(sceneCopy_tmp); + + SplitLargeMeshesProcess_Triangle tri_splitter; + tri_splitter.SetLimit(0xffff); + tri_splitter.Execute(sceneCopy.get()); + + SplitLargeMeshesProcess_Vertex vert_splitter; + vert_splitter.SetLimit(0xffff); + vert_splitter.Execute(sceneCopy.get()); + + mScene = sceneCopy.get(); + std::unique_ptr asset(); mAsset.reset( new glTF::Asset( pIOSystem ) );