diff --git a/examples/DeferredShading/main.cpp b/examples/DeferredShading/main.cpp index 642cc6816..aa2b94f4d 100644 --- a/examples/DeferredShading/main.cpp +++ b/examples/DeferredShading/main.cpp @@ -220,34 +220,16 @@ int main() std::vector instanceDataBuffer(instanceUboOffsets.totalSize); Nz::ModelInstance modelInstance1(spaceshipMat->GetSettings()); - { - spaceshipMat->UpdateShaderBinding(modelInstance1.GetShaderBinding()); - - Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right()); - - std::shared_ptr& instanceDataUBO = modelInstance1.GetInstanceBuffer(); - instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); - } + spaceshipMat->UpdateShaderBinding(modelInstance1.GetShaderBinding()); + modelInstance1.UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right())); Nz::ModelInstance modelInstance2(spaceshipMat->GetSettings()); - { - spaceshipMat->UpdateShaderBinding(modelInstance2.GetShaderBinding()); - - Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right() * 3.f); - - std::shared_ptr& instanceDataUBO = modelInstance2.GetInstanceBuffer(); - instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); - } + spaceshipMat->UpdateShaderBinding(modelInstance2.GetShaderBinding()); + modelInstance2.UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Forward() * 2 + Nz::Vector3f::Right() * 3.f)); Nz::ModelInstance planeInstance(planeMat->GetSettings()); - { - planeMat->UpdateShaderBinding(planeInstance.GetShaderBinding()); - - Nz::AccessByOffset(instanceDataBuffer.data(), instanceUboOffsets.worldMatrixOffset) = Nz::Matrix4f::Translate(Nz::Vector3f::Up() * 2.f); - - std::shared_ptr& instanceDataUBO = planeInstance.GetInstanceBuffer(); - instanceDataUBO->Fill(instanceDataBuffer.data(), 0, instanceDataBuffer.size()); - } + planeMat->UpdateShaderBinding(planeInstance.GetShaderBinding()); + planeInstance.UpdateWorldMatrix(Nz::Matrix4f::Translate(Nz::Vector3f::Up() * 2.f)); std::shared_ptr viewerDataUBO = Nz::Graphics::Instance()->GetViewerDataUBO(); @@ -1045,6 +1027,8 @@ int main() forwardEnabled = !forwardEnabled; else if (event.key.virtualKey == Nz::Keyboard::VKey::A) lightAnimation = !lightAnimation; + else if (event.key.virtualKey == Nz::Keyboard::VKey::E) + modelInstance1.UpdateWorldMatrix(Nz::Matrix4f::Transform(viewerPos, camQuat)); break; } diff --git a/include/Nazara/Graphics/ModelInstance.hpp b/include/Nazara/Graphics/ModelInstance.hpp index 4067249e4..e8c790158 100644 --- a/include/Nazara/Graphics/ModelInstance.hpp +++ b/include/Nazara/Graphics/ModelInstance.hpp @@ -8,6 +8,7 @@ #define NAZARA_MODELINSTANCE_HPP #include +#include #include #include #include @@ -15,7 +16,9 @@ namespace Nz { class AbstractBuffer; + class CommandBufferBuilder; class MaterialSettings; + class UploadPool; class NAZARA_GRAPHICS_API ModelInstance { @@ -29,12 +32,19 @@ namespace Nz inline const std::shared_ptr& GetInstanceBuffer() const; inline ShaderBinding& GetShaderBinding(); + void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder); + inline void UpdateWorldMatrix(const Matrix4f& worldMatrix); + inline void UpdateWorldMatrix(const Matrix4f& worldMatrix, const Matrix4f& invWorldMatrix); + ModelInstance& operator=(const ModelInstance&) = delete; ModelInstance& operator=(ModelInstance&&) noexcept = default; private: std::shared_ptr m_instanceDataBuffer; + Matrix4f m_invWorldMatrix; + Matrix4f m_worldMatrix; ShaderBindingPtr m_shaderBinding; + bool m_dataInvalided; }; } diff --git a/include/Nazara/Graphics/ModelInstance.inl b/include/Nazara/Graphics/ModelInstance.inl index 2c87c6ecf..540963807 100644 --- a/include/Nazara/Graphics/ModelInstance.inl +++ b/include/Nazara/Graphics/ModelInstance.inl @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include namespace Nz @@ -21,6 +22,22 @@ namespace Nz { return *m_shaderBinding; } + + inline void ModelInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix) + { + m_worldMatrix = worldMatrix; + if (!m_worldMatrix.GetInverseAffine(&m_invWorldMatrix)) + NazaraError("failed to inverse world matrix"); + + m_dataInvalided = true; + } + + inline void ModelInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix, const Matrix4f& invWorldMatrix) + { + m_worldMatrix = worldMatrix; + m_invWorldMatrix = invWorldMatrix; + m_dataInvalided = true; + } } #include diff --git a/src/Nazara/Graphics/ModelInstance.cpp b/src/Nazara/Graphics/ModelInstance.cpp index 33fa75bf4..06e13909d 100644 --- a/src/Nazara/Graphics/ModelInstance.cpp +++ b/src/Nazara/Graphics/ModelInstance.cpp @@ -7,11 +7,16 @@ #include #include #include +#include +#include #include namespace Nz { - ModelInstance::ModelInstance(const std::shared_ptr& settings) + ModelInstance::ModelInstance(const std::shared_ptr& settings) : + m_invWorldMatrix(Nz::Matrix4f::Identity()), + m_worldMatrix(Nz::Matrix4f::Identity()), + m_dataInvalided(true) { Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); @@ -48,4 +53,20 @@ namespace Nz if (!bindings.empty()) m_shaderBinding->Update(bindings.data(), bindings.size()); } + + void ModelInstance::UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder) + { + if (m_dataInvalided) + { + Nz::PredefinedInstanceData instanceUboOffsets = Nz::PredefinedInstanceData::GetOffsets(); + + auto& allocation = uploadPool.Allocate(m_instanceDataBuffer->GetSize()); + Nz::AccessByOffset(allocation.mappedPtr, instanceUboOffsets.worldMatrixOffset) = m_worldMatrix; + Nz::AccessByOffset(allocation.mappedPtr, instanceUboOffsets.invWorldMatrixOffset) = m_invWorldMatrix; + + builder.CopyBuffer(allocation, m_instanceDataBuffer.get()); + + m_dataInvalided = false; + } + } }