Added ModelLoader

Changed Model::SetMesh behavior


Former-commit-id: b1c937b22bcebeef8b8fc42ff061dbf8ece8d2f1
This commit is contained in:
Lynix 2013-03-24 01:03:21 +01:00
parent be894c5555
commit b5d73ce389
5 changed files with 164 additions and 80 deletions

View File

@ -9,22 +9,30 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/3D/SceneNode.hpp>
#include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/Updatable.hpp>
#include <Nazara/Renderer/Material.hpp>
#include <Nazara/Utility/Animation.hpp>
#include <Nazara/Utility/Mesh.hpp>
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<NzModel, NzModelParameters>;
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

View File

@ -5,6 +5,7 @@
#include <Nazara/3D/3D.hpp>
#include <Nazara/2D/2D.hpp>
#include <Nazara/3D/Config.hpp>
#include <Nazara/3D/Loaders/Mesh.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Renderer/Renderer.hpp>
@ -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

View File

@ -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 <Nazara/Prerequesites.hpp>
void NzLoaders_Mesh_Register();
void NzLoaders_Mesh_Unregister();
#endif // NAZARA_LOADERS_MESH_HPP

View File

@ -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 <Nazara/3D/Loaders/Mesh.hpp>
#include <Nazara/3D/Model.hpp>
#include <Nazara/Renderer/Material.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <memory>
#include <Nazara/3D/Debug.hpp>
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<NzMesh> 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<NzAnimation> 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<NzMaterial> 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);
}

View File

@ -10,10 +10,21 @@
#include <tuple>
#include <Nazara/3D/Debug.hpp>
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<NzMesh> mesh(new NzMesh);
if (!mesh->LoadFromFile(meshPath, modelParameters.mesh))
{
NazaraError("Failed to load mesh");
return false;
return NzModelLoader::LoadFromFile(this, filePath, params);
}
mesh->SetPersistent(false, false);
SetMesh(mesh.release(), modelParameters);
return true;
bool NzModel::LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& params)
{
return NzModelLoader::LoadFromMemory(this, data, size, params);
}
bool NzModel::LoadFromMemory(const void* data, std::size_t size, const NzModelParameters& modelParameters)
bool NzModel::LoadFromStream(NzInputStream& stream, const NzModelParameters& params)
{
std::unique_ptr<NzMesh> 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;
}
bool NzModel::LoadFromStream(NzInputStream& stream, const NzModelParameters& modelParameters)
{
std::unique_ptr<NzMesh> 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<NzAnimation> 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<NzMaterial> 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());
m_materials.resize(m_matCount, NzMaterial::GetDefault());
m_skinCount = 1;
}
else
{
NazaraWarning("Failed to load material #" + NzString::Number(i));
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;