From b5d73ce389e24bf1df23fae86668627e1d51cbe7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 24 Mar 2013 01:03:21 +0100 Subject: [PATCH] Added ModelLoader Changed Model::SetMesh behavior Former-commit-id: b1c937b22bcebeef8b8fc42ff061dbf8ece8d2f1 --- include/Nazara/3D/Model.hpp | 20 +++-- src/Nazara/3D/3D.cpp | 7 ++ src/Nazara/3D/Loaders/Mesh.hpp | 15 ++++ src/Nazara/3D/Loaders/Mesh/Loader.cpp | 89 ++++++++++++++++++++ src/Nazara/3D/Model.cpp | 113 +++++++++----------------- 5 files changed, 164 insertions(+), 80 deletions(-) create mode 100644 src/Nazara/3D/Loaders/Mesh.hpp create mode 100644 src/Nazara/3D/Loaders/Mesh/Loader.cpp diff --git a/include/Nazara/3D/Model.hpp b/include/Nazara/3D/Model.hpp index b8cb11693..9130018b8 100644 --- a/include/Nazara/3D/Model.hpp +++ b/include/Nazara/3D/Model.hpp @@ -9,22 +9,30 @@ #include #include +#include #include #include #include #include -struct NzModelParameters +struct NAZARA_API NzModelParameters { bool loadAnimation = true; bool loadMaterials = true; NzAnimationParams animation; NzMaterialParams material; NzMeshParams mesh; + + bool IsValid() const; }; +class NzModel; + +using NzModelLoader = NzResourceLoader; + class NAZARA_API NzModel : public NzSceneNode, public NzUpdatable { + friend NzModelLoader; friend class NzScene; public: @@ -56,16 +64,16 @@ class NAZARA_API NzModel : public NzSceneNode, public NzUpdatable bool IsAnimationEnabled() const; bool IsDrawEnabled() const; - bool LoadFromFile(const NzString& meshPath, const NzModelParameters& modelParameters = NzModelParameters()); - bool LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& modelParameters = NzModelParameters()); - bool LoadFromStream(NzInputStream& stream, const NzModelParameters& modelParameters = NzModelParameters()); + bool LoadFromFile(const NzString& filePath, const NzModelParameters& params = NzModelParameters()); + bool LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& params = NzModelParameters()); + bool LoadFromStream(NzInputStream& stream, const NzModelParameters& params = NzModelParameters()); void Reset(); bool SetAnimation(NzAnimation* animation); void SetMaterial(unsigned int matIndex, NzMaterial* material); void SetMaterial(unsigned int skinIndex, unsigned int matIndex, NzMaterial* material); - void SetMesh(NzMesh* mesh, const NzModelParameters& parameters = NzModelParameters()); + void SetMesh(NzMesh* mesh); bool SetSequence(const NzString& sequenceName); void SetSequence(unsigned int sequenceIndex); void SetSkin(unsigned int skin); @@ -97,6 +105,8 @@ class NAZARA_API NzModel : public NzSceneNode, public NzUpdatable unsigned int m_nextFrame; unsigned int m_skin; unsigned int m_skinCount; + + static NzModelLoader::LoaderList s_loaders; }; #endif // NAZARA_MODEL_HPP diff --git a/src/Nazara/3D/3D.cpp b/src/Nazara/3D/3D.cpp index 2af1a57e9..d2ceb6be9 100644 --- a/src/Nazara/3D/3D.cpp +++ b/src/Nazara/3D/3D.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,9 @@ bool Nz3D::Initialize() // Initialisation du module + // Loaders + NzLoaders_Mesh_Register(); + NazaraNotice("Initialized: 3D module"); return true; @@ -50,6 +54,9 @@ void Nz3D::Uninitialize() // Libération du module s_moduleReferenceCounter = 0; + // Loaders + NzLoaders_Mesh_Unregister(); + NazaraNotice("Uninitialized: 3D module"); // Libération des dépendances diff --git a/src/Nazara/3D/Loaders/Mesh.hpp b/src/Nazara/3D/Loaders/Mesh.hpp new file mode 100644 index 000000000..47c03ad18 --- /dev/null +++ b/src/Nazara/3D/Loaders/Mesh.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2013 Jérôme Leclercq +// This file is part of the "Nazara Engine - 3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_LOADERS_MESH_HPP +#define NAZARA_LOADERS_MESH_HPP + +#include + +void NzLoaders_Mesh_Register(); +void NzLoaders_Mesh_Unregister(); + +#endif // NAZARA_LOADERS_MESH_HPP diff --git a/src/Nazara/3D/Loaders/Mesh/Loader.cpp b/src/Nazara/3D/Loaders/Mesh/Loader.cpp new file mode 100644 index 000000000..57095c37f --- /dev/null +++ b/src/Nazara/3D/Loaders/Mesh/Loader.cpp @@ -0,0 +1,89 @@ +// Copyright (C) 2013 Jérôme Leclercq +// This file is part of the "Nazara Engine - 3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include + +namespace +{ + bool Check(NzInputStream& stream, const NzModelParameters& parameters) + { + NazaraUnused(stream); + NazaraUnused(parameters); + + return true; ///FIXME: Pas bon + } + + bool Load(NzModel* model, NzInputStream& stream, const NzModelParameters& parameters) + { + NazaraUnused(parameters); + + std::unique_ptr mesh(new NzMesh); + mesh->SetPersistent(false, false); + if (!mesh->LoadFromStream(stream)) + { + NazaraError("Failed to load model mesh"); + return false; + } + + // Nous ne pouvons plus avoir recours au smart pointeur à partir d'ici si nous voulons être exception-safe + NzMesh* meshPtr = mesh.get(); + + model->Reset(); + model->SetMesh(meshPtr); + mesh.release(); + + if (parameters.loadAnimation && meshPtr->IsAnimable()) + { + NzString animationPath = meshPtr->GetAnimation(); + if (!animationPath.IsEmpty()) + { + std::unique_ptr animation(new NzAnimation); + animation->SetPersistent(false, false); + if (animation->LoadFromFile(animationPath, parameters.animation) && model->SetAnimation(animation.get())) + animation.release(); + else + NazaraWarning("Failed to load animation"); + } + } + + if (parameters.loadMaterials) + { + unsigned int matCount = model->GetMaterialCount(); + + for (unsigned int i = 0; i < matCount; ++i) + { + NzString mat = meshPtr->GetMaterial(i); + if (!mat.IsEmpty()) + { + std::unique_ptr material(new NzMaterial); + material->SetPersistent(false, false); + if (material->LoadFromFile(mat, parameters.material)) + { + model->SetMaterial(i, material.get()); + material.release(); + } + else + NazaraWarning("Failed to load material #" + NzString::Number(i)); + } + } + } + + return true; + } +} + +void NzLoaders_Mesh_Register() +{ + NzModelLoader::RegisterLoader(NzMeshLoader::IsExtensionSupported, Check, Load); +} + +void NzLoaders_Mesh_Unregister() +{ + NzModelLoader::UnregisterLoader(NzMeshLoader::IsExtensionSupported, Check, Load); +} diff --git a/src/Nazara/3D/Model.cpp b/src/Nazara/3D/Model.cpp index 69141fa5e..33d9a991b 100644 --- a/src/Nazara/3D/Model.cpp +++ b/src/Nazara/3D/Model.cpp @@ -10,10 +10,21 @@ #include #include +bool NzModelParameters::IsValid() const +{ + if (loadAnimation && !animation.IsValid()) + return false; + + if (loadMaterials && !material.IsValid()) + return false; + + return mesh.IsValid(); +} + NzModel::NzModel() : m_currentSequence(nullptr), m_animationEnabled(true), -m_boundingBoxUpdated(false), +m_boundingBoxUpdated(true), m_drawEnabled(true), m_matCount(0), m_skin(0), @@ -250,50 +261,19 @@ bool NzModel::IsDrawEnabled() const return m_drawEnabled; } -bool NzModel::LoadFromFile(const NzString& meshPath, const NzModelParameters& modelParameters) +bool NzModel::LoadFromFile(const NzString& filePath, const NzModelParameters& params) { - ///TODO: ResourceManager - std::unique_ptr mesh(new NzMesh); - if (!mesh->LoadFromFile(meshPath, modelParameters.mesh)) - { - NazaraError("Failed to load mesh"); - return false; - } - - mesh->SetPersistent(false, false); - SetMesh(mesh.release(), modelParameters); - - return true; + return NzModelLoader::LoadFromFile(this, filePath, params); } -bool NzModel::LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& modelParameters) +bool NzModel::LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& params) { - std::unique_ptr mesh(new NzMesh); - if (!mesh->LoadFromMemory(data, size, modelParameters.mesh)) - { - NazaraError("Failed to load mesh"); - return false; - } - - mesh->SetPersistent(false, false); - SetMesh(mesh.release(), modelParameters); - - return true; + return NzModelLoader::LoadFromMemory(this, data, size, params); } -bool NzModel::LoadFromStream(NzInputStream& stream, const NzModelParameters& modelParameters) +bool NzModel::LoadFromStream(NzInputStream& stream, const NzModelParameters& params) { - std::unique_ptr mesh(new NzMesh); - if (!mesh->LoadFromStream(stream, modelParameters.mesh)) - { - NazaraError("Failed to load mesh"); - return false; - } - - mesh->SetPersistent(false, false); - SetMesh(mesh.release(), modelParameters); - - return true; + return NzModelLoader::LoadFromStream(this, stream, params); } void NzModel::Reset() @@ -404,58 +384,39 @@ void NzModel::SetMaterial(unsigned int skinIndex, unsigned int matIndex, NzMater m_materials[index] = NzMaterial::GetDefault(); } -void NzModel::SetMesh(NzMesh* mesh, const NzModelParameters& modelParameters) +void NzModel::SetMesh(NzMesh* mesh) { - Reset(); + m_mesh = mesh; - if (mesh) + if (m_mesh) { m_boundingBoxUpdated = false; - m_mesh = mesh; if (m_mesh->GetAnimationType() == nzAnimationType_Skeletal) m_skeleton = *mesh->GetSkeleton(); // Copie du squelette template - if (modelParameters.loadAnimation && m_mesh->IsAnimable()) + if (m_animation) { - NzString animationPath = m_mesh->GetAnimation(); - if (!animationPath.IsEmpty()) + if (m_animation->GetJointCount() != m_mesh->GetJointCount()) { - std::unique_ptr animation(new NzAnimation); - if (animation->LoadFromFile(animationPath, modelParameters.animation) && SetAnimation(animation.get())) - { - animation->SetPersistent(false); - animation.release(); - } - else - NazaraWarning("Failed to load animation"); + NazaraWarning("Animation joint count is not matching new mesh joint count"); + SetAnimation(nullptr); } } m_matCount = mesh->GetMaterialCount(); - m_materials.reserve(m_matCount); - if (modelParameters.loadMaterials) - { - for (unsigned int i = 0; i < m_matCount; ++i) - { - NzString mat = mesh->GetMaterial(i); - if (!mat.IsEmpty()) - { - std::unique_ptr material(new NzMaterial); - if (material->LoadFromFile(mat, modelParameters.material)) - { - material->SetPersistent(false, false); // Pas de vérification des références car nous n'y avons pas encore accroché de référence - m_materials.push_back(material.release()); - } - else - { - NazaraWarning("Failed to load material #" + NzString::Number(i)); + m_materials.resize(m_matCount, NzMaterial::GetDefault()); + m_skinCount = 1; + } + else + { + m_boundingBox.MakeNull(); + m_boundingBoxUpdated = true; + m_matCount = 0; + m_skinCount = 0; + m_materials.clear(); - m_materials.push_back(NzMaterial::GetDefault()); - } - } - } - } + SetAnimation(nullptr); } } @@ -642,3 +603,5 @@ bool NzModel::VisibilityTest(const NzFrustumf& frustum) return frustum.Contains(m_boundingBox); } + +NzModelLoader::LoaderList NzModel::s_loaders;