feat: fix scene loading that it loads from disk if not already loaded
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
#ifndef DESTRUM_ASSETMANAGER_H
|
||||
#define DESTRUM_ASSETMANAGER_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <destrum/Graphics/SkeletalAnimation.h>
|
||||
#include <destrum/Graphics/Skeleton.h>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
#include <destrum/Singleton.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <destrum/Util/ModelDoc.h>
|
||||
|
||||
class AssetManager final : public Singleton<AssetManager> {
|
||||
public:
|
||||
friend class Singleton<AssetManager>;
|
||||
|
||||
[[nodiscard]] std::filesystem::path Resolve(std::string_view reference) const;
|
||||
|
||||
[[nodiscard]] ModelDoc::ModelAsset LoadModel(
|
||||
std::string_view reference,
|
||||
const ModelDoc::LoadOptions& options = {}) const;
|
||||
|
||||
[[nodiscard]] std::vector<SkeletalAnimation> LoadAnimationClips(
|
||||
std::string_view reference,
|
||||
const Skeleton& targetSkeleton) const;
|
||||
|
||||
private:
|
||||
AssetManager() = default;
|
||||
};
|
||||
|
||||
#endif // DESTRUM_ASSETMANAGER_H
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef DESTRUM_ASSETREFERENCE_H
|
||||
#define DESTRUM_ASSETREFERENCE_H
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
struct AssetReference {
|
||||
std::string path;
|
||||
std::string subresource;
|
||||
|
||||
[[nodiscard]] bool empty() const { return path.empty(); }
|
||||
|
||||
[[nodiscard]] std::string cacheKey() const {
|
||||
return path.empty() ? std::string{} : path + "#" + subresource;
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::optional<AssetReference> fromCacheKey(
|
||||
std::string_view key)
|
||||
{
|
||||
const auto separator = key.rfind('#');
|
||||
if (separator == std::string_view::npos ||
|
||||
separator == 0 ||
|
||||
separator + 1 >= key.size()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return AssetReference{
|
||||
.path = std::string{key.substr(0, separator)},
|
||||
.subresource = std::string{key.substr(separator + 1)},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DESTRUM_ASSETREFERENCE_H
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
void Deserialize(const nlohmann::json& data) override;
|
||||
void ImGuiInspector() override;
|
||||
|
||||
// The source reference is carried by the AssetManager-loaded clip.
|
||||
void addClip(std::shared_ptr<SkeletalAnimation> clip);
|
||||
void play(const std::string& name, float blendTime = 0.f);
|
||||
void stop();
|
||||
@@ -41,10 +42,15 @@ public:
|
||||
return &m_skeleton;
|
||||
}
|
||||
|
||||
// A source reference is required when this Animator is saved to a scene.
|
||||
void setSkeleton(Skeleton skeleton) {
|
||||
m_skeletonAsset = skeleton.assetReference;
|
||||
m_skeleton = std::move(skeleton);
|
||||
m_referencesResolved = true;
|
||||
}
|
||||
|
||||
void ResolveReferences(const ObjectMap& objects) override;
|
||||
|
||||
private:
|
||||
struct PlaybackState {
|
||||
SkeletalAnimation* clip = nullptr;
|
||||
@@ -59,14 +65,22 @@ private:
|
||||
float m_blendT = 0.f;
|
||||
float m_blendDuration = 0.f;
|
||||
std::string m_currentClipName;
|
||||
std::string m_previousClipName;
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<SkeletalAnimation>> m_clips;
|
||||
std::vector<std::string> m_clipOrder;
|
||||
std::unordered_map<std::string, AssetReference> m_clipAssets;
|
||||
AssetReference m_skeletonAsset;
|
||||
bool m_referencesResolved{true};
|
||||
|
||||
std::vector<glm::mat4> computeJointMatrices(const Skeleton& skeleton);
|
||||
|
||||
glm::vec3 sampleTranslation(const SkeletalAnimation::Track& track, float t);
|
||||
glm::quat sampleRotation (const SkeletalAnimation::Track& track, float t);
|
||||
glm::vec3 sampleScale (const SkeletalAnimation::Track& track, float t);
|
||||
|
||||
void RestorePlaybackState(const nlohmann::json& data);
|
||||
void LoadAssetReferences();
|
||||
};
|
||||
|
||||
#endif // ANIMATOR_H
|
||||
|
||||
@@ -28,10 +28,16 @@ public:
|
||||
void cleanup(GfxDevice& gfxDevice);
|
||||
|
||||
MaterialID addMaterial(Material material);
|
||||
MaterialID addSimpleColorMaterial(
|
||||
glm::vec3 color,
|
||||
std::string name = {});
|
||||
MaterialID addSimpleTextureMaterial(ImageID textureID);
|
||||
[[nodiscard]] const Material& getMaterial(MaterialID id) const;
|
||||
[[nodiscard]] const std::string& getMaterialKey(MaterialID id) const;
|
||||
[[nodiscard]] std::optional<MaterialID> findMaterialByKey(std::string_view key) const;
|
||||
[[nodiscard]] std::optional<MaterialID> findMaterialByName(
|
||||
std::string_view name,
|
||||
std::string_view sourceReference = {}) const;
|
||||
|
||||
[[nodiscard]] MaterialID getFreeMaterialId() const;
|
||||
[[nodiscard]] MaterialID getPlaceholderMaterialId() const;
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#define MATERIAL_H
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <glm/glm.hpp>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
|
||||
struct alignas(16) MaterialData {
|
||||
alignas(16) glm::vec4 baseColor;
|
||||
@@ -22,6 +24,19 @@ enum class TextureFilteringMode : std::uint32_t {
|
||||
};
|
||||
|
||||
struct Material {
|
||||
[[nodiscard]] static Material SimpleColor(
|
||||
glm::vec3 color,
|
||||
std::string materialName = {})
|
||||
{
|
||||
Material material{};
|
||||
material.baseColor = color;
|
||||
material.metallicFactor = 0.0f;
|
||||
material.roughnessFactor = 1.0f;
|
||||
material.emissiveFactor = 0.0f;
|
||||
material.name = std::move(materialName);
|
||||
return material;
|
||||
}
|
||||
|
||||
glm::vec3 baseColor{1.f, 1.f, 1.f};
|
||||
float metallicFactor{0.f};
|
||||
float roughnessFactor{0.7f};
|
||||
@@ -35,6 +50,7 @@ struct Material {
|
||||
// ImageId emissiveTexture{NULL_IMAGE_ID};
|
||||
|
||||
std::string name;
|
||||
AssetReference assetReference;
|
||||
};
|
||||
|
||||
#endif //MATERIAL_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
class GfxDevice;
|
||||
|
||||
@@ -44,6 +45,10 @@ public:
|
||||
|
||||
ImageID addImageToCache(GPUImage image);
|
||||
|
||||
// Imports a file-backed model and uploads its mesh/material resources.
|
||||
// References are keyed as "source#subresource" in the resource caches.
|
||||
void loadModelAsset(GfxDevice& gfxDevice, std::string_view sourceReference);
|
||||
|
||||
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
|
||||
|
||||
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
|
||||
@@ -72,4 +77,4 @@ private:
|
||||
ImageID defaultNormalImageId{NULL_IMAGE_ID};
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <destrum/Graphics/Resources/Buffer.h>
|
||||
#include <destrum/Graphics/Frustum.h>
|
||||
#include <destrum/Graphics/Skeleton.h>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
|
||||
// ─── CPU Mesh ─────────────────────────────────────────────────────────────────
|
||||
struct CPUMesh {
|
||||
@@ -36,6 +37,7 @@ struct CPUMesh {
|
||||
std::vector<SkinningData> skinningData; // empty if no skeleton
|
||||
|
||||
std::string name;
|
||||
AssetReference assetReference;
|
||||
|
||||
glm::vec3 minPos;
|
||||
glm::vec3 maxPos;
|
||||
@@ -115,4 +117,4 @@ inline std::vector<std::uint32_t> indices = {
|
||||
|
||||
} // namespace CubeMesh
|
||||
|
||||
#endif // MESH_H
|
||||
#endif // MESH_H
|
||||
|
||||
@@ -7,8 +7,11 @@
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
|
||||
struct SkeletalAnimation {
|
||||
AssetReference assetReference;
|
||||
|
||||
struct Keyframe {
|
||||
float time;
|
||||
glm::vec3 translation;
|
||||
@@ -32,4 +35,4 @@ struct SkeletalAnimation {
|
||||
const std::vector<std::string>& getEventsForFrame(int frame) const;
|
||||
};
|
||||
|
||||
#endif // SKELETALANIMATION_H
|
||||
#endif // SKELETALANIMATION_H
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <destrum/Graphics/ids.h>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
|
||||
struct Joint {
|
||||
JointId id{NULL_JOINT_ID};
|
||||
@@ -19,6 +20,8 @@ struct Joint {
|
||||
};
|
||||
|
||||
struct Skeleton {
|
||||
AssetReference assetReference;
|
||||
|
||||
struct JointNode {
|
||||
JointId id{NULL_JOINT_ID};
|
||||
std::vector<JointId> children;
|
||||
@@ -55,4 +58,4 @@ inline void buildParentIndex(Skeleton& skeleton) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SKELETON_H
|
||||
#endif // SKELETON_H
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <destrum/Graphics/Resources/Mesh.h>
|
||||
#include <destrum/Assets/AssetReference.h>
|
||||
#include <destrum/Graphics/SkeletalAnimation.h>
|
||||
#include <destrum/Graphics/Skeleton.h>
|
||||
|
||||
@@ -91,6 +92,7 @@ struct TextureInfo {
|
||||
|
||||
struct MaterialInfo {
|
||||
std::string name;
|
||||
AssetReference assetReference;
|
||||
|
||||
glm::vec4 baseColor{1.0f};
|
||||
glm::vec3 emissiveColor{0.0f};
|
||||
@@ -1018,6 +1020,24 @@ static ModelAsset LoadModel(const std::string& path, const LoadOptions& options
|
||||
CollectMergedPerNodeMeshes(scene, model.skeleton, options, model.primitives);
|
||||
}
|
||||
|
||||
model.skeleton.assetReference.path = model.sourcePath;
|
||||
for (std::size_t index = 0; index < model.primitives.size(); ++index) {
|
||||
auto& primitive = model.primitives[index];
|
||||
primitive.mesh.assetReference.path = model.sourcePath;
|
||||
primitive.mesh.assetReference.subresource = primitive.sourceMeshIndex != InvalidIndex
|
||||
? "mesh:" + std::to_string(primitive.sourceMeshIndex)
|
||||
: "primitive:" + std::to_string(index);
|
||||
}
|
||||
for (std::size_t index = 0; index < model.materials.size(); ++index) {
|
||||
model.materials[index].assetReference.path = model.sourcePath;
|
||||
model.materials[index].assetReference.subresource = "material:" + std::to_string(index);
|
||||
}
|
||||
for (std::size_t index = 0; index < model.animations.size(); ++index) {
|
||||
auto& animation = model.animations[index];
|
||||
animation.assetReference.path = model.sourcePath;
|
||||
animation.assetReference.subresource = "animation:" + std::to_string(index);
|
||||
}
|
||||
|
||||
std::cout << "[ModelDoc] Loaded model: " << path
|
||||
<< " | primitives: " << model.primitives.size()
|
||||
<< " | materials: " << model.materials.size()
|
||||
@@ -1121,7 +1141,13 @@ static const aiScene* LoadAnimationScene(
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = LoadAnimationScene(importer, path);
|
||||
|
||||
return LoadAnimations(scene, targetSkeleton);
|
||||
auto clips = LoadAnimations(scene, targetSkeleton);
|
||||
for (std::size_t index = 0; index < clips.size(); ++index) {
|
||||
auto& clip = clips[index];
|
||||
clip.assetReference.path = path;
|
||||
clip.assetReference.subresource = "animation:" + std::to_string(index);
|
||||
}
|
||||
return clips;
|
||||
}
|
||||
|
||||
} // namespace ModelDoc
|
||||
|
||||
Reference in New Issue
Block a user