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;
};
struct SHSceneInitEvent
{
uint32_t sceneID = std::numeric_limits<uint32_t>::max();
};
struct SHSceneExitEvent
{
uint32_t sceneID = std::numeric_limits<uint32_t>::max();
};
} // namespace SHADE

View File

@ -27,7 +27,7 @@ namespace SHADE
: root { nullptr }
{
// 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
@ -239,7 +239,7 @@ namespace SHADE
if (newParent == nullptr)
newParent = root;
ChangeParent(NODE_ITER->second, newParent);
changeParent(NODE_ITER->second, newParent);
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
}
@ -284,7 +284,7 @@ namespace SHADE
};
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);
}
@ -310,7 +310,7 @@ namespace SHADE
return NODE_ITER->second;
}
SHSceneNode* newNode = AllocateNode(entityID);
SHSceneNode* newNode = allocateNode(entityID);
if (parent == nullptr)
{
@ -320,7 +320,7 @@ namespace SHADE
}
else
{
ChangeParent(newNode, parent);
changeParent(newNode, parent);
}
return newNode;
@ -347,9 +347,9 @@ namespace SHADE
// Remove reference of current node from parent
SHSceneNode* currentNode = NODE_ITER->second;
if (currentNode->parent != nullptr)
RemoveChild(currentNode->parent, currentNode);
removeChild(currentNode->parent, currentNode);
ReleaseNode(currentNode);
releaseNode(currentNode);
return true;
}
@ -357,16 +357,16 @@ namespace SHADE
{
// Remove reference of current node from parent
if (nodeToRemove->parent != nullptr)
RemoveChild(nodeToRemove->parent, nodeToRemove);
removeChild(nodeToRemove->parent, nodeToRemove);
ReleaseNode(nodeToRemove);
releaseNode(nodeToRemove);
return true;
}
void SHSceneGraph::Reset() noexcept
{
for (auto* node : entityNodeMap | std::views::values)
ReleaseNode(node);
releaseNode(node);
}
bool SHSceneGraph::IsChildOf(EntityID entityID, SHSceneNode* targetNode) noexcept
@ -456,39 +456,39 @@ namespace SHADE
void SHSceneGraph::Traverse (const UnaryFunction& function) const
{
TraverseAndInvokeFunction(root, function);
traverseAndInvokeFunction(root, function);
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHSceneNode* SHSceneGraph::AllocateNode(EntityID entityID)
SHSceneNode* SHSceneGraph::allocateNode(EntityID entityID)
{
SHSceneNode* newNode = new SHSceneNode{entityID};
entityNodeMap.emplace(entityID, newNode);
return newNode;
}
void SHSceneGraph::ReleaseNode(SHSceneNode* node) noexcept
void SHSceneGraph::releaseNode(SHSceneNode* node) noexcept
{
SHASSERT(node != nullptr, "Attempting to release Invalid Node!")
// Remove parent's reference to this node if there is a parent
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.
for (auto* child : node->GetChildren())
{
ChangeParent(child, nullptr);
changeParent(child, nullptr);
}
entityNodeMap.erase(node->GetEntityID());
delete node;
}
void SHSceneGraph::ChangeParent(SHSceneNode* node, SHSceneNode* newParent)
void SHSceneGraph::changeParent(SHSceneNode* node, SHSceneNode* newParent)
{
// Handle self assignment
if (node->parent != nullptr && newParent != nullptr && node->parent->entityID == newParent->entityID)
@ -496,7 +496,7 @@ namespace SHADE
// Remove child
if (node->parent)
RemoveChild(node->parent, node);
removeChild(node->parent, node);
if (newParent == nullptr)
{
@ -506,16 +506,16 @@ namespace SHADE
node->parent = newParent;
// 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(newChild != nullptr, "Attempting to add a non-existent child to a SceneNode!")
if (newChild->parent)
RemoveChild(newChild->parent, newChild);
removeChild(newChild->parent, newChild);
newChild->parent = node;
node->children.emplace_back(newChild);
@ -529,7 +529,7 @@ namespace SHADE
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(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);
}
void SHSceneGraph::TraverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function)
void SHSceneGraph::traverseAndInvokeFunction(const SHSceneNode* node, const UnaryFunction& function)
{
for (auto* child : node->children)
{
function(child);
TraverseAndInvokeFunction(child, function);
traverseAndInvokeFunction(child, function);
}
}

View File

@ -24,6 +24,10 @@ namespace SHADE
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a hierarchical tree for objects in the scene.
*/
class SH_API SHSceneGraph
{
public:
@ -64,22 +68,75 @@ namespace SHADE
/* 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;
/**
* @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;
/*---------------------------------------------------------------------------------*/
/* 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);
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:
/*---------------------------------------------------------------------------------*/
@ -93,14 +150,14 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHSceneNode* AllocateNode (EntityID entityID);
void ReleaseNode (SHSceneNode* node) noexcept;
SHSceneNode* allocateNode (EntityID entityID);
void releaseNode (SHSceneNode* node) noexcept;
void ChangeParent (SHSceneNode* node, SHSceneNode* newParent);
void AddChild (SHSceneNode* node, SHSceneNode* newChild);
void RemoveChild (SHSceneNode* node, SHSceneNode* childToRemove);
void changeParent (SHSceneNode* node, SHSceneNode* newParent);
void addChild (SHSceneNode* node, SHSceneNode* newChild);
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

View File

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

View File

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