diff --git a/ChangeLog.md b/ChangeLog.md index d85eb5164..dbf4dfa24 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,10 +16,11 @@ Miscellaneous: - Add Lua unit tests - NDEBUG is now defined in Release - Replaced typedefs keywords with modern using keywords +- When supported, projects are now parts of a virtual "workspace group" according to their kind Nazara Engine: - VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned. -- Bitset swap operation is now correctly marked as noexcept` +- Bitset swap operation is now correctly marked as noexcept - Mesh loaders now takes MeshParams vertexDeclaration into account - ⚠️ Replaced RenderTarget::Get[Height|Width] by RenderTarget::GetSize - ⚠️ Removed Window::Get[Height|Width] methods @@ -94,6 +95,22 @@ Nazara Engine: - ⚠️ Stream::ReadLine will now returns empty lines if present in the file - Fixed cubemaps seams with OpenGL - HandledObject movement constructor/assignement operator are now marked noexcept +- ⚠️ PhysWorld2D callbacks OnPhysWorld2DPreStep and OnPhysWorld2DPostStep now takes a invStepCount depending on the number of step taken this update, fixing force application and other +- ⚠️ Refactored Mesh/SubMesh, allowing a submesh to be attached to multiple meshes, deprecating Create/Destroy methods +- SubMesh class now has a OnSubMeshInvalidateAABB signal, triggered when a new AABB is set to the submesh +- Mesh class now has a OnMeshInvalidateAABB signal, triggered when a mesh invalidates its AABB, which is also submesh updates its AABB +- Model now invalidate properly their bounding volume when their mesh AABB is updated +- Added operator&/|/^ taking an enumeration value and a Flags object using the same enumeration type. +- Added LuaState::CallWithHandler methods, allowing to setup a error handler function +- Added LuaState::Traceback method +- Added ModelLibrary, ModelManager and ModelSaver +- Added AbstractViewer::Project and AbstractViewer::Unproject methods +- Added AbstractViewer::ProjectDepth method +- Fixed SocketPoller not be able to recover from some errors (like invalid sockets and such) +- ⚠️ Replaced currentBitPos and currentByte fields by [read|write][BitPos][Byte] to handle properly bit reading/writing. +- InstancedRenderable::SetMaterial methods are now public. +- Fixed Model copy constructor not copying materials +- ⚠️ Added InstancedRenderable::Clone() method Nazara Development Kit: - Added ImageWidget (#139) @@ -142,6 +159,7 @@ Nazara Development Kit: - ⚠️ TextAreaWidget::GetHoveredGlyph now returns a two-dimensional position instead of a single glyph position - Fixed Entity::OnEntityDestruction signal not being properly moved and thus not being called. - Fixed EntityOwner move assignment which was losing entity ownership +- Add GraphicsComponent:ForEachRenderable method # 0.4: @@ -187,7 +205,8 @@ Nazara Engine: - Added VertexMapper::GetVertexCount() - Added VertexMapper::HasComponentOfType() - Fixed SimpleTextDrawer bounds computation - +- Added LuaState::Load methods which allows to load (compile) lua code to function without executing it. +- Added ENetPeer::GetLastReceiveTime() which gives the last time a reliable packet was received. Nazara Development Kit: - ⚠️ Components no longer need to be copyable by assignation diff --git a/SDK/include/NDK/Components/GraphicsComponent.hpp b/SDK/include/NDK/Components/GraphicsComponent.hpp index e5dce0144..896e17c09 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.hpp +++ b/SDK/include/NDK/Components/GraphicsComponent.hpp @@ -44,6 +44,8 @@ namespace Ndk inline bool DoesRequireRealTimeReflections() const; + template void ForEachRenderable(const Func& func) const; + 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 71b62f367..55e9706fb 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.inl +++ b/SDK/include/NDK/Components/GraphicsComponent.inl @@ -107,6 +107,18 @@ namespace Ndk return m_reflectiveMaterialCount != 0 && m_reflectionMap; } + /*! + * \brief Calls a function for every renderable attached to this component + * + * \param func Callback function which will be called with renderable data + */ + template + void GraphicsComponent::ForEachRenderable(const Func& func) const + { + for (const auto& renderableData : m_renderables) + func(renderableData.renderable, renderableData.data.localMatrix, renderableData.data.renderOrder); + } + /*! * \brief Ensures the bounding volume is up to date */ diff --git a/SDK/src/NDK/Systems/DebugSystem.cpp b/SDK/src/NDK/Systems/DebugSystem.cpp index d7ce4bb3d..0da17c352 100644 --- a/SDK/src/NDK/Systems/DebugSystem.cpp +++ b/SDK/src/NDK/Systems/DebugSystem.cpp @@ -62,12 +62,19 @@ namespace Ndk const DebugComponent& entityDebug = m_entityOwner->GetComponent(); const GraphicsComponent& entityGfx = m_entityOwner->GetComponent(); + Nz::Boxf aabb = entityGfx.GetBoundingVolume().aabb; + Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity(); - transformMatrix.SetScale(entityGfx.GetBoundingVolume().aabb.GetLengths()); - transformMatrix.SetTranslation(entityGfx.GetBoundingVolume().aabb.GetCenter()); + transformMatrix.SetScale(aabb.GetLengths()); + transformMatrix.SetTranslation(aabb.GetCenter()); renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect); } + + std::unique_ptr Clone() const override + { + return nullptr; + } }; class OBBDebugRenderable : public DebugRenderable @@ -82,11 +89,21 @@ namespace Ndk const DebugComponent& entityDebug = m_entityOwner->GetComponent(); const GraphicsComponent& entityGfx = m_entityOwner->GetComponent(); + Nz::Boxf obb = entityGfx.GetBoundingVolume().obb.localBox; + Nz::Matrix4f transformMatrix = instanceData.transformMatrix; - transformMatrix.ApplyScale(entityGfx.GetBoundingVolume().obb.localBox.GetLengths()); + Nz::Vector3f obbCenter = transformMatrix.Transform(obb.GetCenter(), 0.f); //< Apply rotation/scale to obb center, to display it at a correct position + + transformMatrix.ApplyScale(obb.GetLengths()); + transformMatrix.ApplyTranslation(obbCenter); renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect); } + + std::unique_ptr Clone() const override + { + return nullptr; + } }; } @@ -300,9 +317,7 @@ namespace Ndk Nz::MeshRef mesh = Nz::Mesh::New(); mesh->CreateStatic(); - Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(mesh); - subMesh->Create(vertexBuffer); - subMesh->SetIndexBuffer(indexBuffer); + Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer); subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList); subMesh->SetMaterialIndex(0); subMesh->GenerateAABB(); diff --git a/build/scripts/common.lua b/build/scripts/common.lua index 750e2211b..6eb1cfa64 100644 --- a/build/scripts/common.lua +++ b/build/scripts/common.lua @@ -71,10 +71,19 @@ function NazaraBuild:Execute() configurations(configs) end + if (self.Config["PremakeProject"] and os.ishost("windows")) then + group("_Premake") + + local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ') + project("Regenerate premake") + kind("Utility") + prebuildcommands("cd .. && " .. commandLine) + end + -- Extern libraries if (self.Config["BuildDependencies"]) then - self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries - + group("Thirdparties") + for k, libTable in ipairs(self.OrderedExtLibs) do project(libTable.Name) @@ -94,6 +103,8 @@ function NazaraBuild:Execute() links(libTable.Libraries) libdirs("../thirdparty/lib/common") + self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries + filter(clangGccActions) buildoptions("-U__STRICT_ANSI__") @@ -112,14 +123,9 @@ function NazaraBuild:Execute() end end - if (self.Config["PremakeProject"] and os.ishost("windows")) then - local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ') - project("_PremakeProject") - kind("Utility") - prebuildcommands("cd .. && " .. commandLine) - end - -- Modules + group("Engine Modules") + if (_OPTIONS["united"]) then project("NazaraEngine") @@ -175,6 +181,8 @@ function NazaraBuild:Execute() end -- Tools + group("Engine SDK - Tools") + for k, toolTable in ipairs(self.OrderedTools) do local prefix = "Nazara" if (toolTable.Kind == "plugin") then @@ -243,6 +251,8 @@ function NazaraBuild:Execute() filter({}) end + group("Examples") + for k, exampleTable in ipairs(self.OrderedExamples) do local destPath = "../examples/bin" diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 969c07bdd..f21b0c36a 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -219,17 +219,17 @@ namespace Nz */ inline bool Serialize(SerializationContext& context, bool value, TypeTag) { - if (context.currentBitPos == 8) + if (context.writeBitPos == 8) { - context.currentBitPos = 0; - context.currentByte = 0; + context.writeBitPos = 0; + context.writeByte = 0; } if (value) - context.currentByte |= 1 << context.currentBitPos; + context.writeByte |= 1 << context.writeBitPos; - if (++context.currentBitPos >= 8) - return Serialize(context, context.currentByte, TypeTag()); + if (++context.writeBitPos >= 8) + return Serialize(context, context.writeByte, TypeTag()); else return true; } @@ -291,18 +291,18 @@ namespace Nz */ inline bool Unserialize(SerializationContext& context, bool* value, TypeTag) { - if (context.currentBitPos == 8) + if (context.readBitPos == 8) { - if (!Unserialize(context, &context.currentByte, TypeTag())) + if (!Unserialize(context, &context.readByte, TypeTag())) return false; - context.currentBitPos = 0; + context.readBitPos = 0; } if (value) - *value = (context.currentByte & (1 << context.currentBitPos)) != 0; + *value = (context.readByte & (1 << context.readBitPos)) != 0; - context.currentBitPos++; + context.readBitPos++; return true; } @@ -341,7 +341,7 @@ namespace Nz { NazaraAssert(value, "Invalid data pointer"); - context.ResetBitPosition(); + context.ResetReadBitPosition(); if (context.stream->Read(value, sizeof(T)) == sizeof(T)) { diff --git a/include/Nazara/Core/ByteStream.inl b/include/Nazara/Core/ByteStream.inl index 0b32215e7..afd9f1fd3 100644 --- a/include/Nazara/Core/ByteStream.inl +++ b/include/Nazara/Core/ByteStream.inl @@ -86,11 +86,11 @@ namespace Nz if (!m_context.stream) return true; - if (m_context.currentBitPos != 8) + if (m_context.writeBitPos != 8) { - m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself + m_context.writeBitPos = 8; //< To prevent Serialize to flush bits itself - if (!Serialize(m_context, m_context.currentByte)) + if (!Serialize(m_context, m_context.writeByte)) return false; } diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp index c30959446..92c97de9e 100644 --- a/include/Nazara/Core/Flags.hpp +++ b/include/Nazara/Core/Flags.hpp @@ -73,12 +73,16 @@ namespace Nz BitField m_value; }; + template constexpr Flags operator&(E lhs, Flags rhs); + template constexpr Flags operator|(E lhs, Flags rhs); + template constexpr Flags operator^(E lhs, Flags rhs); + // Little hack to have them in both Nz and global scope namespace FlagsOperators { template constexpr std::enable_if_t::value, Flags> operator~(E lhs); - template constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs); template constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs); template constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs); } diff --git a/include/Nazara/Core/Flags.inl b/include/Nazara/Core/Flags.inl index 36bb32ea0..2b57a59a8 100644 --- a/include/Nazara/Core/Flags.inl +++ b/include/Nazara/Core/Flags.inl @@ -221,6 +221,51 @@ namespace Nz return 1U << static_cast(enumValue); } + /*! + * \brief Compare flag states + * \return Compared flags + * + * This will returns a copy of the Flags object compared with the enum state. + * + * \param lhs Enum to compare with flags. + * \param rhs Flags object. + */ + template + constexpr Flags operator&(E lhs, Flags rhs) + { + return rhs & lhs; + } + + /*! + * \brief Combine flag states + * \return Combined flags + * + * This will returns a copy of the Flags object combined with the enum state. + * + * \param lhs Enum to combine with flags. + * \param rhs Flags object. + */ + template + constexpr Flags operator|(E lhs, Flags rhs) + { + return rhs | lhs; + } + + /*! + * \brief XOR flag states + * \return XORed flags + * + * This will returns a copy of the Flags object XORed with the enum state. + * + * \param lhs Enum to XOR with flags. + * \param rhs Flags object. + */ + template + constexpr Flags operator^(E lhs, Flags rhs) + { + return rhs ^ lhs; + } + namespace FlagsOperators { @@ -238,21 +283,6 @@ namespace Nz return ~Flags(lhs); } - /*! - * \brief Override binary OR operator on enum to turns into a Flags object. - * \return A Flags object with combined enum states. - * - * \param lhs First enumeration value to combine. - * \param rhs Second enumeration value to combine. - * - * Returns a Flags object with combined states from the two enumeration values. - */ - template - constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs) - { - return Flags(lhs) | rhs; - } - /*! * \brief Override binary AND operator on enum to turns into a Flags object. * \return A Flags object with compare enum states. @@ -269,6 +299,21 @@ namespace Nz return Flags(lhs) & rhs; } + /*! + * \brief Override binary OR operator on enum to turns into a Flags object. + * \return A Flags object with combined enum states. + * + * \param lhs First enumeration value to combine. + * \param rhs Second enumeration value to combine. + * + * Returns a Flags object with combined states from the two enumeration values. + */ + template + constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs) + { + return Flags(lhs) | rhs; + } + /*! * \brief Override binary XOR operator on enum to turns into a Flags object. * \return A Flags object with XORed enum states. diff --git a/include/Nazara/Core/SerializationContext.hpp b/include/Nazara/Core/SerializationContext.hpp index 94951666d..4111f7a7b 100644 --- a/include/Nazara/Core/SerializationContext.hpp +++ b/include/Nazara/Core/SerializationContext.hpp @@ -20,11 +20,14 @@ namespace Nz { Stream* stream; Endianness endianness = Endianness_BigEndian; //< Default to Big Endian encoding - UInt8 currentBitPos = 8; //< 8 means no bit is currently wrote - UInt8 currentByte; //< Undefined value, will be initialized at the first bit write + UInt8 readBitPos = 8; //< 8 means no bit is currently read + UInt8 readByte; //< Undefined value, will be initialized at the first bit read + UInt8 writeBitPos = 8; //< 8 means no bit is currently wrote + UInt8 writeByte; //< Undefined value, will be initialized at the first bit write void FlushBits(); - inline void ResetBitPosition(); + inline void ResetReadBitPosition(); + inline void ResetWriteBitPosition(); }; } diff --git a/include/Nazara/Core/SerializationContext.inl b/include/Nazara/Core/SerializationContext.inl index 870972655..4379f718d 100644 --- a/include/Nazara/Core/SerializationContext.inl +++ b/include/Nazara/Core/SerializationContext.inl @@ -7,16 +7,24 @@ namespace Nz { /*! - * \brief Reset the current bit cursor + * \brief Reset the current read bit cursor + */ + inline void SerializationContext::ResetReadBitPosition() + { + readBitPos = 8; + } + + /*! + * \brief Reset the current read bit cursor * \remark This function only reset the cursor position, it doesn't do any writing - if you wish to write all bits and reset bit position, call FlushBits + if you wish to write all bits and reset bit position, call FlushBits - \see FlushBits + \see FlushBits */ - inline void SerializationContext::ResetBitPosition() + inline void SerializationContext::ResetWriteBitPosition() { - currentBitPos = 8; + writeBitPos = 8; } } diff --git a/include/Nazara/Graphics/AbstractViewer.hpp b/include/Nazara/Graphics/AbstractViewer.hpp index 2821fdbec..36547b1ec 100644 --- a/include/Nazara/Graphics/AbstractViewer.hpp +++ b/include/Nazara/Graphics/AbstractViewer.hpp @@ -40,6 +40,11 @@ namespace Nz virtual float GetZFar() const = 0; virtual float GetZNear() const = 0; + Nz::Vector3f Project(const Nz::Vector3f& worldPosition) const; + float ProjectDepth(float depth); + + Nz::Vector3f Unproject(const Nz::Vector3f& screenPos) const; + AbstractViewer& operator=(const AbstractViewer&) = default; AbstractViewer& operator=(AbstractViewer&&) noexcept = default; }; diff --git a/include/Nazara/Graphics/Billboard.hpp b/include/Nazara/Graphics/Billboard.hpp index 62f872f39..f875bc23e 100644 --- a/include/Nazara/Graphics/Billboard.hpp +++ b/include/Nazara/Graphics/Billboard.hpp @@ -31,6 +31,8 @@ namespace Nz void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override; + std::unique_ptr Clone() const override; + inline const Color& GetColor() const; inline float GetRotation() const; inline const Vector2f& GetSize() const; diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index 25f6064a8..9ec0d973f 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -39,6 +39,8 @@ namespace Nz virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const = 0; + virtual std::unique_ptr Clone() const = 0; + virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const; inline void EnsureBoundingVolumeUpdated() const; @@ -53,6 +55,8 @@ namespace Nz virtual void InvalidateData(InstanceData* instanceData, UInt32 flags) const; + inline void SetMaterial(std::size_t matIndex, MaterialRef material); + inline void SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material); inline void SetSkin(std::size_t skinIndex); inline void SetSkinCount(std::size_t skinCount); @@ -108,9 +112,6 @@ namespace Nz inline void ResetMaterials(std::size_t matCount, std::size_t skinCount = 1); - inline void SetMaterial(std::size_t matIndex, MaterialRef material); - inline void SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material); - mutable BoundingVolumef m_boundingVolume; private: diff --git a/include/Nazara/Graphics/InstancedRenderable.inl b/include/Nazara/Graphics/InstancedRenderable.inl index c2a8f1b70..f54f9cebe 100644 --- a/include/Nazara/Graphics/InstancedRenderable.inl +++ b/include/Nazara/Graphics/InstancedRenderable.inl @@ -110,6 +110,51 @@ namespace Nz return m_skinCount; } + /*! + * \brief Changes the material used at the specified index by another one + * + * This function changes the active material at the specified index, depending on the current active skin, to the one passed as parameter. + * + * \param matIndex Material index + * \param material New material, cannot be null + * + * \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault) + * + * \see SetMaterial + */ + inline void InstancedRenderable::SetMaterial(std::size_t matIndex, MaterialRef material) + { + SetMaterial(m_skin, matIndex, std::move(material)); + } + + /*! + * \brief Changes the material used at the specified index by another one, independently from the active skin. + * + * This function changes the active material at the specified index and for the specified skin index, to the one passed as parameter. + * + * \param skinIndex Skin index + * \param matIndex Material index + * \param material New material, cannot be null + * + * \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault) + * + * \see SetMaterial + */ + inline void InstancedRenderable::SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material) + { + NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds"); + NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds"); + NazaraAssert(material.IsValid(), "Material must be valid"); + + MaterialRef& matEntry = m_materials[m_matCount * skinIndex + matIndex]; + if (matEntry != material) + { + OnInstancedRenderableInvalidateMaterial(this, skinIndex, matIndex, material); + + matEntry = std::move(material); + } + } + /*! * \brief Changes the active skin * @@ -201,51 +246,6 @@ namespace Nz m_skin = 0; } - /*! - * \brief Changes the material used at the specified index by another one - * - * This function changes the active material at the specified index, depending on the current active skin, to the one passed as parameter. - * - * \param matIndex Material index - * \param material New material, cannot be null - * - * \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault) - * - * \see SetMaterial - */ - inline void InstancedRenderable::SetMaterial(std::size_t matIndex, MaterialRef material) - { - SetMaterial(m_skin, matIndex, std::move(material)); - } - - /*! - * \brief Changes the material used at the specified index by another one, independently from the active skin. - * - * This function changes the active material at the specified index and for the specified skin index, to the one passed as parameter. - * - * \param skinIndex Skin index - * \param matIndex Material index - * \param material New material, cannot be null - * - * \remark If you wish to reset the material to the default one, use the default material (see Material::GetDefault) - * - * \see SetMaterial - */ - inline void InstancedRenderable::SetMaterial(std::size_t skinIndex, std::size_t matIndex, MaterialRef material) - { - NazaraAssert(skinIndex < m_skinCount, "Skin index out of bounds"); - NazaraAssert(matIndex < m_materials.size(), "Material index out of bounds"); - NazaraAssert(material.IsValid(), "Material must be valid"); - - MaterialRef& matEntry = m_materials[m_matCount * skinIndex + matIndex]; - if (matEntry != material) - { - OnInstancedRenderableInvalidateMaterial(this, skinIndex, matIndex, material); - - matEntry = std::move(material); - } - } - /*! * \brief Sets the current instanced renderable with the content of the other one * \return A reference to this diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index b37d68a2e..dd2258e26 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -8,9 +8,11 @@ #define NAZARA_MODEL_HPP #include +#include #include #include #include +#include #include #include #include @@ -32,22 +34,30 @@ namespace Nz class Model; using ModelConstRef = ObjectRef; + using ModelLibrary = ObjectLibrary; using ModelLoader = ResourceLoader; + using ModelManager = ResourceManager; using ModelRef = ObjectRef; + using ModelSaver = ResourceSaver; class NAZARA_GRAPHICS_API Model : public InstancedRenderable, public Resource { + friend ModelLibrary; friend ModelLoader; + friend ModelManager; + friend ModelSaver; public: inline Model(); - Model(const Model& model) = default; - Model(Model&& model) = default; + Model(const Model& model); + Model(Model&& model) = delete; virtual ~Model(); void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override; inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder = 0, const Recti& scissorRect = Recti(-1, -1, -1, -1)) const; + std::unique_ptr Clone() const override; + using InstancedRenderable::GetMaterial; const MaterialRef& GetMaterial(const String& subMeshName) const; const MaterialRef& GetMaterial(std::size_t skinIndex, const String& subMeshName) const; @@ -66,7 +76,7 @@ namespace Nz virtual void SetMesh(Mesh* mesh); Model& operator=(const Model& node) = default; - Model& operator=(Model&& node) = default; + Model& operator=(Model&& node) = delete; template static ModelRef New(Args&&... args); @@ -75,7 +85,13 @@ namespace Nz MeshRef m_mesh; + NazaraSlot(Mesh, OnMeshInvalidateAABB, m_meshAABBInvalidationSlot); + + static ModelLibrary::LibraryMap s_library; static ModelLoader::LoaderList s_loaders; + static ModelManager::ManagerMap s_managerMap; + static ModelManager::ManagerParams s_managerParameters; + static ModelSaver::SaverList s_savers; }; } diff --git a/include/Nazara/Graphics/Model.inl b/include/Nazara/Graphics/Model.inl index 486665f3a..1b0055cf3 100644 --- a/include/Nazara/Graphics/Model.inl +++ b/include/Nazara/Graphics/Model.inl @@ -2,6 +2,7 @@ // This file is part of the "Nazara Engine - Graphics module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include @@ -10,11 +11,22 @@ namespace Nz /*! * \brief Constructs a Model object by default */ - Model::Model() + inline Model::Model() { ResetMaterials(0); } + /*! + * \brief Constructs a Model object by copying another + * + * \param model Model to copy + */ + inline Model::Model(const Model& model) : + InstancedRenderable(model) + { + SetMesh(model.m_mesh); + } + /*! * \brief Adds this model to a render queue, using user-specified transform matrix and render order * @@ -25,8 +37,8 @@ namespace Nz * \param renderOrder Specify the render queue layer to be used * \param scissorRect The Scissor rect to uses for rendering */ - void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const -{ + inline void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const + { InstanceData instanceData(Nz::Matrix4f::Identity()); instanceData.renderOrder = renderOrder; instanceData.transformMatrix = transformMatrix; diff --git a/include/Nazara/Graphics/SkeletalModel.hpp b/include/Nazara/Graphics/SkeletalModel.hpp index 86943b676..a36082619 100644 --- a/include/Nazara/Graphics/SkeletalModel.hpp +++ b/include/Nazara/Graphics/SkeletalModel.hpp @@ -41,7 +41,7 @@ namespace Nz void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override; void AdvanceAnimation(float elapsedTime); - SkeletalModel* Clone() const; + std::unique_ptr Clone() const override; SkeletalModel* Create() const; void EnableAnimation(bool animation); diff --git a/include/Nazara/Graphics/Sprite.hpp b/include/Nazara/Graphics/Sprite.hpp index bf9edc0d1..6548f461a 100644 --- a/include/Nazara/Graphics/Sprite.hpp +++ b/include/Nazara/Graphics/Sprite.hpp @@ -35,6 +35,8 @@ namespace Nz void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override; + std::unique_ptr Clone() const override; + inline const Color& GetColor() const; inline const Color& GetCornerColor(RectCorner corner) const; inline const Vector3f& GetOrigin() const; diff --git a/include/Nazara/Graphics/TextSprite.hpp b/include/Nazara/Graphics/TextSprite.hpp index 355d17fe4..d86d999ad 100644 --- a/include/Nazara/Graphics/TextSprite.hpp +++ b/include/Nazara/Graphics/TextSprite.hpp @@ -34,11 +34,14 @@ namespace Nz inline void Clear(); + std::unique_ptr Clone() const override; + inline const Color& GetColor() const; inline float GetScale() const; inline void SetColor(const Color& color); inline void SetDefaultMaterial(); + using InstancedRenderable::SetMaterial; inline void SetMaterial(MaterialRef material); inline void SetMaterial(std::size_t skinIndex, MaterialRef material); inline void SetScale(float scale); diff --git a/include/Nazara/Graphics/TextSprite.inl b/include/Nazara/Graphics/TextSprite.inl index c35cd562e..04a3c1170 100644 --- a/include/Nazara/Graphics/TextSprite.inl +++ b/include/Nazara/Graphics/TextSprite.inl @@ -14,6 +14,7 @@ namespace Nz inline TextSprite::TextSprite() : m_color(Color::White), + m_localBounds(Nz::Recti::Zero()), m_scale(1.f) { ResetMaterials(1U); diff --git a/include/Nazara/Graphics/TileMap.hpp b/include/Nazara/Graphics/TileMap.hpp index 3692eb3c2..6648a6598 100644 --- a/include/Nazara/Graphics/TileMap.hpp +++ b/include/Nazara/Graphics/TileMap.hpp @@ -35,6 +35,8 @@ namespace Nz void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override; + std::unique_ptr Clone() const override; + inline void DisableTile(const Vector2ui& tilePos); inline void DisableTiles(); inline void DisableTiles(const Vector2ui* tilesPos, std::size_t tileCount); diff --git a/include/Nazara/Lua/LuaCoroutine.hpp b/include/Nazara/Lua/LuaCoroutine.hpp index cdda83b3a..753aa8a4f 100644 --- a/include/Nazara/Lua/LuaCoroutine.hpp +++ b/include/Nazara/Lua/LuaCoroutine.hpp @@ -31,7 +31,7 @@ namespace Nz private: LuaCoroutine(lua_State* internalState, int refIndex); - bool Run(int argCount, int resultCount) override; + bool Run(int argCount, int resultCount, int errHandler) override; int m_ref; }; diff --git a/include/Nazara/Lua/LuaState.hpp b/include/Nazara/Lua/LuaState.hpp index 14f0898c2..47c6d07cf 100644 --- a/include/Nazara/Lua/LuaState.hpp +++ b/include/Nazara/Lua/LuaState.hpp @@ -43,6 +43,8 @@ namespace Nz bool Call(unsigned int argCount); bool Call(unsigned int argCount, unsigned int resultCount); + bool CallWithHandler(unsigned int argCount, int errorHandler); + bool CallWithHandler(unsigned int argCount, unsigned int resultCount, int errorHandler); template T Check(int* index) const; template T Check(int* index, T defValue) const; @@ -84,10 +86,10 @@ namespace Nz void Error(const char* message) const; void Error(const String& message) const; - bool Execute(const String& code); - bool ExecuteFromFile(const String& filePath); - bool ExecuteFromMemory(const void* data, std::size_t size); - bool ExecuteFromStream(Stream& stream); + bool Execute(const String& code, int errorHandler = 0); + bool ExecuteFromFile(const String& filePath, int errorHandler = 0); + bool ExecuteFromMemory(const void* data, std::size_t size, int errorHandler = 0); + bool ExecuteFromStream(Stream& stream, int errorHandler = 0); int GetAbsIndex(int index) const; LuaType GetField(const char* fieldName, int tableIndex = -1) const; @@ -112,6 +114,11 @@ namespace Nz bool IsOfType(int index, const String& tname) const; bool IsValid(int index) const; + bool Load(const String& code); + bool LoadFromFile(const String& filePath); + bool LoadFromMemory(const void* data, std::size_t size); + bool LoadFromStream(Stream& stream); + long long Length(int index) const; std::size_t LengthRaw(int index) const; @@ -134,7 +141,6 @@ namespace Nz template void PushFunction(R(*func)(Args...), DefArgs&&... defArgs) const; template void PushGlobal(const char* name, T&& arg); template void PushGlobal(const String& name, T&& arg); - template void PushInstance(const char* tname, const T& instance) const; template void PushInstance(const char* tname, T&& instance) const; template void PushInstance(const char* tname, Args&&... args) const; void PushInteger(long long value) const; @@ -173,6 +179,8 @@ namespace Nz void* ToUserdata(int index, const char* tname) const; void* ToUserdata(int index, const String& tname) const; + void Traceback(const char* message = nullptr, int level = 0); + LuaState& operator=(const LuaState&) = default; LuaState& operator=(LuaState&& instance) = default; @@ -185,7 +193,7 @@ namespace Nz template std::enable_if_t::value, T> CheckBounds(int index, long long value) const; template std::enable_if_t::value, T> CheckBounds(int index, long long value) const; - virtual bool Run(int argCount, int resultCount); + virtual bool Run(int argCount, int resultCount, int errHandler); static int ProxyFunc(lua_State* internalState); diff --git a/include/Nazara/Lua/LuaState.inl b/include/Nazara/Lua/LuaState.inl index 62669d72b..7dcc4e36f 100644 --- a/include/Nazara/Lua/LuaState.inl +++ b/include/Nazara/Lua/LuaState.inl @@ -706,7 +706,7 @@ namespace Nz template void LuaState::PushField(const char* name, T&& arg, int tableIndex) const { - Push(std::forward(arg)); + Push(std::forward(arg)); SetField(name, tableIndex); } @@ -732,7 +732,7 @@ namespace Nz template void LuaState::PushGlobal(const char* name, T&& arg) { - Push(std::forward(arg)); + Push(std::forward(arg)); SetGlobal(name); } @@ -742,15 +742,6 @@ namespace Nz PushGlobal(name.GetConstBuffer(), std::forward(arg)); } - template - void LuaState::PushInstance(const char* tname, const T& instance) const - { - T* userdata = static_cast(PushUserdata(sizeof(T))); - PlacementNew(userdata, instance); - - SetMetatable(tname); - } - template void LuaState::PushInstance(const char* tname, T&& instance) const { diff --git a/include/Nazara/Network/ENetPeer.hpp b/include/Nazara/Network/ENetPeer.hpp index a58d28201..c1822e761 100644 --- a/include/Nazara/Network/ENetPeer.hpp +++ b/include/Nazara/Network/ENetPeer.hpp @@ -47,6 +47,7 @@ namespace Nz void DisconnectNow(UInt32 data); inline const IpAddress& GetAddress() const; + inline UInt32 GetLastReceiveTime() const; inline UInt32 GetMtu() const; inline UInt32 GetPacketThrottleAcceleration() const; inline UInt32 GetPacketThrottleDeceleration() const; diff --git a/include/Nazara/Network/ENetPeer.inl b/include/Nazara/Network/ENetPeer.inl index 2a833e530..3f8ffa846 100644 --- a/include/Nazara/Network/ENetPeer.inl +++ b/include/Nazara/Network/ENetPeer.inl @@ -22,6 +22,11 @@ namespace Nz return m_address; } + inline UInt32 ENetPeer::GetLastReceiveTime() const + { + return m_lastReceiveTime; + } + inline UInt32 ENetPeer::GetMtu() const { return m_mtu; diff --git a/include/Nazara/Physics2D/PhysWorld2D.hpp b/include/Nazara/Physics2D/PhysWorld2D.hpp index e2ec3b042..301e73563 100644 --- a/include/Nazara/Physics2D/PhysWorld2D.hpp +++ b/include/Nazara/Physics2D/PhysWorld2D.hpp @@ -123,8 +123,8 @@ namespace Nz float fraction; }; - NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/); - NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/); + NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/); + NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/); private: void InitCallbacks(cpCollisionHandler* handler, const Callback& callbacks); diff --git a/include/Nazara/Renderer/DebugDrawer.hpp b/include/Nazara/Renderer/DebugDrawer.hpp index a001b1bab..e6667e7a9 100644 --- a/include/Nazara/Renderer/DebugDrawer.hpp +++ b/include/Nazara/Renderer/DebugDrawer.hpp @@ -36,7 +36,7 @@ namespace Nz static void DrawCone(const Vector3f& origin, const Quaternionf& rotation, float angle, float length); static void DrawLine(const Vector3f& p1, const Vector3f& p2); static void DrawPoints(const Vector3f* ptr, unsigned int pointCount); - static void DrawNormals(const StaticMesh* subMesh); + static void DrawNormals(const StaticMesh* subMesh, float normalLength = 0.01f); static void DrawTangents(const StaticMesh* subMesh); static void EnableDepthBuffer(bool depthBuffer); diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 1f14c04c0..1e9e6d47d 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -15,8 +15,23 @@ namespace Nz { +<<<<<<< HEAD class AbstractBuffer; class Buffer; +======= + class Color; + class Context; + class GpuQuery; + class IndexBuffer; + class RenderTarget; + struct RenderStates; + class Shader; + class Texture; + class TextureSampler; + class UniformBuffer; + class VertexBuffer; + class VertexDeclaration; +>>>>>>> ubo class NAZARA_RENDERER_API Renderer { @@ -24,7 +39,46 @@ namespace Nz Renderer() = delete; ~Renderer() = delete; +<<<<<<< HEAD static inline RendererImpl* GetRendererImpl(); +======= + static void BeginCondition(const GpuQuery& query, GpuQueryCondition condition); + + static void BindUniformBuffer(unsigned int bindingPoint, const UniformBuffer* uniformBuffer); + + static void Clear(UInt32 flags = RendererBuffer_Color | RendererBuffer_Depth); + + static void DrawFullscreenQuad(); + static void DrawIndexedPrimitives(PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); + static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); + static void DrawPrimitives(PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); + static void DrawPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); + + static void Enable(RendererParameter parameter, bool enable); + + static void EndCondition(); + + static void Flush(); + + static RendererComparison GetDepthFunc(); + static VertexBuffer* GetInstanceBuffer(); + static float GetLineWidth(); + static Matrix4f GetMatrix(MatrixType type); + static UInt8 GetMaxAnisotropyLevel(); + static unsigned int GetMaxColorAttachments(); + static unsigned int GetMaxRenderTargets(); + static unsigned int GetMaxTextureSize(); + static unsigned int GetMaxTextureUnits(); + static unsigned int GetMaxVertexAttribs(); + static float GetPointSize(); + static const RenderStates& GetRenderStates(); + static Recti GetScissorRect(); + static const Shader* GetShader(); + static const RenderTarget* GetTarget(); + static Recti GetViewport(); + + static bool HasCapability(RendererCap capability); +>>>>>>> ubo static bool Initialize(); diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index d6fee2127..edc8708b4 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -49,8 +49,9 @@ namespace Nz { BufferType_Index, BufferType_Vertex, + BufferType_Uniform, - BufferType_Max = BufferType_Vertex + BufferType_Max = BufferType_Uniform }; enum BufferUsage diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 7feee06e8..dd30a4e49 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -38,7 +38,6 @@ namespace Nz inline const BufferRef& GetBuffer() const; inline UInt32 GetEndOffset() const; inline UInt32 GetIndexCount() const; - inline DataStorage GetStorage() const; inline UInt32 GetStride() const; inline UInt32 GetStartOffset() const; diff --git a/include/Nazara/Utility/IndexBuffer.inl b/include/Nazara/Utility/IndexBuffer.inl index 1bcf60b26..52103b46d 100644 --- a/include/Nazara/Utility/IndexBuffer.inl +++ b/include/Nazara/Utility/IndexBuffer.inl @@ -22,11 +22,6 @@ namespace Nz return m_indexCount; } - inline DataStorage IndexBuffer::GetStorage() const - { - return DataStorage(); - } - inline UInt32 IndexBuffer::GetStride() const { return static_cast((m_largeIndices) ? sizeof(UInt32) : sizeof(UInt16)); diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 0848ee2fb..0ecd9eb3a 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -20,8 +20,12 @@ #include #include #include +#include +#include #include #include +#include +#include namespace Nz { @@ -56,7 +60,6 @@ namespace Nz class Mesh; struct Primitive; class PrimitiveList; - class Skeleton; class SubMesh; using MeshVertex = VertexStruct_XYZ_Normal_UV_Tangent; @@ -80,8 +83,10 @@ namespace Nz friend class Utility; public: - Mesh() = default; - ~Mesh(); + inline Mesh(); + Mesh(const Mesh&) = delete; + Mesh(Mesh&&) = delete; + inline ~Mesh(); void AddSubMesh(SubMesh* subMesh); void AddSubMesh(const String& identifier, SubMesh* subMesh); @@ -141,14 +146,34 @@ namespace Nz void Transform(const Matrix4f& matrix); + Mesh& operator=(const Mesh&) = delete; + Mesh& operator=(Mesh&&) = delete; + template static MeshRef New(Args&&... args); // Signals: NazaraSignal(OnMeshDestroy, const Mesh* /*mesh*/); + NazaraSignal(OnMeshInvalidateAABB, const Mesh* /*mesh*/); NazaraSignal(OnMeshRelease, const Mesh* /*mesh*/); private: - MeshImpl* m_impl = nullptr; + struct SubMeshData + { + SubMeshRef subMesh; + + NazaraSlot(SubMesh, OnSubMeshInvalidateAABB, onSubMeshInvalidated); + }; + + std::unordered_map m_subMeshMap; + std::vector m_materialData; + std::vector m_subMeshes; + AnimationType m_animationType; + mutable Boxf m_aabb; + Skeleton m_skeleton; // Only used by skeletal meshes + String m_animationPath; + mutable bool m_aabbUpdated; + bool m_isValid; + UInt32 m_jointCount; // Only used by skeletal meshes static bool Initialize(); static void Uninitialize(); diff --git a/include/Nazara/Utility/Mesh.inl b/include/Nazara/Utility/Mesh.inl index e63cb389f..5dbe349d0 100644 --- a/include/Nazara/Utility/Mesh.inl +++ b/include/Nazara/Utility/Mesh.inl @@ -2,11 +2,25 @@ // 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 { + Mesh::Mesh() : + m_materialData(1), + m_aabbUpdated(false) + { + } + + Mesh::~Mesh() + { + OnMeshRelease(this); + + Destroy(); + } + template MeshRef Mesh::New(Args&&... args) { diff --git a/include/Nazara/Utility/SkeletalMesh.hpp b/include/Nazara/Utility/SkeletalMesh.hpp index d1f652e85..ebba1cfb5 100644 --- a/include/Nazara/Utility/SkeletalMesh.hpp +++ b/include/Nazara/Utility/SkeletalMesh.hpp @@ -24,9 +24,14 @@ namespace Nz class NAZARA_UTILITY_API SkeletalMesh final : public SubMesh { public: + SkeletalMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer); + + NAZARA_DEPRECATED("SkeletalMesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh") SkeletalMesh(const Mesh* parent); + ~SkeletalMesh(); + NAZARA_DEPRECATED("SkeletalMesh create/destroy functions are deprecated, please use constructor") bool Create(VertexBuffer* vertexBuffer); void Destroy(); @@ -51,8 +56,8 @@ namespace Nz private: Boxf m_aabb; - IndexBufferConstRef m_indexBuffer = nullptr; - VertexBufferRef m_vertexBuffer = nullptr; + IndexBufferConstRef m_indexBuffer; + VertexBufferRef m_vertexBuffer; }; } diff --git a/include/Nazara/Utility/StaticMesh.hpp b/include/Nazara/Utility/StaticMesh.hpp index 395713835..534157fb6 100644 --- a/include/Nazara/Utility/StaticMesh.hpp +++ b/include/Nazara/Utility/StaticMesh.hpp @@ -21,11 +21,16 @@ namespace Nz class NAZARA_UTILITY_API StaticMesh final : public SubMesh { public: + StaticMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer); + + NAZARA_DEPRECATED("StaticMesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh") StaticMesh(const Mesh* parent); + ~StaticMesh(); void Center(); + NAZARA_DEPRECATED("StaticMesh create/destroy functions are deprecated, please use constructor") bool Create(VertexBuffer* vertexBuffer); void Destroy(); @@ -52,8 +57,8 @@ namespace Nz private: Boxf m_aabb; - IndexBufferConstRef m_indexBuffer = nullptr; - VertexBufferRef m_vertexBuffer = nullptr; + IndexBufferConstRef m_indexBuffer; + VertexBufferRef m_vertexBuffer; }; } diff --git a/include/Nazara/Utility/SubMesh.hpp b/include/Nazara/Utility/SubMesh.hpp index 54c948f89..cfbde074c 100644 --- a/include/Nazara/Utility/SubMesh.hpp +++ b/include/Nazara/Utility/SubMesh.hpp @@ -28,7 +28,13 @@ namespace Nz friend Mesh; public: + SubMesh(); + + NAZARA_DEPRECATED("Submesh constructor taking a mesh is deprecated, submeshes no longer require to be part of a single mesh") SubMesh(const Mesh* parent); + + SubMesh(const SubMesh&) = delete; + SubMesh(SubMesh&&) = delete; virtual ~SubMesh(); void GenerateNormals(); @@ -39,7 +45,6 @@ namespace Nz virtual AnimationType GetAnimationType() const = 0; virtual const IndexBuffer* GetIndexBuffer() const = 0; UInt32 GetMaterialIndex() const; - const Mesh* GetParent() const; PrimitiveMode GetPrimitiveMode() const; UInt32 GetTriangleCount() const; virtual UInt32 GetVertexCount() const = 0; @@ -49,12 +54,15 @@ namespace Nz void SetMaterialIndex(UInt32 matIndex); void SetPrimitiveMode(PrimitiveMode mode); + SubMesh& operator=(const SubMesh&) = delete; + SubMesh& operator=(SubMesh&&) = delete; + // Signals: + NazaraSignal(OnSubMeshInvalidateAABB, const SubMesh* /*subMesh*/); NazaraSignal(OnSubMeshRelease, const SubMesh* /*subMesh*/); protected: PrimitiveMode m_primitiveMode; - const Mesh* m_parent; UInt32 m_matIndex; }; } diff --git a/include/Nazara/Utility/UniformBuffer.hpp b/include/Nazara/Utility/UniformBuffer.hpp new file mode 100644 index 000000000..aa77c3069 --- /dev/null +++ b/include/Nazara/Utility/UniformBuffer.hpp @@ -0,0 +1,69 @@ +// Copyright (C) 2017 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_UNIFORMBUFFER_HPP +#define NAZARA_UNIFORMBUFFER_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class UniformBuffer; + + using UniformBufferConstRef = ObjectRef; + using UniformBufferRef = ObjectRef; + + class NAZARA_UTILITY_API UniformBuffer : public RefCounted + { + public: + UniformBuffer() = default; + UniformBuffer(BufferRef buffer); + UniformBuffer(BufferRef buffer, UInt32 offset, UInt32 size); + UniformBuffer(UInt32 length, DataStorage storage, BufferUsageFlags usage); + UniformBuffer(const UniformBuffer& uniformBuffer); + UniformBuffer(UniformBuffer&&) = delete; + ~UniformBuffer(); + + bool Fill(const void* data, UInt32 offset, UInt32 size); + + inline const BufferRef& GetBuffer() const; + inline UInt32 GetEndOffset() const; + inline UInt32 GetStartOffset() const; + + inline bool IsValid() const; + + void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0); + void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) const; + + void Reset(); + void Reset(BufferRef buffer); + void Reset(BufferRef buffer, UInt32 offset, UInt32 size); + void Reset(UInt32 size, DataStorage storage, BufferUsageFlags usage); + void Reset(const UniformBuffer& uniformBuffer); + + void Unmap() const; + + UniformBuffer& operator=(const UniformBuffer& uniformBuffer); + UniformBuffer& operator=(UniformBuffer&&) = delete; + + template static UniformBufferRef New(Args&&... args); + + // Signals: + NazaraSignal(OnUniformBufferRelease, const UniformBuffer* /*UniformBuffer*/); + + private: + BufferRef m_buffer; + UInt32 m_endOffset; + UInt32 m_startOffset; + }; +} + +#include + +#endif // NAZARA_UNIFORMBUFFER_HPP diff --git a/include/Nazara/Utility/UniformBuffer.inl b/include/Nazara/Utility/UniformBuffer.inl new file mode 100644 index 000000000..50b2199eb --- /dev/null +++ b/include/Nazara/Utility/UniformBuffer.inl @@ -0,0 +1,41 @@ +// Copyright (C) 2017 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 BufferRef& UniformBuffer::GetBuffer() const + { + return m_buffer; + } + + inline UInt32 UniformBuffer::GetEndOffset() const + { + return m_endOffset; + } + + inline UInt32 UniformBuffer::GetStartOffset() const + { + return m_startOffset; + } + + inline bool UniformBuffer::IsValid() const + { + return m_buffer.IsValid(); + } + + template + UniformBufferRef UniformBuffer::New(Args&&... args) + { + std::unique_ptr object(new UniformBuffer(std::forward(args)...)); + object->SetPersistent(false); + + return object.release(); + } +} + +#include diff --git a/plugins/Assimp/Plugin.cpp b/plugins/Assimp/Plugin.cpp index 0dcd5fbcb..4320ae098 100644 --- a/plugins/Assimp/Plugin.cpp +++ b/plugins/Assimp/Plugin.cpp @@ -279,10 +279,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) vertexMapper.Unmap(); // Submesh - StaticMeshRef subMesh = StaticMesh::New(mesh); - subMesh->Create(vertexBuffer); - - subMesh->SetIndexBuffer(indexBuffer); + StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer); subMesh->GenerateAABB(); subMesh->SetMaterialIndex(iMesh->mMaterialIndex); diff --git a/src/Nazara/Core/SerializationContext.cpp b/src/Nazara/Core/SerializationContext.cpp index 5949281e3..cf9711bea 100644 --- a/src/Nazara/Core/SerializationContext.cpp +++ b/src/Nazara/Core/SerializationContext.cpp @@ -19,16 +19,16 @@ namespace Nz /*! * Write bits to the stream (if any) and reset the current bit cursor - * \see ResetBitPosition + * \see ResetWriteBitPosition */ void SerializationContext::FlushBits() { - if (currentBitPos != 8) + if (writeBitPos != 8) { - ResetBitPosition(); + ResetWriteBitPosition(); // Serialize will reset the bit position - if (!Serialize(*this, currentByte)) + if (!Serialize(*this, writeByte)) NazaraWarning("Failed to flush bits"); } } diff --git a/src/Nazara/Graphics/AbstractViewer.cpp b/src/Nazara/Graphics/AbstractViewer.cpp index e83737baa..e9d91c92c 100644 --- a/src/Nazara/Graphics/AbstractViewer.cpp +++ b/src/Nazara/Graphics/AbstractViewer.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -16,4 +17,50 @@ namespace Nz */ AbstractViewer::~AbstractViewer() = default; + + Vector3f AbstractViewer::Project(const Nz::Vector3f& worldPosition) const + { + Vector4f pos4D(worldPosition, 1.f); + pos4D = GetViewMatrix() * pos4D; + pos4D = GetProjectionMatrix() * pos4D; + pos4D /= pos4D.w; + + Rectf viewport = Rectf(GetViewport()); + + Nz::Vector3f screenPosition(pos4D.x * 0.5f + 0.5f, -pos4D.y * 0.5f + 0.5f, pos4D.z * 0.5f + 0.5f); + screenPosition.x = screenPosition.x * viewport.width + viewport.x; + screenPosition.y = screenPosition.y * viewport.height + viewport.y; + + return screenPosition; + } + + float AbstractViewer::ProjectDepth(float depth) + { + const Matrix4f& projectionMatrix = GetProjectionMatrix(); + float a = projectionMatrix(2, 2); + float b = projectionMatrix(2, 3); + + return (0.5f * (-a * depth + b) / depth + 0.5f); + } + + Vector3f AbstractViewer::Unproject(const Nz::Vector3f& screenPos) const + { + Rectf viewport = Rectf(GetViewport()); + + Nz::Vector4f normalizedPosition; + normalizedPosition.x = (screenPos.x - viewport.x) / viewport.width * 2.f - 1.f; + normalizedPosition.y = (screenPos.y - viewport.y) / viewport.height * 2.f - 1.f; + normalizedPosition.z = screenPos.z * 2.f - 1.f; + normalizedPosition.w = 1.f; + + normalizedPosition.y = -normalizedPosition.y; + + Nz::Matrix4f invMatrix = GetViewMatrix() * GetProjectionMatrix(); + invMatrix.Inverse(); + + Nz::Vector4f worldPos = invMatrix * normalizedPosition; + worldPos /= worldPos.w; + + return Nz::Vector3f(worldPos.x, worldPos.y, worldPos.z); + } } diff --git a/src/Nazara/Graphics/Billboard.cpp b/src/Nazara/Graphics/Billboard.cpp index 9cc79acce..35021ef8d 100644 --- a/src/Nazara/Graphics/Billboard.cpp +++ b/src/Nazara/Graphics/Billboard.cpp @@ -27,6 +27,14 @@ namespace Nz renderQueue->AddBillboards(instanceData.renderOrder, GetMaterial(), 1, scissorRect, &position, &m_size, &m_sinCos, &m_color); } + /*! + * \brief Clones this billboard + */ + std::unique_ptr Billboard::Clone() const + { + return std::make_unique(*this); + } + /* * \brief Makes the bounding volume of this billboard */ diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 05b8bc909..b725caef8 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -51,7 +51,6 @@ namespace Nz * \param renderQueue Queue to be added * \param instanceData Data used for this instance */ - void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const { unsigned int submeshCount = m_mesh->GetSubMeshCount(); @@ -69,6 +68,14 @@ namespace Nz } } + /*! + * \brief Clones this model + */ + std::unique_ptr Model::Clone() const + { + return std::make_unique(*this); + } + /*! * \brief Gets the material of the named submesh * \return Pointer to the current material @@ -252,9 +259,15 @@ namespace Nz m_mesh = mesh; if (m_mesh) + { ResetMaterials(mesh->GetMaterialCount()); + m_meshAABBInvalidationSlot.Connect(m_mesh->OnMeshInvalidateAABB, [this](const Nz::Mesh*) { InvalidateBoundingVolume(); }); + } else + { ResetMaterials(0); + m_meshAABBInvalidationSlot.Disconnect(); + } InvalidateBoundingVolume(); } @@ -271,5 +284,9 @@ namespace Nz m_boundingVolume.MakeNull(); } + ModelLibrary::LibraryMap Model::s_library; ModelLoader::LoaderList Model::s_loaders; + ModelManager::ManagerMap Model::s_managerMap; + ModelManager::ManagerParams Model::s_managerParameters; + ModelSaver::SaverList Model::s_savers; } diff --git a/src/Nazara/Graphics/SkeletalModel.cpp b/src/Nazara/Graphics/SkeletalModel.cpp index c42b63a83..03d22f648 100644 --- a/src/Nazara/Graphics/SkeletalModel.cpp +++ b/src/Nazara/Graphics/SkeletalModel.cpp @@ -126,10 +126,9 @@ namespace Nz * \brief Clones this skeletal model * \return Pointer to newly allocated SkeletalModel */ - - SkeletalModel* SkeletalModel::Clone() const + std::unique_ptr SkeletalModel::Clone() const { - return new SkeletalModel(*this); + return std::make_unique(*this); } /*! diff --git a/src/Nazara/Graphics/Sprite.cpp b/src/Nazara/Graphics/Sprite.cpp index 70ba21926..0c16de174 100644 --- a/src/Nazara/Graphics/Sprite.cpp +++ b/src/Nazara/Graphics/Sprite.cpp @@ -21,17 +21,23 @@ namespace Nz * \param renderQueue Queue to be added * \param instanceData Data for the instance */ - void Sprite::AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const { const VertexStruct_XYZ_Color_UV* vertices = reinterpret_cast(instanceData.data.data()); renderQueue->AddSprites(instanceData.renderOrder, GetMaterial(), vertices, 1, scissorRect); } + /*! + * \brief Clones this sprite + */ + std::unique_ptr Sprite::Clone() const + { + return std::make_unique(*this); + } + /*! * \brief Makes the bounding volume of this text */ - void Sprite::MakeBoundingVolume() const { Vector3f origin(m_origin.x, -m_origin.y, m_origin.z); diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 883268963..8cc4961cf 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -41,6 +41,14 @@ namespace Nz } } + /*! + * \brief Clones this text sprite + */ + std::unique_ptr TextSprite::Clone() const + { + return std::make_unique(*this); + } + /*! * \brief Updates the text * diff --git a/src/Nazara/Graphics/TileMap.cpp b/src/Nazara/Graphics/TileMap.cpp index 26a146f88..6a30496c3 100644 --- a/src/Nazara/Graphics/TileMap.cpp +++ b/src/Nazara/Graphics/TileMap.cpp @@ -37,6 +37,14 @@ namespace Nz } } + /*! + * \brief Clones this tilemap + */ + std::unique_ptr TileMap::Clone() const + { + return std::make_unique(*this); + } + void TileMap::MakeBoundingVolume() const { Nz::Vector2f size = GetSize(); diff --git a/src/Nazara/Lua/LuaCoroutine.cpp b/src/Nazara/Lua/LuaCoroutine.cpp index bccf8d7fc..ad3f40736 100644 --- a/src/Nazara/Lua/LuaCoroutine.cpp +++ b/src/Nazara/Lua/LuaCoroutine.cpp @@ -47,7 +47,7 @@ namespace Nz } } - bool LuaCoroutine::Run(int argCount, int /*resultCount*/) + bool LuaCoroutine::Run(int argCount, int /*resultCount*/, int /*errHandler*/) { return Resume(argCount) != Ternary_False; } diff --git a/src/Nazara/Lua/LuaState.cpp b/src/Nazara/Lua/LuaState.cpp index 67bf8efa0..dfbec1117 100644 --- a/src/Nazara/Lua/LuaState.cpp +++ b/src/Nazara/Lua/LuaState.cpp @@ -144,12 +144,22 @@ namespace Nz bool LuaState::Call(unsigned int argCount) { - return Run(argCount, LUA_MULTRET); + return Run(argCount, LUA_MULTRET, 0); } bool LuaState::Call(unsigned int argCount, unsigned int resultCount) { - return Run(argCount, resultCount); + return Run(argCount, resultCount, 0); + } + + bool LuaState::CallWithHandler(unsigned int argCount, int errorHandler) + { + return Run(argCount, LUA_MULTRET, errorHandler); + } + + bool LuaState::CallWithHandler(unsigned int argCount, unsigned int resultCount, int errorHandler) + { + return Run(argCount, resultCount, errorHandler); } void LuaState::CheckAny(int index) const @@ -350,66 +360,37 @@ namespace Nz luaL_error(m_state, message.GetConstBuffer()); } - bool LuaState::Execute(const String& code) + bool LuaState::Execute(const String& code, int errorHandler) { if (code.IsEmpty()) return true; - if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0) - { - m_lastError = lua_tostring(m_state, -1); - lua_pop(m_state, 1); - + if (!Load(code)) return false; - } - return Run(0, LUA_MULTRET); + return CallWithHandler(errorHandler, 0); } - bool LuaState::ExecuteFromFile(const String& filePath) + bool LuaState::ExecuteFromFile(const String& filePath, int errorHandler) { - File file(filePath); - if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) - { - NazaraError("Failed to open file"); + if (!LoadFromFile(filePath)) return false; - } - std::size_t length = static_cast(file.GetSize()); - - String source(length, '\0'); - - if (file.Read(&source[0], length) != length) - { - NazaraError("Failed to read file"); - return false; - } - - file.Close(); - - return Execute(source); + return CallWithHandler(errorHandler, 0); } - bool LuaState::ExecuteFromMemory(const void* data, std::size_t size) + bool LuaState::ExecuteFromMemory(const void* data, std::size_t size, int errorHandler) { MemoryView stream(data, size); - return ExecuteFromStream(stream); + return ExecuteFromStream(stream, errorHandler); } - bool LuaState::ExecuteFromStream(Stream& stream) + bool LuaState::ExecuteFromStream(Stream& stream, int errorHandler) { - StreamData data; - data.stream = &stream; - - if (lua_load(m_state, StreamReader, &data, "C++", nullptr) != 0) - { - m_lastError = lua_tostring(m_state, -1); - lua_pop(m_state, 1); - + if (!LoadFromStream(stream)) return false; - } - return Run(0, LUA_MULTRET); + return CallWithHandler(errorHandler, 0); } int LuaState::GetAbsIndex(int index) const @@ -545,6 +526,65 @@ namespace Nz return lua_isnoneornil(m_state, index) == 0; } + bool LuaState::Load(const String& code) + { + if (luaL_loadstring(m_state, code.GetConstBuffer()) != 0) + { + m_lastError = lua_tostring(m_state, -1); + lua_pop(m_state, 1); + + return false; + } + + return true; + } + + bool LuaState::LoadFromFile(const String& filePath) + { + File file(filePath); + if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) + { + NazaraError("Failed to open file"); + return false; + } + + std::size_t length = static_cast(file.GetSize()); + + String source(length, '\0'); + + if (file.Read(&source[0], length) != length) + { + NazaraError("Failed to read file"); + return false; + } + + file.Close(); + + return Load(source); + } + + bool LuaState::LoadFromMemory(const void* data, std::size_t size) + { + MemoryView stream(data, size); + return LoadFromStream(stream); + } + + bool LuaState::LoadFromStream(Stream& stream) + { + StreamData data; + data.stream = &stream; + + if (lua_load(m_state, StreamReader, &data, "C++", nullptr) != 0) + { + m_lastError = lua_tostring(m_state, -1); + lua_pop(m_state, 1); + + return false; + } + + return true; + } + long long LuaState::Length(int index) const { return luaL_len(m_state, index); @@ -779,14 +819,19 @@ namespace Nz return luaL_testudata(m_state, index, tname.GetConstBuffer()); } - bool LuaState::Run(int argCount, int resultCount) + void LuaState::Traceback(const char* message, int level) + { + luaL_traceback(m_state, m_state, message, level); + } + + bool LuaState::Run(int argCount, int resultCount, int errHandler) { LuaInstance& instance = GetInstance(m_state); if (instance.m_level++ == 0) instance.m_clock.Restart(); - int status = lua_pcall(m_state, argCount, resultCount, 0); + int status = lua_pcall(m_state, argCount, resultCount, errHandler); instance.m_level--; diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.cpp b/src/Nazara/Network/Posix/SocketPollerImpl.cpp index 810427933..01cc9ffa9 100644 --- a/src/Nazara/Network/Posix/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Posix/SocketPollerImpl.cpp @@ -100,17 +100,17 @@ namespace Nz if (entry.revents & (POLLWRNORM | POLLERR)) m_readyToWriteSockets.insert(entry.fd); - - entry.revents = 0; - - if (--socketRemaining == 0) - break; } else { NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by WSAPoll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')'); activeSockets--; } + + entry.revents = 0; + + if (--socketRemaining == 0) + break; } } diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.cpp b/src/Nazara/Network/Win32/SocketPollerImpl.cpp index 658e86c8e..5fa5ac5a2 100644 --- a/src/Nazara/Network/Win32/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Win32/SocketPollerImpl.cpp @@ -154,17 +154,17 @@ namespace Nz if (entry.revents & (POLLWRNORM | POLLERR)) m_readyToWriteSockets.insert(entry.fd); - - entry.revents = 0; - - if (--socketRemaining == 0) - break; } else { NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by WSAPoll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')'); activeSockets--; } + + entry.revents = 0; + + if (--socketRemaining == 0) + break; } } #else diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index 807c0e7cc..ea648b197 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -311,14 +311,15 @@ namespace Nz { m_timestepAccumulator += timestep; - std::size_t stepCount = 0; - while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount) + std::size_t stepCount = std::min(static_cast(m_timestepAccumulator / m_stepSize), m_maxStepCount); + float invStepCount = 1.f / stepCount; + for (std::size_t i = 0; i < stepCount; ++i) { - OnPhysWorld2DPreStep(this); + OnPhysWorld2DPreStep(this, invStepCount); cpSpaceStep(m_handle, m_stepSize); - OnPhysWorld2DPostStep(this); + OnPhysWorld2DPostStep(this, invStepCount); if (!m_rigidPostSteps.empty()) { for (const auto& pair : m_rigidPostSteps) @@ -331,7 +332,6 @@ namespace Nz } m_timestepAccumulator -= m_stepSize; - stepCount++; } } diff --git a/src/Nazara/Utility/Formats/MD2Loader.cpp b/src/Nazara/Utility/Formats/MD2Loader.cpp index 6758a2e1b..ac7d6e5d7 100644 --- a/src/Nazara/Utility/Formats/MD2Loader.cpp +++ b/src/Nazara/Utility/Formats/MD2Loader.cpp @@ -158,12 +158,7 @@ namespace Nz #endif VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, header.num_vertices, parameters.storage, parameters.vertexBufferFlags); - StaticMeshRef subMesh = StaticMesh::New(mesh); - if (!subMesh->Create(vertexBuffer)) - { - NazaraError("Failed to create SubMesh"); - return false; - } + StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer); // Extracting vertices stream.SetCursorPos(header.offset_frames); diff --git a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp index d7104b9d0..84197e1c9 100644 --- a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp +++ b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp @@ -202,13 +202,9 @@ namespace Nz mesh->SetMaterialData(i, std::move(matData)); // Submesh - SkeletalMeshRef subMesh = SkeletalMesh::New(mesh); - subMesh->Create(vertexBuffer); - - subMesh->SetIndexBuffer(indexBuffer); + SkeletalMeshRef subMesh = SkeletalMesh::New(vertexBuffer, indexBuffer); subMesh->GenerateNormalsAndTangents(); subMesh->SetMaterialIndex(i); - subMesh->SetPrimitiveMode(PrimitiveMode_TriangleList); mesh->AddSubMesh(subMesh); @@ -255,6 +251,9 @@ namespace Nz } indexMapper.Unmap(); + if (parameters.optimizeIndexBuffers) + indexBuffer->Optimize(); + // Vertex buffer VertexBufferRef vertexBuffer = VertexBuffer::New(parameters.vertexDeclaration, UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags); @@ -287,13 +286,7 @@ namespace Nz vertexMapper.Unmap(); // Submesh - StaticMeshRef subMesh = StaticMesh::New(mesh); - subMesh->Create(vertexBuffer); - - if (parameters.optimizeIndexBuffers) - indexBuffer->Optimize(); - - subMesh->SetIndexBuffer(indexBuffer); + StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer); subMesh->GenerateAABB(); subMesh->SetMaterialIndex(i); diff --git a/src/Nazara/Utility/Formats/OBJLoader.cpp b/src/Nazara/Utility/Formats/OBJLoader.cpp index 43e938bf4..23a569337 100644 --- a/src/Nazara/Utility/Formats/OBJLoader.cpp +++ b/src/Nazara/Utility/Formats/OBJLoader.cpp @@ -259,6 +259,9 @@ namespace Nz indexMapper.Unmap(); // Pour laisser les autres tâches affecter l'index buffer + if (parameters.optimizeIndexBuffers) + indexBuffer->Optimize(); + // Remplissage des vertices // Make sure the normal matrix won't rescale our normals @@ -311,20 +314,9 @@ namespace Nz vertexMapper.Unmap(); - StaticMeshRef subMesh = StaticMesh::New(mesh); - if (!subMesh->Create(vertexBuffer)) - { - NazaraError("Failed to create StaticMesh"); - continue; - } - - if (parameters.optimizeIndexBuffers) - indexBuffer->Optimize(); - + StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer); subMesh->GenerateAABB(); - subMesh->SetIndexBuffer(indexBuffer); subMesh->SetMaterialIndex(meshes[i].material); - subMesh->SetPrimitiveMode(PrimitiveMode_TriangleList); // Ce que nous pouvons générer dépend des données à disposition (par exemple les tangentes nécessitent des coordonnées de texture) if (hasNormals && hasTexCoords) diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index 4455a2f0c..e1e5cb126 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -106,6 +106,7 @@ namespace Nz void IndexBuffer::Reset(bool largeIndices, BufferRef buffer, UInt32 offset, UInt32 size) { NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer"); + NazaraAssert(buffer->GetType() == BufferType_Index, "Buffer must be an index buffer"); NazaraAssert(size > 0, "Invalid size"); NazaraAssert(offset + size > buffer->GetSize(), "Virtual buffer exceed buffer bounds"); diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 66ee817ff..015ee520d 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// Copyright (C) 2017 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 @@ -56,62 +56,40 @@ namespace Nz return true; } - struct MeshImpl - { - MeshImpl() - { - materialData.resize(1); // One material by default - } - - std::unordered_map subMeshMap; - std::vector materialData; - std::vector subMeshes; - AnimationType animationType; - Boxf aabb; - Skeleton skeleton; // Only used by skeletal meshes - String animationPath; - bool aabbUpdated = false; - UInt32 jointCount; // Only used by skeletal meshes - }; - - Mesh::~Mesh() - { - OnMeshRelease(this); - - Destroy(); - } void Mesh::AddSubMesh(SubMesh* subMesh) { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); NazaraAssert(subMesh, "Invalid submesh"); - NazaraAssert(subMesh->GetAnimationType() == m_impl->animationType, "Submesh animation type doesn't match mesh animation type"); + NazaraAssert(subMesh->GetAnimationType() == m_animationType, "Submesh animation type doesn't match mesh animation type"); - m_impl->subMeshes.emplace_back(subMesh); + m_subMeshes.emplace_back(); + SubMeshData& subMeshData = m_subMeshes.back(); + subMeshData.subMesh = subMesh; + subMeshData.onSubMeshInvalidated.Connect(subMesh->OnSubMeshInvalidateAABB, [this](const SubMesh* /*subMesh*/) { InvalidateAABB(); }); InvalidateAABB(); } void Mesh::AddSubMesh(const String& identifier, SubMesh* subMesh) { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "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(m_subMeshMap.find(identifier) == m_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"); + NazaraAssert(subMesh->GetAnimationType() == m_animationType, "Submesh animation type doesn't match mesh animation type"); - std::size_t index = m_impl->subMeshes.size(); + std::size_t index = m_subMeshes.size(); - m_impl->subMeshes.emplace_back(subMesh); - m_impl->subMeshMap[identifier] = static_cast(index); + AddSubMesh(subMesh); - InvalidateAABB(); + m_subMeshMap[identifier] = static_cast(index); } SubMesh* Mesh::BuildSubMesh(const Primitive& primitive, const MeshParams& params) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Static, "Submesh building only works for static meshes"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Static, "Submesh building only works for static meshes"); NazaraAssert(params.IsValid(), "Invalid parameters"); NazaraAssert(params.vertexDeclaration->HasComponentOfType(VertexComponent_Position), "The vertex declaration doesn't have a Vector3 position component"); @@ -266,18 +244,11 @@ namespace Nz } } - StaticMeshRef subMesh = StaticMesh::New(this); - if (!subMesh->Create(vertexBuffer)) - { - NazaraError("Failed to create StaticMesh"); - return nullptr; - } - if (params.optimizeIndexBuffers) indexBuffer->Optimize(); + StaticMeshRef subMesh = StaticMesh::New(vertexBuffer, indexBuffer); subMesh->SetAABB(aabb); - subMesh->SetIndexBuffer(indexBuffer); AddSubMesh(subMesh); return subMesh; @@ -293,16 +264,15 @@ namespace Nz { Destroy(); - std::unique_ptr impl(new MeshImpl); - impl->animationType = AnimationType_Skeletal; - impl->jointCount = jointCount; - if (!impl->skeleton.Create(jointCount)) + m_animationType = AnimationType_Skeletal; + m_jointCount = jointCount; + if (!m_skeleton.Create(jointCount)) { NazaraError("Failed to create skeleton"); return false; } - m_impl = impl.release(); + m_isValid = true; return true; } @@ -311,236 +281,244 @@ namespace Nz { Destroy(); - m_impl = new MeshImpl; - m_impl->animationType = AnimationType_Static; + m_animationType = AnimationType_Static; + m_isValid = true; return true; } void Mesh::Destroy() { - if (m_impl) + if (m_isValid) { OnMeshDestroy(this); - delete m_impl; - m_impl = nullptr; + m_animationPath.Clear(); + m_materialData.clear(); + m_materialData.resize(1); + m_skeleton.Destroy(); + m_subMeshes.clear(); + m_subMeshMap.clear(); + + m_isValid = false; } } void Mesh::GenerateNormals() { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - for (SubMesh* subMesh : m_impl->subMeshes) - subMesh->GenerateNormals(); + for (SubMeshData& data : m_subMeshes) + data.subMesh->GenerateNormals(); } void Mesh::GenerateNormalsAndTangents() { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - for (SubMesh* subMesh : m_impl->subMeshes) - subMesh->GenerateNormalsAndTangents(); + for (SubMeshData& data : m_subMeshes) + data.subMesh->GenerateNormalsAndTangents(); } void Mesh::GenerateTangents() { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - for (SubMesh* subMesh : m_impl->subMeshes) - subMesh->GenerateTangents(); + for (SubMeshData& data : m_subMeshes) + data.subMesh->GenerateTangents(); } const Boxf& Mesh::GetAABB() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - if (!m_impl->aabbUpdated) + if (!m_aabbUpdated) { - std::size_t subMeshCount = m_impl->subMeshes.size(); + std::size_t subMeshCount = m_subMeshes.size(); if (subMeshCount > 0) { - m_impl->aabb.Set(m_impl->subMeshes[0]->GetAABB()); + m_aabb.Set(m_subMeshes.front().subMesh->GetAABB()); for (std::size_t i = 1; i < subMeshCount; ++i) - m_impl->aabb.ExtendTo(m_impl->subMeshes[i]->GetAABB()); + m_aabb.ExtendTo(m_subMeshes[i].subMesh->GetAABB()); } else - m_impl->aabb.MakeZero(); + m_aabb.MakeZero(); - m_impl->aabbUpdated = true; + m_aabbUpdated = true; } - return m_impl->aabb; + return m_aabb; } String Mesh::GetAnimation() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return m_impl->animationPath; + return m_animationPath; } AnimationType Mesh::GetAnimationType() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return m_impl->animationType; + return m_animationType; } UInt32 Mesh::GetJointCount() const { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal"); - return m_impl->jointCount; + return m_jointCount; } ParameterList& Mesh::GetMaterialData(UInt32 index) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(index < m_impl->materialData.size(), "Material index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(index < m_materialData.size(), "Material index out of range"); - return m_impl->materialData[index]; + return m_materialData[index]; } const ParameterList& Mesh::GetMaterialData(UInt32 index) const { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(index < m_impl->materialData.size(), "Material index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(index < m_materialData.size(), "Material index out of range"); - return m_impl->materialData[index]; + return m_materialData[index]; } UInt32 Mesh::GetMaterialCount() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return static_cast(m_impl->materialData.size()); + return static_cast(m_materialData.size()); } Skeleton* Mesh::GetSkeleton() { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal"); - return &m_impl->skeleton; + return &m_skeleton; } const Skeleton* Mesh::GetSkeleton() const { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Skeletal, "Mesh is not skeletal"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Skeletal, "Mesh is not skeletal"); - return &m_impl->skeleton; + return &m_skeleton; } SubMesh* Mesh::GetSubMesh(const String& identifier) { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - auto it = m_impl->subMeshMap.find(identifier); - NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); + auto it = m_subMeshMap.find(identifier); + NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found"); - return m_impl->subMeshes[it->second]; + return m_subMeshes[it->second].subMesh; } SubMesh* Mesh::GetSubMesh(UInt32 index) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range"); - return m_impl->subMeshes[index]; + return m_subMeshes[index].subMesh; } const SubMesh* Mesh::GetSubMesh(const String& identifier) const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - auto it = m_impl->subMeshMap.find(identifier); - NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); + auto it = m_subMeshMap.find(identifier); + NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found"); - return m_impl->subMeshes[it->second]; + return m_subMeshes[it->second].subMesh; } const SubMesh* Mesh::GetSubMesh(UInt32 index) const { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range"); - return m_impl->subMeshes[index]; + return m_subMeshes[index].subMesh; } UInt32 Mesh::GetSubMeshCount() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return static_cast(m_impl->subMeshes.size()); + return static_cast(m_subMeshes.size()); } UInt32 Mesh::GetSubMeshIndex(const String& identifier) const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - auto it = m_impl->subMeshMap.find(identifier); - NazaraAssert(it != m_impl->subMeshMap.end(), "SubMesh " + identifier + " not found"); + auto it = m_subMeshMap.find(identifier); + NazaraAssert(it != m_subMeshMap.end(), "SubMesh " + identifier + " not found"); return it->second; } UInt32 Mesh::GetTriangleCount() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); UInt32 triangleCount = 0; - for (SubMesh* subMesh : m_impl->subMeshes) - triangleCount += subMesh->GetTriangleCount(); + for (const SubMeshData& data : m_subMeshes) + triangleCount += data.subMesh->GetTriangleCount(); return triangleCount; } UInt32 Mesh::GetVertexCount() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); UInt32 vertexCount = 0; - for (SubMesh* subMesh : m_impl->subMeshes) - vertexCount += subMesh->GetVertexCount(); + for (const SubMeshData& data : m_subMeshes) + vertexCount += data.subMesh->GetVertexCount(); return vertexCount; } void Mesh::InvalidateAABB() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - m_impl->aabbUpdated = false; + m_aabbUpdated = false; + + OnMeshInvalidateAABB(this); } bool Mesh::HasSubMesh(const String& identifier) const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return m_impl->subMeshMap.find(identifier) != m_impl->subMeshMap.end(); + return m_subMeshMap.find(identifier) != m_subMeshMap.end(); } bool Mesh::HasSubMesh(UInt32 index) const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return index < m_impl->subMeshes.size(); + return index < m_subMeshes.size(); } bool Mesh::IsAnimable() const { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - return m_impl->animationType != AnimationType_Static; + return m_animationType != AnimationType_Static; } bool Mesh::IsValid() const { - return m_impl != nullptr; + return m_isValid; } bool Mesh::LoadFromFile(const String& filePath, const MeshParams& params) @@ -560,20 +538,20 @@ namespace Nz void Mesh::Recenter() { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Static, "Mesh is not static"); // The center of our mesh is the center of our *global* AABB Vector3f center = GetAABB().GetCenter(); - for (SubMesh* subMesh : m_impl->subMeshes) + for (SubMeshData& data : m_subMeshes) { - StaticMesh* staticMesh = static_cast(subMesh); + StaticMesh& staticMesh = static_cast(*data.subMesh); - BufferMapper mapper(staticMesh->GetVertexBuffer(), BufferAccess_ReadWrite); + BufferMapper mapper(staticMesh.GetVertexBuffer(), BufferAccess_ReadWrite); MeshVertex* vertices = static_cast(mapper.GetPointer()); - UInt32 vertexCount = staticMesh->GetVertexCount(); + UInt32 vertexCount = staticMesh.GetVertexCount(); for (UInt32 i = 0; i < vertexCount; ++i) { vertices->position -= center; @@ -581,13 +559,11 @@ namespace Nz } // Our AABB doesn't change shape, only position - Boxf aabb = staticMesh->GetAABB(); + Boxf aabb = staticMesh.GetAABB(); aabb.Translate(-center); - staticMesh->SetAABB(aabb); + staticMesh.SetAABB(aabb); // This will invalidate our AABB } - - InvalidateAABB(); } void Mesh::RemoveSubMesh(const String& identifier) @@ -595,22 +571,22 @@ namespace Nz UInt32 index = GetSubMeshIndex(identifier); // On déplace l'itérateur du début d'une distance de x - auto it2 = m_impl->subMeshes.begin(); + auto it2 = m_subMeshes.begin(); std::advance(it2, index); - m_impl->subMeshes.erase(it2); + m_subMeshes.erase(it2); InvalidateAABB(); } void Mesh::RemoveSubMesh(UInt32 index) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(index < m_impl->subMeshes.size(), "Submesh index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(index < m_subMeshes.size(), "Submesh index out of range"); // On déplace l'itérateur du début de x - auto it = m_impl->subMeshes.begin(); + auto it = m_subMeshes.begin(); std::advance(it, index); - m_impl->subMeshes.erase(it); + m_subMeshes.erase(it); InvalidateAABB(); } @@ -627,34 +603,34 @@ namespace Nz void Mesh::SetAnimation(const String& animationPath) { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); - m_impl->animationPath = animationPath; + m_animationPath = animationPath; } void Mesh::SetMaterialData(UInt32 matIndex, ParameterList data) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(matIndex < m_impl->materialData.size(), "Material index out of range"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(matIndex < m_materialData.size(), "Material index out of range"); - m_impl->materialData[matIndex] = std::move(data); + m_materialData[matIndex] = std::move(data); } void Mesh::SetMaterialCount(UInt32 matCount) { - NazaraAssert(m_impl, "Mesh should be created first"); + NazaraAssert(m_isValid, "Mesh should be created first"); NazaraAssert(matCount > 0, "A mesh should have at least a material"); - m_impl->materialData.resize(matCount); + m_materialData.resize(matCount); #ifdef NAZARA_DEBUG - for (SubMesh* subMesh : m_impl->subMeshes) + for (SubMeshData& data : m_subMeshes) { - UInt32 matIndex = subMesh->GetMaterialIndex(); + UInt32 matIndex = data.subMesh->GetMaterialIndex(); if (matIndex >= matCount) { - 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"); + data.subMesh->SetMaterialIndex(0); // To prevent a crash + NazaraWarning("SubMesh " + String::Pointer(data.subMesh) + " material index is over mesh new material count (" + String::Number(matIndex) + " >= " + String::Number(matCount) + "), setting it to first material"); } } #endif @@ -662,19 +638,19 @@ namespace Nz void Mesh::Transform(const Matrix4f& matrix) { - NazaraAssert(m_impl, "Mesh should be created first"); - NazaraAssert(m_impl->animationType == AnimationType_Static, "Mesh is not static"); + NazaraAssert(m_isValid, "Mesh should be created first"); + NazaraAssert(m_animationType == AnimationType_Static, "Mesh is not static"); - for (SubMesh* subMesh : m_impl->subMeshes) + for (SubMeshData& data : m_subMeshes) { - StaticMesh* staticMesh = static_cast(subMesh); + StaticMesh& staticMesh = static_cast(*data.subMesh); - BufferMapper mapper(staticMesh->GetVertexBuffer(), BufferAccess_ReadWrite); + BufferMapper mapper(staticMesh.GetVertexBuffer(), BufferAccess_ReadWrite); MeshVertex* vertices = static_cast(mapper.GetPointer()); Boxf aabb(vertices->position.x, vertices->position.y, vertices->position.z, 0.f, 0.f, 0.f); - UInt32 vertexCount = staticMesh->GetVertexCount(); + UInt32 vertexCount = staticMesh.GetVertexCount(); for (UInt32 i = 0; i < vertexCount; ++i) { vertices->position = matrix.Transform(vertices->position); @@ -683,10 +659,8 @@ namespace Nz vertices++; } - staticMesh->SetAABB(aabb); + staticMesh.SetAABB(aabb); //< This will invalidate our AABB } - - InvalidateAABB(); } bool Mesh::Initialize() diff --git a/src/Nazara/Utility/SkeletalMesh.cpp b/src/Nazara/Utility/SkeletalMesh.cpp index 02550a4d6..e5a3a3268 100644 --- a/src/Nazara/Utility/SkeletalMesh.cpp +++ b/src/Nazara/Utility/SkeletalMesh.cpp @@ -8,8 +8,16 @@ namespace Nz { - SkeletalMesh::SkeletalMesh(const Mesh* parent) : - SubMesh(parent) + SkeletalMesh::SkeletalMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer) : + m_aabb(Nz::Boxf::Zero()), + m_indexBuffer(indexBuffer), + m_vertexBuffer(vertexBuffer) + { + NazaraAssert(m_vertexBuffer, "Invalid vertex buffer"); + } + + SkeletalMesh::SkeletalMesh(const Mesh* /*parent*/) : + m_aabb(Nz::Boxf::Zero()) { } @@ -90,6 +98,8 @@ namespace Nz void SkeletalMesh::SetAABB(const Boxf& aabb) { m_aabb = aabb; + + OnSubMeshInvalidateAABB(this); } void SkeletalMesh::SetIndexBuffer(const IndexBuffer* indexBuffer) diff --git a/src/Nazara/Utility/StaticMesh.cpp b/src/Nazara/Utility/StaticMesh.cpp index 7c7637481..b363736f7 100644 --- a/src/Nazara/Utility/StaticMesh.cpp +++ b/src/Nazara/Utility/StaticMesh.cpp @@ -10,8 +10,16 @@ namespace Nz { - StaticMesh::StaticMesh(const Mesh* parent) : - SubMesh(parent) + StaticMesh::StaticMesh(VertexBuffer* vertexBuffer, const IndexBuffer* indexBuffer) : + m_aabb(Nz::Boxf::Zero()), + m_indexBuffer(indexBuffer), + m_vertexBuffer(vertexBuffer) + { + NazaraAssert(m_vertexBuffer, "Invalid vertex buffer"); + } + + StaticMesh::StaticMesh(const Mesh* /*parent*/) : + m_aabb(Nz::Boxf::Zero()) { } @@ -69,7 +77,7 @@ namespace Nz { // On lock le buffer pour itérer sur toutes les positions et composer notre AABB VertexMapper mapper(m_vertexBuffer, BufferAccess_ReadOnly); - m_aabb = ComputeAABB(mapper.GetComponentPtr(VertexComponent_Position), m_vertexBuffer->GetVertexCount()); + SetAABB(ComputeAABB(mapper.GetComponentPtr(VertexComponent_Position), m_vertexBuffer->GetVertexCount())); return true; } @@ -117,10 +125,12 @@ namespace Nz void StaticMesh::SetAABB(const Boxf& aabb) { m_aabb = aabb; + + OnSubMeshInvalidateAABB(this); } void StaticMesh::SetIndexBuffer(const IndexBuffer* indexBuffer) { m_indexBuffer = indexBuffer; -} + } } diff --git a/src/Nazara/Utility/SubMesh.cpp b/src/Nazara/Utility/SubMesh.cpp index 44e601d22..0b7a95b31 100644 --- a/src/Nazara/Utility/SubMesh.cpp +++ b/src/Nazara/Utility/SubMesh.cpp @@ -12,14 +12,18 @@ namespace Nz { - SubMesh::SubMesh(const Mesh* parent) : - RefCounted(false), // Un SubMesh n'est pas persistant par défaut + SubMesh::SubMesh() : + RefCounted(false), // wut m_primitiveMode(PrimitiveMode_TriangleList), - m_parent(parent), m_matIndex(0) { } + SubMesh::SubMesh(const Mesh* /*parent*/) : + SubMesh() + { + } + SubMesh::~SubMesh() { OnSubMeshRelease(this); @@ -160,11 +164,6 @@ namespace Nz while (iterator.Advance()); } - const Mesh* SubMesh::GetParent() const - { - return m_parent; - } - PrimitiveMode SubMesh::GetPrimitiveMode() const { return m_primitiveMode; diff --git a/src/Nazara/Utility/UniformBuffer.cpp b/src/Nazara/Utility/UniformBuffer.cpp new file mode 100644 index 000000000..0ae065e3f --- /dev/null +++ b/src/Nazara/Utility/UniformBuffer.cpp @@ -0,0 +1,118 @@ +// Copyright (C) 2017 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 + +namespace Nz +{ + UniformBuffer::UniformBuffer(BufferRef buffer) + { + ErrorFlags(ErrorFlag_ThrowException, true); + Reset(std::move(buffer)); + } + + UniformBuffer::UniformBuffer(BufferRef buffer, UInt32 offset, UInt32 size) + { + ErrorFlags(ErrorFlag_ThrowException, true); + Reset(std::move(buffer), offset, size); + } + + UniformBuffer::UniformBuffer(UInt32 length, DataStorage storage, BufferUsageFlags usage) + { + ErrorFlags(ErrorFlag_ThrowException, true); + Reset(length, storage, usage); + } + + UniformBuffer::UniformBuffer(const UniformBuffer& uniformBuffer) : + RefCounted(), + m_buffer(uniformBuffer.m_buffer), + m_endOffset(uniformBuffer.m_endOffset), + m_startOffset(uniformBuffer.m_startOffset) + { + } + + UniformBuffer::~UniformBuffer() + { + OnUniformBufferRelease(this); + } + + bool UniformBuffer::Fill(const void* data, UInt32 offset, UInt32 size) + { + NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer"); + NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size"); + + return m_buffer->Fill(data, m_startOffset + offset, size); + } + + void* UniformBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size) + { + NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer"); + NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size"); + + return m_buffer->Map(access, offset, size); + } + + void* UniformBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size) const + { + NazaraAssert(m_buffer && m_buffer->IsValid(), "Invalid buffer"); + NazaraAssert(m_startOffset + offset + size <= m_endOffset, "Exceeding virtual buffer size"); + + return m_buffer->Map(access, offset, size); + } + + void UniformBuffer::Reset() + { + m_buffer.Reset(); + } + + void UniformBuffer::Reset(BufferRef buffer) + { + NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer"); + + Reset(buffer, 0, buffer->GetSize()); + } + + void UniformBuffer::Reset(BufferRef buffer, UInt32 offset, UInt32 size) + { + NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer"); + NazaraAssert(buffer->GetType() == BufferType_Uniform, "Buffer must be an uniform buffer"); + NazaraAssert(size > 0, "Invalid size"); + NazaraAssert(offset + size > buffer->GetSize(), "Virtual buffer exceed buffer bounds"); + + m_buffer = buffer; + m_endOffset = offset + size; + m_startOffset = offset; + } + + void UniformBuffer::Reset(UInt32 size, DataStorage storage, BufferUsageFlags usage) + { + m_endOffset = size; + m_startOffset = 0; + + m_buffer = Buffer::New(BufferType_Uniform, m_endOffset, storage, usage); + } + + void UniformBuffer::Reset(const UniformBuffer& UniformBuffer) + { + m_buffer = UniformBuffer.m_buffer; + m_endOffset = UniformBuffer.m_endOffset; + m_startOffset = UniformBuffer.m_startOffset; + } + + void UniformBuffer::Unmap() const + { + m_buffer->Unmap(); + } + + UniformBuffer& UniformBuffer::operator=(const UniformBuffer& uniformBuffer) + { + Reset(uniformBuffer); + + return *this; + } +} diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index e072c4aa1..d84dd8b39 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -98,6 +98,7 @@ namespace Nz void VertexBuffer::Reset(VertexDeclarationConstRef vertexDeclaration, BufferRef buffer) { NazaraAssert(buffer && buffer->IsValid(), "Invalid buffer"); + NazaraAssert(buffer->GetType() == BufferType_Vertex, "Buffer must be a vertex buffer"); UInt32 size = buffer->GetSize(); Reset(std::move(vertexDeclaration), std::move(buffer), 0, size);