Fix some import bugs / add support for separated model + anim file

This commit is contained in:
2026-06-22 01:37:16 +02:00
parent 7e5536a02f
commit 6f679e7329
10 changed files with 1514 additions and 34 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,138 @@
#ifndef MODELDOCUTILS_H
#define MODELDOCUTILS_H
#include "destrum/Util/ModelDoc.h"
#include "spdlog/spdlog.h"
#include <algorithm>
#include <filesystem>
#include <initializer_list>
#include <optional>
#include <stdexcept>
#include <string>
namespace ModelDocUtils {
inline const ModelDoc::MeshPrimitive& GetFirstPrimitiveOrThrow(
const ModelDoc::ModelAsset& model,
const std::string& debugName
) {
if (model.primitives.empty()) {
throw std::runtime_error("ModelDoc loaded no mesh primitives for: " + debugName);
}
return model.primitives.front();
}
inline const ModelDoc::MeshPrimitive& GetFirstSkinnedPrimitiveOrFirstOrThrow(
const ModelDoc::ModelAsset& model,
const std::string& debugName
) {
if (model.primitives.empty()) {
throw std::runtime_error("ModelDoc loaded no mesh primitives for: " + debugName);
}
const auto it = std::find_if(
model.primitives.begin(),
model.primitives.end(),
[](const ModelDoc::MeshPrimitive& primitive) {
return primitive.skinned;
}
);
return it != model.primitives.end() ? *it : model.primitives.front();
}
inline glm::vec3 GetImportedBaseColor(
const ModelDoc::ModelAsset& model,
const ModelDoc::MeshPrimitive& primitive,
const glm::vec3& fallback = glm::vec3(1.0f)
) {
if (primitive.materialIndex == ModelDoc::InvalidIndex ||
primitive.materialIndex >= model.materials.size()) {
return fallback;
}
return glm::vec3(model.materials[primitive.materialIndex].baseColor);
}
inline std::string GetImportedMaterialName(
const ModelDoc::ModelAsset& model,
const ModelDoc::MeshPrimitive& primitive,
const std::string& fallback
) {
if (primitive.materialIndex == ModelDoc::InvalidIndex ||
primitive.materialIndex >= model.materials.size()) {
return fallback;
}
const auto& material = model.materials[primitive.materialIndex];
return material.name.empty() ? fallback : material.name;
}
inline std::optional<std::string> FindFirstTexturePath(
const ModelDoc::ModelAsset& model,
const ModelDoc::MeshPrimitive& primitive,
std::initializer_list<ModelDoc::TextureSemantic> preferredSemantics
) {
if (primitive.materialIndex == ModelDoc::InvalidIndex ||
primitive.materialIndex >= model.materials.size()) {
return std::nullopt;
}
const auto& material = model.materials[primitive.materialIndex];
for (const auto semantic : preferredSemantics) {
for (const auto& texture : material.textures) {
// gfxDevice.loadImageFromFile currently expects a real file path.
// Embedded GLB textures like "*0" need extraction/support in GfxDevice first.
if (texture.semantic == semantic && !texture.embedded && !texture.path.empty()) {
return texture.path;
}
}
}
return std::nullopt;
}
inline std::filesystem::path PickTexturePath(
const ModelDoc::ModelAsset& model,
const ModelDoc::MeshPrimitive& primitive,
const std::filesystem::path& fallbackPath
) {
const auto importedTexturePath = FindFirstTexturePath(
model,
primitive,
{
ModelDoc::TextureSemantic::BaseColor,
ModelDoc::TextureSemantic::Diffuse
}
);
if (importedTexturePath.has_value()) {
return std::filesystem::path(*importedTexturePath);
}
spdlog::info("Using fallback path {}", fallbackPath.string());
return fallbackPath;
}
inline void LogModelDocSummary(
const ModelDoc::ModelAsset& model,
const std::string& label
) {
spdlog::info(
"Loaded {} | primitives: {} | materials: {} | animations: {} | skinned: {}",
label,
model.primitives.size(),
model.materials.size(),
model.animations.size(),
model.IsSkinned()
);
}
} // namespace ModelDocUtils
#endif // MODELDOCUTILS_H
@@ -768,6 +768,35 @@ static SkinnedModel LoadSkinnedModel(const std::string& path) {
return model;
}
struct LoadedMesh {
CPUMesh mesh;
std::vector<std::string> diffuseTexturePaths;
};
static std::vector<std::string> LoadMaterialTexturePaths(
const aiScene* scene,
const aiMesh* mesh,
aiTextureType type,
const std::filesystem::path& modelDir
) {
std::vector<std::string> paths;
if (mesh->mMaterialIndex >= scene->mNumMaterials)
return paths;
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
for (unsigned int i = 0; i < material->GetTextureCount(type); ++i) {
aiString texPath;
if (material->GetTexture(type, i, &texPath) == AI_SUCCESS) {
auto fullPath = modelDir / texPath.C_Str();
paths.push_back(fullPath.generic_string());
}
}
return paths;
}
} // namespace ModelLoader
#endif // MODELLOADER_H