From b328d1df82dfdd32dc6c6c45f3551366217bc305 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 18 Nov 2022 18:15:19 +0800 Subject: [PATCH 1/3] Added Physics Raycasts with Debug Drawing Press F11 while the scene is playing to toggle debug drawing of rays. --- .../src/Application/SBApplication.cpp | 6 + SHADE_Engine/src/Math/SHRay.cpp | 21 +- SHADE_Engine/src/Math/SHRay.h | 49 ++- .../Physics/Collision/SHCollisionListener.h | 1 - .../Physics/Collision/SHPhysicsRaycaster.cpp | 350 ++++++++++++++++++ .../Physics/Collision/SHPhysicsRaycaster.h | 142 +++++++ .../Physics/PhysicsObject/SHPhysicsObject.cpp | 2 +- .../PhysicsObject/SHPhysicsObjectManager.cpp | 7 +- .../PhysicsObject/SHPhysicsObjectManager.h | 2 +- .../System/SHPhysicsDebugDrawSystem.cpp | 91 +++-- .../Physics/System/SHPhysicsDebugDrawSystem.h | 20 +- .../src/Physics/System/SHPhysicsSystem.cpp | 39 +- .../src/Physics/System/SHPhysicsSystem.h | 89 ++++- 13 files changed, 748 insertions(+), 71 deletions(-) create mode 100644 SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp create mode 100644 SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index fdfcc08b..acd7d014 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -176,6 +176,12 @@ namespace Sandbox drawColliders = !drawColliders; SHSystemManager::GetSystem()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders); } + static bool drawRays = false; + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F11)) + { + drawRays = !drawRays; + SHSystemManager::GetSystem()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays); + } } // Finish all graphics jobs first graphicsSystem->AwaitGraphicsExecution(); diff --git a/SHADE_Engine/src/Math/SHRay.cpp b/SHADE_Engine/src/Math/SHRay.cpp index 87f12b81..c4931aba 100644 --- a/SHADE_Engine/src/Math/SHRay.cpp +++ b/SHADE_Engine/src/Math/SHRay.cpp @@ -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 \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHRay.h b/SHADE_Engine/src/Math/SHRay.h index 29d55b16..18efc224 100644 --- a/SHADE_Engine/src/Math/SHRay.h +++ b/SHADE_Engine/src/Math/SHRay.h @@ -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 +#include // 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::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 \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h index 6262b946..62882556 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h +++ b/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h @@ -32,7 +32,6 @@ namespace SHADE class SH_API SHCollisionListener final : public rp3d::EventListener { public: - /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp new file mode 100644 index 00000000..11b9fcab --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp @@ -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 + +// 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::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::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(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::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(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(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 \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h new file mode 100644 index 00000000..6d1e6f2d --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h @@ -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 + +#include + +// 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; + using RaycastPairs = std::vector; + + 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::infinity() + ) noexcept; + + SHPhysicsRaycastResult Linecast + ( + const SHVec3& start + , const SHVec3& end + ) noexcept; + + SHPhysicsRaycastResult ColliderRaycast + ( + EntityID eid + , const SHRay& ray + , float distance = std::numeric_limits::infinity() + ) noexcept; + + SHPhysicsRaycastResult ColliderRaycast + ( + EntityID eid + , int shapeIndex + , const SHRay& ray + , float distance = std::numeric_limits::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 \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp index 0a0ff201..3cfa3ec9 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp @@ -294,7 +294,7 @@ namespace SHADE if (!rp3dBody->isActive()) return; - const int NUM_SHAPES = static_cast(component.collisionShapes.size()); + const int NUM_SHAPES = static_cast(rp3dBody->getNbColliders()); for (int i = 0; i < NUM_SHAPES; ++i) { auto& collisionShape = component.collisionShapes[i]; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp index ffd10e0c..389983c3 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp @@ -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 }; /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h index 641fd9df..f41c62ad 100644 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h @@ -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; diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index 7ccfb225..bf1debac 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -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(GetSystem()); + auto* debugDrawSystem = SHSystemManager::GetSystem(); + 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(); 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(); + 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::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(); - if (debugDrawSystem == nullptr) - { - SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!") - return; - } - auto* BOX = reinterpret_cast(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(); - if (debugDrawSystem == nullptr) - { - SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!") - return; - } - auto* SPHERE = reinterpret_cast(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 \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h index 149ed6c1..867a6e11 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h @@ -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 diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 50590e04..fd18a0f8 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -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) + { + 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) { @@ -327,8 +353,9 @@ namespace SHADE // Create physics world 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); diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 9638e05c..4892ee90 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -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::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::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::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. // 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 */ From 6b5b0387a9390ab17094d48c2ddcf9fd1f974270 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 18 Nov 2022 18:31:07 +0800 Subject: [PATCH 2/3] Fixed bug where pausing then playing crashes physics --- SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index fd18a0f8..1a99b808 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -351,6 +351,9 @@ namespace SHADE //////////////////////////////// // Create physics world + if (worldState.world != nullptr) + return onPlayEvent->handle; + worldState.CreateWorld(factory); // Link Collision Listener & Raycaster From 411c4a4e564da3f14740efa58fb953ea6fe2481a Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 19 Nov 2022 04:21:46 +0800 Subject: [PATCH 3/3] Added C# Interface for Raycasting Untested with Scripts, tested engine side. --- .../Collision/SHPhysicsRaycastResult.h | 34 +++++ .../Physics/Collision/SHPhysicsRaycaster.h | 15 +- .../src/Physics/System/SHPhysicsSystem.cpp | 6 +- .../src/Physics/System/SHPhysicsSystem.h | 6 +- .../System/SHPhysicsSystemInterface.cpp | 78 ++++++++++- .../Physics/System/SHPhysicsSystemInterface.h | 25 +++- SHADE_Managed/src/Math/Ray.cxx | 53 +++++--- SHADE_Managed/src/Math/Ray.hxx | 95 +++++++------ SHADE_Managed/src/Physics/Physics.cxx | 105 ++++++++++++++ SHADE_Managed/src/Physics/Physics.hxx | 128 ++++++++++++++++++ SHADE_Managed/src/Physics/RaycastHit.cxx | 19 +++ SHADE_Managed/src/Physics/RaycastHit.hxx | 64 +++++++++ SHADE_Managed/src/Utility/Convert.cxx | 46 ++++++- SHADE_Managed/src/Utility/Convert.hxx | 38 ++++-- 14 files changed, 609 insertions(+), 103 deletions(-) create mode 100644 SHADE_Engine/src/Physics/Collision/SHPhysicsRaycastResult.h create mode 100644 SHADE_Managed/src/Physics/Physics.cxx create mode 100644 SHADE_Managed/src/Physics/Physics.hxx create mode 100644 SHADE_Managed/src/Physics/RaycastHit.cxx create mode 100644 SHADE_Managed/src/Physics/RaycastHit.hxx diff --git a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycastResult.h b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycastResult.h new file mode 100644 index 00000000..cce01845 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycastResult.h @@ -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; + + }; +} diff --git a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h index 6d1e6f2d..81165b56 100644 --- a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h +++ b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h @@ -15,10 +15,11 @@ #include // Project Headers +#include "Math/SHRay.h" #include "Physics/PhysicsObject/SHPhysicsObjectManager.h" #include "Physics/SHPhysicsWorld.h" -#include "Math/SHRay.h" #include "SH_API.h" +#include "SHPhysicsRaycastResult.h" namespace SHADE { @@ -26,18 +27,6 @@ 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: diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 1a99b808..f3513ffb 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -185,7 +185,7 @@ namespace SHADE return raycaster.Raycast(ray, distance); } - SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end) + SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end) noexcept { return raycaster.Linecast(start, end); } @@ -195,7 +195,7 @@ namespace SHADE return raycaster.ColliderRaycast(eid, ray, distance); } - SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) + SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept { return raycaster.ColliderRaycast(eid, shapeIndex, ray, distance); } @@ -205,7 +205,7 @@ namespace SHADE return raycaster.ColliderLinecast(eid, start, end); } - SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) + SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept { return raycaster.ColliderLinecast(eid, shapeIndex, start, end); } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 4892ee90..f92be4cd 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -101,7 +101,7 @@ namespace SHADE ( const SHVec3& start , const SHVec3& end - ); + ) noexcept; /** * @brief Casts a ray at a body with colliders. @@ -131,7 +131,7 @@ namespace SHADE , int shapeIndex , const SHRay& ray , float distance = std::numeric_limits::infinity() - ); + ) noexcept; /** * @brief Casts a bounded ray at a body with colliders. @@ -161,7 +161,7 @@ namespace SHADE , 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. diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index b142d54c..a028ffb5 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -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& 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + if (physicsSystem) + { + return physicsSystem->ColliderLinecast(eid, shapeIndex, start, end); + } + + SHLOGV_WARNING("Failed to get the physics system. No ray was casted."); + return SHPhysicsRaycastResult{}; + } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h index bdd04686..0065aee3 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h @@ -14,12 +14,21 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include +// 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& GetCollisionInfo() noexcept; - [[nodiscard]] static const std::vector& GetTriggerInfo() noexcept; - [[nodiscard]] static double GetFixedDT() noexcept; + + [[nodiscard]] static const std::vector& GetCollisionInfo() noexcept; + [[nodiscard]] static const std::vector& GetTriggerInfo () noexcept; + [[nodiscard]] static double GetFixedDT () noexcept; + + [[nodiscard]] static SHPhysicsRaycastResult Raycast (const SHRay& ray, float distance = std::numeric_limits::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::infinity()) noexcept; + [[nodiscard]] static SHPhysicsRaycastResult ColliderRaycast (EntityID eid, int shapeIndex, const SHRay& ray, float distance = std::numeric_limits::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; }; } diff --git a/SHADE_Managed/src/Math/Ray.cxx b/SHADE_Managed/src/Math/Ray.cxx index ee614cbe..bfb99578 100644 --- a/SHADE_Managed/src/Math/Ray.cxx +++ b/SHADE_Managed/src/Math/Ray.cxx @@ -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 } - {} -} \ No newline at end of file + /*-----------------------------------------------------------------------------------*/ + /* 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 \ No newline at end of file diff --git a/SHADE_Managed/src/Math/Ray.hxx b/SHADE_Managed/src/Math/Ray.hxx index c50191f8..b684aa91 100644 --- a/SHADE_Managed/src/Math/Ray.hxx +++ b/SHADE_Managed/src/Math/Ray.hxx @@ -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 { - /// - /// CLR version of the the SHADE Engine's Ray class that represents a ray in - /// 3-Dimensional space. - /// - public value struct Ray - { - public: - /*-----------------------------------------------------------------------------*/ - /* Public Members */ - /*-----------------------------------------------------------------------------*/ - /// - /// The start point of the ray. - /// - Vector3 Origin; - /// - /// The direction that a ray travels in. - /// - Vector3 Direction; + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ - /*-----------------------------------------------------------------------------*/ - /* Constructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Creates a ray starting at origin along direction. - /// - /// Source of the ray. - /// Direction the ray travels in. - Ray(Vector3 origin, Vector3 direction); - }; -} + public value struct Ray + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + + /// + /// Constructor for a ray. + /// + /// The starting position of the ray. + /// The direction of the ray. + Ray(Vector3 position, Vector3 direction); + + + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + + /// + /// The starting point of the Ray. + /// + property Vector3 Position; + /// + /// The direction of the ray. This should be a normalised vector. + /// + property Vector3 Direction; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + /// + /// Rotates the ray's direction towards a target. + /// + /// The target to direct the ray towards. + void LookAt(Vector3 target); + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Managed/src/Physics/Physics.cxx b/SHADE_Managed/src/Physics/Physics.cxx new file mode 100644 index 00000000..9e2c1413 --- /dev/null +++ b/SHADE_Managed/src/Physics/Physics.cxx @@ -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(); + default.Position = Vector3::Zero; + default.Normal = Vector3::Zero; + default.Distance = System::Single::PositiveInfinity; + default.CollisionShapeIndex = -1; + + return default; + } +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Managed/src/Physics/Physics.hxx b/SHADE_Managed/src/Physics/Physics.hxx new file mode 100644 index 00000000..f13e5952 --- /dev/null +++ b/SHADE_Managed/src/Physics/Physics.hxx @@ -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 */ + /*---------------------------------------------------------------------------------*/ + + /// + /// Casts an infinite ray into the world. + /// + /// The ray to cast. + /// The result of the raycast. + static RaycastHit Raycast (Ray ray); + + /// + /// Casts a ray for a given distance into the world. + /// + /// The ray to cast. + /// The distance to cast the ray. + /// The result of the raycast. + static RaycastHit Raycast (Ray ray, float distance); + + /// + /// Casts a bounded ray into the world. + /// + /// The start of the bounded ray. + /// The end of the bounded ray. + /// The result of the raycast. + static RaycastHit Linecast (Vector3 start, Vector3 end); + + /// + /// Casts an infinite ray w.r.t a GameObject. + /// + /// The GameObject to cast the ray to. + /// The ray to cast. + /// The result of the raycast. + static RaycastHit ColliderRaycast (GameObject object, Ray ray); + + /// + /// Casts a ray for a given distance w.r.t a GameObject. + /// + /// The GameObject to cast the ray to. + /// The ray to cast. + /// The distance to cast the ray. + /// The result of the raycast. + static RaycastHit ColliderRaycast (GameObject object, Ray ray, float distance); + + /// + /// Casts an infinite ray w.r.t a specific collider on a GameObject. + /// + /// The GameObject to cast the ray to. + /// The collision shape index on the collider to cast to. + /// The ray to cast. + /// The result of the raycast. + static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray); + + /// + /// Casts a ray for a given distance w.r.t a specific collider on a GameObject. + /// + /// The GameObject to cast the ray to. + /// The collision shape index on the collider to cast to. + /// The ray to cast. + /// The distance to cast the ray. + /// The result of the raycast. + static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance); + + /// + /// Casts a bounded ray w.r.t a GameObject. + /// + /// The GameObject to cast the ray to. + /// The start of the bounded ray. + /// + /// The result of the raycast. + static RaycastHit ColliderLineCast (GameObject object, Vector3 start, Vector3 end); + + /// + /// Casts a bounded ray w.r.t a specific collider on a GameObject. + /// + /// The GameObject to cast the ray to. + /// The collision shape index on the collider to cast to. + /// The start of the bounded ray. + /// The end of the bounded ray. + /// The result of the raycast. + static RaycastHit ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end); + + private: + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + static RaycastHit generateDefaultResult (); + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Managed/src/Physics/RaycastHit.cxx b/SHADE_Managed/src/Physics/RaycastHit.cxx new file mode 100644 index 00000000..e7ee9b89 --- /dev/null +++ b/SHADE_Managed/src/Physics/RaycastHit.cxx @@ -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 \ No newline at end of file diff --git a/SHADE_Managed/src/Physics/RaycastHit.hxx b/SHADE_Managed/src/Physics/RaycastHit.hxx new file mode 100644 index 00000000..260da2a1 --- /dev/null +++ b/SHADE_Managed/src/Physics/RaycastHit.hxx @@ -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 */ + /*-----------------------------------------------------------------------------------*/ + + /// + /// Defines a struct that contains the information of a raycast. + /// + public value struct RaycastHit + { + public: + /*---------------------------------------------------------------------------------*/ + /* Properties */ + /*---------------------------------------------------------------------------------*/ + + /// + /// Whether or not the raycast hit a collider. + /// + property bool Hit; + + /// + /// The other game object hit. + /// + property System::Nullable Other; + + /// + /// The position where the ray cast hit. Zero if not hit. + /// + property Vector3 Position; + + /// + /// The normal where the ray cast hit. Zero if not hit. + /// + property Vector3 Normal; + + /// + /// The distance the ray was cast. Infinity if not hit. + /// + property float Distance; + + /// + /// The index of the collision shape hit on the collider. -1 if not hit. + /// + property int CollisionShapeIndex; + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Managed/src/Utility/Convert.cxx b/SHADE_Managed/src/Utility/Convert.cxx index 3b1f0f38..38ea2f50 100644 --- a/SHADE_Managed/src/Utility/Convert.cxx +++ b/SHADE_Managed/src/Utility/Convert.cxx @@ -19,6 +19,8 @@ of DigiPen Institute of Technology is prohibited. // External Dependencies #include #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(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(); + + return cli; + } + /*---------------------------------------------------------------------------------*/ /* Handle Conversions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Utility/Convert.hxx b/SHADE_Managed/src/Utility/Convert.hxx index 4d0c5b59..04407f77 100644 --- a/SHADE_Managed/src/Utility/Convert.hxx +++ b/SHADE_Managed/src/Utility/Convert.hxx @@ -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 /// The native Quaternion to convert from. /// Managed copy of a native Quaternion. static Quaternion ToCLI(const SHQuaternion& quat); - /// Converts from a managed Vector2 to a native Vector2. + /// Converts from a managed Ray to a native Ray. /// - /// The managed Vector2 to convert from. - /// Native copy of a managed Vector2. + /// The managed Ray to convert from. + /// Native copy of a managed Ray. static SHRay ToNative(Ray vec); /// - /// Converts from a native Vector2 to a managed Vector2. + /// Converts from a native Ray to a managed Ray. /// - /// The native Vector2 to convert from. - /// Managed copy of a native Vector2. - static Ray ToCLI(const SHRay& vec); + /// The native Ray to convert from. + /// Managed copy of a native Ray. + static Ray ToCLI(const SHRay& ray); /// Converts from a managed Color to a native Colour. /// /// The managed Color to convert from. /// Native copy of a managed Color. - static SHColour ToNative(Color col); + static SHColour ToNative(Color ray); /// /// Converts from a native Colour to a managed Color. /// @@ -134,9 +136,27 @@ namespace SHADE /// Managed copy of a native std::string. static System::String^ ToCLI(const std::string& str); + /*-----------------------------------------------------------------------------*/ + /* Physics Conversions */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Converts from a managed RaycastHit to a native SHPhysicsRaycastResult + /// + /// The managed RaycastHit to convert from. + /// Native copy of a managed RaycastHit. + static SHPhysicsRaycastResult ToNative(RaycastHit cli); + + /// + /// Converts from native SHPhysicsRaycastResult to a managed RaycastHit. + /// + /// The native SHPhysicsRaycastResult to convert from. + /// Managed copy of a native SHPhysicsRaycastResult. + static RaycastHit ToCLI(const SHPhysicsRaycastResult& native); + /*-----------------------------------------------------------------------------*/ /* Handle Conversions */ - /*-----------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------*/ /// /// Converts from a managed GenericHandle to a Handle. ///