diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index e52a35e5a..fa723066b 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -1,12 +1,15 @@ #include "stdafx.h" #include "ModelImporter.h" +#include "Utility/stb_image.h" + #define TINYGLTF_IMPLEMENTATION #define TINYGLTF_NO_STB_IMAGE #define TINYGLTF_NO_STB_IMAGE_WRITE #include "tiny_gltf.h" #include +#include using namespace std; using namespace wiGraphicsTypes; @@ -27,9 +30,66 @@ namespace tinygltf else { // embedded image - assert(0); // TODO - return false; + + // We will load the texture2d by hand here and register to the resource manager + { + // png, tga, jpg, etc. loader: + + const int channelCount = 4; + int width, height, bpp; + unsigned char* rgb = stbi_load_from_memory(bytes, size, &width, &height, &bpp, channelCount); + + if (rgb != nullptr) + { + TextureDesc desc; + desc.ArraySize = 1; + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + desc.CPUAccessFlags = 0; + desc.Format = FORMAT_R8G8B8A8_UNORM; + desc.Height = static_cast(height); + desc.Width = static_cast(width); + desc.MipLevels = (UINT)log2(max(width, height)); + desc.MiscFlags = 0; + desc.Usage = USAGE_DEFAULT; + + UINT mipwidth = width; + SubresourceData* InitData = new SubresourceData[desc.MipLevels]; + for (UINT mip = 0; mip < desc.MipLevels; ++mip) + { + InitData[mip].pSysMem = rgb; + InitData[mip].SysMemPitch = static_cast(mipwidth * channelCount); + mipwidth = max(1, mipwidth / 2); + } + + Texture2D* tex = new Texture2D; + tex->RequestIndependentShaderResourcesForMIPs(true); + tex->RequestIndependentUnorderedAccessResourcesForMIPs(true); + HRESULT hr = wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData, &tex); + assert(SUCCEEDED(hr)); + + if (tex != nullptr) + { + wiRenderer::AddDeferredMIPGen(tex); + + if (image->name.empty()) + { + static UINT imgcounter = 0; + stringstream ss(""); + ss << "gltfLoader_embedded_image" << imgcounter++; + image->name = ss.str(); + } + // We loaded the texture2d, so register to the resource manager to be retrieved later: + wiResourceManager::GetGlobal()->Register(image->name, tex, wiResourceManager::IMAGE); + } + } + + free(rgb); + } + + return true; } + + return false; } bool WriteImageData(const std::string *basepath, const std::string *filename, @@ -101,27 +161,64 @@ Model* ImportModel_GLTF(const std::string& fileName) { auto& tex = gltfModel.textures[baseColorTexture->second.TextureIndex()]; auto& img = gltfModel.images[tex.source]; - material->textureName = directory + img.uri; - if (!material->textureName.empty()) - material->texture = (Texture2D*)wiResourceManager::GetGlobal()->add(material->textureName); + if (img.uri.empty()) + { + // embedded image + material->textureName = img.name; + } + else + { + //external image + material->textureName = directory + img.uri; + } } + else if(!gltfModel.images.empty()) + { + // For some reason, we don't have diffuse texture, but have other textures + // I have a problem, because one model viewer displays textures on a model which has no basecolor set in its material... + // This is probably not how it should be (todo) + material->textureName = gltfModel.images[0].name; + } + if (normalTexture != x.additionalValues.end()) { auto& tex = gltfModel.textures[normalTexture->second.TextureIndex()]; auto& img = gltfModel.images[tex.source]; - material->normalMapName = directory + img.uri; - if (!material->normalMapName.empty()) - material->normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->normalMapName); + if (img.uri.empty()) + { + // embedded image + material->normalMapName = img.name; + } + else + { + //external image + material->normalMapName = directory + img.uri; + } } if (emissiveTexture != x.additionalValues.end()) { auto& tex = gltfModel.textures[emissiveTexture->second.TextureIndex()]; auto& img = gltfModel.images[tex.source]; - material->surfaceMapName = directory + img.uri; - if (!material->surfaceMapName.empty()) - material->surfaceMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->surfaceMapName); + if (img.uri.empty()) + { + // embedded image + material->surfaceMapName = img.name; + } + else + { + //external image + material->surfaceMapName = directory + img.uri; + } } + // Retrieve textures by name: + if (!material->textureName.empty()) + material->texture = (Texture2D*)wiResourceManager::GetGlobal()->add(material->textureName); + if (!material->normalMapName.empty()) + material->normalMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->normalMapName); + if (!material->surfaceMapName.empty()) + material->surfaceMap = (Texture2D*)wiResourceManager::GetGlobal()->add(material->surfaceMapName); + if (baseColorFactor != x.values.end()) { material->baseColor.x = static_cast(baseColorFactor->second.ColorFactor()[0]); @@ -439,7 +536,6 @@ Model* ImportModel_GLTF(const std::string& fileName) { for (size_t i = 0; i < count; i += 3) { - // reorder indices: mesh->indices[offset + i + 0] = data[i + 0]; mesh->indices[offset + i + 1] = data[i + 2]; mesh->indices[offset + i + 2] = data[i + 1]; @@ -449,7 +545,6 @@ Model* ImportModel_GLTF(const std::string& fileName) { for (size_t i = 0; i < count; i += 3) { - // reorder indices: mesh->indices[offset + i + 0] = ((uint16_t*)data)[i + 0]; mesh->indices[offset + i + 1] = ((uint16_t*)data)[i + 2]; mesh->indices[offset + i + 2] = ((uint16_t*)data)[i + 1]; @@ -459,7 +554,6 @@ Model* ImportModel_GLTF(const std::string& fileName) { for (size_t i = 0; i < count; i += 3) { - // reorder indices: mesh->indices[offset + i + 0] = ((uint32_t*)data)[i + 0]; mesh->indices[offset + i + 1] = ((uint32_t*)data)[i + 2]; mesh->indices[offset + i + 2] = ((uint32_t*)data)[i + 1]; @@ -486,7 +580,7 @@ Model* ImportModel_GLTF(const std::string& fileName) if (subset.material == nullptr) { - subset.material = new Material("gltfLoader-defaultMat"); + subset.material = new Material("gltfLoader_defaultMat"); } mesh->subsets.push_back(subset); diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index cd441a867..8256a1f02 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -10,7 +10,14 @@ using namespace std; using namespace wiGraphicsTypes; -wiResourceManager::filetypes wiResourceManager::types; +static const std::map types = { + std::pair("JPG", wiResourceManager::IMAGE), + std::pair("PNG", wiResourceManager::IMAGE), + std::pair("DDS", wiResourceManager::IMAGE), + std::pair("TGA", wiResourceManager::IMAGE), + std::pair("WAV", wiResourceManager::SOUND) +}; + wiResourceManager* wiResourceManager::globalResources = nullptr; wiResourceManager::wiResourceManager():wiThreadSafeManager() @@ -39,20 +46,11 @@ wiResourceManager* wiResourceManager::GetShaderManager() return shaderManager; } -void wiResourceManager::SetUp() -{ - types.clear(); - types.insert(pair("JPG", IMAGE)); - types.insert(pair("PNG", IMAGE)); - types.insert(pair("DDS", IMAGE)); - types.insert(pair("TGA", IMAGE)); - types.insert(pair("WAV", SOUND)); -} const wiResourceManager::Resource* wiResourceManager::get(const wiHashString& name, bool incRefCount) { LOCK(); - container::iterator it = resources.find(name); + auto& it = resources.find(name); if (it != resources.end()) { if(incRefCount) @@ -67,9 +65,6 @@ const wiResourceManager::Resource* wiResourceManager::get(const wiHashString& na void* wiResourceManager::add(const wiHashString& name, Data_Type newType) { - if (types.empty()) - SetUp(); - const Resource* res = get(name,true); if(!res) { @@ -79,7 +74,7 @@ void* wiResourceManager::add(const wiHashString& name, Data_Type newType) // dynamic type selection: if(newType==Data_Type::DYNAMIC){ - filetypes::iterator it = types.find(ext); + auto& it = types.find(ext); if(it!=types.end()) type = it->second; else @@ -231,15 +226,16 @@ void* wiResourceManager::add(const wiHashString& name, Data_Type newType) image = new Texture2D; image->RequestIndependentShaderResourcesForMIPs(true); image->RequestIndependentUnorderedAccessResourcesForMIPs(true); - wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData, &image); + HRESULT hr = wiRenderer::GetDevice()->CreateTexture2D(&desc, InitData, &image); + assert(SUCCEEDED(hr)); + + if (image != nullptr) + { + wiRenderer::AddDeferredMIPGen(image); + } } stbi_image_free(rgb); - - if (image != nullptr) - { - wiRenderer::AddDeferredMIPGen(image); - } } success = image; @@ -367,7 +363,7 @@ bool wiResourceManager::del(const wiHashString& name, bool forceDelete) { LOCK(); Resource* res = nullptr; - container::iterator it = resources.find(name); + auto& it = resources.find(name); if (it != resources.end()) res = it->second; else @@ -428,6 +424,20 @@ bool wiResourceManager::del(const wiHashString& name, bool forceDelete) return false; } +bool wiResourceManager::Register(const wiHashString& name, void* resource, Data_Type newType) +{ + LOCK(); + if (resources.find(name) == resources.end()) + { + resources.insert(make_pair(name, new Resource(resource, newType))); + UNLOCK(); + return true; + } + UNLOCK(); + + return false; +} + bool wiResourceManager::CleanUp() { wiRenderer::GetDevice()->WaitForGPU(); diff --git a/WickedEngine/wiResourceManager.h b/WickedEngine/wiResourceManager.h index cb5fdb52b..1cb7de133 100644 --- a/WickedEngine/wiResourceManager.h +++ b/WickedEngine/wiResourceManager.h @@ -7,8 +7,6 @@ #include #include -class wiSound; - class wiResourceManager : public wiThreadSafeManager { public: @@ -35,14 +33,10 @@ public: refCount = 1; }; }; - typedef std::unordered_map container; - container resources; + std::unordered_map resources; protected: -typedef std::map filetypes; -static filetypes types; static wiResourceManager* globalResources; -static void SetUp(); public: @@ -55,6 +49,7 @@ public: //specify datatype for shaders void* add(const wiHashString& name, Data_Type newType = Data_Type::DYNAMIC); bool del(const wiHashString& name, bool forceDelete = false); + bool Register(const wiHashString& name, void* resource, Data_Type newType); bool CleanUp(); };