From a2eb55e74a8c8a0aa03ead04fdf2593a51f2d049 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 29 Nov 2012 10:15:10 +0100 Subject: [PATCH] Fixed repo Former-commit-id: 5992da5ec759f05dabf82009e660ec58eed96365 --- include/Nazara/3D.hpp | 38 +++ include/Nazara/3D/Enums.hpp | 17 + include/Nazara/3D/Model.hpp | 71 +++++ include/Nazara/3D/SceneNode.hpp | 22 ++ include/Nazara/Renderer/Material.hpp | 12 +- include/Nazara/Renderer/Renderer.hpp | 6 +- include/Nazara/Utility.hpp | 1 - include/Nazara/Utility/Animation.hpp | 1 + include/Nazara/Utility/SkeletalMesh.hpp | 2 +- src/Nazara/3D/Model.cpp | 399 ++++++++++++++++++++++++ src/Nazara/3D/SceneNode.cpp | 8 + src/Nazara/Renderer/Material.cpp | 20 +- src/Nazara/Renderer/Renderer.cpp | 99 +++++- src/Nazara/Utility/Animation.cpp | 19 ++ 14 files changed, 692 insertions(+), 23 deletions(-) create mode 100644 include/Nazara/3D.hpp create mode 100644 include/Nazara/3D/Enums.hpp create mode 100644 include/Nazara/3D/Model.hpp create mode 100644 include/Nazara/3D/SceneNode.hpp create mode 100644 src/Nazara/3D/Model.cpp create mode 100644 src/Nazara/3D/SceneNode.cpp diff --git a/include/Nazara/3D.hpp b/include/Nazara/3D.hpp new file mode 100644 index 000000000..6a255bdfb --- /dev/null +++ b/include/Nazara/3D.hpp @@ -0,0 +1,38 @@ +// This file was automatically generated by Nazara + +/* + Nazara Engine - 3D module + + Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_3D_HPP +#define NAZARA_GLOBAL_3D_HPP + +#include +#include +#include +#include +#include + +#endif // NAZARA_GLOBAL_3D_HPP diff --git a/include/Nazara/3D/Enums.hpp b/include/Nazara/3D/Enums.hpp new file mode 100644 index 000000000..a42bcb22d --- /dev/null +++ b/include/Nazara/3D/Enums.hpp @@ -0,0 +1,17 @@ +// Copyright (C) 2012 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_ENUMS_3D_HPP +#define NAZARA_ENUMS_3D_HPP + +enum nzSceneNodeType +{ + nzSceneNodeType_Model, + + nzSceneNodeType_Max = nzSceneNodeType_Model +}; + +#endif // NAZARA_ENUMS_3D_HPP diff --git a/include/Nazara/3D/Model.hpp b/include/Nazara/3D/Model.hpp new file mode 100644 index 000000000..14b0dc896 --- /dev/null +++ b/include/Nazara/3D/Model.hpp @@ -0,0 +1,71 @@ +// Copyright (C) 2012 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_MODEL_HPP +#define NAZARA_MODEL_HPP + +#include +#include +#include +#include +#include + +struct NzModelParameters +{ + bool loadAnimation = true; + bool loadMaterials = true; + NzAnimationParams animationParams; + NzMaterialParams materialParams; +}; + +class NAZARA_API NzModel : public NzSceneNode +{ + public: + NzModel(); + NzModel(const NzModel& model); + ~NzModel(); + + const NzAnimation* GetAnimation() const; + const NzMaterial* GetMaterial(unsigned int matIndex) const; + const NzMaterial* GetMaterial(unsigned int skinIndex, unsigned int matIndex) const; + unsigned int GetMaterialCount() const; + unsigned int GetSkinCount() const; + const NzMesh* GetMesh() const; + nzSceneNodeType GetSceneNodeType() const override; + const NzSkeleton* GetSkeleton() const; + + bool HasAnimation() const; + + bool LoadFromFile(const NzString& meshPath, const NzMeshParams& meshParameters = NzMeshParams(), const NzModelParameters& modelParameters = NzModelParameters()); + bool LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& meshParameters = NzMeshParams(), const NzModelParameters& modelParameters = NzModelParameters()); + bool LoadFromStream(NzInputStream& stream, const NzMeshParams& meshParameters = NzMeshParams(), const NzModelParameters& modelParameters = NzModelParameters()); + + void Reset(); + + bool SetAnimation(const NzAnimation* animation); + void SetMaterial(unsigned int matIndex, const NzMaterial* material); + void SetMaterial(unsigned int skinIndex, unsigned int matIndex, const NzMaterial* material); + void SetMesh(const NzMesh* mesh, const NzModelParameters& parameters = NzModelParameters()); + void SetSkinCount(unsigned int skinCount); + bool SetSequence(const NzString& sequenceName); + void SetSequence(unsigned int sequenceIndex); + + void Update(float elapsedTime); + + private: + std::vector m_materials; + NzSkeleton m_skeleton; // Uniquement pour les animations squelettiques + const NzAnimation* m_animation; + const NzMesh* m_mesh; + const NzSequence* m_currentSequence; + float m_interpolation; + unsigned int m_currentFrame; + unsigned int m_matCount; + unsigned int m_nextFrame; + unsigned int m_skinCount; +}; + +#endif // NAZARA_MODEL_HPP diff --git a/include/Nazara/3D/SceneNode.hpp b/include/Nazara/3D/SceneNode.hpp new file mode 100644 index 000000000..2d48307bd --- /dev/null +++ b/include/Nazara/3D/SceneNode.hpp @@ -0,0 +1,22 @@ +// Copyright (C) 2012 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_SCENENODE_HPP +#define NAZARA_SCENENODE_HPP + +#include +#include +#include + +class NzSceneNode : public NzNode +{ + public: + virtual ~NzSceneNode(); + + virtual nzSceneNodeType GetSceneNodeType() const = 0; +}; + +#endif // NAZARA_SCENENODE_HPP diff --git a/include/Nazara/Renderer/Material.hpp b/include/Nazara/Renderer/Material.hpp index 4f0f8e9ad..04698cae3 100644 --- a/include/Nazara/Renderer/Material.hpp +++ b/include/Nazara/Renderer/Material.hpp @@ -40,13 +40,13 @@ class NAZARA_API NzMaterial : public NzResource NzColor GetAmbientColor() const; NzColor GetDiffuseColor() const; const NzTexture* GetDiffuseMap() const; - nzBlendFunc GetDstAlpha() const; + nzBlendFunc GetDstBlend() const; nzFaceCulling GetFaceCulling() const; nzFaceFilling GetFaceFilling() const; float GetShininess() const; NzColor GetSpecularColor() const; const NzTexture* GetSpecularMap() const; - nzBlendFunc GetSrcAlpha() const; + nzBlendFunc GetSrcBlend() const; nzRendererComparison GetZTestCompare() const; bool IsAlphaBlendingEnabled() const; @@ -62,20 +62,20 @@ class NAZARA_API NzMaterial : public NzResource void SetAmbientColor(const NzColor& ambient); void SetDiffuseColor(const NzColor& diffuse); void SetDiffuseMap(const NzTexture* map); - void SetDstAlpha(nzBlendFunc func); + void SetDstBlend(nzBlendFunc func); void SetFaceCulling(nzFaceCulling culling); void SetFaceFilling(nzFaceFilling filling); void SetShininess(float shininess); void SetSpecularColor(const NzColor& specular); void SetSpecularMap(const NzTexture* map); - void SetSrcAlpha(nzBlendFunc func); + void SetSrcBlend(nzBlendFunc func); void SetZTestCompare(nzRendererComparison compareFunc); static const NzMaterial* GetDefault(); private: - nzBlendFunc m_dstAlpha; - nzBlendFunc m_srcAlpha; + nzBlendFunc m_dstBlend; + nzBlendFunc m_srcBlend; nzFaceCulling m_faceCulling; nzFaceFilling m_faceFilling; nzRendererComparison m_zTestCompareFunc; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 28ea85697..425c1fc28 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -18,6 +18,7 @@ class NzColor; class NzContext; class NzIndexBuffer; +class NzMaterial; class NzRenderTarget; class NzShader; class NzVertexBuffer; @@ -29,6 +30,8 @@ class NAZARA_API NzRenderer NzRenderer() = delete; ~NzRenderer() = delete; + static void ApplyMaterial(const NzMaterial* material); + static void Clear(unsigned long flags = nzRendererClear_Color | nzRendererClear_Depth); static void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount); @@ -54,11 +57,12 @@ class NAZARA_API NzRenderer static bool IsEnabled(nzRendererParameter parameter); static bool IsInitialized(); - static void SetBlendFunc(nzBlendFunc src, nzBlendFunc dest); + static void SetBlendFunc(nzBlendFunc srcBlend, nzBlendFunc destBlend); static void SetClearColor(const NzColor& color); static void SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a = 255); static void SetClearDepth(double depth); static void SetClearStencil(unsigned int value); + static void SetDepthFunc(nzRendererComparison compareFunc); static void SetFaceCulling(nzFaceCulling cullingMode); static void SetFaceFilling(nzFaceFilling fillingMode); static bool SetIndexBuffer(const NzIndexBuffer* indexBuffer); diff --git a/include/Nazara/Utility.hpp b/include/Nazara/Utility.hpp index e9bc08118..34afb2e86 100644 --- a/include/Nazara/Utility.hpp +++ b/include/Nazara/Utility.hpp @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include diff --git a/include/Nazara/Utility/Animation.hpp b/include/Nazara/Utility/Animation.hpp index 81f63a0bb..21f461ac2 100644 --- a/include/Nazara/Utility/Animation.hpp +++ b/include/Nazara/Utility/Animation.hpp @@ -45,6 +45,7 @@ class NAZARA_API NzAnimation : public NzResource void Destroy(); unsigned int GetFrameCount() const; + unsigned int GetJointCount() const; NzSequence* GetSequence(const NzString& sequenceName); NzSequence* GetSequence(unsigned int index); const NzSequence* GetSequence(const NzString& sequenceName) const; diff --git a/include/Nazara/Utility/SkeletalMesh.hpp b/include/Nazara/Utility/SkeletalMesh.hpp index 29900f6db..9ca9bfc90 100644 --- a/include/Nazara/Utility/SkeletalMesh.hpp +++ b/include/Nazara/Utility/SkeletalMesh.hpp @@ -15,7 +15,7 @@ class NzSkeleton; struct NzVertexWeight { - std::vector weights; + std::vector weights; ///FIXME: Niveau fragmentation mémoire ça doit pas être génial }; struct NzWeight diff --git a/src/Nazara/3D/Model.cpp b/src/Nazara/3D/Model.cpp new file mode 100644 index 000000000..6cbe2eb2e --- /dev/null +++ b/src/Nazara/3D/Model.cpp @@ -0,0 +1,399 @@ +// Copyright (C) 2012 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 + +NzModel::NzModel() : +m_animation(nullptr), +m_mesh(nullptr), +m_currentSequence(nullptr), +m_matCount(0), +m_skinCount(0) +{ +} + +NzModel::NzModel(const NzModel& model) : +m_materials(model.m_materials), +m_animation(model.m_animation), +m_mesh(model.m_mesh), +m_currentSequence(model.m_currentSequence), +m_matCount(model.m_matCount), +m_skinCount(model.m_skinCount) +{ + if (m_mesh) + { + if (m_animation) + m_animation->AddResourceReference(); + + m_mesh->AddResourceReference(); + + // Nous n'avons des matériaux que si nous avons un mesh + for (const NzMaterial* material : m_materials) + material->AddResourceReference(); + } +} + +NzModel::~NzModel() +{ + Reset(); +} + +const NzAnimation* NzModel::GetAnimation() const +{ + return m_animation; +} + +const NzMaterial* NzModel::GetMaterial(unsigned int matIndex) const +{ + #if NAZARA_3D_SAFE + if (matIndex >= m_matCount) + { + NazaraError("Material index out of range (" + NzString::Number(matIndex) + " >= " + NzString::Number(m_matCount)); + return nullptr; + } + #endif + + return m_materials[matIndex]; +} + +const NzMaterial* NzModel::GetMaterial(unsigned int skinIndex, unsigned int matIndex) const +{ + #if NAZARA_3D_SAFE + if (skinIndex >= m_skinCount) + { + NazaraError("Skin index out of range (" + NzString::Number(skinIndex) + " >= " + NzString::Number(m_skinCount)); + return nullptr; + } + + if (matIndex >= m_matCount) + { + NazaraError("Material index out of range (" + NzString::Number(matIndex) + " >= " + NzString::Number(m_matCount)); + return nullptr; + } + #endif + + return m_materials[matIndex]; +} + +unsigned int NzModel::GetMaterialCount() const +{ + return m_matCount; +} +unsigned int NzModel::GetSkinCount() const +{ + return m_skinCount; +} + +const NzMesh* NzModel::GetMesh() const +{ + return m_mesh; +} + +nzSceneNodeType NzModel::GetSceneNodeType() const +{ + return nzSceneNodeType_Model; +} + +const NzSkeleton* NzModel::GetSkeleton() const +{ + return &m_skeleton; +} + +bool NzModel::HasAnimation() const +{ + return m_animation != nullptr; +} + +bool NzModel::LoadFromFile(const NzString& meshPath, const NzMeshParams& meshParameters, const NzModelParameters& modelParameters) +{ + ///TODO: ResourceManager + std::unique_ptr mesh(new NzMesh); + if (!mesh->LoadFromFile(meshPath, meshParameters)) + { + NazaraError("Failed to load mesh"); + return false; + } + + mesh->SetPersistent(false, false); + SetMesh(mesh.release(), modelParameters); + + return true; +} + +bool NzModel::LoadFromMemory(const void* data, std::size_t size, const NzMeshParams& meshParameters, const NzModelParameters& modelParameters) +{ + std::unique_ptr mesh(new NzMesh); + if (!mesh->LoadFromMemory(data, size, meshParameters)) + { + NazaraError("Failed to load mesh"); + return false; + } + + mesh->SetPersistent(false, false); + SetMesh(mesh.release(), modelParameters); + + return true; +} + +bool NzModel::LoadFromStream(NzInputStream& stream, const NzMeshParams& meshParameters, const NzModelParameters& modelParameters) +{ + std::unique_ptr mesh(new NzMesh); + if (!mesh->LoadFromStream(stream, meshParameters)) + { + NazaraError("Failed to load mesh"); + return false; + } + + mesh->SetPersistent(false, false); + SetMesh(mesh.release(), modelParameters); + + return true; +} + +void NzModel::Reset() +{ + m_matCount = 0; + m_skinCount = 0; + + if (m_mesh) + { + m_mesh->RemoveResourceReference(); + m_mesh = nullptr; + + m_skeleton.Destroy(); + + if (m_animation) + { + m_animation->RemoveResourceReference(); + m_animation = nullptr; + } + + // Nous n'avons des matériaux que si nous avons un mesh + for (const NzMaterial* material : m_materials) + material->RemoveResourceReference(); + + m_materials.clear(); + } +} + +bool NzModel::SetAnimation(const NzAnimation* animation) +{ + #if NAZARA_3D_SAFE + if (!m_mesh) + { + NazaraError("Model has no animation"); + return false; + } + + if (animation) + { + if (!animation->IsValid()) + { + NazaraError("Invalid animation"); + return false; + } + + if (animation->GetType() != m_mesh->GetAnimationType()) + { + NazaraError("Animation type must match mesh animation type"); + return false; + } + + if (animation->GetType() == nzAnimationType_Skeletal && animation->GetJointCount() != m_mesh->GetJointCount()) + { + NazaraError("Animation joint count must match mesh joint count"); + return false; + } + } + #endif + + m_animation = animation; + if (m_animation) + { + m_animation->AddResourceReference(); + SetSequence(0); + } + + return true; +} + +void NzModel::SetMaterial(unsigned int matIndex, const NzMaterial* material) +{ + #if NAZARA_3D_SAFE + if (matIndex >= m_matCount) + { + NazaraError("Material index out of range (" + NzString::Number(matIndex) + " >= " + NzString::Number(m_matCount)); + return; + } + #endif + + m_materials[matIndex]->RemoveResourceReference(); + + if (material) + m_materials[matIndex] = material; + else + m_materials[matIndex] = NzMaterial::GetDefault(); + + m_materials[matIndex]->AddResourceReference(); +} + +void NzModel::SetMaterial(unsigned int skinIndex, unsigned int matIndex, const NzMaterial* material) +{ + #if NAZARA_3D_SAFE + if (skinIndex >= m_skinCount) + { + NazaraError("Skin index out of range (" + NzString::Number(skinIndex) + " >= " + NzString::Number(m_skinCount)); + return; + } + + if (matIndex >= m_matCount) + { + NazaraError("Material index out of range (" + NzString::Number(matIndex) + " >= " + NzString::Number(m_matCount)); + return; + } + #endif + + unsigned int index = skinIndex*m_matCount + matIndex; + + m_materials[index]->RemoveResourceReference(); + + if (material) + m_materials[index] = material; + else + m_materials[index] = NzMaterial::GetDefault(); + + m_materials[index]->AddResourceReference(); +} + +void NzModel::SetMesh(const NzMesh* mesh, const NzModelParameters& modelParameters) +{ + Reset(); + + if (mesh) + { + m_mesh = mesh; + m_mesh->AddResourceReference(); + + if (m_mesh->GetAnimationType() == nzAnimationType_Skeletal) + m_skeleton = *mesh->GetSkeleton(); // Copie du squelette template + + if (modelParameters.loadAnimation) + { + NzString animationPath = m_mesh->GetAnimation(); + if (!animationPath.IsEmpty()) + { + std::unique_ptr animation(new NzAnimation); + if (animation->LoadFromFile(animationPath, modelParameters.animationParams) && SetAnimation(animation.get())) + { + animation->SetPersistent(false); + animation.release(); + } + else + NazaraWarning("Failed to load animation"); + } + } + + m_interpolation = 0.f; + m_matCount = mesh->GetMaterialCount(); + m_materials.resize(m_matCount, NzMaterial::GetDefault()); + 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.materialParams)) + { + 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[i] = material.release(); + } + else + NazaraWarning("Failed to load material #" + NzString::Number(i)); + } + } + } + + for (const NzMaterial* material : m_materials) + material->AddResourceReference(); + } +} + +void NzModel::SetSkinCount(unsigned int skinCount) +{ + #if NAZARA_3D_SAFE + if (skinCount == 0) + { + NazaraError("Skin count must be over 0"); + return; + } + #endif + + m_materials.resize(m_matCount*skinCount, NzMaterial::GetDefault()); + m_skinCount = skinCount; +} + +bool NzModel::SetSequence(const NzString& sequenceName) +{ + #if NAZARA_3D_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return false; + } + #endif + + m_currentSequence = m_animation->GetSequence(sequenceName); + if (m_currentSequence) + { + m_nextFrame = m_currentSequence->firstFrame; + return true; + } + else + { + NazaraError("Sequence not found"); + return false; + } +} + +void NzModel::SetSequence(unsigned int sequenceIndex) +{ + #if NAZARA_3D_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return; + } + #endif + + m_currentSequence = m_animation->GetSequence(sequenceIndex); + m_nextFrame = m_currentSequence->firstFrame; +} + +void NzModel::Update(float elapsedTime) +{ + #if NAZARA_3D_SAFE + if (!m_animation) + { + NazaraError("Model has no animation"); + return; + } + #endif + + m_interpolation += m_currentSequence->frameRate * elapsedTime; + while (m_interpolation > 1.f) + { + m_interpolation -= 1.f; + + m_currentFrame = m_nextFrame; + if (++m_nextFrame >= m_currentSequence->firstFrame+m_currentSequence->frameCount) + m_nextFrame = m_currentSequence->firstFrame; + } + + m_mesh->Animate(m_animation, m_currentFrame, m_nextFrame, m_interpolation); +} diff --git a/src/Nazara/3D/SceneNode.cpp b/src/Nazara/3D/SceneNode.cpp new file mode 100644 index 000000000..fb48e863d --- /dev/null +++ b/src/Nazara/3D/SceneNode.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2012 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 + +NzSceneNode::~NzSceneNode() = default; diff --git a/src/Nazara/Renderer/Material.cpp b/src/Nazara/Renderer/Material.cpp index 5676d6534..b55bc4867 100644 --- a/src/Nazara/Renderer/Material.cpp +++ b/src/Nazara/Renderer/Material.cpp @@ -55,9 +55,9 @@ const NzTexture* NzMaterial::GetDiffuseMap() const return m_diffuseMap; } -nzBlendFunc NzMaterial::GetDstAlpha() const +nzBlendFunc NzMaterial::GetDstBlend() const { - return m_dstAlpha; + return m_dstBlend; } nzFaceCulling NzMaterial::GetFaceCulling() const @@ -85,9 +85,9 @@ const NzTexture* NzMaterial::GetSpecularMap() const return m_specularMap; } -nzBlendFunc NzMaterial::GetSrcAlpha() const +nzBlendFunc NzMaterial::GetSrcBlend() const { - return m_srcAlpha; + return m_srcBlend; } nzRendererComparison NzMaterial::GetZTestCompare() const @@ -142,12 +142,12 @@ void NzMaterial::Reset() m_alphaBlendingEnabled = false; m_ambientColor = NzColor::Black; m_diffuseColor = NzColor::White; - m_dstAlpha = nzBlendFunc_Zero; + m_dstBlend = nzBlendFunc_Zero; m_faceCulling = nzFaceCulling_Back; m_faceFilling = nzFaceFilling_Fill; m_shininess = 0; m_specularColor = NzColor::White; - m_srcAlpha = nzBlendFunc_One; + m_srcBlend = nzBlendFunc_One; m_zTestCompareFunc = nzRendererComparison_LessOrEqual; m_zTestEnabled = true; m_zWriteEnabled = true; @@ -173,9 +173,9 @@ void NzMaterial::SetDiffuseMap(const NzTexture* map) m_diffuseMap->AddResourceReference(); } -void NzMaterial::SetDstAlpha(nzBlendFunc func) +void NzMaterial::SetDstBlend(nzBlendFunc func) { - m_dstAlpha = func; + m_dstBlend = func; } void NzMaterial::SetFaceCulling(nzFaceCulling culling) @@ -208,9 +208,9 @@ void NzMaterial::SetSpecularMap(const NzTexture* map) m_specularMap->AddResourceReference(); } -void NzMaterial::SetSrcAlpha(nzBlendFunc func) +void NzMaterial::SetSrcBlend(nzBlendFunc func) { - m_srcAlpha = func; + m_srcBlend = func; } void NzMaterial::SetZTestCompare(nzRendererComparison compareFunc) diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 3b3e07f26..12fd72678 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,11 @@ namespace NzMatrix4f s_matrix[totalMatrixCount]; int s_matrixLocation[totalMatrixCount]; bool s_matrixUpdated[totalMatrixCount]; + nzBlendFunc s_srcBlend; + nzBlendFunc s_dstBlend; + nzFaceCulling s_faceCulling; + nzFaceFilling s_faceFilling; + nzRendererComparison s_depthFunc; nzRendererComparison s_stencilCompare; nzStencilOperation s_stencilFail; nzStencilOperation s_stencilPass; @@ -69,6 +75,57 @@ namespace unsigned int s_stencilReference; } +void NzRenderer::ApplyMaterial(const NzMaterial* material) +{ + ///FIXME; Bouger vers Material::Apply ? + #if NAZARA_RENDERER_SAFE + if (!material) + { + NazaraError("Invalid material"); + return; + } + #endif + + NzShader* shader = s_shader; + + int ambientColorLocation = shader->GetUniformLocation("ambientColor"); + int diffuseColorLocation = shader->GetUniformLocation("diffuseColor"); + int diffuseMapLocation = shader->GetUniformLocation("diffuseMap"); + int shininessLocation = shader->GetUniformLocation("shininess"); + int specularColorLocation = shader->GetUniformLocation("specularColor"); + int specularMapLocation = shader->GetUniformLocation("specularMap"); + + if (ambientColorLocation != -1) + shader->SendColor(ambientColorLocation, material->GetAmbientColor()); + + if (diffuseColorLocation != -1) + shader->SendColor(diffuseColorLocation, material->GetDiffuseColor()); + + if (diffuseMapLocation != -1) + shader->SendTexture(diffuseMapLocation, material->GetDiffuseMap()); + + if (shininessLocation != -1) + shader->SendFloat(shininessLocation, material->GetShininess()); + + if (specularColorLocation != -1) + shader->SendColor(ambientColorLocation, material->GetSpecularColor()); + + if (specularMapLocation != -1) + shader->SendTexture(specularMapLocation, material->GetSpecularMap()); + + if (material->IsAlphaBlendingEnabled()) + { + Enable(nzRendererParameter_Blend, true); + SetBlendFunc(material->GetSrcBlend(), material->GetDstBlend()); + } + else + Enable(nzRendererParameter_Blend, false); + + Enable(nzRendererParameter_DepthTest, material->IsZTestEnabled()); + Enable(nzRendererParameter_DepthWrite, material->IsZWriteEnabled()); + SetDepthFunc(material->GetZTestCompare()); +} + void NzRenderer::Clear(unsigned long flags) { #ifdef NAZARA_DEBUG @@ -377,8 +434,12 @@ bool NzRenderer::Initialize() s_matrixUpdated[i] = false; } + s_dstBlend = nzBlendFunc_Zero; + s_faceCulling = nzFaceCulling_Back; + s_faceFilling = nzFaceFilling_Fill; s_indexBuffer = nullptr; s_shader = nullptr; + s_srcBlend = nzBlendFunc_One; s_stencilCompare = nzRendererComparison_Always; s_stencilFail = nzStencilOperation_Keep; s_stencilFuncUpdated = true; @@ -502,7 +563,7 @@ bool NzRenderer::IsInitialized() return s_moduleReferenceCounter != 0; } -void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest) +void NzRenderer::SetBlendFunc(nzBlendFunc srcBlend, nzBlendFunc destBlend) { #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) @@ -512,7 +573,12 @@ void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest) } #endif - glBlendFunc(NzOpenGL::BlendFunc[src], NzOpenGL::BlendFunc[dest]); + if (s_srcBlend != srcBlend || s_dstBlend != destBlend) + { + glBlendFunc(NzOpenGL::BlendFunc[srcBlend], NzOpenGL::BlendFunc[destBlend]); + s_srcBlend = srcBlend; + s_dstBlend = destBlend; + } } void NzRenderer::SetClearColor(const NzColor& color) @@ -567,6 +633,23 @@ void NzRenderer::SetClearStencil(unsigned int value) glClearStencil(value); } +void NzRenderer::SetDepthFunc(nzRendererComparison compareFunc) +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + if (s_depthFunc != compareFunc) + { + glDepthFunc(NzOpenGL::RendererComparison[compareFunc]); + s_depthFunc = compareFunc; + } +} + void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode) { #ifdef NAZARA_DEBUG @@ -577,7 +660,11 @@ void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode) } #endif - glCullFace(NzOpenGL::FaceCulling[cullingMode]); + if (s_faceCulling != cullingMode) + { + glCullFace(NzOpenGL::FaceCulling[cullingMode]); + s_faceCulling = cullingMode; + } } void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) @@ -590,7 +677,11 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) } #endif - glPolygonMode(GL_FRONT_AND_BACK, NzOpenGL::FaceFilling[fillingMode]); + if (s_faceFilling != fillingMode) + { + glPolygonMode(GL_FRONT_AND_BACK, NzOpenGL::FaceFilling[fillingMode]); + s_faceFilling = fillingMode; + } } bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) diff --git a/src/Nazara/Utility/Animation.cpp b/src/Nazara/Utility/Animation.cpp index cf38fa09d..fb8643833 100644 --- a/src/Nazara/Utility/Animation.cpp +++ b/src/Nazara/Utility/Animation.cpp @@ -219,6 +219,25 @@ unsigned int NzAnimation::GetFrameCount() const return m_impl->frameCount; } +unsigned int NzAnimation::GetJointCount() const +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Animation not created"); + return 0; + } + + if (m_impl->type != nzAnimationType_Skeletal) + { + NazaraError("Animation is not skeletal"); + return 0; + } + #endif + + return m_impl->jointCount; +} + NzSequence* NzAnimation::GetSequence(const NzString& sequenceName) { #if NAZARA_UTILITY_SAFE