From 9e3b99bb5ab0de6d8b992f8730d10b117df3fac4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 30 Apr 2016 18:44:33 +0200 Subject: [PATCH] Make mesh able to carry material informations - Move OBJ Loader to Utility module, where it belongs - Change Mesh material informations from a path to a parameterlist - Improve Mesh code Former-commit-id: 3c18901133fa5ac8281269822f6e2650ddcefd2d --- include/Nazara/Graphics/Material.hpp | 3 + include/Nazara/Renderer/Enums.hpp | 101 ---- include/Nazara/Renderer/RenderStates.hpp | 2 +- include/Nazara/Renderer/TextureSampler.hpp | 2 +- include/Nazara/Utility/Enums.hpp | 101 ++++ include/Nazara/Utility/MaterialData.hpp | 65 +++ include/Nazara/Utility/Mesh.hpp | 5 +- src/Nazara/Graphics/Formats/MeshLoader.cpp | 63 ++- src/Nazara/Graphics/Graphics.cpp | 5 - src/Nazara/Graphics/Material.cpp | 161 ++++++ src/Nazara/Utility/Formats/MD2Loader.cpp | 7 +- src/Nazara/Utility/Formats/MD5MeshLoader.cpp | 11 +- .../Formats/OBJLoader.cpp | 117 ++-- .../Formats/OBJLoader.hpp | 0 src/Nazara/Utility/Mesh.cpp | 510 +++--------------- src/Nazara/Utility/Utility.cpp | 7 +- 16 files changed, 523 insertions(+), 637 deletions(-) create mode 100644 include/Nazara/Utility/MaterialData.hpp rename src/Nazara/{Graphics => Utility}/Formats/OBJLoader.cpp (67%) rename src/Nazara/{Graphics => Utility}/Formats/OBJLoader.hpp (100%) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index a2d30b643..397253022 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace Nz { @@ -62,6 +63,8 @@ namespace Nz const Shader* Apply(UInt32 shaderFlags = 0, UInt8 textureUnit = 0, UInt8* lastUsedUnit = nullptr) const; + void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams()); + void Enable(RendererParameter renderParameter, bool enable); void EnableAlphaTest(bool alphaTest); void EnableDepthSorting(bool depthSorting); diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 30e0b5616..2d0e6d3a7 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -19,40 +19,6 @@ namespace Nz AttachmentPoint_Max = AttachmentPoint_Stencil }; - enum BlendFunc - { - BlendFunc_DestAlpha, - BlendFunc_DestColor, - BlendFunc_SrcAlpha, - BlendFunc_SrcColor, - BlendFunc_InvDestAlpha, - BlendFunc_InvDestColor, - BlendFunc_InvSrcAlpha, - BlendFunc_InvSrcColor, - BlendFunc_One, - BlendFunc_Zero, - - BlendFunc_Max = BlendFunc_Zero - }; - - enum FaceFilling - { - FaceFilling_Fill, - FaceFilling_Line, - FaceFilling_Point, - - FaceFilling_Max = FaceFilling_Point - }; - - enum FaceSide - { - FaceSide_Back, - FaceSide_Front, - FaceSide_FrontAndBack, - - FaceSide_Max = FaceSide_FrontAndBack - }; - enum GpuQueryCondition { GpuQueryCondition_Region_NoWait, @@ -124,59 +90,6 @@ namespace Nz RendererBuffer_Max = RendererBuffer_Stencil*2-1 }; - enum RendererComparison - { - RendererComparison_Always, - RendererComparison_Equal, - RendererComparison_Greater, - RendererComparison_GreaterOrEqual, - RendererComparison_Less, - RendererComparison_LessOrEqual, - RendererComparison_Never, - RendererComparison_NotEqual, - - RendererComparison_Max = RendererComparison_NotEqual - }; - - enum RendererParameter - { - RendererParameter_Blend, - RendererParameter_ColorWrite, - RendererParameter_DepthBuffer, - RendererParameter_DepthWrite, - RendererParameter_FaceCulling, - RendererParameter_ScissorTest, - RendererParameter_StencilTest, - - RendererParameter_Max = RendererParameter_StencilTest - }; - - enum SamplerFilter - { - SamplerFilter_Unknown = -1, - - SamplerFilter_Bilinear, - SamplerFilter_Nearest, - SamplerFilter_Trilinear, - - SamplerFilter_Default, - - SamplerFilter_Max = SamplerFilter_Default - }; - - enum SamplerWrap - { - SamplerWrap_Unknown = -1, - - SamplerWrap_Clamp, - SamplerWrap_MirroredRepeat, - SamplerWrap_Repeat, - - SamplerWrap_Default, - - SamplerWrap_Max = SamplerWrap_Repeat - }; - enum ShaderUniform { ShaderUniform_InvProjMatrix, @@ -205,20 +118,6 @@ namespace Nz ShaderStageType_Max = ShaderStageType_Vertex }; - - enum StencilOperation - { - StencilOperation_Decrement, - StencilOperation_DecrementNoClamp, - StencilOperation_Increment, - StencilOperation_IncrementNoClamp, - StencilOperation_Invert, - StencilOperation_Keep, - StencilOperation_Replace, - StencilOperation_Zero, - - StencilOperation_Max = StencilOperation_Zero - }; } #endif // NAZARA_ENUMS_RENDERER_HPP diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp index 9e9d455f4..4040bec55 100644 --- a/include/Nazara/Renderer/RenderStates.hpp +++ b/include/Nazara/Renderer/RenderStates.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_RENDERSTATES_HPP #define NAZARA_RENDERSTATES_HPP -#include +#include namespace Nz { diff --git a/include/Nazara/Renderer/TextureSampler.hpp b/include/Nazara/Renderer/TextureSampler.hpp index a461f57b2..21675e6c9 100644 --- a/include/Nazara/Renderer/TextureSampler.hpp +++ b/include/Nazara/Renderer/TextureSampler.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace Nz { diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 096aa5fb6..143390906 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -17,6 +17,22 @@ namespace Nz AnimationType_Max = AnimationType_Static }; + enum BlendFunc + { + BlendFunc_DestAlpha, + BlendFunc_DestColor, + BlendFunc_SrcAlpha, + BlendFunc_SrcColor, + BlendFunc_InvDestAlpha, + BlendFunc_InvDestColor, + BlendFunc_InvSrcAlpha, + BlendFunc_InvSrcColor, + BlendFunc_One, + BlendFunc_Zero, + + BlendFunc_Max = BlendFunc_Zero + }; + enum BufferAccess { BufferAccess_DiscardAndWrite, @@ -87,6 +103,24 @@ namespace Nz DataStorage_Max = DataStorage_Software*2-1 }; + enum FaceFilling + { + FaceFilling_Fill, + FaceFilling_Line, + FaceFilling_Point, + + FaceFilling_Max = FaceFilling_Point + }; + + enum FaceSide + { + FaceSide_Back, + FaceSide_Front, + FaceSide_FrontAndBack, + + FaceSide_Max = FaceSide_FrontAndBack + }; + enum ImageType { ImageType_1D, @@ -211,6 +245,73 @@ namespace Nz PrimitiveMode_Max = PrimitiveMode_TriangleFan }; + enum RendererComparison + { + RendererComparison_Always, + RendererComparison_Equal, + RendererComparison_Greater, + RendererComparison_GreaterOrEqual, + RendererComparison_Less, + RendererComparison_LessOrEqual, + RendererComparison_Never, + RendererComparison_NotEqual, + + RendererComparison_Max = RendererComparison_NotEqual + }; + + enum RendererParameter + { + RendererParameter_Blend, + RendererParameter_ColorWrite, + RendererParameter_DepthBuffer, + RendererParameter_DepthWrite, + RendererParameter_FaceCulling, + RendererParameter_ScissorTest, + RendererParameter_StencilTest, + + RendererParameter_Max = RendererParameter_StencilTest + }; + + enum SamplerFilter + { + SamplerFilter_Unknown = -1, + + SamplerFilter_Bilinear, + SamplerFilter_Nearest, + SamplerFilter_Trilinear, + + SamplerFilter_Default, + + SamplerFilter_Max = SamplerFilter_Default + }; + + enum SamplerWrap + { + SamplerWrap_Unknown = -1, + + SamplerWrap_Clamp, + SamplerWrap_MirroredRepeat, + SamplerWrap_Repeat, + + SamplerWrap_Default, + + SamplerWrap_Max = SamplerWrap_Repeat + }; + + enum StencilOperation + { + StencilOperation_Decrement, + StencilOperation_DecrementNoClamp, + StencilOperation_Increment, + StencilOperation_IncrementNoClamp, + StencilOperation_Invert, + StencilOperation_Keep, + StencilOperation_Replace, + StencilOperation_Zero, + + StencilOperation_Max = StencilOperation_Zero + }; + enum TextAlign { TextAlign_Left, diff --git a/include/Nazara/Utility/MaterialData.hpp b/include/Nazara/Utility/MaterialData.hpp new file mode 100644 index 000000000..0f69c9846 --- /dev/null +++ b/include/Nazara/Utility/MaterialData.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_MATERIALDATA_HPP +#define NAZARA_MATERIALDATA_HPP + +namespace Nz +{ + struct MaterialData + { + static constexpr const char* AlphaTest = "MatAlphaTest"; + static constexpr const char* AlphaTexturePath = "MatAlphaTexturePath"; + static constexpr const char* AlphaThreshold = "MatAlphaThreshold"; + static constexpr const char* AmbientColor = "MatAmbientColor"; + static constexpr const char* BackFaceStencilCompare = "MatBackFaceStencilCompare"; + static constexpr const char* BackFaceStencilFail = "MatBackFaceStencilFail"; + static constexpr const char* BackFaceStencilMask = "MatBackFaceStencilMask"; + static constexpr const char* BackFaceStencilPass = "MatBackFaceStencilPass"; + static constexpr const char* BackFaceStencilReference = "MatBackFaceStencilReference"; + static constexpr const char* BackFaceStencilZFail = "MatBackFaceStencilZFail"; + static constexpr const char* Blending = "MatBlending"; + static constexpr const char* CustomDefined = "MatCustomDefined"; + static constexpr const char* ColorWrite = "MatColorWrite"; + static constexpr const char* DepthBuffer = "MatDepthBuffer"; + static constexpr const char* DepthFunc = "MatDepthfunc"; + static constexpr const char* DepthSorting = "MatDepthSorting"; + static constexpr const char* DepthWrite = "MatDepthWrite"; + static constexpr const char* DiffuseAnisotropyLevel = "MatDiffuseAnisotropyLevel"; + static constexpr const char* DiffuseColor = "MatDiffuseColor"; + static constexpr const char* DiffuseFilter = "MatDiffuseFilter"; + static constexpr const char* DiffuseTexturePath = "MatDiffuseTexturePath"; + static constexpr const char* DiffuseWrap = "MatDiffuseWrap"; + static constexpr const char* DstBlend = "MatDstBlend"; + static constexpr const char* EmissiveTexturePath = "MatEmissiveTexturePath"; + static constexpr const char* FaceCulling = "MatFaceCulling"; + static constexpr const char* FaceFilling = "MatFaceFilling"; + static constexpr const char* FilePath = "MatFilePath"; + static constexpr const char* HeightTexturePath = "MatHeightTexturePath"; + static constexpr const char* Lighting = "MatLighting"; + static constexpr const char* LineWidth = "MatLineWidth"; + static constexpr const char* NormalTexturePath = "MatNormalTexturePath"; + static constexpr const char* PointSize = "MatPointSize"; + static constexpr const char* ScissorTest = "MatScissorTest"; + static constexpr const char* Shininess = "MatShininess"; + static constexpr const char* SpecularAnisotropyLevel = "MatSpecularAnisotropyLevel"; + static constexpr const char* SpecularColor = "MatSpecularColor"; + static constexpr const char* SpecularFilter = "MatSpecularFilter"; + static constexpr const char* SpecularTexturePath = "MatSpecularTexturePath"; + static constexpr const char* SpecularWrap = "MatSpecularWrap"; + static constexpr const char* SrcBlend = "MatSrcBlend"; + static constexpr const char* StencilCompare = "MatStencilCompare"; + static constexpr const char* StencilFail = "MatStencilFail"; + static constexpr const char* StencilMask = "MatStencilMask"; + static constexpr const char* StencilPass = "MatStencilPass"; + static constexpr const char* StencilReference = "MatStencilReference"; + static constexpr const char* StencilTest = "MatStencilTest"; + static constexpr const char* StencilZFail = "MatStencilZFail"; + static constexpr const char* Transform = "MatTransform"; + }; +} + +#endif // NAZARA_MATERIALDATA_HPP diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 433f50ab5..ff11b5d4d 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -93,7 +93,8 @@ namespace Nz String GetAnimation() const; AnimationType GetAnimationType() const; unsigned int GetJointCount() const; - String GetMaterial(unsigned int index) const; + ParameterList& GetMaterialData(unsigned int index); + const ParameterList& GetMaterialData(unsigned int index) const; unsigned int GetMaterialCount() const; Skeleton* GetSkeleton(); const Skeleton* GetSkeleton() const; @@ -124,8 +125,8 @@ namespace Nz void RemoveSubMesh(unsigned int index); void SetAnimation(const String& animationPath); - void SetMaterial(unsigned int matIndex, const String& materialPath); void SetMaterialCount(unsigned int matCount); + void SetMaterialData(unsigned int matIndex, ParameterList data); void Transform(const Matrix4f& matrix); diff --git a/src/Nazara/Graphics/Formats/MeshLoader.cpp b/src/Nazara/Graphics/Formats/MeshLoader.cpp index b915c6f2e..ffd2b423e 100644 --- a/src/Nazara/Graphics/Formats/MeshLoader.cpp +++ b/src/Nazara/Graphics/Formats/MeshLoader.cpp @@ -3,9 +3,11 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include +#include #include #include #include @@ -14,6 +16,33 @@ namespace Nz { namespace { + void LoadMaterials(Model* model, const ModelParameters& parameters) + { + unsigned int matCount = model->GetMaterialCount(); + + for (unsigned int i = 0; i < matCount; ++i) + { + const ParameterList& matData = model->GetMesh()->GetMaterialData(i); + + String filePath; + if (matData.GetStringParameter(MaterialData::FilePath, &filePath)) + { + MaterialRef material = Material::New(); + if (material->LoadFromFile(filePath, parameters.material)) + model->SetMaterial(i, std::move(material)); + else + NazaraWarning("Failed to load material from file " + String::Number(i)); + } + else if (matData.HasParameter(MaterialData::CustomDefined)) + { + MaterialRef material = Material::New(); + material->BuildFromParameters(matData, parameters.material); + + model->SetMaterial(i, std::move(material)); + } + } + } + Ternary CheckStatic(Stream& stream, const ModelParameters& parameters) { NazaraUnused(stream); @@ -46,22 +75,7 @@ namespace Nz model->SetMesh(mesh); if (parameters.loadMaterials) - { - unsigned int matCount = model->GetMaterialCount(); - - for (unsigned int i = 0; i < matCount; ++i) - { - String mat = mesh->GetMaterial(i); - if (!mat.IsEmpty()) - { - MaterialRef material = Material::New(); - if (material->LoadFromFile(mat, parameters.material)) - model->SetMaterial(i, material); - else - NazaraWarning("Failed to load material #" + String::Number(i)); - } - } - } + LoadMaterials(model, parameters); return true; } @@ -98,22 +112,7 @@ namespace Nz model->SetMesh(mesh); if (parameters.loadMaterials) - { - unsigned int matCount = model->GetMaterialCount(); - - for (unsigned int i = 0; i < matCount; ++i) - { - String mat = mesh->GetMaterial(i); - if (!mat.IsEmpty()) - { - MaterialRef material = Material::New(); - if (material->LoadFromFile(mat, parameters.material)) - model->SetMaterial(i, material); - else - NazaraWarning("Failed to load material #" + String::Number(i)); - } - } - } + LoadMaterials(model, parameters); return true; } diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index a96f2f4e7..03c343ed3 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -96,9 +95,6 @@ namespace Nz return false; } - // Loaders - Loaders::RegisterOBJ(); - // Loaders génériques Loaders::RegisterMesh(); Loaders::RegisterTexture(); @@ -176,7 +172,6 @@ namespace Nz // Loaders Loaders::UnregisterMesh(); - Loaders::UnregisterOBJ(); Loaders::UnregisterTexture(); DeferredRenderTechnique::Uninitialize(); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 0a4755c03..c646d940b 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -7,6 +7,7 @@ #endif #include +#include #include #include #include @@ -139,6 +140,166 @@ namespace Nz return instance.shader; } + void Material::BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams) + { + Color color; + bool isEnabled; + float fValue; + int iValue; + String path; + + ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled, true); + + + if (matData.GetFloatParameter(MaterialData::AlphaThreshold, &fValue)) + SetAlphaThreshold(fValue); + + if (matData.GetBooleanParameter(MaterialData::AlphaTest, &isEnabled)) + EnableAlphaTest(isEnabled); + + if (matData.GetColorParameter(MaterialData::AmbientColor, &color)) + SetAmbientColor(color); + + if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue)) + SetDepthFunc(static_cast(iValue)); + + if (matData.GetBooleanParameter(MaterialData::DepthSorting, &isEnabled)) + EnableDepthSorting(isEnabled); + + if (matData.GetColorParameter(MaterialData::DiffuseColor, &color)) + SetDiffuseColor(color); + + if (matData.GetIntegerParameter(MaterialData::DstBlend, &iValue)) + SetDstBlend(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::FaceCulling, &iValue)) + SetFaceCulling(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue)) + SetFaceFilling(static_cast(iValue)); + + if (matData.GetBooleanParameter(MaterialData::Lighting, &isEnabled)) + EnableLighting(isEnabled); + + if (matData.GetFloatParameter(MaterialData::LineWidth, &fValue)) + m_states.lineWidth = fValue; + + if (matData.GetFloatParameter(MaterialData::PointSize, &fValue)) + m_states.pointSize = fValue; + + if (matData.GetColorParameter(MaterialData::SpecularColor, &color)) + SetSpecularColor(color); + + if (matData.GetFloatParameter(MaterialData::Shininess, &fValue)) + SetShininess(fValue); + + if (matData.GetIntegerParameter(MaterialData::SrcBlend, &iValue)) + SetSrcBlend(static_cast(iValue)); + + if (matData.GetBooleanParameter(MaterialData::Transform, &isEnabled)) + EnableTransform(isEnabled); + + // RendererParameter + if (matData.GetBooleanParameter(MaterialData::Blending, &isEnabled)) + Enable(RendererParameter_Blend, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::ColorWrite, &isEnabled)) + Enable(RendererParameter_ColorWrite, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::DepthBuffer, &isEnabled)) + Enable(RendererParameter_DepthBuffer, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::DepthWrite, &isEnabled)) + Enable(RendererParameter_DepthWrite, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::FaceCulling, &isEnabled)) + Enable(RendererParameter_FaceCulling, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::ScissorTest, &isEnabled)) + Enable(RendererParameter_ScissorTest, isEnabled); + + if (matData.GetBooleanParameter(MaterialData::StencilTest, &isEnabled)) + Enable(RendererParameter_StencilTest, isEnabled); + + // Samplers + if (matData.GetIntegerParameter(MaterialData::DiffuseAnisotropyLevel, &iValue)) + m_diffuseSampler.SetAnisotropyLevel(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::DiffuseFilter, &iValue)) + m_diffuseSampler.SetFilterMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::DiffuseWrap, &iValue)) + m_diffuseSampler.SetWrapMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularAnisotropyLevel, &iValue)) + m_specularSampler.SetAnisotropyLevel(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularFilter, &iValue)) + m_specularSampler.SetFilterMode(static_cast(iValue)); + + if (matData.GetIntegerParameter(MaterialData::SpecularWrap, &iValue)) + m_specularSampler.SetWrapMode(static_cast(iValue)); + + // Stencil + if (matData.GetIntegerParameter(MaterialData::StencilCompare, &iValue)) + m_states.frontFace.stencilCompare = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilFail, &iValue)) + m_states.frontFace.stencilFail = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilPass, &iValue)) + m_states.frontFace.stencilPass = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilZFail, &iValue)) + m_states.frontFace.stencilZFail = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilMask, &iValue)) + m_states.frontFace.stencilMask = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::StencilReference, &iValue)) + m_states.frontFace.stencilReference = static_cast(iValue); + + // Stencil (back) + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilCompare, &iValue)) + m_states.backFace.stencilCompare = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilFail, &iValue)) + m_states.backFace.stencilFail = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilPass, &iValue)) + m_states.backFace.stencilPass = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilZFail, &iValue)) + m_states.backFace.stencilZFail = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilMask, &iValue)) + m_states.backFace.stencilMask = static_cast(iValue); + + if (matData.GetIntegerParameter(MaterialData::BackFaceStencilReference, &iValue)) + m_states.backFace.stencilReference = static_cast(iValue); + + // Textures + if (matParams.loadAlphaMap && matData.GetStringParameter(MaterialData::AlphaTexturePath, &path)) + SetAlphaMap(path); + + if (matParams.loadDiffuseMap && matData.GetStringParameter(MaterialData::DiffuseTexturePath, &path)) + SetDiffuseMap(path); + + if (matParams.loadEmissiveMap && matData.GetStringParameter(MaterialData::EmissiveTexturePath, &path)) + SetEmissiveMap(path); + + if (matParams.loadHeightMap && matData.GetStringParameter(MaterialData::HeightTexturePath, &path)) + SetHeightMap(path); + + if (matParams.loadNormalMap && matData.GetStringParameter(MaterialData::NormalTexturePath, &path)) + SetNormalMap(path); + + if (matParams.loadSpecularMap && matData.GetStringParameter(MaterialData::SpecularTexturePath, &path)) + SetSpecularMap(path); + + SetShader(matParams.shaderName); + } + void Material::Enable(RendererParameter renderParameter, bool enable) { #ifdef NAZARA_DEBUG diff --git a/src/Nazara/Utility/Formats/MD2Loader.cpp b/src/Nazara/Utility/Formats/MD2Loader.cpp index 184adfe17..eef4ac63d 100644 --- a/src/Nazara/Utility/Formats/MD2Loader.cpp +++ b/src/Nazara/Utility/Formats/MD2Loader.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,11 @@ namespace Nz for (unsigned int i = 0; i < header.num_skins; ++i) { stream.Read(skin, 68*sizeof(char)); - mesh->SetMaterial(i, baseDir + skin); + + ParameterList matData; + matData.SetParameter(MaterialData::FilePath, baseDir + skin); + + mesh->SetMaterialData(i, std::move(matData)); } } } diff --git a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp index 629452161..9f7b6151c 100644 --- a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp +++ b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -189,7 +190,10 @@ namespace Nz vertexMapper.Unmap(); // Material - mesh->SetMaterial(i, baseDir + md5Mesh.shader); + ParameterList matData; + matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader); + + mesh->SetMaterialData(i, std::move(matData)); // Submesh SkeletalMeshRef subMesh = SkeletalMesh::New(mesh); @@ -285,7 +289,10 @@ namespace Nz mesh->AddSubMesh(subMesh); // Material - mesh->SetMaterial(i, baseDir + md5Mesh.shader); + ParameterList matData; + matData.SetParameter(MaterialData::FilePath, baseDir + md5Mesh.shader); + + mesh->SetMaterialData(i, std::move(matData)); } if (parameters.center) diff --git a/src/Nazara/Graphics/Formats/OBJLoader.cpp b/src/Nazara/Utility/Formats/OBJLoader.cpp similarity index 67% rename from src/Nazara/Graphics/Formats/OBJLoader.cpp rename to src/Nazara/Utility/Formats/OBJLoader.cpp index 09ad743d7..75b5ba22f 100644 --- a/src/Nazara/Graphics/Formats/OBJLoader.cpp +++ b/src/Nazara/Utility/Formats/OBJLoader.cpp @@ -1,14 +1,13 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Graphics module" +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp -#include +#include #include #include -#include -#include #include #include +#include #include #include #include @@ -17,7 +16,7 @@ #include #include #include -#include +#include ///TODO: N'avoir qu'un seul VertexBuffer communs à tous les meshes @@ -30,7 +29,7 @@ namespace Nz return (extension == "obj"); } - Ternary Check(Stream& stream, const ModelParameters& parameters) + Ternary Check(Stream& stream, const MeshParams& parameters) { NazaraUnused(stream); @@ -41,7 +40,7 @@ namespace Nz return Ternary_Unknown; } - bool LoadMaterials(Model* model, const String& filePath, const MaterialParams& parameters, const String* materials, const OBJParser::Mesh* meshes, unsigned int meshCount) + bool ParseMTL(Mesh* mesh, const String& filePath, const String* materials, const OBJParser::Mesh* meshes, unsigned int meshCount) { File file(filePath); if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) @@ -57,7 +56,7 @@ namespace Nz return false; } - std::unordered_map materialCache; + std::unordered_map materialCache; String baseDir = file.GetDirectory(); for (unsigned int i = 0; i < meshCount; ++i) { @@ -72,8 +71,9 @@ namespace Nz auto it = materialCache.find(matName); if (it == materialCache.end()) { - MaterialRef material = Material::New(); - material->SetShader(parameters.shaderName); + ParameterList data; + + data.SetParameter(MaterialData::CustomDefined); UInt8 alphaValue = static_cast(mtlMat->alpha*255.f); @@ -84,54 +84,40 @@ namespace Nz diffuseColor.a = alphaValue; specularColor.a = alphaValue; - material->SetAmbientColor(ambientColor); - material->SetDiffuseColor(diffuseColor); - material->SetSpecularColor(specularColor); - material->SetShininess(mtlMat->shininess); + data.SetParameter(MaterialData::AmbientColor, ambientColor); + data.SetParameter(MaterialData::DiffuseColor, diffuseColor); + data.SetParameter(MaterialData::Shininess, mtlMat->shininess); + data.SetParameter(MaterialData::SpecularColor, specularColor); - bool isTranslucent = (alphaValue != 255); + if (!mtlMat->alphaMap.IsEmpty()) + data.SetParameter(MaterialData::AlphaTexturePath, baseDir + mtlMat->alphaMap); - if (parameters.loadAlphaMap && !mtlMat->alphaMap.IsEmpty()) + if (!mtlMat->diffuseMap.IsEmpty()) + data.SetParameter(MaterialData::DiffuseTexturePath, baseDir + mtlMat->diffuseMap); + + if (!mtlMat->specularMap.IsEmpty()) + data.SetParameter(MaterialData::SpecularTexturePath, baseDir + mtlMat->specularMap); + + // If we either have an alpha value or an alpha map, let's configure the material for transparency + if (alphaValue != 255 || !mtlMat->alphaMap.IsEmpty()) { - if (material->SetAlphaMap(baseDir + mtlMat->alphaMap)) - isTranslucent = true; // Une alpha map indique de la transparence - else - NazaraWarning("Failed to load alpha map (" + mtlMat->alphaMap + ')'); + // Some default settings + data.SetParameter(MaterialData::Blending, true); + data.SetParameter(MaterialData::DepthWrite, true); + data.SetParameter(MaterialData::DstBlend, static_cast(BlendFunc_InvSrcAlpha)); + data.SetParameter(MaterialData::SrcBlend, static_cast(BlendFunc_SrcAlpha)); } - if (parameters.loadDiffuseMap && !mtlMat->diffuseMap.IsEmpty()) - { - if (!material->SetDiffuseMap(baseDir + mtlMat->diffuseMap)) - NazaraWarning("Failed to load diffuse map (" + mtlMat->diffuseMap + ')'); - } - - if (parameters.loadSpecularMap && !mtlMat->specularMap.IsEmpty()) - { - if (!material->SetSpecularMap(baseDir + mtlMat->specularMap)) - NazaraWarning("Failed to load specular map (" + mtlMat->specularMap + ')'); - } - - // Si nous avons une alpha map ou des couleurs transparentes, - // nous devons configurer le matériau pour accepter la transparence au mieux - if (isTranslucent) - { - // On paramètre le matériau pour accepter la transparence au mieux - material->Enable(RendererParameter_Blend, true); - material->Enable(RendererParameter_DepthWrite, false); - material->SetDstBlend(BlendFunc_InvSrcAlpha); - material->SetSrcBlend(BlendFunc_SrcAlpha); - } - - it = materialCache.emplace(matName, std::move(material)).first; + it = materialCache.emplace(matName, std::move(data)).first; } - model->SetMaterial(meshes[i].material, it->second); + mesh->SetMaterialData(meshes[i].material, it->second); } return true; } - bool Load(Model* model, Stream& stream, const ModelParameters& parameters) + bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) { int reservedVertexCount; if (!parameters.custom.GetIntegerParameter("NativeOBJLoader_VertexCount", &reservedVertexCount)) @@ -144,12 +130,7 @@ namespace Nz return false; } - MeshRef mesh = Mesh::New(); - if (!mesh->CreateStatic()) // Ne devrait jamais échouer - { - NazaraInternalError("Failed to create mesh"); - return false; - } + mesh->CreateStatic(); const String* materials = parser.GetMaterials(); const Vector4f* positions = parser.GetPositions(); @@ -160,8 +141,8 @@ namespace Nz unsigned int meshCount = parser.GetMeshCount(); NazaraAssert(materials != nullptr && positions != nullptr && normals != nullptr && - texCoords != nullptr && meshes != nullptr && meshCount > 0, - "Invalid OBJParser output"); + texCoords != nullptr && meshes != nullptr && meshCount > 0, + "Invalid OBJParser output"); // Un conteneur temporaire pour contenir les indices de face avant triangulation std::vector faceIndices(3); // Comme il y aura au moins trois sommets @@ -197,8 +178,8 @@ namespace Nz bool operator()(const OBJParser::FaceVertex& lhs, const OBJParser::FaceVertex& rhs) const { return lhs.normal == rhs.normal && - lhs.position == rhs.position && - lhs.texCoord == rhs.texCoord; + lhs.position == rhs.position && + lhs.texCoord == rhs.texCoord; } }; @@ -230,8 +211,8 @@ namespace Nz } // Création des buffers - IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits::max(), indices.size(), parameters.mesh.storage, BufferUsage_Static); - VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.mesh.storage, BufferUsage_Static); + IndexBufferRef indexBuffer = IndexBuffer::New(vertexCount > std::numeric_limits::max(), indices.size(), parameters.storage, BufferUsage_Static); + VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage, BufferUsage_Static); // Remplissage des indices IndexMapper indexMapper(indexBuffer, BufferAccess_WriteOnly); @@ -254,7 +235,7 @@ namespace Nz const Vector4f& vec = positions[vertexIndices.position]; vertex.position.Set(vec.x, vec.y, vec.z); - vertex.position *= parameters.mesh.scale/vec.w; + vertex.position *= parameters.scale/vec.w; if (vertexIndices.normal >= 0) vertex.normal = normals[vertexIndices.normal]; @@ -264,7 +245,7 @@ namespace Nz if (vertexIndices.texCoord >= 0) { const Vector3f& uvw = texCoords[vertexIndices.texCoord]; - vertex.uv.Set(uvw.x, (parameters.mesh.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé + vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé } else hasTexCoords = false; @@ -279,7 +260,7 @@ namespace Nz continue; } - if (parameters.mesh.optimizeIndexBuffers) + if (parameters.optimizeIndexBuffers) indexBuffer->Optimize(); subMesh->GenerateAABB(); @@ -299,17 +280,15 @@ namespace Nz } mesh->SetMaterialCount(parser.GetMaterialCount()); - if (parameters.mesh.center) + if (parameters.center) mesh->Recenter(); - model->SetMesh(mesh); - // On charge les matériaux si demandé String mtlLib = parser.GetMtlLib(); - if (parameters.loadMaterials && !mtlLib.IsEmpty()) + if (!mtlLib.IsEmpty()) { ErrorFlags flags(ErrorFlag_ThrowExceptionDisabled); - LoadMaterials(model, stream.GetDirectory() + mtlLib, parameters.material, materials, meshes, meshCount); + ParseMTL(mesh, stream.GetDirectory() + mtlLib, materials, meshes, meshCount); } return true; @@ -320,12 +299,12 @@ namespace Nz { void RegisterOBJ() { - ModelLoader::RegisterLoader(IsSupported, Check, Load); + MeshLoader::RegisterLoader(IsSupported, Check, Load); } void UnregisterOBJ() { - ModelLoader::UnregisterLoader(IsSupported, Check, Load); + MeshLoader::UnregisterLoader(IsSupported, Check, Load); } } } diff --git a/src/Nazara/Graphics/Formats/OBJLoader.hpp b/src/Nazara/Utility/Formats/OBJLoader.hpp similarity index 100% rename from src/Nazara/Graphics/Formats/OBJLoader.hpp rename to src/Nazara/Utility/Formats/OBJLoader.hpp diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 82c903cae..fca38e415 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -52,11 +52,11 @@ namespace Nz { MeshImpl() { - materials.resize(1); // Un matériau par défaut + materialData.resize(1); // Un matériau par défaut } std::unordered_map subMeshMap; - std::vector materials; + std::vector materialData; std::vector subMeshes; AnimationType animationType; Boxf aabb; @@ -75,93 +75,36 @@ namespace Nz void Mesh::AddSubMesh(SubMesh* subMesh) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(subMesh, "Invalid submesh"); + NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type"); - if (!subMesh) - { - NazaraError("Invalid submesh"); - return; - } - - if (subMesh->GetAnimationType() != m_impl->animationType) - { - NazaraError("Submesh animation type must match mesh animation type"); - return; - } - #endif - - m_impl->aabbUpdated = false; // On invalide l'AABB m_impl->subMeshes.push_back(subMesh); + + InvalidateAABB(); } void Mesh::AddSubMesh(const String& identifier, SubMesh* subMesh) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - - if (identifier.IsEmpty()) - { - NazaraError("Identifier is empty"); - return; - } - - auto it = m_impl->subMeshMap.find(identifier); - if (it != m_impl->subMeshMap.end()) - { - NazaraError("SubMesh identifier \"" + identifier + "\" is already used"); - return; - } - - if (!subMesh) - { - NazaraError("Invalid submesh"); - return; - } - - if (m_impl->animationType != subMesh->GetAnimationType()) - { - NazaraError("Submesh animation type must match mesh animation type"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(!identifier.IsEmpty(), "Identifier is empty"); + NazaraAssert(m_impl->subMeshMap.find(identifier) == m_impl->subMeshMap.end(), "SubMesh identifier \"" + identifier + "\" is already in use"); + NazaraAssert(subMesh, "Invalid submesh"); + NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type"); int index = m_impl->subMeshes.size(); - m_impl->aabbUpdated = false; // On invalide l'AABB m_impl->subMeshes.push_back(subMesh); m_impl->subMeshMap[identifier] = index; + + InvalidateAABB(); } SubMesh* Mesh::BuildSubMesh(const Primitive& primitive, const MeshParams& params) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return nullptr; - } - - if (m_impl->animationType != AnimationType_Static) - { - NazaraError("Mesh must be static"); - return nullptr; - } - - if (!params.IsValid()) - { - NazaraError("Parameters must be valid"); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Static, "Submesh building only works for static meshes"); + NazaraAssert(params.IsValid(), "Invalid parameters"); Boxf aabb; IndexBufferRef indexBuffer; @@ -333,17 +276,7 @@ namespace Nz void Mesh::BuildSubMeshes(const PrimitiveList& list, const MeshParams& params) { - unsigned int primitiveCount = list.GetSize(); - - #if NAZARA_UTILITY_SAFE - if (primitiveCount == 0) - { - NazaraError("PrimitiveList must have at least one primitive"); - return; - } - #endif - - for (unsigned int i = 0; i < primitiveCount; ++i) + for (unsigned int i = 0; i < list.GetSize(); ++i) BuildSubMesh(list.GetPrimitive(i), params); } @@ -351,18 +284,17 @@ namespace Nz { Destroy(); - m_impl = new MeshImpl; - m_impl->animationType = AnimationType_Skeletal; - m_impl->jointCount = jointCount; - if (!m_impl->skeleton.Create(jointCount)) + std::unique_ptr impl(new MeshImpl); + impl->animationType = AnimationType_Skeletal; + impl->jointCount = jointCount; + if (!impl->skeleton.Create(jointCount)) { - delete m_impl; - m_impl = nullptr; - NazaraError("Failed to create skeleton"); return false; } + m_impl = impl.release(); + return true; } @@ -389,13 +321,7 @@ namespace Nz void Mesh::GenerateNormals() { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); for (SubMesh* subMesh : m_impl->subMeshes) subMesh->GenerateNormals(); @@ -403,13 +329,7 @@ namespace Nz void Mesh::GenerateNormalsAndTangents() { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); for (SubMesh* subMesh : m_impl->subMeshes) subMesh->GenerateNormalsAndTangents(); @@ -417,13 +337,7 @@ namespace Nz void Mesh::GenerateTangents() { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); for (SubMesh* subMesh : m_impl->subMeshes) subMesh->GenerateTangents(); @@ -431,15 +345,7 @@ namespace Nz const Boxf& Mesh::GetAABB() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - - static Boxf dummy; - return dummy; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); if (!m_impl->aabbUpdated) { @@ -461,248 +367,121 @@ namespace Nz String Mesh::GetAnimation() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return String(); - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return m_impl->animationPath; } AnimationType Mesh::GetAnimationType() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return AnimationType_Static; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return m_impl->animationType; } unsigned int Mesh::GetJointCount() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return 0; - } - - if (m_impl->animationType != AnimationType_Skeletal) - { - NazaraError("Mesh's animation type is not skeletal"); - return 0; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); return m_impl->jointCount; } - String Mesh::GetMaterial(unsigned int index) const + ParameterList& Mesh::GetMaterialData(unsigned int index) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return String(); - } + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(index < m_impl->materialData.size(), "Material index out of range"); - if (index >= m_impl->materials.size()) - { - NazaraError("Material index out of range (" + String::Number(index) + " >= " + String::Number(m_impl->materials.size()) + ')'); - return String(); - } - #endif + return m_impl->materialData[index]; + } - return m_impl->materials[index]; + const ParameterList& Mesh::GetMaterialData(unsigned int index) const + { + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(index < m_impl->materialData.size(), "Material index out of range"); + + return m_impl->materialData[index]; } unsigned int Mesh::GetMaterialCount() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); - return m_impl->materials.size(); + return m_impl->materialData.size(); } Skeleton* Mesh::GetSkeleton() { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Animation not created"); - return nullptr; - } - - if (m_impl->animationType != AnimationType_Skeletal) - { - NazaraError("Mesh's animation type is not skeletal"); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); return &m_impl->skeleton; } const Skeleton* Mesh::GetSkeleton() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Animation not created"); - return nullptr; - } - - if (m_impl->animationType != AnimationType_Skeletal) - { - NazaraError("Mesh's animation type is not skeletal"); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); return &m_impl->skeleton; } SubMesh* Mesh::GetSubMesh(const String& identifier) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); auto it = m_impl->subMeshMap.find(identifier); - - #if NAZARA_UTILITY_SAFE - if (it == m_impl->subMeshMap.end()) - { - NazaraError("SubMesh not found"); - return nullptr; - } - #endif + NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); return m_impl->subMeshes[it->second]; } SubMesh* Mesh::GetSubMesh(unsigned int index) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return nullptr; - } - - if (index >= m_impl->subMeshes.size()) - { - NazaraError("SubMesh index out of range (" + String::Number(index) + " >= " + String::Number(m_impl->subMeshes.size()) + ')'); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); return m_impl->subMeshes[index]; } const SubMesh* Mesh::GetSubMesh(const String& identifier) const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); auto it = m_impl->subMeshMap.find(identifier); - - #if NAZARA_UTILITY_SAFE - if (it == m_impl->subMeshMap.end()) - { - NazaraError("SubMesh not found"); - return nullptr; - } - #endif + NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); return m_impl->subMeshes[it->second]; } const SubMesh* Mesh::GetSubMesh(unsigned int index) const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return nullptr; - } - - if (index >= m_impl->subMeshes.size()) - { - NazaraError("SubMesh index out of range (" + String::Number(index) + " >= " + String::Number(m_impl->subMeshes.size()) + ')'); - return nullptr; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); return m_impl->subMeshes[index]; } unsigned int Mesh::GetSubMeshCount() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return m_impl->subMeshes.size(); } int Mesh::GetSubMeshIndex(const String& identifier) const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return -1; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); auto it = m_impl->subMeshMap.find(identifier); - - #if NAZARA_UTILITY_SAFE - if (it == m_impl->subMeshMap.end()) - { - NazaraError("SubMesh not found"); - return -1; - } - #endif + NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); return it->second; } unsigned int Mesh::GetTriangleCount() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); unsigned int triangleCount = 0; for (SubMesh* subMesh : m_impl->subMeshes) @@ -713,13 +492,7 @@ namespace Nz unsigned int Mesh::GetVertexCount() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); unsigned int vertexCount = 0; for (SubMesh* subMesh : m_impl->subMeshes) @@ -730,52 +503,28 @@ namespace Nz void Mesh::InvalidateAABB() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); m_impl->aabbUpdated = false; } bool Mesh::HasSubMesh(const String& identifier) const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return false; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end(); } bool Mesh::HasSubMesh(unsigned int index) const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return false; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return index < m_impl->subMeshes.size(); } bool Mesh::IsAnimable() const { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return false; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); return m_impl->animationType != AnimationType_Static; } @@ -802,21 +551,10 @@ namespace Nz void Mesh::Recenter() { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static"); - if (m_impl->animationType != AnimationType_Static) - { - NazaraError("Mesh must be static"); - return; - } - #endif - - // Le centre de notre mesh est le centre de l'AABB *globale* + // The center of our mesh is the center of our *global* AABB Vector3f center = GetAABB().GetCenter(); for (SubMesh* subMesh : m_impl->subMeshes) @@ -833,119 +571,62 @@ namespace Nz vertices++; } - // l'AABB ne change pas de dimensions mais seulement de position, appliquons-lui le même procédé + // Our AABB doesn't change shape, only position Boxf aabb = staticMesh->GetAABB(); aabb.Translate(-center); staticMesh->SetAABB(aabb); } - // Il ne faut pas oublier d'invalider notre AABB - m_impl->aabbUpdated = false; + InvalidateAABB(); } void Mesh::RemoveSubMesh(const String& identifier) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - - auto it = m_impl->subMeshMap.find(identifier); - if (it == m_impl->subMeshMap.end()) - { - NazaraError("SubMesh not found"); - return; - } - - unsigned int index = it->second; - #else - unsigned int index = m_impl->subMeshMap[identifier]; - #endif + unsigned int index = GetSubMeshIndex(identifier); // On déplace l'itérateur du début d'une distance de x auto it2 = m_impl->subMeshes.begin(); std::advance(it2, index); m_impl->subMeshes.erase(it2); - m_impl->aabbUpdated = false; // On invalide l'AABB + InvalidateAABB(); } void Mesh::RemoveSubMesh(unsigned int index) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - - if (index >= m_impl->subMeshes.size()) - { - NazaraError("SubMesh index out of range (" + String::Number(index) + " >= " + String::Number(m_impl->subMeshes.size()) + ')'); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); // On déplace l'itérateur du début de x auto it = m_impl->subMeshes.begin(); std::advance(it, index); m_impl->subMeshes.erase(it); - m_impl->aabbUpdated = false; // On invalide l'AABB + InvalidateAABB(); } void Mesh::SetAnimation(const String& animationPath) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - #endif + NazaraAssert(m_impl, "Mesh should be created first"); m_impl->animationPath = animationPath; } - void Mesh::SetMaterial(unsigned int matIndex, const String& materialPath) + void Mesh::SetMaterialData(unsigned int matIndex, ParameterList data) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(matIndex < m_impl->materialData.size(), "Material index out of range"); - if (matIndex >= m_impl->materials.size()) - { - NazaraError("Material index out of range (" + String::Number(matIndex) + " >= " + String::Number(m_impl->materials.size()) + ')'); - return; - } - #endif - - m_impl->materials[matIndex] = materialPath; + m_impl->materialData[matIndex] = std::move(data); } void Mesh::SetMaterialCount(unsigned int matCount) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(matCount > 0, "A mesh should have at least a material"); - if (matCount == 0) - { - NazaraError("A mesh should have at least a material"); - return; - } - #endif - - m_impl->materials.resize(matCount); + m_impl->materialData.resize(matCount); #ifdef NAZARA_DEBUG for (SubMesh* subMesh : m_impl->subMeshes) @@ -953,7 +634,7 @@ namespace Nz unsigned int matIndex = subMesh->GetMaterialIndex(); if (matIndex >= matCount) { - subMesh->SetMaterialIndex(0); // Pour empêcher un crash + subMesh->SetMaterialIndex(0); // To prevent a crash NazaraWarning("SubMesh " + String::Pointer(subMesh) + " material index is over mesh new material count (" + String::Number(matIndex) + " >= " + String::Number(matCount) + "), setting it to first material"); } } @@ -962,22 +643,8 @@ namespace Nz void Mesh::Transform(const Matrix4f& matrix) { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Mesh not created"); - return; - } - - if (m_impl->animationType != AnimationType_Static) - { - NazaraError("Mesh must be static"); - return; - } - #endif - - if (matrix.IsIdentity()) - return; + NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static"); for (SubMesh* subMesh : m_impl->subMeshes) { @@ -1000,8 +667,7 @@ namespace Nz staticMesh->SetAABB(aabb); } - // Il ne faut pas oublier d'invalider notre AABB - m_impl->aabbUpdated = false; + InvalidateAABB(); } bool Mesh::Initialize() diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index 75084b8c0..78553ce54 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ namespace Nz Loaders::RegisterFreeType(); // Image - Loaders::RegisterDDSLoader(); // Generic loader (STB) + Loaders::RegisterDDSLoader(); // DDS Loader (DirectX format) Loaders::RegisterSTBLoader(); // Generic loader (STB) Loaders::RegisterSTBSaver(); // Generic saver (STB) @@ -122,6 +123,9 @@ namespace Nz // Animation Loaders::RegisterMD5Anim(); // Loader de fichiers .md5anim (v10) + // Mesh (text) + Loaders::RegisterOBJ(); + // Mesh Loaders::RegisterMD2(); // Loader de fichiers .md2 (v8) Loaders::RegisterMD5Mesh(); // Loader de fichiers .md5mesh (v10) @@ -158,6 +162,7 @@ namespace Nz Loaders::UnregisterMD2(); Loaders::UnregisterMD5Anim(); Loaders::UnregisterMD5Mesh(); + Loaders::UnregisterOBJ(); Loaders::UnregisterPCX(); Loaders::UnregisterSTBLoader(); Loaders::UnregisterSTBSaver();