Collider now will have it's sub collider list updated based on events

This commit is contained in:
Kah Wei 2022-10-27 12:32:06 +08:00
parent cd04132fd7
commit d45d621701
11 changed files with 202 additions and 46 deletions

View File

@ -10,6 +10,9 @@
#include <SHpch.h>
// External Dependencies
#include <reactphysics3d/reactphysics3d.h>
// Primary Header
#include "SHRigidBodyComponent.h"

View File

@ -10,7 +10,6 @@
#pragma once
#include <reactphysics3d/reactphysics3d.h>
#include <rttr/registration>
// Project Headers
@ -23,6 +22,11 @@
// class SHPhysicsSystem;
//}
namespace reactphysics3d
{
class RigidBody;
}
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
@ -153,7 +157,7 @@ namespace SHADE
uint16_t dirtyFlags;
bool interpolate;
rp3d::RigidBody* rp3dBody;
reactphysics3d::RigidBody* rp3dBody;
float mass;
float drag;

View File

@ -24,6 +24,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Events/SHEvent.h"
#include "Events/SHEventReceiver.h"
#include "Events/SHEventManager.hpp"
#include "Physics/SHPhysicsSystem.h"
namespace SHADE
{
@ -60,7 +61,7 @@ namespace SHADE
// Initialise the CSharp Engine
csEngineInit();
// Register entity creation events
// Register all events
registerEvents();
}
void SHScriptEngine::UnloadScriptAssembly()
@ -284,6 +285,20 @@ namespace SHADE
return eventData->handle;
}
SHEventHandle SHScriptEngine::onColliderAdded(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHPhysicsColliderAddedEvent>*>(eventPtr.get());
csColliderOnListChanged(eventData->data->entityID);
return eventData->handle;
}
SHEventHandle SHScriptEngine::onColliderRemoved(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHPhysicsColliderRemovedEvent>*>(eventPtr.get());
csColliderOnListChanged(eventData->data->entityID);
return eventData->handle;
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
@ -384,6 +399,12 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
"DeserialiseScripts"
);
csColliderOnListChanged = dotNet.GetFunctionPtr<CsEventRelayFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Collider",
"OnColliderBoundChanged"
);
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
@ -411,8 +432,21 @@ namespace SHADE
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onEntityDestroyed)
};
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(destroyedEventReceiver);
SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, receiver);
SHEventManager::SubscribeTo(SH_ENTITY_DESTROYED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(destroyedEventReceiver));
// Register for collider added event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> addedColliderEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderAdded)
};
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_ADDED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(addedColliderEventReceiver));
// Register for collider removed event
std::shared_ptr<SHEventReceiverSpec<SHScriptEngine>> removedColliderEventReceiver
{
std::make_shared<SHEventReceiverSpec<SHScriptEngine>>(this, &SHScriptEngine::onColliderRemoved)
};
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_REMOVED_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(removedColliderEventReceiver));
}
void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath)

View File

