Merge pull request #1640 from wanadev/gltf2-exporter-improvements

Added support for generating glb2 (binary glTF 2)
pull/1641/head^2
Kim Kulling 2017-12-17 16:09:24 +01:00 committed by GitHub
commit 13dba835a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 3 deletions

View File

@ -92,6 +92,7 @@ void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperti
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
@ -151,6 +152,8 @@ Exporter::ExportFormatEntry gExporters[] =
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
#endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER

View File

@ -81,6 +81,7 @@ public:
AssetWriter(Asset& asset);
void WriteFile(const char* path);
void WriteGLBFile(const char* path);
};
}

View File

@ -561,6 +561,97 @@ namespace glTF2 {
}
}
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));
}
// Padding with spaces as required by the spec
uint32_t padding = 0x20202020;
// Adapt JSON so that it is not pointing to an external file,
// as this is required by the GLB spec'.
mDoc["buffers"][0].RemoveMember("uri");
//
// JSON chunk
//
StringBuffer docBuffer;
Writer<StringBuffer> writer(docBuffer);
mDoc.Accept(writer);
uint32_t jsonChunkLength = (docBuffer.GetSize() + 3) & ~3; // Round up to next multiple of 4
auto paddingLength = jsonChunkLength - docBuffer.GetSize();
GLB_Chunk jsonChunk;
jsonChunk.chunkLength = jsonChunkLength;
jsonChunk.chunkType = ChunkType_JSON;
AI_SWAP4(jsonChunk.chunkLength);
outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
if (outfile->Write(&jsonChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) {
throw DeadlyExportError("Failed to write scene data header!");
}
if (outfile->Write(docBuffer.GetString(), 1, docBuffer.GetSize()) != docBuffer.GetSize()) {
throw DeadlyExportError("Failed to write scene data!");
}
if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
throw DeadlyExportError("Failed to write scene data padding!");
}
//
// Binary chunk
//
uint32_t binaryChunkLength = 0;
if (mAsset.buffers.Size() > 0) {
Ref<Buffer> b = mAsset.buffers.Get(0u);
if (b->byteLength > 0) {
binaryChunkLength = (b->byteLength + 3) & ~3; // Round up to next multiple of 4
auto paddingLength = binaryChunkLength - b->byteLength;
GLB_Chunk binaryChunk;
binaryChunk.chunkLength = binaryChunkLength;
binaryChunk.chunkType = ChunkType_BIN;
AI_SWAP4(binaryChunk.chunkLength);
size_t bodyOffset = sizeof(GLB_Header) + sizeof(GLB_Chunk) + jsonChunk.chunkLength;
outfile->Seek(bodyOffset, aiOrigin_SET);
if (outfile->Write(&binaryChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) {
throw DeadlyExportError("Failed to write body data header!");
}
if (outfile->Write(b->GetPointer(), 1, b->byteLength) != b->byteLength) {
throw DeadlyExportError("Failed to write body data!");
}
if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
throw DeadlyExportError("Failed to write body data padding!");
}
}
}
//
// 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(GLB_Header) + 2 * sizeof(GLB_Chunk) + jsonChunkLength + binaryChunkLength);
AI_SWAP4(header.length);
outfile->Seek(0, aiOrigin_SET);
if (outfile->Write(&header, 1, sizeof(GLB_Header)) != sizeof(GLB_Header)) {
throw DeadlyExportError("Failed to write the header!");
}
}
inline void AssetWriter::WriteMetadata()
{
Value asset;

View File

@ -77,10 +77,18 @@ namespace Assimp {
glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, false);
}
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp
void ExportSceneGLB2(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{
// invoke the exporter
glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, true);
}
} // end of namespace Assimp
glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
const ExportProperties* pProperties, bool /*isBinary*/)
const ExportProperties* pProperties, bool isBinary)
: mFilename(filename)
, mIOSystem(pIOSystem)
, mProperties(pProperties)
@ -118,8 +126,12 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
AssetWriter writer(*mAsset);
if (isBinary) {
writer.WriteGLBFile(filename);
} else {
writer.WriteFile(filename);
}
}
/*
* Copy a 4x4 matrix from struct aiMatrix to typedef mat4.