Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
5 changed files with 115 additions and 44 deletions
Showing only changes of commit 36ceec5855 - Show all commits

View File

@ -38,4 +38,14 @@ namespace SHADE
SHSceneNode* childRemoved = nullptr; SHSceneNode* childRemoved = nullptr;
}; };
struct SHSceneInitEvent
{
uint32_t sceneID = std::numeric_limits<uint32_t>::max();
};
struct SHSceneExitEvent
{
uint32_t sceneID = std::numeric_limits<uint32_t>::max();
};
} // namespace SHADE } // namespace SHADE

View File

@ -27,7 +27,7 @@ namespace SHADE
: root { nullptr } : root { nullptr }
{ {
// The root is set to the maximum entity. It should not be interfaced with. // The root is set to the maximum entity. It should not be interfaced with.
root = AllocateNode(MAX_EID); root = allocateNode(MAX_EID);
} }
SHSceneGraph::~SHSceneGraph() noexcept SHSceneGraph::~SHSceneGraph() noexcept
@ -239,7 +239,7 @@ namespace SHADE
if (newParent == nullptr) if (newParent == nullptr)
newParent = root; newParent = root;
ChangeParent(NODE_ITER->second, newParent); changeParent(NODE_ITER->second, newParent);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
@ -284,7 +284,7 @@ namespace SHADE
}; };
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
ChangeParent(currentNode, PARENT_ITER->second); changeParent(currentNode, PARENT_ITER->second);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
} }
@ -310,7 +310,7 @@ namespace SHADE
return NODE_ITER->second; return NODE_ITER->second;
} }
SHSceneNode* newNode = AllocateNode(entityID); SHSceneNode* newNode = allocateNode(entityID);
if (parent == nullptr) if (parent == nullptr)
{ {
@ -320,7 +320,7 @@ namespace SHADE
} }
else else
{ {
ChangeParent(newNode, parent); changeParent(newNode, parent);
} }
return newNode; return newNode;
@ -347,9 +347,9 @@ namespace SHADE
// Remove reference of current node from parent // Remove reference of current node from parent
SHSceneNode* currentNode = NODE_ITER->second; SHSceneNode* currentNode = NODE_ITER->second;
if (currentNode->parent != nullptr) if (currentNode->parent != nullptr)
RemoveChild(currentNode->parent, currentNode); removeChild(currentNode->parent, currentNode);
ReleaseNode(currentNode); releaseNode(currentNode);
return true; return true;
} }
@ -357,16 +357,16 @@ namespace SHADE
{ {
// Remove reference of current node from parent // Remove reference of current node from parent
if (nodeToRemove->parent != nullptr) if (nodeToRemove->parent != nullptr)
RemoveChild(nodeToRemove->parent, nodeToRemove); removeChild(nodeToRemove->parent, nodeToRemove);
ReleaseNode(nodeToRemove); releaseNode(nodeToRemove);
return true; return true;
} }
void SHSceneGraph::Reset() noexcept void SHSceneGraph::Reset() noexcept
{ {
for (auto* node : entityNodeMap | std::views::values) for (auto* node : entityNodeMap | std::views::values)
ReleaseNode(node); releaseNode(node);
} }
bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept
@ -456,39 +456,39 @@ namespace SHADE
void SHSceneGraph::Traverse (const UnaryFunction& function) const void SHSceneGraph::Traverse (const UnaryFunction& function) const
{ {
TraverseAndInvokeFunction(root, function); traverseAndInvokeFunction(root, function);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */ /* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID) SHSceneNode* SHSceneGraph::allocateNode(EntityID entityID)
{ {
SHSceneNode* newNode = new SHSceneNode{entityID}; SHSceneNode* newNode = new SHSceneNode{entityID};
entityNodeMap.emplace(entityID, newNode); entityNodeMap.emplace(entityID, newNode);
return newNode; return newNode;
} }
void SHSceneGraph::ReleaseNode(SHSceneNode* node) noexcept void SHSceneGraph::releaseNode(SHSceneNode* node) noexcept
{ {
SHASSERT(node != nullptr, "Attempting to release Invalid Node!") SHASSERT(node != nullptr, "Attempting to release Invalid Node!")
// Remove parent's reference to this node if there is a parent // Remove parent's reference to this node if there is a parent
if (node->parent != nullptr) if (node->parent != nullptr)
RemoveChild(node->parent, node); removeChild(node->parent, node);
// Remove child's references to this node. Children end up as floating nodes. // Remove child's references to this node. Children end up as floating nodes.
for (auto* child : node->GetChildren()) for (auto* child : node->GetChildren())
{ {
ChangeParent(child, nullptr); changeParent(child, nullptr);
} }
entityNodeMap.erase(node->GetEntityID()); entityNodeMap.erase(node->GetEntityID());
delete node; delete node;
} }
void SHSceneGraph::ChangeParent(SHSceneNode* node, SHSceneNode* newParent) void SHSceneGraph::changeParent(SHSceneNode* node, SHSceneNode* newParent)
{ {
// Handle self assignment // Handle self assignment
if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID) if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID)
@ -496,7 +496,7 @@ namespace SHADE
// Remove child // Remove child
if (node->parent) if (node->parent)
RemoveChild(node->parent, node); removeChild(node->parent, node);
if (newParent == nullptr) if (newParent == nullptr)
{ {
@ -506,16 +506,16 @@ namespace SHADE
node->parent = newParent; node->parent = newParent;
// Update parent's children // Update parent's children
AddChild(newParent, node); addChild(newParent, node);
} }
void SHSceneGraph::AddChild(SHSceneNode* node, SHSceneNode* newChild) void SHSceneGraph::addChild(SHSceneNode* node, SHSceneNode* newChild)
{ {
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!") SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
SHASSERT(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!") SHASSERT(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!")
if (newChild->parent) if (newChild->parent)
RemoveChild(newChild->parent, newChild); removeChild(newChild->parent, newChild);
newChild->parent = node; newChild->parent = node;
node->children.emplace_back(newChild); node->children.emplace_back(newChild);
@ -529,7 +529,7 @@ namespace SHADE
SHEventManager::BroadcastEvent<SHSceneGraphAddChildEvent>(EVENT_DATA, SH_SCENEGRAPH_ADD_CHILD_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphAddChildEvent>(EVENT_DATA, SH_SCENEGRAPH_ADD_CHILD_EVENT);
} }
void SHSceneGraph::RemoveChild(SHSceneNode* node, SHSceneNode* childToRemove) void SHSceneGraph::removeChild(SHSceneNode* node, SHSceneNode* childToRemove)
{ {
SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!") SHASSERT(node != nullptr, "Attempting to modify a non-existent scene node!")
SHASSERT(childToRemove != nullptr, "Attempting to remove a non-existent child from a SceneNode!") SHASSERT(childToRemove != nullptr, "Attempting to remove a non-existent child from a SceneNode!")
@ -550,12 +550,12 @@ namespace SHADE
SHEventManager::BroadcastEvent<SHSceneGraphRemoveChildEvent>(EVENT_DATA, SH_SCENEGRAPH_REMOVE_CHILD_EVENT); SHEventManager::BroadcastEvent<SHSceneGraphRemoveChildEvent>(EVENT_DATA, SH_SCENEGRAPH_REMOVE_CHILD_EVENT);
} }
void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function) void SHSceneGraph::traverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function)
{ {
for (auto* child : node->children) for (auto* child : node->children)
{ {
function(child); function(child);
TraverseAndInvokeFunction(child, function); traverseAndInvokeFunction(child, function);
} }
} }

View File

@ -24,6 +24,10 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a hierarchical tree for objects in the scene.
*/
class SH_API SHSceneGraph class SH_API SHSceneGraph
{ {
public: public:
@ -64,22 +68,75 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/**
* @brief
* Changing the parent of a node will broadcast three events in the following order:
* <br/>
* 1. SHSceneGraphChangeParentEvent
* 2. SHSceneGraphRemoveChildEvent
* 3. SHSceneGraphAddChildEvent
* <br/><br/>
* See the corresponding header file for the contents of the event struct.
*/
void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept; void SetParent (EntityID entityID, SHSceneNode* newParent) noexcept;
/**
* @brief
* Changing the parent of a node will broadcast three events in the following order:
* <br/>
* 1. SHSceneGraphChangeParentEvent
* 2. SHSceneGraphRemoveChildEvent
* 3. SHSceneGraphAddChildEvent
* <br/><br/>
* See the corresponding header file for the contents of the event struct.
*/
void SetParent (EntityID entityID, EntityID newParent) noexcept; void SetParent (EntityID entityID, EntityID newParent) noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/**
* @brief
* Adding a node will broadcast two events in the following order:
* <br/>
* 1. SHSceneGraphChangeParentEvent
* 2. SHSceneGraphAddChildEvent
* <br/><br/>
* See the corresponding header file for the contents of the event struct.
*/
SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr); SHSceneNode* AddNode (EntityID entityID, SHSceneNode* parent = nullptr);
bool RemoveNode (EntityID entityID) noexcept;
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
void Reset () noexcept;
bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept; /**
bool IsChildOf (EntityID entityID, EntityID targetID) noexcept; * @brief
* Removing a node will broadcast the SHSceneGraphRemoveChildEvent.
* See the corresponding header file for the contents of the event struct.
*/
bool RemoveNode (EntityID entityID) noexcept;
void Traverse (const UnaryFunction& function) const; /**
* @brief
* Removing a node will broadcast the SHSceneGraphRemoveChildEvent.
* See the corresponding header file for the contents of the event struct.
*/
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
/**
* @brief
* Clears all the scene nodes in the scene graph.
*/
void Reset () noexcept;
bool IsChildOf (EntityID entityID, SHSceneNode* targetNode) noexcept;
bool IsChildOf (EntityID entityID, EntityID targetID) noexcept;
/**
* @brief
* Traverses the graph and a depth-first manner and applies the the function onto each node.
* @param function
* A unary function that takes in a SHSceneNode pointer.
*/
void Traverse (const UnaryFunction& function) const;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -93,14 +150,14 @@ namespace SHADE
/* Function Members */ /* Function Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHSceneNode* AllocateNode (EntityID entityID); SHSceneNode* allocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept; void releaseNode (SHSceneNode* node) noexcept;
void ChangeParent (SHSceneNode* node, SHSceneNode* newParent); void changeParent (SHSceneNode* node, SHSceneNode* newParent);
void AddChild (SHSceneNode* node, SHSceneNode* newChild); void addChild (SHSceneNode* node, SHSceneNode* newChild);
void RemoveChild (SHSceneNode* node, SHSceneNode* childToRemove); void removeChild (SHSceneNode* node, SHSceneNode* childToRemove);
static void TraverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function); static void traverseAndInvokeFunction (const SHSceneNode* node, const UnaryFunction& function);
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -17,6 +17,7 @@
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
//#include "FRC/SHFrameRateController.h" //#include "FRC/SHFrameRateController.h"
//#include "ECS_Base/System/SHApplication.h" //#include "ECS_Base/System/SHApplication.h"
#include "SHSceneEvents.h"
#include <iostream> #include <iostream>
@ -55,10 +56,11 @@ namespace SHADE
if (currentScene) if (currentScene)
{ {
currentScene->Free(); currentScene->Free();
SHEventManager::BroadcastEvent<SHSceneExitEvent>(SHSceneExitEvent{ currentSceneID }, SH_SCENE_ON_EXIT_EVENT);
currentScene->Unload(); currentScene->Unload();
SHEntityManager::DestroyAllEntity(); SHEntityManager::DestroyAllEntity();
delete currentScene; delete currentScene;
} }
if (!prevSceneReload) if (!prevSceneReload)
{ {
@ -84,6 +86,8 @@ namespace SHADE
{ {
currentScene->Load(); currentScene->Load();
currentScene->Init(); currentScene->Init();
SHEventManager::BroadcastEvent<SHSceneInitEvent>(SHSceneInitEvent{ currentSceneID }, SH_SCENE_ON_INIT_EVENT);
} }
} }
else // restarting scene else // restarting scene
@ -91,6 +95,8 @@ namespace SHADE
nextSceneID = UINT32_MAX; nextSceneID = UINT32_MAX;
currentScene->Free(); currentScene->Free();
SHEventManager::BroadcastEvent<SHSceneExitEvent>(SHSceneExitEvent{ currentSceneID }, SH_SCENE_ON_EXIT_EVENT);
if (cleanReload == true) if (cleanReload == true)
{ {
cleanReload = false; cleanReload = false;
@ -103,6 +109,7 @@ namespace SHADE
SHEntityManager::DestroyAllEntity(); SHEntityManager::DestroyAllEntity();
currentScene->Init(); currentScene->Init();
SHEventManager::BroadcastEvent<SHSceneInitEvent>(SHSceneInitEvent{ currentSceneID }, SH_SCENE_ON_INIT_EVENT);
} }
} }

View File

@ -15,20 +15,17 @@
// Project Headers // Project Headers
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h" #include "SH_API.h"
#include "SHSceneGraph.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHSceneGraph;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates an object in the scene that is part of the scene's hierarchy.
*/
class SH_API SHSceneNode class SH_API SHSceneNode
{ {
private: private:
@ -66,7 +63,7 @@ namespace SHADE
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SetActive (bool newActiveState) noexcept; void SetActive (bool newActiveState) noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/