diff --git a/examples/PhysicsDemo/main.cpp b/examples/PhysicsDemo/main.cpp new file mode 100644 index 000000000..96dca0bef --- /dev/null +++ b/examples/PhysicsDemo/main.cpp @@ -0,0 +1,410 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + std::filesystem::path resourceDir = "resources"; + if (!std::filesystem::is_directory(resourceDir) && std::filesystem::is_directory(".." / resourceDir)) + resourceDir = ".." / resourceDir; + + Nz::Renderer::Config rendererConfig; + std::cout << "Run using Vulkan? (y/n)" << std::endl; + if (std::getchar() != 'n') + rendererConfig.preferredAPI = Nz::RenderAPI::Vulkan; + else + rendererConfig.preferredAPI = Nz::RenderAPI::OpenGL; + + Nz::Modules nazara(rendererConfig); + + Nz::RenderWindow window; + + Nz::MeshParams meshParams; + meshParams.center = true; + meshParams.storage = Nz::DataStorage::Software; + meshParams.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 90.f, 0.f)) * Nz::Matrix4f::Scale(Nz::Vector3f(0.002f)); + meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_UV); + + std::shared_ptr device = Nz::Graphics::Instance()->GetRenderDevice(); + + std::string windowTitle = "Graphics Test"; + if (!window.Create(device, Nz::VideoMode(1920, 1080, 32), windowTitle)) + { + std::cout << "Failed to create Window" << std::endl; + return __LINE__; + } + + std::shared_ptr spaceshipMesh = Nz::Mesh::LoadFromFile(resourceDir / "Spaceship/spaceship.obj", meshParams); + if (!spaceshipMesh) + { + NazaraError("Failed to load model"); + return __LINE__; + } + + std::shared_ptr gfxMesh = std::make_shared(*spaceshipMesh); + + // Texture + std::shared_ptr diffuseImage = Nz::Image::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png"); + if (!diffuseImage || !diffuseImage->Convert(Nz::PixelFormat::RGBA8_SRGB)) + { + NazaraError("Failed to load image"); + return __LINE__; + } + + Nz::TextureParams texParams; + texParams.renderDevice = device; + texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; + + std::shared_ptr material = std::make_shared(Nz::BasicMaterial::GetSettings()); + material->EnableDepthBuffer(true); + material->EnableFaceCulling(true); + + Nz::TextureSamplerInfo samplerInfo; + samplerInfo.anisotropyLevel = 8; + + Nz::BasicMaterial basicMat(*material); + basicMat.EnableAlphaTest(false); + basicMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); + basicMat.SetDiffuseMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); + basicMat.SetDiffuseSampler(samplerInfo); + + std::shared_ptr model = std::make_shared(std::move(gfxMesh)); + for (std::size_t i = 0; i < model->GetSubMeshCount(); ++i) + model->SetMaterial(i, material); + + Nz::Vector2ui windowSize = window.GetSize(); + + Nz::ViewerInstance viewerInstance; + viewerInstance.UpdateTargetSize(Nz::Vector2f(window.GetSize())); + viewerInstance.UpdateProjViewMatrices(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f), Nz::Matrix4f::Translate(Nz::Vector3f::Backward() * 1)); + + Nz::VertexMapper vertexMapper(*spaceshipMesh->GetSubMesh(0), Nz::BufferAccess::ReadOnly); + Nz::SparsePtr vertices = vertexMapper.GetComponentPtr(Nz::VertexComponent::Position); + + + entt::registry registry; + + Nz::Physics3DSystem physSytem(registry); + + + auto shipCollider = std::make_shared(vertices, vertexMapper.GetVertexCount(), 0.01f); + + std::shared_ptr colliderMat = std::make_shared(Nz::BasicMaterial::GetSettings()); + colliderMat->EnableDepthBuffer(true); + colliderMat->SetPrimitiveMode(Nz::PrimitiveMode::LineList); + + Nz::BasicMaterial colliderBasicMat(*colliderMat); + colliderBasicMat.SetDiffuseColor(Nz::Color::Green); + + std::shared_ptr colliderModel; + { + std::shared_ptr colliderMesh = Nz::Mesh::Build(shipCollider->GenerateMesh()); + std::shared_ptr colliderGraphicalMesh = std::make_shared(*colliderMesh); + + colliderModel = std::make_shared(colliderGraphicalMesh); + for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i) + colliderModel->SetMaterial(i, colliderMat); + } + + entt::entity playerEntity = registry.create(); + Nz::Node headingNode; + { + auto& entityNode = registry.emplace(playerEntity); + entityNode.SetPosition(Nz::Vector3f(12.5f, 0.f, 25.f)); + + auto& entityGfx = registry.emplace(playerEntity); + entityGfx.AttachRenderable(model); + + auto& entityPhys = registry.emplace(playerEntity, physSytem.CreateRigidBody(shipCollider)); + entityPhys.SetMass(50.f); + entityPhys.SetAngularDamping(Nz::Vector3f::Zero()); + + headingNode.SetParent(entityNode); + headingNode.SetInheritRotation(false); + headingNode.SetRotation(entityNode.GetRotation()); + } + + + Nz::Node cameraNode; + cameraNode.SetParent(headingNode); + cameraNode.SetPosition(Nz::Vector3f::Backward() * 2.5f + Nz::Vector3f::Up() * 1.f); + + for (std::size_t x = 0; x < 1; ++x) + { + for (std::size_t y = 0; y < 1; ++y) + { + for (std::size_t z = 0; z < 10; ++z) + { + entt::entity entity = registry.create(); + auto& entityNode = registry.emplace(entity); + entityNode.SetPosition(Nz::Vector3f(x * 2.f, y * 1.5f, z * 2.f)); + + auto& entityGfx = registry.emplace(entity); + entityGfx.AttachRenderable(model); + + auto& entityPhys = registry.emplace(entity, physSytem.CreateRigidBody(shipCollider)); + entityPhys.SetMass(1.f); + entityPhys.SetAngularDamping(Nz::Vector3f::Zero()); + entityPhys.SetLinearDamping(0.f); + } + } + } + + + Nz::RenderWindowImpl* windowImpl = window.GetImpl(); + std::shared_ptr commandPool = windowImpl->CreateCommandPool(Nz::QueueType::Graphics); + + Nz::CommandBufferPtr drawCommandBuffer; + auto RebuildCommandBuffer = [&] + { + Nz::Vector2ui windowSize = window.GetSize(); + drawCommandBuffer = commandPool->BuildCommandBuffer([&](Nz::CommandBufferBuilder& builder) + { + Nz::Recti renderRect(0, 0, window.GetSize().x, window.GetSize().y); + + Nz::CommandBufferBuilder::ClearValues clearValues[2]; + clearValues[0].color = Nz::Color(80, 80, 80); + clearValues[1].depth = 1.f; + clearValues[1].stencil = 0; + + builder.BeginDebugRegion("Main window rendering", Nz::Color::Green); + { + builder.BeginRenderPass(windowImpl->GetFramebuffer(), windowImpl->GetRenderPass(), renderRect, { clearValues[0], clearValues[1] }); + { + builder.SetScissor(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.SetViewport(Nz::Recti{ 0, 0, int(windowSize.x), int(windowSize.y) }); + builder.BindShaderBinding(Nz::Graphics::ViewerBindingSet, viewerInstance.GetShaderBinding()); + + auto view = registry.view(); + for (auto [entity, gfxComponent] : view.each()) + { + const Nz::WorldInstance& worldInstance = gfxComponent.GetWorldInstance(); + for (const auto& renderable : gfxComponent.GetRenderables()) + renderable->Draw(builder, worldInstance); + } + } + builder.EndRenderPass(); + } + builder.EndDebugRegion(); + }); + }; + + + Nz::Vector3f viewerPos = Nz::Vector3f::Zero(); + + Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f); + Nz::Quaternionf camQuat(camAngles); + + window.EnableEventPolling(true); + + Nz::Clock updateClock; + Nz::Clock secondClock; + unsigned int fps = 0; + + Nz::Mouse::SetRelativeMouseMode(true); + + float elapsedTime = 0.f; + Nz::UInt64 time = Nz::GetElapsedMicroseconds(); + + Nz::PidController headingController(0.5f, 0.f, 0.05f); + Nz::PidController upController(1.f, 0.f, 0.1f); + + bool showColliders = false; + bool rebuildCommandBuffer = false; + while (window.IsOpen()) + { + Nz::UInt64 now = Nz::GetElapsedMicroseconds(); + elapsedTime = (now - time) / 1'000'000.f; + time = now; + + Nz::WindowEvent event; + while (window.PollEvent(&event)) + { + switch (event.type) + { + case Nz::WindowEventType::Quit: + window.Close(); + break; + + case Nz::WindowEventType::KeyPressed: + if (event.key.virtualKey == Nz::Keyboard::VKey::A) + { + basicMat.EnableAlphaTest(!basicMat.IsAlphaTestEnabled()); + rebuildCommandBuffer = true; + } + else if (event.key.virtualKey == Nz::Keyboard::VKey::B) + { + showColliders = !showColliders; + if (showColliders) + { + auto view = registry.view(); + for (auto [entity, gfxComponent] : view.each()) + gfxComponent.AttachRenderable(colliderModel); + } + else + { + auto view = registry.view(); + for (auto [entity, gfxComponent] : view.each()) + gfxComponent.DetachRenderable(colliderModel); + } + rebuildCommandBuffer = true; + } + + break; + + case Nz::WindowEventType::MouseMoved: + { + float sensitivity = 0.3f; + + camAngles.yaw = camAngles.yaw - event.mouseMove.deltaX * sensitivity; + camAngles.pitch = camAngles.pitch - event.mouseMove.deltaY * sensitivity; + + camAngles.Normalize(); + + camQuat = camAngles; + + headingNode.SetRotation(camQuat); + break; + } + + case Nz::WindowEventType::Resized: + { + Nz::Vector2ui windowSize = window.GetSize(); + viewerInstance.UpdateProjectionMatrix(Nz::Matrix4f::Perspective(Nz::DegreeAnglef(70.f), float(windowSize.x) / windowSize.y, 0.1f, 1000.f)); + viewerInstance.UpdateTargetSize(Nz::Vector2f(windowSize)); + break; + } + + default: + break; + } + } + + if (updateClock.GetMilliseconds() > 1000 / 60) + { + float updateTime = updateClock.Restart() / 1'000'000.f; + + float cameraSpeed = 20.f * updateTime; + + physSytem.Update(registry, 1000.f / 60.f); + + Nz::RigidBody3DComponent& playerShipBody = registry.get(playerEntity); + Nz::Quaternionf currentRotation = playerShipBody.GetRotation(); + + Nz::Vector3f desiredHeading = headingNode.GetForward(); + Nz::Vector3f currentHeading = currentRotation * Nz::Vector3f::Forward(); + Nz::Vector3f headingError = currentHeading.CrossProduct(desiredHeading); + + Nz::Vector3f desiredUp = headingNode.GetUp(); + Nz::Vector3f currentUp = currentRotation * Nz::Vector3f::Up(); + Nz::Vector3f upError = currentUp.CrossProduct(desiredUp); + + playerShipBody.AddTorque(headingController.Update(headingError, elapsedTime) * 10.f); + playerShipBody.AddTorque(upController.Update(upError, elapsedTime) * 10.f); + + float mass = playerShipBody.GetMass(); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z)) + playerShipBody.AddForce(Nz::Vector3f::Forward() * 2.5f * mass, Nz::CoordSys::Local); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S)) + playerShipBody.AddForce(Nz::Vector3f::Backward() * 2.5f * mass, Nz::CoordSys::Local); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q)) + playerShipBody.AddForce(Nz::Vector3f::Left() * 2.5f * mass, Nz::CoordSys::Local); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D)) + playerShipBody.AddForce(Nz::Vector3f::Right() * 2.5f * mass, Nz::CoordSys::Local); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LShift) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift)) + playerShipBody.AddForce(Nz::Vector3f::Up() * 3.f * mass, Nz::CoordSys::Local); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::LControl) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RControl)) + playerShipBody.AddForce(Nz::Vector3f::Down() * 3.f * mass, Nz::CoordSys::Local); + } + + Nz::RenderFrame frame = windowImpl->Acquire(); + if (!frame) + continue; + + Nz::UploadPool& uploadPool = frame.GetUploadPool(); + + viewerInstance.UpdateViewMatrix(Nz::Matrix4f::ViewMatrix(cameraNode.GetPosition(Nz::CoordSys::Global), cameraNode.GetRotation(Nz::CoordSys::Global))); + + frame.Execute([&](Nz::CommandBufferBuilder& builder) + { + builder.BeginDebugRegion("UBO Update", Nz::Color::Yellow); + { + builder.PreTransferBarrier(); + + viewerInstance.UpdateBuffers(uploadPool, builder); + /* + modelInstance.UpdateBuffers(uploadPool, builder); + modelInstance2.UpdateBuffers(uploadPool, builder); + */ + + auto view = registry.view(); + for (auto [entity, gfxComponent, nodeComponent] : view.each()) + { + Nz::WorldInstance& worldInstance = gfxComponent.GetWorldInstance(); + worldInstance.UpdateWorldMatrix(nodeComponent.GetTransformMatrix()); + + worldInstance.UpdateBuffers(uploadPool, builder); + } + + if (material->Update(frame, builder)) + rebuildCommandBuffer = true; + + if (colliderMat->Update(frame, builder)) + rebuildCommandBuffer = true; + + builder.PostTransferBarrier(); + } + builder.EndDebugRegion(); + }, Nz::QueueType::Transfer); + + if (rebuildCommandBuffer || frame.IsFramebufferInvalidated()) + { + frame.PushForRelease(std::move(drawCommandBuffer)); + RebuildCommandBuffer(); + } + + frame.SubmitCommandBuffer(drawCommandBuffer.get(), Nz::QueueType::Graphics); + + frame.Present(); + + window.Display(); + + rebuildCommandBuffer = false; + + fps++; + + if (secondClock.GetMilliseconds() >= 1000) + { + window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS"); + + fps = 0; + + secondClock.Restart(); + } + } + + registry.clear(); + + return EXIT_SUCCESS; +} diff --git a/examples/PhysicsDemo/xmake.lua b/examples/PhysicsDemo/xmake.lua new file mode 100644 index 000000000..65a6f99f7 --- /dev/null +++ b/examples/PhysicsDemo/xmake.lua @@ -0,0 +1,6 @@ +target("PhysicsDemo") + set_group("Examples") + set_kind("binary") + add_deps("NazaraGraphics", "NazaraPhysics3D") + add_packages("entt") + add_files("main.cpp") diff --git a/include/Nazara/Core/ECS.hpp b/include/Nazara/Core/ECS.hpp new file mode 100644 index 000000000..3ecf2aec9 --- /dev/null +++ b/include/Nazara/Core/ECS.hpp @@ -0,0 +1,46 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_ECS_HPP +#define NAZARA_ECS_HPP + +#include +#include +#include + +namespace Nz +{ + class GraphicsComponent; + class NodeComponent; + class RigidBody3DComponent; + + class ECS : public ModuleBase + { + friend ModuleBase; + friend class Audio; + friend class Graphics; + friend class Physics2D; + friend class Physics3D; + friend class Utility; + + public: + using Dependencies = TypeList; + + struct Config {}; + + inline ECS(Config /*config*/); + ~ECS() = default; + + private: + static inline void RegisterComponents(); + + NAZARA_CORE_API static ECS* s_instance; + }; +} + +#include + +#endif diff --git a/include/Nazara/Core/ECS.inl b/include/Nazara/Core/ECS.inl new file mode 100644 index 000000000..ed9d42ebc --- /dev/null +++ b/include/Nazara/Core/ECS.inl @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + /*! + * \ingroup core + * \class Nz::ECS + * \brief Core class that represents the ECS module + */ + inline ECS::ECS(Config /*config*/) : + ModuleBase("ECS", this) + { + RegisterComponents(); + } + + inline void ECS::RegisterComponents() + { + if (entt::type_seq() != 0) + throw std::runtime_error("NodeComponent has wrong index, please initialize Nazara ECS before instancing your own components"); + + if (entt::type_seq() != 1) + throw std::runtime_error("GraphicsComponent has wrong index, please initialize Nazara ECS before instancing your own components"); + + if (entt::type_seq() != 2) + throw std::runtime_error("GraphicsComponent has wrong index, please initialize Nazara ECS before instancing your own components"); + } +} + +#include diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 4edae9e1c..70de1f7bd 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Graphics/Components.hpp b/include/Nazara/Graphics/Components.hpp new file mode 100644 index 000000000..b92d44c24 --- /dev/null +++ b/include/Nazara/Graphics/Components.hpp @@ -0,0 +1,34 @@ +// This file was automatically generated + +/* + Nazara Engine - Graphics module + + Copyright (C) 2020 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_GRAPHICS_COMPONENTS_HPP +#define NAZARA_GLOBAL_GRAPHICS_COMPONENTS_HPP + +#include + +#endif // NAZARA_GLOBAL_GRAPHICS_COMPONENTS_HPP diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.hpp b/include/Nazara/Graphics/Components/GraphicsComponent.hpp index e69de29bb..835528a87 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.hpp +++ b/include/Nazara/Graphics/Components/GraphicsComponent.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICSCOMPONENT_HPP +#define NAZARA_GRAPHICSCOMPONENT_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_GRAPHICS_API GraphicsComponent + { + public: + GraphicsComponent() = default; + GraphicsComponent(const GraphicsComponent&) = default; + GraphicsComponent(GraphicsComponent&&) = default; + ~GraphicsComponent() = default; + + inline void AttachRenderable(std::shared_ptr renderable); + inline void DetachRenderable(const std::shared_ptr& renderable); + + inline const std::vector>& GetRenderables() const; + inline WorldInstance& GetWorldInstance(); + inline const WorldInstance& GetWorldInstance() const; + + GraphicsComponent& operator=(const GraphicsComponent&) = default; + GraphicsComponent& operator=(GraphicsComponent&&) = default; + + private: + std::vector> m_renderables; + WorldInstance m_worldInstance; + }; +} + +#include + +#endif diff --git a/include/Nazara/Graphics/Components/GraphicsComponent.inl b/include/Nazara/Graphics/Components/GraphicsComponent.inl index e69de29bb..f85cf7b3a 100644 --- a/include/Nazara/Graphics/Components/GraphicsComponent.inl +++ b/include/Nazara/Graphics/Components/GraphicsComponent.inl @@ -0,0 +1,37 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include +#include "GraphicsComponent.hpp" + +namespace Nz +{ + inline void GraphicsComponent::AttachRenderable(std::shared_ptr renderable) + { + m_renderables.push_back(std::move(renderable)); + } + + inline void GraphicsComponent::DetachRenderable(const std::shared_ptr& renderable) + { + auto it = std::find(m_renderables.begin(), m_renderables.end(), renderable); + if (it != m_renderables.end()) + m_renderables.erase(it); + } + + inline const std::vector>& GraphicsComponent::GetRenderables() const + { + return m_renderables; + } + + inline WorldInstance& GraphicsComponent::GetWorldInstance() + { + return m_worldInstance; + } + + inline const WorldInstance& GraphicsComponent::GetWorldInstance() const + { + return m_worldInstance; + } +} diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index d4973bc18..aa1966c16 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -23,7 +23,7 @@ namespace Nz InstancedRenderable(InstancedRenderable&&) noexcept = default; ~InstancedRenderable(); - virtual void Draw(CommandBufferBuilder& commandBuffer, WorldInstance& instance) const = 0; + virtual void Draw(CommandBufferBuilder& commandBuffer, const WorldInstance& instance) const = 0; InstancedRenderable& operator=(const InstancedRenderable&) = delete; InstancedRenderable& operator=(InstancedRenderable&&) noexcept = default; diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 2a737d1f2..dae8c1d17 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -68,6 +68,7 @@ namespace Nz inline const std::shared_ptr& GetPipeline() const; inline const MaterialPipelineInfo& GetPipelineInfo() const; inline float GetPointSize() const; + inline PrimitiveMode GetPrimitiveMode() const; inline const std::shared_ptr& GetSettings() const; inline const std::shared_ptr& GetShader(ShaderStageType shaderStage) const; inline ShaderBinding& GetShaderBinding(); @@ -100,6 +101,7 @@ namespace Nz inline void SetFaceFilling(FaceFilling filling); inline void SetLineWidth(float lineWidth); inline void SetPointSize(float pointSize); + inline void SetPrimitiveMode(PrimitiveMode mode); inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo); inline void SetUniformBuffer(std::size_t bufferIndex, std::shared_ptr uniformBuffer); diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 697930b04..c9687814d 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -425,6 +425,11 @@ namespace Nz return m_pipelineInfo.pointSize; } + inline PrimitiveMode Material::GetPrimitiveMode() const + { + return m_pipelineInfo.primitiveMode; + } + inline const std::shared_ptr& Material::GetSettings() const { return m_settings; @@ -693,6 +698,14 @@ namespace Nz InvalidatePipeline(); } + + inline void Material::SetPrimitiveMode(PrimitiveMode mode) + { + m_pipelineInfo.primitiveMode = mode; + + InvalidatePipeline(); + } + inline void Material::SetTexture(std::size_t textureIndex, std::shared_ptr texture) { NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); diff --git a/include/Nazara/Graphics/Model.hpp b/include/Nazara/Graphics/Model.hpp index 8c6297990..96e4fa0ca 100644 --- a/include/Nazara/Graphics/Model.hpp +++ b/include/Nazara/Graphics/Model.hpp @@ -28,7 +28,7 @@ namespace Nz Model(Model&&) noexcept = default; ~Model() = default; - void Draw(CommandBufferBuilder& commandBuffer, WorldInstance& instance) const override; + void Draw(CommandBufferBuilder& commandBuffer, const WorldInstance& instance) const override; const std::shared_ptr& GetIndexBuffer(std::size_t subMeshIndex) const; std::size_t GetIndexCount(std::size_t subMeshIndex) const; diff --git a/include/Nazara/Graphics/WorldInstance.hpp b/include/Nazara/Graphics/WorldInstance.hpp index ea2c0bd93..8699eacd3 100644 --- a/include/Nazara/Graphics/WorldInstance.hpp +++ b/include/Nazara/Graphics/WorldInstance.hpp @@ -31,6 +31,7 @@ namespace Nz inline std::shared_ptr& GetInstanceBuffer(); inline const std::shared_ptr& GetInstanceBuffer() const; inline ShaderBinding& GetShaderBinding(); + inline const ShaderBinding& GetShaderBinding() const; void UpdateBuffers(UploadPool& uploadPool, CommandBufferBuilder& builder); inline void UpdateWorldMatrix(const Matrix4f& worldMatrix); diff --git a/include/Nazara/Graphics/WorldInstance.inl b/include/Nazara/Graphics/WorldInstance.inl index 03c712bae..4bca9a2dd 100644 --- a/include/Nazara/Graphics/WorldInstance.inl +++ b/include/Nazara/Graphics/WorldInstance.inl @@ -23,6 +23,11 @@ namespace Nz return *m_shaderBinding; } + inline const ShaderBinding& WorldInstance::GetShaderBinding() const + { + return *m_shaderBinding; + } + inline void WorldInstance::UpdateWorldMatrix(const Matrix4f& worldMatrix) { m_worldMatrix = worldMatrix; diff --git a/include/Nazara/Math.hpp b/include/Nazara/Math.hpp index e3d52540f..b4b965e07 100644 --- a/include/Nazara/Math.hpp +++ b/include/Nazara/Math.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Math/PidController.hpp b/include/Nazara/Math/PidController.hpp new file mode 100644 index 000000000..96ac38958 --- /dev/null +++ b/include/Nazara/Math/PidController.hpp @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_PIDCONTROLLER_HPP +#define NAZARA_PIDCONTROLLER_HPP + +namespace Nz +{ + template + class PidController + { + public: + PidController(float p, float i, float d); + + T Update(const T& currentError, float elapsedTime); + + private: + T m_lastError; + T m_integral; + float m_dFactor; + float m_iFactor; + float m_pFactor; + }; +} + +#include + +#endif diff --git a/include/Nazara/Math/PidController.inl b/include/Nazara/Math/PidController.inl new file mode 100644 index 000000000..f6478a4dd --- /dev/null +++ b/include/Nazara/Math/PidController.inl @@ -0,0 +1,28 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +namespace Nz +{ + template + PidController::PidController(float p, float i, float d) : + m_lastError(0), + m_integral(0), + m_dFactor(d), + m_iFactor(i), + m_pFactor(p) + { + } + + template + T PidController::Update(const T& currentError, float elapsedTime) + { + m_integral += currentError * elapsedTime; + T deriv = (currentError - m_lastError) / elapsedTime; + m_lastError = currentError; + + return currentError * m_pFactor + m_integral * m_iFactor + deriv * m_dFactor; + } +} diff --git a/include/Nazara/OpenGLRenderer/Utils.hpp b/include/Nazara/OpenGLRenderer/Utils.hpp index a51cafc93..0a0f635f2 100644 --- a/include/Nazara/OpenGLRenderer/Utils.hpp +++ b/include/Nazara/OpenGLRenderer/Utils.hpp @@ -31,6 +31,7 @@ namespace Nz inline GLenum ToOpenGL(BlendEquation blendEquation); inline GLenum ToOpenGL(BlendFunc blendFunc); + inline GLenum ToOpenGL(FaceFilling filling); inline GLenum ToOpenGL(FaceSide side); inline GLenum ToOpenGL(FrontFace face); inline GLenum ToOpenGL(PrimitiveMode primitiveMode); diff --git a/include/Nazara/OpenGLRenderer/Utils.inl b/include/Nazara/OpenGLRenderer/Utils.inl index a9585d88a..7b85e519d 100644 --- a/include/Nazara/OpenGLRenderer/Utils.inl +++ b/include/Nazara/OpenGLRenderer/Utils.inl @@ -74,6 +74,19 @@ namespace Nz NazaraError("Unhandled BlendFunc 0x" + NumberToString(UnderlyingCast(blendFunc), 16)); return {}; } + + inline GLenum ToOpenGL(FaceFilling side) + { + switch (side) + { + case FaceFilling::Fill: return GL_FILL; + case FaceFilling::Line: return GL_LINE; + case FaceFilling::Point: return GL_POINT; + } + + NazaraError("Unhandled FaceFilling 0x" + NumberToString(UnderlyingCast(side), 16)); + return {}; + } inline GLenum ToOpenGL(FaceSide side) { diff --git a/include/Nazara/OpenGLRenderer/Wrapper.hpp b/include/Nazara/OpenGLRenderer/Wrapper.hpp index dd2753244..77133a5e4 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper.hpp @@ -1,5 +1,29 @@ // This file was automatically generated +/* + Nazara Engine - OpenGL + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #ifndef NAZARA_GLOBAL_OPENGLRENDERER_WRAPPER_HPP diff --git a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp index 851d482e4..34eab95bd 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/CoreFunctions.hpp @@ -12,8 +12,12 @@ #include // Define some OpenGL (not ES) extensions +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 #define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551 #define GL_SPIR_V_BINARY_ARB 0x9552 +typedef void (GL_APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const GLchar* pEntryPoint, GLuint numSpecializationConstants, const GLuint* pConstantIndex, const GLuint* pConstantValue); // OpenGL core @@ -163,6 +167,8 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G \ extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ \ + extCb(glPolygonMode, PFNGLPOLYGONMODEPROC) \ + \ extCb(glMemoryBarrier, PFNGLMEMORYBARRIERPROC) \ extCb(glMemoryBarrierByRegion, PFNGLMEMORYBARRIERBYREGIONPROC) \ \ diff --git a/include/Nazara/Physics3D/Collider3D.hpp b/include/Nazara/Physics3D/Collider3D.hpp index 519f9871b..0e09bad85 100644 --- a/include/Nazara/Physics3D/Collider3D.hpp +++ b/include/Nazara/Physics3D/Collider3D.hpp @@ -30,6 +30,7 @@ namespace Nz class PrimitiveList; class PhysWorld3D; + class StaticMesh; class NAZARA_PHYSICS3D_API Collider3D { @@ -48,6 +49,8 @@ namespace Nz virtual void ForEachPolygon(const std::function& callback) const; + virtual std::shared_ptr GenerateMesh() const; + NewtonCollision* GetHandle(PhysWorld3D* world) const; virtual ColliderType3D GetType() const = 0; diff --git a/include/Nazara/Physics3D/Components.hpp b/include/Nazara/Physics3D/Components.hpp new file mode 100644 index 000000000..73936ed86 --- /dev/null +++ b/include/Nazara/Physics3D/Components.hpp @@ -0,0 +1,34 @@ +// This file was automatically generated + +/* + Nazara Engine - Physics 3D module + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_PHYSICS3D_COMPONENTS_HPP +#define NAZARA_GLOBAL_PHYSICS3D_COMPONENTS_HPP + +#include + +#endif // NAZARA_GLOBAL_PHYSICS3D_COMPONENTS_HPP diff --git a/include/Nazara/Physics3D/Components/RigidBody3DComponent.hpp b/include/Nazara/Physics3D/Components/RigidBody3DComponent.hpp new file mode 100644 index 000000000..8b6362fe5 --- /dev/null +++ b/include/Nazara/Physics3D/Components/RigidBody3DComponent.hpp @@ -0,0 +1,30 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RIGIDBODYCOMPONENT_HPP +#define NAZARA_RIGIDBODYCOMPONENT_HPP + +#include +#include + +namespace Nz +{ + class NAZARA_PHYSICS3D_API RigidBody3DComponent : public RigidBody3D + { + public: + using RigidBody3D::RigidBody3D; + RigidBody3DComponent(const RigidBody3DComponent&) = default; + RigidBody3DComponent(RigidBody3DComponent&&) noexcept = default; + ~RigidBody3DComponent() = default; + + RigidBody3DComponent& operator=(const RigidBody3DComponent&) = default; + RigidBody3DComponent& operator=(RigidBody3DComponent&&) noexcept = default; + }; +} + +#include + +#endif diff --git a/include/Nazara/Physics3D/Components/RigidBody3DComponent.inl b/include/Nazara/Physics3D/Components/RigidBody3DComponent.inl new file mode 100644 index 000000000..97eb269a7 --- /dev/null +++ b/include/Nazara/Physics3D/Components/RigidBody3DComponent.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 3D module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Physics3D/PhysWorld3D.hpp b/include/Nazara/Physics3D/PhysWorld3D.hpp index 76b46803f..3d84a3e9f 100644 --- a/include/Nazara/Physics3D/PhysWorld3D.hpp +++ b/include/Nazara/Physics3D/PhysWorld3D.hpp @@ -33,7 +33,7 @@ namespace Nz PhysWorld3D(); PhysWorld3D(const PhysWorld3D&) = delete; - PhysWorld3D(PhysWorld3D&&) noexcept = default; + PhysWorld3D(PhysWorld3D&& ph) noexcept; ~PhysWorld3D(); int CreateMaterial(std::string name = {}); @@ -62,7 +62,7 @@ namespace Nz void Step(float timestep); PhysWorld3D& operator=(const PhysWorld3D&) = delete; - PhysWorld3D& operator=(PhysWorld3D&&) noexcept = default; + PhysWorld3D& operator=(PhysWorld3D&&) noexcept; private: struct Callback diff --git a/include/Nazara/Physics3D/RigidBody3D.hpp b/include/Nazara/Physics3D/RigidBody3D.hpp index f185fa3c4..2285b32be 100644 --- a/include/Nazara/Physics3D/RigidBody3D.hpp +++ b/include/Nazara/Physics3D/RigidBody3D.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,7 @@ namespace Nz RigidBody3D(PhysWorld3D* world, const Matrix4f& mat = Matrix4f::Identity()); RigidBody3D(PhysWorld3D* world, std::shared_ptr geom, const Matrix4f& mat = Matrix4f::Identity()); RigidBody3D(const RigidBody3D& object); - RigidBody3D(RigidBody3D&& object); + RigidBody3D(RigidBody3D&& object) noexcept; ~RigidBody3D(); void AddForce(const Vector3f& force, CoordSys coordSys = CoordSys::Global); @@ -74,7 +75,7 @@ namespace Nz void SetUserdata(void* ud); RigidBody3D& operator=(const RigidBody3D& object); - RigidBody3D& operator=(RigidBody3D&& object); + RigidBody3D& operator=(RigidBody3D&& object) noexcept; private: void UpdateBody(); @@ -83,9 +84,9 @@ namespace Nz std::shared_ptr m_geom; Matrix4f m_matrix; + MovablePtr m_body; Vector3f m_forceAccumulator; Vector3f m_torqueAccumulator; - NewtonBody* m_body; PhysWorld3D* m_world; void* m_userdata; float m_gravityFactor; diff --git a/include/Nazara/Physics3D/Systems.hpp b/include/Nazara/Physics3D/Systems.hpp new file mode 100644 index 000000000..cf1e7745a --- /dev/null +++ b/include/Nazara/Physics3D/Systems.hpp @@ -0,0 +1,34 @@ +// This file was automatically generated + +/* + Nazara Engine - Physics 3D module + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_PHYSICS3D_SYSTEMS_HPP +#define NAZARA_GLOBAL_PHYSICS3D_SYSTEMS_HPP + +#include + +#endif // NAZARA_GLOBAL_PHYSICS3D_SYSTEMS_HPP diff --git a/include/Nazara/Physics3D/Systems/Physics3DSystem.hpp b/include/Nazara/Physics3D/Systems/Physics3DSystem.hpp new file mode 100644 index 000000000..a1231b04e --- /dev/null +++ b/include/Nazara/Physics3D/Systems/Physics3DSystem.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 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_PHYSICS3DSYSTEM_HPP +#define NAZARA_PHYSICS3DSYSTEM_HPP + +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_PHYSICS3D_API Physics3DSystem + { + public: + Physics3DSystem(entt::registry& registry); + Physics3DSystem(const Physics3DSystem&) = delete; + Physics3DSystem(Physics3DSystem&&) = delete; + ~Physics3DSystem(); + + template RigidBody3DComponent CreateRigidBody(Args&&... args); + + inline PhysWorld3D& GetPhysWorld(); + inline const PhysWorld3D& GetPhysWorld() const; + + void Update(entt::registry& registry, float elapsedTime); + + Physics3DSystem& operator=(const Physics3DSystem&) = delete; + Physics3DSystem& operator=(Physics3DSystem&&) = delete; + + private: + static void OnConstruct(entt::registry& registry, entt::entity entity); + + entt::connection m_constructConnection; + PhysWorld3D m_physWorld; + }; +} + +#include + +#endif diff --git a/include/Nazara/Physics3D/Systems/Physics3DSystem.inl b/include/Nazara/Physics3D/Systems/Physics3DSystem.inl new file mode 100644 index 000000000..e86acefd0 --- /dev/null +++ b/include/Nazara/Physics3D/Systems/Physics3DSystem.inl @@ -0,0 +1,27 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include + +namespace Nz +{ + template + RigidBody3DComponent Physics3DSystem::CreateRigidBody(Args&&... args) + { + return RigidBody3DComponent(&m_physWorld, std::forward(args)...); + } + + inline PhysWorld3D& Physics3DSystem::GetPhysWorld() + { + return m_physWorld; + } + + inline const PhysWorld3D& Physics3DSystem::GetPhysWorld() const + { + return m_physWorld; + } +} + +#include diff --git a/include/Nazara/Renderer/RenderDeviceInfo.hpp b/include/Nazara/Renderer/RenderDeviceInfo.hpp index b151ce9a5..5beb28c66 100644 --- a/include/Nazara/Renderer/RenderDeviceInfo.hpp +++ b/include/Nazara/Renderer/RenderDeviceInfo.hpp @@ -16,6 +16,7 @@ namespace Nz struct RenderDeviceFeatures { bool anisotropicFiltering = false; + bool nonSolidFaceFilling = false; }; struct RenderDeviceLimits diff --git a/include/Nazara/Utility/Components.hpp b/include/Nazara/Utility/Components.hpp new file mode 100644 index 000000000..a7ef8eaa4 --- /dev/null +++ b/include/Nazara/Utility/Components.hpp @@ -0,0 +1,34 @@ +// This file was automatically generated + +/* + Nazara Engine - Utility module + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_UTILITY_COMPONENTS_HPP +#define NAZARA_GLOBAL_UTILITY_COMPONENTS_HPP + +#include + +#endif // NAZARA_GLOBAL_UTILITY_COMPONENTS_HPP diff --git a/include/Nazara/Utility/Components/NodeComponent.hpp b/include/Nazara/Utility/Components/NodeComponent.hpp index e69de29bb..dbc7f99ae 100644 --- a/include/Nazara/Utility/Components/NodeComponent.hpp +++ b/include/Nazara/Utility/Components/NodeComponent.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2021 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_NODECOMPONENT_HPP +#define NAZARA_NODECOMPONENT_HPP + +#include +#include +#include + +namespace Nz +{ + class NAZARA_UTILITY_API NodeComponent : public Node + { + public: + NodeComponent() = default; + NodeComponent(const NodeComponent&) = default; + NodeComponent(NodeComponent&&) noexcept = default; + ~NodeComponent() = default; + + void SetParent(entt::registry& registry, entt::entity entity, bool keepDerived = false); + using Node::SetParent; + + NodeComponent& operator=(const NodeComponent&) = default; + NodeComponent& operator=(NodeComponent&&) noexcept = default; + }; +} + +#include + +#endif diff --git a/include/Nazara/Utility/Components/NodeComponent.inl b/include/Nazara/Utility/Components/NodeComponent.inl index e69de29bb..99b319512 100644 --- a/include/Nazara/Utility/Components/NodeComponent.inl +++ b/include/Nazara/Utility/Components/NodeComponent.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 587fd38ee..be0d5ec27 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -57,6 +57,7 @@ namespace Nz class Mesh; struct Primitive; class PrimitiveList; + class StaticMesh; class SubMesh; using MeshVertex = VertexStruct_XYZ_Normal_UV_Tangent; @@ -132,6 +133,8 @@ namespace Nz Mesh& operator=(const Mesh&) = delete; Mesh& operator=(Mesh&&) = delete; + static inline std::shared_ptr Build(std::shared_ptr staticMesh); + static std::shared_ptr LoadFromFile(const std::filesystem::path& filePath, const MeshParams& params = MeshParams()); static std::shared_ptr LoadFromMemory(const void* data, std::size_t size, const MeshParams& params = MeshParams()); static std::shared_ptr LoadFromStream(Stream& stream, const MeshParams& params = MeshParams()); diff --git a/include/Nazara/Utility/Mesh.inl b/include/Nazara/Utility/Mesh.inl index 0681e0850..daba241c6 100644 --- a/include/Nazara/Utility/Mesh.inl +++ b/include/Nazara/Utility/Mesh.inl @@ -4,16 +4,26 @@ #include #include +#include #include namespace Nz { - Mesh::Mesh() : + inline Mesh::Mesh() : m_materialData(1), m_aabbUpdated(false), m_isValid(false) { } + + inline std::shared_ptr Mesh::Build(std::shared_ptr staticMesh) + { + std::shared_ptr mesh = std::make_shared(); + mesh->CreateStatic(); + mesh->AddSubMesh(std::move(staticMesh)); + + return mesh; + } } #include diff --git a/include/Nazara/Utility/Node.hpp b/include/Nazara/Utility/Node.hpp index 0af3b619f..8bf5bb26d 100644 --- a/include/Nazara/Utility/Node.hpp +++ b/include/Nazara/Utility/Node.hpp @@ -23,6 +23,7 @@ namespace Nz public: Node(); Node(const Node& node); + Node(Node&& node) noexcept; virtual ~Node(); void EnsureDerivedUpdate() const; @@ -92,6 +93,7 @@ namespace Nz Vector3f ToLocalScale(const Vector3f& globalScale) const; Node& operator=(const Node& node); + Node& operator=(Node&& node) noexcept; // Signals: NazaraSignal(OnNodeInvalidation, const Node* /*node*/); diff --git a/include/Nazara/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer.hpp index f5ce90f75..bc1bf2c0e 100644 --- a/include/Nazara/VulkanRenderer.hpp +++ b/include/Nazara/VulkanRenderer.hpp @@ -54,6 +54,5 @@ #include #include #include -#include #endif // NAZARA_GLOBAL_VULKANRENDERER_HPP diff --git a/include/Nazara/VulkanRenderer/Wrapper.hpp b/include/Nazara/VulkanRenderer/Wrapper.hpp index df6896383..94c80b9c5 100644 --- a/include/Nazara/VulkanRenderer/Wrapper.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper.hpp @@ -1,5 +1,29 @@ // This file was automatically generated +/* + Nazara Engine - Vulkan + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + #pragma once #ifndef NAZARA_GLOBAL_VULKANRENDERER_WRAPPER_HPP diff --git a/src/Nazara/Core/ECS.cpp b/src/Nazara/Core/ECS.cpp new file mode 100644 index 000000000..d1d40a6ed --- /dev/null +++ b/src/Nazara/Core/ECS.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2020 Jérôme Leclercq +// This file is part of the "Nazara Engine - Core module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + NAZARA_CORE_API ECS* ECS::s_instance = nullptr; +} diff --git a/src/Nazara/Graphics/Components/GraphicsComponent.cpp b/src/Nazara/Graphics/Components/GraphicsComponent.cpp index e69de29bb..c246b33c8 100644 --- a/src/Nazara/Graphics/Components/GraphicsComponent.cpp +++ b/src/Nazara/Graphics/Components/GraphicsComponent.cpp @@ -0,0 +1,10 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include + +namespace Nz +{ +} diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 4cad0114c..badff0a2c 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include @@ -18,6 +19,8 @@ namespace Nz Graphics::Graphics(Config config) : ModuleBase("Graphics", this) { + ECS::RegisterComponents(); + Renderer* renderer = Renderer::Instance(); const std::vector& renderDeviceInfo = renderer->QueryRenderDevices(); @@ -42,6 +45,7 @@ namespace Nz RenderDeviceFeatures enabledFeatures; enabledFeatures.anisotropicFiltering = renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering; + enabledFeatures.nonSolidFaceFilling = renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling; m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures); if (!m_renderDevice) diff --git a/src/Nazara/Graphics/Model.cpp b/src/Nazara/Graphics/Model.cpp index 53924b6dd..de91798d1 100644 --- a/src/Nazara/Graphics/Model.cpp +++ b/src/Nazara/Graphics/Model.cpp @@ -29,7 +29,7 @@ namespace Nz } } - void Model::Draw(CommandBufferBuilder& commandBuffer, WorldInstance& instance) const + void Model::Draw(CommandBufferBuilder& commandBuffer, const WorldInstance& instance) const { commandBuffer.BindShaderBinding(Graphics::WorldBindingSet, instance.GetShaderBinding()); diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 2a509e63c..e65d5c9cd 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -56,6 +56,9 @@ namespace Nz if ((params.type == GL::ContextType::OpenGL && glVersion >= 460) || m_referenceContext->IsExtensionSupported(GL::Extension::TextureFilterAnisotropic)) m_deviceInfo.features.anisotropicFiltering = true; + if (m_referenceContext->glPolygonMode) //< not supported in core OpenGL ES, but supported in OpenGL or with GL_NV_polygon_mode extension + m_deviceInfo.features.nonSolidFaceFilling = true; + // Limits GLint minUboOffsetAlignment; m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index e719249e1..9e07c28df 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -500,13 +500,11 @@ namespace Nz::GL m_state.renderStates.frontFace = targetFrontFace; } - /* - TODO: Use glPolyonMode if available (OpenGL) - if (m_state.renderStates.faceFilling != renderStates.faceFilling) + if (glPolygonMode && m_state.renderStates.faceFilling != renderStates.faceFilling) { - glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]); + glPolygonMode(GL_FRONT_AND_BACK, ToOpenGL(renderStates.faceFilling)); m_state.renderStates.faceFilling = renderStates.faceFilling; - }*/ + } if (renderStates.stencilTest) { @@ -663,6 +661,12 @@ namespace Nz::GL return true; } + else if (function == "glPolygonMode") + { + constexpr std::size_t functionIndex = UnderlyingCast(FunctionIndex::glPolygonMode); + + return loader.Load(glPolygonMode, "glPolygonModeNV", false, false); + } return false; } diff --git a/src/Nazara/Physics3D/Collider3D.cpp b/src/Nazara/Physics3D/Collider3D.cpp index f48fa75be..0b1367eb8 100644 --- a/src/Nazara/Physics3D/Collider3D.cpp +++ b/src/Nazara/Physics3D/Collider3D.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include #include @@ -139,6 +142,44 @@ namespace Nz NewtonCollisionForEachPolygonDo(m_handles.begin()->second, Nz::Matrix4f::Identity(), newtCallback, const_cast(static_cast(&callback))); //< This isn't that bad; pointer will not be used for writing } + std::shared_ptr Collider3D::GenerateMesh() const + { + std::vector colliderVertices; + std::vector colliderIndices; + + // Generate a line list + ForEachPolygon([&](const Nz::Vector3f* vertices, std::size_t vertexCount) + { + Nz::UInt16 firstIndex = colliderVertices.size(); + for (std::size_t i = 0; i < vertexCount; ++i) + colliderVertices.push_back(vertices[i]); + + for (std::size_t i = 1; i < vertexCount; ++i) + { + colliderIndices.push_back(firstIndex + i - 1); + colliderIndices.push_back(firstIndex + i); + } + + if (vertexCount > 2) + { + colliderIndices.push_back(firstIndex + vertexCount - 1); + colliderIndices.push_back(firstIndex); + } + }); + + std::shared_ptr colliderVB = std::make_shared(Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ), colliderVertices.size(), Nz::DataStorage::Software, 0); + colliderVB->Fill(colliderVertices.data(), 0, colliderVertices.size()); + + std::shared_ptr colliderIB = std::make_shared(false, colliderIndices.size(), Nz::DataStorage::Software, 0); + colliderIB->Fill(colliderIndices.data(), 0, colliderIndices.size()); + + std::shared_ptr colliderSubMesh = std::make_shared(std::move(colliderVB), std::move(colliderIB)); + colliderSubMesh->GenerateAABB(); + colliderSubMesh->SetPrimitiveMode(Nz::PrimitiveMode::LineList); + + return colliderSubMesh; + } + NewtonCollision* Collider3D::GetHandle(PhysWorld3D* world) const { auto it = m_handles.find(world); diff --git a/src/Nazara/Physics3D/Components/RigidBody3DComponent.cpp b/src/Nazara/Physics3D/Components/RigidBody3DComponent.cpp new file mode 100644 index 000000000..3031d479a --- /dev/null +++ b/src/Nazara/Physics3D/Components/RigidBody3DComponent.cpp @@ -0,0 +1,10 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Physics 3D module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include + +namespace Nz +{ +} diff --git a/src/Nazara/Physics3D/PhysWorld3D.cpp b/src/Nazara/Physics3D/PhysWorld3D.cpp index 3cabfb2e6..83adb7157 100644 --- a/src/Nazara/Physics3D/PhysWorld3D.cpp +++ b/src/Nazara/Physics3D/PhysWorld3D.cpp @@ -22,9 +22,22 @@ namespace Nz m_materialIds.emplace("default", NewtonMaterialGetDefaultGroupID(m_world)); } + PhysWorld3D::PhysWorld3D(PhysWorld3D&& physWorld) noexcept : + m_callbacks(std::move(physWorld.m_callbacks)), + m_materialIds(std::move(physWorld.m_materialIds)), + m_maxStepCount(std::move(physWorld.m_maxStepCount)), + m_world(std::move(physWorld.m_world)), + m_gravity(std::move(physWorld.m_gravity)), + m_stepSize(std::move(physWorld.m_stepSize)), + m_timestepAccumulator(std::move(physWorld.m_timestepAccumulator)) + { + NewtonWorldSetUserData(m_world, this); + } + PhysWorld3D::~PhysWorld3D() { - NewtonDestroy(m_world); + if (m_world) + NewtonDestroy(m_world); } int PhysWorld3D::CreateMaterial(std::string name) @@ -159,6 +172,24 @@ namespace Nz } } + PhysWorld3D& PhysWorld3D::operator=(PhysWorld3D&& physWorld) noexcept + { + if (m_world) + NewtonDestroy(m_world); + + m_callbacks = std::move(physWorld.m_callbacks); + m_materialIds = std::move(physWorld.m_materialIds); + m_maxStepCount = std::move(physWorld.m_maxStepCount); + m_world = std::move(physWorld.m_world); + m_gravity = std::move(physWorld.m_gravity); + m_stepSize = std::move(physWorld.m_stepSize); + m_timestepAccumulator = std::move(physWorld.m_timestepAccumulator); + + NewtonWorldSetUserData(m_world, this); + + return *this; + } + int PhysWorld3D::OnAABBOverlap(const NewtonJoint* const contactJoint, float /*timestep*/, int /*threadIndex*/) { RigidBody3D* bodyA = static_cast(NewtonBodyGetUserData(NewtonJointGetBody0(contactJoint))); diff --git a/src/Nazara/Physics3D/Physics3D.cpp b/src/Nazara/Physics3D/Physics3D.cpp index 5795dbeff..89af3bca2 100644 --- a/src/Nazara/Physics3D/Physics3D.cpp +++ b/src/Nazara/Physics3D/Physics3D.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -16,6 +17,7 @@ namespace Nz Physics3D::Physics3D(Config /*config*/) : ModuleBase("Physics3D", this) { + ECS::RegisterComponents(); } unsigned int Physics3D::GetMemoryUsed() diff --git a/src/Nazara/Physics3D/RigidBody3D.cpp b/src/Nazara/Physics3D/RigidBody3D.cpp index 40d6bd833..905729b98 100644 --- a/src/Nazara/Physics3D/RigidBody3D.cpp +++ b/src/Nazara/Physics3D/RigidBody3D.cpp @@ -61,17 +61,17 @@ namespace Nz SetRotation(object.GetRotation()); } - RigidBody3D::RigidBody3D(RigidBody3D&& object) : + RigidBody3D::RigidBody3D(RigidBody3D&& object) noexcept : m_geom(std::move(object.m_geom)), m_matrix(std::move(object.m_matrix)), m_forceAccumulator(std::move(object.m_forceAccumulator)), m_torqueAccumulator(std::move(object.m_torqueAccumulator)), - m_body(object.m_body), + m_body(std::move(object.m_body)), m_world(object.m_world), m_gravityFactor(object.m_gravityFactor), m_mass(object.m_mass) { - object.m_body = nullptr; + NewtonBodySetUserData(m_body, this); } RigidBody3D::~RigidBody3D() @@ -380,6 +380,24 @@ namespace Nz return operator=(std::move(physObj)); } + RigidBody3D& RigidBody3D::operator=(RigidBody3D&& object) noexcept + { + if (m_body) + NewtonDestroyBody(m_body); + + m_body = std::move(object.m_body); + m_forceAccumulator = std::move(object.m_forceAccumulator); + m_geom = std::move(object.m_geom); + m_gravityFactor = object.m_gravityFactor; + m_mass = object.m_mass; + m_matrix = std::move(object.m_matrix); + m_torqueAccumulator = std::move(object.m_torqueAccumulator); + m_world = object.m_world; + + NewtonBodySetUserData(m_body, this); + return *this; + } + void RigidBody3D::UpdateBody() { NewtonBodySetMatrix(m_body, m_matrix); @@ -401,25 +419,6 @@ namespace Nz } } - RigidBody3D& RigidBody3D::operator=(RigidBody3D&& object) - { - if (m_body) - NewtonDestroyBody(m_body); - - m_body = object.m_body; - m_forceAccumulator = std::move(object.m_forceAccumulator); - m_geom = std::move(object.m_geom); - m_gravityFactor = object.m_gravityFactor; - m_mass = object.m_mass; - m_matrix = std::move(object.m_matrix); - m_torqueAccumulator = std::move(object.m_torqueAccumulator); - m_world = object.m_world; - - object.m_body = nullptr; - - return *this; - } - void RigidBody3D::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex) { NazaraUnused(timeStep); diff --git a/src/Nazara/Physics3D/Systems/Physics3DSystem.cpp b/src/Nazara/Physics3D/Systems/Physics3DSystem.cpp new file mode 100644 index 000000000..f92bc1dee --- /dev/null +++ b/src/Nazara/Physics3D/Systems/Physics3DSystem.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include +#include + +namespace Nz +{ + Physics3DSystem::Physics3DSystem(entt::registry& registry) + { + m_constructConnection = registry.on_construct().connect(); + } + + Physics3DSystem::~Physics3DSystem() + { + m_constructConnection.release(); + } + + void Physics3DSystem::Update(entt::registry& registry, float elapsedTime) + { + m_physWorld.Step(elapsedTime); + + // Replicate rigid body position to their node components + auto velView = registry.view(); + for (auto [entity, nodeComponent, rigidBodyComponent] : velView.each()) + { + nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global); + nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global); + } + } + + void Physics3DSystem::OnConstruct(entt::registry& registry, entt::entity entity) + { + // If our entity already has a node component when adding a rigid body, initialize it with + Nz::NodeComponent* node = registry.try_get(entity); + if (node) + { + RigidBody3DComponent& rigidBody = registry.get(entity); + rigidBody.SetPosition(node->GetPosition()); + rigidBody.SetRotation(node->GetRotation()); + } + } +} diff --git a/src/Nazara/Utility/Components/NodeComponent.cpp b/src/Nazara/Utility/Components/NodeComponent.cpp index e69de29bb..9b17be981 100644 --- a/src/Nazara/Utility/Components/NodeComponent.cpp +++ b/src/Nazara/Utility/Components/NodeComponent.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2021 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Prerequisites.hpp + +#include +#include +#include + +namespace Nz +{ + void NodeComponent::SetParent(entt::registry& registry, entt::entity entity, bool keepDerived) + { + NodeComponent* nodeComponent = registry.try_get(entity); + NazaraAssert(nodeComponent, "entity doesn't have a NodeComponent"); + + Node::SetParent(nodeComponent, keepDerived); + } +} diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index 0b70e69f9..3b4e6f8ac 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -41,6 +41,35 @@ namespace Nz SetParent(node.m_parent, false); } + Node::Node(Node&& node) noexcept : + m_childs(std::move(node.m_childs)), + m_initialRotation(node.m_initialRotation), + m_rotation(node.m_rotation), + m_initialPosition(node.m_initialPosition), + m_initialScale(node.m_initialScale), + m_position(node.m_position), + m_scale(node.m_scale), + m_parent(node.m_parent), + m_derivedUpdated(false), + m_inheritPosition(node.m_inheritPosition), + m_inheritRotation(node.m_inheritRotation), + m_inheritScale(node.m_inheritScale), + m_transformMatrixUpdated(false), + OnNodeInvalidation(std::move(node.OnNodeInvalidation)), + OnNodeNewParent(std::move(node.OnNodeNewParent)), + OnNodeRelease(std::move(node.OnNodeRelease)) + { + if (m_parent) + { + m_parent->RemoveChild(&node); + m_parent->AddChild(this); + node.m_parent = nullptr; + } + + for (Node* child : m_childs) + child->m_parent = this; + } + Node::~Node() { OnNodeRelease(this); @@ -643,6 +672,42 @@ namespace Nz return *this; } + Node& Node::operator=(Node&& node) noexcept + { + if (m_parent) + SetParent(nullptr); + + m_inheritPosition = node.m_inheritPosition; + m_inheritRotation = node.m_inheritRotation; + m_inheritScale = node.m_inheritScale; + m_initialPosition = node.m_initialPosition; + m_initialRotation = node.m_initialRotation; + m_initialScale = node.m_initialScale; + m_position = node.m_position; + m_rotation = node.m_rotation; + m_scale = node.m_scale; + + m_childs = std::move(node.m_childs); + for (Node* child : m_childs) + child->m_parent = this; + + m_parent = node.m_parent; + if (m_parent) + { + m_parent->RemoveChild(&node); + m_parent->AddChild(this); + node.m_parent = nullptr; + } + + OnNodeInvalidation = std::move(node.OnNodeInvalidation); + OnNodeNewParent = std::move(node.OnNodeNewParent); + OnNodeRelease = std::move(node.OnNodeRelease); + + InvalidateNode(); + + return *this; + } + void Node::AddChild(Node* node) const { #ifdef NAZARA_DEBUG diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index b1ca74d80..bd5314862 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,8 @@ namespace Nz Utility::Utility(Config /*config*/) : ModuleBase("Utility", this) { + ECS::RegisterComponents(); + if (!Buffer::Initialize()) throw std::runtime_error("failed to initialize buffers"); diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index 449953242..024c530ce 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -54,6 +54,7 @@ namespace Nz deviceInfo.name = physDevice.properties.deviceName; deviceInfo.features.anisotropicFiltering = physDevice.features.samplerAnisotropy; + deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid; deviceInfo.limits.minUniformBufferOffsetAlignment = physDevice.properties.limits.minUniformBufferOffsetAlignment; @@ -274,7 +275,7 @@ namespace Nz VkValidationFeaturesEXT features = { VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT }; - std::vector enabledFeatures = { + std::array enabledFeatures = { //VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, //VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT, VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT diff --git a/xmake.lua b/xmake.lua index 3c68f861d..faa8b90eb 100644 --- a/xmake.lua +++ b/xmake.lua @@ -14,7 +14,8 @@ local modules = { if is_plat("linux") then add_syslinks("dl", "pthread") end - end + end, + Packages = {"entt"} }, Graphics = { Deps = {"NazaraRenderer"}, @@ -54,7 +55,7 @@ local modules = { }, Physics3D = { Deps = {"NazaraUtility"}, - Packages = {"newtondynamics"} + Packages = {"entt", "newtondynamics"} }, Platform = { Deps = {"NazaraUtility"}, diff --git a/xmake/actions/generateheaders.lua b/xmake/actions/generateheaders.lua index b23e88479..872ab4eda 100644 --- a/xmake/actions/generateheaders.lua +++ b/xmake/actions/generateheaders.lua @@ -11,9 +11,11 @@ on_run(function () local paths = {} local excludedFiles = { + ["Components.hpp"] = true, ["ConfigCheck.hpp"] = true, ["Debug.hpp"] = true, ["DebugOff.hpp"] = true, + ["Systems.hpp"] = true, ["ThreadSafety.hpp"] = true, ["ThreadSafetyOff.hpp"] = true } @@ -37,42 +39,80 @@ on_run(function () config:close() - table.insert(paths, { - Excludes = excludedFiles, + paths[moduleName] = { + Excludes = table.copy(excludedFiles), Header = head, HeaderGuard = "NAZARA_GLOBAL_" .. moduleName:upper() .. "_HPP", Name = "Nazara" .. moduleName, SearchDir = modulePath, Target = modulePath .. ".hpp" - }) + } + + -- Handle components and systems + if (os.isdir(modulePath .. "/Components")) then + paths[moduleName .. "_Components"] = { + Excludes = table.copy(excludedFiles), + Header = head, + HeaderGuard = "NAZARA_GLOBAL_" .. moduleName:upper() .. "_COMPONENTS_HPP", + Name = "Nazara" .. moduleName .. " components", + SearchDir = modulePath .. "/Components", + Target = modulePath .. "/Components.hpp" + } + end + + if (os.isdir(modulePath .. "/Systems")) then + paths[moduleName .. "_Systems"] = { + Excludes = table.copy(excludedFiles), + Header = head, + HeaderGuard = "NAZARA_GLOBAL_" .. moduleName:upper() .. "_SYSTEMS_HPP", + Name = "Nazara" .. moduleName .. " systems", + SearchDir = modulePath .. "/Systems", + Target = modulePath .. "/Systems.hpp" + } + end end - table.insert(paths, { + paths["Core"].Excludes["ECS.hpp"] = true + paths["OpenGLRenderer"].Excludes["Wrapper.hpp"] = true + paths["Shader"].Excludes["ShaderLangTokenList.hpp"] = true + paths["VulkanRenderer"].Excludes["Wrapper.hpp"] = true + + -- OpenGL renderer wrapper + paths["OpenGLWrapper"] = { Excludes = { ["DeviceFunctions.hpp"] = true, ["GlobalFunctions.hpp"] = true, ["InstanceFunctions.hpp"] = true, }, + Header = paths["OpenGLRenderer"].Header, HeaderGuard = "NAZARA_GLOBAL_OPENGLRENDERER_WRAPPER_HPP", Name = "OpenGL wrapper", SearchDir = "include/Nazara/OpenGLRenderer/Wrapper", Target = "include/Nazara/OpenGLRenderer/Wrapper.hpp" - }) + } - table.insert(paths, { + -- Vulkan renderer wrapper + paths["VulkanWrapper"] = { Excludes = { ["DeviceFunctions.hpp"] = true, ["GlobalFunctions.hpp"] = true, ["InstanceFunctions.hpp"] = true, }, + Header = paths["VulkanRenderer"].Header, HeaderGuard = "NAZARA_GLOBAL_VULKANRENDERER_WRAPPER_HPP", Name = "Vulkan wrapper", SearchDir = "include/Nazara/VulkanRenderer/Wrapper", Target = "include/Nazara/VulkanRenderer/Wrapper.hpp" - }) + } - for k,v in ipairs(paths) do + for _,v in pairs(paths) do print(v.Name) + local files = os.files(v.SearchDir .. "/*.hpp") + if (#files == 0) then + print("Skipped (no file matched)") + goto continue + end + local header, err = io.open(v.Target, "w+") if (not header) then error("Failed to create header file (" .. v.Target .. "): " .. err) @@ -87,7 +127,6 @@ on_run(function () header:write("#ifndef " .. v.HeaderGuard .. "\n") header:write("#define " .. v.HeaderGuard .. "\n\n") - local files = os.files(v.SearchDir .. "/*.hpp") local count = 0 for _, filePath in pairs(files) do local pathParts = path.split(filePath) @@ -96,7 +135,6 @@ on_run(function () end local include = table.concat(pathParts, "/") - print(include) local fileName = path.filename(filePath) if (not v.Excludes[fileName]) then header:write("#include <" .. include .. ">\n") @@ -108,5 +146,6 @@ on_run(function () header:close() print(string.format("-#include count: %d", count)) + ::continue:: end end)