Implemented a custom physics engine #316
|
@ -31,7 +31,6 @@
|
||||||
#include "Input/SHInputManager.h"
|
#include "Input/SHInputManager.h"
|
||||||
#include "Math/Transform/SHTransformSystem.h"
|
#include "Math/Transform/SHTransformSystem.h"
|
||||||
#include "Physics/System/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
#include "UI/SHUISystem.h"
|
#include "UI/SHUISystem.h"
|
||||||
|
|
||||||
|
@ -74,9 +73,6 @@ namespace Sandbox
|
||||||
SHSystemManager::CreateSystem<SHScriptEngine>();
|
SHSystemManager::CreateSystem<SHScriptEngine>();
|
||||||
SHSystemManager::CreateSystem<SHTransformSystem>();
|
SHSystemManager::CreateSystem<SHTransformSystem>();
|
||||||
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
SHSystemManager::CreateSystem<SHPhysicsSystem>();
|
||||||
#ifndef _PUBLISH
|
|
||||||
SHSystemManager::CreateSystem<SHPhysicsDebugDrawSystem>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SHSystemManager::CreateSystem<SHAudioSystem>();
|
SHSystemManager::CreateSystem<SHAudioSystem>();
|
||||||
SHSystemManager::CreateSystem<SHCameraSystem>();
|
SHSystemManager::CreateSystem<SHCameraSystem>();
|
||||||
|
@ -116,10 +112,6 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||||
|
|
||||||
#ifndef _PUBLISH
|
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
|
||||||
|
|
||||||
|
@ -192,27 +184,6 @@ namespace Sandbox
|
||||||
#else
|
#else
|
||||||
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
|
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
|
||||||
#endif
|
#endif
|
||||||
// TODO: Move into an Editor menu
|
|
||||||
static bool drawContacts = false;
|
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
|
|
||||||
{
|
|
||||||
drawContacts = !drawContacts;
|
|
||||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
|
|
||||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
|
|
||||||
}
|
|
||||||
static bool drawColliders = false;
|
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
|
||||||
{
|
|
||||||
drawColliders = !drawColliders;
|
|
||||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
|
|
||||||
}
|
|
||||||
static bool drawRays = false;
|
|
||||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F11))
|
|
||||||
{
|
|
||||||
drawRays = !drawRays;
|
|
||||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
graphicsSystem->AwaitGraphicsExecution();
|
graphicsSystem->AwaitGraphicsExecution();
|
||||||
|
|
|
@ -51,16 +51,6 @@ namespace Sandbox
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
physicsSystem->ForceBuild(SHSceneManager::GetCurrentSceneGraph());
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* TESTING CODE */
|
/* TESTING CODE */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
|
@ -186,20 +186,20 @@ namespace SHADE
|
||||||
|
|
||||||
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
|
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
|
||||||
|
|
||||||
auto result = physicsSystem->Raycast(pivot.ray );
|
//auto result = physicsSystem->Raycast(pivot.ray );
|
||||||
if (result && result.distance < pivot.GetArmLength())
|
//if (result && result.distance < pivot.GetArmLength())
|
||||||
{
|
//{
|
||||||
|
//
|
||||||
SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
|
// SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
|
||||||
newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
|
// newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
|
||||||
newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
|
// newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
|
||||||
pivot.offset = newOffset;
|
// pivot.offset = newOffset;
|
||||||
//SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
|
// //SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
//SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
|
// //SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -285,8 +285,8 @@ namespace SHADE
|
||||||
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
|
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
|
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
|
||||||
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
//SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||||
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
//SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||||
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||||
|
|
|
@ -1,254 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHCollisionListener.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Collision Listener.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHCollisionListener.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
|
||||||
#include "Physics/PhysicsObject/SHPhysicsObject.h"
|
|
||||||
#include "Physics/System/SHPhysicsSystem.h"
|
|
||||||
#include "Scene/SHSceneManager.h"
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
|
||||||
/* Local Helper Functions */
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
uint32_t matchColliders(const SHADE::SHPhysicsObject&physicsObject, const rp3d::Entity colliderID)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < physicsObject.GetCollisionBody()->getNbColliders(); ++i)
|
|
||||||
{
|
|
||||||
const auto* collider = physicsObject.GetCollisionBody()->getCollider(i);
|
|
||||||
if (collider->getEntity() == colliderID)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::numeric_limits<uint32_t>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHCollisionListener::SHCollisionListener() noexcept
|
|
||||||
: system { nullptr }
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
const std::vector<SHCollisionInfo>& SHCollisionListener::GetCollisionInfoContainer() const noexcept
|
|
||||||
{
|
|
||||||
return collisionInfoContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<SHCollisionInfo>& SHCollisionListener::GetTriggerInfoContainer() const noexcept
|
|
||||||
{
|
|
||||||
return triggerInfoContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHCollisionListener::BindToSystem(SHPhysicsSystem* physicsSystem) noexcept
|
|
||||||
{
|
|
||||||
system = physicsSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollisionListener::BindToWorld(rp3d::PhysicsWorld* world) noexcept
|
|
||||||
{
|
|
||||||
if (!world)
|
|
||||||
return;
|
|
||||||
|
|
||||||
world->setEventListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollisionListener::CleanContainers() noexcept
|
|
||||||
{
|
|
||||||
static const auto CLEAR = [](std::vector<SHCollisionInfo>& container)
|
|
||||||
{
|
|
||||||
for (auto eventIter = container.begin(); eventIter != container.end();)
|
|
||||||
{
|
|
||||||
const SHCollisionInfo& C_INFO = *eventIter;
|
|
||||||
|
|
||||||
const bool INVALID_ENTITY = !SHEntityManager::IsValidEID(C_INFO.GetEntityA()) || !SHEntityManager::IsValidEID(C_INFO.GetEntityB());
|
|
||||||
if (INVALID_ENTITY)
|
|
||||||
{
|
|
||||||
eventIter = container.erase(eventIter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool CLEAR_EVENT = C_INFO.GetCollisionState() == SHCollisionInfo::State::EXIT || C_INFO.GetCollisionState() == SHCollisionInfo::State::INVALID;
|
|
||||||
|
|
||||||
const bool INACTIVE_OBJECT = !SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(C_INFO.GetEntityA())
|
|
||||||
|| !SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(C_INFO.GetEntityB());
|
|
||||||
|
|
||||||
if (CLEAR_EVENT || INACTIVE_OBJECT)
|
|
||||||
{
|
|
||||||
eventIter = container.erase(eventIter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++eventIter;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CLEAR(collisionInfoContainer);
|
|
||||||
CLEAR(triggerInfoContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollisionListener::ClearContainers() noexcept
|
|
||||||
{
|
|
||||||
collisionInfoContainer.clear();
|
|
||||||
triggerInfoContainer.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollisionListener::onContact(const rp3d::CollisionCallback::CallbackData& callbackData)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)
|
|
||||||
{
|
|
||||||
const auto CONTACT_PAIR = callbackData.getContactPair(i);
|
|
||||||
const SHCollisionInfo NEW_INFO = generateCollisionInfo(CONTACT_PAIR);
|
|
||||||
|
|
||||||
updateInfoContainers(NEW_INFO, collisionInfoContainer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollisionListener::onTrigger(const rp3d::OverlapCallback::CallbackData& callbackData)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < callbackData.getNbOverlappingPairs(); ++i)
|
|
||||||
{
|
|
||||||
const auto OVERLAP_PAIR = callbackData.getOverlappingPair(i);
|
|
||||||
const SHCollisionInfo NEW_INFO = generateTriggerInfo(OVERLAP_PAIR);
|
|
||||||
|
|
||||||
updateInfoContainers(NEW_INFO, triggerInfoContainer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHCollisionListener::updateInfoContainers(const SHCollisionInfo& collisionEvent, std::vector<SHCollisionInfo>& container) noexcept
|
|
||||||
{
|
|
||||||
const auto IT = std::ranges::find_if(container.begin(), container.end(), [&](const SHCollisionInfo& info)
|
|
||||||
{
|
|
||||||
const bool ENTITY_MATCH = (info.ids[0] == collisionEvent.ids[0] && info.ids[1] == collisionEvent.ids[1])
|
|
||||||
|| (info.ids[0] == collisionEvent.ids[1] && info.ids[1] == collisionEvent.ids[0]);
|
|
||||||
const bool COLLIDERS_MATCH = (info.ids[2] == collisionEvent.ids[2] && info.ids[3] == collisionEvent.ids[3])
|
|
||||||
|| (info.ids[2] == collisionEvent.ids[3] && info.ids[3] == collisionEvent.ids[2]);
|
|
||||||
return ENTITY_MATCH && COLLIDERS_MATCH;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (IT == container.end())
|
|
||||||
container.emplace_back(collisionEvent);
|
|
||||||
else
|
|
||||||
IT->collisionState = collisionEvent.collisionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHCollisionInfo SHCollisionListener::generateCollisionInfo(const rp3d::CollisionCallback::ContactPair& cp) const noexcept
|
|
||||||
{
|
|
||||||
SHCollisionInfo cInfo;
|
|
||||||
|
|
||||||
// Update collision state
|
|
||||||
cInfo.collisionState = static_cast<SHCollisionInfo::State>(cp.getEventType());
|
|
||||||
|
|
||||||
// Match body and collider for collision event
|
|
||||||
const rp3d::Entity body1 = cp.getBody1()->getEntity();
|
|
||||||
const rp3d::Entity body2 = cp.getBody2()->getEntity();
|
|
||||||
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
|
|
||||||
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
|
|
||||||
|
|
||||||
// Find and match both ids
|
|
||||||
bool matched[2] = { false, false };
|
|
||||||
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
|
||||||
{
|
|
||||||
// Match body 1
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
|
||||||
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
|
||||||
|
|
||||||
matched[SHCollisionInfo::ENTITY_A] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match body 2
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
|
||||||
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
|
||||||
|
|
||||||
matched[SHCollisionInfo::ENTITY_B] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true)
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHCollisionInfo SHCollisionListener::generateTriggerInfo(const rp3d::OverlapCallback::OverlapPair& cp) const noexcept
|
|
||||||
{
|
|
||||||
SHCollisionInfo cInfo;
|
|
||||||
|
|
||||||
// Update collision state
|
|
||||||
cInfo.collisionState = static_cast<SHCollisionInfo::State>(cp.getEventType());
|
|
||||||
|
|
||||||
// Match body and collider for collision event
|
|
||||||
const rp3d::Entity body1 = cp.getBody1()->getEntity();
|
|
||||||
const rp3d::Entity body2 = cp.getBody2()->getEntity();
|
|
||||||
const rp3d::Entity collider1 = cp.getCollider1()->getEntity();
|
|
||||||
const rp3d::Entity collider2 = cp.getCollider2()->getEntity();
|
|
||||||
|
|
||||||
// Find and match both ids
|
|
||||||
bool matched[2] = { false, false };
|
|
||||||
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
|
||||||
{
|
|
||||||
// Match body 1
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
|
||||||
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
|
||||||
|
|
||||||
matched[SHCollisionInfo::ENTITY_A] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match body 2
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
|
||||||
{
|
|
||||||
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
|
||||||
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
|
||||||
|
|
||||||
matched[SHCollisionInfo::ENTITY_B] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matched[SHCollisionInfo::ENTITY_A] == true && matched[SHCollisionInfo::ENTITY_B] == true)
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,80 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHCollisionListener.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for a Collision Listener.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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
|
|
||||||
|
|
||||||
// External Dependencies
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "SH_API.h"
|
|
||||||
#include "SHCollisionInfo.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Forward Declarations */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SHPhysicsSystem;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHCollisionListener final : public rp3d::EventListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHCollisionListener() noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetCollisionInfoContainer () const noexcept;
|
|
||||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetTriggerInfoContainer () const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void BindToSystem (SHPhysicsSystem* physicsSystem) noexcept;
|
|
||||||
void BindToWorld (rp3d::PhysicsWorld* world) noexcept;
|
|
||||||
void CleanContainers () noexcept;
|
|
||||||
void ClearContainers () noexcept;
|
|
||||||
|
|
||||||
void onContact (const rp3d::CollisionCallback::CallbackData& callbackData) override;
|
|
||||||
void onTrigger (const rp3d::OverlapCallback::CallbackData& callbackData) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsSystem* system;
|
|
||||||
std::vector<SHCollisionInfo> collisionInfoContainer;
|
|
||||||
std::vector<SHCollisionInfo> triggerInfoContainer;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static void updateInfoContainers (const SHCollisionInfo& collisionEvent, std::vector<SHCollisionInfo>& container) noexcept;
|
|
||||||
|
|
||||||
SHCollisionInfo generateCollisionInfo (const rp3d::CollisionCallback::ContactPair& cp) const noexcept;
|
|
||||||
SHCollisionInfo generateTriggerInfo (const rp3d::OverlapCallback::OverlapPair& cp) const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,350 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsRaycaster.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Physics Raycaster.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsRaycaster.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO(DIREN):
|
|
||||||
* Once the physics engine has been rebuilt, this whole implementation should change
|
|
||||||
* and just call PhysicsWorld.Raycast etc.
|
|
||||||
*
|
|
||||||
* SHRaycastResult can be converted to a bool when necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsRaycaster::SHPhysicsRaycaster() noexcept
|
|
||||||
: world { nullptr }
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
const SHPhysicsRaycaster::RaycastPairs& SHPhysicsRaycaster::GetRaycasts() const noexcept
|
|
||||||
{
|
|
||||||
return raycasts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsRaycaster::SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept
|
|
||||||
{
|
|
||||||
objectManager = physicsObjectManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
|
||||||
{
|
|
||||||
world = physicsWorld;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsRaycaster::ClearFrame() noexcept
|
|
||||||
{
|
|
||||||
raycasts.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept
|
|
||||||
{
|
|
||||||
// Reset temp
|
|
||||||
temp = SHPhysicsRaycastResult{};
|
|
||||||
temp.distance = distance;
|
|
||||||
|
|
||||||
if (!world)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics world missing for raycasting!")
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If distance in infinity, cast to the default max distance of 2 km.
|
|
||||||
if (distance == std::numeric_limits<float>::infinity())
|
|
||||||
{
|
|
||||||
world->raycast(ray, this, collisionTag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
|
||||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
|
||||||
world->raycast(RP3D_RAY, this, collisionTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a hit was found, populate temp info for return.
|
|
||||||
if (temp.hit)
|
|
||||||
{
|
|
||||||
temp.distance = SHVec3::Distance(ray.position, temp.position);
|
|
||||||
temp.angle = SHVec3::Angle(ray.position, temp.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(ray, temp);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept
|
|
||||||
{
|
|
||||||
temp = SHPhysicsRaycastResult{};
|
|
||||||
temp.distance = SHVec3::Distance(start, end);
|
|
||||||
|
|
||||||
if (!world)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics world missing for raycasting!")
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rp3d::Ray RP3D_RAY{ start, end };
|
|
||||||
world->raycast(RP3D_RAY, this, collisionTag);
|
|
||||||
|
|
||||||
if (temp.hit)
|
|
||||||
{
|
|
||||||
temp.distance = SHVec3::Distance(start, temp.position);
|
|
||||||
temp.angle = SHVec3::Angle(start, temp.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(RP3D_RAY, temp);
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
SHPhysicsRaycastResult result;
|
|
||||||
result.distance = distance;
|
|
||||||
|
|
||||||
// Get a valid physics object with at least 1 collider.
|
|
||||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
|
||||||
if (!PHYSICS_OBJECT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
|
|
||||||
|
|
||||||
// Data to populate
|
|
||||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
|
||||||
bool hit = false;
|
|
||||||
|
|
||||||
if (distance == std::numeric_limits<float>::infinity())
|
|
||||||
{
|
|
||||||
hit = rp3dBody->raycast(ray, rp3dRaycastInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
|
||||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
|
||||||
hit = rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hit)
|
|
||||||
{
|
|
||||||
result.hit = true;
|
|
||||||
result.position = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.normal = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.distance = SHVec3::Distance(ray.position, result.position);
|
|
||||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
|
||||||
result.entityHit = eid;
|
|
||||||
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(ray, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
SHPhysicsRaycastResult result;
|
|
||||||
result.distance = distance;
|
|
||||||
|
|
||||||
// Get a valid physics object with at least 1 collider.
|
|
||||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
|
||||||
if (!PHYSICS_OBJECT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Boundary check for shape index
|
|
||||||
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("Invalid collision shape index passed in")
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
|
|
||||||
|
|
||||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
|
||||||
bool hit = false;
|
|
||||||
if (distance == std::numeric_limits<float>::infinity())
|
|
||||||
{
|
|
||||||
hit = rp3dCollider->raycast(ray, rp3dRaycastInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
|
||||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
|
||||||
hit = rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hit)
|
|
||||||
{
|
|
||||||
result.hit = true;
|
|
||||||
result.position = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.normal = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.distance = SHVec3::Distance(ray.position, result.position);
|
|
||||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
|
||||||
result.entityHit = eid;
|
|
||||||
result.shapeIndex = shapeIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(ray, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
SHPhysicsRaycastResult result;
|
|
||||||
result.distance = SHVec3::Distance(start, end);
|
|
||||||
|
|
||||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
|
||||||
if (!PHYSICS_OBJECT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
|
|
||||||
|
|
||||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
|
||||||
|
|
||||||
const rp3d::Ray RP3D_RAY{ start, end };
|
|
||||||
if (rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo))
|
|
||||||
{
|
|
||||||
result.hit = true;
|
|
||||||
result.position = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.normal = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.distance = SHVec3::Distance(start, result.position);
|
|
||||||
result.angle = SHVec3::Angle(end, result.position);
|
|
||||||
result.entityHit = eid;
|
|
||||||
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(RP3D_RAY, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
SHPhysicsRaycastResult result;
|
|
||||||
result.distance = SHVec3::Distance(start, end);
|
|
||||||
|
|
||||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
|
||||||
if (!PHYSICS_OBJECT)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("Invalid collision shape index passed in")
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
|
|
||||||
|
|
||||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
|
||||||
|
|
||||||
const rp3d::Ray RP3D_RAY{ start, end };
|
|
||||||
if (rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo))
|
|
||||||
{
|
|
||||||
result.hit = true;
|
|
||||||
result.position = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.normal = rp3dRaycastInfo.worldPoint;
|
|
||||||
result.distance = SHVec3::Distance(start, result.position);
|
|
||||||
result.angle = SHVec3::Angle(end, result.position);
|
|
||||||
result.entityHit = eid;
|
|
||||||
result.shapeIndex = shapeIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
raycasts.emplace_back(RP3D_RAY, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::decimal SHPhysicsRaycaster::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo)
|
|
||||||
{
|
|
||||||
temp.hit = true;
|
|
||||||
temp.position = raycastInfo.worldPoint;
|
|
||||||
temp.normal = raycastInfo.worldNormal;
|
|
||||||
|
|
||||||
if (!objectManager)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare body IDs to find the matching physics object
|
|
||||||
const auto HIT_BODY_EID = raycastInfo.body->getEntity();
|
|
||||||
|
|
||||||
for (const auto& [entityID, physicsObject] : objectManager->GetPhysicsObjects())
|
|
||||||
{
|
|
||||||
const auto RP3D_BODY = physicsObject.GetCollisionBody();
|
|
||||||
|
|
||||||
// Match rp3d bodies
|
|
||||||
if (RP3D_BODY->getEntity() != HIT_BODY_EID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
temp.entityHit = entityID;
|
|
||||||
|
|
||||||
// Find collider index
|
|
||||||
if (const int INDEX = findColliderIndex(RP3D_BODY, raycastInfo.collider->getEntity()); INDEX > -1)
|
|
||||||
{
|
|
||||||
temp.shapeIndex = INDEX;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsRaycaster::validateColliderRaycast(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
if (!objectManager)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* physicsObject = objectManager->GetPhysicsObject(eid);
|
|
||||||
if (!physicsObject || physicsObject->GetCollisionBody()->getNbColliders() == 0)
|
|
||||||
{
|
|
||||||
SHLOGV_WARNING("Cannot cast ray at an entity without colliders!")
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return physicsObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SHPhysicsRaycaster::findColliderIndex(const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept
|
|
||||||
{
|
|
||||||
const int NUM_COLLISION_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
|
||||||
for (int i = 0; i < NUM_COLLISION_SHAPES; ++i)
|
|
||||||
{
|
|
||||||
const auto COLLIDER_EID = rp3dBody->getCollider(i)->getEntity();
|
|
||||||
if (COLLIDER_EID == rp3dColliderEID)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,134 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsRaycaster.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for a Physics Raycaster.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "Math/SHRay.h"
|
|
||||||
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
|
|
||||||
#include "Physics/SHPhysicsWorld.h"
|
|
||||||
#include "SH_API.h"
|
|
||||||
#include "SHCollisionTags.h"
|
|
||||||
#include "SHPhysicsRaycastResult.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsRaycaster : public reactphysics3d::RaycastCallback
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
using RaycastPair = std::pair<SHRay, SHPhysicsRaycastResult>;
|
|
||||||
using RaycastPairs = std::vector<RaycastPair>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsRaycaster() noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] const RaycastPairs& GetRaycasts() const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void BindToWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
|
||||||
void ClearFrame () noexcept;
|
|
||||||
|
|
||||||
// TODO(Diren): Filtering, return all shades ray hits
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult Raycast
|
|
||||||
(
|
|
||||||
const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult Linecast
|
|
||||||
(
|
|
||||||
const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult ColliderRaycast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult ColliderRaycast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, int shapeIndex
|
|
||||||
, const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult ColliderLinecast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult ColliderLinecast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, int shapeIndex
|
|
||||||
, const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
rp3d::PhysicsWorld* world;
|
|
||||||
SHPhysicsObjectManager* objectManager; // For
|
|
||||||
SHPhysicsRaycastResult temp; // Holds the temporary result after casting into the world
|
|
||||||
RaycastPairs raycasts; // Used for debug drawing
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* validateColliderRaycast (EntityID eid) noexcept;
|
|
||||||
static int findColliderIndex (const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -25,34 +25,12 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHColliderComponent::SHColliderComponent() noexcept
|
SHColliderComponent::SHColliderComponent() noexcept
|
||||||
: system { nullptr }
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
const SHVec3& SHColliderComponent::GetPosition() const noexcept
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept
|
|
||||||
{
|
|
||||||
return orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHVec3 SHColliderComponent::GetRotation() const noexcept
|
|
||||||
{
|
|
||||||
return orientation.ToEuler();
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHVec3& SHColliderComponent::GetScale() const noexcept
|
|
||||||
{
|
|
||||||
return scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
|
const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
|
||||||
{
|
{
|
||||||
return collisionShapes;
|
return collisionShapes;
|
||||||
|
@ -72,22 +50,7 @@ namespace SHADE
|
||||||
|
|
||||||
void SHColliderComponent::OnCreate()
|
void SHColliderComponent::OnCreate()
|
||||||
{
|
{
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (!physicsSystem)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system = physicsSystem;
|
|
||||||
|
|
||||||
// Sync with transform if one already exists
|
|
||||||
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
|
|
||||||
{
|
|
||||||
position = transformComponent->GetWorldPosition();
|
|
||||||
orientation = transformComponent->GetWorldOrientation();
|
|
||||||
scale = transformComponent->GetWorldScale();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::OnDestroy()
|
void SHColliderComponent::OnDestroy()
|
||||||
|
@ -97,112 +60,22 @@ namespace SHADE
|
||||||
|
|
||||||
void SHColliderComponent::RecomputeCollisionShapes() noexcept
|
void SHColliderComponent::RecomputeCollisionShapes() noexcept
|
||||||
{
|
{
|
||||||
for (auto& collisionShape : collisionShapes)
|
|
||||||
{
|
|
||||||
switch (collisionShape.GetType())
|
|
||||||
{
|
|
||||||
case SHCollisionShape::Type::BOX:
|
|
||||||
{
|
|
||||||
auto* box = reinterpret_cast<SHBox*>(collisionShape.shape);
|
|
||||||
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
|
||||||
|
|
||||||
// Recompute world extents based on new scale and fixed relative extents
|
|
||||||
|
|
||||||
const SHVec3 WORLD_EXTENTS = RELATIVE_EXTENTS * (scale * 0.5f);
|
|
||||||
box->SetWorldExtents(WORLD_EXTENTS);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
auto* sphere = reinterpret_cast<SHSphere*>(collisionShape.shape);
|
|
||||||
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
|
||||||
|
|
||||||
// Recompute world radius based on new scale and fixed radius
|
|
||||||
|
|
||||||
const float MAX_SCALE = SHMath::Max({ scale.x, scale.y, scale.z });
|
|
||||||
const float WORLD_RADIUS = RELATIVE_RADIUS * MAX_SCALE * 0.5f;
|
|
||||||
sphere->SetWorldRadius(WORLD_RADIUS);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
default: continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept
|
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
return 0;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr auto TYPE = SHCollisionShape::Type::BOX;
|
|
||||||
|
|
||||||
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
|
|
||||||
|
|
||||||
collider.entityID = GetEID();
|
|
||||||
collider.SetPositionOffset(posOffset);
|
|
||||||
collider.SetRotationOffset(rotOffset);
|
|
||||||
collider.SetBoundingBox(halfExtents);
|
|
||||||
|
|
||||||
// Notify Physics System
|
|
||||||
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
|
||||||
|
|
||||||
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
|
||||||
return NEW_SHAPE_INDEX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
||||||
{
|
{
|
||||||
if (!system)
|
return 0;
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr auto TYPE = SHCollisionShape::Type::SPHERE;
|
|
||||||
|
|
||||||
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
|
|
||||||
|
|
||||||
collider.entityID = GetEID();
|
|
||||||
collider.SetPositionOffset(posOffset);
|
|
||||||
collider.SetBoundingSphere(radius);
|
|
||||||
|
|
||||||
// Notify Physics System
|
|
||||||
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
|
||||||
|
|
||||||
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
|
||||||
return NEW_SHAPE_INDEX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHColliderComponent::RemoveCollider(int index)
|
void SHColliderComponent::RemoveCollider(int index)
|
||||||
{
|
{
|
||||||
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
|
|
||||||
throw std::invalid_argument("Out-of-range access!");
|
|
||||||
|
|
||||||
int idx = 0;
|
|
||||||
auto it = collisionShapes.begin();
|
|
||||||
for (; it != collisionShapes.end(); ++it)
|
|
||||||
{
|
|
||||||
if (idx == index)
|
|
||||||
break;
|
|
||||||
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
it = collisionShapes.erase(it);
|
|
||||||
|
|
||||||
// Notify Physics System
|
|
||||||
if (!system)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics system does not exist, unable to remove Collider!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system->RemoveCollisionShape(GetEID(), index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -69,11 +69,6 @@ namespace SHADE
|
||||||
|
|
||||||
[[nodiscard]] bool HasChanged () const noexcept;
|
[[nodiscard]] bool HasChanged () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
|
||||||
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
|
||||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
|
||||||
[[nodiscard]] const SHVec3& GetScale () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept;
|
[[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept;
|
||||||
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
|
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
|
||||||
|
|
||||||
|
@ -97,10 +92,6 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsSystem* system;
|
|
||||||
|
|
||||||
SHVec3 position;
|
|
||||||
SHQuaternion orientation;
|
|
||||||
SHVec3 scale;
|
SHVec3 scale;
|
||||||
CollisionShapes collisionShapes;
|
CollisionShapes collisionShapes;
|
||||||
|
|
||||||
|
|
|
@ -190,63 +190,63 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents)
|
void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents)
|
||||||
{
|
{
|
||||||
dirty = true;
|
//dirty = true;
|
||||||
|
|
||||||
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
//const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||||
auto* box = reinterpret_cast<SHBox*>(shape);
|
//auto* box = reinterpret_cast<SHBox*>(shape);
|
||||||
|
|
||||||
SHVec3 correctedHalfExtents = halfExtents;
|
//SHVec3 correctedHalfExtents = halfExtents;
|
||||||
|
|
||||||
// Get current relative halfExtents for error checking. 0 is ignored
|
//// Get current relative halfExtents for error checking. 0 is ignored
|
||||||
const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents();
|
//const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents();
|
||||||
for (size_t i = 0; i < SHVec3::SIZE; ++i)
|
//for (size_t i = 0; i < SHVec3::SIZE; ++i)
|
||||||
{
|
//{
|
||||||
if (SHMath::CompareFloat(halfExtents[i], 0.0f))
|
// if (SHMath::CompareFloat(halfExtents[i], 0.0f))
|
||||||
correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i];
|
// correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i];
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
|
//// Set the half extents relative to world scale
|
||||||
|
//const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f;
|
||||||
|
|
||||||
// Set the half extents relative to world scale
|
//if (type != Type::BOX)
|
||||||
const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f;
|
//{
|
||||||
|
// type = Type::BOX;
|
||||||
|
|
||||||
if (type != Type::BOX)
|
// delete shape;
|
||||||
{
|
// shape = new SHBox{ positionOffset, WORLD_EXTENTS };
|
||||||
type = Type::BOX;
|
//}
|
||||||
|
|
||||||
delete shape;
|
//box->SetWorldExtents(WORLD_EXTENTS);
|
||||||
shape = new SHBox{ positionOffset, WORLD_EXTENTS };
|
//box->SetRelativeExtents(correctedHalfExtents);
|
||||||
}
|
|
||||||
|
|
||||||
box->SetWorldExtents(WORLD_EXTENTS);
|
|
||||||
box->SetRelativeExtents(correctedHalfExtents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCollisionShape::SetBoundingSphere(float radius)
|
void SHCollisionShape::SetBoundingSphere(float radius)
|
||||||
{
|
{
|
||||||
dirty = true;
|
//dirty = true;
|
||||||
|
|
||||||
auto* sphere = reinterpret_cast<SHSphere*>(shape);
|
//auto* sphere = reinterpret_cast<SHSphere*>(shape);
|
||||||
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
//const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||||
|
|
||||||
// Get current relative halfExtents for error checking. 0 is ignored
|
//// Get current relative halfExtents for error checking. 0 is ignored
|
||||||
const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
//const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
||||||
if (SHMath::CompareFloat(radius, 0.0f))
|
//if (SHMath::CompareFloat(radius, 0.0f))
|
||||||
radius = CURRENT_RELATIVE_RADIUS;
|
// radius = CURRENT_RELATIVE_RADIUS;
|
||||||
|
|
||||||
// Set the radius relative to world scale
|
//// Set the radius relative to world scale
|
||||||
const SHVec3 WORLD_SCALE = COLLIDER->GetScale();
|
//const SHVec3 WORLD_SCALE = COLLIDER->GetScale();
|
||||||
const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z });
|
//const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z });
|
||||||
const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f;
|
//const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f;
|
||||||
|
|
||||||
if (type != Type::SPHERE)
|
//if (type != Type::SPHERE)
|
||||||
{
|
//{
|
||||||
type = Type::SPHERE;
|
// type = Type::SPHERE;
|
||||||
|
|
||||||
delete shape;
|
// delete shape;
|
||||||
shape = new SHSphere{ positionOffset, WORLD_RADIUS };
|
// shape = new SHSphere{ positionOffset, WORLD_RADIUS };
|
||||||
}
|
//}
|
||||||
|
|
||||||
sphere->SetWorldRadius(WORLD_RADIUS);
|
//sphere->SetWorldRadius(WORLD_RADIUS);
|
||||||
sphere->SetRelativeRadius(radius);
|
//sphere->SetRelativeRadius(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCollisionShape::SetIsTrigger(bool trigger) noexcept
|
void SHCollisionShape::SetIsTrigger(bool trigger) noexcept
|
||||||
|
|
|
@ -28,18 +28,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
||||||
: type { Type::DYNAMIC }
|
|
||||||
, flags { 0 }
|
|
||||||
, dirtyFlags { std::numeric_limits<uint16_t>::max() }
|
|
||||||
, mass { 1.0f }
|
|
||||||
, drag { 0.01f }
|
|
||||||
, angularDrag { 0.01f }
|
|
||||||
, system { nullptr }
|
|
||||||
{
|
{
|
||||||
// Initialise default flags
|
|
||||||
flags |= 1U << 0; // Gravity set to true
|
|
||||||
flags |= 1U << 1; // Sleeping allowed
|
|
||||||
flags |= 1U << 8; // Interpolate by default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -48,363 +38,166 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 0;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 1;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 8;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetIsSleeping() const noexcept
|
bool SHRigidBodyComponent::GetIsSleeping() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
return physicsObject->GetRigidBody()->isSleeping();
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
|
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
|
||||||
{
|
{
|
||||||
return type;
|
return Type::STATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 2;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 3;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 4;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 5;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 6;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 7;
|
return false;
|
||||||
return flags & (1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool SHRigidBodyComponent::GetAutoMass() const noexcept
|
|
||||||
//{
|
|
||||||
// static constexpr int FLAG_POS = 9;
|
|
||||||
// return flags & (1U << FLAG_POS);
|
|
||||||
//}
|
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetMass() const noexcept
|
float SHRigidBodyComponent::GetMass() const noexcept
|
||||||
{
|
{
|
||||||
return mass;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetDrag() const noexcept
|
float SHRigidBodyComponent::GetDrag() const noexcept
|
||||||
{
|
{
|
||||||
return drag;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
float SHRigidBodyComponent::GetAngularDrag() const noexcept
|
||||||
{
|
{
|
||||||
return angularDrag;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
return physicsObject->GetRigidBody()->getForce();
|
|
||||||
|
|
||||||
return SHVec3::Zero;
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
return physicsObject->GetRigidBody()->getTorque();
|
|
||||||
|
|
||||||
return SHVec3::Zero;
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
return physicsObject->GetRigidBody()->getLinearVelocity();
|
|
||||||
|
|
||||||
return SHVec3::Zero;
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
return physicsObject->GetRigidBody()->getAngularVelocity();
|
|
||||||
|
|
||||||
return SHVec3::Zero;
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHQuaternion& SHRigidBodyComponent::GetOrientation() const noexcept
|
|
||||||
{
|
|
||||||
return orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHVec3 SHRigidBodyComponent::GetRotation() const noexcept
|
|
||||||
{
|
|
||||||
return orientation.ToEuler();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Function Definitions */
|
/* Setter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 8;
|
|
||||||
|
|
||||||
if (type == newType)
|
|
||||||
return;
|
|
||||||
|
|
||||||
type = newType;
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 1;
|
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot enable sleeping of a non-dynamic object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 2;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 3;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 4;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 5;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 6;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 7;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 8;
|
|
||||||
allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept
|
|
||||||
//{
|
|
||||||
// static constexpr int FLAG_POS = 9;
|
|
||||||
// autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
|
||||||
|
|
||||||
// dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
|
||||||
//{
|
|
||||||
// static constexpr int FLAG_POS = 9;
|
|
||||||
|
|
||||||
// if (newMass < 0.0f)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// if (type != Type::DYNAMIC)
|
|
||||||
// {
|
|
||||||
// SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
// mass = newMass;
|
|
||||||
|
|
||||||
// // Turn off automass
|
|
||||||
// flags &= ~(1U << FLAG_POS);
|
|
||||||
//}
|
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 10;
|
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
drag = newDrag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 11;
|
|
||||||
|
|
||||||
if (type != Type::DYNAMIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirtyFlags |= 1U << FLAG_POS;
|
|
||||||
angularDrag = newAngularDrag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
|
||||||
if (!physicsObject)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
||||||
{
|
{
|
||||||
static constexpr int FLAG_POS = 13;
|
|
||||||
|
|
||||||
if (type == Type::STATIC)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
|
||||||
if (!physicsObject)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -413,81 +206,57 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRigidBodyComponent::OnCreate()
|
void SHRigidBodyComponent::OnCreate()
|
||||||
{
|
{
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (!physicsSystem)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
system = physicsSystem;
|
|
||||||
|
|
||||||
// Sync with transform if one already exists
|
|
||||||
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
|
|
||||||
{
|
|
||||||
position = transformComponent->GetWorldPosition();
|
|
||||||
orientation = transformComponent->GetWorldOrientation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyWorldForceAtCenterOfMass(force);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyWorldTorque(torque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->applyLocalTorque(relativeTorque);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::ClearForces() const noexcept
|
void SHRigidBodyComponent::ClearForces() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->resetForce();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHRigidBodyComponent::ClearTorque() const noexcept
|
void SHRigidBodyComponent::ClearTorque() const noexcept
|
||||||
{
|
{
|
||||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
|
||||||
physicsObject->GetRigidBody()->resetTorque();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
@ -512,7 +281,6 @@ RTTR_REGISTRATION
|
||||||
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
|
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
|
||||||
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
|
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
|
||||||
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep)
|
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep)
|
||||||
//.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass )
|
|
||||||
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
|
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
|
||||||
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
|
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
|
||||||
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )
|
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )
|
||||||
|
|
|
@ -82,8 +82,6 @@ namespace SHADE
|
||||||
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
||||||
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
||||||
|
|
||||||
//[[nodiscard]] bool GetAutoMass () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] float GetMass () const noexcept;
|
[[nodiscard]] float GetMass () const noexcept;
|
||||||
[[nodiscard]] float GetDrag () const noexcept;
|
[[nodiscard]] float GetDrag () const noexcept;
|
||||||
[[nodiscard]] float GetAngularDrag () const noexcept;
|
[[nodiscard]] float GetAngularDrag () const noexcept;
|
||||||
|
@ -93,9 +91,9 @@ namespace SHADE
|
||||||
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
||||||
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
//[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
||||||
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
//[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
||||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
//[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
|
@ -144,26 +142,6 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static constexpr size_t NUM_FLAGS = 8;
|
|
||||||
static constexpr size_t NUM_DIRTY_FLAGS = 12;
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
|
|
||||||
uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g
|
|
||||||
uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g
|
|
||||||
|
|
||||||
float mass;
|
|
||||||
float drag;
|
|
||||||
float angularDrag;
|
|
||||||
|
|
||||||
SHVec3 linearVelocity;
|
|
||||||
SHVec3 angularVelocity;
|
|
||||||
|
|
||||||
SHPhysicsSystem* system;
|
|
||||||
|
|
||||||
SHVec3 position;
|
|
||||||
SHQuaternion orientation;
|
|
||||||
|
|
||||||
RTTR_ENABLE()
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -1,431 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsObject.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Physics Object.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsObject.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
|
||||||
#include "Scene/SHSceneManager.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
|
||||||
: entityID { eid }
|
|
||||||
, collidersActive { true }
|
|
||||||
, factory { physicsFactory }
|
|
||||||
, world { physicsWorld }
|
|
||||||
, rp3dBody { nullptr }
|
|
||||||
{
|
|
||||||
// Implicitly create a static body.
|
|
||||||
|
|
||||||
const auto* TRANSFORM = SHComponentManager::GetComponent<SHTransformComponent>(eid);
|
|
||||||
|
|
||||||
const rp3d::Transform RP3D_TRANSFORM { TRANSFORM->GetWorldPosition(), TRANSFORM->GetWorldOrientation() };
|
|
||||||
|
|
||||||
rp3dBody = world->createRigidBody(RP3D_TRANSFORM);
|
|
||||||
rp3dBody->setType(rp3d::BodyType::STATIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsObject::~SHPhysicsObject() noexcept
|
|
||||||
{
|
|
||||||
factory = nullptr;
|
|
||||||
world = nullptr;
|
|
||||||
rp3dBody = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsObject::GetPosition() const noexcept
|
|
||||||
{
|
|
||||||
return rp3dBody->getTransform().getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion SHPhysicsObject::GetOrientation() const noexcept
|
|
||||||
{
|
|
||||||
return rp3dBody->getTransform().getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsObject::GetRotation() const noexcept
|
|
||||||
{
|
|
||||||
return SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler();
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::CollisionBody* SHPhysicsObject::GetCollisionBody() const noexcept
|
|
||||||
{
|
|
||||||
return rp3dBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::RigidBody* SHPhysicsObject::GetRigidBody() const noexcept
|
|
||||||
{
|
|
||||||
return rp3dBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsObject::SetStaticBody() const noexcept
|
|
||||||
{
|
|
||||||
if (!rp3dBody)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rp3dBody->setType(rp3d::BodyType::STATIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int SHPhysicsObject::AddCollisionShape(int index)
|
|
||||||
{
|
|
||||||
// Get collider component
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
|
||||||
if (!colliderComponent)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to add Collision Shape to Entity {} due to Missing Collider Component!", entityID)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& collisionShape = colliderComponent->GetCollisionShape(index);
|
|
||||||
switch (collisionShape.GetType())
|
|
||||||
{
|
|
||||||
// TODO(Diren): Add more collider shapes
|
|
||||||
|
|
||||||
case SHCollisionShape::Type::BOX:
|
|
||||||
{
|
|
||||||
addBoxShape(collisionShape);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SHCollisionShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
addSphereShape(collisionShape);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* rp3dCollider = rp3dBody->getCollider(rp3dBody->getNbColliders() - 1);
|
|
||||||
syncColliderProperties(collisionShape, rp3dCollider);
|
|
||||||
|
|
||||||
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
|
|
||||||
{
|
|
||||||
rp3dBody->updateMassPropertiesFromColliders();
|
|
||||||
|
|
||||||
if (auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); rigidBodyComponent)
|
|
||||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveCollisionShape(int index)
|
|
||||||
{
|
|
||||||
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
|
||||||
if (NUM_COLLIDERS == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (index < 0 || index >= NUM_COLLIDERS)
|
|
||||||
throw std::invalid_argument("Index out of range!");
|
|
||||||
|
|
||||||
auto* collider = rp3dBody->getCollider(index);
|
|
||||||
rp3dBody->removeCollider(collider);
|
|
||||||
|
|
||||||
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
|
|
||||||
{
|
|
||||||
rp3dBody->updateMassPropertiesFromColliders();
|
|
||||||
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
if (rigidBodyComponent)
|
|
||||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept
|
|
||||||
{
|
|
||||||
int numColliders = static_cast<int>(rp3dBody->getNbColliders());
|
|
||||||
if (numColliders == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (numColliders - 1 >= 0)
|
|
||||||
{
|
|
||||||
auto* collider = rp3dBody->getCollider(numColliders - 1);
|
|
||||||
rp3dBody->removeCollider(collider);
|
|
||||||
|
|
||||||
--numColliders;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept
|
|
||||||
{
|
|
||||||
// This state is synced in the pre-update routine
|
|
||||||
if (!rp3dBody->isActive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (component.dirtyFlags == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
|
|
||||||
{
|
|
||||||
if (const bool IS_DIRTY = component.dirtyFlags & (1U << i); IS_DIRTY)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0: // Gravity
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
rp3dBody->enableGravity(IS_ENABLED);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // Sleeping
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
rp3dBody->setIsAllowedToSleep(IS_ENABLED);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: // Lock Position X
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
positionLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // Lock Position Y
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
positionLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // Lock Position Z
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
|
||||||
positionLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5: // Lock Rotation X
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
rotationLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 6: // Lock Rotation Y
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
rotationLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 7: // Lock Rotation Z
|
|
||||||
{
|
|
||||||
const bool IS_ENABLED = component.flags & (1U << i);
|
|
||||||
|
|
||||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
|
||||||
rotationLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
|
||||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8: // Type
|
|
||||||
{
|
|
||||||
rp3dBody->setType(static_cast<rp3d::BodyType>(component.type));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 9: // Mass
|
|
||||||
{
|
|
||||||
//rp3dBody->setMass(component.mass);
|
|
||||||
|
|
||||||
//if (component.GetAutoMass())
|
|
||||||
//{
|
|
||||||
// rp3dBody->updateMassPropertiesFromColliders();
|
|
||||||
// component.mass = rp3dBody->getMass();
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// rp3dBody->setMass(component.mass);
|
|
||||||
// rp3dBody->updateLocalCenterOfMassFromColliders();
|
|
||||||
// rp3dBody->updateLocalInertiaTensorFromColliders();
|
|
||||||
//}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 10: // Drag
|
|
||||||
{
|
|
||||||
rp3dBody->setLinearDamping(component.drag);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 11: // Angular Drag
|
|
||||||
{
|
|
||||||
rp3dBody->setAngularDamping(component.angularDrag);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component.dirtyFlags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept
|
|
||||||
{
|
|
||||||
// This state is synced in the pre-update routine
|
|
||||||
if (!rp3dBody->isActive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const int NUM_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
|
||||||
for (int i = 0; i < NUM_SHAPES; ++i)
|
|
||||||
{
|
|
||||||
auto& collisionShape = component.collisionShapes[i];
|
|
||||||
|
|
||||||
if (!collisionShape.dirty)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (collisionShape.GetType())
|
|
||||||
{
|
|
||||||
case SHCollisionShape::Type::BOX: syncBoxShape(i, collisionShape); break;
|
|
||||||
case SHCollisionShape::Type::SPHERE: syncSphereShape(i, collisionShape); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* rp3dCollider = rp3dBody->getCollider(i);
|
|
||||||
syncColliderProperties(collisionShape, rp3dCollider);
|
|
||||||
|
|
||||||
collisionShape.dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set rigidbody mass if dynamic
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
if (rigidBodyComponent)
|
|
||||||
{
|
|
||||||
// This is generally expensive, will be optimised in the future with my own engine.
|
|
||||||
rp3dBody->updateMassPropertiesFromColliders();
|
|
||||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsObject::syncColliderProperties(const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept
|
|
||||||
{
|
|
||||||
rp3dCollider->setIsTrigger(collisionShape.IsTrigger());
|
|
||||||
|
|
||||||
auto& rp3dMaterial = rp3dCollider->getMaterial();
|
|
||||||
|
|
||||||
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
|
|
||||||
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
|
|
||||||
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
|
|
||||||
|
|
||||||
const unsigned short MASK_BITS = collisionShape.GetCollisionTag();
|
|
||||||
rp3dCollider->setCollisionCategoryBits(MASK_BITS);
|
|
||||||
rp3dCollider->setCollideWithMaskBits(MASK_BITS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::addBoxShape(const SHCollisionShape& boxShape) const noexcept
|
|
||||||
{
|
|
||||||
const rp3d::Transform OFFSETS
|
|
||||||
{
|
|
||||||
boxShape.GetPositionOffset()
|
|
||||||
, boxShape.GetRotationOffset()
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto* BOX = reinterpret_cast<const SHBox*>(boxShape.GetShape());
|
|
||||||
rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents());
|
|
||||||
|
|
||||||
rp3dBody->addCollider(newBox, OFFSETS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::syncBoxShape(int index, const SHCollisionShape& boxShape) const noexcept
|
|
||||||
{
|
|
||||||
const auto* BOX = reinterpret_cast<const SHBox*>(boxShape.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dCollider = rp3dBody->getCollider(index);
|
|
||||||
auto* rp3dBox = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
|
|
||||||
const rp3d::Transform OFFSETS
|
|
||||||
{
|
|
||||||
boxShape.GetPositionOffset()
|
|
||||||
, boxShape.GetRotationOffset()
|
|
||||||
};
|
|
||||||
|
|
||||||
rp3dCollider->setIsTrigger(boxShape.IsTrigger());
|
|
||||||
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
|
||||||
|
|
||||||
rp3dBox->setHalfExtents(BOX->GetWorldExtents());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::addSphereShape(const SHCollisionShape& sphereShape) const noexcept
|
|
||||||
{
|
|
||||||
const rp3d::Transform OFFSETS
|
|
||||||
{
|
|
||||||
sphereShape.GetPositionOffset()
|
|
||||||
, sphereShape.GetRotationOffset()
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(sphereShape.GetShape());
|
|
||||||
rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius());
|
|
||||||
|
|
||||||
rp3dBody->addCollider(newSphere, OFFSETS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObject::syncSphereShape(int index, const SHCollisionShape& sphereShape) const noexcept
|
|
||||||
{
|
|
||||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(sphereShape.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dCollider = rp3dBody->getCollider(index);
|
|
||||||
auto* rp3dSphere = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
|
||||||
|
|
||||||
const rp3d::Transform OFFSETS
|
|
||||||
{
|
|
||||||
sphereShape.GetPositionOffset()
|
|
||||||
, sphereShape.GetRotationOffset()
|
|
||||||
};
|
|
||||||
|
|
||||||
rp3dCollider->setIsTrigger(sphereShape.IsTrigger());
|
|
||||||
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
|
||||||
|
|
||||||
rp3dSphere->setRadius(SPHERE->GetWorldRadius());
|
|
||||||
}
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,111 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsObject.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for a Physics Object.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
|
||||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
|
||||||
#include "Physics/Interface/SHColliderComponent.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsObject
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Friends */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
|
||||||
friend class SHPhysicsObjectManager;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject (EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept;
|
|
||||||
SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default;
|
|
||||||
SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default;
|
|
||||||
virtual ~SHPhysicsObject () noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Operator Overloads */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept = default;
|
|
||||||
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept = default;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
|
||||||
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
|
||||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept;
|
|
||||||
[[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SetStaticBody () const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int AddCollisionShape (int index);
|
|
||||||
void RemoveCollisionShape (int index);
|
|
||||||
void RemoveAllCollisionShapes () const noexcept;
|
|
||||||
|
|
||||||
void SyncRigidBody (SHRigidBodyComponent& component) const noexcept;
|
|
||||||
void SyncColliders (SHColliderComponent& component) const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
EntityID entityID;
|
|
||||||
bool collidersActive; // Only used to sync with SHADE components
|
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory;
|
|
||||||
rp3d::PhysicsWorld* world;
|
|
||||||
|
|
||||||
rp3d::RigidBody* rp3dBody;
|
|
||||||
rp3d::Transform prevTransform; // Cached transform for interpolation
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void syncColliderProperties (const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept;
|
|
||||||
|
|
||||||
// Box Shapes
|
|
||||||
|
|
||||||
void addBoxShape (const SHCollisionShape& boxShape) const noexcept;
|
|
||||||
void syncBoxShape (int index, const SHCollisionShape& boxShape) const noexcept;
|
|
||||||
|
|
||||||
// Sphere Shapes
|
|
||||||
|
|
||||||
void addSphereShape (const SHCollisionShape& sphereShape) const noexcept;
|
|
||||||
void syncSphereShape (int index, const SHCollisionShape& sphereShape) const noexcept;
|
|
||||||
};
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,309 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsObjectManager.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Physics Object Manager.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsObjectManager.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
|
||||||
#include "Tools/Utilities/SHUtilities.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Static Data Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[3][2]
|
|
||||||
{
|
|
||||||
addRigidBody , addCollider , addCollisionShape
|
|
||||||
, removeRigidBody , removeCollider , removeCollisionShape
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon& physicsFactory) noexcept
|
|
||||||
{
|
|
||||||
factory = &physicsFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::SetWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
|
||||||
{
|
|
||||||
world = physicsWorld;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const auto it = physicsObjects.find(eid);
|
|
||||||
if (it == physicsObjects.end())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return &it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHPhysicsObjectManager::PhysicsObjectEntityMap SHPhysicsObjectManager::GetPhysicsObjects() const noexcept
|
|
||||||
{
|
|
||||||
return physicsObjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::AddRigidBody(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::ADD
|
|
||||||
, .component = PhysicsComponents::RIGID_BODY
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::AddCollider(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::ADD
|
|
||||||
, .component = PhysicsComponents::COLLIDER
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::AddCollisionShape(EntityID eid, int shapeIndex) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::ADD
|
|
||||||
, .component = PhysicsComponents::COLLISION_SHAPE
|
|
||||||
, .shapeIndex = shapeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::RemoveRigidBody(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::REMOVE
|
|
||||||
, .component = PhysicsComponents::RIGID_BODY
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::RemoveCollider(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::REMOVE
|
|
||||||
, .component = PhysicsComponents::COLLIDER
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::RemoveCollisionShape(EntityID eid, int shapeIndex) noexcept
|
|
||||||
{
|
|
||||||
const QueueCommand NEW_QUEUE_COMMAND
|
|
||||||
{
|
|
||||||
.eid = eid
|
|
||||||
, .command = QueueCommand::Command::REMOVE
|
|
||||||
, .component = PhysicsComponents::COLLISION_SHAPE
|
|
||||||
, .shapeIndex = shapeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::UpdateCommands()
|
|
||||||
{
|
|
||||||
if (commandQueue.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (!commandQueue.empty())
|
|
||||||
{
|
|
||||||
const QueueCommand COMMAND = commandQueue.front();
|
|
||||||
commandQueue.pop();
|
|
||||||
|
|
||||||
// Check validity of command
|
|
||||||
if (COMMAND.command == QueueCommand::Command::INVALID || COMMAND.component == PhysicsComponents::INVALID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Get physics components
|
|
||||||
const PhysicsComponentGroup COMPONENT_GROUP
|
|
||||||
{
|
|
||||||
.eid = COMMAND.eid
|
|
||||||
, .rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(COMMAND.eid)
|
|
||||||
, .colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(COMMAND.eid)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Delete any object that is missing both components
|
|
||||||
// We infer that a remove command has been pushed for these, but we will ignore those if both components have already been removed.
|
|
||||||
if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent)
|
|
||||||
{
|
|
||||||
destroyPhysicsObject(COMMAND.eid);
|
|
||||||
wakeAllObjects();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the physics Object. If none found and attempting to add, create an object.
|
|
||||||
SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid);
|
|
||||||
if (!physicsObject && COMMAND.command == QueueCommand::Command::ADD)
|
|
||||||
physicsObject = createPhysicsObject(COMMAND.eid);
|
|
||||||
|
|
||||||
componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP);
|
|
||||||
|
|
||||||
// If any removal was done, wake all objects
|
|
||||||
if (COMMAND.command == QueueCommand::Command::REMOVE)
|
|
||||||
wakeAllObjects();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::RemoveAllObjects()
|
|
||||||
{
|
|
||||||
// Destroy all objects and clear
|
|
||||||
for (auto& physicsObject : physicsObjects | std::views::values)
|
|
||||||
{
|
|
||||||
world->destroyRigidBody(physicsObject.GetRigidBody());
|
|
||||||
physicsObject.rp3dBody = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
physicsObjects.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
// Force transforms to sync
|
|
||||||
SHVec3 worldPos = SHVec3::Zero;
|
|
||||||
SHQuaternion worldRot = SHQuaternion::Identity;
|
|
||||||
|
|
||||||
const SHTransformComponent* TRANSFORM = nullptr;
|
|
||||||
if (SHEntityManager::IsValidEID(eid))
|
|
||||||
TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
|
||||||
|
|
||||||
if (TRANSFORM)
|
|
||||||
{
|
|
||||||
worldPos = TRANSFORM->GetWorldPosition();
|
|
||||||
worldRot = TRANSFORM->GetWorldOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
const rp3d::Transform RP3D_TRANSFORM{ worldPos, worldRot };
|
|
||||||
|
|
||||||
auto& newPhysicsObject = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }).first->second;
|
|
||||||
newPhysicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
|
||||||
newPhysicsObject.prevTransform = RP3D_TRANSFORM;
|
|
||||||
|
|
||||||
return &newPhysicsObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
const auto ITER = physicsObjects.find(eid);
|
|
||||||
if (ITER == physicsObjects.end())
|
|
||||||
{
|
|
||||||
// Assume the object has already been successfully destroyed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
world->destroyRigidBody(ITER->second.GetRigidBody());
|
|
||||||
ITER->second.rp3dBody = nullptr;
|
|
||||||
|
|
||||||
physicsObjects.erase(eid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::addRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add body!")
|
|
||||||
|
|
||||||
if (!componentGroup.rigidBodyComponent)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A static rigid body is implicitly created on creation of a physics object.
|
|
||||||
// Nothing is needed here.
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::addCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collider!")
|
|
||||||
|
|
||||||
if (!componentGroup.colliderComponent)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//const int NUM_SHAPES = static_cast<int>(componentGroup.colliderComponent->GetCollisionShapes().size());
|
|
||||||
//for (int i = 0; i < NUM_SHAPES; ++i)
|
|
||||||
// physicsObject->AddCollisionShape(i);
|
|
||||||
|
|
||||||
physicsObject->SyncColliders(*componentGroup.colliderComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::removeRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!")
|
|
||||||
|
|
||||||
if (componentGroup.colliderComponent)
|
|
||||||
physicsObject->SetStaticBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::removeCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!")
|
|
||||||
|
|
||||||
physicsObject->RemoveAllCollisionShapes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::addCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!")
|
|
||||||
|
|
||||||
physicsObject->AddCollisionShape(command.shapeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::removeCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
|
||||||
{
|
|
||||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!")
|
|
||||||
|
|
||||||
physicsObject->RemoveCollisionShape(command.shapeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsObjectManager::wakeAllObjects() noexcept
|
|
||||||
{
|
|
||||||
for (auto& physicsObject : physicsObjects | std::views::values)
|
|
||||||
physicsObject.GetRigidBody()->setIsSleeping(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,181 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsObjectManager.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for a Physics Object Manager.
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "SHPhysicsObject.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsObjectManager
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Friends */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
friend class SHPhysicsSystem;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
using PhysicsObjectEntityMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
enum class PhysicsComponents
|
|
||||||
{
|
|
||||||
RIGID_BODY
|
|
||||||
, COLLIDER
|
|
||||||
, COLLISION_SHAPE
|
|
||||||
|
|
||||||
, TOTAL
|
|
||||||
, INVALID = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObjectManager () = default;
|
|
||||||
~SHPhysicsObjectManager () = default;
|
|
||||||
|
|
||||||
SHPhysicsObjectManager (const SHPhysicsObjectManager&) = delete;
|
|
||||||
SHPhysicsObjectManager (SHPhysicsObjectManager&&) = delete;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Operator Overloads */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObjectManager& operator=(const SHPhysicsObjectManager&) = delete;
|
|
||||||
SHPhysicsObjectManager& operator=(SHPhysicsObjectManager&&) = delete;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
[[nodiscard]] SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept;
|
|
||||||
[[nodiscard]] const PhysicsObjectEntityMap GetPhysicsObjects () const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SetFactory (rp3d::PhysicsCommon& physicsFactory) noexcept;
|
|
||||||
void SetWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void AddRigidBody (EntityID eid) noexcept;
|
|
||||||
void AddCollider (EntityID eid) noexcept;
|
|
||||||
void AddCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
|
||||||
|
|
||||||
void RemoveRigidBody (EntityID eid) noexcept;
|
|
||||||
void RemoveCollider (EntityID eid) noexcept;
|
|
||||||
void RemoveCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
|
||||||
|
|
||||||
void UpdateCommands ();
|
|
||||||
void RemoveAllObjects ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
struct QueueCommand
|
|
||||||
{
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
enum class Command
|
|
||||||
{
|
|
||||||
ADD
|
|
||||||
, REMOVE
|
|
||||||
|
|
||||||
, INVALID = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
EntityID eid = MAX_EID;
|
|
||||||
Command command = Command::INVALID;
|
|
||||||
PhysicsComponents component = PhysicsComponents::INVALID;
|
|
||||||
int shapeIndex = -1; // Only used when adding & removing collision shapes
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PhysicsComponentGroup
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
EntityID eid = MAX_EID;
|
|
||||||
SHRigidBodyComponent* rigidBodyComponent = nullptr;
|
|
||||||
SHColliderComponent* colliderComponent = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CommandFunctionPtr = void(*)(const QueueCommand&, SHPhysicsObject*, const PhysicsComponentGroup&);
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static CommandFunctionPtr componentFunc[3][2]; // 3 components, 2 commands
|
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory = nullptr;
|
|
||||||
rp3d::PhysicsWorld* world = nullptr;
|
|
||||||
|
|
||||||
PhysicsObjectEntityMap physicsObjects;
|
|
||||||
std::queue<QueueCommand> commandQueue;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept;
|
|
||||||
void destroyPhysicsObject (EntityID eid) noexcept;
|
|
||||||
|
|
||||||
void wakeAllObjects () noexcept;
|
|
||||||
|
|
||||||
static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
static void removeCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
|
|
||||||
static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,334 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsDebugDrawSystem.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for the Physics Debug Draw System
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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.
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <SHpch.h>
|
|
||||||
|
|
||||||
// Primary Header
|
|
||||||
#include "SHPhysicsDebugDrawSystem.h"
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
|
||||||
#include "Editor/SHEditor.h"
|
|
||||||
#include "Scene/SHSceneManager.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Static Data Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
|
|
||||||
{
|
|
||||||
drawColliders
|
|
||||||
, drawColliderAABBs
|
|
||||||
, drawBroadPhaseAABBs
|
|
||||||
, drawContactPoints
|
|
||||||
, drawContactNormals
|
|
||||||
, drawRaycasts
|
|
||||||
};
|
|
||||||
|
|
||||||
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
|
||||||
: debugDrawFlags { 0 }
|
|
||||||
, physicsSystem { nullptr }
|
|
||||||
{
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN;
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::RAYCASTS)] = SHColour::ORANGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
|
||||||
: SHSystemRoutine { "Physics Debug Draw", true }
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
bool SHPhysicsDebugDrawSystem::GetDebugDrawFlag(DebugDrawFlags flag) const noexcept
|
|
||||||
{
|
|
||||||
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
|
||||||
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to get debug draw state!", INT_FLAG)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return debugDrawFlags & 1U << SHUtilities::ConvertEnum(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Function Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept
|
|
||||||
{
|
|
||||||
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
|
||||||
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to set debug draw state!", INT_FLAG)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value ? (debugDrawFlags |= 1U << INT_FLAG) : (debugDrawFlags &= ~(1U << INT_FLAG));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::Init()
|
|
||||||
{
|
|
||||||
SystemFamily::GetID<SHPhysicsDebugDrawSystem>();
|
|
||||||
|
|
||||||
SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!")
|
|
||||||
physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
|
|
||||||
// Generate shapes
|
|
||||||
generateBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::Exit()
|
|
||||||
{
|
|
||||||
physicsSystem = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::Execute(double) noexcept
|
|
||||||
{
|
|
||||||
auto* system = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
|
||||||
|
|
||||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
|
||||||
if (debugDrawSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rp3d::DebugRenderer* rp3dRenderer = nullptr;
|
|
||||||
if (system->physicsSystem->worldState.world)
|
|
||||||
rp3dRenderer = &system->physicsSystem->worldState.world->getDebugRenderer();
|
|
||||||
|
|
||||||
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
|
||||||
{
|
|
||||||
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
|
||||||
if (DRAW)
|
|
||||||
{
|
|
||||||
drawFunctions[i](debugDrawSystem, rp3dRenderer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (rp3dRenderer && (i == 3 || i == 4))
|
|
||||||
{
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_POINT, false);
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_NORMAL, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Automatically clear the container of raycasts despite debug drawing state
|
|
||||||
// TODO(Diren): Move this somewhere else
|
|
||||||
system->physicsSystem->raycaster.ClearFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
|
||||||
for (const auto& COLLIDER : COLLIDER_SET)
|
|
||||||
{
|
|
||||||
// Skip inactive colliders
|
|
||||||
if (!SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(COLLIDER.GetEID()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (auto& collisionShape : COLLIDER.GetCollisionShapes())
|
|
||||||
{
|
|
||||||
switch (collisionShape.GetType())
|
|
||||||
{
|
|
||||||
case SHCollisionShape::Type::BOX: debugDrawBox(debugRenderer, COLLIDER, collisionShape); break;
|
|
||||||
case SHCollisionShape::Type::SPHERE: debugDrawSphere(debugRenderer, COLLIDER, collisionShape); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
{
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
|
|
||||||
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
|
|
||||||
if (NUM_TRIS == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
|
|
||||||
for (int i = 0; i < NUM_TRIS; ++i)
|
|
||||||
debugRenderer->DrawTri(SHColour::RED, TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
|
|
||||||
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
|
|
||||||
if (NUM_TRIS == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
|
|
||||||
for (int i = 0; i < NUM_TRIS; ++i)
|
|
||||||
debugRenderer->DrawTri(SHColour::RED, TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
{
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
|
|
||||||
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
|
|
||||||
if (NUM_LINES == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
|
|
||||||
for (int i = 0; i < NUM_LINES; ++i)
|
|
||||||
debugRenderer->DrawLine(SHColour::RED, LINE_ARRAY[i].point1, LINE_ARRAY[i].point2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
|
|
||||||
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
|
|
||||||
if (NUM_LINES == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
|
|
||||||
for (int i = 0; i < NUM_LINES; ++i)
|
|
||||||
debugRenderer->DrawLine(SHColour::RED, LINE_ARRAY[i].point1, LINE_ARRAY[i].point2);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (!physicsSystem)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to retrieve physics system for debug drawing raycasts!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHColour& RAY_COLOUR = SHColour::ORANGE;
|
|
||||||
|
|
||||||
// Draw all raycast pairs
|
|
||||||
for (const auto& [ray, raycastResult] : physicsSystem->raycaster.GetRaycasts())
|
|
||||||
{
|
|
||||||
// If infinity, it is an infinite raycast. If not, render the distance in raycastResult.
|
|
||||||
// Ignore the hit variable as it will always correspond to the length of the raycast, hit or miss.
|
|
||||||
const float RENDER_DIST = raycastResult.distance == std::numeric_limits<float>::infinity() ? SHRay::MAX_RAYCAST_DIST : raycastResult.distance;
|
|
||||||
const SHVec3 END_POS = ray.position + (ray.direction * RENDER_DIST);
|
|
||||||
|
|
||||||
debugRenderer->DrawLine(RAY_COLOUR, ray.position, END_POS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::generateBox() noexcept
|
|
||||||
{
|
|
||||||
boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK
|
|
||||||
boxVertices[1] = { -0.5f, 0.5f, -0.5f }; // TOP_LEFT_BACK
|
|
||||||
boxVertices[2] = { 0.5f, -0.5f, -0.5f }; // BTM_RIGHT_BACK
|
|
||||||
boxVertices[3] = { -0.5f, -0.5f, -0.5f }; // BTM_LEFT_BACK
|
|
||||||
boxVertices[4] = { 0.5f, 0.5f, 0.5f }; // TOP_RIGHT_FRONT
|
|
||||||
boxVertices[5] = { -0.5f, 0.5f, 0.5f }; // TOP_LEFT_FRONT
|
|
||||||
boxVertices[6] = { 0.5f, -0.5f, 0.5f }; // BTM_RIGHT_FRONT
|
|
||||||
boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::debugDrawBox(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
|
||||||
{
|
|
||||||
auto* BOX = reinterpret_cast<const SHBox*>(collisionShape.GetShape());
|
|
||||||
|
|
||||||
// Calculate final position & orientation
|
|
||||||
const SHVec3 COLLIDER_POS = colliderComponent.GetPosition();
|
|
||||||
const SHVec3 BOX_POS = collisionShape.GetPositionOffset();
|
|
||||||
const SHQuaternion COLLIDER_ROT = colliderComponent.GetOrientation();
|
|
||||||
const SHQuaternion BOX_ROT = SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
|
||||||
|
|
||||||
|
|
||||||
const SHMatrix COLLIDER_TR = SHMatrix::Rotate(COLLIDER_ROT) * SHMatrix::Translate(COLLIDER_POS);
|
|
||||||
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(BOX_ROT) * SHMatrix::Translate(BOX_POS);
|
|
||||||
|
|
||||||
const SHMatrix FINAL_TRS = BOX_TRS * COLLIDER_TR;
|
|
||||||
|
|
||||||
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
|
||||||
|
|
||||||
std::array<SHVec3, NUM_BOX_VERTICES> transformedVertices;
|
|
||||||
for (uint32_t i = 0; i < NUM_BOX_VERTICES / 2; ++i)
|
|
||||||
{
|
|
||||||
const uint32_t IDX1 = i;
|
|
||||||
const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2;
|
|
||||||
|
|
||||||
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], FINAL_TRS);
|
|
||||||
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
|
|
||||||
|
|
||||||
// Draw 4 line to connect the quads
|
|
||||||
debugRenderer->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A, B, C, D
|
|
||||||
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
|
||||||
debugRenderer->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
|
|
||||||
|
|
||||||
// E, F, G, H
|
|
||||||
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
|
||||||
debugRenderer->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::debugDrawSphere(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
|
||||||
{
|
|
||||||
auto* SPHERE = reinterpret_cast<const SHSphere*>(collisionShape.GetShape());
|
|
||||||
|
|
||||||
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
|
||||||
|
|
||||||
// Calculate final position & orientation
|
|
||||||
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
|
||||||
const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition());
|
|
||||||
|
|
||||||
debugRenderer->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -1,138 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsDebugDrawSystem.h
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Interface for the Physics Debug Draw System
|
|
||||||
*
|
|
||||||
* \copyright Copyright (C) 2022 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
|
|
||||||
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
|
||||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
|
||||||
#include "Math/SHColour.h"
|
|
||||||
#include "SHPhysicsSystem.h"
|
|
||||||
#include "Tools/Utilities/SHUtilities.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API SHPhysicsDebugDrawSystem final : public SHSystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
enum class DebugDrawFlags
|
|
||||||
{
|
|
||||||
COLLIDER
|
|
||||||
, COLLIDER_AABB
|
|
||||||
, BROAD_PHASE_AABB
|
|
||||||
, CONTACT_POINTS
|
|
||||||
, CONTACT_NORMALS
|
|
||||||
, RAYCASTS
|
|
||||||
|
|
||||||
, NUM_FLAGS
|
|
||||||
};
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
SHPhysicsDebugDrawSystem() noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Getter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
bool GetDebugDrawFlag(DebugDrawFlags flag) const noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Setter Functions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void Init() override;
|
|
||||||
void Exit() override;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* System Routines */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class SH_API PhysicsDebugDrawRoutine final : public SHSystemRoutine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
PhysicsDebugDrawRoutine();
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
|
||||||
void Execute(double dt) noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Type Definitions */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
using DebugDrawFunction = void(*)(SHDebugDrawSystem*, rp3d::DebugRenderer*) noexcept;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
|
|
||||||
static const DebugDrawFunction drawFunctions[NUM_FLAGS];
|
|
||||||
|
|
||||||
// SHAPES INFO
|
|
||||||
|
|
||||||
static constexpr size_t NUM_BOX_VERTICES = 8;
|
|
||||||
static SHVec3 boxVertices[NUM_BOX_VERTICES];
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t debugDrawFlags;
|
|
||||||
SHPhysicsSystem* physicsSystem;
|
|
||||||
SHColour debugColours[NUM_FLAGS];
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Function Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
// Generic Draw Functions
|
|
||||||
|
|
||||||
static void drawColliders (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
static void drawContactPoints (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
static void drawContactNormals (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
static void drawRaycasts (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
|
||||||
|
|
||||||
// Shape Generation Functions
|
|
||||||
|
|
||||||
static void generateBox () noexcept;
|
|
||||||
|
|
||||||
// Shape Draw Functions
|
|
||||||
|
|
||||||
static void debugDrawBox (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
|
||||||
static void debugDrawSphere (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -45,32 +45,6 @@ namespace SHADE
|
||||||
return 1.0 / fixedDT;
|
return 1.0 / fixedDT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept
|
|
||||||
{
|
|
||||||
return worldState.settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<SHCollisionInfo>& SHPhysicsSystem::GetAllCollisionInfo() const noexcept
|
|
||||||
{
|
|
||||||
return collisionListener.GetCollisionInfoContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<SHCollisionInfo>& SHPhysicsSystem::GetAllTriggerInfo() const noexcept
|
|
||||||
{
|
|
||||||
return collisionListener.GetTriggerInfoContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept
|
|
||||||
{
|
|
||||||
return objectManager.GetPhysicsObject(eid);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const SHPhysicsObjectManager::PhysicsObjectEntityMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept
|
|
||||||
{
|
|
||||||
return objectManager.physicsObjects;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Function Definitions */
|
/* Setter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -80,12 +54,6 @@ namespace SHADE
|
||||||
fixedDT = 1.0 / fixedUpdateRate;
|
fixedDT = 1.0 / fixedUpdateRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept
|
|
||||||
{
|
|
||||||
worldState.settings = settings;
|
|
||||||
worldState.UpdateSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -96,41 +64,10 @@ namespace SHADE
|
||||||
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
|
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
|
||||||
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
|
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
|
||||||
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
|
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
|
||||||
|
|
||||||
// Link Physics Object Manager with System & Raycaster
|
|
||||||
objectManager.SetFactory(factory);
|
|
||||||
raycaster.SetObjectManager(&objectManager);
|
|
||||||
|
|
||||||
// Link Collision Listener with System
|
|
||||||
collisionListener.BindToSystem(this);
|
|
||||||
|
|
||||||
// Subscribe to component events
|
|
||||||
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
|
|
||||||
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
|
||||||
|
|
||||||
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::removePhysicsComponent) };
|
|
||||||
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
// Subscribe to Editor State Change Events
|
|
||||||
const std::shared_ptr ON_PLAY_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onPlay) };
|
|
||||||
const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PLAY_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR);
|
|
||||||
|
|
||||||
const std::shared_ptr ON_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onStop) };
|
|
||||||
const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_STOP_RECEIVER);
|
|
||||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::Exit()
|
void SHPhysicsSystem::Exit()
|
||||||
{
|
{
|
||||||
worldState.DestroyWorld(factory);
|
|
||||||
|
|
||||||
// Write collision tag names to file
|
// Write collision tag names to file
|
||||||
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
|
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
|
||||||
|
@ -138,344 +75,13 @@ namespace SHADE
|
||||||
SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath);
|
SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::BuildScene(SHSceneGraph& sceneGraph)
|
|
||||||
{
|
|
||||||
static const auto BUILD_NEW_SCENE_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
|
||||||
{
|
|
||||||
const EntityID EID = node->GetEntityID();
|
|
||||||
|
|
||||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
|
||||||
objectManager.AddRigidBody(EID);
|
|
||||||
|
|
||||||
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
|
||||||
{
|
|
||||||
objectManager.AddCollider(EID);
|
|
||||||
|
|
||||||
auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID);
|
|
||||||
for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i)
|
|
||||||
objectManager.AddCollisionShape(EID, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
// Destroy an existing world
|
|
||||||
if (worldState.world != nullptr)
|
|
||||||
{
|
|
||||||
objectManager.RemoveAllObjects();
|
|
||||||
objectManager.SetWorld(nullptr);
|
|
||||||
|
|
||||||
collisionListener.ClearContainers();
|
|
||||||
raycaster.ClearFrame();
|
|
||||||
|
|
||||||
worldState.DestroyWorld(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
worldState.CreateWorld(factory);
|
|
||||||
#ifdef _PUBLISH
|
|
||||||
worldState.world->setIsDebugRenderingEnabled(false);
|
|
||||||
#else
|
|
||||||
worldState.world->setIsDebugRenderingEnabled(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Link Collision Listener & Raycaster
|
|
||||||
collisionListener.BindToWorld(worldState.world);
|
|
||||||
raycaster.BindToWorld(worldState.world);
|
|
||||||
|
|
||||||
// Link with object manager & create all physics objects
|
|
||||||
objectManager.SetWorld(worldState.world);
|
|
||||||
|
|
||||||
// When building a scene, clear the object manager command queue and build scene objects again.
|
|
||||||
// This is done to avoid duplicate adds.
|
|
||||||
while (!objectManager.commandQueue.empty())
|
|
||||||
objectManager.commandQueue.pop();
|
|
||||||
|
|
||||||
sceneGraph.Traverse(BUILD_NEW_SCENE_PHYSICS_OBJECT);
|
|
||||||
objectManager.UpdateCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::ForceBuild(SHSceneGraph& sceneGraph)
|
|
||||||
{
|
|
||||||
// HACK: Band-aid fix. To be removed.
|
|
||||||
objectManager.UpdateCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SHPhysicsSystem::ForceUpdate()
|
void SHPhysicsSystem::ForceUpdate()
|
||||||
{
|
{
|
||||||
if (!worldState.world)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to force update without a Physics world!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
|
||||||
if (scriptingSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force the physics world to update once
|
|
||||||
if (scriptingSystem != nullptr)
|
|
||||||
scriptingSystem->ExecuteFixedUpdates();
|
|
||||||
|
|
||||||
worldState.world->update(static_cast<rp3d::decimal>(fixedDT));
|
|
||||||
|
|
||||||
// Sync transforms. No interpolation applied here
|
|
||||||
for (auto& [entityID, physicsObject] : objectManager.physicsObjects)
|
|
||||||
{
|
|
||||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
|
||||||
|
|
||||||
const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
|
|
||||||
const auto& RENDER_POS = CURRENT_TF.getPosition();
|
|
||||||
const auto& RENDER_ROT = CURRENT_TF.getOrientation();
|
|
||||||
|
|
||||||
// Cache transform
|
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
|
||||||
|
|
||||||
// Sync with physics components
|
|
||||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID))
|
|
||||||
{
|
|
||||||
rigidBodyComponent->position = RENDER_POS;
|
|
||||||
rigidBodyComponent->orientation = RENDER_ROT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID))
|
|
||||||
{
|
|
||||||
colliderComponent->position = RENDER_POS;
|
|
||||||
colliderComponent->orientation = RENDER_ROT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set transform for rendering
|
|
||||||
if (transformComponent)
|
|
||||||
{
|
|
||||||
transformComponent->SetWorldPosition(RENDER_POS);
|
|
||||||
transformComponent->SetWorldOrientation(RENDER_ROT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.Raycast(ray, distance, collisionTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.Linecast(start, end, collisionTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.ColliderRaycast(eid, ray, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.ColliderRaycast(eid, shapeIndex, ray, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.ColliderLinecast(eid, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
return raycaster.ColliderLinecast(eid, shapeIndex, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
|
||||||
{
|
|
||||||
static const auto ADD_SHAPE = [&](EntityID entityID, int index)
|
|
||||||
{
|
|
||||||
objectManager.AddCollisionShape(entityID, index);
|
|
||||||
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
|
||||||
auto& collisionShape = colliderComponent->GetCollisionShape(index);
|
|
||||||
|
|
||||||
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
|
|
||||||
{
|
|
||||||
.entityID = entityID
|
|
||||||
, .colliderType = collisionShape.GetType()
|
|
||||||
, .colliderIndex = index
|
|
||||||
};
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
ADD_SHAPE(eid, shapeIndex);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
ADD_SHAPE(eid, shapeIndex);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex)
|
|
||||||
{
|
|
||||||
static const auto REMOVE_SHAPE = [&](EntityID entityID, int index)
|
|
||||||
{
|
|
||||||
objectManager.RemoveCollisionShape(entityID, index);
|
|
||||||
|
|
||||||
const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA
|
|
||||||
{
|
|
||||||
.entityID = entityID
|
|
||||||
, .colliderIndex = index
|
|
||||||
};
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
REMOVE_SHAPE(eid, shapeIndex);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
REMOVE_SHAPE(eid, shapeIndex);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::addPhysicsComponent(SHEventPtr addComponentEvent) noexcept
|
|
||||||
{
|
|
||||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
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 EID = EVENT_DATA->data->eid;
|
|
||||||
|
|
||||||
// We only add tell the physics object manager to add a component if the scene is played
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return EVENT_DATA->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::removePhysicsComponent(SHEventPtr removeComponentEvent) noexcept
|
|
||||||
{
|
|
||||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
|
||||||
|
|
||||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
|
||||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
|
||||||
|
|
||||||
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 EID = EVENT_DATA->data->eid;
|
|
||||||
|
|
||||||
// We only add tell the physics object manager to remove a component if the scene is played
|
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return EVENT_DATA->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent)
|
|
||||||
{
|
|
||||||
static const auto BUILD_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
|
||||||
{
|
|
||||||
const EntityID EID = node->GetEntityID();
|
|
||||||
|
|
||||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
|
||||||
objectManager.AddRigidBody(EID);
|
|
||||||
|
|
||||||
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
|
||||||
{
|
|
||||||
objectManager.AddCollider(EID);
|
|
||||||
|
|
||||||
auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID);
|
|
||||||
for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i)
|
|
||||||
objectManager.AddCollisionShape(EID, i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
// Create physics world
|
|
||||||
if (worldState.world != nullptr)
|
|
||||||
return onPlayEvent->handle;
|
|
||||||
|
|
||||||
worldState.CreateWorld(factory);
|
|
||||||
#ifdef _PUBLISH
|
|
||||||
worldState.world->setIsDebugRenderingEnabled(false);
|
|
||||||
#else
|
|
||||||
worldState.world->setIsDebugRenderingEnabled(true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Link Collision Listener & Raycaster
|
|
||||||
collisionListener.BindToWorld(worldState.world);
|
|
||||||
raycaster.BindToWorld(worldState.world);
|
|
||||||
|
|
||||||
// Link with object manager & create all physics objects
|
|
||||||
objectManager.SetWorld(worldState.world);
|
|
||||||
|
|
||||||
// Build scene
|
|
||||||
SHSceneManager::GetCurrentSceneGraph().Traverse(BUILD_PHYSICS_OBJECT);
|
|
||||||
objectManager.UpdateCommands();
|
|
||||||
|
|
||||||
return onPlayEvent->handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent)
|
|
||||||
{
|
|
||||||
// Remove all physics objects
|
|
||||||
objectManager.RemoveAllObjects();
|
|
||||||
objectManager.SetWorld(nullptr);
|
|
||||||
|
|
||||||
// Clear all collision info
|
|
||||||
// Collision listener is automatically unbound when world is destroyed
|
|
||||||
collisionListener.ClearContainers();
|
|
||||||
raycaster.ClearFrame();
|
|
||||||
|
|
||||||
// Destroy the world
|
|
||||||
worldState.DestroyWorld(factory);
|
|
||||||
|
|
||||||
return onStopEvent->handle;
|
|
||||||
}
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -10,22 +10,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
// External Dependencies
|
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||||
|
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Physics/Collision/SHCollisionListener.h"
|
|
||||||
#include "Physics/Collision/SHPhysicsRaycaster.h"
|
|
||||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Interface/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
|
|
||||||
#include "Physics/SHPhysicsWorld.h"
|
#include "Physics/SHPhysicsWorld.h"
|
||||||
#include "Scene/SHSceneGraph.h"
|
#include "Scene/SHSceneGraph.h"
|
||||||
|
|
||||||
|
@ -58,11 +49,6 @@ namespace SHADE
|
||||||
[[nodiscard]] double GetFixedUpdateRate () const noexcept;
|
[[nodiscard]] double GetFixedUpdateRate () const noexcept;
|
||||||
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
|
||||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllTriggerInfo () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept;
|
|
||||||
[[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept;
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -77,105 +63,8 @@ namespace SHADE
|
||||||
void Init () override;
|
void Init () override;
|
||||||
void Exit () override;
|
void Exit () override;
|
||||||
|
|
||||||
void BuildScene (SHSceneGraph& sceneGraph);
|
|
||||||
void ForceBuild (SHSceneGraph& sceneGraph);
|
|
||||||
void ForceUpdate ();
|
void ForceUpdate ();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Casts a ray into the world.
|
|
||||||
* @param ray The ray to cast.
|
|
||||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
|
||||||
* @param collisionTag The collision tag to use for filtering the raycast.
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult Raycast
|
|
||||||
(
|
|
||||||
const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Casts a bounded ray into the world.
|
|
||||||
* @param start The starting point of the ray.
|
|
||||||
* @param end The end point of the ray.
|
|
||||||
* @param collisionTag The collision tag to use for filtering the bounded raycast.
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult Linecast
|
|
||||||
(
|
|
||||||
const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Casts a ray at a body with colliders.
|
|
||||||
* @param eid The entity to cast to.
|
|
||||||
* @param ray The ray to cast.
|
|
||||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult ColliderRaycast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Casts a ray at a collider.
|
|
||||||
* @param eid The entity to cast to.
|
|
||||||
* @param shapeIndex The index of the collision shape.
|
|
||||||
* @param ray The ray to cast.
|
|
||||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult ColliderRaycast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, int shapeIndex
|
|
||||||
, const SHRay& ray
|
|
||||||
, float distance = std::numeric_limits<float>::infinity()
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Casts a bounded ray at a body with colliders.
|
|
||||||
* @param eid
|
|
||||||
* @param start
|
|
||||||
* @param end
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult ColliderLinecast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
* @param eid
|
|
||||||
* @param shapeIndex
|
|
||||||
* @param start
|
|
||||||
* @param end
|
|
||||||
* @return The result of the raycast.
|
|
||||||
*/
|
|
||||||
SHPhysicsRaycastResult ColliderLinecast
|
|
||||||
(
|
|
||||||
EntityID eid
|
|
||||||
, int shapeIndex
|
|
||||||
, const SHVec3& start
|
|
||||||
, const SHVec3& end
|
|
||||||
) noexcept;
|
|
||||||
|
|
||||||
// Specific Handling for Collision Shapes as they are not under the Component System.
|
|
||||||
// This is done as events need to be sent out.
|
|
||||||
// TODO(Diren): Consider using a static method through the ColliderComponent.
|
|
||||||
|
|
||||||
void AddCollisionShape (EntityID eid, int shapeIndex);
|
|
||||||
void RemoveCollisionShape (EntityID eid, int shapeIndex);
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* System Routines */
|
/* System Routines */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -200,17 +89,6 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
|
|
||||||
void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
|
|
||||||
static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept;
|
|
||||||
|
|
||||||
static void preUpdateSyncTransform
|
|
||||||
(
|
|
||||||
SHPhysicsObject& physicsObject
|
|
||||||
, SHTransformComponent* transformComponent
|
|
||||||
, SHRigidBodyComponent* rigidBodyComponent
|
|
||||||
, SHColliderComponent* colliderComponent
|
|
||||||
) noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||||
|
@ -250,14 +128,6 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void postUpdateSyncTransforms
|
|
||||||
(
|
|
||||||
SHPhysicsObject& physicsObject
|
|
||||||
, SHTransformComponent* transformComponent
|
|
||||||
, SHRigidBodyComponent* rigidBodyComponent
|
|
||||||
, SHColliderComponent* colliderComponent
|
|
||||||
, double interpolationFactor
|
|
||||||
) noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -271,26 +141,9 @@ namespace SHADE
|
||||||
double interpolationFactor;
|
double interpolationFactor;
|
||||||
double fixedDT;
|
double fixedDT;
|
||||||
|
|
||||||
// rp3d
|
|
||||||
|
|
||||||
rp3d::PhysicsCommon factory;
|
|
||||||
|
|
||||||
// Interface objects
|
|
||||||
|
|
||||||
SHPhysicsWorldState worldState;
|
|
||||||
SHPhysicsObjectManager objectManager;
|
|
||||||
SHCollisionListener collisionListener;
|
|
||||||
SHPhysicsRaycaster raycaster;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
|
|
||||||
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
|
|
||||||
|
|
||||||
SHEventHandle onPlay (SHEventPtr onPlayEvent);
|
|
||||||
SHEventHandle onStop (SHEventPtr onStopEvent);
|
|
||||||
SHEventHandle buildScene (SHEventPtr onSceneChangeEvent);
|
|
||||||
};
|
};
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -27,26 +27,26 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionInfo> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
//auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
//if (phySystem)
|
||||||
{
|
//{
|
||||||
return phySystem->GetAllCollisionInfo();
|
// return phySystem->GetAllCollisionInfo();
|
||||||
}
|
//}
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get collision events. Empty vector returned instead.");
|
//SHLOGV_WARNING("Failed to get collision events. Empty vector returned instead.");
|
||||||
return emptyVec;
|
return emptyVec;
|
||||||
}
|
}
|
||||||
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
|
||||||
{
|
{
|
||||||
static std::vector<SHCollisionInfo> emptyVec;
|
static std::vector<SHCollisionInfo> emptyVec;
|
||||||
|
|
||||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
//auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||||
if (phySystem)
|
//if (phySystem)
|
||||||
{
|
//{
|
||||||
return phySystem->GetAllTriggerInfo();
|
// return phySystem->GetAllTriggerInfo();
|
||||||
}
|
//}
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get trigger events. Empty vector returned instead.");
|
//SHLOGV_WARNING("Failed to get trigger events. Empty vector returned instead.");
|
||||||
return emptyVec;
|
return emptyVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,76 +61,4 @@ namespace SHADE
|
||||||
SHLOGV_WARNING("Failed to get fixed delta time. 0.0 returned instead.");
|
SHLOGV_WARNING("Failed to get fixed delta time. 0.0 returned instead.");
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::Raycast(const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->Raycast(ray, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::Linecast(const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->Linecast(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->ColliderRaycast(eid, ray, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->ColliderRaycast(eid, shapeIndex, ray, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->ColliderLinecast(eid, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
|
||||||
{
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
if (physicsSystem)
|
|
||||||
{
|
|
||||||
return physicsSystem->ColliderLinecast(eid, shapeIndex, start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
|
||||||
return SHPhysicsRaycastResult{};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Entity/SHEntity.h"
|
#include "ECS_Base/Entity/SHEntity.h"
|
||||||
|
#include "Physics/Collision/SHCollisionInfo.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -24,7 +25,6 @@ namespace SHADE
|
||||||
/* Forward Declarations */
|
/* Forward Declarations */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class SHCollisionInfo;
|
|
||||||
class SHVec3;
|
class SHVec3;
|
||||||
struct SHRay;
|
struct SHRay;
|
||||||
struct SHPhysicsRaycastResult;
|
struct SHPhysicsRaycastResult;
|
||||||
|
@ -52,12 +52,5 @@ namespace SHADE
|
||||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
|
||||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
||||||
[[nodiscard]] static double GetFixedDT () noexcept;
|
[[nodiscard]] static double GetFixedDT () noexcept;
|
||||||
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult Raycast (const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult Linecast (const SHVec3& start, const SHVec3& end) noexcept;
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderRaycast (EntityID eid, const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderRaycast (EntityID eid, int shapeIndex, const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderLinecast (EntityID eid, const SHVec3& start, const SHVec3& end) noexcept;
|
|
||||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderLinecast (EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,85 +55,12 @@ namespace SHADE
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
||||||
{
|
{
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
|
||||||
|
|
||||||
// Only Sync on Play.
|
|
||||||
// Otherwise, Components are only holding data until the world is built on play.
|
|
||||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
|
||||||
{
|
|
||||||
physicsSystem->objectManager.UpdateCommands();
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
|
||||||
{
|
|
||||||
// Ensure a valid physics Object
|
|
||||||
if (physicsObject.rp3dBody == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Sync active states between SHADE & RP3D
|
|
||||||
syncRigidBodyActive(entityID, physicsObject);
|
|
||||||
syncColliderActive(entityID, physicsObject);
|
|
||||||
|
|
||||||
syncOnPlay(entityID, physicsObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto& rigidBodyDense = SHComponentManager::GetDense<SHRigidBodyComponent>();
|
|
||||||
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
|
|
||||||
|
|
||||||
for (auto& rigidBodyComponent : rigidBodyDense)
|
|
||||||
{
|
|
||||||
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
|
|
||||||
|
|
||||||
if (TRANSFORM && TRANSFORM->HasChanged())
|
|
||||||
{
|
|
||||||
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
|
|
||||||
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& colliderComponent : colliderDense)
|
|
||||||
{
|
|
||||||
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(colliderComponent.GetEID());
|
|
||||||
|
|
||||||
if (TRANSFORM && TRANSFORM->HasChanged())
|
|
||||||
{
|
|
||||||
colliderComponent.position = TRANSFORM->GetWorldPosition();
|
|
||||||
colliderComponent.orientation = TRANSFORM->GetWorldOrientation();
|
|
||||||
colliderComponent.scale = TRANSFORM->GetWorldScale();
|
|
||||||
|
|
||||||
colliderComponent.RecomputeCollisionShapes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Always sync Rigid Body & Collider Components with Physics Objects
|
|
||||||
// Do not check for an editor here
|
|
||||||
|
|
||||||
physicsSystem->objectManager.UpdateCommands();
|
|
||||||
|
|
||||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
|
||||||
{
|
|
||||||
// Ensure a valid physics Object
|
|
||||||
if (physicsObject.rp3dBody == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
syncRigidBodyActive(entityID, physicsObject);
|
|
||||||
syncColliderActive(entityID, physicsObject);
|
|
||||||
|
|
||||||
syncOnPlay(entityID, physicsObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
||||||
{
|
{
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||||
if (scriptingSystem == nullptr)
|
if (scriptingSystem == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -141,20 +68,16 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
const double FIXED_DT = physicsSystem->fixedDT;
|
const double FIXED_DT = physicsSystem->fixedDT;
|
||||||
// HACK: Clamp DT here to prevent a ridiculous amount of updates. This limits updates from large dt to 2.
|
|
||||||
// HACK: This should be done by the FRC and not here for predictable behaviour.
|
|
||||||
|
|
||||||
accumulatedTime += dt;
|
accumulatedTime += dt;
|
||||||
|
|
||||||
//testFunction();
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (accumulatedTime > FIXED_DT)
|
while (accumulatedTime > FIXED_DT)
|
||||||
{
|
{
|
||||||
if (scriptingSystem != nullptr)
|
if (scriptingSystem != nullptr)
|
||||||
scriptingSystem->ExecuteFixedUpdates();
|
scriptingSystem->ExecuteFixedUpdates();
|
||||||
|
|
||||||
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(FIXED_DT));
|
// TODO: Update World
|
||||||
|
|
||||||
accumulatedTime -= FIXED_DT;
|
accumulatedTime -= FIXED_DT;
|
||||||
++count;
|
++count;
|
||||||
|
@ -177,236 +100,16 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate transforms for rendering
|
// Interpolate transforms for rendering
|
||||||
if (physicsSystem->worldUpdated)
|
|
||||||
{
|
|
||||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
|
||||||
{
|
|
||||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
|
||||||
|
|
||||||
postUpdateSyncTransforms
|
|
||||||
(
|
|
||||||
physicsObject
|
|
||||||
, transformComponent
|
|
||||||
, rigidBodyComponent
|
|
||||||
, colliderComponent
|
|
||||||
, physicsSystem->interpolationFactor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collision & Trigger messages
|
// Collision & Trigger messages
|
||||||
if (scriptingSystem != nullptr)
|
if (scriptingSystem != nullptr)
|
||||||
scriptingSystem->ExecuteCollisionFunctions();
|
scriptingSystem->ExecuteCollisionFunctions();
|
||||||
|
|
||||||
// Since this function never runs when editor in not in play, execute the function anyway
|
|
||||||
physicsSystem->collisionListener.CleanContainers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept
|
|
||||||
{
|
|
||||||
if (!SHComponentManager::HasComponent<SHRigidBodyComponent>(eid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(eid);
|
|
||||||
const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive();
|
|
||||||
|
|
||||||
if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE)
|
|
||||||
physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept
|
|
||||||
{
|
|
||||||
const auto* COLLIDER = SHComponentManager::GetComponent_s<SHColliderComponent>(eid);
|
|
||||||
if (!COLLIDER)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(eid);
|
|
||||||
const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive;
|
|
||||||
|
|
||||||
if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE)
|
|
||||||
{
|
|
||||||
// HACK: If active state turned off, remove all collision shapes. If turned on, add them back.
|
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
|
||||||
|
|
||||||
const int NUM_SHAPES = static_cast<int>(COLLIDER->GetCollisionShapes().size());
|
|
||||||
if (IS_ACTIVE_IN_SCENE)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NUM_SHAPES; ++i)
|
|
||||||
physicsSystem->objectManager.AddCollisionShape(eid, i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = NUM_SHAPES - 1; i >= 0; --i)
|
|
||||||
physicsSystem->objectManager.RemoveCollisionShape(eid, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
physicsObject.collidersActive = IS_ACTIVE_IN_SCENE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept
|
|
||||||
{
|
|
||||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid);
|
|
||||||
|
|
||||||
// Sync transforms & physics components transforms
|
|
||||||
if (transformComponent && transformComponent->HasChanged())
|
|
||||||
{
|
|
||||||
physicsObject.GetRigidBody()->setIsSleeping(false);
|
|
||||||
|
|
||||||
preUpdateSyncTransform
|
|
||||||
(
|
|
||||||
physicsObject
|
|
||||||
, transformComponent
|
|
||||||
, rigidBodyComponent
|
|
||||||
, colliderComponent
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync Rigid Bodies
|
|
||||||
if (rigidBodyComponent)
|
|
||||||
physicsObject.SyncRigidBody(*rigidBodyComponent);
|
|
||||||
|
|
||||||
// Sync Colliders
|
|
||||||
if (colliderComponent)
|
|
||||||
physicsObject.SyncColliders(*colliderComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
|
|
||||||
(
|
|
||||||
SHPhysicsObject& physicsObject
|
|
||||||
, SHTransformComponent* transformComponent
|
|
||||||
, SHRigidBodyComponent* rigidBodyComponent
|
|
||||||
, SHColliderComponent* colliderComponent
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
if (!transformComponent)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
|
|
||||||
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
|
|
||||||
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
|
|
||||||
|
|
||||||
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
|
|
||||||
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
|
||||||
physicsObject.prevTransform = RP3D_TRANSFORM;
|
|
||||||
|
|
||||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
|
|
||||||
{
|
|
||||||
rigidBodyComponent->position = WORLD_POS;
|
|
||||||
rigidBodyComponent->orientation = WORLD_ROT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
|
|
||||||
{
|
|
||||||
colliderComponent->position = WORLD_POS;
|
|
||||||
colliderComponent->orientation = WORLD_ROT;
|
|
||||||
colliderComponent->scale = WORLD_SCL;
|
|
||||||
|
|
||||||
colliderComponent->RecomputeCollisionShapes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms
|
|
||||||
(
|
|
||||||
SHPhysicsObject& physicsObject
|
|
||||||
, SHTransformComponent* transformComponent
|
|
||||||
, SHRigidBodyComponent* rigidBodyComponent
|
|
||||||
, SHColliderComponent* colliderComponent
|
|
||||||
, double interpolationFactor
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
|
|
||||||
auto renderPos = CURRENT_TF.getPosition();
|
|
||||||
auto renderRot = CURRENT_TF.getOrientation();
|
|
||||||
|
|
||||||
// Cache transforms
|
|
||||||
if (physicsObject.GetRigidBody()->isActive())
|
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
|
||||||
|
|
||||||
// Sync with rigid bodies
|
|
||||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
|
|
||||||
{
|
|
||||||
// Skip static bodies
|
|
||||||
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Check if transform should be interpolated
|
|
||||||
if (rigidBodyComponent->IsInterpolating())
|
|
||||||
{
|
|
||||||
// Interpolate transforms between current and predicted next transform
|
|
||||||
|
|
||||||
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
|
||||||
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
|
||||||
|
|
||||||
renderPos = INTERPOLATED_TF.getPosition();
|
|
||||||
renderRot = INTERPOLATED_TF.getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
|
||||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
|
||||||
|
|
||||||
// Sync with colliders
|
|
||||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
|
|
||||||
{
|
|
||||||
// Skip colliders without rigidbody components. If any transform was updated, it was done in pre-update.
|
|
||||||
|
|
||||||
colliderComponent->position = CURRENT_TF.getPosition();
|
|
||||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set transform for rendering
|
|
||||||
if (transformComponent)
|
|
||||||
{
|
|
||||||
transformComponent->SetWorldPosition(renderPos);
|
|
||||||
transformComponent->SetWorldOrientation(renderRot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void testFunction()
|
|
||||||
{
|
|
||||||
using namespace SHADE;
|
|
||||||
|
|
||||||
// Test movement
|
|
||||||
const float forceModifier = 25.0f;
|
|
||||||
EntityID eid = 65538;
|
|
||||||
|
|
||||||
if (SHEntityManager::IsValidEID(eid))
|
|
||||||
{
|
|
||||||
auto* rb = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
|
||||||
if (rb)
|
|
||||||
{
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
|
|
||||||
rb->AddForce(SHVec3::UnitZ * forceModifier);
|
|
||||||
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
|
|
||||||
rb->AddForce(-SHVec3::UnitX * forceModifier);
|
|
||||||
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
|
|
||||||
rb->AddForce(-SHVec3::UnitZ * forceModifier);
|
|
||||||
|
|
||||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
|
|
||||||
rb->AddForce(SHVec3::UnitX * forceModifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cast rays
|
|
||||||
auto* tag = SHCollisionTagMatrix::GetTag(1);
|
|
||||||
tag->SetLayerState(SHCollisionTag::Layer::_1, false);
|
|
||||||
tag->SetLayerState(SHCollisionTag::Layer::_2, true);
|
|
||||||
|
|
||||||
SHRay ray { SHVec3{3.0f, 3.5f, 0.0f}, -SHVec3::UnitX };
|
|
||||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
|
||||||
physicsSystem->Raycast(ray, std::numeric_limits<float>::infinity(), *tag);
|
|
||||||
}
|
|
||||||
|
|
|
@ -43,47 +43,47 @@ namespace SHADE
|
||||||
|
|
||||||
RaycastHit Physics::Raycast(Ray ray)
|
RaycastHit Physics::Raycast(Ray ray)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::Raycast(Ray ray, float distance)
|
RaycastHit Physics::Raycast(Ray ray, float distance)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray), distance));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::Linecast(Vector3 start, Vector3 end)
|
RaycastHit Physics::Linecast(Vector3 start, Vector3 end)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::Linecast(Convert::ToNative(start), Convert::ToNative(end)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray)
|
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray, float distance)
|
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray, float distance)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray), distance));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray)
|
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance)
|
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray), distance));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end)
|
RaycastHit Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, Convert::ToNative(start), Convert::ToNative(end)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
RaycastHit Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end)
|
RaycastHit Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end)
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, shapeIndex, Convert::ToNative(start), Convert::ToNative(end)));
|
return RaycastHit{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -103,38 +103,6 @@ namespace SHADE
|
||||||
/* Physics Conversions */
|
/* Physics Conversions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsRaycastResult Convert::ToNative(RaycastHit cli)
|
|
||||||
{
|
|
||||||
// This function shouldn't be used anyway, so we leave the entityHit empty.
|
|
||||||
|
|
||||||
SHPhysicsRaycastResult native;
|
|
||||||
|
|
||||||
native.hit = cli.Hit;
|
|
||||||
native.position = ToNative(cli.Position);
|
|
||||||
native.normal = ToNative(cli.Normal);
|
|
||||||
native.distance = cli.Distance;
|
|
||||||
native.shapeIndex = cli.CollisionShapeIndex;
|
|
||||||
|
|
||||||
return native;
|
|
||||||
}
|
|
||||||
|
|
||||||
RaycastHit Convert::ToCLI(const SHPhysicsRaycastResult& native)
|
|
||||||
{
|
|
||||||
RaycastHit cli;
|
|
||||||
|
|
||||||
cli.Hit = native.hit;
|
|
||||||
cli.Position = ToCLI(native.position);
|
|
||||||
cli.Normal = ToCLI(native.normal);
|
|
||||||
cli.Distance = native.distance;
|
|
||||||
cli.CollisionShapeIndex = native.shapeIndex;
|
|
||||||
|
|
||||||
cli.Other = SHEntityManager::IsValidEID(native.entityHit)
|
|
||||||
? GameObject(native.entityHit)
|
|
||||||
: System::Nullable<GameObject>();
|
|
||||||
|
|
||||||
return cli;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Handle Conversions */
|
/* Handle Conversions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -141,20 +141,6 @@ namespace SHADE
|
||||||
/* Physics Conversions */
|
/* Physics Conversions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts from a managed RaycastHit to a native SHPhysicsRaycastResult
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="raycastHit">The managed RaycastHit to convert from.</param>
|
|
||||||
/// <returns>Native copy of a managed RaycastHit.</returns>
|
|
||||||
static SHPhysicsRaycastResult ToNative(RaycastHit cli);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts from native SHPhysicsRaycastResult to a managed RaycastHit.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="raycastResult">The native SHPhysicsRaycastResult to convert from.</param>
|
|
||||||
/// <returns>Managed copy of a native SHPhysicsRaycastResult.</returns>
|
|
||||||
static RaycastHit ToCLI(const SHPhysicsRaycastResult& native);
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Handle Conversions */
|
/* Handle Conversions */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in New Issue