From a8885c2728d44413be5329f9fb6a402a1d555fb2 Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Wed, 27 May 2026 19:36:41 +0800 Subject: [PATCH 1/2] fix(asset-loader): support MSFT DDS texture sources Co-Authored-By: GPT 5.5 --- AssetLoader/src/GLTFLoader.cpp | 97 +++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 3c17be30..28312752 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -1117,6 +1117,94 @@ void Model::InitMaterialTextureAddressingAttribs(Material& Mat, Uint32 TextureIn } } +namespace +{ + +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 GetMSFTTextureDDSSource(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 RemoveMSFTTextureDDSWarnings(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 (!GetMSFTTextureDDSSource(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 + 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 (GetMSFTTextureDDSSource(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); } + RemoveMSFTTextureDDSWarnings(gltf_model, LoaderData.BaseDir, warning); if (!warning.empty()) { LOG_WARNING_MESSAGE("Loaded gltf file ", filename, " with the following warning:", warning); From 398fe86e31764262abd6514564953dc130527e1f Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Mon, 1 Jun 2026 12:09:40 +0800 Subject: [PATCH 2/2] refactor(asset-loader): rename MSFT texture DDS helpers Co-Authored-By: GPT 5.5 --- AssetLoader/src/GLTFLoader.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 28312752..fa29aeb8 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -1117,7 +1117,7 @@ void Model::InitMaterialTextureAddressingAttribs(Material& Mat, Uint32 TextureIn } } -namespace +namespace MSFTTextureDDS { constexpr const char* MSFTTextureDDSExtension = "MSFT_texture_dds"; @@ -1139,10 +1139,10 @@ bool IsImageAvailable(const tinygltf::Image& gltf_image, const std::string& Base return FileSystem::FileExists(ImagePath.c_str()); } -bool GetMSFTTextureDDSSource(const tinygltf::Texture& gltf_tex, - const tinygltf::Model& gltf_model, - const std::string& BaseDir, - int& Source) +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()) @@ -1172,9 +1172,9 @@ void EraseAll(std::string& Str, const std::string& Substr) } } -void RemoveMSFTTextureDDSWarnings(const tinygltf::Model& gltf_model, - const std::string& BaseDir, - std::string& Warning) +void RemoveWarnings(const tinygltf::Model& gltf_model, + const std::string& BaseDir, + std::string& Warning) { if (Warning.empty()) return; @@ -1182,7 +1182,7 @@ void RemoveMSFTTextureDDSWarnings(const tinygltf::Model& gltf_model, for (const tinygltf::Texture& gltf_tex : gltf_model.textures) { int DDSSource = -1; - if (!GetMSFTTextureDDSSource(gltf_tex, gltf_model, BaseDir, DDSSource)) + if (!GetSource(gltf_tex, gltf_model, BaseDir, DDSSource)) continue; if (!IsValidImageSource(gltf_model, gltf_tex.source)) @@ -1203,7 +1203,7 @@ void RemoveMSFTTextureDDSWarnings(const tinygltf::Model& gltf_model, } } -} // namespace +} // namespace MSFTTextureDDS void Model::LoadTextures(IRenderDevice* pDevice, const tinygltf::Model& gltf_model, @@ -1217,7 +1217,7 @@ void Model::LoadTextures(IRenderDevice* pDevice, { int ImageSource = gltf_tex.source; int DDSSource = -1; - if (GetMSFTTextureDDSSource(gltf_tex, gltf_model, BaseDir, DDSSource)) + if (MSFTTextureDDS::GetSource(gltf_tex, gltf_model, BaseDir, DDSSource)) ImageSource = DDSSource; const tinygltf::Image& gltf_image = gltf_model.images[ImageSource]; @@ -2334,7 +2334,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, { LOG_ERROR_AND_THROW("Failed to load gltf file ", filename, ": ", error); } - RemoveMSFTTextureDDSWarnings(gltf_model, LoaderData.BaseDir, warning); + MSFTTextureDDS::RemoveWarnings(gltf_model, LoaderData.BaseDir, warning); if (!warning.empty()) { LOG_WARNING_MESSAGE("Loaded gltf file ", filename, " with the following warning:", warning);