From 0e518c52a953da2023a4fef789ff175ea89dd565 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 2 Oct 2022 04:22:32 +0800 Subject: [PATCH 01/35] Fixed bug when SceneGraph is destroyed --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index da2dcffd..60f0794d 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -312,6 +312,11 @@ namespace SHADE if (parentNode == nullptr) { SHLOG_WARNING("Removing Entity {}'s parent", entityID) + + if (parent) + parent->RemoveChild(this); + + return; } // Handle self assignment From 5a0b34ceea63dd80bdedda43e6c74611424b5517 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 17:47:32 +0800 Subject: [PATCH 02/35] Added Event for Scene Graph Change Parent --- SHADE_Engine/src/Events/SHEventDefines.h | 11 ++++++----- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 21 +++++++++++++++++++-- SHADE_Engine/src/Scene/SHSceneGraph.h | 15 +++++++++------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index 317b67c1..fc9f41e1 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier; typedef uint32_t SHEventHandle; //Add your event identifiers here: -constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; -constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 }; -constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 }; -constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 }; -constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 }; +constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 }; +constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 }; +constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 }; +constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 }; +constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 }; +constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 572e5927..291b5b2b 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHEntityManager.h" +#include "Events/SHEventManager.hpp" #include "Tools/SHLogger.h" #include "Tools/SHException.h" @@ -364,10 +365,18 @@ namespace SHADE } //////////////////////////////////////// + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), + .newParentID = parent->GetEntityID() + }; + if (parent == nullptr) parent = root; NODE_ITER->second->SetParent(parent); + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept @@ -401,8 +410,16 @@ namespace SHADE } //////////////////////////////////////// + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), + .newParentID = parent + }; + SHSceneNode* currentNode = NODE_ITER->second; currentNode->SetParent(PARENT_ITER->second); + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } /*-----------------------------------------------------------------------------------*/ @@ -563,7 +580,7 @@ namespace SHADE ReleaseNode(node); } - void SHSceneGraph::Traverse (const UnaryPredicate& predicate) const + void SHSceneGraph::Traverse (const UnaryFunction& predicate) const { TraverseAndInvokePredicate(root, predicate); } @@ -602,7 +619,7 @@ namespace SHADE delete node; } - void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryPredicate& predicate) + void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryFunction& predicate) { for (auto* child : node->children) { diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 3f3ebf92..62715f72 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -97,9 +97,8 @@ namespace SHADE /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using EntityNodeMap = std::unordered_map; - - using UnaryPredicate = std::function; + using EntityNodeMap = std::unordered_map; + using UnaryFunction = std::function; /*---------------------------------------------------------------------------------*/ @@ -143,8 +142,7 @@ namespace SHADE bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; void Reset () noexcept; - void Traverse (const UnaryPredicate& predicate) const; - + void Traverse (const UnaryFunction& predicate) const; private: /*---------------------------------------------------------------------------------*/ @@ -160,8 +158,13 @@ namespace SHADE SHSceneNode* AllocateNode (EntityID entityID); void ReleaseNode (SHSceneNode* node) noexcept; - static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryPredicate& predicate); + static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryFunction& predicate); }; + struct SHSceneGraphChangeParentEvent + { + EntityID oldParentID; + EntityID newParentID; + }; } // namespace SHADE \ No newline at end of file From 314d497b66c93cf21c5f245e4846961297eb6a60 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 18:35:57 +0800 Subject: [PATCH 03/35] Reparenting objects maintain world transforms --- Assets/Editor/Layouts/UserLayout.ini | 20 ++++----- SHADE_Application/src/Scenes/SBTestScene.cpp | 6 +-- .../src/Math/Transform/SHTransformSystem.cpp | 43 ++++++++++++++++++- .../src/Math/Transform/SHTransformSystem.h | 6 ++- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 10 +++-- SHADE_Engine/src/Scene/SHSceneGraph.h | 1 + 6 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 530ee770..7b0a70f8 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Hierarchy Panel] Pos=0,142 -Size=571,918 +Size=349,918 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,29 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1649,48 -Size=271,1012 +Pos=1483,48 +Size=437,1012 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] Pos=0,48 -Size=571,92 +Size=349,92 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=573,48 -Size=1074,1012 +Pos=351,48 +Size=1130,1012 Collapsed=0 DockId=0x00000002,0 [Docking][Data] DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=571,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1074,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1130,1036 CentralNode=1 Selected=0x13926F0B + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=437,1036 Selected=0xE7039252 diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index f1d656ee..d81550e1 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -77,9 +77,9 @@ namespace Sandbox customMat->SetProperty("data.alpha", 0.1f); // Create Stress Test Objects - static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f; - constexpr int NUM_ROWS = 10; - constexpr int NUM_COLS = 10; + static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; + constexpr int NUM_ROWS = 2; + constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 6b05e323..448fa60d 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -17,7 +17,6 @@ #include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/SHException.h" namespace SHADE { @@ -47,7 +46,9 @@ namespace SHADE void SHTransformSystem::Init() { - + std::shared_ptr thisReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; + ReceiverPtr receiver = std::dynamic_pointer_cast(thisReceiver); + SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver); } void SHTransformSystem::Exit() @@ -59,6 +60,44 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent) + { + const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); + + // Get Current Respective Components + auto* tf = SHComponentManager::GetComponent(eventData->data->entityID); + const auto* PARENT = SHComponentManager::GetComponent_s(eventData->data->newParentID); + + // Recompute local transform and store localToWorld Matrix + SHMatrix localToWorld = SHMatrix::Identity; + SHMatrix worldToLocal = SHMatrix::Identity; + + if (PARENT != nullptr) // Not the root + { + localToWorld = PARENT->GetTRS(); + worldToLocal = SHMatrix::Inverse(localToWorld); + } + + // Maintain World Transform and recompute Local Transform + + // Compute Local Position + tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); + + // Compute Local Rotation + tf->local.rotation = tf->world.rotation; + if (PARENT) + tf->local.rotation -= PARENT->GetLocalRotation(); + + // Compute Local Scale + tf->local.scale = tf->world.scale; + if (PARENT) + tf->local.scale /= PARENT->GetLocalScale(); + + tf->local.trs = localToWorld; + + return eventData->handle; + } + void SHTransformSystem::UpdateEntity(const SHSceneNode* node) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 02c3b6c6..8a50b368 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -84,8 +84,10 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - static void UpdateEntity (const SHSceneNode* node); - static void UpdateTransform(SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); + SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + + static void UpdateEntity (const SHSceneNode* node); + static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 291b5b2b..ac6975fb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -367,8 +367,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), - .newParentID = parent->GetEntityID() + .entityID = entityID + , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() + , .newParentID = parent ? parent->GetEntityID() : root->GetEntityID() }; if (parent == nullptr) @@ -412,8 +413,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), - .newParentID = parent + .entityID = entityID + , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() + , .newParentID = parent }; SHSceneNode* currentNode = NODE_ITER->second; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 62715f72..1dfc1542 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -163,6 +163,7 @@ namespace SHADE struct SHSceneGraphChangeParentEvent { + EntityID entityID; EntityID oldParentID; EntityID newParentID; }; From fda33f7461087c84299a6afcac050a22e1ee81ac Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 22:55:59 +0800 Subject: [PATCH 04/35] Fixed multi-level transform updates --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- .../src/Math/Transform/SHTransformSystem.cpp | 87 +++++++++++++++---- .../src/Math/Transform/SHTransformSystem.h | 7 +- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 12 +-- SHADE_Engine/src/Scene/SHSceneGraph.h | 6 +- 5 files changed, 84 insertions(+), 30 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index d81550e1..be09768b 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -78,7 +78,7 @@ namespace Sandbox // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; - constexpr int NUM_ROWS = 2; + constexpr int NUM_ROWS = 3; constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 448fa60d..a3ca3e75 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -64,17 +64,18 @@ namespace SHADE { const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); - // Get Current Respective Components - auto* tf = SHComponentManager::GetComponent(eventData->data->entityID); - const auto* PARENT = SHComponentManager::GetComponent_s(eventData->data->newParentID); + auto* node = eventData->data->node; + auto* tf = SHComponentManager::GetComponent_s(node->GetEntityID()); // Recompute local transform and store localToWorld Matrix SHMatrix localToWorld = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity; - if (PARENT != nullptr) // Not the root + auto* newParent = eventData->data->newParent; + const auto* PARENT_TF = SHComponentManager::GetComponent_s(newParent->GetEntityID()); + if (PARENT_TF != nullptr) // Not the root { - localToWorld = PARENT->GetTRS(); + localToWorld = PARENT_TF->GetTRS(); worldToLocal = SHMatrix::Inverse(localToWorld); } @@ -83,21 +84,74 @@ namespace SHADE // Compute Local Position tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); - // Compute Local Rotation - tf->local.rotation = tf->world.rotation; - if (PARENT) - tf->local.rotation -= PARENT->GetLocalRotation(); + + tf->local.rotation = tf->world.rotation; + tf->local.scale = tf->world.scale; - // Compute Local Scale - tf->local.scale = tf->world.scale; - if (PARENT) - tf->local.scale /= PARENT->GetLocalScale(); + if (PARENT_TF != nullptr) + { + // Compute Local Rotation + tf->local.rotation -= PARENT_TF->GetLocalRotation(); + + // Compute Local Scale + tf->local.scale /= PARENT_TF->GetLocalScale(); + } tf->local.trs = localToWorld; + // Propagate maintaining world transform down the branch + UpdateChildrenLocalTransforms(node); return eventData->handle; } + void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node) + { + // Structure is similar to update entity, albeit without a queue to do being a forced update + for (const auto* child : node->GetChildren()) + { + if (auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); childTransform) + { + const bool IS_NODE_ACTIVE = child->IsActive(); + if (IS_NODE_ACTIVE && childTransform->isActive) + { + // Recompute local transform and store localToWorld Matrix + SHMatrix localToWorld = SHMatrix::Identity; + SHMatrix worldToLocal = SHMatrix::Identity; + + const auto* parent = SHComponentManager::GetComponent_s(node->GetEntityID()); + + if (parent != nullptr) // Not the root + { + localToWorld = parent->GetTRS(); + worldToLocal = SHMatrix::Inverse(localToWorld); + } + + // Maintain World Transform and recompute Local Transform + + // Compute Local Position + childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal); + + + childTransform->local.rotation = childTransform->world.rotation; + childTransform->local.scale = childTransform->world.scale; + + if (parent) + { + // Compute Local Rotation + childTransform->local.rotation -= parent->GetLocalRotation(); + + // Compute Local Scale + childTransform->local.scale /= parent->GetLocalScale(); + } + + childTransform->local.trs = localToWorld; + } + } + + + } + } + void SHTransformSystem::UpdateEntity(const SHSceneNode* node) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); @@ -113,7 +167,10 @@ namespace SHADE if (IS_NODE_ACTIVE && childTransform->isActive) { if (childTransform->dirty || HAS_PARENT_CHANGED) + { UpdateTransform(*childTransform, NODE_TRANSFORM); + childTransform->dirty = true; + } } } @@ -177,10 +234,6 @@ 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 8a50b368..95957830 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -84,10 +84,11 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + static void UpdateChildrenLocalTransforms (SHSceneNode* node); - static void UpdateEntity (const SHSceneNode* node); - static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); + static void UpdateEntity (const SHSceneNode* node); + static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index ac6975fb..950fd6a0 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -367,9 +367,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .entityID = entityID - , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() - , .newParentID = parent ? parent->GetEntityID() : root->GetEntityID() + .node = NODE_ITER->second + , .oldParent = NODE_ITER->second->GetParent() + , .newParent = parent ? parent : root }; if (parent == nullptr) @@ -413,9 +413,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .entityID = entityID - , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() - , .newParentID = parent + .node = NODE_ITER->second + , .oldParent = NODE_ITER->second->GetParent() + , .newParent = PARENT_ITER->second }; SHSceneNode* currentNode = NODE_ITER->second; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 1dfc1542..a4cf45eb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -163,9 +163,9 @@ namespace SHADE struct SHSceneGraphChangeParentEvent { - EntityID entityID; - EntityID oldParentID; - EntityID newParentID; + SHSceneNode* node; + SHSceneNode* oldParent; + SHSceneNode* newParent; }; } // namespace SHADE \ No newline at end of file From a52f0ddeed7f7090a21567daeb85c366437bd2d5 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 21 Oct 2022 00:08:24 +0800 Subject: [PATCH 05/35] Added a degree getter and setter for rotation --- Assets/Editor/Layouts/UserLayout.ini | 2 +- .../Math/Transform/SHTransformComponent.cpp | 64 ++++++++++++++++++- .../src/Math/Transform/SHTransformComponent.h | 42 ++++++------ 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 7b0a70f8..396b853b 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -38,7 +38,7 @@ Collapsed=0 DockId=0x00000002,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=-227,-1256 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index 949cfa67..a8b75497 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -12,6 +12,8 @@ // Primary Header #include "SHTransformComponent.h" +// Project Headers +#include "Math/SHMathHelpers.h" namespace SHADE { @@ -43,6 +45,15 @@ namespace SHADE return local.rotation; } + SHVec3 SHTransformComponent::GetLocalRotationDeg() const noexcept + { + SHVec3 rot = local.rotation; + rot.x = SHMath::RadiansToDegrees(rot.x); + rot.y = SHMath::RadiansToDegrees(rot.y); + rot.z = SHMath::RadiansToDegrees(rot.z); + return rot; + } + const SHVec3& SHTransformComponent::GetLocalScale() const noexcept { return local.scale; @@ -58,6 +69,15 @@ namespace SHADE return world.rotation; } + SHVec3 SHTransformComponent::GetWorldRotationDeg() const noexcept + { + SHVec3 rot = world.rotation; + rot.x = SHMath::RadiansToDegrees(rot.x); + rot.y = SHMath::RadiansToDegrees(rot.y); + rot.z = SHMath::RadiansToDegrees(rot.z); + return rot; + } + const SHVec3& SHTransformComponent::GetWorldScale() const noexcept { return world.scale; @@ -94,6 +114,15 @@ namespace SHADE local.rotation = newLocalRotation; } + void SHTransformComponent::SetLocalRotationDeg(SHVec3 newLocalRotationDeg) noexcept + { + dirty = true; + + local.rotation.x = SHMath::DegreesToRadians(newLocalRotationDeg.x); + local.rotation.y = SHMath::DegreesToRadians(newLocalRotationDeg.y); + local.rotation.z = SHMath::DegreesToRadians(newLocalRotationDeg.z); + } + void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept { dirty = true; @@ -103,6 +132,13 @@ namespace SHADE local.rotation.z = roll; } + void SHTransformComponent::SetLocalRotationDeg(float pitch, float yaw, float roll) noexcept + { + local.rotation.x = SHMath::DegreesToRadians(pitch); + local.rotation.y = SHMath::DegreesToRadians(yaw); + local.rotation.z = SHMath::DegreesToRadians(roll); + } + void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept { dirty = true; @@ -125,6 +161,17 @@ namespace SHADE updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation }); } + void SHTransformComponent::SetWorldRotationDeg(const SHVec3& newWorldRotation) noexcept + { + dirty = true; + + world.rotation.x = SHMath::DegreesToRadians(newWorldRotation.x); + world.rotation.y = SHMath::DegreesToRadians(newWorldRotation.y); + world.rotation.z = SHMath::DegreesToRadians(newWorldRotation.z); + + updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } + void SHTransformComponent::SetWorldRotation(float pitch, float yaw, float roll) noexcept { dirty = true; @@ -136,6 +183,17 @@ namespace SHADE updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} }); } + void SHTransformComponent::SetWorldRotationDeg(float pitch, float yaw, float roll) noexcept + { + dirty = true; + + world.rotation.x = SHMath::DegreesToRadians(pitch); + world.rotation.y = SHMath::DegreesToRadians(yaw); + world.rotation.z = SHMath::DegreesToRadians(roll); + + updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } + void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept { dirty = true; @@ -152,7 +210,7 @@ RTTR_REGISTRATION using namespace rttr; registration::class_("Transform Component") - .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) - .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload(&SHTransformComponent::SetLocalRotation) ) - .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); + .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) + .property("Rotate" , &SHTransformComponent::GetLocalRotationDeg, select_overload(&SHTransformComponent::SetLocalRotationDeg)) + .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index ad355694..2a3fa7a0 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -56,32 +56,38 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; + [[nodiscard]] bool HasChanged () const noexcept; - [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; - [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; - [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; - [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; - [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; - [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; + [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; + [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; + [[nodiscard]] SHVec3 GetLocalRotationDeg () const noexcept; + [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; + [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; + [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; + [[nodiscard]] SHVec3 GetWorldRotationDeg () const noexcept; + [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; - [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; - [[nodiscard]] SHMatrix GetWorldToLocal () const noexcept; + [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; + [[nodiscard]] SHMatrix GetWorldToLocal () const noexcept; - [[nodiscard]] const SHMatrix& GetTRS () const noexcept; + [[nodiscard]] const SHMatrix& GetTRS () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; - void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; - void SetLocalRotation (float pitch, float yaw, float roll) noexcept; - void SetLocalScale (const SHVec3& newLocalScale) noexcept; - void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; - void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotation (float pitch, float yaw, float roll) noexcept; - void SetWorldScale (const SHVec3& newWorldScale) noexcept; + void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; + void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; + void SetLocalRotationDeg (SHVec3 newLocalRotationDeg) noexcept; + void SetLocalRotation (float pitch, float yaw, float roll) noexcept; + void SetLocalRotationDeg (float pitch, float yaw, float roll) noexcept; + void SetLocalScale (const SHVec3& newLocalScale) noexcept; + void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; + void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotationDeg (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotation (float pitch, float yaw, float roll) noexcept; + void SetWorldRotationDeg (float pitch, float yaw, float roll) noexcept; + void SetWorldScale (const SHVec3& newWorldScale) noexcept; private: /*---------------------------------------------------------------------------------*/ From db751bd1418955f3b35be6e384aeedff65cdf438 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 22 Oct 2022 18:22:26 +0800 Subject: [PATCH 06/35] Editor & Scripts can now override Physics-Based objects' Transforms --- Assets/Editor/Layouts/UserLayout.ini | 2 +- .../src/Application/SBApplication.cpp | 4 +- .../src/Math/Transform/SHTransformSystem.cpp | 44 +++++++++++++++++-- .../src/Math/Transform/SHTransformSystem.h | 42 +++++++++++++++--- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 396b853b..7b0a70f8 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -38,7 +38,7 @@ Collapsed=0 DockId=0x00000002,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=-227,-1256 Size=1920,1012 Split=X +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 8733e7b9..3675e275 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -83,11 +83,13 @@ namespace Sandbox SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); - SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index a3ca3e75..4b4f1cce 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -28,8 +28,12 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() - : SHSystemRoutine { "Transform Update", true } + SHTransformSystem::TransformPostLogicUpdate::TransformPostLogicUpdate() + : SHSystemRoutine { "Transform Post-Logic Update", true } + {} + + SHTransformSystem::TransformPostPhysicsUpdate::TransformPostPhysicsUpdate() + : SHSystemRoutine { "Transform Post-Physics Update", false } {} @@ -37,13 +41,20 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept + void SHTransformSystem::TransformPostLogicUpdate::Execute(double) noexcept { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); UpdateEntity(SCENE_GRAPH.GetRoot()); } + void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double dt) noexcept + { + // Get the current scene graph to traverse and update + const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); + UpdateEntityAndClear(SCENE_GRAPH.GetRoot()); + } + void SHTransformSystem::Init() { std::shared_ptr thisReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; @@ -175,6 +186,33 @@ namespace SHADE } UpdateEntity(child); + } + } + + + void SHTransformSystem::UpdateEntityAndClear(const SHSceneNode* node) + { + const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); + const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; + + for (const auto* child : node->GetChildren()) + { + auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); + if (childTransform) + { + // 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); + childTransform->dirty = true; + } + } + } + + UpdateEntityAndClear(child); // Clear dirty flag after all children are updated if (childTransform) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 95957830..256c1561 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -45,25 +45,52 @@ namespace SHADE /* System Routines */ /*---------------------------------------------------------------------------------*/ - class SH_API TransformUpdateRoutine final: public SHSystemRoutine + class SH_API TransformPostLogicUpdate final: public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*-------------------------------------------------------------------------------*/ - TransformUpdateRoutine (); - ~TransformUpdateRoutine () = default; + TransformPostLogicUpdate (); + ~TransformPostLogicUpdate () = default; - TransformUpdateRoutine (const TransformUpdateRoutine&) = delete; - TransformUpdateRoutine (TransformUpdateRoutine&&) = delete; + TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete; + TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Operator Overloads */ /*-------------------------------------------------------------------------------*/ - TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete; - TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete; + TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete; + TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete; + + /*-------------------------------------------------------------------------------*/ + /* Function Members */ + /*-------------------------------------------------------------------------------*/ + + void Execute(double dt) noexcept override; + }; + + class SH_API TransformPostPhysicsUpdate final: public SHSystemRoutine + { + public: + /*-------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*-------------------------------------------------------------------------------*/ + + TransformPostPhysicsUpdate (); + ~TransformPostPhysicsUpdate () = default; + + TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete; + TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete; + + /*-------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-------------------------------------------------------------------------------*/ + + TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete; + TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -88,6 +115,7 @@ namespace SHADE static void UpdateChildrenLocalTransforms (SHSceneNode* node); static void UpdateEntity (const SHSceneNode* node); + static void UpdateEntityAndClear (const SHSceneNode* node); static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; From ebfcf1c6bbbeae4c8a16c7d96ed3be9b4205fb6c Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 22 Oct 2022 20:16:38 +0800 Subject: [PATCH 07/35] Transform now stores orientation as Quaternions. Interface unchanged --- SHADE_Application/src/Scenes/SBTestScene.cpp | 6 +- SHADE_Engine/src/Math/SHMatrix.cpp | 81 +++----- SHADE_Engine/src/Math/SHMatrix.h | 2 + SHADE_Engine/src/Math/SHQuaternion.cpp | 174 +++++++----------- SHADE_Engine/src/Math/SHQuaternion.h | 9 +- .../src/Math/Transform/SHTransform.cpp | 18 +- SHADE_Engine/src/Math/Transform/SHTransform.h | 22 +-- .../Math/Transform/SHTransformComponent.cpp | 78 +++----- .../src/Math/Transform/SHTransformComponent.h | 36 ++-- .../src/Math/Transform/SHTransformSystem.cpp | 75 ++++---- .../src/Math/Transform/SHTransformSystem.h | 3 +- SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 6 +- 12 files changed, 209 insertions(+), 301 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index be09768b..23259ee4 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -104,10 +104,10 @@ namespace Sandbox transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldScale(TEST_OBJ_SCALE); - if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) + //if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero); - else - collider.AddBoundingSphere(0.5f, SHVec3::Zero); + //else + // collider.AddBoundingSphere(0.5f, SHVec3::Zero); stressTestObjects.emplace_back(entity); } diff --git a/SHADE_Engine/src/Math/SHMatrix.cpp b/SHADE_Engine/src/Math/SHMatrix.cpp index 571fa4e0..ec3951e2 100644 --- a/SHADE_Engine/src/Math/SHMatrix.cpp +++ b/SHADE_Engine/src/Math/SHMatrix.cpp @@ -295,32 +295,33 @@ namespace SHADE ) != 0; } + SHMatrix::operator XMMATRIX() const noexcept + { + return XMLoadFloat4x4(this); + } + SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept { return rhs * lhs; } - /*-----------------------------------------------------------------------------------*/ /* Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ void SHMatrix::Transpose() noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - XMStoreFloat4x4(this, XMMatrixTranspose(M)); + XMStoreFloat4x4(this, XMMatrixTranspose(*this)); } void SHMatrix::Invert() noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M)); + XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this)); } float SHMatrix::Determinant() const noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - return XMVectorGetX(XMMatrixDeterminant(M)); + return XMVectorGetX(XMMatrixDeterminant(*this)); } std::string SHMatrix::ToString() const noexcept @@ -337,9 +338,8 @@ namespace SHADE bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept { XMVECTOR s, r, t; - const XMMATRIX M = XMLoadFloat4x4(this); - if (!XMMatrixDecompose(&s, &r, &t, M)) + if (!XMMatrixDecompose(&s, &r, &t, *this)) return false; SHQuaternion orientation; @@ -356,9 +356,8 @@ namespace SHADE bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept { XMVECTOR s, r, t; - const XMMATRIX M = XMLoadFloat4x4(this); - if (!XMMatrixDecompose(&s, &r, &t, M)) + if (!XMMatrixDecompose(&s, &r, &t, *this)) return false; XMStoreFloat3(&scale, s); @@ -376,8 +375,7 @@ namespace SHADE { SHMatrix result; - const XMMATRIX M = XMLoadFloat4x4(&matrix); - XMStoreFloat4x4(&result, XMMatrixTranspose(M)); + XMStoreFloat4x4(&result, XMMatrixTranspose(matrix)); return result; } @@ -385,8 +383,7 @@ namespace SHADE { SHMatrix result; - const XMMATRIX M = XMLoadFloat4x4(&matrix); - XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M)); + XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix)); return result; } @@ -401,8 +398,8 @@ namespace SHADE SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z)); + XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z)); return result; } @@ -410,25 +407,23 @@ namespace SHADE { SHMatrix result; - const XMVECTOR A = XMLoadFloat3(&axis); - XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad)); - + XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad)); return result; } SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll)); + XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll)); return result; } SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z)); + XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles)); return result; } @@ -436,57 +431,55 @@ namespace SHADE { SHMatrix result; - const XMVECTOR Q = XMLoadFloat4(&q); - XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q)); - + XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q)); return result; } SHMatrix SHMatrix::RotateX(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad)); return result; } SHMatrix SHMatrix::RotateY(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad)); return result; } SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad)); return result; } SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor)); + XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor)); return result; } SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z)); + XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z)); return result; } SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z)); + XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale)); return result; } @@ -494,12 +487,7 @@ namespace SHADE { SHMatrix result; - const XMVECTOR EYE = XMLoadFloat3(&eye); - const XMVECTOR TGT = XMLoadFloat3(&target); - const XMVECTOR UP = XMLoadFloat3(&up); - - XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP)); - + XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up)); return result; } @@ -507,12 +495,7 @@ namespace SHADE { SHMatrix result; - const XMVECTOR EYE = XMLoadFloat3(&eye); - const XMVECTOR TGT = XMLoadFloat3(&target); - const XMVECTOR UP = XMLoadFloat3(&up); - - XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP)); - + XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up)); return result; } @@ -522,8 +505,8 @@ namespace SHADE const SHVec3 FWD_HAT = SHVec3::Normalise(-forward); - const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); - const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); + const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT); + const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT)); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); XMStoreFloat3(reinterpret_cast(&result._11), X_HAT); @@ -543,8 +526,8 @@ namespace SHADE const SHVec3 FWD_HAT = SHVec3::Normalise(forward); - const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); - const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); + const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT); + const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT)); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); XMStoreFloat3(reinterpret_cast(&result._11), X_HAT); @@ -563,7 +546,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane)); - return result; } @@ -572,7 +554,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane)); - return result; } @@ -581,7 +562,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane)); - return result; } @@ -590,7 +570,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane)); - return result; } @@ -599,7 +578,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane)); - return result; } @@ -608,7 +586,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane)); - return result; } diff --git a/SHADE_Engine/src/Math/SHMatrix.h b/SHADE_Engine/src/Math/SHMatrix.h index 7a662478..4d8f1bfe 100644 --- a/SHADE_Engine/src/Math/SHMatrix.h +++ b/SHADE_Engine/src/Math/SHMatrix.h @@ -77,6 +77,8 @@ namespace SHADE SHMatrix& operator= (const SHMatrix& rhs) = default; SHMatrix& operator= (SHMatrix&& rhs) = default; + operator DirectX::XMMATRIX () const noexcept; + SHMatrix& operator+= (const SHMatrix& rhs) noexcept; SHMatrix& operator-= (const SHMatrix& rhs) noexcept; SHMatrix& operator*= (const SHMatrix& rhs) noexcept; diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 33c568a5..924ac67a 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -40,40 +40,10 @@ namespace SHADE : XMFLOAT4( _x, _y, _z, _w ) {} - SHQuaternion::SHQuaternion(float yaw, float pitch, float roll) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - XMStoreFloat4(this, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll)); - } - - SHQuaternion::SHQuaternion(const SHVec3& eulerAngles) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMVECTOR V = XMLoadFloat3(&eulerAngles); - XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); - } - - SHQuaternion::SHQuaternion(const SHVec3& axis, float angleInRad) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMVECTOR AXIS = XMLoadFloat3(&axis); - XMStoreFloat4(this, XMQuaternionRotationAxis(AXIS, angleInRad)); - } - - SHQuaternion::SHQuaternion(const SHMatrix& rotationMatrix) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMMATRIX M = XMLoadFloat4x4(&rotationMatrix); - XMStoreFloat4(this, XMQuaternionRotationMatrix(M)); - } - SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) { - const SHVec3& SHADE_VEC{ rp3dEuler }; - - const XMVECTOR V = XMLoadFloat3(&SHADE_VEC); - XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); + XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler })); } SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept @@ -113,10 +83,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVectorAdd(Q1, Q2)); + XMStoreFloat4(&result, XMVectorAdd(*this, rhs)); return result; } @@ -124,10 +91,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2)); + XMStoreFloat4(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -135,9 +99,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(this); - - XMStoreFloat4(&result, XMVectorNegate(Q)); + XMStoreFloat4(&result, XMVectorNegate(*this)); return result; } @@ -145,10 +107,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2)); + XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs)); return result; } @@ -156,9 +115,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(this); - - XMStoreFloat4(&result, XMVectorScale(Q, rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, rhs)); return result; } @@ -166,27 +123,18 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs)); - - XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2)); + XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs))); return result; } bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMQuaternionEqual(Q1, Q2); + return XMQuaternionEqual(*this, rhs); } bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMQuaternionNotEqual(Q1, Q2); + return XMQuaternionNotEqual(*this, rhs); } SHQuaternion::operator reactphysics3d::Quaternion() const noexcept @@ -199,6 +147,11 @@ namespace SHADE return reactphysics3d::Vector3{ ToEuler() }; } + SHQuaternion::operator XMVECTOR() const noexcept + { + return XMLoadFloat4(this); + } + SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept { return rhs * lhs; @@ -213,8 +166,7 @@ namespace SHADE XMVECTOR axis; float angle; - const XMVECTOR Q = XMLoadFloat4(this); - XMQuaternionToAxisAngle(&axis, &angle, Q); + XMQuaternionToAxisAngle(&axis, &angle, *this); return angle; } @@ -223,8 +175,7 @@ namespace SHADE XMVECTOR axis; float angle; - const XMVECTOR Q = XMLoadFloat4(this); - XMQuaternionToAxisAngle(&axis, &angle, Q); + XMQuaternionToAxisAngle(&axis, &angle, *this); return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle}; @@ -238,28 +189,22 @@ namespace SHADE void SHQuaternion::Invert() noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - XMStoreFloat4(this, XMQuaternionInverse(Q)); + XMStoreFloat4(this, XMQuaternionInverse(*this)); } float SHQuaternion::Length() const noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - return XMVectorGetX(XMQuaternionLength(Q)); + return XMVectorGetX(XMQuaternionLength(*this)); } float SHQuaternion::LengthSquared() const noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - return XMVectorGetX(XMQuaternionLengthSq(Q)); + return XMVectorGetX(XMQuaternionLengthSq(*this)); } float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMQuaternionDot(Q1, Q2)); + return XMVectorGetX(XMQuaternionDot(*this, rhs)); } SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept @@ -273,29 +218,29 @@ namespace SHADE SHVec3 SHQuaternion::ToEuler() const noexcept { - const float xx = x * x; - const float yy = y * y; - const float zz = z * z; + const float XX = x * x; + const float YY = y * y; + const float ZZ = z * z; - const float m31 = 2.f * x * z + 2.f * y * w; - const float m32 = 2.f * y * z - 2.f * x * w; - const float m33 = 1.f - 2.f * xx - 2.f * yy; + const float M_31 = 2.f * x * z + 2.f * y * w; + const float M_32 = 2.f * y * z - 2.f * x * w; + const float M_33 = 1.f - 2.f * XX - 2.f * YY; - const float cy = sqrtf(m33 * m33 + m31 * m31); - const float cx = atan2f(-m32, cy); - if (cy > 16.0f * SHMath::EPSILON) + const float CY = sqrtf(M_33 * M_33 + M_31 * M_31); + const float CX = atan2f(-M_32, CY); + if (CY > 16.0f * SHMath::EPSILON) { - const float m12 = 2.f * x * y + 2.f * z * w; - const float m22 = 1.f - 2.f * xx - 2.f * zz; + const float M_12 = 2.f * x * y + 2.f * z * w; + const float M_22 = 1.f - 2.f * XX - 2.f * ZZ; - return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22)); + return SHVec3(CX, atan2f(M_31, M_33), atan2f(M_12, M_22)); } else { - const float m11 = 1.f - 2.f * yy - 2.f * zz; - const float m21 = 2.f * x * y - 2.f * z * w; + const float m11 = 1.f - 2.f * YY - 2.f * ZZ; + const float m21 = 2.f * x * y - 2.f * z * w; - return SHVec3(cx, 0.f, atan2f(-m21, m11)); + return SHVec3(CX, 0.f, atan2f(-m21, m11)); } } @@ -311,13 +256,43 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHQuaternion SHQuaternion::FromEuler(const SHVec3& eulerAngles) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationRollPitchYawFromVector(eulerAngles)); + return result; + } + + SHQuaternion SHQuaternion::FromPitchYawRoll(float pitch, float yaw, float roll) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll)); + return result; + } + + SHQuaternion SHQuaternion::FromAxisAngle(const SHVec3& axis, float angle) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationAxis(axis, angle)); + return result; + } + + SHQuaternion SHQuaternion::FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationMatrix(rotationMatrix)); + return result; + } + SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - - XMStoreFloat4(&result, XMQuaternionNormalize(Q)); + XMStoreFloat4(&result, XMQuaternionNormalize(q)); return result; } @@ -325,9 +300,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - - XMStoreFloat4(&result, XMQuaternionConjugate(Q)); + XMStoreFloat4(&result, XMQuaternionConjugate(q)); return result; } @@ -335,9 +308,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - XMStoreFloat4(&result, XMQuaternionInverse(Q)); - + XMStoreFloat4(&result, XMQuaternionInverse(q)); return result; } @@ -362,10 +333,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(&q1); - const XMVECTOR Q2 = XMLoadFloat4(&q2); - - XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t)); + XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t)); return result; } diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index c94907b5..f3ce3d61 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -51,9 +51,6 @@ namespace SHADE SHQuaternion () noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float yaw, float pitch, float roll) noexcept; - SHQuaternion (const SHVec3& eulerAngles) noexcept; - SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; - SHQuaternion (const SHMatrix& rotationMatrix) noexcept; // Conversion from other math types @@ -87,6 +84,7 @@ namespace SHADE operator reactphysics3d::Quaternion () const noexcept; operator reactphysics3d::Vector3 () const noexcept; + operator DirectX::XMVECTOR () const noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -113,6 +111,11 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ + [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; + [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; + [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; + [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; + [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.cpp b/SHADE_Engine/src/Math/Transform/SHTransform.cpp index f51d73ec..ef7c5fda 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransform.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransform.cpp @@ -26,15 +26,15 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHTransform::SHTransform() noexcept - : position { SHVec3::Zero } - , rotation { SHVec3::Zero } - , scale { SHVec3::One } + : position { SHVec3::Zero } + , orientation { SHQuaternion::Identity } + , scale { SHVec3::One } {} SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept - : position { pos } - , rotation { rot } - , scale { scl } + : position { pos } + , orientation { SHQuaternion::FromEuler(rot) } + , scale { scl } {} /*-----------------------------------------------------------------------------------*/ @@ -43,12 +43,12 @@ namespace SHADE bool SHTransform::operator==(const SHTransform& rhs) const noexcept { - return !(position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); + return !(position != rhs.position || orientation != rhs.orientation || scale != rhs.scale); } bool SHTransform::operator!=(const SHTransform& rhs) const noexcept { - return (position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); + return (position != rhs.position || orientation != rhs.orientation || scale != rhs.scale); } /*-----------------------------------------------------------------------------------*/ @@ -59,7 +59,7 @@ namespace SHADE { const SHMatrix T = SHMatrix::Translate(position); - const SHMatrix R = SHMatrix::Rotate(rotation); + const SHMatrix R = SHMatrix::Rotate(orientation); const SHMatrix S = SHMatrix::Scale(scale); trs = S * R * T; diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.h b/SHADE_Engine/src/Math/Transform/SHTransform.h index c1a0e565..2e7d236c 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransform.h +++ b/SHADE_Engine/src/Math/Transform/SHTransform.h @@ -12,8 +12,8 @@ // Project Headers #include "SH_API.h" -#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" #include "Math/SHMatrix.h" namespace SHADE @@ -31,22 +31,23 @@ namespace SHADE static const SHTransform Identity; - SHVec3 position; - SHVec3 rotation; - SHVec3 scale; + SHVec3 position; + SHQuaternion orientation; + SHVec3 scale; - SHMatrix trs; + SHMatrix trs; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHTransform (const SHTransform&) = default; - SHTransform (SHTransform&&) = default; - ~SHTransform () = default; + SHTransform (const SHTransform&) = default; + SHTransform (SHTransform&&) = default; + ~SHTransform () = default; - SHTransform () noexcept; - SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept; + SHTransform () noexcept; + SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept; + SHTransform (const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -63,7 +64,6 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ const SHMatrix& ComputeTRS(); - }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index a8b75497..306cde67 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -42,16 +42,12 @@ namespace SHADE const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept { - return local.rotation; + return localRotation; } - SHVec3 SHTransformComponent::GetLocalRotationDeg() const noexcept + const SHQuaternion& SHTransformComponent::GetLocalOrientation() const noexcept { - SHVec3 rot = local.rotation; - rot.x = SHMath::RadiansToDegrees(rot.x); - rot.y = SHMath::RadiansToDegrees(rot.y); - rot.z = SHMath::RadiansToDegrees(rot.z); - return rot; + return local.orientation; } const SHVec3& SHTransformComponent::GetLocalScale() const noexcept @@ -66,16 +62,12 @@ namespace SHADE const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept { - return world.rotation; + return worldRotation; } - SHVec3 SHTransformComponent::GetWorldRotationDeg() const noexcept + const SHQuaternion& SHTransformComponent::GetWorldOrientation() const noexcept { - SHVec3 rot = world.rotation; - rot.x = SHMath::RadiansToDegrees(rot.x); - rot.y = SHMath::RadiansToDegrees(rot.y); - rot.z = SHMath::RadiansToDegrees(rot.z); - return rot; + return world.orientation; } const SHVec3& SHTransformComponent::GetWorldScale() const noexcept @@ -111,32 +103,21 @@ namespace SHADE void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept { dirty = true; - local.rotation = newLocalRotation; - } - - void SHTransformComponent::SetLocalRotationDeg(SHVec3 newLocalRotationDeg) noexcept - { - dirty = true; - - local.rotation.x = SHMath::DegreesToRadians(newLocalRotationDeg.x); - local.rotation.y = SHMath::DegreesToRadians(newLocalRotationDeg.y); - local.rotation.z = SHMath::DegreesToRadians(newLocalRotationDeg.z); + localRotation = newLocalRotation; } void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept { dirty = true; - local.rotation.x = pitch; - local.rotation.y = yaw; - local.rotation.z = roll; + localRotation.x = pitch; + localRotation.y = yaw; + localRotation.z = roll; } - void SHTransformComponent::SetLocalRotationDeg(float pitch, float yaw, float roll) noexcept + void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept { - local.rotation.x = SHMath::DegreesToRadians(pitch); - local.rotation.y = SHMath::DegreesToRadians(yaw); - local.rotation.z = SHMath::DegreesToRadians(roll); + } void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept @@ -157,41 +138,24 @@ namespace SHADE { dirty = true; - world.rotation = newWorldRotation; + worldRotation = newWorldRotation; updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation }); } - void SHTransformComponent::SetWorldRotationDeg(const SHVec3& newWorldRotation) noexcept - { - dirty = true; - - world.rotation.x = SHMath::DegreesToRadians(newWorldRotation.x); - world.rotation.y = SHMath::DegreesToRadians(newWorldRotation.y); - world.rotation.z = SHMath::DegreesToRadians(newWorldRotation.z); - - updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); - } - void SHTransformComponent::SetWorldRotation(float pitch, float yaw, float roll) noexcept { dirty = true; - world.rotation.x = pitch; - world.rotation.y = yaw; - world.rotation.z = roll; + worldRotation.x = pitch; + worldRotation.y = yaw; + worldRotation.z = roll; updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} }); } - void SHTransformComponent::SetWorldRotationDeg(float pitch, float yaw, float roll) noexcept + void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept { - dirty = true; - - world.rotation.x = SHMath::DegreesToRadians(pitch); - world.rotation.y = SHMath::DegreesToRadians(yaw); - world.rotation.z = SHMath::DegreesToRadians(roll); - - updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept @@ -210,7 +174,7 @@ RTTR_REGISTRATION using namespace rttr; registration::class_("Transform Component") - .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) - .property("Rotate" , &SHTransformComponent::GetLocalRotationDeg, select_overload(&SHTransformComponent::SetLocalRotationDeg)) - .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); + .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) + .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload(&SHTransformComponent::SetLocalRotation) ) + .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index 2a3fa7a0..d1d21bec 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -60,11 +60,11 @@ namespace SHADE [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; - [[nodiscard]] SHVec3 GetLocalRotationDeg () const noexcept; + [[nodiscard]] const SHQuaternion& GetLocalOrientation () const noexcept; [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; - [[nodiscard]] SHVec3 GetWorldRotationDeg () const noexcept; + [[nodiscard]] const SHQuaternion& GetWorldOrientation () const noexcept; [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; @@ -76,28 +76,30 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; - void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; - void SetLocalRotationDeg (SHVec3 newLocalRotationDeg) noexcept; - void SetLocalRotation (float pitch, float yaw, float roll) noexcept; - void SetLocalRotationDeg (float pitch, float yaw, float roll) noexcept; - void SetLocalScale (const SHVec3& newLocalScale) noexcept; - void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; - void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotationDeg (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotation (float pitch, float yaw, float roll) noexcept; - void SetWorldRotationDeg (float pitch, float yaw, float roll) noexcept; - void SetWorldScale (const SHVec3& newWorldScale) noexcept; + void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; + void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; + void SetLocalRotation (float pitch, float yaw, float roll) noexcept; + void SetLocalOrientation (const SHQuaternion& newLocalOrientation) noexcept; + void SetLocalScale (const SHVec3& newLocalScale) noexcept; + void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; + void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotation (float pitch, float yaw, float roll) noexcept; + void SetWorldOrientation (const SHQuaternion& newWorldOrientation) noexcept; + void SetWorldScale (const SHVec3& newWorldScale) noexcept; private: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ /*---------------------------------------------------------------------------------*/ + // Differentiate between rotation and orientation for setters + // Setting a quaternion directly is different from using euler angle rotations. + enum class UpdateCommandType { WORLD_POSITION , WORLD_ROTATION + , WORLD_ORIENTATION , WORLD_SCALE }; @@ -120,6 +122,12 @@ namespace SHADE bool dirty; + // We store euler angle rotations separately to interface with transform quaternions. + // Reading quaternions are unreliable. + + SHVec3 localRotation; // Stored in degrees + SHVec3 worldRotation; // Stored in degrees + SHTransform local; // Local TRS holds Local To World Transform SHTransform world; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 4b4f1cce..3244db1b 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -17,6 +17,8 @@ #include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Math/SHMathHelpers.h" namespace SHADE { @@ -45,14 +47,16 @@ namespace SHADE { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); - UpdateEntity(SCENE_GRAPH.GetRoot()); + + // TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode. + UpdateEntity(SCENE_GRAPH.GetRoot(), false); } - void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double dt) noexcept + void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); - UpdateEntityAndClear(SCENE_GRAPH.GetRoot()); + UpdateEntity(SCENE_GRAPH.GetRoot(), true); } void SHTransformSystem::Init() @@ -96,13 +100,13 @@ namespace SHADE tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); - tf->local.rotation = tf->world.rotation; - tf->local.scale = tf->world.scale; + tf->localRotation = tf->worldRotation; + tf->local.scale = tf->world.scale; if (PARENT_TF != nullptr) { // Compute Local Rotation - tf->local.rotation -= PARENT_TF->GetLocalRotation(); + tf->localRotation -= PARENT_TF->GetLocalRotation(); // Compute Local Scale tf->local.scale /= PARENT_TF->GetLocalScale(); @@ -143,13 +147,13 @@ namespace SHADE childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal); - childTransform->local.rotation = childTransform->world.rotation; - childTransform->local.scale = childTransform->world.scale; + childTransform->localRotation = childTransform->worldRotation; + childTransform->local.scale = childTransform->world.scale; if (parent) { // Compute Local Rotation - childTransform->local.rotation -= parent->GetLocalRotation(); + childTransform->localRotation -= parent->GetLocalRotation(); // Compute Local Scale childTransform->local.scale /= parent->GetLocalScale(); @@ -158,12 +162,10 @@ namespace SHADE childTransform->local.trs = localToWorld; } } - - } } - void SHTransformSystem::UpdateEntity(const SHSceneNode* node) + void SHTransformSystem::UpdateEntity(const SHSceneNode* node, bool clearDirtyFlag) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; @@ -185,37 +187,10 @@ namespace SHADE } } - UpdateEntity(child); - } - } - - - void SHTransformSystem::UpdateEntityAndClear(const SHSceneNode* node) - { - const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); - const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; - - for (const auto* child : node->GetChildren()) - { - auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); - if (childTransform) - { - // 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); - childTransform->dirty = true; - } - } - } - - UpdateEntityAndClear(child); + UpdateEntity(child, clearDirtyFlag); // Clear dirty flag after all children are updated - if (childTransform) + if (childTransform && clearDirtyFlag) childTransform->dirty = false; } } @@ -244,12 +219,17 @@ namespace SHADE } case SHTransformComponent::UpdateCommandType::WORLD_ROTATION: { - tf.local.rotation = tf.world.rotation; + tf.localRotation = tf.worldRotation; if (parent) - tf.local.rotation -= parent->GetLocalRotation(); + tf.localRotation -= parent->GetLocalRotation(); break; } + case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION: + { + // TODO(Diren): Test using scripts by concat quaternions? + break; + } case SHTransformComponent::UpdateCommandType::WORLD_SCALE: { tf.local.scale = tf.world.scale; @@ -268,7 +248,14 @@ namespace SHADE tf.local.trs = localToWorld; tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); - tf.world.rotation = tf.local.rotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + // TODO(Diren): Wrap rotations between -360 and 360 + + tf.world.orientation = SHQuaternion::FromEuler(tf.worldRotation); + tf.local.orientation = SHQuaternion::FromEuler(tf.localRotation); + tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.ComputeTRS(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 256c1561..e63969ce 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -114,8 +114,7 @@ namespace SHADE SHEventHandle ChangeParent (SHEventPtr changeParentEvent); static void UpdateChildrenLocalTransforms (SHSceneNode* node); - static void UpdateEntity (const SHSceneNode* node); - static void UpdateEntityAndClear (const SHSceneNode* node); + static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag); static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 36f7c57e..f9b476ef 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -140,12 +140,12 @@ namespace SHADE isRigidBody = true; rb->position = tf->GetWorldPosition(); - rb->orientation = tf->GetWorldRotation(); + rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); if (hasColliders) { c->position = tf->GetWorldPosition(); - c->orientation = tf->GetWorldRotation(); + c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); // Get array of colliders and add them back into the rigidbody for (auto& collider : c->colliders | std::views::keys) AddCollider(&collider); @@ -160,7 +160,7 @@ namespace SHADE hasColliders = true; c->position = tf->GetWorldPosition(); - c->orientation = tf->GetWorldRotation(); + c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); for (auto& collider : c->colliders | std::views::keys) AddCollider(&collider); From 33a6d3798c38ce0de2dcfe2aff19c94c8a39452f Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 16:55:01 +0800 Subject: [PATCH 08/35] Added orientation interface and fixed compatibility between physics and transform --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- SHADE_Engine/src/Math/SHQuaternion.cpp | 4 ++ SHADE_Engine/src/Math/SHQuaternion.h | 1 + .../Math/Transform/SHTransformComponent.cpp | 14 +++- .../src/Math/Transform/SHTransformComponent.h | 6 +- .../src/Math/Transform/SHTransformSystem.cpp | 68 +++++++++++++++---- SHADE_Engine/src/Math/Vector/SHVec4.cpp | 9 +++ SHADE_Engine/src/Math/Vector/SHVec4.h | 14 ++-- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 6 +- 9 files changed, 99 insertions(+), 25 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 23259ee4..966a00a5 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -101,7 +101,7 @@ namespace Sandbox //Set initial positions transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) }); //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); - transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); + transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f)); transform.SetWorldScale(TEST_OBJ_SCALE); //if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 924ac67a..3878cea1 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -36,6 +36,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) {} + SHQuaternion::SHQuaternion(const SHVec4& vec4) noexcept + : XMFLOAT4( vec4.x, vec4.y, vec4.z, vec4.w ) + {} + SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept : XMFLOAT4( _x, _y, _z, _w ) {} diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index f3ce3d61..cc1b5ff4 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -49,6 +49,7 @@ namespace SHADE SHQuaternion (SHQuaternion&& rhs) = default; SHQuaternion () noexcept; + SHQuaternion (const SHVec4& vec4) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float yaw, float pitch, float roll) noexcept; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index 306cde67..e56cbc8d 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -103,7 +103,9 @@ namespace SHADE void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept { dirty = true; + localRotation = newLocalRotation; + updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, newLocalRotation }); } void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept @@ -113,11 +115,16 @@ namespace SHADE localRotation.x = pitch; localRotation.y = yaw; localRotation.z = roll; + + updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, SHVec3{pitch, yaw, roll} }); } void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept { - + dirty = true; + + local.orientation = newLocalOrientation; + updateQueue.push({ UpdateCommandType::LOCAL_ORIENTATION, newLocalOrientation }); } void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept @@ -155,7 +162,10 @@ namespace SHADE void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept { - + dirty = true; + + world.orientation = newWorldOrientation; + updateQueue.push({ UpdateCommandType::WORLD_ORIENTATION, newWorldOrientation }); } void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index d1d21bec..ce8bb6fe 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -97,7 +97,9 @@ namespace SHADE enum class UpdateCommandType { - WORLD_POSITION + LOCAL_ROTATION + , LOCAL_ORIENTATION + , WORLD_POSITION , WORLD_ROTATION , WORLD_ORIENTATION , WORLD_SCALE @@ -111,7 +113,7 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ UpdateCommandType type; - SHVec3 data; + SHVec4 data; }; using UpdateQueue = std::queue; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 3244db1b..8bd01fb4 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -200,6 +200,8 @@ namespace SHADE SHMatrix localToWorld = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity; + bool convertRotation = true; + if (parent) { localToWorld = parent->GetTRS(); @@ -212,27 +214,44 @@ namespace SHADE switch (UPDATE_COMMAND.type) { + case SHTransformComponent::UpdateCommandType::LOCAL_ROTATION: + { + convertRotation = true; + break; + } + case SHTransformComponent::UpdateCommandType::LOCAL_ORIENTATION: + { + convertRotation = false; + break; + } case SHTransformComponent::UpdateCommandType::WORLD_POSITION: { - tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data, worldToLocal); + tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data.ToVec3(), worldToLocal); break; } case SHTransformComponent::UpdateCommandType::WORLD_ROTATION: { - tf.localRotation = tf.worldRotation; + tf.localRotation = UPDATE_COMMAND.data.ToVec3(); if (parent) tf.localRotation -= parent->GetLocalRotation(); + convertRotation = true; + break; } case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION: { - // TODO(Diren): Test using scripts by concat quaternions? + tf.local.orientation = UPDATE_COMMAND.data; + if (parent) + tf.local.orientation /= parent->GetLocalOrientation(); + + convertRotation = false; + break; } case SHTransformComponent::UpdateCommandType::WORLD_SCALE: { - tf.local.scale = tf.world.scale; + tf.local.scale = UPDATE_COMMAND.data.ToVec3(); if (parent) tf.local.scale /= parent->GetLocalScale(); @@ -247,17 +266,42 @@ namespace SHADE tf.local.trs = localToWorld; + // Compute world transforms tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); - - tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); - - // TODO(Diren): Wrap rotations between -360 and 360 - - tf.world.orientation = SHQuaternion::FromEuler(tf.worldRotation); - tf.local.orientation = SHQuaternion::FromEuler(tf.localRotation); - tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); + SHVec3 worldRotRad, localRotRad; + + if (convertRotation) + { + tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + // Set the orientation + // Wrap rotations between -360 and 360 and convert to radians + for (size_t i = 0; i < SHVec3::SIZE; ++i) + { + worldRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.worldRotation[i], -360.0f, 360.0f)); + localRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.localRotation[i], -360.0f, 360.0f)); + } + + tf.world.orientation = SHQuaternion::FromEuler(worldRotRad); + tf.local.orientation = SHQuaternion::FromEuler(localRotRad); + } + else + { + tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation; + + // Set the euler angle rotations + worldRotRad = tf.world.orientation.ToEuler(); + localRotRad = tf.local.orientation.ToEuler(); + + for (size_t i = 0; i < SHVec3::SIZE; ++i) + { + tf.worldRotation[i] = SHMath::RadiansToDegrees(worldRotRad[i]); + tf.localRotation[i] = SHMath::RadiansToDegrees(localRotRad[i]); + } + } + tf.world.ComputeTRS(); } diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index bcf2ef97..9857818a 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ) {} + SHVec4::SHVec4(const SHVec3& vec3) noexcept + : XMFLOAT4( vec3.x, vec3.y, vec3.z, 1.0f ) + {} + SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept : XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w ) {} @@ -271,6 +275,11 @@ namespace SHADE return result; } + SHVec3 SHVec4::ToVec3() const noexcept + { + return SHVec3{ x, y, z }; + } + /*-----------------------------------------------------------------------------------*/ /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.h b/SHADE_Engine/src/Math/Vector/SHVec4.h index 911a714e..ce341bed 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.h +++ b/SHADE_Engine/src/Math/Vector/SHVec4.h @@ -16,6 +16,7 @@ // Project Headers #include "SH_API.h" +#include "SHVec3.h" namespace SHADE { @@ -53,6 +54,7 @@ namespace SHADE ~SHVec4 () = default; SHVec4 () noexcept; + SHVec4 (const SHVec3& vec3) noexcept; SHVec4 (const XMFLOAT4& xmfloat4) noexcept; SHVec4 (float x, float y, float z, float w) noexcept; @@ -102,16 +104,18 @@ namespace SHADE [[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept; [[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept; [[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept; + + [[nodiscard]] SHVec3 ToVec3 () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Min (const std::initializer_list& vs) noexcept; - [[nodiscard]] static SHVec4 Max (const std::initializer_list& vs) noexcept; + [[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Min (const std::initializer_list& vs) noexcept; + [[nodiscard]] static SHVec4 Max (const std::initializer_list& vs) noexcept; [[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept; [[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept; [[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 7dc6c44e..a1994ad2 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" +#include "Math/SHMathHelpers.h" #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformComponent.h" @@ -315,7 +316,7 @@ namespace SHADE if (TF->HasChanged()) { physicsObject.SetPosition(TF->GetWorldPosition()); - physicsObject.SetRotation(TF->GetWorldRotation()); + physicsObject.SetOrientation(TF->GetWorldOrientation()); } } } @@ -492,8 +493,7 @@ namespace SHADE // Convert RP3D Transform to SHADE auto* tfComponent = SHComponentManager::GetComponent(entityID); tfComponent->SetWorldPosition(rp3dPos); - tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler()); - + tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot }); // Cache transforms physicsObject.prevTransform = CURRENT_TF; From e15f7696e62ad51896e58fde0bda32df87339d8a Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 18:22:58 +0800 Subject: [PATCH 09/35] Rotations are stored as radians to reduce the number of conversions --- .../src/Math/Transform/SHTransformComponent.h | 4 ++-- .../src/Math/Transform/SHTransformSystem.cpp | 17 ++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index ce8bb6fe..2fe67bdd 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -127,8 +127,8 @@ namespace SHADE // We store euler angle rotations separately to interface with transform quaternions. // Reading quaternions are unreliable. - SHVec3 localRotation; // Stored in degrees - SHVec3 worldRotation; // Stored in degrees + SHVec3 localRotation; // Stored in Radians + SHVec3 worldRotation; // Stored in Radians SHTransform local; // Local TRS holds Local To World Transform SHTransform world; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 8bd01fb4..5a540cd4 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -270,7 +270,7 @@ namespace SHADE tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); - SHVec3 worldRotRad, localRotRad; + if (convertRotation) { @@ -278,10 +278,11 @@ namespace SHADE // Set the orientation // Wrap rotations between -360 and 360 and convert to radians + SHVec3 worldRotRad, localRotRad; for (size_t i = 0; i < SHVec3::SIZE; ++i) { - worldRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.worldRotation[i], -360.0f, 360.0f)); - localRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.localRotation[i], -360.0f, 360.0f)); + worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); + localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); } tf.world.orientation = SHQuaternion::FromEuler(worldRotRad); @@ -292,14 +293,8 @@ namespace SHADE tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation; // Set the euler angle rotations - worldRotRad = tf.world.orientation.ToEuler(); - localRotRad = tf.local.orientation.ToEuler(); - - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - tf.worldRotation[i] = SHMath::RadiansToDegrees(worldRotRad[i]); - tf.localRotation[i] = SHMath::RadiansToDegrees(localRotRad[i]); - } + tf.worldRotation = tf.world.orientation.ToEuler(); + tf.localRotation = tf.local.orientation.ToEuler(); } tf.world.ComputeTRS(); From 57f9898e07667e00fede342e79fc4bee42551693 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 20:03:18 +0800 Subject: [PATCH 10/35] Finished quaternion implementation --- SHADE_Engine/src/Math/SHQuaternion.cpp | 125 +++++++++++++++++++++---- SHADE_Engine/src/Math/SHQuaternion.h | 40 ++++---- SHADE_Managed/Quaternion.hxx | 17 ++++ SHADE_Managed/src/Math/Vector3.hxx | 1 + 4 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 SHADE_Managed/Quaternion.hxx diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 3878cea1..3564916a 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -211,15 +211,6 @@ namespace SHADE return XMVectorGetX(XMQuaternionDot(*this, rhs)); } - SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept - { - SHQuaternion result; - - // TODO (Diren) - - return result; - } - SHVec3 SHQuaternion::ToEuler() const noexcept { const float XX = x * x; @@ -317,19 +308,32 @@ namespace SHADE } - float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept + float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept { - // TODO (Diren) + XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2); - return 0.0f; + const float RS = XMVectorGetW(R); + R = XMVector3Length(R); + return 2.0f * atan2f(XMVectorGetX(R), RS); } - SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept + SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept { SHQuaternion result; - // TODO (Diren) + XMVECTOR R = XMVectorZero(); + if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R)) + { + R = XMVectorLerp(q1, q2, t); + } + else + { + const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t)); + const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t)); + R = XMVectorSubtract(X0, X1); + } + XMStoreFloat4(&result, XMQuaternionNormalize(R)); return result; } @@ -341,13 +345,102 @@ namespace SHADE return result; } - SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept + SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept { + return Lerp(q1, q2, std::clamp(t, tMin, tMax)); + } + + + SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept + { + return Slerp(q1, q2, std::clamp(t, tMin, tMax)); + } + + SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept + { + // Melax, "The Shortest Arc Quaternion", Game Programming Gems + SHQuaternion result; - // TODO (Diren) + const XMVECTOR F = XMVector3Normalize(from); + const XMVECTOR T = XMVector3Normalize(to); + + const float dot = XMVectorGetX(XMVector3Dot(F, T)); + if (dot >= 1.f) + { + result = Identity; + } + else if (dot <= -1.f) + { + XMVECTOR axis = XMVector3Cross(F, SHVec3::Right); + if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon)) + { + axis = XMVector3Cross(F, SHVec3::Up); + } + + const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI); + XMStoreFloat4(&result, Q); + } + else + { + const XMVECTOR C = XMVector3Cross(F, T); + XMStoreFloat4(&result, C); + + const float s = sqrtf((1.f + dot) * 2.f); + result.x /= s; + result.y /= s; + result.z /= s; + result.w = s * 0.5f; + } return result; } + SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept + { + SHQuaternion result; + + const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward); + + const XMVECTOR C = XMVector3Cross(forward, up); + if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon)) + { + // forward and up are co-linear + return Q1; + } + + SHVec3 qU; + XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up)); + + const SHQuaternion Q2 = FromToRotation(qU, up); + + XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1)); + + return result; + } + + SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept + { + SHQuaternion result; + + // We can use the conjugate here instead of inverse assuming q1 & q2 are normalized. + const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to); + + const float RS = XMVectorGetW(R); + const XMVECTOR L = XMVector3Length(R); + const float angle = 2.f * atan2f(XMVectorGetX(L), RS); + if (angle > maxAngleInRad) + { + const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad); + const XMVECTOR Q = XMQuaternionMultiply(delta, from); + XMStoreFloat4(&result, Q); + } + else + { + // Don't overshoot. + result = to; + } + return result; + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index cc1b5ff4..fa5b5d36 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -51,7 +51,6 @@ namespace SHADE SHQuaternion () noexcept; SHQuaternion (const SHVec4& vec4) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; - SHQuaternion (float yaw, float pitch, float roll) noexcept; // Conversion from other math types @@ -98,34 +97,37 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void Invert () noexcept; + void Invert () noexcept; - [[nodiscard]] float Length () const noexcept; - [[nodiscard]] float LengthSquared () const noexcept; - [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; - [[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept; + [[nodiscard]] float Length () const noexcept; + [[nodiscard]] float LengthSquared () const noexcept; + [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; - [[nodiscard]] SHVec3 ToEuler () const noexcept; - [[nodiscard]] std::string ToString () const noexcept; + [[nodiscard]] SHVec3 ToEuler () const noexcept; + [[nodiscard]] std::string ToString () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; - [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; - [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; - [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; + [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; + [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; + [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; + [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; - [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; - [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; - [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; - [[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept; + [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; + [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; + [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; + [[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept; - [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; - [[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; + [[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; - [[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept; + [[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept; + [[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept; + [[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept; }; SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept; diff --git a/SHADE_Managed/Quaternion.hxx b/SHADE_Managed/Quaternion.hxx new file mode 100644 index 00000000..0b07a34e --- /dev/null +++ b/SHADE_Managed/Quaternion.hxx @@ -0,0 +1,17 @@ +/************************************************************************************//*! +\file Quaternion.hxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +#pragma once + +// TODO(Diren) diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx index e6cdc7d4..8b66439c 100644 --- a/SHADE_Managed/src/Math/Vector3.hxx +++ b/SHADE_Managed/src/Math/Vector3.hxx @@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ + #pragma once // Standard Libraries From c34faade8679b7d34735ad47332e445bafc4abb8 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 02:45:47 +0800 Subject: [PATCH 11/35] Converted doubles to floats in SHADE Managed. Added Quaternions. --- SHADE_Managed/Quaternion.hxx | 17 -- SHADE_Managed/src/Math/Math.cxx | 14 +- SHADE_Managed/src/Math/Math.hxx | 24 +-- SHADE_Managed/src/Math/Quaternion.cxx | 170 ++++++++++++++++++ SHADE_Managed/src/Math/Quaternion.hxx | 237 ++++++++++++++++++++++++++ SHADE_Managed/src/Math/Vector2.cxx | 52 +++--- SHADE_Managed/src/Math/Vector2.hxx | 76 ++++----- SHADE_Managed/src/Math/Vector3.cxx | 61 +++---- SHADE_Managed/src/Math/Vector3.hxx | 98 +++++------ SHADE_Managed/src/Utility/Convert.cxx | 19 ++- SHADE_Managed/src/Utility/Convert.hxx | 14 ++ 11 files changed, 596 insertions(+), 186 deletions(-) delete mode 100644 SHADE_Managed/Quaternion.hxx create mode 100644 SHADE_Managed/src/Math/Quaternion.cxx create mode 100644 SHADE_Managed/src/Math/Quaternion.hxx diff --git a/SHADE_Managed/Quaternion.hxx b/SHADE_Managed/Quaternion.hxx deleted file mode 100644 index 0b07a34e..00000000 --- a/SHADE_Managed/Quaternion.hxx +++ /dev/null @@ -1,17 +0,0 @@ -/************************************************************************************//*! -\file Quaternion.hxx -\author Diren D Bharwani, diren.dbharwani, 390002520 -\par email: diren.dbharwani\@digipen.edu -\date Oct 23, 2022 -\brief Contains the definitions of Quaternion struct. - - Note: This file is written in C++17/CLI. - -Copyright (C) 2021 DigiPen Institute of Technology. -Reproduction or disclosure of this file or its contents without the prior written consent -of DigiPen Institute of Technology is prohibited. -*//*************************************************************************************/ - -#pragma once - -// TODO(Diren) diff --git a/SHADE_Managed/src/Math/Math.cxx b/SHADE_Managed/src/Math/Math.cxx index 5ec850a1..fa72e2b6 100644 --- a/SHADE_Managed/src/Math/Math.cxx +++ b/SHADE_Managed/src/Math/Math.cxx @@ -21,7 +21,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Utility Functions */ /*---------------------------------------------------------------------------------*/ - double Math::Wrap(double value, double min, double max) + float Math::Wrap(float value, float min, float max) { while (value < min) { @@ -33,24 +33,24 @@ namespace SHADE } return value; } - double Math::DegreesToRadians(double degrees) + float Math::DegreesToRadians(float degrees) { return degrees * Deg2Rad; } - double Math::RadiansToDegrees(double radians) + float Math::RadiansToDegrees(float radians) { return radians * Rad2Deg; } - double Math::Lerp(double a, double b, double t) + float Math::Lerp(float a, float b, float t) { - return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0f, 1.0f)); } - double Math::LerpUnclamped(double a, double b, double t) + float Math::LerpUnclamped(float a, float b, float t) { return a + t * (b - a); } - double Math::InverseLerp(double a, double b, double value) + float Math::InverseLerp(float a, float b, float value) { return (value - a) / (b - a); } diff --git a/SHADE_Managed/src/Math/Math.hxx b/SHADE_Managed/src/Math/Math.hxx index 3ddc5149..1578d97c 100644 --- a/SHADE_Managed/src/Math/Math.hxx +++ b/SHADE_Managed/src/Math/Math.hxx @@ -27,11 +27,11 @@ namespace SHADE /// /// Degrees-to-radians conversion constant /// - static constexpr double Deg2Rad = System::Math::PI / 180.0; + static constexpr float Deg2Rad = System::Math::PI / 180.0f; /// /// Radians-to-degrees conversion constant /// - static constexpr double Rad2Deg = 180.0 / System::Math::PI; + static constexpr float Rad2Deg = 180.0f / System::Math::PI; /// /// Small value used for single precision floating point comparisons. /// @@ -47,28 +47,28 @@ namespace SHADE /// Minimum value to wrap at. /// Maximum value to wrap at. /// Wrapped value. - static double Wrap(double value, double min, double max); + static float Wrap(float value, float min, float max); /// /// Converts an angle from degree representation to radian representation. /// /// Degree-based angle to convert. /// The specified angle in radians. - static double DegreesToRadians(double degrees); + static float DegreesToRadians(float degrees); /// /// Converts an angle from radian representation to degree representation. /// /// Radian-based angle to convert. /// The specified angle in degrees. - static double RadiansToDegrees(double radians); + static float RadiansToDegrees(float radians); /// /// Linearly interpolates between a and b by t. /// The parameter t is clamped to the range [0, 1]. /// /// The start value. /// The end value. - /// The interpolation value between the two double. - /// The interpolated double result between the two double values. - static double Lerp(double a, double b, double t); + /// The interpolation value between the two float. + /// The interpolated float result between the two float values. + static float Lerp(float a, float b, float t); /// /// Linearly interpolates between a and b by t. /// The parameter t is not clamped and a value based on a and b is supported. @@ -77,9 +77,9 @@ namespace SHADE /// /// The start value. /// The end value. - /// The interpolation value between the two double. - /// The interpolated double result between the two double values. - static double LerpUnclamped(double a, double b, double t); + /// The interpolation value between the two float. + /// The interpolated float result between the two float values. + static float LerpUnclamped(float a, float b, float t); /// /// Calculates the linear parameter t that produces the interpolant value within the range [a, b]. /// @@ -87,6 +87,6 @@ namespace SHADE /// End value. /// Value between start and end. /// Percentage of value between start and end. - static double InverseLerp(double a, double b, double value); + static float InverseLerp(float a, float b, float value); }; } diff --git a/SHADE_Managed/src/Math/Quaternion.cxx b/SHADE_Managed/src/Math/Quaternion.cxx new file mode 100644 index 00000000..863241ac --- /dev/null +++ b/SHADE_Managed/src/Math/Quaternion.cxx @@ -0,0 +1,170 @@ +/************************************************************************************//*! +\file Quaternion.cxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of functions in the Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Quaternion.hxx" +// External Dependencies +#include "Math/SHQuaternion.h" +#include "Math/Vector/SHVec4.h" +// Project Headers +#include "Utility/Convert.hxx" +#include "Math.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + + Quaternion::Quaternion(float _x, float _y, float _z, float _w) + : x { _x } + , y { _y } + , z { _z } + , w { _w } + {} + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + + void Quaternion::SetFromToRotation(Vector3 fromDirection, Vector3 toDirection) + { + const SHQuaternion R = SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection)); + *this = Convert::ToCLI(R); + } + + void Quaternion::SetLookRotation(Vector3 view, Vector3 up) + { + const SHQuaternion R = SHQuaternion::LookRotation(Convert::ToNative(view), Convert::ToNative(up)); + *this = Convert::ToCLI(R); + } + + void Quaternion::ToAngleAxis(float^% angle, Vector3^% axis) + { + const SHVec4 NATIVE_AXIS_ANGLE = Convert::ToNative(*this).GetAxisAngle(); + axis = Convert::ToCLI(NATIVE_AXIS_ANGLE.ToVec3()); + angle = NATIVE_AXIS_ANGLE.w; + } + + System::String^ Quaternion::ToString() + { + return ValueType::ToString(); + } + + /*---------------------------------------------------------------------------------*/ + /* IEquatable */ + /*---------------------------------------------------------------------------------*/ + + bool Quaternion::Equals(Quaternion other) + { + const float DOT = Dot(*this, other); + return fabs(1.0f - DOT) <= Math::Epsilon; + } + + /*---------------------------------------------------------------------------------*/ + /* Object Overrides */ + /*---------------------------------------------------------------------------------*/ + + bool Quaternion::Equals(Object^ o) + { + return ValueType::Equals(o); + } + + int Quaternion::GetHashCode() + { + return ValueType::GetHashCode(); + } + + /*---------------------------------------------------------------------------------*/ + /* Static Functions */ + /*---------------------------------------------------------------------------------*/ + + float Quaternion::Angle(Quaternion a, Quaternion b) + { + return SHQuaternion::Angle(Convert::ToNative(a), Convert::ToNative(b)); + } + + Quaternion Quaternion::AngleAxis(float angle, Vector3 axis) + { + return Convert::ToCLI(SHQuaternion::FromAxisAngle(Convert::ToNative(axis), angle)); + } + + float Quaternion::Dot(Quaternion a, Quaternion b) + { + return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); + } + + Quaternion Quaternion::Euler(float _x, float _y, float _z) + { + return Convert::ToCLI(SHQuaternion::FromPitchYawRoll(_x, _y, _z)); + } + + Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 toDirection) + { + return Convert::ToCLI(SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection))); + } + + Quaternion Quaternion::Inverse(Quaternion rotation) + { + return Convert::ToCLI(SHQuaternion::Inverse(Convert::ToNative(rotation))); + } + + Quaternion Quaternion::Lerp(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::ClampedLerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::LerpUnclamped(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::Lerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::LookRotation(Vector3 forward, Vector3 upwards) + { + return Convert::ToCLI(SHQuaternion::LookRotation(Convert::ToNative(forward), Convert::ToNative(upwards))); + } + + Quaternion Quaternion::Normalize(Quaternion q) + { + return Convert::ToCLI(SHQuaternion::Normalise(Convert::ToNative(q))); + } + + Quaternion Quaternion::RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta) + { + return Convert::ToCLI(SHQuaternion::RotateTowards(Convert::ToNative(from), Convert::ToNative(to), Math::DegreesToRadians(maxDegreesDelta))); + } + + Quaternion Quaternion::Slerp(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::ClampedSlerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::SlerpUnclamped(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::Slerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + + Quaternion Quaternion::operator*(Quaternion lhs, Quaternion rhs) + { + return Convert::ToCLI(Convert::ToNative(lhs) * Convert::ToNative(rhs)); + } + + bool Quaternion::operator==(Quaternion lhs, Quaternion rhs) + { + return lhs.Equals(rhs); + } +} \ No newline at end of file diff --git a/SHADE_Managed/src/Math/Quaternion.hxx b/SHADE_Managed/src/Math/Quaternion.hxx new file mode 100644 index 00000000..783038c9 --- /dev/null +++ b/SHADE_Managed/src/Math/Quaternion.hxx @@ -0,0 +1,237 @@ +/************************************************************************************//*! +\file Quaternion.hxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +#pragma once + +// Standard Libraries +#include +// Project Includes +#include "Vector3.hxx" + +namespace SHADE +{ + /// + /// CLR version of SHADE's Quaternion class that represents an orientation. + /// Designed to closely match Unity's Quaternion struct. + /// + [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] + public value struct Quaternion : public System::IEquatable + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ +#pragma region Constants + + /// + /// Shorthand for writing Quaternion(0, 0, 0, 1). + /// + static initonly Quaternion Identity = Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + +#pragma endregion + + /*-----------------------------------------------------------------------------*/ + /* Public Members */ + /*-----------------------------------------------------------------------------*/ + + /// + /// X-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float x; + /// + /// Y-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float y; + /// + /// Z-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float z; + /// + /// W-component of the Quaternion. Do not directly modify quaternions. + /// + float w; + + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Constructor to construct a Quaternion with the specified components. + /// + /// X-coordinate to set. + /// Y-coordinate to set. + /// Z-coordinate to set. + /// W-coordinate to set. + Quaternion(float _x, float _y, float _z, float _w); + + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Creates a rotation which rotates from fromDirection to toDirection.
+ /// Use this to create a rotation which starts at the first Vector (fromDirection) and rotates to the second Vector (toDirection). + /// These Vectors must be set up in a script. + ///
+ void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection); + + /// + /// Creates a rotation with the specified forward and upwards directions.
+ /// The result is applied to this quaternion. + /// If used to orient a Transform, the Z axis will be aligned with forward and the Y axis with upwards, assuming these vectors are orthogonal. + /// Logs an error if the forward direction is zero. + ///
+ /// The direction to look in. + /// The vector that defines in which direction up is. + void SetLookRotation(Vector3 view, Vector3 up); + + /// + /// Converts a rotation to angle-axis representation (angles in degrees). + /// + void ToAngleAxis(float^% angle, Vector3^% axis); + + System::String^ ToString() override; + + /*-----------------------------------------------------------------------------*/ + /* IEquatable */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Compares equality with an object of the same type. + /// + /// The object to compare with. + /// True if both objects are the same. + virtual bool Equals(Quaternion other); + + /*-----------------------------------------------------------------------------*/ + /* Object */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Compares equality with another unboxed object. + /// + /// The unboxed object to compare with. + /// True if both objects are the same. + bool Equals(Object^ o) override; + + /// + /// Gets a unique hash for this object. + /// + /// Unique hash for this object. + int GetHashCode() override; + + /*-----------------------------------------------------------------------------*/ + /* Static Functions */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Returns the angle in degrees between two rotations a and b.
+ ///
+ /// The angle in degrees between the two vectors. + static float Angle(Quaternion a, Quaternion b); + + /// + /// Creates a rotation which rotates angle degrees around axis. + /// + static Quaternion AngleAxis(float angle, Vector3 axis); + + /// + /// The dot product between two rotations. + /// + static float Dot(Quaternion a, Quaternion b); + + /// + /// Returns a rotation that rotates y degrees around the y axis, x degrees around the x axis, and z degrees around the z axis; applied in that order. + /// + static Quaternion Euler(float _x, float _y, float _z); + + /// + /// Creates a rotation which rotates from fromDirection to toDirection. + /// + static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection); + + /// + /// Returns the Inverse of rotation. + /// + static Quaternion Inverse(Quaternion rotation); + + /// + /// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is clamped to the range [0, 1]. + /// + /// Start value, returned when t = 0. + /// End value, returned when t = 1. + /// Interpolation ratio. + /// A quaternion interpolated between quaternions a and b. + static Quaternion Lerp(Quaternion a, Quaternion b, float t); + + /// + /// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is not clamped. + /// + static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t); + + /// + /// Creates a rotation with the specified forward and upwards directions.
+ /// Z axis will be aligned with forward, X axis aligned with cross product between forward and upwards, and Y axis aligned with cross product between Z and X. + ///
+ static Quaternion LookRotation(Vector3 forward, Vector3 upwards); + + /// + /// Converts this quaternion to one with the same orientation but with a magnitude of 1. + /// + static Quaternion Normalize(Quaternion q); + + /// + /// Rotates a rotation from towards to.
+ /// The from quaternion is rotated towards to by an angular step of maxDegreesDelta (but note that the rotation will not overshoot). + /// Negative values of maxDegreesDelta will move away from to until the rotation is exactly the opposite direction. + ///
+ static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta); + + /// + /// Spherically interpolates between quaternions a and b by ratio t. The parameter t is clamped to the range [0, 1]. + /// + /// Start value, returned when t = 0. + /// End value, returned when t = 1. + /// Interpolation ratio. + /// A quaternion spherically interpolated between quaternions a and b. + static Quaternion Slerp(Quaternion a, Quaternion b, float t); + + /// + /// Spherically interpolates between a and b by t. The parameter t is not clamped. + /// + static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t); + + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Combines rotations lhs and rhs. + /// + /// Left-hand side quaternion. + /// Right-hand side quaternion. + static Quaternion operator*(Quaternion lhs, Quaternion rhs); + + /// + /// Are two quaternions equal to each other? + /// + /// Left-hand side quaternion. + /// Right-hand side quaternion. + static bool operator==(Quaternion lhs, Quaternion rhs); + }; + +} // namespace SHADE diff --git a/SHADE_Managed/src/Math/Vector2.cxx b/SHADE_Managed/src/Math/Vector2.cxx index d40e2323..b110d4f8 100644 --- a/SHADE_Managed/src/Math/Vector2.cxx +++ b/SHADE_Managed/src/Math/Vector2.cxx @@ -26,10 +26,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - Vector2::Vector2(double _x) - : Vector2 { _x, 0.0 } + Vector2::Vector2(float _x) + : Vector2 { _x, 0.0f } {} - Vector2::Vector2(double _x, double _y) + Vector2::Vector2(float _x, float _y) : x { _x } , y { _y } {} @@ -47,22 +47,22 @@ namespace SHADE return *this / GetMagnitude(); } - double Vector2::GetMagnitude() + float Vector2::GetMagnitude() { return sqrt(x * x + y * y); } - double Vector2::GetSqrMagnitude() + float Vector2::GetSqrMagnitude() { return x * x + y * y; } - double Vector2::AngleFromRightRadians() + float Vector2::AngleFromRightRadians() { return atan2(y, x); } - double Vector2::AngleFromRightDegrees() + float Vector2::AngleFromRightDegrees() { return Math::RadiansToDegrees(AngleFromRightRadians()); } @@ -72,7 +72,7 @@ namespace SHADE return IsNearPoint(point, Math::Epsilon); } - bool Vector2::IsNearPoint(Vector2 point, double tolerance) + bool Vector2::IsNearPoint(Vector2 point, float tolerance) { return (*this - point).GetSqrMagnitude() < (tolerance * tolerance); } @@ -113,13 +113,13 @@ namespace SHADE { return IsNear(lhs, rhs, Math::Epsilon); } - bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, double tolerance) + bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, float tolerance) { return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance && (std::abs(lhs.y) - std::abs(rhs.y)) < tolerance; } - double Vector2::Dot(Vector2 lhs, Vector2 rhs) + float Vector2::Dot(Vector2 lhs, Vector2 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; } @@ -153,12 +153,12 @@ namespace SHADE } Vector2 Vector2::Reflect(Vector2 vec, Vector2 normal) { - return vec - (Project(vec, normal.GetNormalised()) * 2.0); + return vec - (Project(vec, normal.GetNormalised()) * 2.0f); } - Vector2 Vector2::RotateRadians(Vector2 vec, double radians) + Vector2 Vector2::RotateRadians(Vector2 vec, float radians) { - const double SINE = sin(radians); - const double COSINE = cos(radians); + const float SINE = sin(radians); + const float COSINE = cos(radians); return Vector2 ( @@ -166,35 +166,35 @@ namespace SHADE vec.x * SINE + vec.y * COSINE ); } - Vector2 Vector2::RotateDegrees(Vector2 vec, double degrees) + Vector2 Vector2::RotateDegrees(Vector2 vec, float degrees) { return RotateRadians(vec, Math::DegreesToRadians(degrees)); } Vector2 Vector2::Min(Vector2 lhs, Vector2 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; return Vector2(std::min(lx, rx), std::min(ly, ry)); } Vector2 Vector2::Max(Vector2 lhs, Vector2 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; return Vector2(std::max(lx, rx), std::max(ly, ry)); } - Vector2 Vector2::Lerp(Vector2 a, Vector2 b, double t) + Vector2 Vector2::Lerp(Vector2 a, Vector2 b, float t) { - return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f)); } - Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, double t) + Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, float t) { return a + ((b - a) * t); } - Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta) + Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta) { // Ignore if it is exactly on the same point if (current == target) @@ -206,7 +206,7 @@ namespace SHADE // Check if check if is behind or ahead of target Vector2 DIFF = target - newPos; - if (Dot(DELTA, DIFF) < 0.0) + if (Dot(DELTA, DIFF) < 0.0f) { newPos = target; } @@ -236,7 +236,7 @@ namespace SHADE lhs.y * rhs.y ); } - Vector2 Vector2::operator*(Vector2 lhs, double rhs) + Vector2 Vector2::operator*(Vector2 lhs, float rhs) { return Vector2 ( @@ -244,7 +244,7 @@ namespace SHADE lhs.y * rhs ); } - Vector2 Vector2::operator/(Vector2 lhs, double rhs) + Vector2 Vector2::operator/(Vector2 lhs, float rhs) { return Vector2 ( diff --git a/SHADE_Managed/src/Math/Vector2.hxx b/SHADE_Managed/src/Math/Vector2.hxx index 9253a703..94b1989f 100644 --- a/SHADE_Managed/src/Math/Vector2.hxx +++ b/SHADE_Managed/src/Math/Vector2.hxx @@ -19,8 +19,8 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// CLR version of the the SHADE Engine's Vector2 class that represents a - /// 2-Dimensional Vector. Designed to closely match Unity's Vector2 struct. + /// CLR version of SHADE Engine's Vector2 class that represents a 2-Dimensional Vector. + /// Designed to closely match Unity's Vector2 struct. /// [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] public value struct Vector2 : public System::IEquatable @@ -33,37 +33,37 @@ namespace SHADE /// /// Shorthand for writing Vector2(0, -1). /// - static initonly Vector2 Down = Vector2(0.0, -1.0); + static initonly Vector2 Down = Vector2(0.0f, -1.0f); /// /// Shorthand for writing Vector2(-1, 0). /// - static initonly Vector2 Left = Vector2(-1.0, 0.0); + static initonly Vector2 Left = Vector2(-1.0f, 0.0f); /// - /// Shorthand for writing Vector2(double.NegativeInfinity, - /// double.NegativeInfinity). + /// Shorthand for writing Vector2(float.NegativeInfinity, + /// float.NegativeInfinity). /// - static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits::lowest(), std::numeric_limits::lowest()); + static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits::lowest(), std::numeric_limits::lowest()); /// /// Shorthand for writing Vector2(1, 1). /// - static initonly Vector2 One = Vector2(1.0, 1.0); + static initonly Vector2 One = Vector2(1.0f, 1.0f); /// - /// Shorthand for writing Vector2(double.PositiveInfinity, - /// double.PositiveInfinity). + /// Shorthand for writing Vector2(float.PositiveInfinity, + /// float.PositiveInfinity). /// - static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits::max(), std::numeric_limits::max()); + static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits::max(), std::numeric_limits::max()); /// /// Shorthand for writing Vector2(1, 0). /// - static initonly Vector2 Right = Vector2(1.0, 0.0); + static initonly Vector2 Right = Vector2(1.0f, 0.0f); /// /// Shorthand for writing Vector2(0, 1). /// - static initonly Vector2 Up = Vector2(0.0, 1.0); + static initonly Vector2 Up = Vector2(0.0f, 1.0f); /// /// Shorthand for writing Vector2(0, 0). /// - static initonly Vector2 Zero = Vector2(0.0, 0.0); + static initonly Vector2 Zero = Vector2(0.0f, 0.0f); #pragma endregion /*-----------------------------------------------------------------------------*/ @@ -72,27 +72,27 @@ namespace SHADE /// /// X-component of the Vector2. /// - double x; + float x; /// /// Y-component of the Vector2. /// - double y; + float y; /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ /// /// Constructor to construct a Vector2 with the specified components with the - /// Y-component set to 0.0. + /// Y-component set to 0.0f. /// /// X-coordinate to set. - Vector2(double _x); + Vector2(float _x); /// /// Constructor to construct a Vector2 with the specified components.. /// /// X-coordinate to set. /// Y-coordinate to set. - Vector2(double _x, double _y); + Vector2(float _x, float _y); /*-----------------------------------------------------------------------------*/ /* Usage Functions */ @@ -117,24 +117,24 @@ namespace SHADE /// need the precise magnitude, consider using GetSqrMagnitude() instead. /// /// Returns the length of this Vector2. - double GetMagnitude(); + float GetMagnitude(); /// /// Calculates and returns the squared magnitude of this Vector2. /// /// Returns the squared length of this Vector2. - double GetSqrMagnitude(); + float GetSqrMagnitude(); /// /// Calculates and returns the angle of this vector from the right vector. This /// function returns values between -Math.PI and Math.PI. /// /// Returns the angle of this vector from the right vector in radians. - double AngleFromRightRadians(); + float AngleFromRightRadians(); /// /// Calculates and returns the angle of this vector from the right vector. This - /// function returns values between -180.0 and 180.0. + /// function returns values between -180.0f and 180.0f. /// /// Returns the angle of this vector from the right vector in degrees. - double AngleFromRightDegrees(); + float AngleFromRightDegrees(); /// /// Checks if a specified point is near this Vector2 that represents a point with /// a tolerance value of PLS_EPSILON. @@ -156,7 +156,7 @@ namespace SHADE /// True if this Vector2 representing a point and the specified point are within /// the range of the specified tolerance. False otherwise. /// - bool IsNearPoint(Vector2 point, double tolerance); + bool IsNearPoint(Vector2 point, float tolerance); /*-----------------------------------------------------------------------------*/ /* IEquatable */ @@ -206,7 +206,7 @@ namespace SHADE /// /// True if the two Vector2s are within the tolerance value specified /// - static bool IsNear(Vector2 lhs, Vector2 rhs, double tolerance); + static bool IsNear(Vector2 lhs, Vector2 rhs, float tolerance); /// /// Computes and returns the dot product of 2 specified Vector2s. /// @@ -215,7 +215,7 @@ namespace SHADE /// /// Scalar value representing the dot product of the two Vector2s. /// - static double Dot(Vector2 lhs, Vector2 rhs); + static float Dot(Vector2 lhs, Vector2 rhs); /// /// Computes the inward perpendicular Vector2 to the specified Vector2. /// Equivalent to calling Perpendicular(lhs, true). This means, the @@ -260,7 +260,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in radians. /// /// The Vector2 that represents the rotated vector. - static Vector2 RotateRadians(Vector2 vec, double radians); + static Vector2 RotateRadians(Vector2 vec, float radians); /// /// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise /// direction. @@ -270,7 +270,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in degrees. /// /// The Vector2 that represents the rotated vector. - static Vector2 RotateDegrees(Vector2 vec, double degrees); + static Vector2 RotateDegrees(Vector2 vec, float degrees); /// /// Computes and returns a Vector2 that is made from the smallest components of /// the two specified Vector2s. @@ -298,25 +298,25 @@ namespace SHADE /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// - /// The start Vector2, returned when t = 0.0. - /// The end Vector2, returned when t = 1.0. + /// The start Vector2, returned when t = 0.0f. + /// The end Vector2, returned when t = 1.0f. /// /// Value used to interpolate between a and b which is clamped to /// the range[0, 1]. /// /// The interpolated Vector2. - static Vector2 Lerp(Vector2 a, Vector2 b, double t); + static Vector2 Lerp(Vector2 a, Vector2 b, float t); /// /// Linearly interpolates between two specified points. /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// Unlike Lerp(), t is not clamped to a range at all. /// - /// The start Vector2, returned when t = 0.0. - /// The end Vector2, returned when t = 1.0. + /// The start Vector2, returned when t = 0.0f. + /// The end Vector2, returned when t = 1.0f. /// Value used to interpolate between a and b. /// The interpolated Vector2. - static Vector2 LerpUnclamped(Vector2 a, Vector2 b, double t); + static Vector2 LerpUnclamped(Vector2 a, Vector2 b, float t); /// /// Moves a point current towards target. /// Similar to Lerp(), however, the function will ensure that the distance never @@ -327,7 +327,7 @@ namespace SHADE /// The target position to move to. /// Maximum distance moved per call. /// Vector representing the moved point. - static Vector2 MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta); + static Vector2 MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta); /*-----------------------------------------------------------------------------*/ /* Overloaded Operators */ @@ -361,7 +361,7 @@ namespace SHADE /// Vector2 to multiply with. /// Scalar to multiply with. /// The result of the scalar multiplication. - static Vector2 operator*(Vector2 lhs, double rhs); + static Vector2 operator*(Vector2 lhs, float rhs); /// /// Calculates the division of a Vector2 with a scalar value and returns /// the result. @@ -369,7 +369,7 @@ namespace SHADE /// Scalar to divide with. /// Vector2 to divide with. /// The result of the scalar division. - static Vector2 operator/(Vector2 lhs, double rhs); + static Vector2 operator/(Vector2 lhs, float rhs); /// /// Checks if two Vector2s are approximately equal. This is equivalent to /// calling Vector2.IsNear() with default tolerance values. diff --git a/SHADE_Managed/src/Math/Vector3.cxx b/SHADE_Managed/src/Math/Vector3.cxx index 26ff5a72..adbb4d3a 100644 --- a/SHADE_Managed/src/Math/Vector3.cxx +++ b/SHADE_Managed/src/Math/Vector3.cxx @@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ + // Precompiled Headers #include "SHpch.h" // Primary Header @@ -26,13 +27,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - Vector3::Vector3(double _x) - : Vector3 {_x, 0.0, 0.0} + Vector3::Vector3(float _x) + : Vector3 {_x, 0.0f, 0.0f} {} - Vector3::Vector3(double _x, double _y) - : Vector3 {_x, _y, 0.0} + Vector3::Vector3(float _x, float _y) + : Vector3 {_x, _y, 0.0f} {} - Vector3::Vector3(double _x, double _y, double _z) + Vector3::Vector3(float _x, float _y, float _z) : x { _x } , y { _y } , z { _z } @@ -54,22 +55,22 @@ namespace SHADE return *this / GetSqrMagnitude(); } - double Vector3::GetMagnitude() + float Vector3::GetMagnitude() { return sqrt(x * x + y * y + z * z); } - double Vector3::GetSqrMagnitude() + float Vector3::GetSqrMagnitude() { return x * x + y * y + z * z; } - double Vector3::Angle2DFromRightRadians() + float Vector3::Angle2DFromRightRadians() { return atan2(y, x); } - double Vector3::Angle2DFromRightDegrees() + float Vector3::Angle2DFromRightDegrees() { return Math::RadiansToDegrees(Angle2DFromRightRadians()); } @@ -79,7 +80,7 @@ namespace SHADE return IsNearPoint(point, Math::Epsilon); } - bool Vector3::IsNearPoint(Vector3 point, double tolerance) + bool Vector3::IsNearPoint(Vector3 point, float tolerance) { return (*this - point).GetSqrMagnitude() < (tolerance * tolerance); } @@ -121,7 +122,7 @@ namespace SHADE { return IsNear(lhs, rhs, Math::Epsilon); } - bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, double tolerance) + bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, float tolerance) { return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance && @@ -129,7 +130,7 @@ namespace SHADE && (std::abs(lhs.z) - std::abs(rhs.z)) < tolerance; } - double Vector3::Dot(Vector3 lhs, Vector3 rhs) + float Vector3::Dot(Vector3 lhs, Vector3 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; } @@ -145,12 +146,12 @@ namespace SHADE } Vector3 Vector3::Reflect(Vector3 vec, Vector3 normal) { - return vec - (Project(vec, normal.GetNormalised()) * 2.0); + return vec - (Project(vec, normal.GetNormalised()) * 2.0f); } - Vector3 Vector3::RotateRadians(Vector3 vec, double radians) + Vector3 Vector3::RotateRadians(Vector3 vec, float radians) { - const double SINE = sin(radians); - const double COSINE = cos(radians); + const float SINE = sin(radians); + const float COSINE = cos(radians); return Vector3 ( @@ -159,15 +160,15 @@ namespace SHADE vec.z ); } - Vector3 Vector3::RotateDegrees(Vector3 vec, double degrees) + Vector3 Vector3::RotateDegrees(Vector3 vec, float degrees) { return RotateRadians(vec, Math::DegreesToRadians(degrees)); } Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; - double lz = lhs.z, rz = rhs.z; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; + float lz = lhs.z, rz = rhs.z; return Vector3(std::min(lx, rx), std::min(ly, ry), @@ -175,23 +176,23 @@ namespace SHADE } Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; - double lz = lhs.z, rz = rhs.z; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; + float lz = lhs.z, rz = rhs.z; return Vector3(std::max(lx, rx), std::max(ly, ry), std::max(lz, rz)); } - Vector3 Vector3::Lerp(Vector3 a, Vector3 b, double t) + Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t) { - return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f)); } - Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, double t) + Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t) { return a + ((b - a) * t); } - Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta) + Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta) { // Ignore if it is exactly on the same point if (current == target) @@ -203,7 +204,7 @@ namespace SHADE // Check if check if is behind or ahead of target Vector3 DIFF = target - newPos; - if (Dot(DELTA, DIFF) < 0.0) + if (Dot(DELTA, DIFF) < 0.0f) { newPos = target; } @@ -236,7 +237,7 @@ namespace SHADE lhs.z * rhs.z ); } - Vector3 Vector3::operator*(Vector3 lhs, double rhs) + Vector3 Vector3::operator*(Vector3 lhs, float rhs) { return Vector3 ( @@ -245,7 +246,7 @@ namespace SHADE lhs.z * rhs ); } - Vector3 Vector3::operator/(Vector3 lhs, double rhs) + Vector3 Vector3::operator/(Vector3 lhs, float rhs) { return Vector3 ( diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx index 8b66439c..70cff88f 100644 --- a/SHADE_Managed/src/Math/Vector3.hxx +++ b/SHADE_Managed/src/Math/Vector3.hxx @@ -22,8 +22,8 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// CLR version of the the PlushieEngine's Vector3 class that represents a - /// 3-Dimensional Vector. Designed to closely match Unity's Vector3 struct. + /// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector. + /// Designed to closely match Unity's Vector3 struct. /// [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] public value struct Vector3 : public System::IEquatable @@ -36,49 +36,49 @@ namespace SHADE /// /// Shorthand for writing Vector3(0, 0, -1). /// - static initonly Vector3 Back = Vector3(0.0, 0.0, -1.0); + static initonly Vector3 Back = Vector3(0.0f, 0.0f, -1.0f); /// /// Shorthand for writing Vector3(0, -1, 0). /// - static initonly Vector3 Down = Vector3(0.0, -1.0, 0.0); + static initonly Vector3 Down = Vector3(0.0f, -1.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 0, 1). /// - static initonly Vector3 Forward = Vector3(0.0, 0.0, 1.0); + static initonly Vector3 Forward = Vector3(0.0f, 0.0f, 1.0f); /// /// Shorthand for writing Vector3(-1, 0, 0). /// - static initonly Vector3 Left = Vector3(-1.0, 0.0, 0.0); + static initonly Vector3 Left = Vector3(-1.0f, 0.0f, 0.0f); /// - /// Shorthand for writing Vector3(double.NegativeInfinity, - /// double.NegativeInfinity, double.NegativeInfinity). + /// Shorthand for writing Vector3(float.NegativeInfinity, + /// float.NegativeInfinity, float.NegativeInfinity). /// - static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits::lowest(), - std::numeric_limits::lowest(), - std::numeric_limits::lowest()); + static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()); /// /// Shorthand for writing Vector3(1, 1, 1). /// - static initonly Vector3 One = Vector3(1.0, 1.0, 1.0); + static initonly Vector3 One = Vector3(1.0f, 1.0f, 1.0f); /// - /// Shorthand for writing Vector3(double.PositiveInfinity, - /// double.PositiveInfinity, double.PositiveInfinity). + /// Shorthand for writing Vector3(float.PositiveInfinity, + /// float.PositiveInfinity, float.PositiveInfinity). /// - static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max()); + static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()); /// /// Shorthand for writing Vector3(1, 0, 0). /// - static initonly Vector3 Right = Vector3(1.0, 0.0, 0.0); + static initonly Vector3 Right = Vector3(1.0f, 0.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 1, 0). /// - static initonly Vector3 Up = Vector3(0.0, 1.0, 0.0); + static initonly Vector3 Up = Vector3(0.0f, 1.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 0, 0). /// - static initonly Vector3 Zero = Vector3(0.0, 0.0, 0.0); + static initonly Vector3 Zero = Vector3(0.0f, 0.0f, 0.0f); #pragma endregion /*-----------------------------------------------------------------------------*/ @@ -87,39 +87,39 @@ namespace SHADE /// /// X-component of the Vector3. /// - double x; + float x; /// /// Y-component of the Vector3. /// - double y; + float y; /// /// Z-component of the Vector3. /// - double z; + float z; /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ /// /// Constructor to construct a Vector3 with the specified components with the - /// Y and Z-component set to 0.0. + /// Y and Z-component set to 0.0f. /// /// X-coordinate to set. - Vector3(double _x); + Vector3(float _x); /// /// Constructor to construct a Vector3 with the specified components with the - /// Z-component set to 0.0. + /// Z-component set to 0.0f. /// /// X-coordinate to set. /// Y-coordinate to set. - Vector3(double _x, double _y); + Vector3(float _x, float _y); /// /// Constructor to construct a Vector3 with the specified components. /// /// X-coordinate to set. /// Y-coordinate to set. /// Z-coordinate to set. - Vector3(double _x, double _y, double _z); + Vector3(float _x, float _y, float _z); /// /// Conversion constructor to construct a Vector3 using a Vector2. /// @@ -149,24 +149,24 @@ namespace SHADE /// need the precise magnitude, consider using GetSqrMagnitude() instead. /// /// Returns the length of this Vector3. - double GetMagnitude(); + float GetMagnitude(); /// /// Calculates and returns the squared magnitude of this Vector3. /// /// Returns the squared length of this Vector3. - double GetSqrMagnitude(); + float GetSqrMagnitude(); /// /// Calculates and returns the angle of this vector from the right vector. This /// function returns values between -Math.PI and Math.PI. /// /// Returns the angle of this vector from the right vector in radians. - double Angle2DFromRightRadians(); + float Angle2DFromRightRadians(); /// /// Calculates and returns the angle of this vector from the right vector. This - /// function returns values between -180.0 and 180.0. + /// function returns values between -180.0f and 180.0f. /// /// Returns the angle of this vector from the right vector in degrees. - double Angle2DFromRightDegrees(); + float Angle2DFromRightDegrees(); /// /// Checks if a specified point is near this Vector3 that represents a point with /// a tolerance value of PLS_EPSILON. @@ -188,7 +188,7 @@ namespace SHADE /// True if this Vector3 representing a point and the specified point are within /// the range of the specified tolerance. False otherwise. /// - bool IsNearPoint(Vector3 point, double tolerance); + bool IsNearPoint(Vector3 point, float tolerance); /*-----------------------------------------------------------------------------*/ /* IEquatable */ @@ -208,12 +208,12 @@ namespace SHADE /// /// The unboxed object to compare with. /// True if both objects are the same. - bool Equals(Object^ o) override; + bool Equals(Object^ o) override; /// /// Gets a unique hash for this object. /// /// Unique hash for this object. - int GetHashCode() override; + int GetHashCode() override; /*-----------------------------------------------------------------------------*/ /* Static Functions */ @@ -236,14 +236,14 @@ namespace SHADE /// /// True if the two Vector3s are within the tolerance value specified /// - static bool IsNear(Vector3 lhs, Vector3 rhs, double tolerance); + static bool IsNear(Vector3 lhs, Vector3 rhs, float tolerance); /// /// Computes and returns the dot product of 2 specified Vector3s. /// /// Vector3 to calculate dot product with. /// Another Vector3 to calculate dot product with. /// Scalar value representing the dot product of the two Vector3s. - static double Dot(Vector3 lhs, Vector3 rhs); + static float Dot(Vector3 lhs, Vector3 rhs); /// /// Computes and returns the cross product of 2 specified Vector3s. /// @@ -274,7 +274,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in radians. /// /// The Vector3 that represents the rotated vector. - static Vector3 RotateRadians(Vector3 vec, double radians); + static Vector3 RotateRadians(Vector3 vec, float radians); /// /// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise /// direction. @@ -284,7 +284,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in degrees. /// /// The Vector3 that represents the rotated vector. - static Vector3 RotateDegrees(Vector3 vec, double degrees); + static Vector3 RotateDegrees(Vector3 vec, float degrees); /// /// Computes and returns a Vector3 that is made from the smallest components of /// the two specified Vector3s. @@ -312,25 +312,25 @@ namespace SHADE /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// - /// The start Vector3, returned when t = 0.0. - /// The end Vector3, returned when t = 1.0. + /// The start Vector3, returned when t = 0.0f. + /// The end Vector3, returned when t = 1.0f. /// /// Value used to interpolate between a and b which is clamped to /// the range[0, 1]. /// /// The interpolated Vector3. - static Vector3 Lerp(Vector3 a, Vector3 b, double t); + static Vector3 Lerp(Vector3 a, Vector3 b, float t); /// /// Linearly interpolates between two specified points. /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// Unlike Lerp(), t is not clamped to a range at all. /// - /// The start Vector3, returned when t = 0.0. - /// The end Vector3, returned when t = 1.0. + /// The start Vector3, returned when t = 0.0f. + /// The end Vector3, returned when t = 1.0f. /// Value used to interpolate between a and b. /// The interpolated Vector3. - static Vector3 LerpUnclamped(Vector3 a, Vector3 b, double t); + static Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t); /// /// Moves a point current towards target. /// Similar to Lerp(), however, the function will ensure that the distance never @@ -341,7 +341,7 @@ namespace SHADE /// The target position to move to. /// Maximum distance moved per call. /// Vector representing the moved point. - static Vector3 MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta); + static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta); /*-----------------------------------------------------------------------------*/ /* Overloaded Operators */ @@ -375,7 +375,7 @@ namespace SHADE /// Vector3 to multiply with. /// Scalar to multiply with. /// The result of the scalar multiplication. - static Vector3 operator*(Vector3 lhs, double rhs); + static Vector3 operator*(Vector3 lhs, float rhs); /// /// Calculates the division of a Vector3 with a scalar value and returns /// the result. @@ -383,7 +383,7 @@ namespace SHADE /// Scalar to divide with. /// Vector3 to divide with. /// The result of the scalar division. - static Vector3 operator/(Vector3 lhs, double rhs); + static Vector3 operator/(Vector3 lhs, float rhs); /// /// Checks if two Vector3s are approximately equal. This is equivalent to /// calling Vector3.IsNear() with default tolerance values. diff --git a/SHADE_Managed/src/Utility/Convert.cxx b/SHADE_Managed/src/Utility/Convert.cxx index 661eb3e4..4646194b 100644 --- a/SHADE_Managed/src/Utility/Convert.cxx +++ b/SHADE_Managed/src/Utility/Convert.cxx @@ -35,10 +35,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHVec3 Convert::ToNative(Vector3 vec) { - const double X = vec.x; - const double Y = vec.y; - const double Z = vec.z; - return SHVec3(X, Y, Z); + return SHVec3(vec.x, vec.y, vec.z); } Vector3 Convert::ToCLI(const SHVec3& vec) { @@ -46,9 +43,7 @@ namespace SHADE } SHVec2 Convert::ToNative(Vector2 vec) { - const double X = vec.x; - const double Y = vec.y; - return SHVec2(X, Y); + return SHVec2(vec.x, vec.y); } Vector2 Convert::ToCLI(const SHVec2& vec) @@ -56,6 +51,16 @@ namespace SHADE return Vector2(vec.x, vec.y); } + SHQuaternion Convert::ToNative(Quaternion quat) + { + return SHQuaternion{ quat.x, quat.y, quat.z, quat.w }; + } + + Quaternion Convert::ToCLI(const SHQuaternion& quat) + { + return Quaternion{ quat.x, quat.y, quat.z, quat.w }; + } + /*---------------------------------------------------------------------------------*/ /* String Conversions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Utility/Convert.hxx b/SHADE_Managed/src/Utility/Convert.hxx index f04cbf4b..d694ca6a 100644 --- a/SHADE_Managed/src/Utility/Convert.hxx +++ b/SHADE_Managed/src/Utility/Convert.hxx @@ -18,10 +18,12 @@ of DigiPen Institute of Technology is prohibited. #include "ECS_Base/Entity/SHEntity.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" // Project Includes #include "Engine/Entity.hxx" #include "Math/Vector2.hxx" #include "Math/Vector3.hxx" +#include "Math/Quaternion.hxx" namespace SHADE { @@ -74,6 +76,18 @@ namespace SHADE /// The native Vector2 to convert from. /// Managed copy of a native Vector2. static Vector2 ToCLI(const SHVec2& vec); + /// + /// Converts from a managed Quaternion to a native Quaternion. + /// + /// The managed Quaternion to convert from. + /// Native copy of a managed Quaternion. + static SHQuaternion ToNative(Quaternion quat); + /// + /// Converts from a native Quaternion to a managed Quaternion. + /// + /// The native Quaternion to convert from. + /// Managed copy of a native Quaternion. + static Quaternion ToCLI(const SHQuaternion& quat); /*-----------------------------------------------------------------------------*/ /* String Conversions */ From 26eb4ad18cf98d7d9b8f8b7806a52e97ce2f8c97 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Mon, 24 Oct 2022 16:18:18 +0800 Subject: [PATCH 12/35] Fix command registrations and mouse pick polling when using transform gizmo --- Assets/Editor/Layouts/UserLayout.ini | 54 ----- .../src/Application/SBApplication.cpp | 10 +- .../HierarchyPanel/SHHierarchyPanel.cpp | 2 +- .../Inspector/SHEditorComponentView.hpp | 4 + .../ViewportWindow/SHEditorViewport.cpp | 2 +- .../src/Editor/Gizmos/SHTransformGizmo.cpp | 65 +++--- .../src/Editor/Gizmos/SHTransformGizmo.h | 6 + SHADE_Engine/src/Editor/SHEditor.cpp | 2 +- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 191 +++++++++--------- 9 files changed, 151 insertions(+), 185 deletions(-) delete mode 100644 Assets/Editor/Layouts/UserLayout.ini diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini deleted file mode 100644 index baced6b8..00000000 --- a/Assets/Editor/Layouts/UserLayout.ini +++ /dev/null @@ -1,54 +0,0 @@ -[Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 -Collapsed=0 - -[Window][SHEditorMenuBar] -Pos=0,48 -Size=1920,1012 -Collapsed=0 - -[Window][Hierarchy Panel] -Pos=0,142 -Size=387,918 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Inspector] -Pos=1649,48 -Size=271,1012 -Collapsed=0 -DockId=0x00000006,0 - -[Window][Profiler] -Pos=0,48 -Size=387,92 -Collapsed=0 -DockId=0x00000003,0 - -[Window][Viewport] -Pos=648,48 -Size=2519,1319 -Collapsed=0 -DockId=0x00000002,0 - -[Window][ Viewport] -Pos=389,48 -Size=1258,1012 -Collapsed=0 -DockId=0x00000002,0 - -[Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7 - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 - diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index a93148d5..54dc0ccf 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -56,8 +56,8 @@ namespace Sandbox _In_ INT nCmdShow ) { - // Set working directory - SHFileUtilities::SetWorkDirToExecDir(); + // Set working directory + SHFileUtilities::SetWorkDirToExecDir(); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); @@ -152,16 +152,16 @@ namespace Sandbox SHSceneManager::SceneUpdate(0.016f); #endif SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f); - //editor->PollPicking(); + editor->PollPicking(); } // Finish all graphics jobs first - graphicsSystem->AwaitGraphicsExecution(); + graphicsSystem->AwaitGraphicsExecution(); } void SBApplication::Exit(void) { - #ifdef SHEDITOR + #ifdef SHEDITOR SDL_DestroyWindow(sdlWindow); SDL_Quit(); #endif diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 27e46d98..972d4ae3 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -94,7 +94,7 @@ namespace SHADE if (ImGui::BeginMenuBar()) { - ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 40.0f); if(ImGui::SmallButton(ICON_MD_DESELECT)) { auto editor = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 08f5695b..0bbbe0dd 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -39,6 +39,10 @@ namespace SHADE { SHComponentManager::RemoveComponent(component->GetEID()); } + if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data())) + { + *component = T(); + } ImGui::EndPopup(); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index b06c37c7..cb30fa81 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -24,7 +24,7 @@ namespace SHADE void SHEditorViewport::Init() { SHEditorWindow::Init(); - + transformGizmo.Init(); } void SHEditorViewport::Update() diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp index a53b8c10..3c984051 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp @@ -13,6 +13,12 @@ #include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h" namespace SHADE { + void SHTransformGizmo::Init() + { + auto& style = ImGuizmo::GetStyle(); + style.RotationLineThickness = 2.5f; + } + void SHTransformGizmo::Draw() { bool justChangedTfm = false; @@ -26,9 +32,12 @@ namespace SHADE SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix()); SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix()); + + //Invert projection y-axis proj(1, 1) *= -1; + static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity; - //ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f); + if (selectedEntityTransformComponent == nullptr) { SHEditor* editor = SHSystemManager::GetSystem(); @@ -55,31 +64,37 @@ namespace SHADE return; SHMatrix mat = selectedEntityTransformComponent->GetTRS(); - isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11); - if (!justChangedTfm) + useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); + if(useSnap) { - if (ImGui::IsItemClicked()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - }))); - else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - })), true); + switch (operation) + { + case Operation::TRANSLATE: snap = &translationSnap.x; break; + case Operation::ROTATE: snap = &rotationSnap; break; + case Operation::SCALE: snap = &scaleSnap; break; + default: snap = &translationSnap.x; + } } + ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr); + static bool startRecording = false; + if (!justChangedTfm && ImGuizmo::IsUsing()) + { + + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx) + { + if (!tfm) + return; + SHVec3 translate{}, rotate{}, scale{}; + mtx.Decompose(translate, rotate, scale); + tfm->SetWorldPosition(translate); + tfm->SetWorldRotation(rotate); + tfm->SetWorldScale(scale); + })), startRecording); + if(!startRecording) + startRecording = true; + } + isManipulating = ImGuizmo::IsUsing() || startRecording; + if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; } } diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h index 2565575f..fd847335 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h @@ -37,11 +37,17 @@ namespace SHADE UNIVERSAL = TRANSLATE | ROTATE | SCALEU }; + void Init(); void Draw(); bool isManipulating = false; + bool useSnap = false; Mode mode = Mode::WORLD; Operation operation = Operation::TRANSLATE; private: + float scaleSnap = 0.25f; + float rotationSnap = 1.0f; + SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f); + float* snap = nullptr; SHTransformComponent* selectedEntityTransformComponent{nullptr}; SHCameraComponent* editorCamera{nullptr}; }; diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index aff1eaad..912f9d0f 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -134,7 +134,7 @@ namespace SHADE } } - PollPicking(); + //PollPicking(); if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) { diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 5788dc15..dc65d6c2 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -40,7 +40,6 @@ namespace SHADE { ImGui::BeginGroup(); - auto cursorPos = ImGui::GetCursorScreenPos(); auto itemSpacing = ImGui::GetStyle().ItemSpacing; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -175,7 +174,7 @@ namespace SHADE ImGui::SetColumnWidth(-1, 80.0f); ImGui::Text(fieldLabel.c_str()); if (isHovered) - *isHovered = ImGui::IsItemHovered(); + *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); for (std::size_t i = 0; i < N; ++i) { @@ -208,21 +207,16 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec2 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; return changed; } @@ -232,20 +226,20 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec3 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); + + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHVec3 old = get(); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(old, values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } return changed; @@ -256,20 +250,17 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec4 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } return changed; @@ -325,112 +316,116 @@ namespace SHADE float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - std::cout << value << " \n"; - //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); - - if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } template static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) + bool const changed = ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return changed; } static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + bool const changed = ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return changed; } static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + bool const changed = ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } - return false; } From 24c591ec27b186431ea145e7053d2d8542d23031 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 20:07:59 +0800 Subject: [PATCH 13/35] Modified Managed Transform Interface to use Quaternions --- SHADE_Managed/src/Components/Transform.cxx | 16 ++++++++-------- SHADE_Managed/src/Components/Transform.hxx | 21 ++++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx index 0f0716dc..41298c21 100644 --- a/SHADE_Managed/src/Components/Transform.cxx +++ b/SHADE_Managed/src/Components/Transform.cxx @@ -29,13 +29,13 @@ namespace SHADE { GetNativeComponent()->SetLocalPosition(Convert::ToNative(val)); } - Vector3 Transform::LocalRotation::get() + Quaternion Transform::LocalRotation::get() { - return Convert::ToCLI(GetNativeComponent()->GetLocalRotation()); + return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation()); } - void Transform::LocalRotation::set(Vector3 val) + void Transform::LocalRotation::set(Quaternion val) { - GetNativeComponent()->SetLocalRotation(Convert::ToNative(val)); + GetNativeComponent()->SetLocalOrientation(Convert::ToNative(val)); } Vector3 Transform::LocalScale::get() { @@ -54,13 +54,13 @@ namespace SHADE { GetNativeComponent()->SetWorldPosition(Convert::ToNative(val)); } - Vector3 Transform::GlobalRotation::get() + Quaternion Transform::GlobalRotation::get() { - return Convert::ToCLI(GetNativeComponent()->GetWorldRotation()); + return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation()); } - void Transform::GlobalRotation::set(Vector3 val) + void Transform::GlobalRotation::set(Quaternion val) { - GetNativeComponent()->SetWorldRotation(Convert::ToNative(val)); + GetNativeComponent()->SetWorldOrientation(Convert::ToNative(val)); } Vector3 Transform::GlobalScale::get() { diff --git a/SHADE_Managed/src/Components/Transform.hxx b/SHADE_Managed/src/Components/Transform.hxx index 9efd2927..43118b1f 100644 --- a/SHADE_Managed/src/Components/Transform.hxx +++ b/SHADE_Managed/src/Components/Transform.hxx @@ -17,14 +17,14 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Components/Component.hxx" #include "Math/Vector3.hxx" -#include "Utility/Convert.hxx" +#include "Math/Quaternion.hxx" // External Dependencies #include "Math/Transform/SHTransformComponent.h" namespace SHADE { /// - /// CLR version of the the SHADE Engine's TransformComponent. + /// CLR version of the SHADE Engine's TransformComponent. /// public ref class Transform : public Component { @@ -52,12 +52,12 @@ namespace SHADE void set(Vector3 val); } /// - /// Local Z-axis rotation angle stored by this Transform in Radians. + /// Local rotation quaternion stored by this Transform. /// - property Vector3 LocalRotation + property Quaternion LocalRotation { - Vector3 get(); - void set(Vector3 val); + Quaternion get(); + void set(Quaternion val); } /// /// Local scale stored by this Transform. @@ -76,16 +76,15 @@ namespace SHADE void set(Vector3 val); } /// - /// Global Z-axis rotation angle stored by this Transform in Radians. + /// Global rotation quaternion stored by this Transform. /// - property Vector3 GlobalRotation + property Quaternion GlobalRotation { - Vector3 get(); - void set(Vector3 val); + Quaternion get(); + void set(Quaternion val); } /// /// Global scale stored by this Transform. - /// Note that this operation is expensive. /// property Vector3 GlobalScale { From ff025f212cc93e3668dd435015c8bab632b7889f Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 22:41:36 +0800 Subject: [PATCH 14/35] Added Euler Angles properties to Managed Transforms --- SHADE_Managed/src/Components/Transform.cxx | 16 ++++++++++++++++ SHADE_Managed/src/Components/Transform.hxx | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx index 41298c21..98f0da4f 100644 --- a/SHADE_Managed/src/Components/Transform.cxx +++ b/SHADE_Managed/src/Components/Transform.cxx @@ -37,6 +37,14 @@ namespace SHADE { GetNativeComponent()->SetLocalOrientation(Convert::ToNative(val)); } + Vector3 Transform::LocalEulerAngles::get() + { + return Convert::ToCLI(GetNativeComponent()->GetLocalRotation()); + } + void Transform::LocalEulerAngles::set(Vector3 val) + { + GetNativeComponent()->SetLocalRotation(Convert::ToNative(val)); + } Vector3 Transform::LocalScale::get() { return Convert::ToCLI(GetNativeComponent()->GetLocalScale()); @@ -62,6 +70,14 @@ namespace SHADE { GetNativeComponent()->SetWorldOrientation(Convert::ToNative(val)); } + Vector3 Transform::GlobalEulerAngles::get() + { + return Convert::ToCLI(GetNativeComponent()->GetWorldRotation()); + } + void Transform::GlobalEulerAngles::set(Vector3 val) + { + GetNativeComponent()->SetWorldRotation(Convert::ToNative(val)); + } Vector3 Transform::GlobalScale::get() { return Convert::ToCLI(GetNativeComponent()->GetWorldScale()); diff --git a/SHADE_Managed/src/Components/Transform.hxx b/SHADE_Managed/src/Components/Transform.hxx index 43118b1f..bbe9fd19 100644 --- a/SHADE_Managed/src/Components/Transform.hxx +++ b/SHADE_Managed/src/Components/Transform.hxx @@ -60,6 +60,14 @@ namespace SHADE void set(Quaternion val); } /// + /// Local euler angle rotations stored by this Transform. + /// + property Vector3 LocalEulerAngles + { + Vector3 get(); + void set(Vector3 val); + } + /// /// Local scale stored by this Transform. /// property Vector3 LocalScale @@ -84,6 +92,14 @@ namespace SHADE void set(Quaternion val); } /// + /// Global euler angle rotations stored by this Transform. + /// + property Vector3 GlobalEulerAngles + { + Vector3 get(); + void set(Vector3 val); + } + /// /// Global scale stored by this Transform. /// property Vector3 GlobalScale From 8fb0eddcc1bfd795e6b0b1e4dfcd7579d7728d24 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Tue, 25 Oct 2022 00:00:22 +0800 Subject: [PATCH 15/35] Lights WIP --- Assets/Editor/Layouts/UserLayout.ini | 12 +- .../src/Graphics/Instance/SHVkInstance.cpp | 2 +- .../GlobalData/SHGraphicsGlobalData.cpp | 2 +- .../MiddleEnd/Interface/SHGraphicsConstants.h | 2 +- .../MiddleEnd/Lights/SHLightComponent.cpp | 109 ++++++++ .../MiddleEnd/Lights/SHLightComponent.h | 54 ++++ .../Graphics/MiddleEnd/Lights/SHLightData.cpp | 21 ++ .../Graphics/MiddleEnd/Lights/SHLightData.h | 55 ++++ .../MiddleEnd/Lights/SHLightingSubSystem.cpp | 250 ++++++++++++++++++ .../MiddleEnd/Lights/SHLightingSubSystem.h | 109 ++++++++ SHADE_Engine/src/Tools/SHUtilities.h | 9 + SHADE_Engine/src/Tools/SHUtilities.hpp | 6 + 12 files changed, 622 insertions(+), 9 deletions(-) create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index baced6b8..9add170c 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Hierarchy Panel] Pos=0,142 -Size=387,918 +Size=768,918 Collapsed=0 DockId=0x00000004,0 @@ -27,7 +27,7 @@ DockId=0x00000006,0 [Window][Profiler] Pos=0,48 -Size=387,92 +Size=768,92 Collapsed=0 DockId=0x00000003,0 @@ -38,17 +38,17 @@ Collapsed=0 DockId=0x00000002,0 [Window][ Viewport] -Pos=389,48 -Size=1258,1012 +Pos=770,48 +Size=877,1012 Collapsed=0 DockId=0x00000002,0 [Docking][Data] DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=768,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=877,1036 CentralNode=1 Selected=0xB41284E7 DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 diff --git a/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp b/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp index 191bc563..edfe4b46 100644 --- a/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp +++ b/SHADE_Engine/src/Graphics/Instance/SHVkInstance.cpp @@ -155,7 +155,7 @@ namespace SHADE SHVkDebugMessenger::GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE)); instanceDbgInfo.pfnUserCallback = SHVulkanDebugUtil::GenericDebugCallback; - instanceInfo.pNext = static_cast(&instanceDbgInfo); + //instanceInfo.pNext = static_cast(&instanceDbgInfo); } // Finally create the instance diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index d8b1bad1..ed1d3100 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -49,7 +49,7 @@ namespace SHADE { .Type = vk::DescriptorType::eStorageBufferDynamic, .Stage = vk::ShaderStageFlagBits::eFragment, - .BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA, + .BindPoint = SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA, .DescriptorCount = 1, }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index a0457b65..15f192c0 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -101,7 +101,7 @@ namespace SHADE */ /***************************************************************************/ - static constexpr uint32_t LIGHTS_DATA = 0; + static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0; /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp new file mode 100644 index 00000000..e3bcec58 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -0,0 +1,109 @@ +#include "SHpch.h" +#include "SHLightComponent.h" + +namespace SHADE +{ + + + void SHLightComponent::OnCreate(void) + { + lightData.Reset(); + SetType(SH_LIGHT_TYPE::DIRECTIONAL); + indexInBuffer = std::numeric_limits::max(); + Unbind(); + } + + + void SHLightComponent::OnDestroy(void) + { + + } + + void SHLightComponent::SetPosition(SHVec3 position) noexcept + { + lightData.position = position; + MakeDirty(); + } + + + void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept + { + lightData.type = type; + MakeDirty(); + } + + + void SHLightComponent::SetDirection(SHVec3 direction) noexcept + { + lightData.direction = direction; + MakeDirty(); + } + + + void SHLightComponent::SetDiffuseColor(SHVec4 diffuseColor) noexcept + { + lightData.diffuseColor = diffuseColor; + MakeDirty(); + } + + void SHLightComponent::ModifyLayer(uint8_t layerIndex, bool value) noexcept + { + if (value) + lightData.cullingMask |= (1u << layerIndex); + else + lightData.cullingMask &= ~(1u << layerIndex); + + MakeDirty(); + } + + + void SHLightComponent::SetAllLayers(void) noexcept + { + lightData.cullingMask = std::numeric_limits::max(); + MakeDirty(); + } + + + void SHLightComponent::ClearAllLayers(void) noexcept + { + lightData.cullingMask = 0; + MakeDirty(); + } + + void SHLightComponent::MakeDirty(void) noexcept + { + dirty = true; + } + + void SHLightComponent::ClearDirtyFlag(void) noexcept + { + dirty = false; + } + + void SHLightComponent::Unbind(void) noexcept + { + bound = false; + MakeDirty(); + } + + void SHLightComponent::SetBound(void) noexcept + { + bound = true; + } + + SHLightData const& SHLightComponent::GetLightData(void) const noexcept + { + return lightData; + } + + bool SHLightComponent::IsDirty(void) const noexcept + { + return dirty; + } + + bool SHLightComponent::GetBound(void) const noexcept + { + return bound; + } + +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h new file mode 100644 index 00000000..3b06a612 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h @@ -0,0 +1,54 @@ +#pragma once + +#include "ECS_Base/Components/SHComponent.h" +#include "SHLightData.h" + +namespace SHADE +{ + + class SH_API SHLightComponent final : public SHComponent + { + private: + //! General data for the light. This will purely be CPU bound. Whatever gets sent to the + //! GPU depends on the type of the light. + SHLightData lightData; + + //! Since the lighting system is gonna be self contained and light weight, we store this + //! so that we only write this to the CPU buffer when this light component change, we don't + //! rewrite everything. However we still write to the GPU buffer when everything changes. + uint32_t indexInBuffer; + + //! If the light component changed some value we mark this true. + bool dirty; + + //! If the light's data is already in the buffers, this will be set to true. + bool bound; + + public: + /*-----------------------------------------------------------------------*/ + /* LIFECYCLE FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void OnCreate (void) override final; + void OnDestroy (void) override final; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + void SetPosition (SHVec3 position) noexcept; + void SetType (SH_LIGHT_TYPE type) noexcept; + void SetDirection (SHVec3 direction) noexcept; + void SetDiffuseColor (SHVec4 diffuseColor) noexcept; + void ModifyLayer (uint8_t layerIndex, bool value) noexcept; + void SetAllLayers (void) noexcept; + void ClearAllLayers (void) noexcept; + void MakeDirty (void) noexcept; + void ClearDirtyFlag (void) noexcept; + void Unbind (void) noexcept; + void SetBound (void) noexcept; + + SHLightData const& GetLightData (void) const noexcept; + bool IsDirty (void) const noexcept; + bool GetBound (void) const noexcept; + + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp new file mode 100644 index 00000000..ba910408 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.cpp @@ -0,0 +1,21 @@ +#include "SHpch.h" +#include "SHLightData.h" + +namespace SHADE +{ + void SHLightData::Reset(void) noexcept + { + // no culling is done. + cullingMask = std::numeric_limits::max(); + + // reset position to 0 + position = SHVec3::Zero; + + // direction just point in positive z axis + direction = SHVec3::Forward; + + // Diffuse color set to 1 + diffuseColor = SHVec4::One; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h new file mode 100644 index 00000000..607978a4 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightData.h @@ -0,0 +1,55 @@ +#pragma once + +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" + +namespace SHADE +{ + enum class SH_LIGHT_TYPE : uint32_t + { + DIRECTIONAL = 0, + POINT, + SPOT, + NUM_TYPES + }; + + /***************************************************************************/ + /*! + + \class + Every light will essentially be using this struct. However, when passing + light data over to the GPU, the light data will be split according to + type for more optimal cache access. + + */ + /***************************************************************************/ + struct SHLightData + { + //! position of the light + SHVec3 position; + + //! Type of the light + SH_LIGHT_TYPE type; + + //! direction of the light + SHVec3 direction; + + //! Each bit in this 32 bit field will represent a layer. If the bit is set, + //! when a fragment is being evaluated, the shader will use the fragment's + //! layer value to AND with the light's. If result is 1, do lighting calculations. + uint32_t cullingMask; + + //! Diffuse color emitted by the light + SHVec4 diffuseColor; + + void Reset (void) noexcept; + //! TODO: + //! - Add cut off. (inner and outer). + //! - Add constant, linear and quadratic for attenuation + //! - Specular color if needed. see below. + + //! Specular color + //SHVec4 specularColor; + }; + +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp new file mode 100644 index 00000000..3d39ed89 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -0,0 +1,250 @@ +#include "SHpch.h" +#include "SHLightingSubSystem.h" +#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" +#include "Tools/SHUtilities.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Graphics/Buffers/SHVkBuffer.h" +#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" +#include "SHLightComponent.h" +#include "ECS_Base/Managers/SHComponentManager.h" + +namespace SHADE +{ + + /***************************************************************************/ + /*! + + \brief + Initializes type, intermediate data and buffer. dirty will be true. + + \param lightType + type of the light. + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::InitializeData(Handle logicalDevice, SH_LIGHT_TYPE type) noexcept + { + // initialize the type + lightType = type; + + // we want to write to GPU when system runs + dirty = true; + + // boilerplate + intermediateData = nullptr; + numLights = 0; + + // initialize alignment + lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type)); + + // So create some data! + Expand(logicalDevice); + } + + /***************************************************************************/ + /*! + + \brief + Expands both the CPU container and the GPU buffer when the number of + lights have exceeded + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::Expand(Handle logicalDevice) noexcept + { + // we want to wait for the command buffers to finish using the buffers first + logicalDevice->WaitIdle(); + + // this is for CPU buffer. + uint32_t structSize = GetLightTypeSize(lightType); + + // First time we are initializing lights + if (intermediateData == nullptr) + { + // num lights should start of at STARTING_NUM_LIGHTS lights + numLights = STARTING_NUM_LIGHTS; + + // Initialize the data for lights + intermediateData = std::make_unique(lightDataAlignmentSize * STARTING_NUM_LIGHTS); + + dataBuffer = logicalDevice->CreateBuffer(numLights * lightDataAlignmentSize, nullptr, numLights * lightDataAlignmentSize, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + } + else + { + // save old number of lights + uint32_t const OLD_NUM_LIGHTS = numLights; + + // before we increase the number of lights, create space to store old data. + std::unique_ptr oldData = std::make_unique(lightDataAlignmentSize * OLD_NUM_LIGHTS); + + // copy data over. + std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); + + // now we start to expand.... + + // double space for lights + numLights *= 2; + + // destroy old data and initialize container for double the amount of data. + intermediateData = std::make_unique(lightDataAlignmentSize * numLights); + + // copy old data to new container + std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); + + // Resize the GPU buffer + dataBuffer->ResizeReplace(lightDataAlignmentSize * numLights, oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); + + } + + } + + /***************************************************************************/ + /*! + + \brief + This function takes in a light comp in the event that its data has not + been placed in the buffer yet. It also checks if the size of the buffer + is big enough + + \param lightComp + + \return + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::AddLight(SHLightComponent* lightComp) noexcept + { + + } + + /***************************************************************************/ + /*! + + \brief + Gets the size required to store data for a light type. + + \param type + Type of a light. + + \return + Size required to store a light based on type. + + */ + /***************************************************************************/ + uint32_t SHLightingSubSystem::PerTypeData::GetLightTypeSize(SH_LIGHT_TYPE type) noexcept + { + switch (type) + { + case SH_LIGHT_TYPE::DIRECTIONAL: + // TOOD: Change after creating point light struct + return 0; + case SH_LIGHT_TYPE::POINT: + return sizeof (SHDirectionalLightData); + case SH_LIGHT_TYPE::SPOT: + // TOOD: Change after creating spot light struct + return 0; + case SH_LIGHT_TYPE::NUM_TYPES: + default: + return 0; + + } + } + + + Handle SHLightingSubSystem::PerTypeData::GetDataBuffer(void) const noexcept + { + return dataBuffer; + } + + + uint32_t SHLightingSubSystem::PerTypeData::GetAlignmentSize(void) const noexcept + { + return lightDataAlignmentSize; + } + + void SHLightingSubSystem::UpdateDescSet(uint32_t binding) noexcept + { + auto buffer = perTypeData[binding].GetDataBuffer(); + + // We bind the buffer with the correct desc set binding + lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, + binding, + { &buffer, 1 }, + 0, + perTypeData[binding].GetAlignmentSize()); + + lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding); + } + + /***************************************************************************/ + /*! + + \brief + Initializes per light type data. This includes buffers and descriptor + sets. + + + */ + /***************************************************************************/ + void SHLightingSubSystem::Init(Handle logicalDevice, Handle descPool) noexcept + { + std::vector variableSizes{ SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES) }; + std::fill (variableSizes.begin(), variableSizes.end(), 1); + + // Create the descriptor set + lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes); + + // initialize all the data first. We add more lights here as we add more types. + perTypeData[SHUtilities::ToUnderlying(SH_LIGHT_TYPE::DIRECTIONAL)].InitializeData(logicalDevice, SH_LIGHT_TYPE::DIRECTIONAL); + UpdateDescSet(SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA); + } + + /***************************************************************************/ + /*! + + \brief + Loops through every single light component and checks for dirty light + data. If light data is dirty, rewrite to the CPU container and do a + copy to the GPU data. We also check if the per light type data is too small + to handle more lights, if it is, expand buffer (both CPU and GPU). + + */ + /***************************************************************************/ + void SHLightingSubSystem::Run(void) noexcept + { + auto& lightComps = SHComponentManager::GetDense(); + for (auto& light : lightComps) + { + // First we want to make sure the light is already bound to the system. if it + // isn't, we write it to the correct buffer. + if (!light.GetBound()) + { + + + light.SetBound(); + } + + // if there was modification to the light data + if (light.IsDirty()) + { + + } + } + + } + + /***************************************************************************/ + /*! + + \brief + Does nothing for now. + + */ + /***************************************************************************/ + void SHLightingSubSystem::Exit(void) noexcept + { + + } + + +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h new file mode 100644 index 00000000..4c99354f --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h @@ -0,0 +1,109 @@ +#pragma once + +#include "Resource/SHHandle.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" +#include "SHLightData.h" + +namespace SHADE +{ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetGroup; + class SHVkDescriptorSetLayout; + class SHVkBuffer; + + // Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU. + struct SHDirectionalLightData + { + //! Direction of the light + SHVec3 direction; + + //! Each bit in this 32 bit field will represent a layer. If the bit is set, + //! when a fragment is being evaluated, the shader will use the fragment's + //! layer value to AND with the light's. If result is 1, do lighting calculations. + uint32_t cullingMask; + + //! Diffuse color emitted by the light + SHVec4 diffuseColor; + + }; + + class SHLightingSubSystem + { + private: + + class PerTypeData + { + private: + /*-----------------------------------------------------------------------*/ + /* STATIC MEMBER VARIABLES */ + /*-----------------------------------------------------------------------*/ + static constexpr uint32_t STARTING_NUM_LIGHTS = 20; + + /*-----------------------------------------------------------------------*/ + /* PRIVATE MEMBER VARIABLES */ + /*-----------------------------------------------------------------------*/ + + //! SSBOs need to be aligned. This is to pad lighting structs + uint32_t lightDataAlignmentSize; + + //! type of the light. Will be used later when we want to expand + SH_LIGHT_TYPE lightType; + + //! number of lights currently alive. + uint32_t numLights; + + //! if intermediateData has been modified(i.e. any 1 light's data is changed), set to true. + bool dirty; + + //! GPU buffer required to store GPU data + Handle dataBuffer; + + //! Before data gets copied to the GPU, it goes into here first. Data here is aligned to whatever struct is + //! used to represent data in this container. + std::unique_ptr intermediateData; + + public: + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void InitializeData (Handle logicalDevice, SH_LIGHT_TYPE type) noexcept; + void Expand (Handle logicalDevice) noexcept; + void AddLight (SHLightComponent* lightComp) noexcept; + + /*-----------------------------------------------------------------------*/ + /* GETTERS */ + /*-----------------------------------------------------------------------*/ + static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept; + Handle GetDataBuffer (void) const noexcept; + uint32_t GetAlignmentSize (void) const noexcept; + }; + + private: + + //! logical device used for creation + Handle logicalDevice; + + //! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required. + Handle lightingDataDescSet; + + //! Each type will have some data associated with it for processing + std::array(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData; + + /*-----------------------------------------------------------------------*/ + /* PRIVATE MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void UpdateDescSet (uint32_t binding) noexcept; + + public: + + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void Init (Handle logicalDevice, Handle descPool) noexcept; + void Run (void) noexcept; + void Exit (void) noexcept; + + }; +} diff --git a/SHADE_Engine/src/Tools/SHUtilities.h b/SHADE_Engine/src/Tools/SHUtilities.h index 543c771c..b3d840e7 100644 --- a/SHADE_Engine/src/Tools/SHUtilities.h +++ b/SHADE_Engine/src/Tools/SHUtilities.h @@ -42,6 +42,15 @@ namespace SHADE template static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept; + /** + * @brief Converts an enum class member from it's type to the underlying type. + * @tparam Enum Restricted to an enum class + * @param[in] value A member of the specified enum class. + * @returns The value of the enum class member in the output type. + */ + template + static constexpr typename std::underlying_type_t ToUnderlying (Enum value) noexcept; + }; } // namespace SHADE diff --git a/SHADE_Engine/src/Tools/SHUtilities.hpp b/SHADE_Engine/src/Tools/SHUtilities.hpp index 0e21a9d0..e0404ea1 100644 --- a/SHADE_Engine/src/Tools/SHUtilities.hpp +++ b/SHADE_Engine/src/Tools/SHUtilities.hpp @@ -25,4 +25,10 @@ namespace SHADE return static_cast(enumClassMember); } + template + constexpr typename std::underlying_type_t SHUtilities::ToUnderlying(Enum value) noexcept + { + return static_cast>(value); + } + } // namespace SHADE \ No newline at end of file From 869916cb2a94e64050acaadfdd8ae559fba47116 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Tue, 25 Oct 2022 13:47:27 +0800 Subject: [PATCH 16/35] Lights WIP --- .../MiddleEnd/Lights/SHLightComponent.cpp | 18 +- .../MiddleEnd/Lights/SHLightComponent.h | 14 +- .../MiddleEnd/Lights/SHLightingSubSystem.cpp | 267 ++++++++++++++---- .../MiddleEnd/Lights/SHLightingSubSystem.h | 39 ++- 4 files changed, 266 insertions(+), 72 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp index e3bcec58..fd122334 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.cpp @@ -10,6 +10,7 @@ namespace SHADE lightData.Reset(); SetType(SH_LIGHT_TYPE::DIRECTIONAL); indexInBuffer = std::numeric_limits::max(); + active = true; Unbind(); } @@ -86,9 +87,17 @@ namespace SHADE MakeDirty(); } - void SHLightComponent::SetBound(void) noexcept - { + void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept +{ bound = true; + indexInBuffer = inIndexInBuffer; + } + + void SHLightComponent::SetActive(bool flag) noexcept + { + MakeDirty(); + active = flag; + } SHLightData const& SHLightComponent::GetLightData(void) const noexcept @@ -106,4 +115,9 @@ namespace SHADE return bound; } + uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept + { + return indexInBuffer; + } + } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h index 3b06a612..20ae3892 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightComponent.h @@ -23,6 +23,9 @@ namespace SHADE //! If the light's data is already in the buffers, this will be set to true. bool bound; + + //! If the light is active, this is true. + bool active; public: /*-----------------------------------------------------------------------*/ @@ -44,11 +47,14 @@ namespace SHADE void MakeDirty (void) noexcept; void ClearDirtyFlag (void) noexcept; void Unbind (void) noexcept; - void SetBound (void) noexcept; + void SetBound (uint32_t inIndexInBuffer) noexcept; + void SetActive (bool flag) noexcept; + - SHLightData const& GetLightData (void) const noexcept; - bool IsDirty (void) const noexcept; - bool GetBound (void) const noexcept; + SHLightData const& GetLightData (void) const noexcept; + bool IsDirty (void) const noexcept; + bool GetBound (void) const noexcept; + uint32_t GetIndexInBuffer (void) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 3d39ed89..613d50d3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -7,9 +7,55 @@ #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "SHLightComponent.h" #include "ECS_Base/Managers/SHComponentManager.h" +#include "SHLightComponent.h" namespace SHADE { + /***************************************************************************/ + /*! + + \brief + This function takes an address in the CPU container and writes light + component data to it. What gets written depends on the light type. + + \param address + The address to write to. + + \param lightComp + The light component with the data to write from. + + \param lightType + The type of the light + + \return + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept + { + auto const& lightData = lightComp->GetLightData(); + switch (lightData.type) + { + case SH_LIGHT_TYPE::DIRECTIONAL: + { + SHDirectionalLightData* lightPtr = reinterpret_cast(address); + + lightPtr->cullingMask = lightData.cullingMask; + lightPtr->direction = lightData.direction; + lightPtr->diffuseColor = lightData.diffuseColor; + break; + } + case SH_LIGHT_TYPE::POINT: + break; + case SH_LIGHT_TYPE::SPOT: + break; + case SH_LIGHT_TYPE::NUM_TYPES: + break; + default: + break; + + } + } /***************************************************************************/ /*! @@ -27,12 +73,8 @@ namespace SHADE // initialize the type lightType = type; - // we want to write to GPU when system runs - dirty = true; - // boilerplate intermediateData = nullptr; - numLights = 0; // initialize alignment lightDataAlignmentSize = logicalDevice->PadSSBOSize(GetLightTypeSize(type)); @@ -46,7 +88,7 @@ namespace SHADE \brief Expands both the CPU container and the GPU buffer when the number of - lights have exceeded + lights have exceeded the capacity. */ /***************************************************************************/ @@ -55,66 +97,46 @@ namespace SHADE // we want to wait for the command buffers to finish using the buffers first logicalDevice->WaitIdle(); - // this is for CPU buffer. - uint32_t structSize = GetLightTypeSize(lightType); - // First time we are initializing lights if (intermediateData == nullptr) { - // num lights should start of at STARTING_NUM_LIGHTS lights - numLights = STARTING_NUM_LIGHTS; + // max lights should start of at STARTING_NUM_LIGHTS lights + maxLights = STARTING_NUM_LIGHTS; + numLights = 0; // Initialize the data for lights - intermediateData = std::make_unique(lightDataAlignmentSize * STARTING_NUM_LIGHTS); + intermediateData = std::make_unique(lightDataAlignmentSize * maxLights); - dataBuffer = logicalDevice->CreateBuffer(numLights * lightDataAlignmentSize, nullptr, numLights * lightDataAlignmentSize, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); + // We want to initialize 3 times the amount of data required. + dataBuffer = logicalDevice->CreateBuffer(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); } else { // save old number of lights - uint32_t const OLD_NUM_LIGHTS = numLights; + uint32_t const OLD_MAX_LIGHTS = maxLights; // before we increase the number of lights, create space to store old data. - std::unique_ptr oldData = std::make_unique(lightDataAlignmentSize * OLD_NUM_LIGHTS); + std::unique_ptr oldData = std::make_unique(lightDataAlignmentSize * OLD_MAX_LIGHTS); // copy data over. - std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); + std::memcpy (oldData.get(), intermediateData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); // now we start to expand.... // double space for lights - numLights *= 2; + maxLights *= 2; // destroy old data and initialize container for double the amount of data. - intermediateData = std::make_unique(lightDataAlignmentSize * numLights); + intermediateData = std::make_unique(lightDataAlignmentSize * maxLights); // copy old data to new container - std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); - - // Resize the GPU buffer - dataBuffer->ResizeReplace(lightDataAlignmentSize * numLights, oldData.get(), lightDataAlignmentSize * OLD_NUM_LIGHTS); + std::memcpy(intermediateData.get(), oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); + // Resize the GPU buffer. TODO: Replace with Resize no copy here + dataBuffer->ResizeReplace(maxLights * lightDataAlignmentSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, oldData.get(), lightDataAlignmentSize * OLD_MAX_LIGHTS); } - } - - /***************************************************************************/ - /*! - - \brief - This function takes in a light comp in the event that its data has not - been placed in the buffer yet. It also checks if the size of the buffer - is big enough - \param lightComp - - \return - - */ - /***************************************************************************/ - void SHLightingSubSystem::PerTypeData::AddLight(SHLightComponent* lightComp) noexcept - { - } /***************************************************************************/ @@ -162,20 +184,128 @@ namespace SHADE return lightDataAlignmentSize; } + uint32_t SHLightingSubSystem::PerTypeData::GetNumLights(void) const noexcept + { + return numLights; + } + + uint32_t SHLightingSubSystem::PerTypeData::GetMaxLights(void) const noexcept + { + return maxLights; + } + + + /***************************************************************************/ + /*! + + \brief + This function takes in a light comp in the event that its data has not + been placed in the buffer yet. It also checks if the size of the buffer + is big enough to hold the new light. If the buffer is too small, expand + it. + + \param lightComp + The light component to add. + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::AddLight(Handle logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept + { + if (unboundLight) + { + // capacity is full + if (numLights == maxLights) + { + // expand first + Expand(logicalDevice); + + expanded = true; + } + + // Now that the container is big enough, bind the new light + + // Get address of write location + void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignmentSize * numLights); + + // Write the light data to address + WriteLightToAddress(writeLocation, unboundLight); + + // Set the light component to be bound to that location + unboundLight->SetBound(numLights); + + // Increase light count + ++numLights; + } + } + + /***************************************************************************/ + /*! + + \brief + Modify the data at a specific light address. + + \param lightComp + The light component to write. + + */ + /***************************************************************************/ + void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept + { + void* writeLocation = reinterpret_cast(intermediateData.get()) + (lightDataAlignmentSize * lightComp->GetIndexInBuffer()); + WriteLightToAddress(writeLocation, lightComp); + } + + void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept + { + // we want to write to the offset of the current frame + dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex); + } + + /***************************************************************************/ + /*! + + \brief + Update descriptor sets. We want to call this everytime we expand buffers. + + \param binding + The binding in the set we want to update. + + */ + /***************************************************************************/ void SHLightingSubSystem::UpdateDescSet(uint32_t binding) noexcept { auto buffer = perTypeData[binding].GetDataBuffer(); // We bind the buffer with the correct desc set binding lightingDataDescSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, - binding, - { &buffer, 1 }, - 0, - perTypeData[binding].GetAlignmentSize()); + binding, + { &buffer, 1 }, + 0, + perTypeData[binding].GetAlignmentSize()); lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding); } + /***************************************************************************/ + /*! + + \brief + Computes dynamic offsets. + + */ + /***************************************************************************/ + void SHLightingSubSystem::ComputeDynamicOffsets(void) noexcept + { + for (uint32_t i = 0; i < dynamicOffsets.size(); ++i) + { + auto const& typeData = perTypeData[i]; + for (uint32_t j = 0; j < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++j) + { + dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights(); + } + } + } + /***************************************************************************/ /*! @@ -186,8 +316,10 @@ namespace SHADE */ /***************************************************************************/ - void SHLightingSubSystem::Init(Handle logicalDevice, Handle descPool) noexcept + void SHLightingSubSystem::Init(Handle device, Handle descPool) noexcept { + logicalDevice = device; + std::vector variableSizes{ SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES) }; std::fill (variableSizes.begin(), variableSizes.end(), 1); @@ -197,6 +329,7 @@ namespace SHADE // initialize all the data first. We add more lights here as we add more types. perTypeData[SHUtilities::ToUnderlying(SH_LIGHT_TYPE::DIRECTIONAL)].InitializeData(logicalDevice, SH_LIGHT_TYPE::DIRECTIONAL); UpdateDescSet(SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA); + } /***************************************************************************/ @@ -204,33 +337,61 @@ namespace SHADE \brief Loops through every single light component and checks for dirty light - data. If light data is dirty, rewrite to the CPU container and do a - copy to the GPU data. We also check if the per light type data is too small - to handle more lights, if it is, expand buffer (both CPU and GPU). + data. If light data is dirty, rewrite to the CPU container. We also want + to bind the descriptor set for the light data. */ /***************************************************************************/ - void SHLightingSubSystem::Run(void) noexcept + void SHLightingSubSystem::Run(Handle cmdBuffer, uint32_t frameIndex) noexcept { auto& lightComps = SHComponentManager::GetDense(); + bool expanded = false; for (auto& light : lightComps) { + auto enumValue = SHUtilities::ToUnderlying(light.GetLightData().type); + // First we want to make sure the light is already bound to the system. if it // isn't, we write it to the correct buffer. if (!light.GetBound()) { - - - light.SetBound(); + perTypeData[enumValue].AddLight(logicalDevice, &light, expanded); } // if there was modification to the light data if (light.IsDirty()) { - + // Write the data to the CPU + perTypeData[enumValue].ModifyLight(&light); + + // Light is now updated in the container + light.ClearDirtyFlag(); } } + // Write data to GPU + for (auto& data : perTypeData) + { + data.WriteToGPU(frameIndex); + } + + // If any of the buffers got expanded, the descriptor set is invalid because the expanded buffer + // is a new buffer. If some expansion was detected, update descriptor sets. + if (expanded) + { + uint32_t numLightTyes = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); + for (uint32_t i = 0; i < numLightTyes; ++i) + { + UpdateDescSet(i); + } + } + + // compute dynamic offsets. We don't actually have to compute every frame but its pretty lightweight, + // so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing. + ComputeDynamicOffsets(); + + // Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data). + cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]}); + } /***************************************************************************/ @@ -245,6 +406,4 @@ namespace SHADE { } - - } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h index 4c99354f..e5336b4e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.h @@ -4,6 +4,7 @@ #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" #include "SHLightData.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" namespace SHADE { @@ -12,6 +13,8 @@ namespace SHADE class SHVkDescriptorSetGroup; class SHVkDescriptorSetLayout; class SHVkBuffer; + class SHLightComponent; + class SHVkCommandBuffer; // Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU. struct SHDirectionalLightData @@ -19,6 +22,9 @@ namespace SHADE //! Direction of the light SHVec3 direction; + //! Represents if the light is active or not + uint32_t active; + //! Each bit in this 32 bit field will represent a layer. If the bit is set, //! when a fragment is being evaluated, the shader will use the fragment's //! layer value to AND with the light's. If result is 1, do lighting calculations. @@ -29,7 +35,7 @@ namespace SHADE }; - class SHLightingSubSystem + class SH_API SHLightingSubSystem { private: @@ -44,6 +50,8 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*-----------------------------------------------------------------------*/ + //! Capacity of the container. + uint32_t maxLights; //! SSBOs need to be aligned. This is to pad lighting structs uint32_t lightDataAlignmentSize; @@ -54,23 +62,24 @@ namespace SHADE //! number of lights currently alive. uint32_t numLights; - //! if intermediateData has been modified(i.e. any 1 light's data is changed), set to true. - bool dirty; - //! GPU buffer required to store GPU data Handle dataBuffer; //! Before data gets copied to the GPU, it goes into here first. Data here is aligned to whatever struct is - //! used to represent data in this container. + //! used to represent data in this container. Note this will store only 1 copy of all the lights, compared + //! to the GPU that stores NUM_FRAME_BUFFERS copies. std::unique_ptr intermediateData; + void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept; public: /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void InitializeData (Handle logicalDevice, SH_LIGHT_TYPE type) noexcept; void Expand (Handle logicalDevice) noexcept; - void AddLight (SHLightComponent* lightComp) noexcept; + void AddLight (Handle logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept; + void ModifyLight (SHLightComponent* lightComp) noexcept; + void WriteToGPU (uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS */ @@ -78,31 +87,37 @@ namespace SHADE static uint32_t GetLightTypeSize (SH_LIGHT_TYPE type) noexcept; Handle GetDataBuffer (void) const noexcept; uint32_t GetAlignmentSize (void) const noexcept; + uint32_t GetNumLights (void) const noexcept; + uint32_t GetMaxLights (void) const noexcept; }; private: //! logical device used for creation - Handle logicalDevice; + Handle logicalDevice; //! The descriptor set that will hold the lighting data. Each binding will hold a buffer, NUM_FRAMES times the size required. - Handle lightingDataDescSet; + Handle lightingDataDescSet; //! Each type will have some data associated with it for processing - std::array(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData; + std::array(SH_LIGHT_TYPE::NUM_TYPES)> perTypeData; + + //! Container to store dynamic offsets for binding descriptor sets + std::array, static_cast(SHGraphicsConstants::NUM_FRAME_BUFFERS)> dynamicOffsets; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void UpdateDescSet (uint32_t binding) noexcept; + void UpdateDescSet (uint32_t binding) noexcept; + void ComputeDynamicOffsets (void) noexcept; public: /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle logicalDevice, Handle descPool) noexcept; - void Run (void) noexcept; + void Init (Handle device, Handle descPool) noexcept; + void Run (Handle cmdBuffer, uint32_t frameIndex) noexcept; void Exit (void) noexcept; }; From c2e51dc603118eb025aa95b4fcf64f44cc5cfca9 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 14:31:28 +0800 Subject: [PATCH 17/35] Fixed deletion crash caused by Renderables --- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 74 ++++++++++++------- .../src/Graphics/MiddleEnd/Batching/SHBatch.h | 2 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 4 +- .../MiddleEnd/Interface/SHRenderable.cpp | 24 +++--- .../MiddleEnd/Interface/SHRenderable.h | 4 +- 5 files changed, 67 insertions(+), 41 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 40826047..24dd76c5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -59,7 +59,7 @@ namespace SHADE } // Add renderable in - subBatch->Renderables.insert(renderable); + subBatch->Renderables.insert(renderable->GetEID()); // Also add material instance in referencedMatInstances.insert(renderable->GetMaterial()); @@ -80,27 +80,34 @@ namespace SHADE if (subBatch == subBatches.end()) return; - subBatch->Renderables.erase(renderable); + subBatch->Renderables.erase(renderable->GetEID()); // Check if other renderables in subBatches contain the same material instance bool matUnused = true; for (const auto& sb : subBatches) - for (const auto& rend : sb.Renderables) + for (const auto& rendId : sb.Renderables) { - if (rend->GetMaterial() == renderable->GetMaterial()) + auto rend = SHComponentManager::GetComponent(rendId); + if (rend) { - matUnused = false; - break; + if (rend->GetMaterial() == renderable->GetMaterial()) + { + matUnused = false; + break; + } + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } } // Material is no longer in this library, so we remove it if (matUnused) - referencedMatInstances.erase(renderable->GetMaterial()); + referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); // Mark all as dirty - for (bool& dirt : isDirty) - dirt = true; + setAllDirtyFlags(); } void SHBatch::Clear() @@ -162,9 +169,17 @@ namespace SHADE // Build CPU Buffer char* propsCurrPtr = matPropsData.get(); for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); + const SHRenderable* renderable = SHComponentManager::GetComponent(rendId); + if (renderable) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); + } propsCurrPtr += singleMatPropAlignedSize; } @@ -188,18 +203,18 @@ namespace SHADE // Populate on the CPU for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { // Transform - auto transform = SHComponentManager::GetComponent(renderable->GetEID()); - if (!transform) + auto transform = SHComponentManager::GetComponent(rendId); + if (transform) { - SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); - transformData.emplace_back(); + transformData.emplace_back(transform->GetTRS()); } else { - transformData.emplace_back(transform->GetTRS()); + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); } } @@ -221,10 +236,10 @@ namespace SHADE // Populate on the CPU for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) - { - eidData.emplace_back(renderable->GetEID()); - } + for (auto rendId : subBatch.Renderables) + { + eidData.emplace_back(rendId); + } // Transfer to GPU if (eidBuffer[frameIndex]) @@ -305,11 +320,10 @@ namespace SHADE }); // Fill in buffers (CPU) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { // Transform - EntityID eid = renderable->GetEID(); - auto transform = SHComponentManager::GetComponent_s(eid); + auto transform = SHComponentManager::GetComponent_s(rendId); if (!transform) { SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); @@ -320,12 +334,20 @@ namespace SHADE transformData.emplace_back(transform->GetTRS()); } - eidData.emplace_back(eid); + eidData.emplace_back(rendId); // Material Properties if (!EMPTY_MAT_PROPS) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); + const SHRenderable* renderable = SHComponentManager::GetComponent(rendId); + if (renderable) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); + } propsCurrPtr += singleMatPropAlignedSize; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index 193fff0d..fa18fad5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -55,7 +55,7 @@ namespace SHADE /* Data Members */ /*-----------------------------------------------------------------------------*/ Handle Mesh; - std::unordered_set Renderables; + std::unordered_set Renderables; }; /***********************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 7ecd92d2..4280cafd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -677,10 +677,10 @@ namespace SHADE continue; // Remove from old material's SuperBatch - Handle prevMaterial = renderable.GetPrevMaterial(); + Handle prevMaterial = renderable.GetPrevMaterial(); if (prevMaterial) { - Handle oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + Handle oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); oldSuperBatch->Remove(&renderable); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 0b1c1b66..9dcd391d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -31,15 +31,16 @@ namespace SHADE void SHRenderable::OnDestroy() { + // Remove from SuperBatch + Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + superBatch->Remove(this); + + // Free resources if (material) { material.Free(); material = {}; } - - // Remove from SuperBatch - Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); - superBatch->Remove(this); } /*-----------------------------------------------------------------------------------*/ @@ -51,20 +52,23 @@ namespace SHADE if (!material && sharedMaterial == materialInstance) return; + // Flag that material was changed + materialChanged = true; + // Free copies of materials if any if (material) { + oldMaterial = material; material.Free(); material = {}; } - - // Flag that material was changed - materialChanged = true; - if (sharedMaterial) - oldMaterial = sharedMaterial->GetBaseMaterial(); + else if (sharedMaterial) + { + oldMaterial = sharedMaterial; + } // Update the material - sharedMaterial = materialInstance; + sharedMaterial = materialInstance; } Handle SHRenderable::GetMaterial() const diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index bc885ca2..5312cf82 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -55,7 +55,7 @@ namespace SHADE /* Getter Functions */ /*-------------------------------------------------------------------------------*/ bool WasMaterialChanged() const noexcept { return materialChanged; } - Handle GetPrevMaterial() const noexcept { return oldMaterial; } + Handle GetPrevMaterial() const noexcept { return oldMaterial; } /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ @@ -74,7 +74,7 @@ namespace SHADE Handle sharedMaterial; Handle material; bool materialChanged = true; - Handle oldMaterial; + Handle oldMaterial; }; } From 9f98bed4d15b85bd8aae1a6909e4045030fc278e Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 15:11:01 +0800 Subject: [PATCH 18/35] Fixed batching renedering the wrong number of instances --- SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 24dd76c5..012d9526 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -310,14 +310,16 @@ namespace SHADE for (auto& subBatch : subBatches) { // Create command + const uint32_t CURR_INSTANCES = static_cast(subBatch.Renderables.size()); drawData.emplace_back(vk::DrawIndexedIndirectCommand { .indexCount = subBatch.Mesh->IndexCount, - .instanceCount = static_cast(subBatch.Renderables.size()), + .instanceCount = CURR_INSTANCES, .firstIndex = subBatch.Mesh->FirstIndex, .vertexOffset = subBatch.Mesh->FirstVertex, - .firstInstance = nextInstanceIndex++ + .firstInstance = nextInstanceIndex }); + nextInstanceIndex += CURR_INSTANCES; // Fill in buffers (CPU) for (auto rendId : subBatch.Renderables) From da167ec3a58acff2152dd633edd86e994e59851f Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 15:39:18 +0800 Subject: [PATCH 19/35] Added .editorconfig to enforce 2-spacing indentation --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..29c5e400 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*.{c,cpp,h,hpp}] +indent_style = space +indent_size = 2 \ No newline at end of file From 0acd6a99a43fd3a3e51cf2abc5fb7d13ed6af725 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 17:08:15 +0800 Subject: [PATCH 20/35] Tweaks to editor widgets --- .../HierarchyPanel/SHHierarchyPanel.cpp | 3 +- .../Inspector/SHEditorComponentView.hpp | 21 +++-- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 84 ++++++++++++++++--- 3 files changed, 87 insertions(+), 21 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 972d4ae3..f2f8d927 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -93,8 +93,7 @@ namespace SHADE { if (ImGui::BeginMenuBar()) { - - ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 40.0f); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f); if(ImGui::SmallButton(ICON_MD_DESELECT)) { auto editor = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 0bbbe0dd..7fa39d74 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -52,7 +52,7 @@ namespace SHADE if (!component) return; const auto componentType = rttr::type::get(*component); - SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); if (ImGui::CollapsingHeader(componentType.get_name().data())) { @@ -93,7 +93,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin && metaMax) { - SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); } else { @@ -119,7 +119,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -132,7 +132,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMin.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMax.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -145,7 +145,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -156,13 +156,18 @@ namespace SHADE { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); + float min{}, max{}; + if(metaMin.is_valid()) + min = std::max(metaMin.template get_value(), -FLT_MAX * 0.5f); + if(metaMax.is_valid()) + max = std::min(metaMax.template get_value(), FLT_MAX * 0.5f); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test"); } } else if (type == rttr::type::get()) @@ -171,7 +176,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); } else { diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index dc65d6c2..4a299d25 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -203,7 +203,7 @@ namespace SHADE } static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec2 values = get(); @@ -217,12 +217,20 @@ namespace SHADE } if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) startRecording = false; - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); @@ -241,12 +249,20 @@ namespace SHADE { startRecording = false; } - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); @@ -262,7 +278,15 @@ namespace SHADE { startRecording = false; } - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } @@ -270,14 +294,38 @@ namespace SHADE //|| Widget Extensions || //#==============================================================# - static bool CheckBox(std::string const& label, std::function get, std::function set) + static void TextLabel(std::string_view const& text, bool sameLine = true) + { + const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true); + if(textSize.x > 0.0f) + { + ImGui::Text(text.data()); + ImGui::SameLine(); + } + } + + static bool CheckBox(std::string_view const& label, std::function get, std::function set, std::string_view const& tooltip = {}) { bool value = get(); - if (ImGui::Checkbox(label.c_str(), &value)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::Checkbox("##", &value)) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); return true; } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return false; } @@ -331,11 +379,14 @@ namespace SHADE return hasChange; } - static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, + static bool DragFloat(const std::string_view& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - const bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -347,6 +398,17 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } @@ -389,7 +451,7 @@ namespace SHADE return changed; } - static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, + static bool SliderFloat(const std::string& fieldLabel, float const& min, float const& max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); From 416c571fd2259bb616a04648f249985ec6ee6f03 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 17:40:13 +0800 Subject: [PATCH 21/35] Added proper deletion of VKSamplers --- SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp index 4300f2bd..7443b6e2 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp @@ -49,7 +49,7 @@ namespace SHADE SHVkSampler::~SHVkSampler() noexcept { if (vkSampler) - device->GetVkLogicalDevice().destroySampler(); + device->GetVkLogicalDevice().destroySampler(vkSampler); } /*-----------------------------------------------------------------------------------*/ From d1d64ec167ff76e727057d2e0725d36575ae459f Mon Sep 17 00:00:00 2001 From: Glence Date: Tue, 25 Oct 2022 18:48:45 +0800 Subject: [PATCH 22/35] added tooltips for the rest of the widgets --- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 178 ++++++++++++++++---- 1 file changed, 144 insertions(+), 34 deletions(-) diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 4a299d25..b54a6799 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -157,7 +157,7 @@ namespace SHADE } template - static bool DragN(const std::string& fieldLabel, std::vectorconst& componentLabels, + static bool DragN(const std::string& label, std::vectorconst& componentLabels, std::vector values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), ImGuiSliderFlags flags = 0, bool* isHovered = nullptr) { @@ -168,11 +168,11 @@ namespace SHADE const ImGuiContext& g = *GImGui; bool valueChanged = false; ImGui::BeginGroup(); - ImGui::PushID(fieldLabel.c_str()); + ImGui::PushID(label.c_str()); PushMultiItemsWidthsAndLabels(componentLabels, 0.0f); ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); ImGui::SetColumnWidth(-1, 80.0f); - ImGui::Text(fieldLabel.c_str()); + ImGui::Text(label.c_str()); if (isHovered) *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); @@ -202,12 +202,12 @@ namespace SHADE return valueChanged; } - static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec2(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec2 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; if (changed) { @@ -229,12 +229,12 @@ namespace SHADE return changed; } - static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec3(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; @@ -261,12 +261,12 @@ namespace SHADE return changed; } - static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec4(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; if (changed) { @@ -330,41 +330,72 @@ namespace SHADE } template - static bool RadioButton(std::vector const& listLabels, std::vector const& listTypes, std::function get, std::function set) + static bool RadioButton(std::vector const& label, std::vector const& listTypes, std::function get, std::function set ,std::string_view const& tooltip = {}) { T type = get(); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); for (size_t i = 0; i < listTypes.size(); i++) { - if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i])) + if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i])) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), listTypes[i], set)), false); } ImGui::SameLine(); } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return true; } static bool InputText(const std::string& label, const std::function get, - const std::function set, ImGuiInputTextFlags flag = 0, - ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) + const std::function set, std::string_view const& tooltip = {}, + ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) { std::string text = get(); - if (ImGui::InputText(label.c_str(), &text, flag, callback, userData)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::InputText("##", &text, flag, callback, userData)) { if (ImGui::IsItemDeactivatedAfterEdit()) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), text, set)), false); return true; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return false; } template - static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function get, std::function set, - float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) + static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function get, std::function set, + float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0) { T value = get(); - const bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -376,6 +407,17 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } @@ -412,11 +454,14 @@ namespace SHADE return hasChange; } - static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, + static bool DragInt(const std::string& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - const bool hasChange = ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -428,16 +473,30 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } template - static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, + static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - bool const changed = ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); if (!startRecording) @@ -448,16 +507,30 @@ namespace SHADE { startRecording = false; } - return changed; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderFloat(const std::string& fieldLabel, float const& min, float const& max, std::function get, std::function set, + static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - bool const changed = ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); if (!startRecording) @@ -468,16 +541,30 @@ namespace SHADE { startRecording = false; } - return changed; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, + static bool SliderInt(const std::string& label, int min, int max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - bool const changed = ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); @@ -488,21 +575,44 @@ namespace SHADE { startRecording = false; } - return false; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool ComboBox(const std::string& fieldLabel, std::vector list, std::function get, std::function set) + static bool ComboBox(const std::string& label, std::vector list, std::function get, std::function set, std::string_view const& tooltip = {}) { bool edited = false; int selected = get(); - ImGui::PushID(fieldLabel.c_str()); - ImGui::Text(fieldLabel.c_str()); ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::PushID(label.c_str()); + TextLabel(label); + ImGui::SameLine(); if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast(list.size()))) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), selected, set)), false); } ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return edited; } }; From 0395df5c6305d8dcca38b49e48895158da644a73 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Tue, 25 Oct 2022 19:59:16 +0800 Subject: [PATCH 23/35] Lights WIP (bug fixes) --- .../GlobalData/SHGraphicsGlobalData.cpp | 35 ++++++++-- .../MiddleEnd/Interface/SHGraphicsConstants.h | 32 +++++++-- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 11 +++- .../MiddleEnd/Interface/SHGraphicsSystem.h | 2 + .../MiddleEnd/Lights/SHLightingSubSystem.cpp | 66 ++++++++++++------- 5 files changed, 108 insertions(+), 38 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index ed1d3100..94d1d2c5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -4,6 +4,8 @@ #include "Graphics/Pipeline/SHPipelineState.h" #include "Graphics/Pipeline/SHVkPipelineLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" +#include "Graphics/MiddleEnd/Lights/SHLightData.h" +#include "Tools/SHUtilities.h" namespace SHADE { @@ -45,16 +47,35 @@ namespace SHADE // For global data (generic data and textures) Handle staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding }); - SHVkDescriptorSetLayout::Binding lightBinding + std::vector lightBindings{}; + for (uint32_t i = 0; i < SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); ++i) { - .Type = vk::DescriptorType::eStorageBufferDynamic, - .Stage = vk::ShaderStageFlagBits::eFragment, - .BindPoint = SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA, - .DescriptorCount = 1, - }; + lightBindings.push_back (SHVkDescriptorSetLayout::Binding + { + .Type = vk::DescriptorType::eStorageBufferDynamic, + .Stage = vk::ShaderStageFlagBits::eFragment, + .BindPoint = i, + .DescriptorCount = 1, + }); + } + //SHVkDescriptorSetLayout::Binding pointLightBinding + //{ + // .Type = vk::DescriptorType::eStorageBufferDynamic, + // .Stage = vk::ShaderStageFlagBits::eFragment, + // .BindPoint = SHGraphicsConstants::DescriptorSetBindings::POINT_LIGHT_DATA, + // .DescriptorCount = 1, + //}; + + //SHVkDescriptorSetLayout::Binding spotLightBinding + //{ + // .Type = vk::DescriptorType::eStorageBufferDynamic, + // .Stage = vk::ShaderStageFlagBits::eFragment, + // .BindPoint = SHGraphicsConstants::DescriptorSetBindings::SPOT_LIGHT_DATA, + // .DescriptorCount = 1, + //}; // For Dynamic global data (lights) - Handle dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding }); + Handle dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, lightBindings); SHVkDescriptorSetLayout::Binding cameraDataBinding { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index 15f192c0..f31816ce 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -94,14 +94,32 @@ namespace SHADE /***************************************************************************/ static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1; - /***************************************************************************/ - /*! - \brief - DescriptorSet binding for lights. + ///***************************************************************************/ + ///*! + // \brief + // DescriptorSet binding for directional lights. - */ - /***************************************************************************/ - static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0; + //*/ + ///***************************************************************************/ + //static constexpr uint32_t DIRECTIONAL_LIGHT_DATA = 0; + + ///***************************************************************************/ + ///*! + // \brief + // DescriptorSet binding for directional lights. + + //*/ + ///***************************************************************************/ + //static constexpr uint32_t POINT_LIGHT_DATA = 1; + + ///***************************************************************************/ + ///*! + // \brief + // DescriptorSet binding for directional lights. + + //*/ + ///***************************************************************************/ + //static constexpr uint32_t SPOT_LIGHT_DATA = 2; /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 7ecd92d2..b7d4bd2f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -36,6 +36,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/Images/SHVkSampler.h" #include "Assets/Asset Types/SHTextureAsset.h" #include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" +#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" namespace SHADE { @@ -231,11 +232,15 @@ namespace SHADE for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i) cmdPools.push_back(renderContext.GetFrameData(i).cmdPoolHdls[0]); + // Mouse picking system for the editor (Will still run with editor disabled) mousePickSystem->Init(device, cmdPools, worldRenderGraph->GetRenderGraphResource("Entity ID")); // Register the post offscreen render to the system postOffscreenRender = resourceManager.Create(); postOffscreenRender->Init(device, worldRenderGraph->GetRenderGraphResource("Scene"), descPool); + + lightingSubSystem = resourceManager.Create(); + lightingSubSystem->Init(device, descPool); } #ifdef SHEDITOR @@ -353,10 +358,12 @@ namespace SHADE // Begin recording the command buffer currentCmdBuffer->BeginRecording(); + // set viewport and scissor uint32_t w = static_cast(viewports[vpIndex]->GetWidth()); uint32_t h = static_cast(viewports[vpIndex]->GetHeight()); currentCmdBuffer->SetViewportScissor (static_cast(w), static_cast(h), w, h); + // Force set the pipeline layout currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout(), SH_PIPELINE_TYPE::GRAPHICS); // Bind all the buffers required for meshes @@ -368,6 +375,8 @@ namespace SHADE currentCmdBuffer->BindIndexBuffer(buffer, 0); } + // Bind the descriptor set for lights + lightingSubSystem->Run(currentCmdBuffer, frameIndex); // Bind textures auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup(); @@ -401,7 +410,7 @@ namespace SHADE renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); #endif - // Draw first + // Draw the scene renderers[renIndex]->Draw(frameIndex, descPool); // End the command buffer recording diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 870325ac..ae93bd78 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -32,6 +32,7 @@ of DigiPen Institute of Technology is prohibited. #include "../Textures/SHTextureLibrary.h" #include "../Textures/SHVkSamplerCache.h" #include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h" +#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" namespace SHADE { @@ -351,6 +352,7 @@ namespace SHADE // Sub systems Handle mousePickSystem; Handle postOffscreenRender; + Handle lightingSubSystem; uint32_t resizeWidth; uint32_t resizeHeight; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 613d50d3..30bbd363 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -94,6 +94,12 @@ namespace SHADE /***************************************************************************/ void SHLightingSubSystem::PerTypeData::Expand(Handle logicalDevice) noexcept { + if (lightDataAlignmentSize == 0) + { + SHLOG_ERROR ("One of the types of lights have not been accounted for. Make sure lightDataAlignmentSize is not nullptr."); + return; + } + // we want to wait for the command buffers to finish using the buffers first logicalDevice->WaitIdle(); @@ -159,15 +165,15 @@ namespace SHADE { case SH_LIGHT_TYPE::DIRECTIONAL: // TOOD: Change after creating point light struct - return 0; + return sizeof(SHDirectionalLightData); case SH_LIGHT_TYPE::POINT: - return sizeof (SHDirectionalLightData); + return 4; case SH_LIGHT_TYPE::SPOT: // TOOD: Change after creating spot light struct - return 0; + return 4; case SH_LIGHT_TYPE::NUM_TYPES: default: - return 0; + return 4; } } @@ -257,15 +263,18 @@ namespace SHADE void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept { - // we want to write to the offset of the current frame - dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex); + if (intermediateData) + { + // we want to write to the offset of the current frame + dataBuffer->WriteToMemory(intermediateData.get(), lightDataAlignmentSize * numLights, 0, lightDataAlignmentSize * maxLights * frameIndex); + } } /***************************************************************************/ /*! \brief - Update descriptor sets. We want to call this everytime we expand buffers. + Update descriptor sets. We want to call this every time we expand buffers. \param binding The binding in the set we want to update. @@ -281,27 +290,29 @@ namespace SHADE binding, { &buffer, 1 }, 0, - perTypeData[binding].GetAlignmentSize()); + perTypeData[binding].GetAlignmentSize() * perTypeData[binding].GetMaxLights()); lightingDataDescSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, binding); } /***************************************************************************/ - /*! - + /*! + \brief - Computes dynamic offsets. - - */ + Computes dynamic offsets. + + */ /***************************************************************************/ void SHLightingSubSystem::ComputeDynamicOffsets(void) noexcept { - for (uint32_t i = 0; i < dynamicOffsets.size(); ++i) + for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) { - auto const& typeData = perTypeData[i]; - for (uint32_t j = 0; j < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++j) + for (uint32_t j = 0; j < dynamicOffsets.size(); ++j) { - dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights(); + auto const& typeData = perTypeData[j]; + { + dynamicOffsets[i][j] = j * typeData.GetAlignmentSize() * typeData.GetMaxLights(); + } } } } @@ -319,17 +330,26 @@ namespace SHADE void SHLightingSubSystem::Init(Handle device, Handle descPool) noexcept { logicalDevice = device; + uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); - std::vector variableSizes{ SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES) }; + std::vector variableSizes{ NUM_LIGHT_TYPES }; std::fill (variableSizes.begin(), variableSizes.end(), 1); // Create the descriptor set lightingDataDescSet = descPool->Allocate({SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS]}, variableSizes); - // initialize all the data first. We add more lights here as we add more types. - perTypeData[SHUtilities::ToUnderlying(SH_LIGHT_TYPE::DIRECTIONAL)].InitializeData(logicalDevice, SH_LIGHT_TYPE::DIRECTIONAL); - UpdateDescSet(SHGraphicsConstants::DescriptorSetBindings::DIRECTIONAL_LIGHT_DATA); + for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i) + { + // initialize all the data first. We add more lights here as we add more types. + perTypeData[i].InitializeData(logicalDevice, static_cast(i)); + UpdateDescSet(i); + } + + for (uint32_t i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + dynamicOffsets[i].resize(NUM_LIGHT_TYPES); + } } /***************************************************************************/ @@ -378,8 +398,8 @@ namespace SHADE // is a new buffer. If some expansion was detected, update descriptor sets. if (expanded) { - uint32_t numLightTyes = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); - for (uint32_t i = 0; i < numLightTyes; ++i) + uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); + for (uint32_t i = 0; i < NUM_LIGHT_TYPES; ++i) { UpdateDescSet(i); } From 6d9a8e484c4b08a9642a6f6ff998efd036cafc33 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 20:55:46 +0800 Subject: [PATCH 24/35] Asset browser --- .../AssetBrowser/SHAssetBrowser.cpp | 84 +++++++++++++++++++ .../AssetBrowser/SHAssetBrowser.h | 24 ++++++ .../Inspector/SHEditorInspector.cpp | 4 +- .../EditorWindow/SHEditorWindowIncludes.h | 3 +- .../ViewportWindow/SHEditorViewport.cpp | 3 +- SHADE_Engine/src/Editor/SHEditor.cpp | 1 + 6 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp create mode 100644 SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp new file mode 100644 index 00000000..caad9b10 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -0,0 +1,84 @@ +#include "SHpch.h" +#include "SHAssetBrowser.h" + +#include "Editor/IconsMaterialDesign.h" +#include "Editor/SHImGuiHelpers.hpp" +#include + +#include "Assets/SHAssetManager.h" +#include "Editor/DragDrop/SHDragDrop.hpp" + +namespace SHADE +{ + SHAssetBrowser::SHAssetBrowser() + :SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar) + { + } + + void SHAssetBrowser::Init() + { + SHEditorWindow::Init(); + } + + void SHAssetBrowser::Update() + { + SHEditorWindow::Update(); + if(Begin()) + { + DrawMenuBar(); + auto const& assets = SHAssetManager::GetAllAssets(); + if(ImGui::BeginTable("AssetBrowserTable", 3)) + { + ImGui::TableNextColumn(); + ImGui::TableHeader("Asset ID"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Name"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Type"); + for(SHAsset const& asset : assets) + { + DrawAsset(asset); + } + ImGui::EndTable(); + } + } + ImGui::End(); + } + + void SHAssetBrowser::DrawMenuBar() + { + if(ImGui::BeginMenuBar()) + { + + ImGui::EndMenuBar(); + } + } + + void SHAssetBrowser::DrawAsset(SHAsset const& asset) + { + ImGui::PushID(asset.id); + ImGui::BeginGroup(); + + ImGui::TableNextColumn(); + ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns); + if(SHDragDrop::BeginSource()) + { + auto id = asset.id; + ImGui::Text("Moving Asset: %zu", id); + SHDragDrop::SetPayload(DRAG_RESOURCE, &id); + SHDragDrop::EndSource(); + } + + ImGui::TableNextColumn(); + ImGui::Text("%s", asset.name.c_str()); + + ImGui::TableNextColumn(); + ImGui::Text("%s", "Type"); + + ImGui::EndGroup(); + ImGui::PopID(); + + + + } +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h new file mode 100644 index 00000000..0e3053bc --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Assets/SHAsset.h" +#include "Editor/EditorWindow/SHEditorWindow.h" + +namespace SHADE +{ + class SHAssetBrowser final : public SHEditorWindow + { + public: + SHAssetBrowser(); + + void Init(); + void Update(); + + void Refresh(); + private: + void DrawMenuBar(); + void DrawAsset(SHAsset const& asset); + + float idColumnWidth, nameColumnWidth, typeColumnWidth; + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index b59ce9cc..ada5a35a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -84,8 +84,8 @@ namespace SHADE } ImGui::Separator(); // Render Scripts - SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); - scriptEngine->RenderScriptsInInspector(eid); + SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); + scriptEngine->RenderScriptsInInspector(eid); ImGui::Separator(); if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) { diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h index f0267b06..5208c6d9 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h @@ -3,4 +3,5 @@ #include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel #include "Inspector/SHEditorInspector.h" //Inspector #include "Profiling/SHEditorProfiler.h" //Profiler -#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport \ No newline at end of file +#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport +#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index cb30fa81..f5170999 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -30,6 +30,7 @@ namespace SHADE void SHEditorViewport::Update() { SHEditorWindow::Update(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f)); if(Begin()) { ImGuizmo::SetDrawlist(); @@ -55,7 +56,7 @@ namespace SHADE ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y); transformGizmo.Draw(); ImGui::End(); - + ImGui::PopStyleVar(); } void SHEditorViewport::Exit() diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 912f9d0f..06fadfee 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -92,6 +92,7 @@ namespace SHADE SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); io = &ImGui::GetIO(); From 534aeba06b4728e2f7a4e494e51b03ed903c34cb Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 20:59:32 +0800 Subject: [PATCH 25/35] Latest Default Layout --- Assets/Editor/Layouts/Default.ini | 103 ++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/Assets/Editor/Layouts/Default.ini b/Assets/Editor/Layouts/Default.ini index 4ddc46c2..d7a7bf69 100644 --- a/Assets/Editor/Layouts/Default.ini +++ b/Assets/Editor/Layouts/Default.ini @@ -4,13 +4,13 @@ Size=1920,20 Collapsed=0 [Window][SHEditorMenuBar] -Pos=0,24 -Size=1920,1036 +Pos=0,48 +Size=1920,1012 Collapsed=0 [Window][Hierarchy Panel] -Pos=0,120 -Size=225,940 +Pos=0,197 +Size=308,863 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,96 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1686,24 -Size=234,1036 +Pos=1528,48 +Size=392,1012 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] -Pos=0,24 -Size=225,94 +Pos=0,48 +Size=308,147 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=227,24 -Size=1457,1036 +Pos=227,48 +Size=1457,1012 Collapsed=0 -DockId=0x00000002,0 +DockId=0x0000000B,0 + +[Window][o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][] +Pos=60,60 +Size=999,581 +Collapsed=0 + +[Window][o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][] +Pos=60,60 +Size=553,422 +Collapsed=0 + +[Window][] +Pos=60,60 +Size=770,394 +Collapsed=0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=310,48 +Size=1216,715 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][V] +Pos=310,722 +Size=1501,338 +Collapsed=0 +DockId=0x00000008,0 + +[Window][p] +Pos=310,750 +Size=1501,310 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][ Asset Browser] +Pos=310,765 +Size=1216,295 +Collapsed=0 +DockId=0x0000000C,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252 +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881 + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7 + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A + DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252 From 388795a2db374eeb1b2c3bda8384dcd204f7020e Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 25 Oct 2022 22:13:27 +0800 Subject: [PATCH 26/35] Transform Components are Enforced through the editor for certain components --- .../Inspector/SHEditorInspector.cpp | 33 +++++-- SHADE_Engine/src/Events/SHEventManager.hpp | 3 +- .../src/Math/Transform/SHTransformSystem.cpp | 94 +++++++++---------- .../src/Math/Transform/SHTransformSystem.h | 9 +- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 6 +- SHADE_Engine/src/Physics/SHPhysicsSystem.h | 2 +- 6 files changed, 83 insertions(+), 64 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index b59ce9cc..116ad8d6 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -35,6 +35,23 @@ namespace SHADE return selected; } + template , bool> = true, std::enable_if_t, bool> = true> + bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid) + { + bool selected = false; + if (!SHComponentManager::HasComponent(eid)) + { + if(selected = ImGui::Selectable(std::format("Add {}", rttr::type::get().get_name().data()).data()); selected) + { + if(SHComponentManager::GetComponent_s(eid) == nullptr) + SHComponentManager::AddComponent(eid); + + SHComponentManager::AddComponent(eid); + } + } + return selected; + } + SHEditorInspector::SHEditorInspector() :SHEditorWindow("Inspector", ImGuiWindowFlags_MenuBar) { @@ -90,15 +107,13 @@ namespace SHADE if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) { DrawAddComponentButton(eid); - DrawAddComponentButton(eid); - DrawAddComponentButton(eid); - if(DrawAddComponentButton(eid)) - { - if(SHComponentManager::GetComponent_s(eid) == nullptr) - { - SHComponentManager::AddComponent(eid); - } - } + + // Components that require Transforms + + DrawAddComponentWithEnforcedComponentButton(eid); + DrawAddComponentWithEnforcedComponentButton(eid); + DrawAddComponentWithEnforcedComponentButton(eid); + ImGui::EndMenu(); } diff --git a/SHADE_Engine/src/Events/SHEventManager.hpp b/SHADE_Engine/src/Events/SHEventManager.hpp index f511518a..490c6b10 100644 --- a/SHADE_Engine/src/Events/SHEventManager.hpp +++ b/SHADE_Engine/src/Events/SHEventManager.hpp @@ -12,6 +12,7 @@ #include "SHpch.h" #include "SHEvent.h" #include "SHEventReceiver.h" +#include "SH_API.h" /****************************************************************************** INSTRUCTIONS FOR USE: @@ -67,7 +68,7 @@ namespace SHADE using EventManagerListener = std::function; - class SHEventManager + class SH_API SHEventManager { private: diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 5a540cd4..4ab6b909 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -61,9 +61,9 @@ namespace SHADE void SHTransformSystem::Init() { - std::shared_ptr thisReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; - ReceiverPtr receiver = std::dynamic_pointer_cast(thisReceiver); - SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver); + std::shared_ptr thisChangeParentReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; + ReceiverPtr changeParentReceiver = std::dynamic_pointer_cast(thisChangeParentReceiver); + SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, changeParentReceiver); } void SHTransformSystem::Exit() @@ -75,50 +75,6 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent) - { - const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); - - auto* node = eventData->data->node; - auto* tf = SHComponentManager::GetComponent_s(node->GetEntityID()); - - // Recompute local transform and store localToWorld Matrix - SHMatrix localToWorld = SHMatrix::Identity; - SHMatrix worldToLocal = SHMatrix::Identity; - - auto* newParent = eventData->data->newParent; - const auto* PARENT_TF = SHComponentManager::GetComponent_s(newParent->GetEntityID()); - if (PARENT_TF != nullptr) // Not the root - { - localToWorld = PARENT_TF->GetTRS(); - worldToLocal = SHMatrix::Inverse(localToWorld); - } - - // Maintain World Transform and recompute Local Transform - - // Compute Local Position - tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); - - - tf->localRotation = tf->worldRotation; - tf->local.scale = tf->world.scale; - - if (PARENT_TF != nullptr) - { - // Compute Local Rotation - tf->localRotation -= PARENT_TF->GetLocalRotation(); - - // Compute Local Scale - tf->local.scale /= PARENT_TF->GetLocalScale(); - } - - tf->local.trs = localToWorld; - - // Propagate maintaining world transform down the branch - UpdateChildrenLocalTransforms(node); - return eventData->handle; - } - void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node) { // Structure is similar to update entity, albeit without a queue to do being a forced update @@ -300,4 +256,48 @@ namespace SHADE tf.world.ComputeTRS(); } + SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent) + { + const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); + + auto* node = eventData->data->node; + auto* tf = SHComponentManager::GetComponent_s(node->GetEntityID()); + + // Recompute local transform and store localToWorld Matrix + SHMatrix localToWorld = SHMatrix::Identity; + SHMatrix worldToLocal = SHMatrix::Identity; + + auto* newParent = eventData->data->newParent; + const auto* PARENT_TF = SHComponentManager::GetComponent_s(newParent->GetEntityID()); + if (PARENT_TF != nullptr) // Not the root + { + localToWorld = PARENT_TF->GetTRS(); + worldToLocal = SHMatrix::Inverse(localToWorld); + } + + // Maintain World Transform and recompute Local Transform + + // Compute Local Position + tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); + + + tf->localRotation = tf->worldRotation; + tf->local.scale = tf->world.scale; + + if (PARENT_TF != nullptr) + { + // Compute Local Rotation + tf->localRotation -= PARENT_TF->GetLocalRotation(); + + // Compute Local Scale + tf->local.scale /= PARENT_TF->GetLocalScale(); + } + + tf->local.trs = localToWorld; + + // Propagate maintaining world transform down the branch + UpdateChildrenLocalTransforms(node); + return eventData->handle; + } + } // 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 e63969ce..f09da3ea 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -11,9 +11,9 @@ #pragma once // Project Headers -#include "SHTransformComponent.h" -#include "Scene/SHSceneGraph.h" #include "ECS_Base/System/SHSystemRoutine.h" +#include "Scene/SHSceneGraph.h" +#include "SHTransformComponent.h" namespace SHADE { @@ -111,11 +111,14 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHEventHandle ChangeParent (SHEventPtr changeParentEvent); static void UpdateChildrenLocalTransforms (SHSceneNode* node); static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag); static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); + + // Event Handlers + + SHEventHandle ChangeParent (SHEventPtr changeParentEvent); }; diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index a1994ad2..f989e41d 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -203,7 +203,7 @@ namespace SHADE // SHLOG_INFO("Adding a Rigidbody to the Physics World.") //#endif - auto* physicsObject = CreatePhysicsObject(entityID); + auto* physicsObject = EnsurePhysicsObject(entityID); physicsObject->CreateRigidBody ( @@ -219,7 +219,7 @@ namespace SHADE // SHLOG_INFO("Adding a Collider to the Physics World.") //#endif - auto* physicsObject = CreatePhysicsObject(entityID); + auto* physicsObject = EnsurePhysicsObject(entityID); physicsObject->CreateCollisionBody ( @@ -359,7 +359,7 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept + SHPhysicsObject* SHPhysicsSystem::EnsurePhysicsObject(EntityID entityID) noexcept { const auto it = map.find(entityID); if (it == map.end()) diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index bc6a1ba2..37d98300 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -186,7 +186,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept; + SHPhysicsObject* EnsurePhysicsObject (EntityID entityID) noexcept; SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; void DestroyPhysicsObject (EntityID entityID) noexcept; From 3c5a1b73d6f1bde4c5980f694f34c040d76e49fb Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 25 Oct 2022 22:26:07 +0800 Subject: [PATCH 27/35] Fixed bug with destroying a rigidbody component --- .../Components/SHRigidBodyComponent.cpp | 72 +++---------------- SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 7 +- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 44 ++---------- SHADE_Engine/src/Physics/SHPhysicsSystem.h | 18 +---- 4 files changed, 19 insertions(+), 122 deletions(-) diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index e5938717..4c620ad0 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -289,98 +289,42 @@ namespace SHADE void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddForce(GetEID(), force); + } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddForceAtLocalPos(GetEID(), force, localPos); + } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddForceAtWorldPos(GetEID(), force, worldPos); + } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddRelativeForce(GetEID(), force); + } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddRelativeForceAtLocalPos(GetEID(), force, localPos); + } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddRelativeForceAtWorldPos(GetEID(), force, worldPos); + } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddTorque(GetEID(), torque); + } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to Add Force to a body!") - return; - } - - // Notify Physics Systems - system->AddRelativeTorque(GetEID(), relativeTorque); + } } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index f9b476ef..91e7a3dc 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -133,7 +133,7 @@ namespace SHADE void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c) { // If collider already exists, recreate the collision body as a rigid body - if (hasColliders) + if (c != nullptr) world->destroyCollisionBody(rp3dBody); rp3dBody = world->createRigidBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); @@ -142,7 +142,7 @@ namespace SHADE rb->position = tf->GetWorldPosition(); rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); - if (hasColliders) + if (c != nullptr) { c->position = tf->GetWorldPosition(); c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); @@ -196,8 +196,9 @@ namespace SHADE void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept { world->destroyRigidBody(reinterpret_cast(rp3dBody)); + rp3dBody = nullptr; - if (hasColliders) + if (c != nullptr) { // Preserve colliders as a collision body rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation }); diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index f989e41d..334fc6c5 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -250,46 +250,6 @@ namespace SHADE #endif } - void SHPhysicsSystem::AddForce(EntityID entityID, const SHVec3& force) const noexcept - { - - } - - void SHPhysicsSystem::AddForceAtLocalPos(EntityID entityID, const SHVec3& force, const SHVec3& localPos) const noexcept - { - - } - - void SHPhysicsSystem::AddForceAtWorldPos(EntityID entityID, const SHVec3& force, const SHVec3& worldPos) const noexcept - { - - } - - void SHPhysicsSystem::AddRelativeForce(EntityID entityID, const SHVec3& relativeForce) const noexcept - { - - } - - void SHPhysicsSystem::AddRelativeForceAtLocalPos(EntityID entityID, const SHVec3& relativeForce, const SHVec3& localPos) const noexcept - { - - } - - void SHPhysicsSystem::AddRelativeForceAtWorldPos(EntityID entityID, const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept - { - - } - - void SHPhysicsSystem::AddTorque(EntityID entityID, const SHVec3& torque) const noexcept - { - - } - - void SHPhysicsSystem::AddRelativeTorque(EntityID entityID, const SHVec3& relativeTorque) const noexcept - { - - } - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) { auto* physicsObject = GetPhysicsObject(entityID); @@ -312,6 +272,10 @@ namespace SHADE // Sync transforms for (auto& physicsObject : system->map | std::views::values) { + // Ensure a valid physics Object + if (physicsObject.rp3dBody == nullptr) + continue; + const auto* TF = SHComponentManager::GetComponent(physicsObject.entityID); if (TF->HasChanged()) { diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index 37d98300..933b36af 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -32,7 +32,7 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHPhysicsSystem : public SHSystem + class SH_API SHPhysicsSystem final : public SHSystem { public: /*---------------------------------------------------------------------------------*/ @@ -90,17 +90,6 @@ namespace SHADE void RemoveRigidBody (EntityID entityID) noexcept; void RemoveCollider (EntityID entityID) noexcept; - void AddForce (EntityID entityID, const SHVec3& force) const noexcept; - void AddForceAtLocalPos (EntityID entityID, const SHVec3& force, const SHVec3& localPos) const noexcept; - void AddForceAtWorldPos (EntityID entityID, const SHVec3& force, const SHVec3& worldPos) const noexcept; - - void AddRelativeForce (EntityID entityID, const SHVec3& relativeForce) const noexcept; - void AddRelativeForceAtLocalPos (EntityID entityID, const SHVec3& relativeForce, const SHVec3& localPos) const noexcept; - void AddRelativeForceAtWorldPos (EntityID entityID, const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept; - - void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept; - void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept; - void AddCollisionShape (EntityID entityID, SHCollider* collider); void RemoveCollisionShape (EntityID entityID, int index); @@ -170,15 +159,14 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - // TODO(Diren): Store interpFactor - bool worldUpdated; double interpolationFactor; double fixedDT; - rp3d::PhysicsWorld* world; + rp3d::PhysicsWorld* world; rp3d::PhysicsCommon factory; + EntityObjectMap map; From 0defa58c77f6d700943fa3f0296758045fd0df4b Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Tue, 25 Oct 2022 23:09:46 +0800 Subject: [PATCH 28/35] Physics Component Synchronisation is now done through events --- .../src/Math/Transform/SHTransformSystem.cpp | 15 +- .../src/Math/Transform/SHTransformSystem.h | 22 --- .../Components/SHColliderComponent.cpp | 12 +- .../Components/SHRigidBodyComponent.cpp | 14 +- SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 40 ----- SHADE_Engine/src/Physics/SHPhysicsObject.h | 6 +- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 155 ++++++++++++------ SHADE_Engine/src/Physics/SHPhysicsSystem.h | 26 ++- 8 files changed, 143 insertions(+), 147 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 4ab6b909..a2ab6880 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -61,9 +61,9 @@ namespace SHADE void SHTransformSystem::Init() { - std::shared_ptr thisChangeParentReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; - ReceiverPtr changeParentReceiver = std::dynamic_pointer_cast(thisChangeParentReceiver); - SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, changeParentReceiver); + const std::shared_ptr CHANGE_PARENT_RECEIVER { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; + const ReceiverPtr CHANGE_PARENT_RECEIVER_PTR = std::dynamic_pointer_cast(CHANGE_PARENT_RECEIVER); + SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, CHANGE_PARENT_RECEIVER_PTR); } void SHTransformSystem::Exit() @@ -258,16 +258,16 @@ namespace SHADE SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent) { - const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); + const auto& EVENT_DATA = reinterpret_cast*>(changeParentEvent.get()); - auto* node = eventData->data->node; + auto* node = EVENT_DATA->data->node; auto* tf = SHComponentManager::GetComponent_s(node->GetEntityID()); // Recompute local transform and store localToWorld Matrix SHMatrix localToWorld = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity; - auto* newParent = eventData->data->newParent; + auto* newParent = EVENT_DATA->data->newParent; const auto* PARENT_TF = SHComponentManager::GetComponent_s(newParent->GetEntityID()); if (PARENT_TF != nullptr) // Not the root { @@ -297,7 +297,8 @@ namespace SHADE // Propagate maintaining world transform down the branch UpdateChildrenLocalTransforms(node); - return eventData->handle; + + return EVENT_DATA->handle; } } // 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 f09da3ea..bb373f3a 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -53,17 +53,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ TransformPostLogicUpdate (); - ~TransformPostLogicUpdate () = default; - - TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete; - TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete; - - /*-------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-------------------------------------------------------------------------------*/ - - TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete; - TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -80,17 +69,6 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ TransformPostPhysicsUpdate (); - ~TransformPostPhysicsUpdate () = default; - - TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete; - TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete; - - /*-------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*-------------------------------------------------------------------------------*/ - - TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete; - TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index 71183f00..242b8d8f 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -69,13 +69,13 @@ namespace SHADE void SHColliderComponent::OnCreate() { system = SHSystemManager::GetSystem(); - if (!system) - { - SHLOG_ERROR("Physics system does not exist, Collider Component not added!") - return; - } + //if (!system) + //{ + // SHLOG_ERROR("Physics system does not exist, Collider Component not added!") + // return; + //} - system->AddCollider(GetEID()); + //system->AddCollider(GetEID()); } void SHColliderComponent::OnDestroy() diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 4c620ad0..934b67f6 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -265,14 +265,14 @@ namespace SHADE void SHRigidBodyComponent::OnCreate() { system = SHSystemManager::GetSystem(); - if (!system) - { - SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!") - return; - } + //if (!system) + //{ + // SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!") + // return; + //} - // Notify Physics System - system->AddRigidBody(GetEID()); + //// Notify Physics System + //system->AddRigidBody(GetEID()); } void SHRigidBodyComponent::OnDestroy() diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 91e7a3dc..8c067482 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -26,8 +26,6 @@ namespace SHADE SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept : entityID { eid } - , isRigidBody { false } - , hasColliders{ false } , factory { physicsFactory } , world { physicsWorld } , rp3dBody { nullptr } @@ -130,42 +128,6 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c) - { - // If collider already exists, recreate the collision body as a rigid body - if (c != nullptr) - world->destroyCollisionBody(rp3dBody); - - rp3dBody = world->createRigidBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); - isRigidBody = true; - - rb->position = tf->GetWorldPosition(); - rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); - - if (c != nullptr) - { - c->position = tf->GetWorldPosition(); - c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); - // Get array of colliders and add them back into the rigidbody - for (auto& collider : c->colliders | std::views::keys) - AddCollider(&collider); - } - } - - void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c) - { - if (rp3dBody == nullptr) - rp3dBody = world->createCollisionBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() }); - - hasColliders = true; - - c->position = tf->GetWorldPosition(); - c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); - - for (auto& collider : c->colliders | std::views::keys) - AddCollider(&collider); - } - int SHPhysicsObject::AddCollider(SHCollider* collider) { switch (collider->GetType()) @@ -205,8 +167,6 @@ namespace SHADE for (auto& collider : c->colliders | std::views::keys) AddCollider(&collider); } - - isRigidBody = false; } void SHPhysicsObject::DestroyCollisionBody() noexcept diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h index 39a85421..11e41ad1 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -69,8 +69,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void CreateRigidBody (const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c); - void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c); + void CreateRigidBody (const SHVec3& pos, const SHQuaternion& orientation); + void CreateCollisionBody (const SHVec3& pos, const SHQuaternion& orientation); int AddCollider (SHCollider* collider); void DestroyRigidBody (SHColliderComponent* c) noexcept; @@ -86,8 +86,6 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ EntityID entityID; - bool isRigidBody; - bool hasColliders; rp3d::PhysicsCommon* factory; rp3d::PhysicsWorld* world; diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 334fc6c5..76e54b09 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -175,11 +175,9 @@ namespace SHADE void SHPhysicsSystem::Init() { - using namespace rp3d; - // Create a physics world with the default settings - PhysicsWorld::WorldSettings settings; - settings.gravity = Vector3{ 0.0f, -9.81f, 0.0f }; + rp3d::PhysicsWorld::WorldSettings settings; + settings.gravity = SHVec3{ 0.0f, -9.81f, 0.0f }; settings.isSleepingEnabled = true; settings.defaultVelocitySolverNbIterations = 8; settings.defaultPositionSolverNbIterations = 3; @@ -190,6 +188,12 @@ namespace SHADE // Set up solvers world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES); + + // Subscribe to component events + + const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::AddPhysicsComponent) }; + const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(ADD_COMPONENT_RECEIVER); + SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR); } void SHPhysicsSystem::Exit() @@ -197,36 +201,29 @@ namespace SHADE factory.destroyPhysicsWorld(world); } - void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept - { - //#ifdef _DEBUG - // SHLOG_INFO("Adding a Rigidbody to the Physics World.") - //#endif + //void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept + //{ + // //#ifdef _DEBUG + // // SHLOG_INFO("Adding a Rigidbody to the Physics World.") + // //#endif - auto* physicsObject = EnsurePhysicsObject(entityID); + // + //} - physicsObject->CreateRigidBody - ( - EnsureTransform(entityID), - SHComponentManager::GetComponent(entityID), - SHComponentManager::GetComponent_s(entityID) - ); - } + //void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept + //{ + // //#ifdef _DEBUG + // // SHLOG_INFO("Adding a Collider to the Physics World.") + // //#endif - void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept - { - //#ifdef _DEBUG - // SHLOG_INFO("Adding a Collider to the Physics World.") - //#endif + // auto* physicsObject = EnsurePhysicsObject(entityID); - auto* physicsObject = EnsurePhysicsObject(entityID); - - physicsObject->CreateCollisionBody - ( - EnsureTransform(entityID), - SHComponentManager::GetComponent(entityID) - ); - } + // physicsObject->CreateCollisionBody + // ( + // SHComponentManager::GetComponent(entityID), + // SHComponentManager::GetComponent(entityID) + // ); + //} void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept { @@ -415,15 +412,18 @@ namespace SHADE const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform(); + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + // Check if transform should be interpolated - if (physicsObject.isRigidBody) + if (rigidBodyComponent != nullptr) { - auto* rbComponent = SHComponentManager::GetComponent(entityID); - if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC) + + if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) continue; - if (rbComponent->IsInterpolating()) + if (rigidBodyComponent->IsInterpolating()) { const rp3d::Transform PREV_TF = physicsObject.prevTransform; const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); @@ -438,12 +438,12 @@ namespace SHADE rp3dRot = CURRENT_TF.getOrientation(); } - rbComponent->position = CURRENT_TF.getPosition(); - rbComponent->orientation = CURRENT_TF.getOrientation(); + rigidBodyComponent->position = CURRENT_TF.getPosition(); + rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - if (physicsObject.hasColliders) + if (colliderComponent != nullptr) { - auto* colliderComponent = SHComponentManager::GetComponent(entityID); + colliderComponent->position = CURRENT_TF.getPosition(); colliderComponent->orientation = CURRENT_TF.getOrientation(); } @@ -457,26 +457,89 @@ namespace SHADE // Convert RP3D Transform to SHADE auto* tfComponent = SHComponentManager::GetComponent(entityID); tfComponent->SetWorldPosition(rp3dPos); - tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot }); + tfComponent->SetWorldOrientation(rp3dRot); // Cache transforms physicsObject.prevTransform = CURRENT_TF; } } - SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID) + SHEventHandle SHPhysicsSystem::AddPhysicsComponent(SHEventPtr addComponentEvent) { - auto* tf = SHComponentManager::GetComponent_s(entityID); + const auto& EVENT_DATA = reinterpret_cast*>(addComponentEvent.get()); - // Possibly redundant - if (!tf) + static const auto RIGID_BODY_ID = ComponentFamily::GetID(); + static const auto COLLIDER_ID = ComponentFamily::GetID(); + + const auto COMPONENT_ADDED_ID = EVENT_DATA->data->addedComponentType; + const bool IS_PHYSICS_COMPONENT = COMPONENT_ADDED_ID == RIGID_BODY_ID || COMPONENT_ADDED_ID == COLLIDER_ID; + if (IS_PHYSICS_COMPONENT) { - SHComponentManager::AddComponent(entityID); - tf = SHComponentManager::GetComponent(entityID); + const EntityID ENTITY_ID = EVENT_DATA->data->eid; + auto* physicsObject = EnsurePhysicsObject(ENTITY_ID); + + auto* transformComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + if (transformComponent == nullptr) + { + SHLOG_ERROR("Entity {} cannot add a Physics Component without a Transform! Component not created!", ENTITY_ID) + return EVENT_DATA->handle; + } + + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + + if (COMPONENT_ADDED_ID == RIGID_BODY_ID) + { + if (colliderComponent != nullptr) + { + world->destroyCollisionBody(physicsObject->rp3dBody); + physicsObject->rp3dBody = nullptr; + } + + rigidBodyComponent->position = transformComponent->GetWorldPosition(); + rigidBodyComponent->orientation = transformComponent->GetWorldOrientation(); + + physicsObject->rp3dBody = world->createRigidBody + ( + rp3d::Transform{ rigidBodyComponent->position, rigidBodyComponent->orientation } + ); + + + // Add collision shapes back into the body + if (colliderComponent != nullptr) + { + for (auto& collider : colliderComponent->colliders | std::views::keys) + physicsObject->AddCollider(&collider); + } + } + + if (COMPONENT_ADDED_ID == COLLIDER_ID) + { + colliderComponent->position = transformComponent->GetWorldPosition(); + colliderComponent->orientation = transformComponent->GetWorldOrientation(); + + if (physicsObject->rp3dBody == nullptr) + { + physicsObject->rp3dBody = world->createCollisionBody + ( + rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } + ); + } + + // Add Collision Shapes + for (auto& collider : colliderComponent->colliders | std::views::keys) + physicsObject->AddCollider(&collider); + } } - return tf; + return EVENT_DATA->handle; } + SHEventHandle SHPhysicsSystem::RemovePhysicsComponent(SHEventPtr removeComponentEvent) + { + const auto& EVENT_DATA = reinterpret_cast*>(removeComponentEvent.get()); + + return EVENT_DATA->handle; + } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index 933b36af..d88f8c06 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -16,14 +16,14 @@ #include // Project Headers -#include "SHPhysicsObject.h" #include "Components/SHRigidBodyComponent.h" #include "Components/SHColliderComponent.h" -#include "Math/Transform/SHTransformComponent.h" - -#include "Scene/SHSceneGraph.h" #include "ECS_Base/System/SHSystemRoutine.h" #include "ECS_Base/System/SHFixedSystemRoutine.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Scene/SHSceneGraph.h" +#include "SHPhysicsObject.h" + namespace SHADE @@ -85,8 +85,8 @@ namespace SHADE void Init () override; void Exit () override; - void AddRigidBody (EntityID entityID) noexcept; - void AddCollider (EntityID entityID) noexcept; + //void AddRigidBody (EntityID entityID) noexcept; + //void AddCollider (EntityID entityID) noexcept; void RemoveRigidBody (EntityID entityID) noexcept; void RemoveCollider (EntityID entityID) noexcept; @@ -97,10 +97,7 @@ namespace SHADE /* System Routines */ /*---------------------------------------------------------------------------------*/ - /** - * @brief Synchronises RP3D with SHADE - */ - class SH_API PhysicsPreUpdate : public SHSystemRoutine + class SH_API PhysicsPreUpdate final : public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ @@ -116,7 +113,7 @@ namespace SHADE void Execute(double dt) noexcept override; }; - class SH_API PhysicsFixedUpdate : public SHFixedSystemRoutine + class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine { public: /*-------------------------------------------------------------------------------*/ @@ -132,7 +129,7 @@ namespace SHADE void Execute (double dt) noexcept override; }; - class SH_API PhysicsPostUpdate : public SHSystemRoutine + class SH_API PhysicsPostUpdate final : public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ @@ -182,10 +179,9 @@ namespace SHADE void SyncRigidBodyComponents (std::vector& denseArray) noexcept; void SyncColliderComponents (std::vector& denseArray) noexcept; void SyncTransforms () noexcept; - // TODO(Diren): Trigger handling - // TODO(Diren): Remove when responsibility shifted to editor - SHTransformComponent* EnsureTransform (EntityID entityID); + SHEventHandle AddPhysicsComponent (SHEventPtr addComponentEvent); + SHEventHandle RemovePhysicsComponent (SHEventPtr removeComponentEvent); }; From 5016600397d70845eb509f5b90c6a7596eb22283 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Tue, 25 Oct 2022 23:39:35 +0800 Subject: [PATCH 29/35] Lights WIP --- Assets/Editor/Layouts/UserLayout.ini | 12 ++++++------ .../Graphics/MiddleEnd/Interface/SHRenderable.cpp | 7 +++++++ .../src/Graphics/MiddleEnd/Interface/SHRenderable.h | 2 ++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 9add170c..4d608401 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Hierarchy Panel] Pos=0,142 -Size=768,918 +Size=494,918 Collapsed=0 DockId=0x00000004,0 @@ -27,7 +27,7 @@ DockId=0x00000006,0 [Window][Profiler] Pos=0,48 -Size=768,92 +Size=494,92 Collapsed=0 DockId=0x00000003,0 @@ -38,17 +38,17 @@ Collapsed=0 DockId=0x00000002,0 [Window][ Viewport] -Pos=770,48 -Size=877,1012 +Pos=496,48 +Size=1151,1012 Collapsed=0 DockId=0x00000002,0 [Docking][Data] DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=768,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=494,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=877,1036 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1151,1036 CentralNode=1 Selected=0xB41284E7 DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 0b1c1b66..523722e4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -27,6 +27,8 @@ namespace SHADE sharedMaterial = {}; material = {}; oldMaterial = {}; + + lightLayer = 0; } void SHRenderable::OnDestroy() @@ -87,6 +89,11 @@ namespace SHADE return material; } + uint8_t SHRenderable::GetLightLayer(void) const noexcept + { + return lightLayer; + } + void SHRenderable::ResetChangedFlag() { materialChanged = false; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index bc885ca2..95b53b9e 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -56,6 +56,7 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ bool WasMaterialChanged() const noexcept { return materialChanged; } Handle GetPrevMaterial() const noexcept { return oldMaterial; } + uint8_t GetLightLayer (void) const noexcept; /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ @@ -75,6 +76,7 @@ namespace SHADE Handle material; bool materialChanged = true; Handle oldMaterial; + uint8_t lightLayer; }; } From 4b7a8374698a161caa1cb4310c4bb6ef93e145f5 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Wed, 26 Oct 2022 01:08:02 +0800 Subject: [PATCH 30/35] Fixed some bugs in render graph - Changed the eid buffer for instanced rendering to a vec2 (potentially vec3 or 4), to pass other types of data like light layer index. - Renamed some render graph nodes and subpasses. Added a dummy render pass to transition the scene to read only optimal. - offscreen buffer resource now transitions to eShaderReadOnlyOptimal instead of eGeneral --- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 40 +++++++++++------- .../src/Graphics/MiddleEnd/Batching/SHBatch.h | 7 +-- .../MiddleEnd/Batching/SHSuperBatch.cpp | 2 +- .../GlobalData/SHGraphicsGlobalData.cpp | 2 +- .../MiddleEnd/Interface/SHGraphicsConstants.h | 2 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 23 +++++----- .../Interface/SHInstancedIntegerData.h | 12 ++++++ .../Interface/SHPostOffscreenRenderSystem.cpp | 2 +- .../src/Graphics/Pipeline/SHPipelineState.cpp | 6 +++ .../Graphics/RenderGraph/SHRenderGraph.cpp | 3 ++ SHADE_Engine/src/Graphics/SHVkUtil.cpp | 12 ++++++ .../VertexDescriptors/SHVertexAttribute.h | 3 ++ TempShaderFolder/TestCubeVs.glsl | 5 ++- TempShaderFolder/TestCubeVs.spv | Bin 2300 -> 2376 bytes 14 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 40826047..476351c9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -110,7 +110,7 @@ namespace SHADE // Clear CPU buffers drawData.clear(); transformData.clear(); - eidData.clear(); + instancedIntegerData.clear(); matPropsData.reset(); matPropsDataSize = 0; @@ -120,7 +120,7 @@ namespace SHADE { drawDataBuffer[i].Free(); transformDataBuffer[i].Free(); - eidBuffer[i].Free(); + instancedIntegerBuffer[i].Free(); matPropsBuffer[i].Free(); } } @@ -208,7 +208,7 @@ namespace SHADE transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast(transformData.size() * sizeof(SHMatrix)), 0, 0); } - void SHBatch::UpdateEIDBuffer(uint32_t frameIndex) + void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex) { if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) { @@ -217,18 +217,23 @@ namespace SHADE } // Reset Transform Data - eidData.clear(); + instancedIntegerData.clear(); // Populate on the CPU for (auto& subBatch : subBatches) for (const SHRenderable* renderable : subBatch.Renderables) { - eidData.emplace_back(renderable->GetEID()); + instancedIntegerData.emplace_back(SHInstancedIntegerData + { + renderable->GetEID(), + renderable->GetLightLayer() + } + ); } // Transfer to GPU - if (eidBuffer[frameIndex]) - eidBuffer[frameIndex]->WriteToMemory(eidData.data(), static_cast(eidData.size() * sizeof(EntityID)), 0, 0); + if (instancedIntegerBuffer[frameIndex]) + instancedIntegerBuffer[frameIndex]->WriteToMemory(instancedIntegerData.data(), static_cast(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)), 0, 0); } @@ -264,8 +269,8 @@ namespace SHADE transformData.reserve(numTotalElements); transformData.clear(); // - EID data - eidData.reserve(numTotalElements); - eidData.clear(); + instancedIntegerData.reserve(numTotalElements); + instancedIntegerData.clear(); // - Material Properties Data @@ -320,8 +325,13 @@ namespace SHADE transformData.emplace_back(transform->GetTRS()); } - eidData.emplace_back(eid); - + instancedIntegerData.emplace_back(SHInstancedIntegerData + { + eid, + renderable->GetLightLayer() + } + ); + // Material Properties if (!EMPTY_MAT_PROPS) { @@ -351,10 +361,10 @@ namespace SHADE device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES, BuffUsage::eVertexBuffer ); - const uint32_t EID_DATA_BYTES = static_cast(eidData.size() * sizeof(EntityID)); + const uint32_t EID_DATA_BYTES = static_cast(instancedIntegerData.size() * sizeof(SHInstancedIntegerData)); SHVkUtil::EnsureBufferAndCopyHostVisibleData ( - device, eidBuffer[frameIndex], eidData.data(), EID_DATA_BYTES, + device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES, BuffUsage::eVertexBuffer ); // - Material Properties Buffer @@ -378,8 +388,8 @@ namespace SHADE // Bind all required objects before drawing static std::array dynamicOffset { 0 }; cmdBuffer->BindPipeline(pipeline); - cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); - cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::EID, eidBuffer[frameIndex], 0); + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); + cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0); if (matPropsDescSet[frameIndex]) { cmdBuffer->BindDescriptorSet diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index 193fff0d..a7124e05 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -23,6 +23,7 @@ of DigiPen Institute of Technology is prohibited. #include "Math/SHMatrix.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "ECS_Base/SHECSMacros.h" +#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h" namespace SHADE { @@ -79,7 +80,7 @@ namespace SHADE void Clear(); void UpdateMaterialBuffer(uint32_t frameIndex, Handle descPool); void UpdateTransformBuffer(uint32_t frameIndex); - void UpdateEIDBuffer(uint32_t frameIndex); + void UpdateInstancedIntegerBuffer(uint32_t frameIndex); void Build(Handle device, Handle descPool, uint32_t frameIndex) ; void Draw(Handle cmdBuffer, uint32_t frameIndex); @@ -111,7 +112,7 @@ namespace SHADE // CPU Buffers std::vector drawData; std::vector transformData; - std::vector eidData; + std::vector instancedIntegerData; std::unique_ptr matPropsData; Byte matPropsDataSize = 0; Byte singleMatPropAlignedSize = 0; @@ -120,7 +121,7 @@ namespace SHADE // GPU Buffers TripleBuffer drawDataBuffer; TripleBuffer transformDataBuffer; - TripleBuffer eidBuffer; + TripleBuffer instancedIntegerBuffer; TripleBuffer matPropsBuffer; TripleDescSet matPropsDescSet; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index 14f2aa76..434e7163 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -85,7 +85,7 @@ namespace SHADE { batch.UpdateMaterialBuffer(frameIndex, descPool); batch.UpdateTransformBuffer(frameIndex); - batch.UpdateEIDBuffer(frameIndex); + batch.UpdateInstancedIntegerBuffer(frameIndex); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp index 94d1d2c5..0f1658f3 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.cpp @@ -115,7 +115,7 @@ namespace SHADE defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Normals at binding 2 defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3 defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots) - defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // EID at binding 8 + defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8 } void SHGraphicsGlobalData::Init(Handle logicalDevice) noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index f31816ce..4c3ba7f9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -182,7 +182,7 @@ namespace SHADE Vertex buffer bindings for the eid buffer. */ /***************************************************************************/ - static constexpr uint32_t EID = 5; + static constexpr uint32_t INTEGER_DATA = 5; }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index b7d4bd2f..252d4af6 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -176,18 +176,21 @@ namespace SHADE worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); - worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32G32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); - auto node = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors + auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors + auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write"); + gBufferSubpass->AddColorOutput("Scene Pre-Process"); + gBufferSubpass->AddColorOutput("Entity ID"); + gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); - //First subpass to write to G-Buffer - auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write"); - gBufferWriteSubpass->AddColorOutput("Scene Pre-Process"); - gBufferWriteSubpass->AddColorOutput("Entity ID"); - gBufferWriteSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); + auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); + gBufferNode->AddNodeCompute (kirschShader, {"Scene Pre-Process", "Scene"}); + + auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors + auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass"); + dummySubpass->AddInput("Scene"); - auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); - node->AddNodeCompute (greyscale, {"Scene Pre-Process", "Scene"}); // Generate world render graph worldRenderGraph->Generate(); @@ -201,7 +204,7 @@ namespace SHADE auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); - defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass); + defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferSubpass); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h new file mode 100644 index 00000000..8ba5adf8 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h @@ -0,0 +1,12 @@ +#pragma once + +#include "ECS_Base/SHECSMacros.h" + +namespace SHADE +{ + struct SHInstancedIntegerData + { + EntityID eid; + uint32_t lightLayer; + }; +} diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp index ebce5c9e..8b41a979 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.cpp @@ -68,7 +68,7 @@ namespace SHADE { std::vector combinedImageSampler { - std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eGeneral), + std::make_tuple(offscreenRender->GetImageView(), offscreenRenderSampler, vk::ImageLayout::eShaderReadOnlyOptimal), }; // Register the image view and sampler with the descriptor set. Now whenever rendering to the offscreen image is done, the descriptor set will see the change diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp index f8934bf6..c7ada11f 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp @@ -142,6 +142,12 @@ namespace SHADE case SHAttribFormat::UINT32_1D: return std::make_tuple(1, 4, vk::Format::eR32Uint); + case SHAttribFormat::UINT32_2D: + return std::make_tuple(1, 8, vk::Format::eR32G32Uint); + case SHAttribFormat::UINT32_3D: + return std::make_tuple(1, 12, vk::Format::eR32G32B32Uint); + case SHAttribFormat::UINT32_4D: + return std::make_tuple(1, 16, vk::Format::eR32G32B32A32Uint); } return std::make_tuple(0, 0, vk::Format::eR32Sfloat); } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index 4684419a..93be2413 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -142,6 +142,9 @@ namespace SHADE attDesc.loadOp = vk::AttachmentLoadOp::eLoad; predAttDesc.storeOp = vk::AttachmentStoreOp::eStore; + attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad; + attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore; + // TODO: Stencil load and store // When an image is done being used in a renderpass, the image layout will end up being the finalLayout diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index cf486a7a..8b21e7d1 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -51,6 +51,18 @@ namespace SHADE case vk::Format::eR32Uint: case vk::Format::eR32Sfloat: return 4; + case vk::Format::eR32G32Sint: + case vk::Format::eR32G32Uint: + case vk::Format::eR32G32Sfloat: + return 8; + case vk::Format::eR32G32B32Sint: + case vk::Format::eR32G32B32Uint: + case vk::Format::eR32G32B32Sfloat: + return 12; + case vk::Format::eR32G32B32A32Sint: + case vk::Format::eR32G32B32A32Uint: + case vk::Format::eR32G32B32A32Sfloat: + return 16; } return 0; } diff --git a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h index b216f5f4..b7191c21 100644 --- a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h +++ b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h @@ -22,6 +22,9 @@ namespace SHADE // integer formats UINT32_1D, + UINT32_2D, + UINT32_3D, + UINT32_4D, }; struct SHVertexAttribute diff --git a/TempShaderFolder/TestCubeVs.glsl b/TempShaderFolder/TestCubeVs.glsl index b7453f13..c6b4071f 100644 --- a/TempShaderFolder/TestCubeVs.glsl +++ b/TempShaderFolder/TestCubeVs.glsl @@ -3,12 +3,13 @@ //#include "ShaderDescriptorDefinitions.glsl" + layout(location = 0) in vec3 aVertexPos; layout(location = 1) in vec2 aUV; layout(location = 2) in vec3 aNormal; layout(location = 3) in vec3 aTangent; layout(location = 4) in mat4 worldTransform; -layout(location = 8) in uint eid; +layout(location = 8) in uvec2 integerData; layout(location = 0) out struct @@ -36,7 +37,7 @@ void main() { Out.uv = aUV; Out2.materialIndex = gl_InstanceIndex; - Out2.eid = eid; + Out2.eid = integerData[0]; gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); Out.vertColor = vec4 (aVertexPos, 1.0f); } \ No newline at end of file diff --git a/TempShaderFolder/TestCubeVs.spv b/TempShaderFolder/TestCubeVs.spv index 1662cfbd308b1bd28ec466201103f91aaa761084..904062a69b13a76b244a967674fc08ed38bbca58 100644 GIT binary patch literal 2376 zcmZ9N+fEcg5QbZrT@VCC6i^Wt@PLAN;2??!2)K(u!GPRuCc7hgpQk?3nB_=7Q-ledfK%)_~~{Voa|o+P%E9zcbrP>$CF< zPhs?%PD_MySwEI1IrhUCy;lM{B)K8EBY7m5lPpOpl5I(+ejVEXD3PZM$~)Ea?rwQ! zt6FO|tF82V6jY-y4yyGq32JG08o=vrfFWud}#G+(pg2*Wt@KOr$G|>(RN%9zFD7VedG(my5c=uuVDKX#%XXAB%6Nf3n`kZjK3EohpOBjWA6jbQm(y5 zD@?;iY-Qa>*70!qB9>o;SE{TIHP^TKMoS# zmS}4MV>MkN(u+BlT27lE{8T&fv)XHI@!XO5_}WOK`a$BytuKw_IO8%ies*o$5zMnQ z!k8D2X$v^Ppqafx8Qx=Ce9K+DU<{h!A1)KTArWe?}2{F^T&D`SemQ-|#>opvf z!^j85?l5wK(MyM+gE60FdE7hTcfFgGk5v&1jGP5)XB=!eSI%Mjh%H85;@q9+^TauO zTsDh4({t{a)#Tal6Pty`RuH^<_G@`-IUK;`?)*e8gk(?#@3To&5O8H>kZNVNnm? zG-qVECr-u(Cm%L*Lk@TTuyhvZk7(yCa=^!CuH5;zq!Wvue%#j1S@eT=dJ7kvcx>hn zjPu&-g+HGAT)lT?lONmh@8_IR@gGR1|6pU%rnI{^!iSLep?31%rw(ksf3OkR)7pvS zUFq9QZi5s5SUYzDCmx$wboYFc>yFPK#_Wz6AA2sx=+mNf>gIg%zsP;y{sjpfa5(h$rG(yo5{EZf&M|Fg*y|jlpN_YZWAt)Qou~J2 zB*eqV&l~+xUVN((&WFPt*6g0mo$J%OFnF%Ex6<2d+mH>$a&>G<2WziwE5|ytyV~AK YCmue2YIAjzrSrb74s7`Ulyyn+A89?W<^TWy literal 2300 zcmZ9NYflqF6oyCG7QCT&!8;aEyr6gk#0!G9T1cv3P`@^tb|sr^x6O8omrwo${Ym~R zznJ(wGdrYlnv3)p&uiVb;3AheN+ZJCA%P-md(rV$(Cd_*=yOTej}QHD^Z{d>WyZ7d%NCv z-E8%G&3^tZiJD2AM$LAdMXfyEkI;<|>Eg7N4BEqjk`%+Wl(ffT?ZGJP=hypDmRGw; zH?w?TdCoJ~H-;F_usz7_nzMu-KiTyetr=xAX8gJn=1~@h$yVBqzFJ>kedLScw&DWY z3*~!AY)P^7WiM%NrTsiiTagd7d(bZzS2ow2ZYRnDzSn3No+BR|v**YO zM=w3c8ZMC4@;9BC;#L0@mh|&#Q8JP=h^@8j4*>U({s+~ zY6|Rk31;B0X$Jdz^cl=qPK$+~5dyQG(yFYvB0Hye>H?D=OfSJ`r-k_r(ZE-Pk7yFJeYg;{zfu{v561`6I6XZ1 zz`PrB`2Ejm&0zoYn%RpS=)t@zzyBqziFM})%$35&e(1sU*Xt`E#_6{l!lX`gm6c?=k;`>FF=U;C~=P1CNGYF3afSduiz5 zz4E#z1xMd@)MfhoR7N~{{M^S+<#l)9_D91RxSur{Z_M`u{LJ#Mwij9t s*S0PU$MAJ*Xbm@9+slF*uI-gL;x}aYsm<3>)tbBXb%4?TRn}G6KNk$B#sB~S From fbb613b859a202308991120ad7dca9fff2c628a3 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Wed, 26 Oct 2022 01:16:49 +0800 Subject: [PATCH 31/35] m dumb. it work. --- .../Components/SHColliderComponent.cpp | 13 --- .../Components/SHRigidBodyComponent.cpp | 26 ----- .../Physics/Components/SHRigidBodyComponent.h | 8 +- SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 24 ---- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 106 ++++++++++-------- SHADE_Engine/src/Physics/SHPhysicsSystem.h | 4 +- 6 files changed, 66 insertions(+), 115 deletions(-) diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index 242b8d8f..c216bb83 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -69,24 +69,11 @@ namespace SHADE void SHColliderComponent::OnCreate() { system = SHSystemManager::GetSystem(); - //if (!system) - //{ - // SHLOG_ERROR("Physics system does not exist, Collider Component not added!") - // return; - //} - - //system->AddCollider(GetEID()); } void SHColliderComponent::OnDestroy() { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to remove Collider component!") - return; - } - system->RemoveCollider(GetEID()); } SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 934b67f6..1c671d23 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -32,7 +32,6 @@ namespace SHADE , mass { 1.0f } , drag { 0.01f } , angularDrag { 0.01f } - { // Set default flags: Gravity & Sleeping enabled flags |= 1U << 0; @@ -262,31 +261,6 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHRigidBodyComponent::OnCreate() - { - system = SHSystemManager::GetSystem(); - //if (!system) - //{ - // SHLOG_ERROR("Physics system does not exist, Rigid Body Component not added!") - // return; - //} - - //// Notify Physics System - //system->AddRigidBody(GetEID()); - } - - void SHRigidBodyComponent::OnDestroy() - { - // Notify Physics System - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to remove Rigid Body Component!") - return; - } - - system->RemoveRigidBody(GetEID()); - } - void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h index 03b350e1..78de84e7 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.h @@ -10,6 +10,7 @@ #pragma once +#include #include // Project Headers @@ -125,9 +126,6 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void OnCreate () override; - void OnDestroy () override; - void AddForce (const SHVec3& force) const noexcept; void AddForceAtLocalPos (const SHVec3& force, const SHVec3& localPos) const noexcept; void AddForceAtWorldPos (const SHVec3& force, const SHVec3& worldPos) const noexcept; @@ -155,7 +153,7 @@ namespace SHADE uint16_t dirtyFlags; bool interpolate; - SHPhysicsSystem* system; + rp3d::RigidBody* rp3dBody; float mass; float drag; @@ -167,8 +165,6 @@ namespace SHADE SHVec3 torque; SHVec3 angularVelocity; - // TODO(Diren): Once quaternions have replaced euler angles in transforms, store it for the rigidbody. - SHVec3 position; SHQuaternion orientation; diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 8c067482..986ce503 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -155,30 +155,6 @@ namespace SHADE return static_cast(rp3dBody->getNbColliders()) - 1; } - void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept - { - world->destroyRigidBody(reinterpret_cast(rp3dBody)); - rp3dBody = nullptr; - - if (c != nullptr) - { - // Preserve colliders as a collision body - rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation }); - for (auto& collider : c->colliders | std::views::keys) - AddCollider(&collider); - } - } - - void SHPhysicsObject::DestroyCollisionBody() noexcept - { - // Remove all colliders - for (uint32_t i = 0; i < rp3dBody->getNbColliders(); ++i) - { - auto* collider = rp3dBody->getCollider(i); - rp3dBody->removeCollider(collider); - } - } - void SHPhysicsObject::RemoveCollider(int index) { const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 76e54b09..d4da329b 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -194,6 +194,10 @@ namespace SHADE const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::AddPhysicsComponent) }; const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(ADD_COMPONENT_RECEIVER); SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR); + + const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::RemovePhysicsComponent) }; + const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(REMOVE_COMPONENT_RECEIVER); + SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR); } void SHPhysicsSystem::Exit() @@ -201,52 +205,23 @@ namespace SHADE factory.destroyPhysicsWorld(world); } - //void SHPhysicsSystem::AddRigidBody(EntityID entityID) noexcept + //void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept //{ - // //#ifdef _DEBUG - // // SHLOG_INFO("Adding a Rigidbody to the Physics World.") - // //#endif + // #ifdef _DEBUG + // SHLOG_INFO("Removing a Rigidbody from the Physics World.") + // #endif - // + // auto* physicsObject = GetPhysicsObject(entityID); + // SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") //} - //void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept + //void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept //{ - // //#ifdef _DEBUG - // // SHLOG_INFO("Adding a Collider to the Physics World.") - // //#endif - - // auto* physicsObject = EnsurePhysicsObject(entityID); - - // physicsObject->CreateCollisionBody - // ( - // SHComponentManager::GetComponent(entityID), - // SHComponentManager::GetComponent(entityID) - // ); + // #ifdef _DEBUG + // SHLOG_INFO("Removing a Collider from the Physics World.") + // #endif //} - void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept - { - #ifdef _DEBUG - SHLOG_INFO("Removing a Rigidbody from the Physics World.") - #endif - - auto* physicsObject = GetPhysicsObject(entityID); - SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") - - physicsObject->DestroyRigidBody(SHComponentManager::GetComponent_s(entityID)); - - if (physicsObject->rp3dBody == nullptr) - DestroyPhysicsObject(entityID); - } - - void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept - { - #ifdef _DEBUG - SHLOG_INFO("Removing a Collider from the Physics World.") - #endif - } - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) { auto* physicsObject = GetPhysicsObject(entityID); @@ -255,7 +230,8 @@ namespace SHADE void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index) { - + auto* physicsObject = GetPhysicsObject(entityID); + physicsObject->RemoveCollider(index); } void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept @@ -471,8 +447,8 @@ namespace SHADE static const auto RIGID_BODY_ID = ComponentFamily::GetID(); static const auto COLLIDER_ID = ComponentFamily::GetID(); - const auto COMPONENT_ADDED_ID = EVENT_DATA->data->addedComponentType; - const bool IS_PHYSICS_COMPONENT = COMPONENT_ADDED_ID == RIGID_BODY_ID || COMPONENT_ADDED_ID == COLLIDER_ID; + const auto ADDED_ID = EVENT_DATA->data->addedComponentType; + const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID; if (IS_PHYSICS_COMPONENT) { const EntityID ENTITY_ID = EVENT_DATA->data->eid; @@ -488,7 +464,7 @@ namespace SHADE auto* rigidBodyComponent = SHComponentManager::GetComponent_s(ENTITY_ID); auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); - if (COMPONENT_ADDED_ID == RIGID_BODY_ID) + if (ADDED_ID == RIGID_BODY_ID) { if (colliderComponent != nullptr) { @@ -513,7 +489,7 @@ namespace SHADE } } - if (COMPONENT_ADDED_ID == COLLIDER_ID) + if (ADDED_ID == COLLIDER_ID) { colliderComponent->position = transformComponent->GetWorldPosition(); colliderComponent->orientation = transformComponent->GetWorldOrientation(); @@ -539,6 +515,48 @@ namespace SHADE { const auto& EVENT_DATA = reinterpret_cast*>(removeComponentEvent.get()); + static const auto RIGID_BODY_ID = ComponentFamily::GetID(); + static const auto COLLIDER_ID = ComponentFamily::GetID(); + + const auto REMOVED_ID = EVENT_DATA->data->removedComponentType; + const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID; + if (IS_PHYSICS_COMPONENT) + { + const EntityID ENTITY_ID = EVENT_DATA->data->eid; + auto* physicsObject = GetPhysicsObject(ENTITY_ID); + + SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") + + if (REMOVED_ID == RIGID_BODY_ID) + { + world->destroyRigidBody(reinterpret_cast(physicsObject->rp3dBody)); + physicsObject->rp3dBody = nullptr; + + auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); + if (colliderComponent != nullptr) + { + // Preserve colliders as a collision body + physicsObject->rp3dBody = world->createCollisionBody + ( + rp3d::Transform{ colliderComponent->position, colliderComponent->orientation } + ); + + for (auto& collider : colliderComponent->colliders | std::views::keys) + physicsObject->AddCollider(&collider); + } + } + + if (REMOVED_ID == COLLIDER_ID) + { + // Remove all colliders + for (uint32_t i = 0; i < physicsObject->rp3dBody->getNbColliders(); ++i) + physicsObject->rp3dBody->removeCollider(physicsObject->rp3dBody->getCollider(i)); + } + + if (physicsObject->rp3dBody == nullptr) + DestroyPhysicsObject(ENTITY_ID); + } + return EVENT_DATA->handle; } diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/SHPhysicsSystem.h index d88f8c06..0af22e7a 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.h @@ -87,8 +87,8 @@ namespace SHADE //void AddRigidBody (EntityID entityID) noexcept; //void AddCollider (EntityID entityID) noexcept; - void RemoveRigidBody (EntityID entityID) noexcept; - void RemoveCollider (EntityID entityID) noexcept; + //void RemoveRigidBody (EntityID entityID) noexcept; + //void RemoveCollider (EntityID entityID) noexcept; void AddCollisionShape (EntityID entityID, SHCollider* collider); void RemoveCollisionShape (EntityID entityID, int index); From 7ba02aeb0fb7fd5f1e2292078b32ed7c98933287 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Wed, 26 Oct 2022 01:46:13 +0800 Subject: [PATCH 32/35] Removed unused functions, fixed RigidBody --- SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp | 1 - SHADE_Engine/src/Physics/SHPhysicsObject.h | 5 ----- 2 files changed, 6 deletions(-) diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 1c671d23..8327c3ec 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -28,7 +28,6 @@ namespace SHADE , flags { 0 } , dirtyFlags { 0 } , interpolate { true } - , system { nullptr } , mass { 1.0f } , drag { 0.01f } , angularDrag { 0.01f } diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.h b/SHADE_Engine/src/Physics/SHPhysicsObject.h index 11e41ad1..67e5ec64 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.h +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.h @@ -69,13 +69,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void CreateRigidBody (const SHVec3& pos, const SHQuaternion& orientation); - void CreateCollisionBody (const SHVec3& pos, const SHQuaternion& orientation); int AddCollider (SHCollider* collider); - - void DestroyRigidBody (SHColliderComponent* c) noexcept; void RemoveCollider (int index); - void DestroyCollisionBody () noexcept; void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept; void SyncColliders (SHColliderComponent* c) const noexcept; From 5637fb707f7f24e905c43516c399019af1f8ec31 Mon Sep 17 00:00:00 2001 From: Brandon Mak Date: Wed, 26 Oct 2022 02:14:43 +0800 Subject: [PATCH 33/35] Tested light component. Values reflected in renderdoc correctly - Added pure copy compute shader (used instead of kirsch) - Created sparse set for lights - Note that while the instanced attribute contains both EID and layer light index and in the future potentially more, the objects still write to a uint framebuffer. - Light layer index is in a different frame buffer than the eid one. - Updated shaders to accommodate light layer index. --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 + .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 25 +++++-- .../MiddleEnd/Interface/SHMousePickSystem.cpp | 3 +- .../MiddleEnd/Lights/SHLightingSubSystem.cpp | 2 + TempShaderFolder/PureCopyCs.glsl | 67 ++++++++++++++++++ TempShaderFolder/PureCopyCs.spv | Bin 0 -> 1264 bytes TempShaderFolder/TestCubeFs.glsl | 3 + TempShaderFolder/TestCubeFs.spv | Bin 2156 -> 2300 bytes TempShaderFolder/TestCubeVs.glsl | 4 +- TempShaderFolder/TestCubeVs.spv | Bin 2376 -> 2492 bytes 10 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 TempShaderFolder/PureCopyCs.glsl create mode 100644 TempShaderFolder/PureCopyCs.spv diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index b414ecaf..9c178429 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -12,6 +12,7 @@ #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Physics/Components/SHRigidBodyComponent.h" #include "Physics/Components/SHColliderComponent.h" +#include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Assets/SHAssetManager.h" #include "Camera/SHCameraComponent.h" @@ -158,6 +159,7 @@ namespace Sandbox scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase"); SHComponentManager::AddComponent(0); + SHComponentManager::AddComponent(0); SHComponentManager::RemoveComponent (0); SHComponentManager::RemoveComponent (0); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 252d4af6..7b8b9e45 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -125,14 +125,17 @@ namespace SHADE shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true); shaderSourceLibrary.LoadShader(2, "KirschCs.glsl", SH_SHADER_TYPE::COMPUTE, true); + shaderSourceLibrary.LoadShader(3, "PureCopyCs.glsl", SH_SHADER_TYPE::COMPUTE, true); shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary); auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl"); auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl"); auto greyscale = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); + auto pureCopy = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl"); cubeVS->Reflect(); cubeFS->Reflect(); greyscale->Reflect(); + pureCopy->Reflect(); } void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept @@ -173,19 +176,27 @@ namespace SHADE // Initialize world render graph worldRenderGraph->Init(device, swapchain); - worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); - worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); - worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); - worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32G32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Scene Pre-Process", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); + worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); + worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); + worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); + worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); - auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors + auto gBufferNode = worldRenderGraph->AddNode("G-Buffer", { "Light Layer Indices", "Entity ID", "Depth Buffer", "Scene", "Scene Pre-Process"}, {}); // no predecessors auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write"); gBufferSubpass->AddColorOutput("Scene Pre-Process"); gBufferSubpass->AddColorOutput("Entity ID"); + gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); - auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); - gBufferNode->AddNodeCompute (kirschShader, {"Scene Pre-Process", "Scene"}); + //// kirsch + //auto kirschShader = shaderModuleLibrary.GetShaderModule("KirschCs.glsl"); + //gBufferNode->AddNodeCompute(kirschShader, { "Scene Pre-Process", "Scene" }); + + // copy + auto pureCopyShader = shaderModuleLibrary.GetShaderModule("PureCopyCs.glsl"); + gBufferNode->AddNodeCompute(pureCopyShader, { "Scene Pre-Process", "Scene" }); + auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, {"G-Buffer"}); // no predecessors auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass"); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp index 57a08d47..46126ae1 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMousePickSystem.cpp @@ -7,6 +7,7 @@ #include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/SHVkUtil.h" #include "Graphics/MiddleEnd/Interface/SHViewport.h" +//#include "Graphics/MiddleEnd/Interface/SHInstancedIntegerData.h" namespace SHADE { @@ -53,7 +54,7 @@ namespace SHADE // wait for the copy to be done afterCopyFence->Wait(true, std::numeric_limits::max()); - pickedEID = imageDataDstBuffer->GetDataFromMappedPointer(static_cast(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast(viewportMousePos.x)); + pickedEID = imageDataDstBuffer->GetDataFromMappedPointer(static_cast(viewportMousePos.y) * entityIDAttachment->GetWidth() + static_cast(viewportMousePos.x)); } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp index 30bbd363..8d9efe54 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Lights/SHLightingSubSystem.cpp @@ -329,6 +329,8 @@ namespace SHADE /***************************************************************************/ void SHLightingSubSystem::Init(Handle device, Handle descPool) noexcept { + SHComponentManager::CreateComponentSparseSet(); + logicalDevice = device; uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES); diff --git a/TempShaderFolder/PureCopyCs.glsl b/TempShaderFolder/PureCopyCs.glsl new file mode 100644 index 00000000..89da6dd9 --- /dev/null +++ b/TempShaderFolder/PureCopyCs.glsl @@ -0,0 +1,67 @@ +//#version 450 +// +//layout(local_size_x = 16, local_size_y = 16) in; +//layout(set = 4, binding = 0, rgba8) uniform image2D targetImage; +// +// +//void main() +//{ +// ivec2 imageSize = imageSize (targetImage); +// +// if (gl_GlobalInvocationID.x >= imageSize.x && gl_GlobalInvocationID.y >= imageSize.y) +// return; +// +// // load the image +// vec4 color = imageLoad (targetImage, ivec2 (gl_GlobalInvocationID)); +// +// // get the average +// float average = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; +// +// // store result into result image +// imageStore(targetImage, ivec2(gl_GlobalInvocationID), vec4(average, average, average, 1.0f)); +// +//} +// +// +// +// + +/* Start Header *****************************************************************/ + +/*! \file (e.g. kirsch.comp) + + \author William Zheng, william.zheng, 60001906. Brandon Mak, brandon.hao 390003920. + + \par william.zheng\@digipen.edu. brandon.hao\@digipen.edu. + + \date Sept 20, 2022 + + \brief Copyright (C) 20xx DigiPen Institute of Technology. + + Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. */ + + /* End Header *******************************************************************/ + +#version 450 + + +layout(local_size_x = 16, local_size_y = 16) in; +layout(set = 4, binding = 0, rgba8) uniform image2D inputImage; +layout(set = 4, binding = 1, rgba8) uniform image2D targetImage; + + +void main() +{ + // convenient variables + ivec2 globalThread = ivec2(gl_GlobalInvocationID); + + vec3 color = imageLoad (inputImage, globalThread).rgb; + + // store result into result image + imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1.0f)); + +} + + + + diff --git a/TempShaderFolder/PureCopyCs.spv b/TempShaderFolder/PureCopyCs.spv new file mode 100644 index 0000000000000000000000000000000000000000..bf967bbf80b801df07d30879ae29890b7e7b147b GIT binary patch literal 1264 zcmYk5TTj$b6oog;6bBFx5%6wDR8(;EL5+z~Uo_1mlMF`Ro6>2G_QEbd(~Td);dvzK;pHf>Ri*{Ur$8;!n=2B-C8@cPXw6zkS; zLNpuF1hQS>B*{wxYr-}0aGUOqPZiUX9c4HBBd4pX(I}3_<7o6HPG__DwEkISagmo< zJjv%-TIc5(x?W3{muYb}X$t}=+Vum~URI51Q5`46_aE~tnaEY2J=fc`h$9yomgiNP z)Ol47Kf8F>c4gD5sOHWO?6z!P&d%!LNitP0f&M~qbuyo34H>CAGp`DF1$>@+DA1Sp z`?_=RL)ms5pZJ16d>~7{Tf&w$#?Ja~d*<%j(kzJ!1)kZJuNUb!w4wZ-EF3_;;&}bj zK~H`--X{91vgCq)-}ubs^Ka-*P4qkZe?vAD$h9qt?{n?weo>bhmhEN}Cs+H>D?6e- zvvSZ|j!;#19o;Msl9w{?( X9SA&+p7_3yst)~9m-s(*^G^5=Amdbt literal 0 HcmV?d00001 diff --git a/TempShaderFolder/TestCubeFs.glsl b/TempShaderFolder/TestCubeFs.glsl index 18890c92..4dc6deca 100644 --- a/TempShaderFolder/TestCubeFs.glsl +++ b/TempShaderFolder/TestCubeFs.glsl @@ -23,6 +23,7 @@ layout(location = 2) flat in struct { int materialIndex; uint eid; + uint lightLayerIndex; } In2; //layout (set = 0, binding = ) @@ -35,6 +36,7 @@ layout (set = 3, binding = 0) buffer MaterialProperties // For materials layout(location = 0) out vec4 outColor; layout(location = 1) out uint outEntityID; +layout(location = 2) out uint lightLayerIndices; void main() { @@ -42,5 +44,6 @@ void main() MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha; outEntityID = In2.eid; + lightLayerIndices = In2.lightLayerIndex; //outColor = vec4 (1.0f); } \ No newline at end of file diff --git a/TempShaderFolder/TestCubeFs.spv b/TempShaderFolder/TestCubeFs.spv index bde6213644b38cb5e844a04ac20ad1ca3e43b62c..9955abe53ff6b413215a81ed14c71a2cae54e69d 100644 GIT binary patch delta 209 zcmaDO@JEoBnMs+Qfq{{Mi-DKHWg>4bBiF=gMMlSsGoLd`voWwUNH8!kFadE+W_m`6 zPhw?ik!M~?YQ^MwrbKC0pu8ixTxN1=F$2Tq`%H$6yzUGvUlUf`^{+K$iT{A2jn^du@n%S0#cgLy1J`o2M4Byo!jAdyHWSn6>Gm6kj1$XR}Xum`Jp-6&pWeox39w( zbAy2hXRm&&nqk-K@$!W=~iU_!5oP&8H|b`< zUJG{av%cXRG2CHgJr6o}@t-~i{g8B4-3>d_*L)sju}_xMPV_zaYQaaoDDG@=xoZ-y ze$AVHGs+4!_3}!voHF&y4(HEAuU{oJSR$kNI;6y7pU^Jq277Jcqzsk%Bp%(bm7VJv)A^xG4E$)PmI^|nP;@)Ch)UXvt=kcv4$(E1z zqQ5L^WJnhLT9o-vVyGnyj_f@vM0&mCQp-l~jnB0c&qK5;@!XNw`PR*n&d1EB{V&~Y zt>7|GzPPsTh^-dp%fA)HCm|oR=0Ey$HA*?cHN>I6696qRJqA+?n4W-n3ovs`%uI=y zY5Y4SOFD&jW5HpWjeOYH%|=dayrtRDu`#<1d8`lk?d_)JV=ak=jhsUP7aTC0ecNpM zz=Msv#MzyA=QG>zlrW1s^XA;KsHqmdT`&uOQ+xG|cxNzoIjB=OXG#c+eneVb`=sQk z;;9QvelTwdhC3n5w+aXQr0{O-mT=rL(AETs!BH2R@kDvKmfECl)_% za!NaA@g~IczHqS<4`vpzabC4%_*13N>OCt=ez4VdUOM?L{(^M!omBjcc6x$sLfRGW z);D|z=UmlJUi{Pr=05@3xbQXY#L;Vd%N&BS6MsWHHDD(m%zWCtZPyPqm@nMG#=D!0Q_lEme;@r`X8m%W+XUIW9;n$0h05Eyrc)f`s$oa0mMSLc;9YTZ7?QZ7-!)YikH&V_6+b(y>)*TP|(Y+Fr>gpQk?3nB_=7Q-ledfK%)_~~{Voa|o+P%E9zcbrP>$CF< zPhs?%PD_MySwEI1IrhUCy;lM{B)K8EBY7m5lPpOpl5I(+ejVEXD3PZM$~)Ea?rwQ! zt6FO|tF82V6jY-y4yyGq32JG08o=vrfFWud}#G+(pg2*Wt@KOr$G|>(RN%9zFD7VedG(my5c=uuVDKX#%XXAB%6Nf3n`kZjK3EohpOBjWA6jbQm(y5 zD@?;iY-Qa>*70!qB9>o;SE{TIHP^TKMoS# zmS}4MV>MkN(u+BlT27lE{8T&fv)XHI@!XO5_}WOK`a$BytuKw_IO8%ies*o$5zMnQ z!k8D2X$v^Ppqafx8Qx=Ce9K+DU<{h!A1)KTArWe?}2{F^T&D`SemQ-|#>opvf z!^j85?l5wK(MyM+gE60FdE7hTcfFgGk5v&1jGP5)XB=!eSI%Mjh%H85;@q9+^TauO zTsDh4({t{a)#Tal6Pty`RuH^<_G@`-IUK;`?)*e8gk(?#@3To&5O8H>kZNVNnm? zG-qVECr-u(Cm%L*Lk@TTuyhvZk7(yCa=^!CuH5;zq!Wvue%#j1S@eT=dJ7kvcx>hn zjPu&-g+HGAT)lT?lONmh@8_IR@gGR1|6pU%rnI{^!iSLep?31%rw(ksf3OkR)7pvS zUFq9QZi5s5SUYzDCmx$wboYFc>yFPK#_Wz6AA2sx=+mNf>gIg%zsP;y{sjpfa5(h$rG(yo5{EZf&M|Fg*y|jlpN_YZWAt)Qou~J2 zB*eqV&l~+xUVN((&WFPt*6g0mo$J%OFnF%Ex6<2d+mH>$a&>G<2WziwE5|ytyV~AK YCmue2YIAjzrSrb74s7`Ulyyn+A89?W<^TWy From 7c0bcd8a3e2f839ae4792123ce2ed0babfd55961 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Wed, 26 Oct 2022 16:09:54 +0800 Subject: [PATCH 34/35] Delete UserLayout.ini @Xenosas1337 stop pushing this please --- Assets/Editor/Layouts/UserLayout.ini | 62 ---------------------------- 1 file changed, 62 deletions(-) delete mode 100644 Assets/Editor/Layouts/UserLayout.ini diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini deleted file mode 100644 index e27f5cca..00000000 --- a/Assets/Editor/Layouts/UserLayout.ini +++ /dev/null @@ -1,62 +0,0 @@ -[Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 -Collapsed=0 - -[Window][SHEditorMenuBar] -Pos=0,48 -Size=1920,1012 -Collapsed=0 - -[Window][Hierarchy Panel] -Pos=0,142 -Size=494,690 -Collapsed=0 -DockId=0x00000007,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Inspector] -Pos=1649,48 -Size=271,1012 -Collapsed=0 -DockId=0x00000006,0 - -[Window][Profiler] -Pos=0,48 -Size=494,92 -Collapsed=0 -DockId=0x00000003,0 - -[Window][Viewport] -Pos=648,48 -Size=2519,1319 -Collapsed=0 -DockId=0x00000002,0 - -[Window][ Viewport] -Pos=496,48 -Size=1151,1012 -Collapsed=0 -DockId=0x00000002,0 - -[Window][ Asset Browser] -Pos=0,834 -Size=494,226 -Collapsed=0 -DockId=0x00000008,0 - -[Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=494,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Split=Y Selected=0xE096E5AE - DockNode ID=0x00000007 Parent=0x00000004 SizeRef=494,690 Selected=0xE096E5AE - DockNode ID=0x00000008 Parent=0x00000004 SizeRef=494,226 Selected=0xB128252A - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1151,1036 CentralNode=1 Selected=0xB41284E7 - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 - From 58491fcbffa9800095c32b03f9c3e8cc4d4304be Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Wed, 26 Oct 2022 16:17:22 +0800 Subject: [PATCH 35/35] Fixed physics bugs 1. Colliders are now properly deleted along with its component. 2. Forces and velocities are reset on stop. --- .../Components/SHColliderComponent.cpp | 33 ++-- .../Physics/Components/SHColliderComponent.h | 8 +- .../Components/SHRigidBodyComponent.cpp | 159 ++++++++++++++++-- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 91 ++++++---- 4 files changed, 223 insertions(+), 68 deletions(-) diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp index c216bb83..75a00491 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.cpp @@ -26,7 +26,6 @@ namespace SHADE SHColliderComponent::SHColliderComponent() noexcept : system { nullptr } - , colliders {} {} /*-----------------------------------------------------------------------------------*/ @@ -78,9 +77,15 @@ namespace SHADE SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept { - const auto TYPE = SHCollider::Type::BOX; + if (!system) + { + SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!") + return nullptr; + } - auto boxPair = std::make_pair(SHCollider{TYPE}, true); + static constexpr auto TYPE = SHCollider::Type::BOX; + + auto boxPair = std::make_pair(SHCollider{ TYPE }, true); auto& collider = colliders.emplace_back(boxPair).first; const auto* tf = SHComponentManager::GetComponent(GetEID()); @@ -88,12 +93,6 @@ namespace SHADE collider.SetPositionOffset(posOffset); collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents); - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!") - return nullptr; - } - // Notify Physics System system->AddCollisionShape(GetEID(), &collider); @@ -102,7 +101,13 @@ namespace SHADE SHBoundingSphere* SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept { - const auto TYPE = SHCollider::Type::SPHERE; + if (!system) + { + SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") + return nullptr; + } + + static constexpr auto TYPE = SHCollider::Type::SPHERE; auto spherePair = std::make_pair(SHCollider{ TYPE }, true); auto& collider = colliders.emplace_back(spherePair).first; @@ -113,13 +118,7 @@ namespace SHADE const SHVec3 TF_WORLD_SCALE = tf->GetWorldScale(); const float MAX_SCALE = SHMath::Max({ TF_WORLD_SCALE.x, TF_WORLD_SCALE.y, TF_WORLD_SCALE.z }); - collider.SetAsBoundingSphere(MAX_SCALE * 0.5f); - - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") - return nullptr; - } + collider.SetAsBoundingSphere(MAX_SCALE * 0.5f * radius); // Notify Physics System system->AddCollisionShape(GetEID(), &collider); diff --git a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h index 22d5ceee..4ecd0e93 100644 --- a/SHADE_Engine/src/Physics/Components/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Components/SHColliderComponent.h @@ -44,7 +44,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ using ColliderDirtyPair = std::pair; - using Colliders = std::vector; + using Colliders = std::vector; public: @@ -81,10 +81,10 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void OnCreate () override; - void OnDestroy () override; + void OnCreate () override; + void OnDestroy () override; - void RemoveCollider (int index); + void RemoveCollider (int index); SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept; SHBoundingSphere* AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; diff --git a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp index 8327c3ec..b0172f64 100644 --- a/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Components/SHRigidBodyComponent.cpp @@ -28,6 +28,7 @@ namespace SHADE , flags { 0 } , dirtyFlags { 0 } , interpolate { true } + , rp3dBody { nullptr } , mass { 1.0f } , drag { 0.01f } , angularDrag { 0.01f } @@ -159,7 +160,13 @@ namespace SHADE void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept { - constexpr int FLAG_POS = 0; + static constexpr int FLAG_POS = 0; + + if (type != Type::DYNAMIC) + { + SHLOG_WARNING("Cannot enable gravity of a non-dynamic object {}", GetEID()) + return; + } dirtyFlags |= 1U << FLAG_POS; enableGravity ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -167,7 +174,13 @@ namespace SHADE void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept { - constexpr int FLAG_POS = 1; + static constexpr int FLAG_POS = 1; + + if (type != Type::DYNAMIC) + { + SHLOG_WARNING("Cannot enable sleeping of a non-dynamic object {}", GetEID()) + return; + } dirtyFlags |= 1U << 1; isAllowedToSleep ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -175,7 +188,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept { - constexpr int FLAG_POS = 2; + static constexpr int FLAG_POS = 2; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 2; freezePositionX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -183,7 +202,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept { - constexpr int FLAG_POS = 3; + static constexpr int FLAG_POS = 3; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 2; freezePositionY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -191,7 +216,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept { - constexpr int FLAG_POS = 4; + static constexpr int FLAG_POS = 4; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 2; freezePositionZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -199,7 +230,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept { - constexpr int FLAG_POS = 5; + static constexpr int FLAG_POS = 5; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 3; freezeRotationX ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -207,7 +244,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept { - constexpr int FLAG_POS = 6; + static constexpr int FLAG_POS = 6; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 3; freezeRotationY ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -215,7 +258,13 @@ namespace SHADE void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept { - constexpr int FLAG_POS = 7; + static constexpr int FLAG_POS = 7; + + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) + return; + } dirtyFlags |= 1U << 3; freezeRotationZ ? flags |= (1U << FLAG_POS) : flags &= ~(1U << FLAG_POS); @@ -228,30 +277,60 @@ namespace SHADE void SHRigidBodyComponent::SetMass(float newMass) noexcept { + if (type != Type::DYNAMIC) + { + SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) + return; + } + dirtyFlags |= 1U << 5; mass = newMass; } void SHRigidBodyComponent::SetDrag(float newDrag) noexcept { + if (type != Type::DYNAMIC) + { + SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID()) + return; + } + dirtyFlags |= 1U << 6; drag = newDrag; } void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept { + if (type != Type::DYNAMIC) + { + SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID()) + return; + } + dirtyFlags |= 1U << 7; angularDrag = newAngularDrag; } void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept { + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID()) + return; + } + dirtyFlags |= 1U << 8; linearVelocity = newLinearVelocity; } void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept { + if (type == Type::STATIC) + { + SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID()) + return; + } + dirtyFlags |= 1U << 9; angularVelocity = newAngularVelocity; } @@ -262,42 +341,90 @@ namespace SHADE void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyWorldForceAtCenterOfMass(force); } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyWorldForceAtLocalPosition(force, localPos); } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyWorldForceAtWorldPosition(force, worldPos); } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyLocalForceAtCenterOfMass(relativeForce); } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyLocalForceAtLocalPosition(relativeForce, localPos); } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyLocalForceAtWorldPosition(relativeForce, worldPos); } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyWorldTorque(torque); } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - + if (rp3dBody == nullptr) + { + SHLOGV_ERROR("Entity {} is missing an rp3dBody!", GetEID()) + return; + } + + rp3dBody->applyLocalTorque(relativeTorque); } } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index d4da329b..389e518f 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -16,6 +16,8 @@ // Project Headers #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Editor/SHEditor.hpp" #include "Math/SHMathHelpers.h" #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformComponent.h" @@ -205,23 +207,6 @@ namespace SHADE factory.destroyPhysicsWorld(world); } - //void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept - //{ - // #ifdef _DEBUG - // SHLOG_INFO("Removing a Rigidbody from the Physics World.") - // #endif - - // auto* physicsObject = GetPhysicsObject(entityID); - // SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!") - //} - - //void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept - //{ - // #ifdef _DEBUG - // SHLOG_INFO("Removing a Collider from the Physics World.") - // #endif - //} - void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider) { auto* physicsObject = GetPhysicsObject(entityID); @@ -238,24 +223,55 @@ namespace SHADE { auto* system = reinterpret_cast(GetSystem()); - // Update bodies and colliders if component is dirty - system->SyncRigidBodyComponents(SHComponentManager::GetDense()); - system->SyncColliderComponents(SHComponentManager::GetDense()); - // Sync transforms - for (auto& physicsObject : system->map | std::views::values) + for (auto& [entityID, physicsObject] : system->map) { // Ensure a valid physics Object if (physicsObject.rp3dBody == nullptr) continue; - const auto* TF = SHComponentManager::GetComponent(physicsObject.entityID); - if (TF->HasChanged()) + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + + // Clear all forces and velocities if editor is not in play + if (SHSystemManager::GetSystem()->editorState == SHEditor::State::STOP) { - physicsObject.SetPosition(TF->GetWorldPosition()); - physicsObject.SetOrientation(TF->GetWorldOrientation()); + if (rigidBodyComponent) + { + auto* rp3dRigidBody = reinterpret_cast(physicsObject.rp3dBody); + rp3dRigidBody->resetForce(); + rp3dRigidBody->resetTorque(); + rp3dRigidBody->setLinearVelocity(SHVec3::Zero); + rp3dRigidBody->setAngularVelocity(SHVec3::Zero); + } + } + + const auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + if (transformComponent && transformComponent->HasChanged()) + { + const auto WORLD_POS = transformComponent->GetWorldPosition(); + const auto WORLD_ROT = transformComponent->GetWorldOrientation(); + + physicsObject.SetPosition(WORLD_POS); + physicsObject.SetOrientation(WORLD_ROT); + + if (rigidBodyComponent) + { + rigidBodyComponent->position = WORLD_POS; + rigidBodyComponent->orientation = WORLD_ROT; + } + + auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); + if (colliderComponent) + { + colliderComponent->position = WORLD_POS; + colliderComponent->orientation = WORLD_ROT; + } } } + + // Update bodies and colliders if component is dirty + system->SyncRigidBodyComponents(SHComponentManager::GetDense()); + system->SyncColliderComponents(SHComponentManager::GetDense()); } void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept @@ -431,9 +447,9 @@ namespace SHADE } // Convert RP3D Transform to SHADE - auto* tfComponent = SHComponentManager::GetComponent(entityID); - tfComponent->SetWorldPosition(rp3dPos); - tfComponent->SetWorldOrientation(rp3dRot); + auto* transformComponent = SHComponentManager::GetComponent(entityID); + transformComponent->SetWorldPosition(rp3dPos); + transformComponent->SetWorldOrientation(rp3dRot); // Cache transforms physicsObject.prevTransform = CURRENT_TF; @@ -480,6 +496,7 @@ namespace SHADE rp3d::Transform{ rigidBodyComponent->position, rigidBodyComponent->orientation } ); + rigidBodyComponent->rp3dBody = reinterpret_cast(physicsObject->rp3dBody); // Add collision shapes back into the body if (colliderComponent != nullptr) @@ -491,6 +508,8 @@ namespace SHADE if (ADDED_ID == COLLIDER_ID) { + SHASSERT(colliderComponent != nullptr, "Collider Component was not added to Entity " + std::to_string(ENTITY_ID) + "!"); + colliderComponent->position = transformComponent->GetWorldPosition(); colliderComponent->orientation = transformComponent->GetWorldOrientation(); @@ -530,7 +549,7 @@ namespace SHADE if (REMOVED_ID == RIGID_BODY_ID) { world->destroyRigidBody(reinterpret_cast(physicsObject->rp3dBody)); - physicsObject->rp3dBody = nullptr; + physicsObject->rp3dBody = nullptr; auto* colliderComponent = SHComponentManager::GetComponent_s(ENTITY_ID); if (colliderComponent != nullptr) @@ -544,13 +563,23 @@ namespace SHADE for (auto& collider : colliderComponent->colliders | std::views::keys) physicsObject->AddCollider(&collider); } + + // Wake up all physics objects + for (auto& [entityID, object] : map) + { + if (SHComponentManager::HasComponent(entityID)) + reinterpret_cast(object.rp3dBody)->setIsSleeping(false); + } } if (REMOVED_ID == COLLIDER_ID) { // Remove all colliders for (uint32_t i = 0; i < physicsObject->rp3dBody->getNbColliders(); ++i) - physicsObject->rp3dBody->removeCollider(physicsObject->rp3dBody->getCollider(i)); + { + auto* collider = physicsObject->rp3dBody->getCollider(i); + physicsObject->rp3dBody->removeCollider(collider); + } } if (physicsObject->rp3dBody == nullptr)