From 84039cd78ad8be4423a49d32b8c8e4830841b315 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 20 Jun 2016 13:10:09 +0200 Subject: [PATCH 01/12] Core/ObjectRef: Add comparison operators Former-commit-id: 64e1994a16df92191d22dd3d6cd9b249707c74f7 [formerly b77b0afef5c0b720b5660893adb3246c97e55797] Former-commit-id: b9dbc04e30c52f8414637b89b52028103022bead --- include/Nazara/Core/ObjectRef.hpp | 29 +++- include/Nazara/Core/ObjectRef.inl | 235 ++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+), 2 deletions(-) diff --git a/include/Nazara/Core/ObjectRef.hpp b/include/Nazara/Core/ObjectRef.hpp index 6f3ccab9a..d1cd13ec0 100644 --- a/include/Nazara/Core/ObjectRef.hpp +++ b/include/Nazara/Core/ObjectRef.hpp @@ -44,8 +44,33 @@ namespace Nz T* m_object; }; - template struct PointedType> {typedef T type;}; - template struct PointedType const> {typedef T type;}; + template bool operator==(const ObjectRef& lhs, const ObjectRef& rhs); + template bool operator==(const T& lhs, const ObjectRef& rhs); + template bool operator==(const ObjectRef& lhs, const T& rhs); + + template bool operator!=(const ObjectRef& lhs, const ObjectRef& rhs); + template bool operator!=(const T& lhs, const ObjectRef& rhs); + template bool operator!=(const ObjectRef& lhs, const T& rhs); + + template bool operator<(const ObjectRef& lhs, const ObjectRef& rhs); + template bool operator<(const T& lhs, const ObjectRef& rhs); + template bool operator<(const ObjectRef& lhs, const T& rhs); + + template bool operator<=(const ObjectRef, const ObjectRef& rhs); + template bool operator<=(const T& lhs, const ObjectRef& rhs); + template bool operator<=(const ObjectRef& lhs, const T& rhs); + + template bool operator>(const ObjectRef& lhs, const ObjectRef& rhs); + template bool operator>(const T& lhs, const ObjectRef& rhs); + template bool operator>(const ObjectRef& lhs, const T& rhs); + + template bool operator>=(const ObjectRef& lhs, const ObjectRef& rhs); + template bool operator>=(const T& lhs, const ObjectRef& rhs); + template bool operator>=(const ObjectRef& lhs, const T& rhs); + + + template struct PointedType> { typedef T type; }; + template struct PointedType const> { typedef T type; }; } #include diff --git a/include/Nazara/Core/ObjectRef.inl b/include/Nazara/Core/ObjectRef.inl index ad74b4f2e..8dab06948 100644 --- a/include/Nazara/Core/ObjectRef.inl +++ b/include/Nazara/Core/ObjectRef.inl @@ -245,6 +245,241 @@ namespace Nz return *this; } + + + /*! + * \brief Checks whether the first object handle is equal to the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator==(const ObjectRef& lhs, const ObjectRef& rhs) + { + return lhs.Get() == rhs.Get(); + } + + /*! + * \brief Checks whether the object is equal to the second object handle + * \return true if it is the case + * + * \param first Object to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator==(const T& lhs, const ObjectRef& rhs) + { + return &lhs == rhs.Get(); + } + + /*! + * \brief Checks whether the object handle is equal to the second object + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second Object to compare in right hand side + */ + template + bool operator==(const ObjectRef& lhs, const T& rhs) + { + return lhs.Get() == &rhs; + } + + /*! + * \brief Checks whether the first object handle is equal to the second object handle + * \return false if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator!=(const ObjectRef& lhs, const ObjectRef& rhs) + { + return !(lhs == rhs); + } + + /*! + * \brief Checks whether the object is equal to the second object handle + * \return false if it is the case + * + * \param first Object to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator!=(const T& lhs, const ObjectRef& rhs) + { + return !(lhs == rhs); + } + + /*! + * \brief Checks whether the object handle is equal to the second object + * \return false if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second Object to compare in right hand side + */ + template + bool operator!=(const ObjectRef& lhs, const T& rhs) + { + return !(lhs == rhs); + } + + /*! + * \brief Checks whether the first object handle is less than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<(const ObjectRef& lhs, const ObjectRef& rhs) + { + return lhs.m_object < rhs.m_object; + } + + /*! + * \brief Checks whether the first object handle is less than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<(const T& lhs, const ObjectRef& rhs) + { + return &lhs < rhs.m_object; + } + + /*! + * \brief Checks whether the first object handle is less than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<(const ObjectRef& lhs, const T& rhs) + { + return lhs.m_object < &rhs; + } + + /*! + * \brief Checks whether the first object handle is less or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<=(const ObjectRef& lhs, const ObjectRef& rhs) + { + return !(lhs > rhs); + } + + /*! + * \brief Checks whether the first object handle is less or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<=(const T& lhs, const ObjectRef& rhs) + { + return !(lhs > rhs); + } + + /*! + * \brief Checks whether the first object handle is less or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator<=(const ObjectRef& lhs, const T& rhs) + { + return !(lhs > rhs); + } + + /*! + * \brief Checks whether the first object handle is greather than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>(const ObjectRef& lhs, const ObjectRef& rhs) + { + return rhs < lhs; + } + + /*! + * \brief Checks whether the first object handle is greather than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>(const T& lhs, const ObjectRef& rhs) + { + return rhs < lhs; + } + + /*! + * \brief Checks whether the first object handle is greather than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>(const ObjectRef& lhs, const T& rhs) + { + return rhs < lhs; + } + + /*! + * \brief Checks whether the first object handle is greather or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>=(const ObjectRef& lhs, const ObjectRef& rhs) + { + return !(lhs < rhs); + } + + /*! + * \brief Checks whether the first object handle is greather or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>=(const T& lhs, const ObjectRef& rhs) + { + return !(lhs < rhs); + } + + /*! + * \brief Checks whether the first object handle is greather or equal than the second object handle + * \return true if it is the case + * + * \param first ObjectRef to compare in left hand side + * \param second ObjectRef to compare in right hand side + */ + template + bool operator>=(const ObjectRef& lhs, const T& rhs) + { + return !(lhs < rhs); + } } namespace std From 04e52caa88301d2504db4bef33b5d82ceeb81092 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 20 Jun 2016 13:11:31 +0200 Subject: [PATCH 02/12] Sdk/GraphicsComponent: Add Detach method Former-commit-id: 16bcd7d8a3b50235cdd50443d8a1ed55e4b939f2 [formerly 93e838eebb955d5bbe17113ced86a247122bf522] Former-commit-id: be3d0d2e8fb9a887eb903c6b17f16a56e5eee1c7 --- .../NDK/Components/GraphicsComponent.hpp | 18 ++++++++++++++++++ .../NDK/Components/GraphicsComponent.inl | 13 +++++++++++++ .../Nazara/Graphics/InstancedRenderable.hpp | 17 +++++++++++++++-- src/Nazara/Core/String.cpp | 2 +- src/Nazara/Graphics/Billboard.cpp | 2 +- src/Nazara/Graphics/InstancedRenderable.cpp | 2 +- src/Nazara/Graphics/Model.cpp | 2 +- src/Nazara/Graphics/SkeletalModel.cpp | 2 +- src/Nazara/Graphics/Sprite.cpp | 8 ++++---- src/Nazara/Graphics/TextSprite.cpp | 2 +- 10 files changed, 56 insertions(+), 12 deletions(-) diff --git a/SDK/include/NDK/Components/GraphicsComponent.hpp b/SDK/include/NDK/Components/GraphicsComponent.hpp index c94cec4ab..f079303b8 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.hpp +++ b/SDK/include/NDK/Components/GraphicsComponent.hpp @@ -31,6 +31,8 @@ namespace Ndk inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0); + inline void Detach(Nz::InstancedRenderableRef renderable); + inline void EnsureBoundingVolumeUpdate() const; inline void EnsureTransformMatrixUpdate() const; @@ -63,6 +65,22 @@ namespace Ndk { } + Renderable(Renderable&& renderable) noexcept : + data(std::move(renderable.data)), + renderable(std::move(renderable.renderable)), + dataUpdated(renderable.dataUpdated) + { + } + + Renderable& operator=(Renderable&& r) noexcept + { + data = std::move(r.data); + dataUpdated = r.dataUpdated; + renderable = std::move(r.renderable); + + return *this; + } + NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateData, renderableInvalidationSlot); mutable Nz::InstancedRenderable::InstanceData data; diff --git a/SDK/include/NDK/Components/GraphicsComponent.inl b/SDK/include/NDK/Components/GraphicsComponent.inl index c330da5eb..c736ecc48 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.inl +++ b/SDK/include/NDK/Components/GraphicsComponent.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include +#include "GraphicsComponent.hpp" namespace Ndk { @@ -46,6 +47,18 @@ namespace Ndk InvalidateBoundingVolume(); } + inline void GraphicsComponent::Detach(Nz::InstancedRenderableRef renderable) + { + for (auto it = m_renderables.begin(); it != m_renderables.end(); ++it) + { + if (it->renderable == renderable) + { + m_renderables.erase(it); + break; + } + } + } + inline void GraphicsComponent::EnsureBoundingVolumeUpdate() const { if (!m_boundingVolumeUpdated) diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index 561cc4c97..d1c07bf9b 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -55,14 +55,27 @@ namespace Nz struct InstanceData { InstanceData(Matrix4f& referenceMatrix) : - transformMatrix(referenceMatrix), + transformMatrix(&referenceMatrix), flags(0) { } + InstanceData(InstanceData&& instanceData) noexcept = default; + + InstanceData& operator=(InstanceData&& instanceData) noexcept + { + data = std::move(instanceData.data); + flags = instanceData.flags; + renderOrder = instanceData.renderOrder; + transformMatrix = instanceData.transformMatrix; + volume = instanceData.volume; + + return *this; + } + std::vector data; BoundingVolumef volume; - Matrix4f& transformMatrix; + Matrix4f* transformMatrix; UInt32 flags; int renderOrder; }; diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index a57d89861..21831bcdf 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -211,7 +211,7 @@ namespace Nz */ String::String(const std::string& string) : - String(string.c_str(), string.size()) + String(string.data(), string.size()) { } diff --git a/src/Nazara/Graphics/Billboard.cpp b/src/Nazara/Graphics/Billboard.cpp index 6f47e9847..e06d3c921 100644 --- a/src/Nazara/Graphics/Billboard.cpp +++ b/src/Nazara/Graphics/Billboard.cpp @@ -30,7 +30,7 @@ namespace Nz if (!m_material) return; - renderQueue->AddBillboard(instanceData.renderOrder, m_material, instanceData.transformMatrix.GetTranslation(), m_size, m_sinCos, m_color); + renderQueue->AddBillboard(instanceData.renderOrder, m_material, instanceData.transformMatrix->GetTranslation(), m_size, m_sinCos, m_color); } /* diff --git a/src/Nazara/Graphics/InstancedRenderable.cpp b/src/Nazara/Graphics/InstancedRenderable.cpp index ef5f62b96..03da17984 100644 --- a/src/Nazara/Graphics/InstancedRenderable.cpp +++ b/src/Nazara/Graphics/InstancedRenderable.cpp @@ -80,7 +80,7 @@ namespace Nz NazaraAssert(instanceData, "Invalid instance data"); NazaraUnused(instanceData); - instanceData->volume.Update(instanceData->transformMatrix); + instanceData->volume.Update(*instanceData->transformMatrix); } /*! diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index d382c77d9..2b9e03cc1 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -82,7 +82,7 @@ namespace Nz meshData.primitiveMode = mesh->GetPrimitiveMode(); meshData.vertexBuffer = mesh->GetVertexBuffer(); - renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), instanceData.transformMatrix); + renderQueue->AddMesh(instanceData.renderOrder, material, meshData, mesh->GetAABB(), *instanceData.transformMatrix); } } diff --git a/src/Nazara/Graphics/SkeletalModel.cpp b/src/Nazara/Graphics/SkeletalModel.cpp index b91ac0076..8621d1fce 100644 --- a/src/Nazara/Graphics/SkeletalModel.cpp +++ b/src/Nazara/Graphics/SkeletalModel.cpp @@ -69,7 +69,7 @@ namespace Nz meshData.primitiveMode = mesh->GetPrimitiveMode(); meshData.vertexBuffer = SkinningManager::GetBuffer(mesh, &m_skeleton); - renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), instanceData.transformMatrix); + renderQueue->AddMesh(instanceData.renderOrder, material, meshData, m_skeleton.GetAABB(), *instanceData.transformMatrix); } } diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 76bf5fff2..4bf076183 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -58,19 +58,19 @@ namespace Nz SparsePtr texCoordPtr(&vertices[0].uv, sizeof(VertexStruct_XYZ_Color_UV)); *colorPtr++ = m_color; - *posPtr++ = instanceData->transformMatrix.Transform(Vector3f(0.f)); + *posPtr++ = instanceData->transformMatrix->Transform(Vector3f(0.f)); *texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftTop); *colorPtr++ = m_color; - *posPtr++ = instanceData->transformMatrix.Transform(m_size.x*Vector3f::Right()); + *posPtr++ = instanceData->transformMatrix->Transform(m_size.x*Vector3f::Right()); *texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightTop); *colorPtr++ = m_color; - *posPtr++ = instanceData->transformMatrix.Transform(m_size.y*Vector3f::Down()); + *posPtr++ = instanceData->transformMatrix->Transform(m_size.y*Vector3f::Down()); *texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_LeftBottom); *colorPtr++ = m_color; - *posPtr++ = instanceData->transformMatrix.Transform(m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down()); + *posPtr++ = instanceData->transformMatrix->Transform(m_size.x*Vector3f::Right() + m_size.y*Vector3f::Down()); *texCoordPtr++ = m_textureCoords.GetCorner(RectCorner_RightBottom); } diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 42dba4aaf..2f1d733b4 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -310,7 +310,7 @@ namespace Nz Vector3f localPos = localVertex->position.x*Vector3f::Right() + localVertex->position.y*Vector3f::Down(); localPos *= m_scale; - *pos++ = instanceData->transformMatrix.Transform(localPos); + *pos++ = instanceData->transformMatrix->Transform(localPos); *color++ = m_color * localVertex->color; *uv++ = localVertex->uv; From bd2b73bba7419a101922d83262990c18f2bcaf96 Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 20 Jun 2016 13:12:09 +0200 Subject: [PATCH 03/12] Renderer/RenderWindow: Fix visibility of OnWindow*() events Former-commit-id: 221602aecc845cf0b8c385d7ffd7bbf94fcc716f [formerly 43f42f18548e618a5af37d8b4a2e195694d925b8] Former-commit-id: 30084dc77a88fc721f06b28755a44b7ffa32e2a3 --- include/Nazara/Renderer/RenderWindow.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index d9889d803..1cda9d63d 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -65,12 +65,11 @@ namespace Nz protected: bool Activate() const override; void EnsureTargetUpdated() const override; - - private: bool OnWindowCreated() override; void OnWindowDestroy() override; void OnWindowResized() override; + private: mutable std::vector m_buffer; Clock m_clock; ContextParameters m_parameters; From 63ed1aaa51d9a1eaa632ad280a590ece398ff4a7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 21 Jun 2016 19:14:29 +0200 Subject: [PATCH 04/12] Sdk/GraphicsComponent: Add Clear method Former-commit-id: dfa7a9813fe3e15212c16103763cb185e1d8df30 [formerly ead9d5788df957502aa22c526fa272f797348599] Former-commit-id: 74ce601066d7ab1d28609d6a859495e4626c7a18 --- SDK/include/NDK/Components/GraphicsComponent.hpp | 4 +++- SDK/include/NDK/Components/GraphicsComponent.inl | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/SDK/include/NDK/Components/GraphicsComponent.hpp b/SDK/include/NDK/Components/GraphicsComponent.hpp index f079303b8..aed427105 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.hpp +++ b/SDK/include/NDK/Components/GraphicsComponent.hpp @@ -31,7 +31,9 @@ namespace Ndk inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0); - inline void Detach(Nz::InstancedRenderableRef renderable); + inline void Clear(); + + inline void Detach(const Nz::InstancedRenderableRef& renderable); inline void EnsureBoundingVolumeUpdate() const; inline void EnsureTransformMatrixUpdate() const; diff --git a/SDK/include/NDK/Components/GraphicsComponent.inl b/SDK/include/NDK/Components/GraphicsComponent.inl index c736ecc48..9ca100d0e 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.inl +++ b/SDK/include/NDK/Components/GraphicsComponent.inl @@ -47,12 +47,20 @@ namespace Ndk InvalidateBoundingVolume(); } - inline void GraphicsComponent::Detach(Nz::InstancedRenderableRef renderable) + inline void GraphicsComponent::Clear() + { + m_renderables.clear(); + + InvalidateBoundingVolume(); + } + + inline void GraphicsComponent::Detach(const Nz::InstancedRenderableRef& renderable) { for (auto it = m_renderables.begin(); it != m_renderables.end(); ++it) { if (it->renderable == renderable) { + InvalidateBoundingVolume(); m_renderables.erase(it); break; } From 9215e80db6b4fd014dc93145b198894abb43ee42 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 23 Jun 2016 00:37:32 +0200 Subject: [PATCH 05/12] Core/PluginManager: Fix usage of Mount(Plugin) Former-commit-id: b1e02a118828724f83be8830e4f0c8966558d0fa [formerly a1c537e8962a75da319c127e8b9bc27109a595bb] Former-commit-id: 6e706993915981df3b77ae7ae1c9139eb5d97ac4 --- src/Nazara/Core/PluginManager.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Core/PluginManager.cpp b/src/Nazara/Core/PluginManager.cpp index 24fbafcfb..b71af6677 100644 --- a/src/Nazara/Core/PluginManager.cpp +++ b/src/Nazara/Core/PluginManager.cpp @@ -19,8 +19,7 @@ namespace Nz String s_pluginFiles[] = { - "NazaraAssimp", // Plugin_Assimp - "NazaraFreetype" // Plugin_FreeType + "PluginAssimp", // Plugin_Assimp }; } @@ -80,7 +79,13 @@ namespace Nz bool PluginManager::Mount(Plugin plugin) { - return Mount(s_pluginFiles[plugin]); + Nz::String pluginName = s_pluginFiles[plugin]; + #ifdef NAZARA_DEBUG + if (Mount(pluginName + "-d", true)) + return true; + #endif + + return Mount(pluginName, true); } /*! From c83b9d049193486c66002e735b286f5155161838 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 08:56:18 +0200 Subject: [PATCH 06/12] Graphics/Material: Add SaveToParameters Former-commit-id: 87b9ca6e0f5f391f45edf6106efbd550dd52ac53 [formerly 91ba614d69d3a2e9762da0e059ee96985c891749] Former-commit-id: e049a9db776f407e2cd7635bfb1825d809223c77 --- include/Nazara/Graphics/Material.hpp | 2 + src/Nazara/Graphics/Material.cpp | 100 ++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 85c4d315c..b30c215c1 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -120,6 +120,8 @@ namespace Nz void Reset(); + void SaveToParameters(ParameterList* matData); + inline bool SetAlphaMap(const String& textureName); inline void SetAlphaMap(TextureRef alphaMap); inline void SetAlphaThreshold(float alphaThreshold); diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index bfc6ee88a..14da83eb0 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -310,10 +310,108 @@ namespace Nz SetShader(matParams.shaderName); } + void Material::SaveToParameters(ParameterList* matData) + { + NazaraAssert(matData, "Invalid ParameterList"); + + matData->SetParameter(MaterialData::AlphaTest, IsAlphaTestEnabled()); + matData->SetParameter(MaterialData::AlphaThreshold, GetAlphaThreshold()); + matData->SetParameter(MaterialData::AmbientColor, GetAmbientColor()); + matData->SetParameter(MaterialData::CullingSide, int(GetFaceCulling())); + matData->SetParameter(MaterialData::DepthFunc, int(GetDepthFunc())); + matData->SetParameter(MaterialData::DepthSorting, IsDepthSortingEnabled()); + matData->SetParameter(MaterialData::DiffuseColor, GetDiffuseColor()); + matData->SetParameter(MaterialData::DstBlend, int(GetDstBlend())); + matData->SetParameter(MaterialData::FaceFilling, int(GetFaceFilling())); + matData->SetParameter(MaterialData::Lighting, IsLightingEnabled()); + matData->SetParameter(MaterialData::LineWidth, GetRenderStates().lineWidth); + matData->SetParameter(MaterialData::PointSize, GetRenderStates().pointSize); + matData->SetParameter(MaterialData::Shininess, GetShininess()); + matData->SetParameter(MaterialData::SpecularColor, GetSpecularColor()); + matData->SetParameter(MaterialData::SrcBlend, int(GetSrcBlend())); + matData->SetParameter(MaterialData::Transform, IsTransformEnabled()); + + // RendererParameter + matData->SetParameter(MaterialData::Blending, GetRenderStates().parameters[RendererParameter_Blend]); + matData->SetParameter(MaterialData::ColorWrite, GetRenderStates().parameters[RendererParameter_ColorWrite]); + matData->SetParameter(MaterialData::DepthBuffer, GetRenderStates().parameters[RendererParameter_DepthBuffer]); + matData->SetParameter(MaterialData::DepthWrite, GetRenderStates().parameters[RendererParameter_DepthWrite]); + matData->SetParameter(MaterialData::FaceCulling, GetRenderStates().parameters[RendererParameter_FaceCulling]); + matData->SetParameter(MaterialData::ScissorTest, GetRenderStates().parameters[RendererParameter_ScissorTest]); + matData->SetParameter(MaterialData::StencilTest, GetRenderStates().parameters[RendererParameter_StencilTest]); + + // Samplers + matData->SetParameter(MaterialData::DiffuseAnisotropyLevel, int(GetDiffuseSampler().GetAnisotropicLevel())); + matData->SetParameter(MaterialData::DiffuseFilter, int(GetDiffuseSampler().GetFilterMode())); + matData->SetParameter(MaterialData::DiffuseWrap, int(GetDiffuseSampler().GetWrapMode())); + + matData->SetParameter(MaterialData::SpecularAnisotropyLevel, int(GetSpecularSampler().GetAnisotropicLevel())); + matData->SetParameter(MaterialData::SpecularFilter, int(GetSpecularSampler().GetFilterMode())); + matData->SetParameter(MaterialData::SpecularWrap, int(GetSpecularSampler().GetWrapMode())); + + // Stencil + matData->SetParameter(MaterialData::StencilCompare, int(GetRenderStates().frontFace.stencilCompare)); + matData->SetParameter(MaterialData::StencilFail, int(GetRenderStates().frontFace.stencilFail)); + matData->SetParameter(MaterialData::StencilPass, int(GetRenderStates().frontFace.stencilPass)); + matData->SetParameter(MaterialData::StencilZFail, int(GetRenderStates().frontFace.stencilZFail)); + matData->SetParameter(MaterialData::StencilMask, int(GetRenderStates().frontFace.stencilMask)); + matData->SetParameter(MaterialData::StencilReference, int(GetRenderStates().frontFace.stencilReference)); + + // Stencil (back) + matData->SetParameter(MaterialData::BackFaceStencilCompare, int(GetRenderStates().backFace.stencilCompare)); + matData->SetParameter(MaterialData::BackFaceStencilFail, int(GetRenderStates().backFace.stencilFail)); + matData->SetParameter(MaterialData::BackFaceStencilPass, int(GetRenderStates().backFace.stencilPass)); + matData->SetParameter(MaterialData::BackFaceStencilZFail, int(GetRenderStates().backFace.stencilZFail)); + matData->SetParameter(MaterialData::BackFaceStencilMask, int(GetRenderStates().backFace.stencilMask)); + matData->SetParameter(MaterialData::BackFaceStencilReference, int(GetRenderStates().backFace.stencilReference)); + + // Textures + if (HasAlphaMap()) + { + const String& path = GetAlphaMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::AlphaTexturePath, path); + } + + if (HasDiffuseMap()) + { + const String& path = GetDiffuseMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::DiffuseTexturePath, path); + } + + if (HasEmissiveMap()) + { + const String& path = GetEmissiveMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::EmissiveTexturePath, path); + } + + if (HasHeightMap()) + { + const String& path = GetHeightMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::HeightTexturePath, path); + } + + if (HasNormalMap()) + { + const String& path = GetNormalMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::NormalTexturePath, path); + } + + if (HasSpecularMap()) + { + const String& path = GetSpecularMap()->GetFilePath(); + if (!path.IsEmpty()) + matData->SetParameter(MaterialData::SpecularTexturePath, path); + } + } + /*! * \brief Resets the material, cleans everything */ - void Material::Reset() { OnMaterialReset(this); From 832cde4bea6ce00174fe2d22034cb9b8732c1640 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 08:56:45 +0200 Subject: [PATCH 07/12] Core/StringStream: Add Clear and GetBufferSize methods Former-commit-id: 4d8b940c300ff415fb8060b0e20b3087dc6bb076 [formerly af2dfd84721ba70df0735c04021f9ff39e90d05d] Former-commit-id: 3eecd417e811c29345f502f82219754ffa54c141 --- include/Nazara/Core/StringStream.hpp | 4 +++ src/Nazara/Core/StringStream.cpp | 41 +++++++++++++--------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/include/Nazara/Core/StringStream.hpp b/include/Nazara/Core/StringStream.hpp index da68e8b27..f727ed35c 100644 --- a/include/Nazara/Core/StringStream.hpp +++ b/include/Nazara/Core/StringStream.hpp @@ -22,6 +22,10 @@ namespace Nz StringStream(const StringStream&) = default; StringStream(StringStream&&) noexcept = default; + void Clear(); + + std::size_t GetBufferSize() const; + String ToString() const; StringStream& operator=(const StringStream&) = default; diff --git a/src/Nazara/Core/StringStream.cpp b/src/Nazara/Core/StringStream.cpp index ebd509c65..14d35799d 100644 --- a/src/Nazara/Core/StringStream.cpp +++ b/src/Nazara/Core/StringStream.cpp @@ -1,3 +1,4 @@ +#include "..\..\..\include\Nazara\Core\StringStream.hpp" // Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -16,7 +17,6 @@ namespace Nz /*! * \brief Constructs a StringStream object by default */ - StringStream::StringStream() : m_bufferSize(0) { @@ -27,18 +27,34 @@ namespace Nz * * \param str First value of the stream */ - StringStream::StringStream(const String& str) : m_bufferSize(str.GetSize()) { m_strings.push_back(str); } + /*! + * \brief Resets the state of the stream, erasing every contained text + */ + void StringStream::Clear() + { + m_bufferSize = 0; + m_strings.clear(); + } + + /*! + * \brief Get the current buffer size + * \return The internal accumulation buffer size, this is equivalent to the size of the final string + */ + std::size_t StringStream::GetBufferSize() const + { + return m_bufferSize; + } + /*! * \brief Gives a string representation * \return A string representation of the object where every objects of the stream has been converted with Nz::String */ - String StringStream::ToString() const { String string; @@ -56,7 +72,6 @@ namespace Nz * * \param boolean Boolean value */ - StringStream& StringStream::operator<<(bool boolean) { m_strings.push_back(String::Boolean(boolean)); @@ -71,7 +86,6 @@ namespace Nz * * \param number Short value */ - StringStream& StringStream::operator<<(short number) { m_strings.push_back(String::Number(number)); @@ -86,7 +100,6 @@ namespace Nz * * \param number Short value */ - StringStream& StringStream::operator<<(unsigned short number) { m_strings.push_back(String::Number(number)); @@ -101,7 +114,6 @@ namespace Nz * * \param number Int value */ - StringStream& StringStream::operator<<(int number) { m_strings.push_back(String::Number(number)); @@ -116,7 +128,6 @@ namespace Nz * * \param number Int value */ - StringStream& StringStream::operator<<(unsigned int number) { m_strings.push_back(String::Number(number)); @@ -131,7 +142,6 @@ namespace Nz * * \param number Long value */ - StringStream& StringStream::operator<<(long number) { m_strings.push_back(String::Number(number)); @@ -146,7 +156,6 @@ namespace Nz * * \param number Long value */ - StringStream& StringStream::operator<<(unsigned long number) { m_strings.push_back(String::Number(number)); @@ -161,7 +170,6 @@ namespace Nz * * \param number Long long value */ - StringStream& StringStream::operator<<(long long number) { m_strings.push_back(String::Number(number)); @@ -176,7 +184,6 @@ namespace Nz * * \param number Long long value */ - StringStream& StringStream::operator<<(unsigned long long number) { m_strings.push_back(String::Number(number)); @@ -191,7 +198,6 @@ namespace Nz * * \param number Float value */ - StringStream& StringStream::operator<<(float number) { m_strings.push_back(String::Number(number)); @@ -206,7 +212,6 @@ namespace Nz * * \param number Double value */ - StringStream& StringStream::operator<<(double number) { m_strings.push_back(String::Number(number)); @@ -221,7 +226,6 @@ namespace Nz * * \param number Long double value */ - StringStream& StringStream::operator<<(long double number) { m_strings.push_back(String::Number(number)); @@ -236,7 +240,6 @@ namespace Nz * * \param character Char value */ - StringStream& StringStream::operator<<(char character) { m_strings.push_back(String(character)); @@ -251,7 +254,6 @@ namespace Nz * * \param character Char value */ - StringStream& StringStream::operator<<(unsigned char character) { m_strings.push_back(String(static_cast(character))); @@ -266,7 +268,6 @@ namespace Nz * * \param string String value */ - StringStream& StringStream::operator<<(const char* string) { m_strings.push_back(string); @@ -281,7 +282,6 @@ namespace Nz * * \param string String value */ - StringStream& StringStream::operator<<(const std::string& string) { m_strings.push_back(string); @@ -296,7 +296,6 @@ namespace Nz * * \param string String value */ - StringStream& StringStream::operator<<(const String& string) { m_strings.push_back(string); @@ -311,7 +310,6 @@ namespace Nz * * \param ptr Pointer value */ - StringStream& StringStream::operator<<(const void* ptr) { m_strings.push_back(String::Pointer(ptr)); @@ -324,7 +322,6 @@ namespace Nz * \brief Converts this to Nz::String * \return The string representation of the stream */ - StringStream::operator String() const { return ToString(); From 0b0dfda89d7f720c4c71275d960f57fd59031062 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 08:57:11 +0200 Subject: [PATCH 08/12] Utility/MaterialData: Fix FaceCulling being used for FaceSide Former-commit-id: b82f598a9c94700bea58d651b5f29dcf47251af1 [formerly 5790a8397870a66dfaeb9e56862e5fb2ae850cfc] Former-commit-id: 93372a3b733d3c84de11abacc6eaa3804b98079a --- include/Nazara/Utility/MaterialData.hpp | 1 + src/Nazara/Graphics/Material.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/Nazara/Utility/MaterialData.hpp b/include/Nazara/Utility/MaterialData.hpp index ea8ffd0f5..66df97689 100644 --- a/include/Nazara/Utility/MaterialData.hpp +++ b/include/Nazara/Utility/MaterialData.hpp @@ -22,6 +22,7 @@ namespace Nz static constexpr const char* BackFaceStencilReference = "MatBackFaceStencilReference"; static constexpr const char* BackFaceStencilZFail = "MatBackFaceStencilZFail"; static constexpr const char* Blending = "MatBlending"; + static constexpr const char* CullingSide = "MatCullingSide"; static constexpr const char* CustomDefined = "MatCustomDefined"; static constexpr const char* ColorWrite = "MatColorWrite"; static constexpr const char* DepthBuffer = "MatDepthBuffer"; diff --git a/src/Nazara/Graphics/Material.cpp b/src/Nazara/Graphics/Material.cpp index 14da83eb0..651f2581c 100644 --- a/src/Nazara/Graphics/Material.cpp +++ b/src/Nazara/Graphics/Material.cpp @@ -170,6 +170,9 @@ namespace Nz if (matData.GetColorParameter(MaterialData::AmbientColor, &color)) SetAmbientColor(color); + if (matData.GetIntegerParameter(MaterialData::CullingSide, &iValue)) + SetFaceCulling(static_cast(iValue)); + if (matData.GetIntegerParameter(MaterialData::DepthFunc, &iValue)) SetDepthFunc(static_cast(iValue)); @@ -182,9 +185,6 @@ namespace Nz 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)); From 964b4cf730ab530ac5a2be99f8100595bb214754 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 08:57:29 +0200 Subject: [PATCH 09/12] Renderer/Texture: Remember FilePath when loading from an image Former-commit-id: 45ccc8b81490ab30e0f31b09a77ab77bcee6c975 [formerly ba58653223f2c61a0b8ba3a5f3abae8037efc266] Former-commit-id: 81e567f17199a829cc03004bca17699a34fb516d --- src/Nazara/Renderer/Texture.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index b8bed61a0..458fb9992 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -582,6 +582,9 @@ namespace Nz } } + // Keep resource path info + SetFilePath(image.GetFilePath()); + destroyOnExit.Reset(); return true; From a92a3a290113d9b01ee3334baa31c7b60ca1a9e1 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 09:00:35 +0200 Subject: [PATCH 10/12] Utility/OBJParser: Optimized loading Former-commit-id: b21724d63e15bda0a9c5b8a4c9941b4b606b3525 [formerly 375bc4032044631fd2a1f51f3407b71c2c582944] Former-commit-id: aa71b4fcfacd25991da8c3b69fbc7ac9c0039ad6 --- include/Nazara/Utility/Formats/OBJParser.hpp | 50 ++-- include/Nazara/Utility/Formats/OBJParser.inl | 88 +++++++ src/Nazara/Utility/Formats/OBJLoader.cpp | 22 +- src/Nazara/Utility/Formats/OBJParser.cpp | 253 +++++++------------ 4 files changed, 222 insertions(+), 191 deletions(-) create mode 100644 include/Nazara/Utility/Formats/OBJParser.inl diff --git a/include/Nazara/Utility/Formats/OBJParser.hpp b/include/Nazara/Utility/Formats/OBJParser.hpp index 90e653f93..64fd0ce4c 100644 --- a/include/Nazara/Utility/Formats/OBJParser.hpp +++ b/include/Nazara/Utility/Formats/OBJParser.hpp @@ -29,51 +29,59 @@ namespace Nz struct Face { - std::vector vertices; + std::size_t firstVertex; + std::size_t vertexCount; }; struct Mesh { std::vector faces; + std::vector vertices; String name; - unsigned int material; + std::size_t material; }; - OBJParser(Stream& stream$); - ~OBJParser(); + OBJParser() = default; + ~OBJParser() = default; - const String* GetMaterials() const; - unsigned int GetMaterialCount() const; - const Mesh* GetMeshes() const; - unsigned int GetMeshCount() const; - const String& GetMtlLib() const; - const Vector3f* GetNormals() const; - unsigned int GetNormalCount() const; - const Vector4f* GetPositions() const; - unsigned int GetPositionCount() const; - const Vector3f* GetTexCoords() const; - unsigned int GetTexCoordCount() const; + inline const String* GetMaterials() const; + inline unsigned int GetMaterialCount() const; + inline const Mesh* GetMeshes() const; + inline unsigned int GetMeshCount() const; + inline const String& GetMtlLib() const; + inline const Vector3f* GetNormals() const; + inline unsigned int GetNormalCount() const; + inline const Vector4f* GetPositions() const; + inline unsigned int GetPositionCount() const; + inline const Vector3f* GetTexCoords() const; + inline unsigned int GetTexCoordCount() const; - bool Parse(std::size_t reservedVertexCount = 100); + bool Parse(Stream& stream, std::size_t reservedVertexCount = 100); private: bool Advance(bool required = true); - void Error(const String& message); - void Warning(const String& message); - void UnrecognizedLine(bool error = false); + template void Emit(const T& text) const; + inline void EmitLine() const; + template void EmitLine(const T& line) const; + inline void Error(const String& message); + inline void Flush() const; + inline void Warning(const String& message); + inline void UnrecognizedLine(bool error = false); std::vector m_meshes; std::vector m_materials; std::vector m_normals; std::vector m_positions; std::vector m_texCoords; - Stream& m_stream; + mutable Stream* m_currentStream; String m_currentLine; String m_mtlLib; + mutable StringStream m_outputStream; bool m_keepLastLine; unsigned int m_lineCount; - unsigned int m_streamFlags; }; } +#include + #endif // NAZARA_FORMATS_OBJPARSER_HPP diff --git a/include/Nazara/Utility/Formats/OBJParser.inl b/include/Nazara/Utility/Formats/OBJParser.inl new file mode 100644 index 000000000..c8ea75e8c --- /dev/null +++ b/include/Nazara/Utility/Formats/OBJParser.inl @@ -0,0 +1,88 @@ +// 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 + +namespace Nz +{ + inline const String* OBJParser::GetMaterials() const + { + return m_materials.data(); + } + + inline unsigned int OBJParser::GetMaterialCount() const + { + return m_materials.size(); + } + + inline const OBJParser::Mesh* OBJParser::GetMeshes() const + { + return m_meshes.data(); + } + + inline unsigned int OBJParser::GetMeshCount() const + { + return m_meshes.size(); + } + + inline const String& OBJParser::GetMtlLib() const + { + return m_mtlLib; + } + + inline const Vector3f* OBJParser::GetNormals() const + { + return m_normals.data(); + } + + inline unsigned int OBJParser::GetNormalCount() const + { + return m_normals.size(); + } + + inline const Vector4f* OBJParser::GetPositions() const + { + return m_positions.data(); + } + + inline unsigned int OBJParser::GetPositionCount() const + { + return m_positions.size(); + } + + inline const Vector3f* OBJParser::GetTexCoords() const + { + return m_texCoords.data(); + } + + inline unsigned int OBJParser::GetTexCoordCount() const + { + return m_texCoords.size(); + } + + + inline void OBJParser::Error(const String& message) + { + NazaraError(message + " at line #" + String::Number(m_lineCount)); + } + + inline void OBJParser::Warning(const String& message) + { + NazaraWarning(message + " at line #" + String::Number(m_lineCount)); + } + + inline void OBJParser::UnrecognizedLine(bool error) + { + String message = "Unrecognized \"" + m_currentLine + '"'; + + if (error) + Error(message); + else + Warning(message); + } +} + +#include diff --git a/src/Nazara/Utility/Formats/OBJLoader.cpp b/src/Nazara/Utility/Formats/OBJLoader.cpp index 05b39f81f..720b5ec5d 100644 --- a/src/Nazara/Utility/Formats/OBJLoader.cpp +++ b/src/Nazara/Utility/Formats/OBJLoader.cpp @@ -123,8 +123,8 @@ namespace Nz if (!parameters.custom.GetIntegerParameter("NativeOBJLoader_VertexCount", &reservedVertexCount)) reservedVertexCount = 100; - OBJParser parser(stream); - if (!parser.Parse(reservedVertexCount)) + OBJParser parser; + if (!parser.Parse(stream, reservedVertexCount)) { NazaraError("OBJ parser failed"); return false; @@ -177,23 +177,24 @@ namespace Nz { bool operator()(const OBJParser::FaceVertex& lhs, const OBJParser::FaceVertex& rhs) const { - return lhs.normal == rhs.normal && + return lhs.normal == rhs.normal && lhs.position == rhs.position && lhs.texCoord == rhs.texCoord; } }; std::unordered_map vertices; + vertices.reserve(meshes[i].vertices.size()); unsigned int vertexCount = 0; for (unsigned int j = 0; j < faceCount; ++j) { - unsigned int faceVertexCount = meshes[i].faces[j].vertices.size(); + unsigned int faceVertexCount = meshes[i].faces[j].vertexCount; faceIndices.resize(faceVertexCount); for (unsigned int k = 0; k < faceVertexCount; ++k) { - const OBJParser::FaceVertex& vertex = meshes[i].faces[j].vertices[k]; + const OBJParser::FaceVertex& vertex = meshes[i].vertices[meshes[i].faces[j].firstVertex + k]; auto it = vertices.find(vertex); if (it == vertices.end()) @@ -202,6 +203,7 @@ namespace Nz faceIndices[k] = it->second; } + // Triangulation for (unsigned int k = 1; k < faceVertexCount-1; ++k) { indices.push_back(faceIndices[0]); @@ -233,17 +235,17 @@ namespace Nz MeshVertex& vertex = meshVertices[index]; - const Vector4f& vec = positions[vertexIndices.position]; + const Vector4f& vec = positions[vertexIndices.position-1]; vertex.position = Vector3f(parameters.matrix * vec); - if (vertexIndices.normal >= 0) - vertex.normal = normals[vertexIndices.normal]; + if (vertexIndices.normal > 0) + vertex.normal = normals[vertexIndices.normal-1]; else hasNormals = false; - if (vertexIndices.texCoord >= 0) + if (vertexIndices.texCoord > 0) { - const Vector3f& uvw = texCoords[vertexIndices.texCoord]; + const Vector3f& uvw = texCoords[vertexIndices.texCoord-1]; vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé } else diff --git a/src/Nazara/Utility/Formats/OBJParser.cpp b/src/Nazara/Utility/Formats/OBJParser.cpp index c0daf1f84..03a251d5a 100644 --- a/src/Nazara/Utility/Formats/OBJParser.cpp +++ b/src/Nazara/Utility/Formats/OBJParser.cpp @@ -3,7 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -13,77 +13,22 @@ namespace Nz { - OBJParser::OBJParser(Stream& stream) : - m_stream(stream), - m_streamFlags(stream.GetStreamOptions()) //< Saves stream flags + bool OBJParser::Parse(Nz::Stream& stream, std::size_t reservedVertexCount) { - m_stream.EnableTextMode(true); - } + m_currentStream = &stream; - OBJParser::~OBJParser() - { - // Reset stream flags - if ((m_streamFlags & StreamOption_Text) == 0) - m_stream.EnableTextMode(false); - } + // Force stream in text mode, reset it at the end + Nz::CallOnExit resetTextMode; + if ((stream.GetStreamOptions() & StreamOption_Text) == 0) + { + stream.EnableTextMode(true); - const String* OBJParser::GetMaterials() const - { - return m_materials.data(); - } + resetTextMode.Reset([&stream] () + { + stream.EnableTextMode(false); + }); + } - unsigned int OBJParser::GetMaterialCount() const - { - return m_materials.size(); - } - - const OBJParser::Mesh* OBJParser::GetMeshes() const - { - return m_meshes.data(); - } - - unsigned int OBJParser::GetMeshCount() const - { - return m_meshes.size(); - } - - const String& OBJParser::GetMtlLib() const - { - return m_mtlLib; - } - - const Vector3f* OBJParser::GetNormals() const - { - return m_normals.data(); - } - - unsigned int OBJParser::GetNormalCount() const - { - return m_normals.size(); - } - - const Vector4f* OBJParser::GetPositions() const - { - return m_positions.data(); - } - - unsigned int OBJParser::GetPositionCount() const - { - return m_positions.size(); - } - - const Vector3f* OBJParser::GetTexCoords() const - { - return m_texCoords.data(); - } - - unsigned int OBJParser::GetTexCoordCount() const - { - return m_texCoords.size(); - } - - bool OBJParser::Parse(std::size_t reservedVertexCount) - { String matName, meshName; matName = meshName = "default"; m_keepLastLine = false; @@ -100,32 +45,56 @@ namespace Nz m_positions.reserve(reservedVertexCount); m_texCoords.reserve(reservedVertexCount); - // On va regrouper les meshs par nom et par matériau - using FaceVec = std::vector; - using MatPair = std::pair; - std::unordered_map> meshes; + // Sort meshes by material and group + using MatPair = std::pair; + std::unordered_map> meshesByName; - unsigned int matIndex = 0; - auto GetMaterial = [&meshes, &matIndex] (const String& mesh, const String& material) -> FaceVec* + std::size_t faceReserve = 0; + std::size_t vertexReserve = 0; + unsigned int matCount = 0; + auto GetMaterial = [&] (const String& meshName, const String& matName) -> Mesh* { - auto& map = meshes[mesh]; - auto it = map.find(material); + auto& map = meshesByName[meshName]; + auto it = map.find(matName); if (it == map.end()) - it = map.insert(std::make_pair(material, MatPair(FaceVec(), matIndex++))).first; + it = map.insert(std::make_pair(matName, MatPair(Mesh(), matCount++))).first; + + Mesh& mesh = it->second.first; + + mesh.faces.reserve(faceReserve); + mesh.vertices.reserve(vertexReserve); + faceReserve = 0; + vertexReserve = 0; return &(it->second.first); }; // On prépare le mesh par défaut - FaceVec* currentMesh = nullptr; + Mesh* currentMesh = nullptr; while (Advance(false)) { switch (std::tolower(m_currentLine[0])) { - case 'f': // Une face + case '#': //< Comment + // Some softwares write comments to gives the number of vertex/faces an importer can expect + std::size_t data; + if (std::sscanf(m_currentLine.GetConstBuffer(), "# position count: %zu", &data) == 1) + m_positions.reserve(data); + else if (std::sscanf(m_currentLine.GetConstBuffer(), "# normal count: %zu", &data) == 1) + m_normals.reserve(data); + else if (std::sscanf(m_currentLine.GetConstBuffer(), "# texcoords count: %zu", &data) == 1) + m_texCoords.reserve(data); + else if (std::sscanf(m_currentLine.GetConstBuffer(), "# face count: %zu", &data) == 1) + faceReserve = data; + else if (std::sscanf(m_currentLine.GetConstBuffer(), "# vertex count: %zu", &data) == 1) + vertexReserve = data; + + break; + + case 'f': //< Face { - if (m_currentLine.GetSize() < 7) // Le minimum syndical pour définir une face de trois sommets (f 1 2 3) + if (m_currentLine.GetSize() < 7) // Since we only treat triangles, this is the minimum length of a face line (f 1 2 3) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); @@ -142,17 +111,23 @@ namespace Nz break; } + if (!currentMesh) + currentMesh = GetMaterial(meshName, matName); + Face face; - face.vertices.resize(vertexCount); + face.firstVertex = currentMesh->vertices.size(); + face.vertexCount = vertexCount; + + currentMesh->vertices.resize(face.firstVertex + vertexCount, FaceVertex{0, 0, 0}); bool error = false; unsigned int pos = 2; for (unsigned int i = 0; i < vertexCount; ++i) { int offset; - int& n = face.vertices[i].normal; - int& p = face.vertices[i].position; - int& t = face.vertices[i].texCoord; + int& n = currentMesh->vertices[face.firstVertex + i].normal; + int& p = currentMesh->vertices[face.firstVertex + i].position; + int& t = currentMesh->vertices[face.firstVertex + i].texCoord; if (std::sscanf(&m_currentLine[pos], "%d/%d/%d%n", &p, &t, &n, &offset) != 3) { @@ -168,22 +143,13 @@ namespace Nz error = true; break; } - else - { - n = 0; - t = 0; - } } - else - n = 0; } - else - t = 0; } if (p < 0) { - p += m_positions.size(); + p += m_positions.size() - 1; if (p < 0) { Error("Vertex index out of range (" + String::Number(p) + " < 0"); @@ -191,48 +157,42 @@ namespace Nz break; } } - else - p--; if (n < 0) { - n += m_normals.size(); + n += m_normals.size() - 1; if (n < 0) { - Error("Vertex index out of range (" + String::Number(n) + " < 0"); + Error("Normal index out of range (" + String::Number(n) + " < 0"); error = true; break; } } - else - n--; if (t < 0) { - t += m_texCoords.size(); + t += m_texCoords.size() - 1; if (t < 0) { - Error("Vertex index out of range (" + String::Number(t) + " < 0"); + Error("Texture coordinates index out of range (" + String::Number(t) + " < 0"); error = true; break; } } - else - t--; - if (static_cast(p) >= m_positions.size()) + if (static_cast(p) > m_positions.size()) { Error("Vertex index out of range (" + String::Number(p) + " >= " + String::Number(m_positions.size()) + ')'); error = true; break; } - else if (n >= 0 && static_cast(n) >= m_normals.size()) + else if (n != 0 && static_cast(n) > m_normals.size()) { Error("Normal index out of range (" + String::Number(n) + " >= " + String::Number(m_normals.size()) + ')'); error = true; break; } - else if (t >= 0 && static_cast(t) >= m_texCoords.size()) + else if (t != 0 && static_cast(t) > m_texCoords.size()) { Error("TexCoord index out of range (" + String::Number(t) + " >= " + String::Number(m_texCoords.size()) + ')'); error = true; @@ -243,17 +203,14 @@ namespace Nz } if (!error) - { - if (!currentMesh) - currentMesh = GetMaterial(meshName, matName); - - currentMesh->push_back(std::move(face)); - } + currentMesh->faces.push_back(std::move(face)); + else + currentMesh->vertices.resize(face.firstVertex); //< Remove vertices break; } - case 'm': + case 'm': //< MTLLib #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (m_currentLine.GetWord(0).ToLower() != "mtllib") UnrecognizedLine(); @@ -262,8 +219,8 @@ namespace Nz m_mtlLib = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); break; - case 'g': - case 'o': + case 'g': //< Group (inside a mesh) + case 'o': //< Object (defines a mesh) { if (m_currentLine.GetSize() <= 2 || m_currentLine[1] != ' ') { @@ -283,12 +240,12 @@ namespace Nz } meshName = objectName; - currentMesh = GetMaterial(meshName, matName); + currentMesh = nullptr; break; } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING - case 's': + case 's': //< Smooth if (m_currentLine.GetSize() <= 2 || m_currentLine[1] == ' ') { String param = m_currentLine.SubString(2); @@ -298,15 +255,16 @@ namespace Nz else UnrecognizedLine(); break; - #endif + #endif - case 'u': + case 'u': //< Usemtl #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (m_currentLine.GetWord(0) != "usemtl") UnrecognizedLine(); #endif matName = m_currentLine.SubString(m_currentLine.GetWordPosition(1)); + currentMesh = nullptr; if (matName.IsEmpty()) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING @@ -314,18 +272,16 @@ namespace Nz #endif break; } - - currentMesh = GetMaterial(meshName, matName); break; - case 'v': + case 'v': //< Position/Normal/Texcoords { String word = m_currentLine.GetWord(0).ToLower(); if (word == 'v') { Vector4f vertex(Vector3f::Zero(), 1.f); unsigned int paramCount = std::sscanf(&m_currentLine[2], "%f %f %f %f", &vertex.x, &vertex.y, &vertex.z, &vertex.w); - if (paramCount >= 3) + if (paramCount >= 1) m_positions.push_back(vertex); #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else @@ -371,26 +327,24 @@ namespace Nz } std::unordered_map materials; - m_materials.resize(matIndex); + m_materials.resize(matCount); - for (auto& meshIt : meshes) + for (auto& meshPair : meshesByName) { - for (auto& matIt : meshIt.second) + for (auto& matPair : meshPair.second) { - auto& faceVec = matIt.second.first; - unsigned int index = matIt.second.second; - if (!faceVec.empty()) + Mesh& mesh = matPair.second.first; + unsigned int index = matPair.second.second; + if (!mesh.faces.empty()) { - Mesh mesh; - mesh.faces = std::move(faceVec); - mesh.name = meshIt.first; + mesh.name = meshPair.first; - auto it = materials.find(matIt.first); + auto it = materials.find(matPair.first); if (it == materials.end()) { mesh.material = index; - materials[matIt.first] = index; - m_materials[index] = matIt.first; + materials[matPair.first] = index; + m_materials[index] = matPair.first; } else mesh.material = it->second; @@ -415,7 +369,7 @@ namespace Nz { do { - if (m_stream.EndOfStream()) + if (m_currentStream->EndOfStream()) { if (required) Error("Incomplete OBJ file"); @@ -425,9 +379,8 @@ namespace Nz m_lineCount++; - m_currentLine = m_stream.ReadLine(); - m_currentLine = m_currentLine.SubStringTo("#"); // On ignore les commentaires - m_currentLine.Simplify(); // Pour un traitement plus simple + m_currentLine = m_currentStream->ReadLine(); + m_currentLine.Simplify(); // Simplify lines (convert multiple blanks into a single space and trims) } while (m_currentLine.IsEmpty()); } @@ -436,24 +389,4 @@ namespace Nz return true; } - - void OBJParser::Error(const String& message) - { - NazaraError(message + " at line #" + String::Number(m_lineCount)); - } - - void OBJParser::Warning(const String& message) - { - NazaraWarning(message + " at line #" + String::Number(m_lineCount)); - } - - void OBJParser::UnrecognizedLine(bool error) - { - String message = "Unrecognized \"" + m_currentLine + '"'; - - if (error) - Error(message); - else - Warning(message); - } } From bbb218f9a0a9f6ddb2276140ecc7e37e6af3748c Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 09:00:50 +0200 Subject: [PATCH 11/12] Utility/OBJParser: Add saving Former-commit-id: f991f0a66a82a68659f14a7ba887b49a2690f5a7 [formerly e4c96019484ad436048d001bd307ac549dfc615a] Former-commit-id: 946f9e5f99ff46c26741f1877391506b23602517 --- include/Nazara/Utility/Formats/OBJParser.hpp | 2 + include/Nazara/Utility/Formats/OBJParser.inl | 25 ++++ src/Nazara/Utility/Formats/OBJParser.cpp | 142 +++++++++++++++++++ 3 files changed, 169 insertions(+) diff --git a/include/Nazara/Utility/Formats/OBJParser.hpp b/include/Nazara/Utility/Formats/OBJParser.hpp index 64fd0ce4c..79aa1824a 100644 --- a/include/Nazara/Utility/Formats/OBJParser.hpp +++ b/include/Nazara/Utility/Formats/OBJParser.hpp @@ -58,6 +58,8 @@ namespace Nz bool Parse(Stream& stream, std::size_t reservedVertexCount = 100); + bool Save(Stream& stream) const; + private: bool Advance(bool required = true); template void Emit(const T& text) const; diff --git a/include/Nazara/Utility/Formats/OBJParser.inl b/include/Nazara/Utility/Formats/OBJParser.inl index c8ea75e8c..7cd0060b4 100644 --- a/include/Nazara/Utility/Formats/OBJParser.inl +++ b/include/Nazara/Utility/Formats/OBJParser.inl @@ -63,12 +63,37 @@ namespace Nz return m_texCoords.size(); } + template + void OBJParser::Emit(const T& text) const + { + m_outputStream << text; + if (m_outputStream.GetBufferSize() > 1024 * 1024) + Flush(); + } + + inline void OBJParser::EmitLine() const + { + Emit('\n'); + } + + template + void OBJParser::EmitLine(const T& line) const + { + Emit(line); + Emit('\n'); + } inline void OBJParser::Error(const String& message) { NazaraError(message + " at line #" + String::Number(m_lineCount)); } + inline void OBJParser::Flush() const + { + m_currentStream->Write(m_outputStream); + m_outputStream.Clear(); + } + inline void OBJParser::Warning(const String& message) { NazaraWarning(message + " at line #" + String::Number(m_lineCount)); diff --git a/src/Nazara/Utility/Formats/OBJParser.cpp b/src/Nazara/Utility/Formats/OBJParser.cpp index 03a251d5a..a05ef6960 100644 --- a/src/Nazara/Utility/Formats/OBJParser.cpp +++ b/src/Nazara/Utility/Formats/OBJParser.cpp @@ -363,6 +363,148 @@ namespace Nz return true; } + bool OBJParser::Save(Stream& stream) const + { + m_currentStream = &stream; + + // Force stream in text mode, reset it at the end + Nz::CallOnExit resetTextMode; + if ((stream.GetStreamOptions() & StreamOption_Text) == 0) + { + stream.EnableTextMode(true); + + resetTextMode.Reset([&stream] () + { + stream.EnableTextMode(false); + }); + } + + m_outputStream.Clear(); + + EmitLine("# Exported by Nazara Engine"); + + if (!m_mtlLib.IsEmpty()) + { + Emit("mtlib "); + EmitLine(m_mtlLib); + EmitLine(); + } + + Emit("# position count: "); + EmitLine(m_positions.size()); + + for (const Nz::Vector4f& position : m_positions) + { + Emit("v "); + Emit(position.x); + Emit(' '); + Emit(position.y); + if (!NumberEquals(position.z, 0.f) || !NumberEquals(position.w, 1.f)) + { + Emit(' '); + Emit(position.z); + + if (!NumberEquals(position.w, 1.f)) + { + Emit(' '); + Emit(position.w); + } + } + EmitLine(); + } + EmitLine(); + + Emit("# normal count: "); + EmitLine(m_normals.size()); + + for (const Nz::Vector3f& normal : m_normals) + { + Emit("vn "); + Emit(normal.x); + Emit(' '); + Emit(normal.y); + Emit(' '); + Emit(normal.y); + EmitLine(); + } + EmitLine(); + + Emit("# texcoords count: "); + EmitLine(m_texCoords.size()); + + for (const Nz::Vector3f& uvw : m_texCoords) + { + Emit("vt "); + Emit(uvw.x); + Emit(' '); + Emit(uvw.y); + if (NumberEquals(uvw.z, 0.f)) + { + Emit(' '); + Emit(uvw.z); + } + EmitLine(); + } + EmitLine(); + + std::unordered_map /* meshes*/> meshesByMaterials; + std::size_t meshIndex = 0; + for (const Mesh& mesh : m_meshes) + meshesByMaterials[mesh.material].push_back(meshIndex++); + + for (auto& pair : meshesByMaterials) + { + Emit("usemtl "); + EmitLine(m_materials[pair.first]); + Emit("# groups count: "); + EmitLine(pair.second.size()); + EmitLine(); + + for (std::size_t meshIndex : pair.second) + { + const Mesh& mesh = m_meshes[meshIndex]; + + Emit("g "); + EmitLine(mesh.name); + EmitLine(); + + Emit("# face count: "); + EmitLine(mesh.faces.size()); + Emit("# vertex count: "); + EmitLine(mesh.vertices.size()); + + for (const Face& face : mesh.faces) + { + Emit('f'); + for (std::size_t i = 0; i < face.vertexCount; ++i) + { + Emit(' '); + const FaceVertex& faceVertex = mesh.vertices[face.firstVertex + i]; + Emit(faceVertex.position); + if (faceVertex.texCoord != 0 || faceVertex.normal != 0) + { + Emit('/'); + if (faceVertex.texCoord != 0) + Emit(faceVertex.texCoord); + + if (faceVertex.normal != 0) + { + Emit('/'); + Emit(faceVertex.normal); + } + } + } + EmitLine(); + } + } + EmitLine(); + } + + Flush(); + + return true; + } + bool OBJParser::Advance(bool required) { if (!m_keepLastLine) From 068465b6b987ce9ee55d3feaffba585fb8e27284 Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 7 Jul 2016 09:01:08 +0200 Subject: [PATCH 12/12] Math/Vector4: Fix w value when converting from Vector3 Former-commit-id: 54b45268d18c3839bceffa065e52e47a7a44e811 [formerly 3a349b4380d23163a5f56a2aedb1860f140856cb] Former-commit-id: 453d4705694d89bba0122c5a37c76ddf5478213b --- include/Nazara/Math/Vector4.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Nazara/Math/Vector4.hpp b/include/Nazara/Math/Vector4.hpp index d1e51433a..b84a4cb17 100644 --- a/include/Nazara/Math/Vector4.hpp +++ b/include/Nazara/Math/Vector4.hpp @@ -28,7 +28,7 @@ namespace Nz explicit Vector4(T scale); Vector4(const T vec[4]); Vector4(const Vector2& vec, T Z = 0.0, T W = 1.0); - Vector4(const Vector3& vec, T W = 0.0); + Vector4(const Vector3& vec, T W = 1.0); template explicit Vector4(const Vector4& vec); Vector4(const Vector4& vec) = default; ~Vector4() = default;