Added in Raycasting through Physics #226

Merged
direnbharwani merged 5 commits from SP3-2-Physics into main 2022-11-19 16:24:50 +08:00
24 changed files with 1341 additions and 155 deletions

View File

@ -180,6 +180,12 @@ namespace Sandbox
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
graphicsSystem->AwaitGraphicsExecution();

View File

@ -30,11 +30,17 @@ namespace SHADE
, direction { dir }
{}
SHRay::SHRay(const reactphysics3d::Ray rp3dRay) noexcept
: position { rp3dRay.point1 }
, direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) }
{}
/*-----------------------------------------------------------------------------------*/
/* 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 RHS_POS = XMLoadFloat3(&rhs.position);
@ -45,7 +51,7 @@ namespace SHADE
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 RHS_POS = XMLoadFloat3(&rhs.position);
@ -56,5 +62,16 @@ namespace SHADE
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

View File

@ -1,7 +1,7 @@
/****************************************************************************************
* \file SHRay.h
* \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
* disclosure of this file or its contents without the prior written consent
@ -10,7 +10,7 @@
#pragma once
#include <DirectXMath.h>
#include <reactphysics3d/mathematics/Ray.h>
// Project Headers
#include "SH_API.h"
@ -29,6 +29,8 @@ namespace SHADE
/* 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 direction;
@ -36,19 +38,46 @@ namespace SHADE
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHRay() noexcept;
SHRay(const SHVec3& pos, const SHVec3& dir) noexcept;
SHRay(const SHRay& rhs) noexcept = default;
SHRay(SHRay&& rhs) noexcept = default;
SHRay () noexcept;
SHRay (const SHVec3& pos, const SHVec3& dir) noexcept;
SHRay (const reactphysics3d::Ray rp3dRay) noexcept;
SHRay (const SHRay&) noexcept = default;
SHRay (SHRay&& ) noexcept = default;
~SHRay() = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHRay& operator= (const SHRay& rhs) noexcept = default;
SHRay& operator= (SHRay&& rhs) noexcept = default;
SHRay& operator= (const SHRay&) 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

View File

@ -32,7 +32,6 @@ namespace SHADE
class SH_API SHCollisionListener final : public rp3d::EventListener
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/

View File

@ -0,0 +1,34 @@
/****************************************************************************************
* \file SHPhysicsRaycastResult.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a Physics Raycast Result
*
* \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
// Project Includes
#include "ECS_Base/SHECSMacros.h"
#include "Math/SHRay.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
struct SH_API SHPhysicsRaycastResult : public SHRaycastResult
{
public:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
EntityID entityHit = MAX_EID;
int shapeIndex = -1;
};
}

View File

@ -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

View File

@ -0,0 +1,131 @@
/****************************************************************************************
* \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 "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()
) 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

View File

@ -294,7 +294,7 @@ namespace SHADE
if (!rp3dBody->isActive())
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)
{
auto& collisionShape = component.collisionShapes[i];

View File

@ -23,11 +23,10 @@ namespace SHADE
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[2][3]
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[3][2]
{
addRigidBody , addCollider
, removeRigidBody , removeCollider
, addCollisionShape , removeCollisionShape
addRigidBody , addCollider , addCollisionShape
, removeRigidBody , removeCollider , removeCollisionShape
};
/*-----------------------------------------------------------------------------------*/

View File

