From 85909b2a9fc470d0f425fed5962bb8fc5a5fde57 Mon Sep 17 00:00:00 2001 From: s-ol Date: Wed, 31 Mar 2021 15:53:23 +0200 Subject: implement loading GLTF files from memory --- AssetLoader/include/GLTFLoader.hpp | 11 +++++ AssetLoader/interface/GLTFLoader.h | 27 ++++++++++++ AssetLoader/src/GLTFLoader.cpp | 90 ++++++++++++++++++++++++++++++++++---- 3 files changed, 119 insertions(+), 9 deletions(-) (limited to 'AssetLoader') diff --git a/AssetLoader/include/GLTFLoader.hpp b/AssetLoader/include/GLTFLoader.hpp index 83b9a4d..2b9afaf 100644 --- a/AssetLoader/include/GLTFLoader.hpp +++ b/AssetLoader/include/GLTFLoader.hpp @@ -391,6 +391,17 @@ private: IDeviceContext* pContext, const IGLTFModelCreateInfo& CI); + void LoadFromMemory(IRenderDevice* pDevice, + IDeviceContext* pContext, + const IGLTFModelCreateInfo& CI); + + void LoadScene(IRenderDevice* pDevice, + const tinygltf::Model& gltf_model, + const std::string& BaseDir, + GLTF_TextureCacheType* pTextureCache, + ResourceManager* pResourceMgr, + const IGLTFModelCreateInfo& CI); + void LoadNode(Node* parent, const tinygltf::Node& gltf_node, uint32_t nodeIndex, diff --git a/AssetLoader/interface/GLTFLoader.h b/AssetLoader/interface/GLTFLoader.h index 810a7c4..402559e 100644 --- a/AssetLoader/interface/GLTFLoader.h +++ b/AssetLoader/interface/GLTFLoader.h @@ -100,12 +100,39 @@ typedef enum GLTF_BUFFER_ID GLTF_BUFFER_ID; struct GLTF_TextureCacheType; typedef struct GLTF_TextureCacheType GLTF_TextureCacheType; +enum GLTF_FILE_TYPE +{ + GLTF_FILE_TYPE_UNKNOWN = 0, + GLTF_FILE_TYPE_ASCII, + GLTF_FILE_TYPE_BINARY, +}; +typedef enum GLTF_FILE_TYPE GLTF_FILE_TYPE; + /// Model create information struct IGLTFModelCreateInfo { /// File name + + /// If FileName is provided, Data member must be null const char* FileName DEFAULT_INITIALIZER(nullptr); + /// In-memory GLTF Data + + /// If Data is provided, FileName member must be null + const void* Data DEFAULT_INITIALIZER(nullptr); + + /// In-memory GLTF Data length + + /// Data size (in bytes) must be provided if Data is not null + size_t DataSize DEFAULT_INITIALIZER(0); + + /// File type + + /// If GLTF_FILE_TYPE_UNKNOWN and File name is provided, this + /// is detected based on the file extension (.gltf / .glb). + /// If Data is provided, this must not be GLTF_FILE_TYPE_UNKNOWN. + GLTF_FILE_TYPE FileType DEFAULT_INITIALIZER(GLTF_FILE_TYPE_UNKNOWN); + /// Optional texture cache to use when loading the model. /// The loader will try to find all the textures in the cache /// and add all new textures to the cache. diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 1c546f7..9fabac2 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -250,7 +250,13 @@ Model::Model(IRenderDevice* pDevice, IDeviceContext* pContext, const IGLTFModelCreateInfo& CI) { - LoadFromFile(pDevice, pContext, CI); + if (CI.FileName) { + LoadFromFile(pDevice, pContext, CI); + } else if (CI.Data) { + LoadFromMemory(pDevice, pContext, CI); + } else { + LOG_ERROR_AND_THROW("Either File Name or Data must be set"); + } } Model::~Model() @@ -1753,14 +1759,85 @@ void Model::LoadFromFile(IRenderDevice* pDevice, LOG_WARNING_MESSAGE("Loaded gltf file ", filename, " with the following warning:", warning); } - LoadTextureSamplers(pDevice, gltf_model); - LoadTextures(pDevice, gltf_model, LoaderData.BaseDir, pTextureCache, pResourceMgr); - LoadMaterials(gltf_model); + LoadScene(pDevice, gltf_model, LoaderData.BaseDir, pTextureCache, pResourceMgr, CI); + + if (pContext != nullptr) + { + PrepareGPUResources(pDevice, pContext); + } +} + +void Model::LoadFromMemory(IRenderDevice* pDevice, + IDeviceContext* pContext, + const IGLTFModelCreateInfo& CI) +{ + if (CI.Data == nullptr || CI.DataSize == 0) + LOG_ERROR_AND_THROW("Data must not be empty"); + auto* const pTextureCache = CI.pTextureCache; + auto* const pResourceMgr = CI.pCacheInfo != nullptr ? CI.pCacheInfo->pResourceMgr : nullptr; + if (CI.pTextureCache != nullptr && pResourceMgr != nullptr) + LOG_WARNING_MESSAGE("Texture cache is ignored when resource manager is used"); + + Callbacks::ImageLoaderData LoaderData{pTextureCache, pResourceMgr}; + LoaderData.BaseDir = ""; + + tinygltf::TinyGLTF gltf_context; + gltf_context.SetImageLoader(Callbacks::LoadImageData, &LoaderData); + + bool binary; + switch (CI.FileType) { + case GLTF_FILE_TYPE_UNKNOWN: + LOG_ERROR_AND_THROW("FileType must not be UNKNOWN when loading from memory"); + case GLTF_FILE_TYPE_ASCII: + binary = false; + break; + case GLTF_FILE_TYPE_BINARY: + binary = true; + break; + } + + std::string error; + std::string warning; + tinygltf::Model gltf_model; + + bool modelLoaded = false; + if (binary) + modelLoaded = gltf_context.LoadBinaryFromMemory(&gltf_model, &error, &warning, (const unsigned char*)CI.Data, CI.DataSize); + else + modelLoaded = gltf_context.LoadASCIIFromString(&gltf_model, &error, &warning, (const char*)CI.Data, CI.DataSize, ""); + if (!modelLoaded) + { + LOG_ERROR_AND_THROW("Failed to load gltf file from memory: ", error); + } + if (!warning.empty()) + { + LOG_WARNING_MESSAGE("Loaded gltf file from memory with the following warning:", warning); + } + + LoadScene(pDevice, gltf_model, "", pTextureCache, pResourceMgr, CI); + + if (pContext != nullptr) + { + PrepareGPUResources(pDevice, pContext); + } +} + +void Model::LoadScene(IRenderDevice* pDevice, + const tinygltf::Model& gltf_model, + const std::string& BaseDir, + GLTF_TextureCacheType* pTextureCache, + ResourceManager* pResourceMgr, + const IGLTFModelCreateInfo& CI) +{ std::vector IndexData; std::vector VertexBasicData; std::vector VertexSkinData; + LoadTextureSamplers(pDevice, gltf_model); + LoadTextures(pDevice, gltf_model, BaseDir, pTextureCache, pResourceMgr); + LoadMaterials(gltf_model); + // TODO: scene handling with no default scene const tinygltf::Scene& scene = gltf_model.scenes[gltf_model.defaultScene > -1 ? gltf_model.defaultScene : 0]; for (size_t i = 0; i < scene.nodes.size(); i++) @@ -1854,11 +1931,6 @@ void Model::LoadFromFile(IRenderDevice* pDevice, CreateBuffer(GLTF_BUFFER_ID_INDEX, IndexData.data(), IndexData.size() * sizeof(IndexData[0]), BIND_INDEX_BUFFER, "GLTF index buffer"); } - - if (pContext != nullptr) - { - PrepareGPUResources(pDevice, pContext); - } } void Model::CalculateBoundingBox(Node* node, const Node* parent) -- cgit v1.2.3