The tingygltf library has recently been used in writing osgb tilted data publishing tools. This library relies on json.hpp. The current version is 2.2, in which gltf data serialization functions have been ingested. Instead, it still saves writing JSON to a file as a gltf data function. In fact, the serialization function is still used in osgb data publishing. In the old version of tinygltf library, the serialization function is as follows.
std::string TinyGLTF::Serialize(Model *model) { json output; // ACCESSORS json accessors; for (unsigned int i = 0; i < model->accessors.size(); ++i) { json accessor; SerializeGltfAccessor(model->accessors[i], accessor); accessors.push_back(accessor); } output["accessors"] = accessors; // ANIMATIONS if (model->animations.size()) { json animations; for (unsigned int i = 0; i < model->animations.size(); ++i) { if (model->animations[i].channels.size()) { json animation; SerializeGltfAnimation(model->animations[i], animation); animations.push_back(animation); } } output["animations"] = animations; } // ASSET json asset; SerializeGltfAsset(model->asset, asset); output["asset"] = asset; // BUFFERS (We expect only one buffer here) json buffers; for (unsigned int i = 0; i < model->buffers.size(); ++i) { json buffer; SerializeNumberProperty("byteLength", model->buffers[i].data.size(), buffer); if (model->buffers[i].name.size()) SerializeStringProperty("name", model->buffers[i].name, buffer); buffers.push_back(buffer); } output["buffers"] = buffers; // BUFFERVIEWS json bufferViews; for (unsigned int i = 0; i < model->bufferViews.size(); ++i) { json bufferView; SerializeGltfBufferView(model->bufferViews[i], bufferView); bufferViews.push_back(bufferView); } output["bufferViews"] = bufferViews; // Extensions used if (model->extensionsUsed.size()) { SerializeStringArrayProperty("extensionsUsed", model->extensionsUsed, output); } // Extensions required if (model->extensionsRequired.size()) { SerializeStringArrayProperty("extensionsRequired", model->extensionsRequired, output); } // IMAGES if (model->images.size()) { json images; for (unsigned int i = 0; i < model->images.size(); ++i) { json image; SerializeGltfImage(model->images[i], image); images.push_back(image); } output["images"] = images; } // MATERIALS if (model->materials.size()) { json materials; for (unsigned int i = 0; i < model->materials.size(); ++i) { json material; SerializeGltfMaterial(model->materials[i], material); materials.push_back(material); } output["materials"] = materials; } // SHADER { for (auto& shader : model->shaders) { json val; val["bufferView"] = shader.bufferView; val["type"] = shader.type; output["shaders"].push_back(val); } } // PROGREAM { for (auto& prog : model->programs) { json val = json::parse(prog.prog_string); output["programs"].push_back(val); } } // TECHNICH { for (auto& tech : model->techniques) { json val = json::parse(tech.tech_string); output["techniques"].push_back(val); } } // MESHES json meshes; for (unsigned int i = 0; i < model->meshes.size(); ++i) { json mesh; SerializeGltfMesh(model->meshes[i], mesh); meshes.push_back(mesh); } output["meshes"] = meshes; // NODES json nodes; for (unsigned int i = 0; i < model->nodes.size(); ++i) { json node; SerializeGltfNode(model->nodes[i], node); nodes.push_back(node); } output["nodes"] = nodes; // SCENE SerializeNumberProperty<int>("scene", model->defaultScene, output); // SCENES json scenes; for (unsigned int i = 0; i < model->scenes.size(); ++i) { json currentScene; SerializeGltfScene(model->scenes[i], currentScene); scenes.push_back(currentScene); } output["scenes"] = scenes; // SKINS if (model->skins.size()) { json skins; for (unsigned int i = 0; i < model->skins.size(); ++i) { json skin; SerializeGltfSkin(model->skins[i], skin); skins.push_back(skin); } output["skins"] = skins; } // TEXTURES if (model->textures.size()) { json textures; for (unsigned int i = 0; i < model->textures.size(); ++i) { json texture; SerializeGltfTexture(model->textures[i], texture); textures.push_back(texture); } output["textures"] = textures; } // SAMPLERS if (model->samplers.size()) { json samplers; for (unsigned int i = 0; i < model->samplers.size(); ++i) { json sampler; SerializeGltfSampler(model->samplers[i], sampler); samplers.push_back(sampler); } output["samplers"] = samplers; } // CAMERAS if (model->cameras.size()) { json cameras; for (unsigned int i = 0; i < model->cameras.size(); ++i) { json camera; SerializeGltfCamera(model->cameras[i], camera); cameras.push_back(camera); } output["cameras"] = cameras; } // LIGHTS if (model->lights.size()) { json lights; for (unsigned int i = 0; i < model->lights.size(); ++i) { json light; SerializeGltfLight(model->lights[i], light); lights.push_back(light); } output["lights"] = lights; } std::string json_out = output.dump(); while (json_out.size() % 4 != 0) { json_out.push_back(0x20); } std::string bin_out; std::string final_buf; uint32_t json_length = json_out.size(); uint32_t bin_length = 0; // we will append mesh\image\shader\.. into BIN if (model->buffers.size() > 0) { auto& buffer_data = model->buffers[0].data; bin_out.append(buffer_data.data(), buffer_data.data() + buffer_data.size()); while (bin_out.size() % 4 != 0) { bin_out.push_back(0x00); } bin_length = buffer_data.size(); } final_buf += "glTF"; int version = 2; final_buf.append((char*)&version, (char*)&version + 4); int total_len = 12 + 16 + json_length + bin_length; final_buf.append((char*)&total_len, (char*)&total_len + 4); // JSON final_buf.append((char*)&json_length, (char*)&json_length + 4); final_buf += "JSON"; final_buf.append(json_out.data(), json_out.data() + json_out.size()); // BIN final_buf.append((char*)&bin_length, (char*)&bin_length + 4); final_buf += "BIN"; final_buf.push_back(0x00); final_buf.append(bin_out.data(), bin_out.data() + bin_out.size()); return final_buf; }
This function is very useful, but I don't know why it was cut out in the new edition. But it can still be written in the new edition. Most of them are implemented for texture, buffering, buffering views, cameras and shaders.