@ -150,7 +150,7 @@ namespace SHADE
/* 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::PhysicsWorld* world = nullptr;

View File

@ -15,7 +15,6 @@
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Scene/SHSceneManager.h"
namespace SHADE
@ -26,11 +25,12 @@ namespace SHADE
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
{
SHPhysicsDebugDrawSystem::drawColliders
, SHPhysicsDebugDrawSystem::drawColliderAABBs
, SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs
, SHPhysicsDebugDrawSystem::drawContactPoints
, SHPhysicsDebugDrawSystem::drawContactNormals
drawColliders
, drawColliderAABBs
, drawBroadPhaseAABBs
, drawContactPoints
, drawContactNormals
, drawRaycasts
};
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
@ -42,13 +42,13 @@ namespace SHADE
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
: debugDrawFlags { 0 }
, physicsSystem { nullptr }
, rp3dDebugRenderer { 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()
@ -111,19 +111,30 @@ namespace SHADE
{
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)
{
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
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 */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsDebugDrawSystem::drawColliders(rp3d::DebugRenderer* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer) noexcept
{
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
for (const auto& COLLIDER : COLLIDER_SET)
@ -136,34 +147,58 @@ namespace SHADE
{
switch (collisionShape.GetType())
{
case SHCollisionShape::Type::BOX: debugDrawBox(COLLIDER, collisionShape); break;
case SHCollisionShape::Type::SPHERE: debugDrawSphere(COLLIDER, collisionShape); break;
case SHCollisionShape::Type::BOX: debugDrawBox(debugRenderer, COLLIDER, collisionShape); break;
case SHCollisionShape::Type::SPHERE: debugDrawSphere(debugRenderer, COLLIDER, collisionShape); 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
{
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
}
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());
// Calculate final position & orientation
@ -211,27 +239,20 @@ namespace SHADE
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
// 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
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
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());
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 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

View File

@ -14,6 +14,7 @@
// 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"
@ -38,6 +39,7 @@ namespace SHADE
, BROAD_PHASE_AABB
, CONTACT_POINTS
, CONTACT_NORMALS
, RAYCASTS
, NUM_FLAGS
};
@ -91,7 +93,7 @@ namespace SHADE
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using DebugDrawFunction = void(*)(rp3d::DebugRenderer*) noexcept;
using DebugDrawFunction = void(*)(SHDebugDrawSystem*) noexcept;
/*---------------------------------------------------------------------------------*/
/* Data Members */
@ -108,7 +110,6 @@ namespace SHADE
uint8_t debugDrawFlags;
SHPhysicsSystem* physicsSystem;
rp3d::DebugRenderer* rp3dDebugRenderer;
SHColour debugColours[NUM_FLAGS];
/*---------------------------------------------------------------------------------*/
@ -117,11 +118,12 @@ namespace SHADE
// Generic Draw Functions
static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawColliders (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawContactPoints (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawContactNormals (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawRaycasts (SHDebugDrawSystem* debugRenderer) noexcept;
// Shape Generation Functions
@ -129,8 +131,8 @@ namespace SHADE
// Shape Draw Functions
static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
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

View File

@ -22,10 +22,6 @@
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h"
/*-------------------------------------------------------------------------------------*/
/* Local Helper Functions */
/*-------------------------------------------------------------------------------------*/
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
@ -115,8 +111,9 @@ namespace SHADE
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
#endif
// Link Physics Object Manager with System
// Link Physics Object Manager with System & Raycaster
objectManager.SetFactory(factory);
raycaster.SetObjectManager(&objectManager);
// Link Collision Listener with System
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) noexcept
{
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) 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)
{
@ -325,10 +351,14 @@ namespace SHADE
////////////////////////////////
// Create physics world
if (worldState.world != nullptr)
return onPlayEvent->handle;
worldState.CreateWorld(factory);
// Link Collision Listener
// Link Collision Listener & Raycaster
collisionListener.BindToWorld(worldState.world);
raycaster.BindToWorld(worldState.world);
// Link with object manager & create all physics objects
objectManager.SetWorld(worldState.world);

View File

@ -21,11 +21,11 @@
#include "ECS_Base/System/SHFixedSystemRoutine.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Physics/Collision/SHCollisionListener.h"
#include "Physics/Collision/SHPhysicsRaycaster.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/PhysicsObject//SHPhysicsObjectManager.h"
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/SHPhysicsWorld.h"
@ -79,6 +79,90 @@ namespace SHADE
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
) 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.
@ -190,6 +274,7 @@ namespace SHADE
SHPhysicsWorldState worldState;
SHPhysicsObjectManager objectManager;
SHCollisionListener collisionListener;
SHPhysicsRaycaster raycaster;
/*---------------------------------------------------------------------------------*/
/* Function Members */

View File

@ -33,7 +33,7 @@ namespace SHADE
return phySystem->GetAllCollisionInfo();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get collision events. Empty vector returned instead.");
SHLOGV_WARNING("Failed to get collision events. Empty vector returned instead.");
return emptyVec;
}
const std::vector<SHCollisionInfo>& SHPhysicsSystemInterface::GetTriggerInfo() noexcept
@ -46,7 +46,7 @@ namespace SHADE
return phySystem->GetAllTriggerInfo();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get trigger events. Empty vector returned instead.");
SHLOGV_WARNING("Failed to get trigger events. Empty vector returned instead.");
return emptyVec;
}
@ -58,7 +58,79 @@ namespace SHADE
return phySystem->GetFixedUpdateRate();
}
SHLOG_WARNING("[SHPhysicsSystemInterface] 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;
}
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{};
}
}

