Fix some import bugs / add support for separated model + anim file
This commit is contained in:
Binary file not shown.
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
|
||||
|
||||
Reference in New Issue
Block a user