diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 93d1cdff..bb4ccc35 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -22,6 +22,8 @@ #include "ECS_Base/Managers/SHEntityManager.h" #include "Graphics/MiddleEnd/Interface/SHRenderable.h" #include "Scene/SHSceneManager.h" +#include "Math/Transform/SHTransformSystem.h" + #include "Scenes/SBTestScene.h" #include "Math/Transform/SHTransformComponent.h" @@ -45,8 +47,10 @@ namespace Sandbox window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); // Create Systems - SHADE::SHSystemManager::CreateSystem(); SHADE::SHSystemManager::CreateSystem(); + // TODO(Diren): Create Physics System here + SHADE::SHSystemManager::CreateSystem(); + SHADE::SHSystemManager::CreateSystem(); SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); // Create Routines @@ -54,6 +58,12 @@ namespace Sandbox SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); + + // TODO(Diren): Register Physics System & Routines here + + SHADE::SHSystemManager::RegisterRoutine(); + SHADE::SHComponentManager::CreateComponentSparseSet(); + SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); SHADE::SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index e6082d3f..0caf3c7e 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -38,35 +38,56 @@ namespace Sandbox // Create Materials auto matInst = graphicsSystem->AddMaterialInstance(); - // Create entity and add mesh - testObj = SHADE::SHEntityManager::CreateEntity(); - //SHComponentManager::AddComponent(testObj); - auto& renderable = *SHADE::SHComponentManager::GetComponent_s(testObj); - auto& transform = *SHADE::SHComponentManager::GetComponent_s(testObj); + // Create Stress Test Objects + static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; + constexpr int NUM_ROWS = 200; + constexpr int NUM_COLS = 100; + static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f }; + static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f }; + for (int z = 0; z < NUM_ROWS; ++z) + for (int x = 0; x < NUM_COLS; ++x) + { + auto entity = SHEntityManager::CreateEntity(); + auto& renderable = *SHComponentManager::GetComponent_s(entity); + auto& transform = *SHComponentManager::GetComponent_s(entity); - renderable.Mesh = CUBE_MESH; - renderable.SetMaterial(matInst); - renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f); - - // Add script + renderable.Mesh = CUBE_MESH; + renderable.SetMaterial(matInst); + + // Set initial positions + transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z }); + //transform.SetLocalScale(TEST_OBJ_SCALE); + + stressTestObjects.emplace_back(entity); + } + + // Create blank entity with a script + testObj = SHADE::SHEntityManager::CreateEntity(); SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); - scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript"); + scriptEngine->AddScript(testObj, "TestScript"); } void SBTestScene::Update(float dt) { - static float rotation = 0.0f; + /*static float rotation = 0.0f; - auto& renderable = *SHADE::SHComponentManager::GetComponent_s(testObj); - SHTransform tf; - tf.rotation = SHVec3(rotation, 0.0f, 0.0f); - renderable.TransformMatrix = tf.ComputeTRS(); + auto& transform = *SHADE::SHComponentManager::GetComponent_s(testObj); - rotation += dt * 10.0f; + transform.SetLocalRotation(rotation, 0.0f, 0.0f); + rotation += dt * 10.0f;*/ + /*static float rotation = 0.0f; + + auto& transform = *SHADE::SHComponentManager::GetComponent_s(stressTestObjects[0]); + + transform.SetWorldPosition({rotation, 0.0f, 0.0f}); + rotation += dt * 10.0f;*/ // Destroy entity if space is pressed if (GetKeyState(VK_SPACE) & 0x8000) - SHADE::SHEntityManager::DestroyEntity(testObj); + { + SHADE::SHScriptEngine* scriptEngine = static_cast(SHADE::SHSystemManager::GetSystem()); + scriptEngine->RemoveAllScripts(testObj); + } } void SBTestScene::Render() diff --git a/SHADE_Application/src/Scenes/SBTestScene.h b/SHADE_Application/src/Scenes/SBTestScene.h index 81ee3e7b..3a1598d5 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.h +++ b/SHADE_Application/src/Scenes/SBTestScene.h @@ -10,6 +10,7 @@ namespace Sandbox private: EntityID camera; EntityID testObj; + std::vector stressTestObjects; public: virtual void Load(); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index c2090fc0..a68ee7fa 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -22,6 +22,8 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "Math/Transform/SHTransformComponent.h" namespace SHADE { @@ -33,6 +35,9 @@ namespace SHADE { if (!pipeline) throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!"); + + // Mark all as dirty + setAllDirtyFlags(); } void SHBatch::Add(const SHRenderable* renderable) @@ -52,6 +57,9 @@ namespace SHADE // Add renderable in subBatch->Renderables.insert(renderable); + + // Mark all as dirty + setAllDirtyFlags(); } void SHBatch::Remove(const SHRenderable* renderable) @@ -67,6 +75,10 @@ namespace SHADE return; subBatch->Renderables.erase(renderable); + + // Mark all as dirty + for (bool& dirt : isDirty) + dirt = true; } void SHBatch::Clear() @@ -81,13 +93,22 @@ namespace SHADE // Clear GPU buffers - drawDataBuffer.Free(); - transformDataBuffer.Free(); - matPropsBuffer.Free(); + for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + drawDataBuffer[i].Free(); + transformDataBuffer[i].Free(); + matPropsBuffer[i].Free(); + } } - void SHBatch::UpdateTransformBuffer() + void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index."); + return; + } + // Reset Transform Data transformData.clear(); @@ -96,17 +117,32 @@ namespace SHADE for (const SHRenderable* renderable : subBatch.Renderables) { // Transform - transformData.emplace_back(renderable->TransformMatrix); + auto transform = SHComponentManager::GetComponent(renderable->GetEID()); + if (!transform) + { + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); + } + else + { + transformData.emplace_back(transform->GetTRS()); + } } // Transfer to GPU - transformDataBuffer->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0); + transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0); } - void SHBatch::Build(Handle device) + void SHBatch::Build(Handle device, uint32_t frameIndex) { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index."); + return; + } + // No need to build as there are no changes - if (!isDirty) + if (!isDirty[frameIndex]) return; // Count number of elements @@ -116,61 +152,77 @@ namespace SHADE numTotalElements += subBatch.Renderables.size(); } - // Generate CPU buffers - // - Draw data - drawData.reserve(subBatches.size()); - drawData.clear(); - // - Transform data - transformData.reserve(numTotalElements); - transformData.clear(); - // - Material Properties Data - const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface - ( - SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, - SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, - vk::ShaderStageFlagBits::eFragment - ); - const bool EMPTY_MAT_PROPS = !SHADER_INFO; - Byte singleMatPropSize = 0; - Byte matPropTotalBytes = 0; - if (!EMPTY_MAT_PROPS) + // Generate CPU buffers if there are changes + if (isCPUBuffersDirty) { - singleMatPropSize = SHADER_INFO->GetBytesRequired(); - matPropTotalBytes = drawData.size() * singleMatPropSize; - if (matPropsDataSize < matPropTotalBytes) + // - Draw data + drawData.reserve(subBatches.size()); + drawData.clear(); + // - Transform data + transformData.reserve(numTotalElements); + transformData.clear(); + // - Material Properties Data + const Handle SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, + vk::ShaderStageFlagBits::eFragment + ); + const bool EMPTY_MAT_PROPS = !SHADER_INFO; + Byte singleMatPropSize = 0; + Byte matPropTotalBytes = 0; + if (!EMPTY_MAT_PROPS) { - matPropsData.reset(new char[matPropTotalBytes]); - matPropsDataSize = matPropTotalBytes; - } - } - - // Build Sub Batches - uint32_t nextInstanceIndex = 0; - char* propsCurrPtr = matPropsData.get(); - for (auto& subBatch : subBatches) - { - // Create command - drawData.emplace_back(vk::DrawIndexedIndirectCommand - { - .indexCount = subBatch.Mesh->IndexCount, - .instanceCount = static_cast(subBatch.Renderables.size()), - .firstIndex = subBatch.Mesh->FirstIndex, - .vertexOffset = subBatch.Mesh->FirstVertex, - .firstInstance = nextInstanceIndex - }); - - // Fill in buffers (CPU) - for (const SHRenderable* renderable : subBatch.Renderables) - { - // Transform - transformData.emplace_back(renderable->TransformMatrix); - // Material Properties - if (!EMPTY_MAT_PROPS) + singleMatPropSize = SHADER_INFO->GetBytesRequired(); + matPropTotalBytes = drawData.size() * singleMatPropSize; + if (matPropsDataSize < matPropTotalBytes) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); - propsCurrPtr += singleMatPropSize; + matPropsData.reset(new char[matPropTotalBytes]); + matPropsDataSize = matPropTotalBytes; } } + + // Build Sub Batches + uint32_t nextInstanceIndex = 0; + char* propsCurrPtr = matPropsData.get(); + for (auto& subBatch : subBatches) + { + // Create command + drawData.emplace_back(vk::DrawIndexedIndirectCommand + { + .indexCount = subBatch.Mesh->IndexCount, + .instanceCount = static_cast(subBatch.Renderables.size()), + .firstIndex = subBatch.Mesh->FirstIndex, + .vertexOffset = subBatch.Mesh->FirstVertex, + .firstInstance = nextInstanceIndex + }); + + // Fill in buffers (CPU) + for (const SHRenderable* renderable : subBatch.Renderables) + { + // Transform + auto transform = SHComponentManager::GetComponent_s(renderable->GetEID()); + if (!transform) + { + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); + } + else + { + transformData.emplace_back(transform->GetTRS()); + } + + // Material Properties + if (!EMPTY_MAT_PROPS) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + propsCurrPtr += singleMatPropSize; + } + } + } + + // Successfully update CPU buffers + isCPUBuffersDirty = false; } // Send all buffered data to the GPU buffers @@ -179,36 +231,52 @@ namespace SHADE const uint32_t DRAW_DATA_BYTES = static_cast(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES, + device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES, BuffUsage::eIndirectBuffer ); // - Transform Buffer const uint32_t TF_DATA_BYTES = static_cast(transformData.size() * sizeof(SHMatrix)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, transformDataBuffer, transformData.data(), TF_DATA_BYTES, + device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, BuffUsage::eVertexBuffer ); // - Material Properties Buffer - if (!EMPTY_MAT_PROPS) + if (matPropsData) { SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, matPropsBuffer, matPropsData.get(), static_cast(matPropTotalBytes), + device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast(matPropsDataSize), BuffUsage::eStorageBuffer ); } - isDirty = false; + isDirty[frameIndex] = false; } /*---------------------------------------------------------------------------------*/ /* SHBatch - Usage Functions */ /*---------------------------------------------------------------------------------*/ - void SHBatch::Draw(Handle cmdBuffer) + void SHBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) { + if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) + { + SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index."); + return; + } + cmdBuffer->BindPipeline(pipeline); - cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer, 0); - cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast(drawData.size())); + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); + cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast(drawData.size())); + } + + /*---------------------------------------------------------------------------------*/ + /* SHBatch - Helper Functions */ + /*---------------------------------------------------------------------------------*/ + void SHBatch::setAllDirtyFlags() + { + for (bool& dirt : isDirty) + dirt = true; + isCPUBuffersDirty = true; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index f438d6c1..a572adca 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -14,12 +14,14 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include +#include // External Dependencies #include "Graphics/SHVulkanIncludes.h" // Project Includes #include "Resource/Handle.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Math/SHMatrix.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" namespace SHADE { @@ -71,9 +73,9 @@ namespace SHADE void Add(const SHRenderable* renderable); void Remove(const SHRenderable* renderable); void Clear(); - void UpdateTransformBuffer(); - void Build(Handle device); - void Draw(Handle cmdBuffer); + void UpdateTransformBuffer(uint32_t frameIndex); + void Build(Handle device, uint32_t frameIndex); + void Draw(Handle cmdBuffer, uint32_t frameIndex); /*-----------------------------------------------------------------------------*/ /* Getter Functions */ @@ -88,15 +90,21 @@ namespace SHADE Handle pipeline; // Batch Tree std::vector subBatches; - bool isDirty = true; + std::array isDirty; // CPU Buffers std::vector drawData; std::vector transformData; std::unique_ptr matPropsData; Byte matPropsDataSize = 0; + bool isCPUBuffersDirty = true; // GPU Buffers - Handle drawDataBuffer; - Handle transformDataBuffer; - Handle matPropsBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer; + std::array, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer; + + /*-----------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------*/ + void setAllDirtyFlags(); }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp index ea216ed5..ecd99a20 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.cpp @@ -91,12 +91,12 @@ namespace SHADE (*superBatch)->Remove(renderable); } - void SHBatcher::FinaliseBatches(Handle device) + void SHBatcher::FinaliseBatches(Handle device, uint32_t frameIndex) { // Build SuperBatches for (auto& batch : superBatches) { - batch->Build(device); + batch->Build(device, frameIndex); } } @@ -109,11 +109,11 @@ namespace SHADE superBatches.clear(); } - void SHBatcher::UpdateTransformBuffer() - { + void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex) +{ for (auto& batch : superBatches) { - batch->UpdateTransformBuffer(); + batch->UpdateTransformBuffer(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h index 89dea2eb..b4fff203 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatcher.h @@ -51,9 +51,9 @@ namespace SHADE void PrepareBatches(); void AddToBatch(SHRenderable const* renderable); void RemoveFromBatch(SHRenderable const* renderable); - void FinaliseBatches(Handle device); + void FinaliseBatches(Handle device, uint32_t frameIndex); void ClearBatches(); - void UpdateTransformBuffer(); + void UpdateTransformBuffer(uint32_t frameIndex); void RegisterSuperBatch(Handle superBatch); void DeregisterSuperBatch(Handle superBatch); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index 8b7ea619..633d40a9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -78,29 +78,29 @@ namespace SHADE batches.clear(); } - void SHSuperBatch::UpdateTransformBuffer() + void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex) { for (auto& batch : batches) { - batch.UpdateTransformBuffer(); + batch.UpdateTransformBuffer(frameIndex); } } - void SHSuperBatch::Build(Handle device) noexcept + void SHSuperBatch::Build(Handle device, uint32_t frameIndex) noexcept { // Build all batches for (auto& batch : batches) { - batch.Build(device); + batch.Build(device, frameIndex); } } - void SHSuperBatch::Draw(Handle cmdBuffer) noexcept + void SHSuperBatch::Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept { // Build all batches for (auto& batch : batches) { - batch.Draw(cmdBuffer); + batch.Draw(cmdBuffer, frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h index 6151e56e..5379ee61 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.h @@ -55,9 +55,9 @@ namespace SHADE void Add(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept; void Clear() noexcept; - void UpdateTransformBuffer(); - void Build(Handle device) noexcept; - void Draw(Handle cmdBuffer) noexcept; + void UpdateTransformBuffer(uint32_t frameIndex); + void Build(Handle device, uint32_t frameIndex) noexcept; + void Draw(Handle cmdBuffer, uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------------*/ /* Getter Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp index 992aff05..4a1117c3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHCamera.cpp @@ -22,24 +22,24 @@ namespace SHADE void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up) { SHVec3 view = target - pos; view = SHVec3::Normalise(view); - SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); - const SHVec3 UP = SHVec3::Cross(right, view); - - viewMatrix = SHMatrix::Identity; - viewMatrix(0, 0) = UP[0]; - viewMatrix(1, 0) = UP[1]; - viewMatrix(2, 0) = UP[2]; - viewMatrix(0, 1) = right[0]; - viewMatrix(1, 1) = right[1]; - viewMatrix(2, 1) = right[2]; - viewMatrix(0, 2) = view[0]; - viewMatrix(1, 2) = view[1]; - viewMatrix(2, 2) = view[2]; - viewMatrix(3, 0) = -UP.Dot(pos); - viewMatrix(3, 1) = -right.Dot(pos); - viewMatrix(3, 2) = -view.Dot(pos); - - isDirty = true; + SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); + const SHVec3 UP = SHVec3::Cross(right, view); + + viewMatrix = SHMatrix::Identity; + viewMatrix(0, 0) = UP[0]; + viewMatrix(1, 0) = UP[1]; + viewMatrix(2, 0) = UP[2]; + viewMatrix(0, 1) = right[0]; + viewMatrix(1, 1) = right[1]; + viewMatrix(2, 1) = right[2]; + viewMatrix(0, 2) = view[0]; + viewMatrix(1, 2) = view[1]; + viewMatrix(2, 2) = view[2]; + viewMatrix(3, 0) = -UP.Dot(pos); + viewMatrix(3, 1) = -right.Dot(pos); + viewMatrix(3, 2) = -view.Dot(pos); + + isDirty = true; } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index cee00c9b..48f16713 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -114,7 +114,8 @@ namespace SHADE screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); screenCamera->SetOrthographic(static_cast(windowDims.first), static_cast(windowDims.second), 0.01f, 100.0f); worldCamera = resourceManager.Create(); - worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f)); + //worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f)); + worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f)); worldCamera->SetPerspective(90.0f, static_cast(windowDims.first), static_cast(windowDims.second), 0.0f, 100.0f); // Create Default Viewport @@ -306,7 +307,7 @@ namespace SHADE for (auto vp : viewports) for (auto renderer : vp->GetRenderers()) { - renderer->GetRenderGraph()->FinaliseBatch(); + renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame()); } // Resize diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 32a6a99a..5199565c 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -92,5 +92,4 @@ namespace SHADE materialChanged = false; oldMaterial = {}; } - } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 0d48b5cb..3bb7cfda 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -66,7 +66,6 @@ namespace SHADE /* Data Members */ /*-------------------------------------------------------------------------------*/ Handle Mesh; - SHMatrix TransformMatrix; // TODO: Replace with Transform component private: /*-------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index f53f3e99..ecf9059c 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -346,13 +346,13 @@ namespace SHADE inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); } - void SHSubpass::Execute(Handle& commandBuffer) noexcept + void SHSubpass::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept { // Ensure correct transforms are provided - superBatch->UpdateTransformBuffer(); + superBatch->UpdateTransformBuffer(frameIndex); // Draw all the batches - superBatch->Draw(commandBuffer); + superBatch->Draw(commandBuffer, frameIndex); // Draw all the exterior draw calls for (auto& drawCall : exteriorDrawCalls) @@ -591,7 +591,7 @@ namespace SHADE for (uint32_t i = 0; i < subpasses.size(); ++i) { - subpasses[i]->Execute(commandBuffer); + subpasses[i]->Execute(commandBuffer, frameIndex); // Go to next subpass if not last subpass if (i != subpasses.size() - 1) @@ -624,14 +624,9 @@ namespace SHADE return pipeline; } - void SHRenderGraphNode::FinaliseBatch() - { - batcher.FinaliseBatches(logicalDeviceHdl); - } - - void SHRenderGraphNode::UpdateBatchTransforms() - { - batcher.UpdateTransformBuffer(); + void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) +{ + batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); } /***************************************************************************/ @@ -1088,11 +1083,11 @@ namespace SHADE node->Execute(cmdBuffer, frameIndex); } - void SHRenderGraph::FinaliseBatch() - { + void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) +{ for (auto& node : nodes) { - node->FinaliseBatch(); + node->FinaliseBatch(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index 16770475..b8c00417 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -137,7 +137,7 @@ namespace SHADE void AddInput(std::string resourceToReference) noexcept; // Runtime functions - void Execute(Handle& commandBuffer) noexcept; + void Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept; void AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept; /*-----------------------------------------------------------------------*/ @@ -230,8 +230,7 @@ namespace SHADE // TODO: RemoveSubpass() void Execute (Handle& commandBuffer, uint32_t frameIndex) noexcept; Handle GetOrCreatePipeline (std::pair, Handle> const& vsFsPair, Handle subpass) noexcept; - void FinaliseBatch(); - void UpdateBatchTransforms(); + void FinaliseBatch(uint32_t frameIndex); /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ @@ -289,7 +288,7 @@ namespace SHADE Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; void Generate (void) noexcept; void Execute (uint32_t frameIndex, Handle cmdBuffer) noexcept; - void FinaliseBatch(); + void FinaliseBatch(uint32_t frameIndex); /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index adbdf746..8f05f96f 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -25,14 +25,12 @@ namespace SHADE /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ - //SHTransformSystem::TransformUpdateRoutine SHTransformSystem::UpdateRoutine; - /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() - : SHSystemRoutine { "Transform Update", false } + : SHSystemRoutine { "Transform Update", true } {} @@ -47,6 +45,16 @@ namespace SHADE UpdateEntity(SCENE_GRAPH.GetRoot()); } + void SHTransformSystem::Init() + { + + } + + void SHTransformSystem::Exit() + { + + } + /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -58,19 +66,8 @@ namespace SHADE for (const auto* child : node->GetChildren()) { - // Active states of entities should sync with scene nodes - const bool IS_NODE_ACTIVE = child->IsActive(); - - #ifdef _DEBUG - const bool IS_ENTITY_ACTIVE = SHEntityManager::GetEntityByID(child->GetEntityID())->GetActive(); - SHASSERT(IS_NODE_ACTIVE == IS_ENTITY_ACTIVE, "Entity and Node active states are not synced!") - #endif - - if (!IS_NODE_ACTIVE) - { - UpdateEntity(child); - continue; - } + + const bool HAS_TRANSFORM = SHComponentManager::HasComponent(child->GetEntityID()); if (!HAS_TRANSFORM) @@ -78,8 +75,13 @@ namespace SHADE auto* childTransform = SHComponentManager::GetComponent(child->GetEntityID()); - if (childTransform->dirty || HAS_PARENT_CHANGED) - UpdateTransform(*childTransform, NODE_TRANSFORM); + // Only update if node in hierarchy and component are both active + const bool IS_NODE_ACTIVE = child->IsActive(); + if (IS_NODE_ACTIVE && childTransform->isActive) + { + if (childTransform->dirty || HAS_PARENT_CHANGED) + UpdateTransform(*childTransform, NODE_TRANSFORM); + } UpdateEntity(child); @@ -96,7 +98,7 @@ namespace SHADE if (parent) { localToWorld = parent->GetTRS(); - worldToLocal = SHMatrix::Inverse(tf.local.trs); + worldToLocal = SHMatrix::Inverse(localToWorld); } while (!tf.updateQueue.empty()) @@ -140,6 +142,10 @@ namespace SHADE tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.ComputeTRS(); + + // Transpose TRS to column major + tf.local.trs.Transpose(); + tf.world.trs.Transpose(); } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index c57cbdbd..02c3b6c6 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -21,7 +21,7 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHTransformSystem : public SHSystem + class SH_API SHTransformSystem final : public SHSystem { public: /*---------------------------------------------------------------------------------*/ @@ -29,7 +29,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHTransformSystem () = default; - ~SHTransformSystem () = default; + ~SHTransformSystem () override = default; SHTransformSystem (const SHTransformSystem&) = delete; SHTransformSystem (SHTransformSystem&&) = delete; @@ -45,7 +45,7 @@ namespace SHADE /* System Routines */ /*---------------------------------------------------------------------------------*/ - class TransformUpdateRoutine : public SHSystemRoutine + class SH_API TransformUpdateRoutine final: public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ @@ -72,7 +72,12 @@ namespace SHADE void Execute(double dt) noexcept override; }; - //static TransformUpdateRoutine UpdateRoutine; + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void Init () override; + void Exit () override; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 84c7f1c5..da2dcffd 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -497,9 +497,16 @@ namespace SHADE SHSceneNode* newNode = AllocateNode(entityID); if (parent == nullptr) + { + // Specific handling for root to avoid a warning when removing a non-existent child parent = root; - - newNode->SetParent(parent); + newNode->parent = root; + root->children.emplace_back(newNode); + } + else + { + newNode->SetParent(parent); + } return newNode; } diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index fada5b70..0c508a34 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -103,17 +103,17 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ /* Script Manipulation Functions */ /*-----------------------------------------------------------------------------------*/ - bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName) + bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName) { - return csScriptsAdd(entity.GetEID(), scriptName.data()); + return csScriptsAdd(entity, scriptName.data()); } - void SHScriptEngine::RemoveAllScripts(const SHEntity& entity) + void SHScriptEngine::RemoveAllScripts(EntityID entity) { - csScriptsRemoveAll(entity.GetEID()); + csScriptsRemoveAll(entity); } - void SHScriptEngine::RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy) + void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy) { - csScriptsRemoveAllImmediately(entity.GetEID(), callOnDestroy); + csScriptsRemoveAllImmediately(entity, callOnDestroy); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.h b/SHADE_Engine/src/Scripting/SHScriptEngine.h index 0994bb5d..08852e90 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.h +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.h @@ -116,14 +116,14 @@ namespace SHADE /// True if successfully added. False otherwise with the error logged to the /// console. /// - bool AddScript(const SHEntity& entity, const std::string_view& scriptName); + bool AddScript(EntityID entity, const std::string_view& scriptName); /// /// Removes all Scripts attached to the specified Entity. Does not do anything /// if the specified Entity is invalid or does not have any Scripts /// attached. /// /// The entity to remove the scripts from. - void RemoveAllScripts(const SHEntity& entity); + void RemoveAllScripts(EntityID entity); /// /// Removes all Scripts attached to the specified Entity. Unlike /// RemoveAllScripts(), this removes all the scripts immediately. @@ -135,7 +135,7 @@ namespace SHADE /// Whether or not to call OnDestroy on the scripts. This is ignored if not in /// play mode. /// - void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy); + void RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy); /*-----------------------------------------------------------------------------*/ /* Script Serialisation Functions */