View File

@ -14,12 +14,21 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <vector>
// Project Headers
#include "ECS_Base/Entity/SHEntity.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHCollisionInfo;
class SHCollisionInfo;
class SHVec3;
struct SHRay;
struct SHPhysicsRaycastResult;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
@ -39,8 +48,16 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Static Usage Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo() noexcept;
[[nodiscard]] static double GetFixedDT() noexcept;
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () 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;
};
}

View File

@ -1,28 +1,37 @@
/************************************************************************************//*!
\file Ray.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 20, 2022
\brief Contains the definitions of functions of the Vector2 struct.
Note: This file is written in C++17/CLI.
/****************************************************************************************
* \file Ray.cxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the managed Ray struct.
*
* \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.
****************************************************************************************/
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.
*//*************************************************************************************/
// Precompiled Headers
#include "SHpch.h"
// Primary Header
#include "Math/Ray.hxx"
#include "Ray.hxx"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
Ray::Ray(Vector3 origin, Vector3 direction)
: Origin { origin }
, Direction{ direction }
{}
}
/*-----------------------------------------------------------------------------------*/
/* Constructor Definitions */
/*-----------------------------------------------------------------------------------*/
Ray::Ray(Vector3 position, Vector3 direction)
{
Position = position;
Direction = direction;
}
/*-----------------------------------------------------------------------------------*/
/* Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void Ray::LookAt(Vector3 target)
{
Direction = (target - Position).GetNormalised();
}
} // namespace SHADE

View File

@ -1,50 +1,61 @@
/************************************************************************************//*!
\file Ray.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 20, 2021
\brief Contains the definitions of Vector2 struct.
Note: This file is written in C++17/CLI.
/****************************************************************************************
* \file Ray.hxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for the managed Ray struct.
*
* \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.
****************************************************************************************/
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
// Project Includes
#include "Vector3.hxx"
#include "Math/Vector3.hxx"
namespace SHADE
{
///<summary>
/// CLR version of the the SHADE Engine's Ray class that represents a ray in
/// 3-Dimensional space.
/// </summary>
public value struct Ray
{
public:
/*-----------------------------------------------------------------------------*/
/* Public Members */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// The start point of the ray.
/// </summary>
Vector3 Origin;
/// <summary>
/// The direction that a ray travels in.
/// </summary>
Vector3 Direction;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Creates a ray starting at origin along direction.
/// </summary>
/// <param name="origin">Source of the ray.</param>
/// <param name="direction">Direction the ray travels in.</param>
Ray(Vector3 origin, Vector3 direction);
};
}
public value struct Ray
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Constructor for a ray.
/// </summary>
/// <param name="position">The starting position of the ray.</param>
/// <param name="direction">The direction of the ray.</param>
Ray(Vector3 position, Vector3 direction);
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// The starting point of the Ray.
/// </summary>
property Vector3 Position;
/// <summary>
/// The direction of the ray. This should be a normalised vector.
/// </summary>
property Vector3 Direction;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Rotates the ray's direction towards a target.
/// </summary>
/// <param name="target">The target to direct the ray towards.</param>
void LookAt(Vector3 target);
};
} // namespace SHADE

View File

