diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 3c17be30..fa29aeb8 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -1117,6 +1117,94 @@ void Model::InitMaterialTextureAddressingAttribs(Material& Mat, Uint32 TextureIn } } +namespace MSFTTextureDDS +{ + +constexpr const char* MSFTTextureDDSExtension = "MSFT_texture_dds"; + +bool IsValidImageSource(const tinygltf::Model& gltf_model, int Source) +{ + return Source >= 0 && Source < static_cast(gltf_model.images.size()); +} + +bool IsImageAvailable(const tinygltf::Image& gltf_image, const std::string& BaseDir) +{ + if (!gltf_image.image.empty() || gltf_image.bufferView >= 0) + return true; + + if (gltf_image.uri.empty()) + return false; + + const std::string ImagePath = FileSystem::SimplifyPath((BaseDir + gltf_image.uri).c_str()); + return FileSystem::FileExists(ImagePath.c_str()); +} + +bool GetSource(const tinygltf::Texture& gltf_tex, + const tinygltf::Model& gltf_model, + const std::string& BaseDir, + int& Source) +{ + const auto ExtIt = gltf_tex.extensions.find(MSFTTextureDDSExtension); + if (ExtIt == gltf_tex.extensions.end() || !ExtIt->second.IsObject()) + return false; + + const tinygltf::Value& SourceValue = ExtIt->second.Get("source"); + if (!SourceValue.IsInt()) + return false; + + const int DDSSource = SourceValue.GetNumberAsInt(); + if (!IsValidImageSource(gltf_model, DDSSource)) + return false; + + if (!IsImageAvailable(gltf_model.images[DDSSource], BaseDir)) + return false; + + Source = DDSSource; + return true; +} + +void EraseAll(std::string& Str, const std::string& Substr) +{ + size_t Pos = 0; + while ((Pos = Str.find(Substr, Pos)) != std::string::npos) + { + Str.erase(Pos, Substr.length()); + } +} + +void RemoveWarnings(const tinygltf::Model& gltf_model, + const std::string& BaseDir, + std::string& Warning) +{ + if (Warning.empty()) + return; + + for (const tinygltf::Texture& gltf_tex : gltf_model.textures) + { + int DDSSource = -1; + if (!GetSource(gltf_tex, gltf_model, BaseDir, DDSSource)) + continue; + + if (!IsValidImageSource(gltf_model, gltf_tex.source)) + continue; + + const tinygltf::Image& StandardImage = gltf_model.images[gltf_tex.source]; + if (StandardImage.uri.empty()) + continue; + + const std::string StandardImagePath = FileSystem::SimplifyPath((BaseDir + StandardImage.uri).c_str()); + if (FileSystem::FileExists(StandardImagePath.c_str())) + continue; + + EraseAll(Warning, FormatString("File not found : ", StandardImage.uri, "\n")); + EraseAll(Warning, FormatString("File not found : ", StandardImage.uri)); + EraseAll(Warning, FormatString("Failed to load external 'uri' for image[", gltf_tex.source, "] name = \"", StandardImage.uri, "\"\n")); + EraseAll(Warning, FormatString("Failed to load external 'uri' for image[", gltf_tex.source, "] name = \"", StandardImage.uri, "\"")); + } +} + +} // namespace MSFTTextureDDS + void Model::LoadTextures(IRenderDevice* pDevice, const tinygltf::Model& gltf_model, const std::string& BaseDir, @@ -1127,7 +1215,12 @@ void Model::LoadTextures(IRenderDevice* pDevice, Textures.reserve(gltf_model.textures.size()); for (const tinygltf::Texture& gltf_tex : gltf_model.textures) { - const tinygltf::Image& gltf_image = gltf_model.images[gltf_tex.source]; + int ImageSource = gltf_tex.source; + int DDSSource = -1; + if (MSFTTextureDDS::GetSource(gltf_tex, gltf_model, BaseDir, DDSSource)) + ImageSource = DDSSource; + + const tinygltf::Image& gltf_image = gltf_model.images[ImageSource]; const std::string CacheId = !gltf_image.uri.empty() ? FileSystem::SimplifyPath((BaseDir + gltf_image.uri).c_str()) : ""; ImageData Image; @@ -1877,7 +1970,6 @@ struct LoaderData ModelCreateInfo::ReadWholeFileCallbackType ReadWholeFile = nullptr; }; - bool LoadImageData(tinygltf::Image* gltf_image, const int gltf_image_idx, std::string* error, @@ -2242,6 +2334,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, { LOG_ERROR_AND_THROW("Failed to load gltf file ", filename, ": ", error); } + MSFTTextureDDS::RemoveWarnings(gltf_model, LoaderData.BaseDir, warning); if (!warning.empty()) { LOG_WARNING_MESSAGE("Loaded gltf file ", filename, " with the following warning:", warning);