Added in Raycasting through Physics #226
|
@ -176,6 +176,12 @@ namespace Sandbox
|
||||||
drawColliders = !drawColliders;
|
drawColliders = !drawColliders;
|
||||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, 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();
|
||||||
|
|
|
@ -30,11 +30,17 @@ namespace SHADE
|
||||||
, direction { dir }
|
, direction { dir }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
SHRay::SHRay(const reactphysics3d::Ray rp3dRay) noexcept
|
||||||
|
: position { rp3dRay.point1 }
|
||||||
|
, direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) }
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Operator Overload Definitions */
|
/* Operator Overload Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
bool SHRay::operator==(const SHRay& rhs) noexcept
|
bool SHRay::operator==(const SHRay& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR LHS_POS = XMLoadFloat3(&position);
|
const XMVECTOR LHS_POS = XMLoadFloat3(&position);
|
||||||
const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position);
|
const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position);
|
||||||
|
@ -45,7 +51,7 @@ namespace SHADE
|
||||||
return XMVector3Equal(LHS_POS, RHS_POS) && XMVector3NotEqual(LHS_DIR, RHS_DIR);
|
return XMVector3Equal(LHS_POS, RHS_POS) && XMVector3NotEqual(LHS_DIR, RHS_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHRay::operator!=(const SHRay& rhs) noexcept
|
bool SHRay::operator!=(const SHRay& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR LHS_POS = XMLoadFloat3(&position);
|
const XMVECTOR LHS_POS = XMLoadFloat3(&position);
|
||||||
const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position);
|
const XMVECTOR RHS_POS = XMLoadFloat3(&rhs.position);
|
||||||
|
@ -56,5 +62,16 @@ namespace SHADE
|
||||||
return XMVector3NotEqual(LHS_POS, RHS_POS) || XMVector3NotEqual(LHS_DIR, RHS_DIR);
|
return XMVector3NotEqual(LHS_POS, RHS_POS) || XMVector3NotEqual(LHS_DIR, RHS_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHRay::operator reactphysics3d::Ray() const noexcept
|
||||||
|
{
|
||||||
|
// We use 2km. Temp solution.
|
||||||
|
return reactphysics3d::Ray{ position, position + (direction * MAX_RAYCAST_DIST) };
|
||||||
|
}
|
||||||
|
|
||||||
|
SHRaycastResult::operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* \file SHRay.h
|
* \file SHRay.h
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
* \brief Interface for a Ray.
|
* \brief Interface for a Ray & Raycast Result
|
||||||
*
|
*
|
||||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
* disclosure of this file or its contents without the prior written consent
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <DirectXMath.h>
|
#include <reactphysics3d/mathematics/Ray.h>
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
@ -29,6 +29,8 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static constexpr float MAX_RAYCAST_DIST = 2000.0f; // We use 2km as physics typically tends to lose accuracy beyond 2km.
|
||||||
|
|
||||||
SHVec3 position;
|
SHVec3 position;
|
||||||
SHVec3 direction;
|
SHVec3 direction;
|
||||||
|
|
||||||
|
@ -36,19 +38,46 @@ namespace SHADE
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHRay() noexcept;
|
SHRay () noexcept;
|
||||||
SHRay(const SHVec3& pos, const SHVec3& dir) noexcept;
|
SHRay (const SHVec3& pos, const SHVec3& dir) noexcept;
|
||||||
SHRay(const SHRay& rhs) noexcept = default;
|
SHRay (const reactphysics3d::Ray rp3dRay) noexcept;
|
||||||
SHRay(SHRay&& rhs) noexcept = default;
|
|
||||||
|
SHRay (const SHRay&) noexcept = default;
|
||||||
|
SHRay (SHRay&& ) noexcept = default;
|
||||||
|
~SHRay() = default;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Operator Overloads */
|
/* Operator Overloads */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHRay& operator= (const SHRay& rhs) noexcept = default;
|
SHRay& operator= (const SHRay&) noexcept = default;
|
||||||
SHRay& operator= (SHRay&& rhs) noexcept = default;
|
SHRay& operator= (SHRay&&) noexcept = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool operator==(const SHRay& rhs) const noexcept;
|
||||||
|
[[nodiscard]] bool operator!=(const SHRay& rhs) const noexcept;
|
||||||
|
|
||||||
|
operator reactphysics3d::Ray() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SH_API SHRaycastResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool hit = false;
|
||||||
|
float distance = std::numeric_limits<float>::infinity();
|
||||||
|
float angle = 0.0f;
|
||||||
|
|
||||||
|
SHVec3 position;
|
||||||
|
SHVec3 normal;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
operator bool() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const SHRay& rhs) noexcept;
|
|
||||||
[[nodiscard]] bool operator!=(const SHRay& rhs) noexcept;
|
|
||||||
};
|
};
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -32,7 +32,6 @@ namespace SHADE
|
||||||
class SH_API SHCollisionListener final : public rp3d::EventListener
|
class SH_API SHCollisionListener final : public rp3d::EventListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -0,0 +1,350 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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) 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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
||||||
|
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
||||||
|
world->raycast(RP3D_RAY, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) 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);
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,142 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \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 "Physics/PhysicsObject/SHPhysicsObjectManager.h"
|
||||||
|
#include "Physics/SHPhysicsWorld.h"
|
||||||
|
#include "Math/SHRay.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
struct SH_API SHPhysicsRaycastResult : public SHRaycastResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
EntityID entityHit = MAX_EID;
|
||||||
|
int shapeIndex = -1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
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()
|
||||||
|
) noexcept;
|
||||||
|
|
||||||
|
SHPhysicsRaycastResult Linecast
|
||||||
|
(
|
||||||
|
const SHVec3& start
|
||||||
|
, const SHVec3& end
|
||||||
|
) 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
|
|
@ -294,7 +294,7 @@ namespace SHADE
|
||||||
if (!rp3dBody->isActive())
|
if (!rp3dBody->isActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int NUM_SHAPES = static_cast<int>(component.collisionShapes.size());
|
const int NUM_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
||||||
for (int i = 0; i < NUM_SHAPES; ++i)
|
for (int i = 0; i < NUM_SHAPES; ++i)
|
||||||
{
|
{
|
||||||
auto& collisionShape = component.collisionShapes[i];
|
auto& collisionShape = component.collisionShapes[i];
|
||||||
|
|
|
@ -23,11 +23,10 @@ namespace SHADE
|
||||||
/* Static Data Member Definitions */
|
/* Static Data Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[2][3]
|
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[3][2]
|
||||||
{
|
{
|
||||||
addRigidBody , addCollider
|
addRigidBody , addCollider , addCollisionShape
|
||||||
, removeRigidBody , removeCollider
|
, removeRigidBody , removeCollider , removeCollisionShape
|
||||||
, addCollisionShape , removeCollisionShape
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static CommandFunctionPtr componentFunc[2][3]; // 2 commands, 3 components
|
static CommandFunctionPtr componentFunc[3][2]; // 3 components, 2 commands
|
||||||
|
|
||||||
rp3d::PhysicsCommon* factory = nullptr;
|
rp3d::PhysicsCommon* factory = nullptr;
|
||||||
rp3d::PhysicsWorld* world = nullptr;
|
rp3d::PhysicsWorld* world = nullptr;
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -26,11 +25,12 @@ namespace SHADE
|
||||||
|
|
||||||
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
|
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
|
||||||
{
|
{
|
||||||
SHPhysicsDebugDrawSystem::drawColliders
|
drawColliders
|
||||||
, SHPhysicsDebugDrawSystem::drawColliderAABBs
|
, drawColliderAABBs
|
||||||
, SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs
|
, drawBroadPhaseAABBs
|
||||||
, SHPhysicsDebugDrawSystem::drawContactPoints
|
, drawContactPoints
|
||||||
, SHPhysicsDebugDrawSystem::drawContactNormals
|
, drawContactNormals
|
||||||
|
, drawRaycasts
|
||||||
};
|
};
|
||||||
|
|
||||||
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
|
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
|
||||||
|
@ -42,13 +42,13 @@ namespace SHADE
|
||||||
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
||||||
: debugDrawFlags { 0 }
|
: debugDrawFlags { 0 }
|
||||||
, physicsSystem { nullptr }
|
, physicsSystem { nullptr }
|
||||||
, rp3dDebugRenderer { nullptr }
|
|
||||||
{
|
{
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN;
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN;
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
||||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
||||||
|
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::RAYCASTS)] = SHColour::ORANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
||||||
|
@ -111,19 +111,30 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto* system = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
||||||
{
|
{
|
||||||
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
||||||
if (DRAW)
|
if (DRAW)
|
||||||
drawFunctions[i](system->rp3dDebugRenderer);
|
drawFunctions[i](debugDrawSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Automatically clear the container of raycasts despite debug drawing state
|
||||||
|
// TODO(Diren): Move this somewhere else
|
||||||
|
system->physicsSystem->raycaster.ClearFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawColliders(rp3d::DebugRenderer* debugRenderer) noexcept
|
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer) noexcept
|
||||||
{
|
{
|
||||||
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
||||||
for (const auto& COLLIDER : COLLIDER_SET)
|
for (const auto& COLLIDER : COLLIDER_SET)
|
||||||
|
@ -136,34 +147,58 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
switch (collisionShape.GetType())
|
switch (collisionShape.GetType())
|
||||||
{
|
{
|
||||||
case SHCollisionShape::Type::BOX: debugDrawBox(COLLIDER, collisionShape); break;
|
case SHCollisionShape::Type::BOX: debugDrawBox(debugRenderer, COLLIDER, collisionShape); break;
|
||||||
case SHCollisionShape::Type::SPHERE: debugDrawSphere(COLLIDER, collisionShape); break;
|
case SHCollisionShape::Type::SPHERE: debugDrawSphere(debugRenderer, COLLIDER, collisionShape); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawColliderAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(rp3d::DebugRenderer* debugRenderer) noexcept
|
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawContactPoints(rp3d::DebugRenderer* debugRenderer) noexcept
|
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::drawContactNormals(rp3d::DebugRenderer* debugRenderer) noexcept
|
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer) 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
|
void SHPhysicsDebugDrawSystem::generateBox() noexcept
|
||||||
{
|
{
|
||||||
boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK
|
boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK
|
||||||
|
@ -176,15 +211,8 @@ namespace SHADE
|
||||||
boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT
|
boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::debugDrawBox(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
void SHPhysicsDebugDrawSystem::debugDrawBox(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
{
|
{
|
||||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
|
||||||
if (debugDrawSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* BOX = reinterpret_cast<const SHBox*>(collisionShape.GetShape());
|
auto* BOX = reinterpret_cast<const SHBox*>(collisionShape.GetShape());
|
||||||
|
|
||||||
// Calculate final position & orientation
|
// Calculate final position & orientation
|
||||||
|
@ -211,27 +239,20 @@ namespace SHADE
|
||||||
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
|
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
|
||||||
|
|
||||||
// Draw 4 line to connect the quads
|
// Draw 4 line to connect the quads
|
||||||
debugDrawSystem->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
|
debugRenderer->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A, B, C, D
|
// A, B, C, D
|
||||||
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
||||||
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
|
debugRenderer->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
|
||||||
|
|
||||||
// E, F, G, H
|
// E, F, G, H
|
||||||
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
||||||
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
|
debugRenderer->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsDebugDrawSystem::debugDrawSphere(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
void SHPhysicsDebugDrawSystem::debugDrawSphere(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||||
{
|
{
|
||||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
|
||||||
if (debugDrawSystem == nullptr)
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* SPHERE = reinterpret_cast<const SHSphere*>(collisionShape.GetShape());
|
auto* SPHERE = reinterpret_cast<const SHSphere*>(collisionShape.GetShape());
|
||||||
|
|
||||||
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||||
|
@ -240,7 +261,7 @@ namespace SHADE
|
||||||
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
||||||
const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition());
|
const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition());
|
||||||
|
|
||||||
debugDrawSystem->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius());
|
debugRenderer->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
|
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||||
#include "Math/SHColour.h"
|
#include "Math/SHColour.h"
|
||||||
#include "SHPhysicsSystem.h"
|
#include "SHPhysicsSystem.h"
|
||||||
#include "Tools/Utilities/SHUtilities.h"
|
#include "Tools/Utilities/SHUtilities.h"
|
||||||
|
@ -38,6 +39,7 @@ namespace SHADE
|
||||||
, BROAD_PHASE_AABB
|
, BROAD_PHASE_AABB
|
||||||
, CONTACT_POINTS
|
, CONTACT_POINTS
|
||||||
, CONTACT_NORMALS
|
, CONTACT_NORMALS
|
||||||
|
, RAYCASTS
|
||||||
|
|
||||||
, NUM_FLAGS
|
, NUM_FLAGS
|
||||||
};
|
};
|
||||||
|
@ -91,7 +93,7 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
using DebugDrawFunction = void(*)(rp3d::DebugRenderer*) noexcept;
|
using DebugDrawFunction = void(*)(SHDebugDrawSystem*) noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
@ -108,7 +110,6 @@ namespace SHADE
|
||||||
|
|
||||||
uint8_t debugDrawFlags;
|
uint8_t debugDrawFlags;
|
||||||
SHPhysicsSystem* physicsSystem;
|
SHPhysicsSystem* physicsSystem;
|
||||||
rp3d::DebugRenderer* rp3dDebugRenderer;
|
|
||||||
SHColour debugColours[NUM_FLAGS];
|
SHColour debugColours[NUM_FLAGS];
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -117,11 +118,12 @@ namespace SHADE
|
||||||
|
|
||||||
// Generic Draw Functions
|
// Generic Draw Functions
|
||||||
|
|
||||||
static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept;
|
static void drawColliders (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
|
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept;
|
static void drawContactPoints (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept;
|
static void drawContactNormals (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
|
static void drawRaycasts (SHDebugDrawSystem* debugRenderer) noexcept;
|
||||||
|
|
||||||
// Shape Generation Functions
|
// Shape Generation Functions
|
||||||
|
|
||||||
|
@ -129,8 +131,8 @@ namespace SHADE
|
||||||
|
|
||||||
// Shape Draw Functions
|
// Shape Draw Functions
|
||||||
|
|
||||||
static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
static void debugDrawBox (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
static void debugDrawSphere (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -22,10 +22,6 @@
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
|
||||||
/* Local Helper Functions */
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -115,8 +111,9 @@ namespace SHADE
|
||||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
|
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// Link Physics Object Manager with System
|
// Link Physics Object Manager with System & Raycaster
|
||||||
objectManager.SetFactory(factory);
|
objectManager.SetFactory(factory);
|
||||||
|
raycaster.SetObjectManager(&objectManager);
|
||||||
|
|
||||||
// Link Collision Listener with System
|
// Link Collision Listener with System
|
||||||
collisionListener.BindToSystem(this);
|
collisionListener.BindToSystem(this);
|
||||||
|
@ -183,6 +180,35 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHPhysicsRaycastResult SHPhysicsSystem::Raycast(const SHRay& ray, float distance) noexcept
|
||||||
|
{
|
||||||
|
return raycaster.Raycast(ray, distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end)
|
||||||
|
{
|
||||||
|
return raycaster.Linecast(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return raycaster.ColliderLinecast(eid, shapeIndex, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
||||||
{
|
{
|
||||||
|
@ -327,8 +353,9 @@ namespace SHADE
|
||||||
// Create physics world
|
// Create physics world
|
||||||
worldState.CreateWorld(factory);
|
worldState.CreateWorld(factory);
|
||||||
|
|
||||||
// Link Collision Listener
|
// Link Collision Listener & Raycaster
|
||||||
collisionListener.BindToWorld(worldState.world);
|
collisionListener.BindToWorld(worldState.world);
|
||||||
|
raycaster.BindToWorld(worldState.world);
|
||||||
|
|
||||||
// Link with object manager & create all physics objects
|
// Link with object manager & create all physics objects
|
||||||
objectManager.SetWorld(worldState.world);
|
objectManager.SetWorld(worldState.world);
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
#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/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/PhysicsObject/SHPhysicsObjectManager.h"
|
||||||
#include "Physics/SHPhysicsWorld.h"
|
#include "Physics/SHPhysicsWorld.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,6 +79,90 @@ namespace SHADE
|
||||||
|
|
||||||
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.
|
||||||
|
* @return The result of the raycast.
|
||||||
|
*/
|
||||||
|
SHPhysicsRaycastResult Raycast
|
||||||
|
(
|
||||||
|
const SHRay& ray
|
||||||
|
, float distance = std::numeric_limits<float>::infinity()
|
||||||
|
) 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.
|
||||||
|
* @return The result of the raycast.
|
||||||
|
*/
|
||||||
|
SHPhysicsRaycastResult Linecast
|
||||||
|
(
|
||||||
|
const SHVec3& start
|
||||||
|
, const SHVec3& end
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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()
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
);
|
||||||
|
|
||||||
// Specific Handling for Collision Shapes as they are not under the Component System.
|
// Specific Handling for Collision Shapes as they are not under the Component System.
|
||||||
// This is done as events need to be sent out.
|
// This is done as events need to be sent out.
|
||||||
// TODO(Diren): Consider using a static method through the ColliderComponent.
|
// TODO(Diren): Consider using a static method through the ColliderComponent.
|
||||||
|
@ -190,6 +274,7 @@ namespace SHADE
|
||||||
SHPhysicsWorldState worldState;
|
SHPhysicsWorldState worldState;
|
||||||
SHPhysicsObjectManager objectManager;
|
SHPhysicsObjectManager objectManager;
|
||||||
SHCollisionListener collisionListener;
|
SHCollisionListener collisionListener;
|
||||||
|
SHPhysicsRaycaster raycaster;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
|
|
Loading…
Reference in New Issue