@ -0,0 +1,105 @@
/****************************************************************************************
* \file Physics.cxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the managed Physics class.
*
* \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 "Physics.hxx"
// External Dependencies
#include "Physics/System/SHPhysicsSystemInterface.h"
// Project Header
#include "Engine/GameObject.hxx"
#include "Utility/Convert.hxx"
#include "Utility/Debug.hxx"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Property Function Definitions */
/*-----------------------------------------------------------------------------------*/
Vector3 Physics::Gravity::get()
{
// TODO(Diren)
return Vector3::Zero;
}
void Physics::Gravity::set(Vector3 value)
{
(void)value;
}
/*-----------------------------------------------------------------------------------*/
/* Raycast Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
RaycastHit Physics::Raycast(Ray ray)
{
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray)));
}
RaycastHit Physics::Raycast(Ray ray, float distance)
{
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray), distance));
}
RaycastHit Physics::Linecast(Vector3 start, Vector3 end)
{
return Convert::ToCLI(SHPhysicsSystemInterface::Linecast(Convert::ToNative(start), Convert::ToNative(end)));
}
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray)
{
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray)));
}
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray, float distance)
{
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray), distance));
}
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray)
{
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray)));
}
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance)
{
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray), distance));
}
RaycastHit Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end)
{
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, Convert::ToNative(start), Convert::ToNative(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)));
}
/*-----------------------------------------------------------------------------------*/
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
RaycastHit Physics::generateDefaultResult()
{
RaycastHit default;
default.Hit = false;
default.Other = System::Nullable<GameObject>();
default.Position = Vector3::Zero;
default.Normal = Vector3::Zero;
default.Distance = System::Single::PositiveInfinity;
default.CollisionShapeIndex = -1;
return default;
}
} // namespace SHADE

View File

@ -0,0 +1,128 @@
/****************************************************************************************
* \file Physics.hxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for the managed Physics class.
*
* \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
// Project Includes
#include "Math/Ray.hxx"
#include "RaycastHit.hxx"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
public ref class Physics abstract sealed
{
public:
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
static property Vector3 Gravity
{
Vector3 get();
void set(Vector3 value);
}
// TODO(Diren): Add more properties for physics system settings.
/*---------------------------------------------------------------------------------*/
/* Raycast Function Members */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Casts an infinite ray into the world.
/// </summary>
/// <param name="ray">The ray to cast.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit Raycast (Ray ray);
/// <summary>
/// Casts a ray for a given distance into the world.
/// </summary>
/// <param name="ray">The ray to cast.</param>
/// <param name="distance">The distance to cast the ray.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit Raycast (Ray ray, float distance);
/// <summary>
/// Casts a bounded ray into the world.
/// </summary>
/// <param name="start">The start of the bounded ray.</param>
/// <param name="end">The end of the bounded ray.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit Linecast (Vector3 start, Vector3 end);
/// <summary>
/// Casts an infinite ray w.r.t a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="ray">The ray to cast.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderRaycast (GameObject object, Ray ray);
/// <summary>
/// Casts a ray for a given distance w.r.t a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="ray">The ray to cast.</param>
/// <param name="distance">The distance to cast the ray.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderRaycast (GameObject object, Ray ray, float distance);
/// <summary>
/// Casts an infinite ray w.r.t a specific collider on a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
/// <param name="ray">The ray to cast.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray);
/// <summary>
/// Casts a ray for a given distance w.r.t a specific collider on a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
/// <param name="ray">The ray to cast.</param>
/// <param name="distance">The distance to cast the ray.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance);
/// <summary>
/// Casts a bounded ray w.r.t a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="start">The start of the bounded ray.</param>
/// <param name="end"></param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderLineCast (GameObject object, Vector3 start, Vector3 end);
/// <summary>
/// Casts a bounded ray w.r.t a specific collider on a GameObject.
/// </summary>
/// <param name="object">The GameObject to cast the ray to.</param>
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
/// <param name="start">The start of the bounded ray.</param>
/// <param name="end">The end of the bounded ray.</param>
/// <returns>The result of the raycast.</returns>
static RaycastHit ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end);
private:
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
static RaycastHit generateDefaultResult ();
};
} // namespace SHADE

View File