@ -218,6 +218,7 @@ namespace SHADE
using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*);
using CsScriptDeserialiseYamlFuncPtr = bool(*)(EntityID, const void*);
using CsScriptEditorFuncPtr = void(*)(EntityID);
using CsEventRelayFuncPtr = void(*)(EntityID);
/*-----------------------------------------------------------------------------*/
/* Constants */
@ -250,6 +251,8 @@ namespace SHADE
CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately = nullptr;
CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml = nullptr;
CsScriptDeserialiseYamlFuncPtr csScriptsDeserialiseYaml = nullptr;
// - Events
CsEventRelayFuncPtr csColliderOnListChanged = nullptr;
// - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
CsFuncPtr csEditorUndo = nullptr;
@ -259,6 +262,8 @@ namespace SHADE
/* Event Handler Functions */
/*-----------------------------------------------------------------------------*/
SHEventHandle onEntityDestroyed(SHEventPtr eventPtr);
SHEventHandle onColliderAdded(SHEventPtr eventPtr);
SHEventHandle onColliderRemoved(SHEventPtr eventPtr);
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -134,7 +134,16 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
Collider::Collider(Entity entity)
: Component(entity)
{}
{
// Create lists if they don't exist
if (colliders == nullptr)
colliders = gcnew CollidersMap;
if (!colliders->ContainsKey(entity))
colliders->Add(entity, gcnew WeakReferenceList());
// Store a weak reference
colliders[entity]->Add(gcnew System::WeakReference(this));
}
/*---------------------------------------------------------------------------------*/
/* Collider - Properties */
@ -152,29 +161,7 @@ namespace SHADE
// Populate the list if it hasn't been
if (subColliderList == nullptr)
{
subColliderList = gcnew System::Collections::Generic::List<ColliderBound^>();
for (const auto& collider : GetNativeComponent()->GetColliders())
{
ColliderBound^ bound = nullptr;
switch (collider.first.GetType())
{
case SHCollider::Type::BOX:
bound = gcnew BoxColliderBound(index, Owner.GetEntity());
break;
case SHCollider::Type::SPHERE:
bound = gcnew SphereColliderBound(index, Owner.GetEntity());
break;
case SHCollider::Type::CAPSULE:
// TODO
break;
default:
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
break;
}
// Add into list
subColliderList->Add(bound);
}
updateSubColliderList();
}
// Check if valid
@ -189,4 +176,68 @@ namespace SHADE
{
return safe_cast<T>(GetColliderBound(index));
}
/*---------------------------------------------------------------------------------*/
/* Event Handling Functions */
/*---------------------------------------------------------------------------------*/
void Collider::OnColliderBoundChanged(EntityID entity)
{
// Check if there are any colliders to update
if (colliders == nullptr || !colliders->ContainsKey(entity))
return;
// Update any colliders
System::Collections::Generic::List<System::WeakReference^>^ toRemove = gcnew System::Collections::Generic::List<System::WeakReference ^>();
WeakReferenceList^ collidersList = colliders[entity];
for each (System::WeakReference^ wr in collidersList)
{
Collider^ collider = safe_cast<Collider^>(wr->Target);
// Update collider bounds
if (collider && collider->subColliderList != nullptr)
collider->updateSubColliderList();
else
toRemove->Add(wr);
}
// Sweep through and clear any invalid references while we're at it
for each (System::WeakReference ^ wr in toRemove)
{
collidersList->Remove(wr);
}
}
void Collider::updateSubColliderList()
{
// Prepare the list
if (subColliderList)
subColliderList->Clear();
else
subColliderList = gcnew System::Collections::Generic::List<ColliderBound^>();
// Populate the list
int i = 0;
for (const auto& collider : GetNativeComponent()->GetColliders())
{
ColliderBound^ bound = nullptr;
switch (collider.first.GetType())
{
case SHCollider::Type::BOX:
bound = gcnew BoxColliderBound(i, Owner.GetEntity());
break;
case SHCollider::Type::SPHERE:
bound = gcnew SphereColliderBound(i, Owner.GetEntity());
break;
case SHCollider::Type::CAPSULE:
// TODO
break;
default:
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
break;
}
++i;
// Add into list
subColliderList->Add(bound);
}
}
}

View File

@ -136,7 +136,7 @@ namespace SHADE
/// </summary>
public ref class SphereColliderBound : public ColliderBound
{
public:
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
@ -165,7 +165,7 @@ namespace SHADE
/// <inheritdoc/>
bool Raycast(Ray ray, float maxDistance) override;
internal:
internal:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
@ -220,11 +220,33 @@ namespace SHADE
generic<typename T> where T:ColliderBound
T GetColliderBound(int index);
internal:
/*-----------------------------------------------------------------------------*/
/* Event Handling Functions */
/*-----------------------------------------------------------------------------*/
static void OnColliderBoundChanged(EntityID entity);
private:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using WeakReferenceList = System::Collections::Generic::List<System::WeakReference^>;
using CollidersMap = System::Collections::Generic::Dictionary<EntityID, WeakReferenceList^>;
/*-----------------------------------------------------------------------------*/
/* Static Data Members */
/*-----------------------------------------------------------------------------*/
static CollidersMap^ colliders;
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
System::Collections::Generic::List<ColliderBound^>^ subColliderList; // TODO: Update elements in this list if the list on native collider changes
System::Collections::Generic::List<ColliderBound^>^ subColliderList;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void updateSubColliderList();
};
}

View File

@ -22,6 +22,8 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Physics\Components\SHColliderComponent.h"
#include "Physics\Components\SHRigidBodyComponent.h"
#include "Scene/SHSceneManager.h"
#include "Scene/SHSceneGraph.h"
#include "Tools/SHLog.h"
@ -29,6 +31,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Utility/Convert.hxx"
#include "Utility/Debug.hxx"
#include "Components/Transform.hxx"
#include "Components\RigidBody.hxx"
#include "Components\Collider.hxx"
namespace SHADE
{
@ -242,6 +246,8 @@ namespace SHADE
static ECS::ECS()
{
componentMap.Add(createComponentSet<SHTransformComponent, Transform>());
componentMap.Add(createComponentSet<SHColliderComponent, Collider>());
componentMap.Add(createComponentSet<SHRigidBodyComponent, RigidBody>());
}
/*---------------------------------------------------------------------------------*/

View File

@ -132,7 +132,7 @@ namespace SHADE
/// Immutable list of references to scripts of the specified type.
/// </returns>
generic<typename T> where T : ref class, Script
static System::Collections::Generic::IEnumerable<T> ^ GetScripts(Entity entity);
static System::Collections::Generic::IEnumerable<T>^ GetScripts(Entity entity);
/// <summary>
/// Retrieves an immutable list of all scripts attached to a specified Entity.
/// </summary>
@ -295,4 +295,4 @@ namespace SHADE
static System::Type^ getScriptType(System::String^ scriptName);
static bool isEntityActive(Entity entity);
};
} // namespace PlushieAPI
}

View File

@ -0,0 +1,36 @@
using SHADE;
using System;
public class PhysicsTest : Script
{
[SerializeField]
[Tooltip("Force to apply when pressing Space.")]
private Vector3 Force = new Vector3(0.0f, 1.0f, 0.0f);
private RigidBody RigidBody;
private Collider Collider;
public PhysicsTest(GameObject gameObj) : base(gameObj) { }
protected override void awake()
{
RigidBody = GetComponent<RigidBody>();
if (RigidBody == null)
{
Debug.LogError("RigidBody is NULL!");
}
Collider = GetComponent<Collider>();
if (Collider == null)
{
Debug.LogError("Collider is NULL!");
}
var subColider = Collider.ColliderBoundsCount;
Debug.Log($"There are {subColider} colliders.");
}
protected override void update()
{
if (Input.GetKeyUp(Input.KeyCode.Space))
{
RigidBody.AddForce(Force);
}
}
}

View File

@ -12,7 +12,7 @@ public class RaccoonShowcase : Script
//private int test = 5;
[SerializeField]
[Tooltip("Speed of the scaling in radians per second around each axis.")]
private Vector3 ScaleSpeed = new Vector3(1.0, 1.0, 0.0);
private Vector3 ScaleSpeed = Vector3.One;
private Transform Transform;
private double rotation = 0.0;
private Vector3 scale = Vector3.Zero;
@ -31,9 +31,9 @@ public class RaccoonShowcase : Script
}
protected override void update()
{
rotation += RotateSpeed * 0.16;
scale += ScaleSpeed * 0.16;
Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
Transform.LocalScale = new Vector3(System.Math.Abs(System.Math.Sin(scale.x)) * originalScale, System.Math.Abs(System.Math.Cos(scale.y)) * originalScale, System.Math.Abs(System.Math.Sin(scale.z)) * originalScale);
//rotation += RotateSpeed * 0.16;
//scale += ScaleSpeed * 0.16;
//Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
//Transform.LocalScale = new Vector3(System.Math.Abs(System.Math.Sin(scale.x)) * originalScale, System.Math.Abs(System.Math.Cos(scale.y)) * originalScale, System.Math.Abs(System.Math.Sin(scale.z)) * originalScale);
}
}

View File

@ -5,8 +5,8 @@ public class RaccoonSpin : Script
{
[SerializeField]
[Tooltip("Speed of the rotation in radians per second.")]
private double RotateSpeed = 1.0;
private double rotation = 0.0;
private float RotateSpeed = 1.0f;
private float rotation = 0.0f;
[SerializeField]
private CallbackEvent<int> testEvent;
[SerializeField]
@ -22,9 +22,4 @@ public class RaccoonSpin : Script
Debug.LogError("Transform is NULL!");
}
}
protected override void update()
{
rotation += RotateSpeed * 0.16;
Transform.LocalRotation = new Vector3(0.0f, rotation, 0.0f);
}
}