@ -0,0 +1,19 @@
/****************************************************************************************
* \file RaycastHit.cxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for the managed RaycastHit struct.
*
* \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 "RaycastHit.hxx"
namespace SHADE
{
} // namespace SHADE

View File

@ -0,0 +1,64 @@
/****************************************************************************************
* \file RaycastHit.hxx
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for the managed RaycastHit struct.
*
* \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
// Project Includes
#include "Engine/GameObject.hxx"
#include "Math/Vector3.hxx"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/// <summary>
/// Defines a struct that contains the information of a raycast.
/// </summary>
public value struct RaycastHit
{
public:
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Whether or not the raycast hit a collider.
/// </summary>
property bool Hit;
/// <summary>
/// The other game object hit.
/// </summary>
property System::Nullable<GameObject> Other;
/// <summary>
/// The position where the ray cast hit. Zero if not hit.
/// </summary>
property Vector3 Position;
/// <summary>
/// The normal where the ray cast hit. Zero if not hit.
/// </summary>
property Vector3 Normal;
/// <summary>
/// The distance the ray was cast. Infinity if not hit.
/// </summary>
property float Distance;
/// <summary>
/// The index of the collision shape hit on the collider. -1 if not hit.
/// </summary>
property int CollisionShapeIndex;
};
} // namespace SHADE

View File

@ -19,6 +19,8 @@ of DigiPen Institute of Technology is prohibited.
// External Dependencies
#include <msclr/marshal_cppstd.h>
#include "ECS_Base/Managers/SHEntityManager.h"
// Project Headers
#include "Engine/GameObject.hxx"
namespace SHADE
{
@ -62,14 +64,14 @@ namespace SHADE
return Quaternion{ quat.x, quat.y, quat.z, quat.w };
}
SHRay Convert::ToNative(Ray vec)
SHRay Convert::ToNative(Ray ray)
{
return SHRay(ToNative(vec.Origin), ToNative(vec.Direction));
return SHRay(ToNative(ray.Position), ToNative(ray.Direction));
}
Ray Convert::ToCLI(const SHRay& vec)
Ray Convert::ToCLI(const SHRay& ray)
{
return Ray(ToCLI(vec.position), ToCLI(vec.direction));
return Ray(ToCLI(ray.position), ToCLI(ray.direction));
}
SHColour Convert::ToNative(Color col)
@ -95,6 +97,42 @@ namespace SHADE
return msclr::interop::marshal_as<System::String^>(str);
}
/*---------------------------------------------------------------------------------*/
/* 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 */
/*---------------------------------------------------------------------------------*/

View File

@ -28,9 +28,11 @@ of DigiPen Institute of Technology is prohibited.
#include "Math/Vector3.hxx"
#include "Math/Quaternion.hxx"
#include "Math/Ray.hxx"
#include "Physics/RaycastHit.hxx"
#include "Engine/GenericHandle.hxx"
#include "Math/SHColour.h"
#include "Graphics/Color.hxx"
#include "Physics/Collision/SHPhysicsRaycastResult.h"
namespace SHADE
{
@ -95,22 +97,22 @@ namespace SHADE
/// <param name="quat">The native Quaternion to convert from.</param>
/// <returns>Managed copy of a native Quaternion.</returns>
static Quaternion ToCLI(const SHQuaternion& quat);
/// Converts from a managed Vector2 to a native Vector2.
/// Converts from a managed Ray to a native Ray.
/// </summary>
/// <param name="vec">The managed Vector2 to convert from.</param>
/// <returns>Native copy of a managed Vector2.</returns>
/// <param name="ray">The managed Ray to convert from.</param>
/// <returns>Native copy of a managed Ray.</returns>
static SHRay ToNative(Ray vec);
/// <summary>
/// Converts from a native Vector2 to a managed Vector2.
/// Converts from a native Ray to a managed Ray.
/// </summary>
/// <param name="vec">The native Vector2 to convert from.</param>
/// <returns>Managed copy of a native Vector2.</returns>
static Ray ToCLI(const SHRay& vec);
/// <param name="ray">The native Ray to convert from.</param>
/// <returns>Managed copy of a native Ray.</returns>
static Ray ToCLI(const SHRay& ray);
/// Converts from a managed Color to a native Colour.
/// </summary>
/// <param name="vec">The managed Color to convert from.</param>
/// <returns>Native copy of a managed Color.</returns>
static SHColour ToNative(Color col);
static SHColour ToNative(Color ray);
/// <summary>
/// Converts from a native Colour to a managed Color.
/// </summary>
@ -134,9 +136,27 @@ namespace SHADE
/// <returns>Managed copy of a native std::string.</returns>
static System::String^ ToCLI(const std::string& str);
/*-----------------------------------------------------------------------------*/
/* 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 */
/*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Converts from a managed GenericHandle to a Handle<void>.
/// </summary>