From 6a57be2e60a0ac2fd4a38ddaebb173ae398c7f7a Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 19:06:56 +0800 Subject: [PATCH 1/9] Refactored old physics to match new interface Compiles but still buggy, need a bit of time to clear up all the bugs --- Assets/Scenes/PhysicsTest.shade | 210 +++++++ Assets/Scenes/PhysicsTest.shade.shmeta | 3 + Assets/Scenes/Test.shade | 42 ++ Assets/Scenes/Test.shade.shmeta | 3 + Assets/Scenes/x.shade | 25 + Assets/Scenes/x.shade.shmeta | 3 + .../src/Application/SBApplication.cpp | 25 +- SHADE_Application/src/Scenes/SBMainScene.cpp | 17 - SHADE_Application/src/Scenes/SBTestScene.cpp | 18 +- SHADE_Engine/src/Camera/SHCameraSystem.cpp | 35 +- .../ColliderTagPanel/SHColliderTagPanel.cpp | 10 +- .../Inspector/SHEditorComponentView.hpp | 59 +- .../EditorWindow/MenuBar/SHEditorMenuBar.cpp | 25 + .../EditorWindow/MenuBar/SHEditorMenuBar.h | 1 + SHADE_Engine/src/Events/SHEventDefines.h | 1 + SHADE_Engine/src/Math/Geometry/SHBox.cpp | 250 -------- SHADE_Engine/src/Math/Geometry/SHBox.h | 105 ---- SHADE_Engine/src/Math/Geometry/SHSphere.cpp | 208 ------- SHADE_Engine/src/Math/SHRay.cpp | 4 +- SHADE_Engine/src/Math/SHRay.h | 7 +- .../SHCollisionTagMatrix.cpp | 0 .../SHCollisionTagMatrix.h | 0 .../{ => CollisionTags}/SHCollisionTags.cpp | 0 .../{ => CollisionTags}/SHCollisionTags.h | 0 .../SHPhysicsMaterial.cpp | 0 .../SHPhysicsMaterial.h | 0 .../Physics/Collision/SHPhysicsRaycaster.cpp | 350 ------------ .../Physics/Collision/SHPhysicsRaycaster.h | 134 ----- .../src/Physics/Collision/Shapes/SHBox.cpp | 105 ++++ .../Collision/Shapes/SHBox.h} | 68 +-- .../Collision/Shapes/SHCollisionShape.cpp | 209 +++++++ .../Collision/Shapes/SHCollisionShape.h | 157 +++++ .../src/Physics/Collision/Shapes/SHSphere.cpp | 105 ++++ .../Collision/Shapes/SHSphere.h} | 78 ++- .../PhysicsObject/SHPhysicsObject.cpp} | 26 +- .../Interface/PhysicsObject/SHPhysicsObject.h | 48 ++ .../PhysicsObject/SHPhysicsObjectManager.cpp | 408 +++++++++++++ .../PhysicsObject/SHPhysicsObjectManager.h | 183 ++++++ .../Physics/Interface/SHColliderComponent.cpp | 307 ++++++---- .../Physics/Interface/SHColliderComponent.h | 122 +++- .../Physics/Interface/SHCollisionShape.cpp | 368 ------------ .../src/Physics/Interface/SHCollisionShape.h | 134 ----- .../Interface/SHRigidBodyComponent.cpp | 381 +++++------- .../Physics/Interface/SHRigidBodyComponent.h | 101 ++-- .../Physics/PhysicsObject/SHPhysicsObject.cpp | 431 -------------- .../Physics/PhysicsObject/SHPhysicsObject.h | 111 ---- .../PhysicsObject/SHPhysicsObjectManager.cpp | 309 ---------- .../PhysicsObject/SHPhysicsObjectManager.h | 181 ------ .../SHCollisionListener.cpp | 18 +- .../SHCollisionListener.h | 2 +- .../{ => RP3DWrapper}/SHPhysicsWorld.cpp | 0 .../{ => RP3DWrapper}/SHPhysicsWorld.h | 3 +- .../src/Physics/RP3DWrapper/SHRaycaster.cpp | 132 +++++ .../src/Physics/RP3DWrapper/SHRaycaster.h | 133 +++++ SHADE_Engine/src/Physics/SHPhysicsEvents.h | 12 +- .../Routines/SHPhysicsDebugDrawRoutine.cpp | 113 ++++ .../Routines/SHPhysicsPostUpdateRoutine.cpp | 120 ++++ .../Routines/SHPhysicsPreUpdateRoutine.cpp | 95 +++ .../Routines/SHPhysicsUpdateRoutine.cpp | 66 +++ .../System/SHPhysicsDebugDrawSystem.cpp | 330 +++-------- .../Physics/System/SHPhysicsDebugDrawSystem.h | 137 ++--- .../src/Physics/System/SHPhysicsSystem.cpp | 540 ++++++------------ .../src/Physics/System/SHPhysicsSystem.h | 276 +++------ .../System/SHPhysicsSystemInterface.cpp | 84 +-- .../Physics/System/SHPhysicsSystemInterface.h | 63 +- .../System/SHPhysicsSystemRoutines.cpp | 412 ------------- .../src/Serialization/SHYAMLConverters.h | 29 +- SHADE_Managed/src/Components/Collider.cxx | 72 +-- SHADE_Managed/src/Components/Collider.h++ | 2 +- SHADE_Managed/src/Components/Collider.hxx | 27 +- SHADE_Managed/src/Physics/Physics.cxx | 253 +++++++- SHADE_Managed/src/Physics/Physics.hxx | 111 +++- 72 files changed, 3691 insertions(+), 4706 deletions(-) create mode 100644 Assets/Scenes/PhysicsTest.shade create mode 100644 Assets/Scenes/PhysicsTest.shade.shmeta create mode 100644 Assets/Scenes/Test.shade create mode 100644 Assets/Scenes/Test.shade.shmeta create mode 100644 Assets/Scenes/x.shade create mode 100644 Assets/Scenes/x.shade.shmeta delete mode 100644 SHADE_Engine/src/Math/Geometry/SHBox.cpp delete mode 100644 SHADE_Engine/src/Math/Geometry/SHBox.h delete mode 100644 SHADE_Engine/src/Math/Geometry/SHSphere.cpp rename SHADE_Engine/src/Physics/Collision/{ => CollisionTags}/SHCollisionTagMatrix.cpp (100%) rename SHADE_Engine/src/Physics/Collision/{ => CollisionTags}/SHCollisionTagMatrix.h (100%) rename SHADE_Engine/src/Physics/Collision/{ => CollisionTags}/SHCollisionTags.cpp (100%) rename SHADE_Engine/src/Physics/Collision/{ => CollisionTags}/SHCollisionTags.h (100%) rename SHADE_Engine/src/Physics/{Interface => Collision}/SHPhysicsMaterial.cpp (100%) rename SHADE_Engine/src/Physics/{Interface => Collision}/SHPhysicsMaterial.h (100%) delete mode 100644 SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp delete mode 100644 SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp rename SHADE_Engine/src/{Math/Geometry/SHSphere.h => Physics/Collision/Shapes/SHBox.h} (57%) create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h create mode 100644 SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp rename SHADE_Engine/src/{Math/Geometry/SHShape.h => Physics/Collision/Shapes/SHSphere.h} (64%) rename SHADE_Engine/src/{Math/Geometry/SHShape.cpp => Physics/Interface/PhysicsObject/SHPhysicsObject.cpp} (57%) create mode 100644 SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h create mode 100644 SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp create mode 100644 SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h delete mode 100644 SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp delete mode 100644 SHADE_Engine/src/Physics/Interface/SHCollisionShape.h delete mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp delete mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h delete mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp delete mode 100644 SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h rename SHADE_Engine/src/Physics/{Collision => RP3DWrapper}/SHCollisionListener.cpp (94%) rename SHADE_Engine/src/Physics/{Collision => RP3DWrapper}/SHCollisionListener.h (98%) rename SHADE_Engine/src/Physics/{ => RP3DWrapper}/SHPhysicsWorld.cpp (100%) rename SHADE_Engine/src/Physics/{ => RP3DWrapper}/SHPhysicsWorld.h (97%) create mode 100644 SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.cpp create mode 100644 SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.h create mode 100644 SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp create mode 100644 SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp create mode 100644 SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp create mode 100644 SHADE_Engine/src/Physics/System/Routines/SHPhysicsUpdateRoutine.cpp delete mode 100644 SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade new file mode 100644 index 00000000..b3fda265 --- /dev/null +++ b/Assets/Scenes/PhysicsTest.shade @@ -0,0 +1,210 @@ +- EID: 0 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 7, z: 0} + Rotate: {x: 0, y: 0, z: 0.785398185} + Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523} + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0 + Use Gravity: true + Interpolate: true + Sleeping Enabled: true + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: + - Type: PhysicsTestObj + Enabled: true + forceAmount: 200 + torqueAmount: 5 +- EID: 1 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 4, z: 0} + Rotate: {x: -0, y: 0, z: -0.436332315} + Scale: {x: 4.5999999, y: 1, z: 1} + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 2 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Camera Component: + Position: {x: 0, y: 2, z: 7} + Pitch: 0 + Yaw: 95 + Roll: 0 + Width: 1920 + Height: 1080 + Near: 0.00999999978 + Far: 10000 + Perspective: true + IsActive: true + Scripts: ~ +- EID: 65539 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 2.70000005, y: 0.5, z: 0} + Rotate: {x: -0, y: 0, z: 0.436332315} + Scale: {x: 4.5999999, y: 1, z: 1} + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 4 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -1.70000005, z: 0} + Rotate: {x: -0, y: 0, z: 0} + Scale: {x: 10, y: 0.5, z: 10} + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 5 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: -4.80000019, y: 3, z: 0} + Rotate: {x: -0, y: 0, z: 1.57079637} + Scale: {x: 10, y: 0.5, z: 10} + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 65542 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 4.80000019, y: 3, z: 0} + Rotate: {x: -0, y: 0, z: 1.57079637} + Scale: {x: 10, y: 0.5, z: 10} + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 7 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 3} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + RigidBody Component: + Type: Static + Drag: 0.00999999978 + Angular Drag: 0.00999999978 + Use Gravity: true + Interpolate: true + Sleeping Enabled: true + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/PhysicsTest.shade.shmeta b/Assets/Scenes/PhysicsTest.shade.shmeta new file mode 100644 index 00000000..11f96258 --- /dev/null +++ b/Assets/Scenes/PhysicsTest.shade.shmeta @@ -0,0 +1,3 @@ +Name: PhysicsTest +ID: 97086054 +Type: 5 diff --git a/Assets/Scenes/Test.shade b/Assets/Scenes/Test.shade new file mode 100644 index 00000000..4b831802 --- /dev/null +++ b/Assets/Scenes/Test.shade @@ -0,0 +1,42 @@ +- EID: 0 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Camera Component: + Position: {x: 0, y: 0, z: 0} + Pitch: 0 + Yaw: 0 + Roll: 0 + Width: 1920 + Height: 1080 + Near: 0.00999999978 + Far: 10000 + Perspective: true + IsActive: true + Scripts: ~ +- EID: 1 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0.100000001 + Use Gravity: false + Interpolate: true + Sleeping Enabled: true + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/Test.shade.shmeta b/Assets/Scenes/Test.shade.shmeta new file mode 100644 index 00000000..d5ded40c --- /dev/null +++ b/Assets/Scenes/Test.shade.shmeta @@ -0,0 +1,3 @@ +Name: Test +ID: 97979840 +Type: 5 diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade new file mode 100644 index 00000000..ae4767bc --- /dev/null +++ b/Assets/Scenes/x.shade @@ -0,0 +1,25 @@ +- EID: 65536 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0.100000001 + Use Gravity: false + Interpolate: true + Sleeping Enabled: true + Freeze Position X: false + Freeze Position Y: false + Freeze Position Z: false + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/x.shade.shmeta b/Assets/Scenes/x.shade.shmeta new file mode 100644 index 00000000..2e00ee43 --- /dev/null +++ b/Assets/Scenes/x.shade.shmeta @@ -0,0 +1,3 @@ +Name: x +ID: 91446183 +Type: 5 diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 4466c7a8..e97d9eb4 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -119,11 +119,11 @@ namespace Sandbox SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); - SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); #ifndef _PUBLISH - SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); #endif SHSystemManager::RegisterRoutine(); @@ -206,27 +206,6 @@ namespace Sandbox #else SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime()); #endif - // TODO: Move into an Editor menu - static bool drawContacts = false; - if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9)) - { - drawContacts = !drawContacts; - SHSystemManager::GetSystem()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts); - SHSystemManager::GetSystem()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts); - } - static bool drawColliders = false; - if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10)) - { - 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_Application/src/Scenes/SBMainScene.cpp b/SHADE_Application/src/Scenes/SBMainScene.cpp index 73926115..dd713980 100644 --- a/SHADE_Application/src/Scenes/SBMainScene.cpp +++ b/SHADE_Application/src/Scenes/SBMainScene.cpp @@ -44,23 +44,6 @@ namespace Sandbox { sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID); - auto* physicsSystem = SHSystemManager::GetSystem(); - if (!physicsSystem) - { - SHLOGV_CRITICAL("Failed to get the physics system for building the scene!") - return; - } - - #ifdef SHEDITOR - - physicsSystem->ForceBuild(SHSceneManager::GetCurrentSceneGraph()); - - #else - - physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph()); - - #endif - /*-----------------------------------------------------------------------*/ /* TESTING CODE */ /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index a5edd124..52327b22 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -92,7 +92,7 @@ namespace Sandbox floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); - floorCollider.AddBoundingBox(); + //floorCollider.AddBoundingBox(); // Create blank entity with a script //testObj = SHADE::SHEntityManager::CreateEntity(); @@ -113,9 +113,9 @@ namespace Sandbox racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f }); - racoonCollider.AddBoundingBox(); + //racoonCollider.AddBoundingBox(); racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f)); - racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); auto racoonItemLocation = SHEntityManager::CreateEntity(); auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s(racoonItemLocation); @@ -138,15 +138,15 @@ namespace Sandbox itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f }); - itemCollider.AddBoundingBox(); - itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); + //itemCollider.AddBoundingBox(); + //itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f)); itemCollider.GetCollisionShape(1).SetIsTrigger(true); itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); + //itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f)); itemRigidBody.SetInterpolate(false); itemRigidBody.SetFreezeRotationX(true); @@ -167,9 +167,9 @@ namespace Sandbox AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f }); AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f }); - AICollider.AddBoundingBox(); + //AICollider.AddBoundingBox(); AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f)); - AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); + //AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f)); AIRigidBody.SetInterpolate(false); AIRigidBody.SetFreezeRotationX(true); diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp index 6feece48..b31345cd 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp +++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp @@ -10,7 +10,6 @@ #include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" -#include "Math/Geometry/SHBox.h" #include "Math/SHRay.h" #include "Physics/System/SHPhysicsSystem.h" @@ -186,25 +185,25 @@ namespace SHADE //SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z) - auto result = physicsSystem->Raycast(pivot.ray ); - if (result && result.distance < pivot.GetArmLength()) - { - - SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f }; - newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch()))); - newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw()))); - pivot.offset = newOffset; - //SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance); - } - else - { - //SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA"); - } + //auto result = physicsSystem->Raycast(pivot.ray ); + //if (result && result.distance < pivot.GetArmLength()) + //{ + // + // SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f }; + // newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch()))); + // newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw()))); + // pivot.offset = newOffset; + // //SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance); + //} + //else + //{ + // //SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA"); + //} - - + // + // - // pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); + //// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/ColliderTagPanel/SHColliderTagPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/ColliderTagPanel/SHColliderTagPanel.cpp index 8169aa5c..f28e29c5 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ColliderTagPanel/SHColliderTagPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ColliderTagPanel/SHColliderTagPanel.cpp @@ -1,7 +1,7 @@ #include "SHpch.h" #include "SHColliderTagPanel.h" #include "ECS_Base/Managers/SHSystemManager.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" #include "Editor/SHEditorWidgets.hpp" namespace SHADE @@ -15,7 +15,7 @@ namespace SHADE ImGui::TableNextRow(); ImGui::PushID("CollisionTagNames"); - for (int i = SHCollisionTag::NUM_LAYERS; i >= 0; --i) + for (int i = SHCollisionTag::NUM_LAYERS; i >= 1; --i) { ImGui::TableNextColumn(); if(i == SHCollisionTag::NUM_LAYERS) continue; @@ -29,7 +29,7 @@ namespace SHADE ImGui::PopID(); } ImGui::PopID(); - for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i) + for (int i = 0; i < SHCollisionTag::NUM_LAYERS - 1; ++i) { std::string tagName = SHCollisionTagMatrix::GetTagName(i); auto tag = SHCollisionTagMatrix::GetTag(i); @@ -53,8 +53,8 @@ namespace SHADE tagName2 = std::to_string(idx); ImGui::TableNextColumn(); - //if(i == idx) - // continue; + if(i == idx) + continue; std::string label = std::format("##{} vs {}", tagName, tagName2); SHEditorWidgets::CheckBox(label, [tag, &idx]{return tag->GetLayerState(idx);}, [tag, i, idx](bool const& value){tag->SetLayerState(idx, value); SHCollisionTagMatrix::GetTag(idx)->SetLayerState(i, value);}, label.substr(2)); } diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index a2873bd0..b3653fff 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -18,12 +18,13 @@ #include "Physics/Interface/SHColliderComponent.h" #include "Reflection/SHReflectionMetadata.h" #include "Resource/SHResourceManager.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" #include "Serialization/SHSerializationHelper.hpp" #include "Tools/Utilities/SHClipboardUtilities.h" #include "SHInspectorCommands.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" #include "Animation/SHAnimatorComponent.h" +#include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Collision/Shapes/SHSphere.h" namespace SHADE { template @@ -302,7 +303,7 @@ namespace SHADE { SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); - SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep"); + SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->IsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep"); } } @@ -334,6 +335,8 @@ namespace SHADE { DrawContextMenu(component); + SHEditorWidgets::CheckBox("Draw Colliders", [component] { return component->GetDebugDrawState(); }, [component](bool value) { component->SetDebugDrawState(value); }); + auto& colliders = component->GetCollisionShapes(); int const size = static_cast(colliders.size()); ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true); @@ -341,57 +344,57 @@ namespace SHADE for (int i{}; i < size; ++i) { ImGui::PushID(i); - SHCollisionShape* collider = &component->GetCollisionShape(i); + SHCollisionShape* collisionShape = &component->GetCollisionShape(i); auto cursorPos = ImGui::GetCursorPos(); - if (collider->GetType() == SHCollisionShape::Type::BOX) + if (collisionShape->GetType() == SHCollisionShape::Type::BOX) { SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* BOX = reinterpret_cast(collider->GetShape()); + auto* boxShape = dynamic_cast(collisionShape); SHEditorWidgets::DragVec3 ( "Half Extents", { "X", "Y", "Z" }, - [BOX] { return BOX->GetRelativeExtents(); }, - [collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); }); + [boxShape] { return boxShape->GetRelativeExtents(); }, + [boxShape](SHVec3 const& vec) { boxShape->SetRelativeExtents(vec); }); } - else if (collider->GetType() == SHCollisionShape::Type::SPHERE) + else if (collisionShape->GetType() == SHCollisionShape::Type::SPHERE) { SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); - const auto* SPHERE = reinterpret_cast(collider->GetShape()); + auto* sphereShape = dynamic_cast(collisionShape); SHEditorWidgets::DragFloat ( "Radius", - [SPHERE] { return SPHERE->GetRelativeRadius(); }, - [collider](float const& value) { collider->SetBoundingSphere(value); }); + [sphereShape] { return sphereShape->GetRelativeRadius(); }, + [sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); }); } - else if (collider->GetType() == SHCollisionShape::Type::CAPSULE) - { + //else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE) + //{ - } + //} { - SHEditorWidgets::CheckBox("Is Trigger", [collider] { return collider->IsTrigger(); }, [collider](bool value) { collider->SetIsTrigger(value); }); - SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collider]{return SHCollisionTagMatrix::GetTagIndex(collider->GetCollisionTag().GetName());}, [collider](int const& value){collider->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));}); + SHEditorWidgets::CheckBox("Is Trigger", [collisionShape] { return collisionShape->IsTrigger(); }, [collisionShape](bool value) { collisionShape->SetIsTrigger(value); }); + SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collisionShape]{return SHCollisionTagMatrix::GetTagIndex(collisionShape->GetCollisionTag().GetName());}, [collisionShape](int const& value){collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));}); if(ImGui::CollapsingHeader("Physics Material")) { - SHEditorWidgets::DragFloat("Friction", [collider] { return collider->GetFriction(); }, [collider](float value) { collider->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f); - SHEditorWidgets::DragFloat("Bounciness", [collider] { return collider->GetBounciness(); }, [collider](float value) { collider->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f); - SHEditorWidgets::DragFloat("Mass Density", [collider] { return collider->GetDensity(); }, [collider](float value) { collider->SetDensity(value); }, "Mass Density", 0.1f, 0.0f); + SHEditorWidgets::DragFloat("Friction", [collisionShape] { return collisionShape->GetFriction(); }, [collisionShape](float value) { collisionShape->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f); + SHEditorWidgets::DragFloat("Bounciness", [collisionShape] { return collisionShape->GetBounciness(); }, [collisionShape](float value) { collisionShape->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f); + SHEditorWidgets::DragFloat("Mass Density", [collisionShape] { return collisionShape->GetDensity(); }, [collisionShape](float value) { collisionShape->SetDensity(value); }, "Mass Density", 0.1f, 0.0f); } SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f }); - SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); }); + SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collisionShape] {return collisionShape->GetPositionOffset(); }, [&collisionShape](SHVec3 const& vec) {collisionShape->SetPositionOffset(vec); }); SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, - [&collider] + [&collisionShape] { - auto offset = collider->GetRotationOffset(); + auto offset = collisionShape->GetRotationOffset(); return offset; }, - [&collider](SHVec3 const& vec) + [&collisionShape](SHVec3 const& vec) { - collider->SetRotationOffset(vec); + collisionShape->SetRotationOffset(vec); }, true); SHEditorWidgets::EndPanel(); } @@ -406,7 +409,7 @@ namespace SHADE } if (colliderToDelete.has_value()) { - component->RemoveCollider(colliderToDelete.value()); + component->RemoveCollisionShape(colliderToDelete.value()); } ImGui::EndChild(); @@ -416,11 +419,11 @@ namespace SHADE if (ImGui::Selectable("Box Collider")) { - newColl = component->AddBoundingBox(); + newColl = component->AddBoxCollisionShape(SHVec3::One); } if (ImGui::Selectable("Sphere Collider")) { - newColl = component->AddBoundingSphere(); + newColl = component->AddSphereCollisionShape(1.0f); } //No idea why this doesn't work diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp index 3fe9ceb5..e8c943c2 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.cpp @@ -25,6 +25,7 @@ #include "Serialization/SHSerialization.h" #include "Serialization/Configurations/SHConfigurationManager.h" #include "Editor/EditorWindow/SHEditorWindowManager.h" +#include "Physics/System/SHPhysicsDebugDrawSystem.h" const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" }; @@ -88,6 +89,7 @@ namespace SHADE DrawThemeMenu(); DrawLayoutMenu(); DrawApplicationConfig(); + DrawPhysicsSettings(); std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())}; auto const size = ImGui::CalcTextSize(sceneName.data()); @@ -304,4 +306,27 @@ namespace SHADE ImGui::EndMenu(); } } + + void SHEditorMenuBar::DrawPhysicsSettings() noexcept + { + if (ImGui::BeginMenu("Physics Settings")) + { + if (auto* physicsDebugDraw = SHSystemManager::GetSystem()) + { + bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS); + if (ImGui::Checkbox("Draw Colliders", &drawColliders)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders); + + bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS); + if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints); + + bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS); + if (ImGui::Checkbox("Draw Rays", &drawRays)) + physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays); + } + + ImGui::EndMenu(); + } + } }//namespace SHADE diff --git a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h index 77ebcf55..4891dc5b 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h +++ b/SHADE_Engine/src/Editor/EditorWindow/MenuBar/SHEditorMenuBar.h @@ -25,6 +25,7 @@ namespace SHADE void DrawThemeMenu() noexcept; void DrawLayoutMenu() noexcept; void DrawApplicationConfig() noexcept; + void DrawPhysicsSettings() noexcept; float menuBarHeight = 20.0f; std::vector layoutPaths; diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index c090cd69..e2fcba10 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -24,4 +24,5 @@ constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 }; constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 }; constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 }; constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 }; +constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 19 }; diff --git a/SHADE_Engine/src/Math/Geometry/SHBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBox.cpp deleted file mode 100644 index 7261749b..00000000 --- a/SHADE_Engine/src/Math/Geometry/SHBox.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************************** - * \file SHBox.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box - * - * \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 "SHBox.h" -// Project Headers -#include "Math/SHMathHelpers.h" -#include "Math/SHRay.h" - -using namespace DirectX; - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHBox::SHBox() noexcept - : RelativeExtents { SHVec3::One } - { - type = Type::BOX; - } - - SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept - : RelativeExtents { SHVec3::One } - { - type = Type::BOX; - - Center = c; - Extents = hE; - } - - - SHBox::SHBox(const SHBox& rhs) noexcept - { - if (this == &rhs) - return; - - type = Type::BOX; - - Center = rhs.Center; - Extents = rhs.Extents; - RelativeExtents = rhs.RelativeExtents; - } - - SHBox::SHBox(SHBox&& rhs) noexcept - { - type = Type::BOX; - - Center = rhs.Center; - Extents = rhs.Extents; - RelativeExtents = rhs.RelativeExtents; - } - - /*-----------------------------------------------------------------------------------*/ - /* Operator Overload Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHBox& SHBox::operator=(const SHBox& rhs) noexcept - { - if (rhs.type != Type::BOX) - { - SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") - } - else if (this != &rhs) - { - Center = rhs.Center; - Extents = rhs.Extents; - RelativeExtents = rhs.RelativeExtents; - } - - return *this; - } - - SHBox& SHBox::operator=(SHBox&& rhs) noexcept - { - if (rhs.type != Type::BOX) - { - SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!") - } - else - { - Center = rhs.Center; - Extents = rhs.Extents; - RelativeExtents = rhs.RelativeExtents; - } - - return *this; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHVec3 SHBox::GetCenter() const noexcept - { - return Center; - } - - SHVec3 SHBox::GetWorldExtents() const noexcept - { - return Extents; - } - - const SHVec3& SHBox::GetRelativeExtents() const noexcept - { - return RelativeExtents; - } - - SHVec3 SHBox::GetMin() const noexcept - { - return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z }; - } - - SHVec3 SHBox::GetMax() const noexcept - { - return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z }; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHBox::SetCenter(const SHVec3& newCenter) noexcept - { - Center = newCenter; - } - - void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept - { - Extents = newWorldExtents; - } - - void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept - { - RelativeExtents = newRelativeExtents; - } - - void SHBox::SetMin(const SHVec3& min) noexcept - { - const SHVec3 MAX = GetMax(); - - Center = SHVec3::Lerp(min, MAX, 0.5f); - Extents = SHVec3::Abs((MAX - min) * 0.5f); - } - - void SHBox::SetMax(const SHVec3& max) noexcept - { - const SHVec3 MIN = GetMin(); - - Center = SHVec3::Lerp(MIN, max, 0.5f); - Extents = SHVec3::Abs((max - MIN) * 0.5f); - } - - void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept - { - Center = SHVec3::Lerp(min, max, 0.5f); - Extents = SHVec3::Abs((max - min) * 0.5f); - } - - std::vector SHBox::GetVertices() const noexcept - { - std::vector vertices{ 8 }; - GetCorners(vertices.data()); - return vertices; - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - bool SHBox::TestPoint(const SHVec3& point) const noexcept - { - return BoundingBox::Contains(point); - } - - SHRaycastResult SHBox::Raycast(const SHRay& ray) const noexcept - { - SHRaycastResult result; - - result.hit = Intersects(ray.position, ray.direction, result.distance); - if (result.hit) - { - result.position = ray.position + ray.direction * result.distance; - result.angle = SHVec3::Angle(ray.position, result.position); - } - - return result; - } - - bool SHBox::Contains(const SHBox& rhs) const noexcept - { - return BoundingBox::Contains(rhs); - } - - float SHBox::Volume() const noexcept - { - return 8.0f * (Extents.x * Extents.y * Extents.z); - } - - float SHBox::SurfaceArea() const noexcept - { - return 8.0f * ((Extents.x * Extents.y) - + (Extents.x * Extents.z) - + (Extents.y * Extents.z)); - } - - /*-----------------------------------------------------------------------------------*/ - /* Static Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept - { - SHBox result; - CreateMerged(result, lhs, rhs); - return result; - } - - bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept - { - return lhs.Intersects(rhs); - } - - SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept - { - SHBox result; - - for (size_t i = 1; i < numBoxes; ++i) - CreateMerged(result, boxes[i - 1], boxes[i]); - - return result; - } - - SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept - { - SHBox result; - CreateFromPoints(result, numVertices, vertices, stride); - return result; - } - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHBox.h b/SHADE_Engine/src/Math/Geometry/SHBox.h deleted file mode 100644 index a0ca9458..00000000 --- a/SHADE_Engine/src/Math/Geometry/SHBox.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************************** - * \file SHBox.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a 3-Dimensional Axis Aligned Bounding Box - * - * \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 - -// Project Headers -#include "SHShape.h" -#include "SH_API.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------------*/ - - class SH_API SHBox : public SHShape, - private DirectX::BoundingBox - { - public: - /*---------------------------------------------------------------------------------*/ - /* Static Data Members */ - /*---------------------------------------------------------------------------------*/ - - static constexpr size_t NUM_VERTICES = 8; - - /*---------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*---------------------------------------------------------------------------------*/ - - ~SHBox () override = default; - - SHBox () noexcept; - SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept; - SHBox (const SHBox& rhs) noexcept; - SHBox (SHBox&& rhs) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - - SHBox& operator= (const SHBox& rhs) noexcept; - SHBox& operator= (SHBox&& rhs) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Getter Functions */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] SHVec3 GetCenter () const noexcept; - [[nodiscard]] SHVec3 GetWorldExtents () const noexcept; - [[nodiscard]] const SHVec3& GetRelativeExtents () const noexcept; - [[nodiscard]] SHVec3 GetMin () const noexcept; - [[nodiscard]] SHVec3 GetMax () const noexcept; - [[nodiscard]] std::vector GetVertices () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetCenter (const SHVec3& newCenter) noexcept; - void SetWorldExtents (const SHVec3& newWorldExtents) noexcept; - void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept; - void SetMin (const SHVec3& min) noexcept; - void SetMax (const SHVec3& max) noexcept; - void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; - [[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override; - - [[nodiscard]] bool Contains (const SHBox& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Static Function Members */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept; - [[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept; - [[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - SHVec3 RelativeExtents; - }; - - -} // namespace SHADE - diff --git a/SHADE_Engine/src/Math/Geometry/SHSphere.cpp b/SHADE_Engine/src/Math/Geometry/SHSphere.cpp deleted file mode 100644 index 54935251..00000000 --- a/SHADE_Engine/src/Math/Geometry/SHSphere.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/**************************************************************************************** - * \file SHBoundingSphere.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Bounding Sphere - * - * \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 "SHSphere.h" -// Project Headers -#include "Math/SHMathHelpers.h" -#include "Math/SHRay.h" - -using namespace DirectX; - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHSphere::SHSphere() noexcept - : RelativeRadius { 1.0f } - { - type = Type::SPHERE; - } - - SHSphere::SHSphere(const SHVec3& center, float radius) noexcept - : RelativeRadius { 1.0f } - { - type = Type::SPHERE; - - Center = center; - Radius = radius; - } - - SHSphere::SHSphere(const SHSphere& rhs) noexcept - { - if (this == &rhs) - return; - - type = Type::SPHERE; - - Center = rhs.Center; - Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; - } - - SHSphere::SHSphere(SHSphere&& rhs) noexcept - { - type = Type::SPHERE; - - Center = rhs.Center; - Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; - } - - /*-----------------------------------------------------------------------------------*/ - /* Operator Overload Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept - { - if (rhs.type != Type::SPHERE) - { - SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") - } - else if (this != &rhs) - { - Center = rhs.Center; - Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; - } - - return *this; - } - - SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept - { - if (rhs.type != Type::SPHERE) - { - SHLOG_WARNING("Cannot assign a non-sphere to a sphere!") - } - else - { - Center = rhs.Center; - Radius = rhs.Radius; - RelativeRadius = rhs.RelativeRadius; - } - - return *this; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHVec3 SHSphere::GetCenter() const noexcept - { - return Center; - } - - float SHSphere::GetWorldRadius() const noexcept - { - return Radius; - } - - float SHSphere::GetRelativeRadius() const noexcept - { - return RelativeRadius; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHSphere::SetCenter(const SHVec3& center) noexcept - { - Center = center; - } - - void SHSphere::SetWorldRadius(float newWorldRadius) noexcept - { - Radius = newWorldRadius; - } - - void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept - { - RelativeRadius = newRelativeRadius; - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - bool SHSphere::TestPoint(const SHVec3& point) const noexcept - { - return BoundingSphere::Contains(point); - } - - SHRaycastResult SHSphere::Raycast(const SHRay& ray) const noexcept - { - SHRaycastResult result; - - result.hit = Intersects(ray.position, ray.direction, result.distance); - if (result.hit) - { - result.position = ray.position + ray.direction * result.distance; - result.angle = SHVec3::Angle(ray.position, result.position); - } - - return result; - } - - bool SHSphere::Contains(const SHSphere& rhs) const noexcept - { - return BoundingSphere::Contains(rhs); - } - - float SHSphere::Volume() const noexcept - { - return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius); - } - - float SHSphere::SurfaceArea() const noexcept - { - return 4.0f * SHMath::PI * (Radius * Radius); - } - - /*-----------------------------------------------------------------------------------*/ - /* Static Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept - { - SHSphere result; - CreateMerged(result, lhs, rhs); - return result; - } - - bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept - { - return lhs.Intersects(rhs); - } - - SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept - { - SHSphere result; - - for (size_t i = 1; i < numSpheres; ++i) - CreateMerged(result, spheres[i - 1], spheres[i]); - - return result; - } - - SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept - { - SHSphere result; - CreateFromPoints(result, numVertices, vertices, stride); - return result; - } - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHRay.cpp b/SHADE_Engine/src/Math/SHRay.cpp index c4931aba..b8a47f0e 100644 --- a/SHADE_Engine/src/Math/SHRay.cpp +++ b/SHADE_Engine/src/Math/SHRay.cpp @@ -10,6 +10,8 @@ #include +#include + // Primary Header #include "SHRay.h" @@ -30,7 +32,7 @@ namespace SHADE , direction { dir } {} - SHRay::SHRay(const reactphysics3d::Ray rp3dRay) noexcept + SHRay::SHRay(const reactphysics3d::Ray& rp3dRay) noexcept : position { rp3dRay.point1 } , direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) } {} diff --git a/SHADE_Engine/src/Math/SHRay.h b/SHADE_Engine/src/Math/SHRay.h index 18efc224..6e33be5e 100644 --- a/SHADE_Engine/src/Math/SHRay.h +++ b/SHADE_Engine/src/Math/SHRay.h @@ -16,8 +16,13 @@ #include "SH_API.h" #include "Vector/SHVec3.h" +/*-------------------------------------------------------------------------------------*/ +/* Forward Declarations */ +/*-------------------------------------------------------------------------------------*/ + namespace SHADE { + /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -40,7 +45,7 @@ namespace SHADE SHRay () noexcept; SHRay (const SHVec3& pos, const SHVec3& dir) noexcept; - SHRay (const reactphysics3d::Ray rp3dRay) noexcept; + SHRay (const reactphysics3d::Ray& rp3dRay) noexcept; SHRay (const SHRay&) noexcept = default; SHRay (SHRay&& ) noexcept = default; diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionTagMatrix.cpp b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp similarity index 100% rename from SHADE_Engine/src/Physics/Collision/SHCollisionTagMatrix.cpp rename to SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionTagMatrix.h b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h similarity index 100% rename from SHADE_Engine/src/Physics/Collision/SHCollisionTagMatrix.h rename to SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionTags.cpp b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp similarity index 100% rename from SHADE_Engine/src/Physics/Collision/SHCollisionTags.cpp rename to SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionTags.h b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h similarity index 100% rename from SHADE_Engine/src/Physics/Collision/SHCollisionTags.h rename to SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h diff --git a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp b/SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.cpp similarity index 100% rename from SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.cpp rename to SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.cpp diff --git a/SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h b/SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.h similarity index 100% rename from SHADE_Engine/src/Physics/Interface/SHPhysicsMaterial.h rename to SHADE_Engine/src/Physics/Collision/SHPhysicsMaterial.h diff --git a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp b/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp deleted file mode 100644 index cab5c93b..00000000 --- a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsRaycaster.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Physics Raycaster. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#include - -// Primary Header -#include "SHPhysicsRaycaster.h" - -/* - * TODO(DIREN): - * Once the physics engine has been rebuilt, this whole implementation should change - * and just call PhysicsWorld.Raycast etc. - * - * SHRaycastResult can be converted to a bool when necessary. - */ - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsRaycaster::SHPhysicsRaycaster() noexcept - : world { nullptr } - {} - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - const SHPhysicsRaycaster::RaycastPairs& SHPhysicsRaycaster::GetRaycasts() const noexcept - { - return raycasts; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsRaycaster::SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept - { - objectManager = physicsObjectManager; - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept - { - world = physicsWorld; - } - - void SHPhysicsRaycaster::ClearFrame() noexcept - { - raycasts.clear(); - } - - SHPhysicsRaycastResult SHPhysicsRaycaster::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept - { - // Reset temp - temp = SHPhysicsRaycastResult{}; - temp.distance = distance; - - if (!world) - { - SHLOG_ERROR("Physics world missing for raycasting!") - return temp; - } - - // If distance in infinity, cast to the default max distance of 2 km. - if (distance == std::numeric_limits::infinity()) - { - world->raycast(ray, this, collisionTag); - } - else - { - const SHVec3 END_POINT = ray.position + ray.direction * distance; - const rp3d::Ray RP3D_RAY{ ray.position, END_POINT }; - world->raycast(RP3D_RAY, this, collisionTag); - } - - // If a hit was found, populate temp info for return. - if (temp.hit) - { - temp.distance = SHVec3::Distance(ray.position, temp.position); - temp.angle = SHVec3::Angle(ray.position, temp.position); - } - - raycasts.emplace_back(ray, temp); - return temp; - } - - SHPhysicsRaycastResult SHPhysicsRaycaster::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept - { - temp = SHPhysicsRaycastResult{}; - temp.distance = SHVec3::Distance(start, end); - - if (!world) - { - SHLOG_ERROR("Physics world missing for raycasting!") - return temp; - } - - const rp3d::Ray RP3D_RAY{ start, end }; - world->raycast(RP3D_RAY, this, collisionTag); - - if (temp.hit) - { - temp.distance = SHVec3::Distance(start, temp.position); - temp.angle = SHVec3::Angle(start, temp.position); - } - - raycasts.emplace_back(RP3D_RAY, temp); - return temp; - } - - SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept - { - SHPhysicsRaycastResult result; - result.distance = distance; - - // Get a valid physics object with at least 1 collider. - const auto* PHYSICS_OBJECT = validateColliderRaycast(eid); - if (!PHYSICS_OBJECT) - return result; - - auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody(); - - // Data to populate - rp3d::RaycastInfo rp3dRaycastInfo; - bool hit = false; - - if (distance == std::numeric_limits::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 deleted file mode 100644 index 447207c7..00000000 --- a/SHADE_Engine/src/Physics/Collision/SHPhysicsRaycaster.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsRaycaster.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Physics Raycaster. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#pragma once - -#include - -#include - -// Project Headers -#include "Math/SHRay.h" -#include "Physics/PhysicsObject/SHPhysicsObjectManager.h" -#include "Physics/SHPhysicsWorld.h" -#include "SH_API.h" -#include "SHCollisionTags.h" -#include "SHPhysicsRaycastResult.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------------*/ - - class SH_API SHPhysicsRaycaster : public reactphysics3d::RaycastCallback - { - private: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - using RaycastPair = std::pair; - 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() - , const SHCollisionTag& collisionTag = SHCollisionTag{} - ) noexcept; - - SHPhysicsRaycastResult Linecast - ( - const SHVec3& start - , const SHVec3& end - , const SHCollisionTag& collisionTag = SHCollisionTag{} - ) noexcept; - - SHPhysicsRaycastResult ColliderRaycast - ( - EntityID eid - , const SHRay& ray - , float distance = std::numeric_limits::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/Collision/Shapes/SHBox.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp new file mode 100644 index 00000000..1e2a4a22 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp @@ -0,0 +1,105 @@ +/**************************************************************************************** + * \file SHBoxCollisionShape.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Box Collision Shape. + * + * \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 + +#include + +// Primary Header +#include "SHBox.h" + +// Project Headers +#include "Math/SHMatrix.h" +#include "Physics/Interface/SHColliderComponent.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHBox::SHBox() noexcept + : SHCollisionShape (Type::BOX) + , relativeExtents { SHVec3::One } + , scale { SHVec3::One } + { + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(SHVec3::One * 0.5f); + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHVec3 SHBox::GetWorldExtents() const noexcept + { + return SHVec3{ dynamic_cast(rp3dCollider->getCollisionShape())->getHalfExtents() }; + } + + SHVec3 SHBox::GetRelativeExtents() const noexcept + { + return relativeExtents; + } + + SHVec3 SHBox::GetWorldCentroid() const noexcept + { + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + return SHVec3::Transform(positionOffset, TRS); + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept + { + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(newWorldExtents); + + // Recompute Relative radius + relativeExtents = 2.0f * newWorldExtents / scale; + } + + void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept + { + relativeExtents = newRelativeExtents; + + // Recompute world radius + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); + } + + void SHBox::SetScale(const SHVec3& newScale) noexcept + { + scale = SHVec3::Abs(newScale); + + // Recompute world radius + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHMatrix SHBox::GetTRS() const noexcept + { + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHVec3 SCALE = GetWorldExtents() * 2.0f; + + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS); + + return SHMatrix::Transform(POSITION, ROTATION, SCALE); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHSphere.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h similarity index 57% rename from SHADE_Engine/src/Math/Geometry/SHSphere.h rename to SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h index e056f21a..5fa394d9 100644 --- a/SHADE_Engine/src/Math/Geometry/SHSphere.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHBoundingSphere.h + * \file SHBox.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Bounding Sphere. + * \brief Interface for a Box Collision Shape. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -10,11 +10,8 @@ #pragma once -#include - // Project Headers -#include "SHShape.h" -#include "SH_API.h" +#include "SHCollisionShape.h" namespace SHADE { @@ -22,71 +19,60 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHSphere : public SHShape, - private DirectX::BoundingSphere + /** + * @brief + * Encapsulate a Box Shape used for Physics Simulations. + */ + class SH_API SHBox final : public SHCollisionShape { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHColliderComponent; + public: /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHSphere () noexcept; - SHSphere (const SHVec3& center, float radius) noexcept; - SHSphere (const SHSphere& rhs) noexcept; - SHSphere (SHSphere&& rhs) noexcept; - - ~SHSphere () override = default; + SHBox () noexcept; + ~SHBox () override = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ /*---------------------------------------------------------------------------------*/ - SHSphere& operator= (const SHSphere& rhs) noexcept; - SHSphere& operator= (SHSphere&& rhs) noexcept; - /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] SHVec3 GetCenter () const noexcept; - [[nodiscard]] float GetWorldRadius () const noexcept; - [[nodiscard]] float GetRelativeRadius () const noexcept; + [[nodiscard]] SHVec3 GetWorldExtents () const noexcept; + [[nodiscard]] SHVec3 GetRelativeExtents () const noexcept; + + [[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetCenter (const SHVec3& center) noexcept; - void SetWorldRadius (float newWorldRadius) noexcept; - void SetRelativeRadius (float newRelativeRadius) noexcept; + void SetWorldExtents (const SHVec3& newWorldExtents) noexcept; + void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept; + void SetScale (const SHVec3& newScale) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; - [[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override; - - [[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept; - [[nodiscard]] float Volume () const noexcept; - [[nodiscard]] float SurfaceArea () const noexcept; - - - /*---------------------------------------------------------------------------------*/ - /* Static Function Members */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept; - [[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept; - [[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept; - [[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept; + [[nodiscard]] SHMatrix GetTRS () const noexcept override; private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - float RelativeRadius; - + SHVec3 relativeExtents; + SHVec3 scale; }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp new file mode 100644 index 00000000..2acffe29 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp @@ -0,0 +1,209 @@ +/**************************************************************************************** + * \file SHCollider.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Collider. + * + * \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 + + +#include + +// Primary Header +#include "SHCollisionShape.h" + +// Project Headers +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" +#include "Reflection/SHReflectionMetadata.h" +#include "Tools/Utilities/SHUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHCollisionShape::SHCollisionShape(Type colliderType) + : rp3dCollider { nullptr } + , collider { nullptr } + , collisionTag { SHCollisionTagMatrix::GetTag(0) } + , flags { 0 } + { + flags |= 1U << SHUtilities::ConvertEnum(colliderType); + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + float SHCollisionShape::GetFriction() const noexcept + { + return material.GetFriction(); + } + + float SHCollisionShape::GetBounciness() const noexcept + { + return material.GetBounciness(); + } + + float SHCollisionShape::GetDensity() const noexcept + { + return material.GetDensity(); + } + + const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept + { + return material; + } + + const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept + { + return positionOffset; + } + + const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept + { + return rotationOffset; + } + + SHCollisionShape::Type SHCollisionShape::GetType() const noexcept + { + for (int i = 0; i < SHUtilities::ConvertEnum(Type::COUNT); ++i) + { + const uint8_t FLAG_VALUE = 1U << SHUtilities::ConvertEnum(static_cast(i)); + + if (flags & FLAG_VALUE) + return static_cast(i); + } + + return Type::INVALID; + } + + bool SHCollisionShape::IsTrigger() const noexcept + { + static constexpr int FLAG_POS = 3; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + bool SHCollisionShape::IsColliding() const noexcept + { + static constexpr int FLAG_POS = 4; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept + { + return *collisionTag; + } + + SHVec3 SHCollisionShape::GetWorldCentroid() const noexcept + { + return collider->GetTransform().position; + } + + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept + { + collisionTag = newCollisionTag; + } + + void SHCollisionShape::SetFriction(float friction) noexcept + { + material.SetFriction(friction); + rp3dCollider->getMaterial().setFrictionCoefficient(material.GetFriction()); + } + + void SHCollisionShape::SetBounciness(float bounciness) noexcept + { + material.SetBounciness(bounciness); + rp3dCollider->getMaterial().setBounciness(material.GetBounciness()); + } + + void SHCollisionShape::SetDensity(float density) noexcept + { + material.SetDensity(density); + rp3dCollider->getMaterial().setMassDensity(material.GetDensity()); + } + + void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept + { + material = newMaterial; + + auto& rp3dMaterial = rp3dCollider->getMaterial(); + rp3dMaterial.setFrictionCoefficient(material.GetFriction()); + rp3dMaterial.setBounciness(material.GetBounciness()); + rp3dMaterial.setMassDensity(material.GetDensity()); + } + + void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept + { + positionOffset = posOffset; + Update(); + } + + void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept + { + rotationOffset = rotOffset; + Update(); + } + + void SHCollisionShape::SetIsTrigger(bool isTrigger) noexcept + { + static constexpr int FLAG_POS = 3; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + isTrigger ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; + + rp3dCollider->setIsTrigger(isTrigger); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionShape::Update() noexcept + { + const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; + rp3dCollider->setLocalToBodyTransform(OFFSETS); + } + + SHMatrix SHCollisionShape::GetTRS() const noexcept + { + return SHMatrix::Identity; + } + +} // namespace SHADE + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::enumeration("Collider Type") + ( + value("Box", SHCollisionShape::Type::BOX), + value("Sphere", SHCollisionShape::Type::SPHERE) + // TODO(Diren): Add More Shapes + ); + + registration::class_("Collider") + .property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger ) + .property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction ) + .property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness ) + .property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity ) + .property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset) + .property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true)); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h new file mode 100644 index 00000000..44c4d479 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h @@ -0,0 +1,157 @@ +/**************************************************************************************** + * \file SHCollisionShape.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Base CollisionShape 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 + +#include +#include + +// Project Headers +#include "ECS_Base/Entity/SHEntity.h" +#include "Physics/Collision/CollisionTags/SHCollisionTags.h" +#include "Physics/Collision/SHPhysicsMaterial.h" +#include "Math/Transform/SHTransform.h" +#include "Physics/Collision/SHPhysicsRaycastResult.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHColliderComponent; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHCollisionShape + { + private: + + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHPhysicsSystem; + friend class SHColliderComponent; + + public: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + enum class Type + { + SPHERE + , BOX + + , COUNT + , INVALID = -1 + }; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionShape(Type colliderType = Type::INVALID); + + SHCollisionShape(const SHCollisionShape& rhs) noexcept = default; + SHCollisionShape(SHCollisionShape&& rhs) noexcept = default; + virtual ~SHCollisionShape() noexcept = default; + + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ + + SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept = default; + SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept = default; + + /*---------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*---------------------------------------------------------------------------------*/ + + // Material Properties + // TODO: Remove individual setters once instanced materials are supported + + [[nodiscard]] float GetFriction() const noexcept; + [[nodiscard]] float GetBounciness() const noexcept; + [[nodiscard]] float GetDensity() const noexcept; + [[nodiscard]] const SHPhysicsMaterial& GetMaterial() const noexcept; + + // Offsets + + [[nodiscard]] const SHVec3& GetPositionOffset() const noexcept; + [[nodiscard]] const SHVec3& GetRotationOffset() const noexcept; + + // Flags + + [[nodiscard]] Type GetType() const noexcept; + [[nodiscard]] bool IsTrigger() const noexcept; + [[nodiscard]] bool IsColliding() const noexcept; + + [[nodiscard]] const SHCollisionTag& GetCollisionTag() const noexcept; + + [[nodiscard]] virtual SHVec3 GetWorldCentroid() const noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept; + + void SetFriction(float friction) noexcept; + void SetBounciness(float bounciness) noexcept; + void SetDensity(float density) noexcept; + void SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept; + + void SetPositionOffset(const SHVec3& posOffset) noexcept; + void SetRotationOffset(const SHVec3& rotOffset) noexcept; + + // Forces rigidbody to recompute mass if one exists + void SetIsTrigger(bool isTrigger) noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + /** + * @brief + * Computes the transform of the shape. + */ + void Update() noexcept; + + /** + * @brief + * Computes the TRS matrix for rendering the shape. + * @return + * The model-to-world matrix for rendering the shape. + */ + [[nodiscard]] virtual SHMatrix GetTRS() const noexcept; + + protected: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + reactphysics3d::Collider* rp3dCollider; + SHColliderComponent* collider; // The collider it belongs to. + SHCollisionTag* collisionTag; + SHPhysicsMaterial material; // TODO: Change to pointer once instancing is supported + + SHVec3 positionOffset; + SHVec3 rotationOffset; + + uint8_t flags; // 0 0 0 trigger 0 capsule sphere box + + + RTTR_ENABLE() + }; +} diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp new file mode 100644 index 00000000..f8c73f90 --- /dev/null +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp @@ -0,0 +1,105 @@ +/**************************************************************************************** + * \file SHSphereCollisionShape.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Sphere Collision Shape. + * + * \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 + +#include + +// Primary Header +#include "SHSphere.h" + +// Project Headers +#include "Math/SHMathHelpers.h" +#include "Math/SHMatrix.h" +#include "Physics/Interface/SHColliderComponent.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHSphere::SHSphere() noexcept + : SHCollisionShape (Type::SPHERE) + , relativeRadius { 1.0f } + , scale { 1.0f } + { + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(0.5f); + } + + /*-----------------------------------------------------------------------------------*/ + /* Operator Overload Definitions */ + /*-----------------------------------------------------------------------------------*/ + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + float SHSphere::GetWorldRadius() const noexcept + { + return dynamic_cast(rp3dCollider->getCollisionShape())->getRadius(); + } + + float SHSphere::GetRelativeRadius() const noexcept + { + return relativeRadius; + } + + SHVec3 SHSphere::GetWorldCentroid() const noexcept + { + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + return SHVec3::Transform(positionOffset, TRS); + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHSphere::SetWorldRadius(float newWorldRadius) noexcept + { + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius); + + // Recompute Relative radius + relativeRadius = 2.0f * newWorldRadius / scale; + } + + void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept + { + relativeRadius = newRelativeRadius; + + // Recompute world radius + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); + } + + void SHSphere::SetScale(float maxScale) noexcept + { + scale = std::fabs(maxScale); + + // Recompute world radius + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHMatrix SHSphere::GetTRS() const noexcept + { + const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); + const SHVec3 SCALE = GetWorldRadius() * 2.0f; + + const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); + const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS); + + return SHMatrix::Transform(POSITION, ROTATION, SCALE); + } +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h similarity index 64% rename from SHADE_Engine/src/Math/Geometry/SHShape.h rename to SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h index 812cb169..bf9301fe 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHShape.h + * \file SHSphereCollisionShape.h * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a shape. + * \brief Interface for a Sphere Collision Shape. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -11,9 +11,7 @@ #pragma once // Project Headers -#include "SH_API.h" -#include "Math/SHRay.h" - +#include "SHCollisionShape.h" namespace SHADE { @@ -21,62 +19,60 @@ namespace SHADE /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ - class SH_API SHShape + /** + * @brief + * Encapsulate a Sphere Shape used for Physics Simulations. + */ + class SH_API SHSphere final : public SHCollisionShape { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHColliderComponent; + public: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - enum class Type - { - BOX - , SPHERE - , CAPSULE - , CONVEX_HULL - - , COUNT - , NONE = -1 - }; - - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - bool isIntersecting; - /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - virtual ~SHShape () = default; + SHSphere () noexcept; + ~SHSphere () override = default; - SHShape (const SHShape&) = default; - SHShape (SHShape&&) = default; - - SHShape& operator=(const SHShape&) = default; - SHShape& operator=(SHShape&&) = default; - - SHShape(); + /*---------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] Type GetType () const noexcept; + [[nodiscard]] float GetWorldRadius () const noexcept; + [[nodiscard]] float GetRelativeRadius () const noexcept; + + [[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override; + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetWorldRadius (float newWorldRadius) noexcept; + void SetRelativeRadius (float newRelativeRadius) noexcept; + void SetScale (float maxScale) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] virtual bool TestPoint (const SHVec3& point) const noexcept = 0; - [[nodiscard]] virtual SHRaycastResult Raycast (const SHRay& ray) const noexcept = 0; + [[nodiscard]] SHMatrix GetTRS () const noexcept override; - protected: + private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - Type type; + float relativeRadius; + float scale; }; -} // namespace SHADE \ No newline at end of file +} diff --git a/SHADE_Engine/src/Math/Geometry/SHShape.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp similarity index 57% rename from SHADE_Engine/src/Math/Geometry/SHShape.cpp rename to SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp index 2f869029..26387d6c 100644 --- a/SHADE_Engine/src/Math/Geometry/SHShape.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.cpp @@ -1,7 +1,7 @@ /**************************************************************************************** - * \file SHShape.cpp + * \file SHPhysicsObject.cpp * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a shape. + * \brief Implementation for a Physics Object. * * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or * disclosure of this file or its contents without the prior written consent @@ -11,25 +11,25 @@ #include // Primary Header -#include "SHShape.h" +#include "SHPhysicsObject.h" + +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" + namespace SHADE { /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ + /* Constructor & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHShape::SHShape() - : type { Type::NONE } + SHPhysicsObject::SHPhysicsObject(EntityID eid) noexcept + : entityID { eid } {} - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHShape::Type SHShape::GetType() const noexcept + SHPhysicsObject::~SHPhysicsObject() noexcept { - return type; + entityID = MAX_EID; + body = nullptr; } - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h new file mode 100644 index 00000000..f9568e33 --- /dev/null +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObject.h @@ -0,0 +1,48 @@ +/**************************************************************************************** + * \file SHPhysicsObject.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Physics Object. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include + +// Project Headers +#include "ECS_Base/Entity/SHEntity.h" + +namespace SHADE +{ + /*-------------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-------------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates a rigid body and a collider tied to an Entity. + */ + struct SH_API SHPhysicsObject + { + public: + /*-----------------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------------*/ + + // We use a rigid body all the time. Colliders without rigid bodies have a static body. + + EntityID entityID = MAX_EID; + rp3d::RigidBody* body = nullptr; + + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject (EntityID eid) noexcept; + ~SHPhysicsObject () noexcept; + + }; +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp new file mode 100644 index 00000000..9fc403f8 --- /dev/null +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -0,0 +1,408 @@ +/**************************************************************************************** + * \file SHPhysicsObjectManager.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for a Physics Object Manager. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#include + +// Primary Header +#include "SHPhysicsObjectManager.h" + +// Project Headers +#include "Math/Transform/SHTransformComponent.h" +#include "Physics/Collision/Shapes/SHSphere.h" +#include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Tools/Utilities/SHUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager::SHPhysicsObjectManager() noexcept + : factory { nullptr } + , physicsWorld { nullptr } + {} + + + + SHPhysicsObjectManager::~SHPhysicsObjectManager() noexcept + { + RemoveAllObjects(); + } + + /*-----------------------------------------------------------------------------------*/ + /* Getter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager::EntityObjectMap& SHPhysicsObjectManager::GetPhysicsObjects() noexcept + { + return physicsObjects; + } + + const SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID entityID) noexcept + { + const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); + if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end()) + { + SHLOG_ERROR("Cannot find physics object for entity {}!", entityID) + return nullptr; + } + + return &PHYSICS_OBJECT_ITERATOR->second; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon* physicsFactory) noexcept + { + factory = physicsFactory; + } + + void SHPhysicsObjectManager::SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept + { + physicsWorld = world; + } + + /*-----------------------------------------------------------------------------------*/ + /* Public Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept + { + SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!") + + SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID); + + // Get the rigidbody and transform components + auto* rigidBodyComponent = SHComponentManager::GetComponent(entityID); + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + + + + if (!physicsObject->body) + { + if (!transformComponent) + { + SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", entityID) + return; + } + + // Create a new rigidbody in the physics object + const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() }; + physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM); + } + + // Link with the component + rigidBodyComponent->SetRigidBody(physicsObject->body); + + // Reset the type + const auto RIGID_BODY_TYPE = rigidBodyComponent->GetType(); + switch (RIGID_BODY_TYPE) + { + case SHRigidBodyComponent::Type::STATIC: + physicsObject->body->setType(rp3d::BodyType::STATIC); + break; + case SHRigidBodyComponent::Type::KINEMATIC: + physicsObject->body->setType(rp3d::BodyType::KINEMATIC); + break; + case SHRigidBodyComponent::Type::DYNAMIC: + physicsObject->body->setType(rp3d::BodyType::DYNAMIC); + break; + default: + break; + } + } + + void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept + { + SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!") + + const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); + if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end()) + return; + + SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; + + // If a collider component exists, we just set the body to static + if (SHComponentManager::GetComponent_s(entityID)) + physicsObject->body->setType(rp3d::BodyType::STATIC); + else + { + physicsWorld->destroyRigidBody(physicsObject->body); + destroyPhysicsObject(entityID); + } + } + + void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept + { + SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!") + + SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID); + + // Get the collider & transform component + auto* colliderComponent = SHComponentManager::GetComponent(entityID); + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + + // Check if a body already exists. If it does, link it with the component + if (!physicsObject->body) + { + if (!transformComponent) + { + SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", entityID) + return; + } + + // Create a static body + const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() }; + physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM); + physicsObject->body->setType(rp3d::BodyType::STATIC); + } + + // Link with component + colliderComponent->SetFactory(factory); + colliderComponent->SetCollisionBody(physicsObject->body); + } + + void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept + { + auto* colliderComponent = SHComponentManager::GetComponent(entityID); + + const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); + if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end()) + { + SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second; + + // Remove all collision shapes from the body + int32_t numShapes = static_cast(physicsObject->body->getNbColliders()); + while (--numShapes >= 0) + { + auto* rp3dCollider = physicsObject->body->getCollider(numShapes); + physicsObject->body->removeCollider(rp3dCollider); + + delete colliderComponent->shapes[numShapes]; + colliderComponent->shapes[numShapes] = nullptr; + } + + colliderComponent->shapes.clear(); + + // Destroy if no rigidbody component + if (!SHComponentManager::GetComponent_s(entityID)) + destroyPhysicsObject(entityID); + } + } + + void SHPhysicsObjectManager::RemoveAllObjects() noexcept + { + // Physics objects itself will delete the object + physicsObjects.clear(); + } + + void SHPhysicsObjectManager::AddRigidBodyDef(EntityID entityID) noexcept + { + auto* rigidBody = SHComponentManager::GetComponent(entityID); + + const SHRigidBodyDef RIGID_BODY_DEF + { + .entityID = rigidBody->GetEID() + , .bodyType = rigidBody->type + , .flags = rigidBody->flags + , .interpolate = rigidBody->interpolate + , .drag = rigidBody->drag + , .angularDrag = rigidBody->angularDrag + }; + + rigidBodyQueue.push(RIGID_BODY_DEF); + } + + void SHPhysicsObjectManager::AddColliderDef(EntityID entityID) noexcept + { + auto* collider = SHComponentManager::GetComponent(entityID); + + SHColliderDef colliderDef + { + .entityID = collider->GetEID() + }; + + for (const auto* shape : collider->shapes) + { + SHColliderDef::ShapeDef shapeDef + { + .type = shape->GetType() + , .posOffset = shape->GetPositionOffset() + , .rotOffset = shape->GetRotationOffset() + }; + + switch (shape->GetType()) + { + case SHCollisionShape::Type::SPHERE: + shapeDef.size.x = dynamic_cast(shape)->GetWorldRadius(); + break; + case SHCollisionShape::Type::BOX: + shapeDef.size = dynamic_cast(shape)->GetWorldExtents(); + break; + default: + break; + } + + colliderDef.shapes.emplace_back(shapeDef); + } + + colliderQueue.push(colliderDef); + } + + void SHPhysicsObjectManager::FlushDefinitions() noexcept + { + SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!") + + // Flush all rigid bodies + while (!rigidBodyQueue.empty()) + { + const SHRigidBodyDef& DEF = rigidBodyQueue.front(); + + SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID); + + // Get transform component + auto* transformComponent = SHComponentManager::GetComponent_s(DEF.entityID); + if (!transformComponent) + { + SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", DEF.entityID) + + rigidBodyQueue.pop(); + continue; + } + + // Create a new rigidbody in the physics object + const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() }; + physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM); + + // Get rigidBody component + auto* rigidBodyComponent = SHComponentManager::GetComponent(DEF.entityID); + rigidBodyComponent->SetRigidBody(physicsObject->body); + + // Set type + rigidBodyComponent->type = DEF.bodyType; + switch (DEF.bodyType) + { + case SHRigidBodyComponent::Type::STATIC: + physicsObject->body->setType(rp3d::BodyType::STATIC); + break; + case SHRigidBodyComponent::Type::KINEMATIC: + physicsObject->body->setType(rp3d::BodyType::KINEMATIC); + break; + case SHRigidBodyComponent::Type::DYNAMIC: + physicsObject->body->setType(rp3d::BodyType::DYNAMIC); + break; + default: + break; + } + + + // Re-set properties + rigidBodyComponent->SetGravityEnabled (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::GRAVITY)); + rigidBodyComponent->SetIsAllowedToSleep (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::SLEEPING)); + rigidBodyComponent->SetFreezePositionX (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_X)); + rigidBodyComponent->SetFreezePositionY (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_Y)); + rigidBodyComponent->SetFreezePositionZ (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_Z)); + rigidBodyComponent->SetFreezeRotationX (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_X)); + rigidBodyComponent->SetFreezeRotationY (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_Y)); + rigidBodyComponent->SetFreezeRotationZ (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_Z)); + + rigidBodyComponent->SetInterpolate (DEF.interpolate); + rigidBodyComponent->SetDrag (DEF.drag); + rigidBodyComponent->SetAngularDrag (DEF.angularDrag); + + rigidBodyQueue.pop(); + } + + // Flush all colliders + while (!colliderQueue.empty()) + { + const SHColliderDef& DEF = colliderQueue.front(); + + SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID); + + // Get transform component + auto* transformComponent = SHComponentManager::GetComponent_s(DEF.entityID); + if (!transformComponent) + { + SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", DEF.entityID) + + colliderQueue.pop(); + continue; + } + + if (!physicsObject->body) + { + // Create a static body + const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() }; + physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM); + physicsObject->body->setType(rp3d::BodyType::STATIC); + } + + // Get rigidBody component + auto* colliderComponent = SHComponentManager::GetComponent(DEF.entityID); + + colliderComponent->SetFactory(factory); + colliderComponent->SetCollisionBody(physicsObject->body); + + // Add all shapes + for (auto& shapeDef : DEF.shapes) + { + switch (shapeDef.type) + { + case SHCollisionShape::Type::SPHERE: + { + colliderComponent->AddSphereCollisionShape(shapeDef.size.x); + break; + } + case SHCollisionShape::Type::BOX: + { + colliderComponent->AddBoxCollisionShape(shapeDef.size); + break; + } + default: break; + } + } + } + + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Member Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID entityID) + { + const auto& NEW_OBJECT = physicsObjects.emplace(entityID, SHPhysicsObject{entityID}).first; + return &NEW_OBJECT->second; + } + + SHPhysicsObject* SHPhysicsObjectManager::ensurePhysicsObject(EntityID entityID) + { + const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); + + SHPhysicsObject* physicsObject = PHYSICS_OBJECT_ITERATOR == physicsObjects.end() + ? createPhysicsObject(entityID) + : &PHYSICS_OBJECT_ITERATOR->second; + + return physicsObject; + } + + + void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID) + { + physicsObjects.erase(entityID); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h new file mode 100644 index 00000000..3c333ff9 --- /dev/null +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h @@ -0,0 +1,183 @@ +/**************************************************************************************** + * \file SHPhysicsObjectManager.h + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Interface for a Physics Object Manager. + * + * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. +****************************************************************************************/ + +#pragma once + +#include +#include +#include + +// Project Headers +#include "SHPhysicsObject.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" + +namespace SHADE +{ + /*-------------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-------------------------------------------------------------------------------------*/ + + /** + * @brief + * Encapsulates a manager for physics objects that links raw physics components with the + * engine's components. + */ + class SH_API SHPhysicsObjectManager + { + private: + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + using EntityObjectMap = std::unordered_map; + + public: + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + struct SHRigidBodyDef + { + EntityID entityID = MAX_EID; + SHRigidBodyComponent::Type bodyType = SHRigidBodyComponent::Type::STATIC; + uint8_t flags = 0; // aZ aY aX lZ lY lX sleepEnabled gravity + bool interpolate = true; + float drag = 0.0f; + float angularDrag = 0.0f; + }; + + struct SHColliderDef + { + struct ShapeDef + { + SHCollisionShape::Type type = SHCollisionShape::Type::SPHERE; + SHVec3 posOffset = SHVec3::Zero; + SHVec3 rotOffset = SHVec3::Zero; + SHVec3 size = SHVec3::Zero; // x for sphere radius, all 3 for box extents + }; + + EntityID entityID = MAX_EID; + std::vector shapes; + }; + + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObjectManager () noexcept; + ~SHPhysicsObjectManager () noexcept; + + /*-----------------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------------*/ + + [[nodiscard]] EntityObjectMap& GetPhysicsObjects () noexcept; + [[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept; + + /*-----------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*-----------------------------------------------------------------------------------*/ + + void SetFactory (rp3d::PhysicsCommon* physicsFactory) noexcept; + void SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept; + + /*-----------------------------------------------------------------------------------*/ + /* Member Functions */ + /*-----------------------------------------------------------------------------------*/ + + /** + * @brief + * Creates a rigid body and links it with the rigid body component. + * @param entityID + * The entity to link the new rigid body to. + */ + void AddRigidBody (EntityID entityID) noexcept; + + /** + * @brief + * Destroys a rigid body and removes the link with the rigid body component. + * @param entityID + * The entity to destroy the rigid body of. + */ + void RemoveRigidBody (EntityID entityID) noexcept; + + /** + * @brief + * Creates a composite collider and links it with the collider component. + * @param entityID + * The entity to link the new collider to. + */ + void AddCollider (EntityID entityID) noexcept; + + /** + * @brief + * Destroys a composite collider and removes the link with the collider component. + * @param entityID + * The entity to destroy the collider of. + */ + void RemoveCollider (EntityID entityID) noexcept; + + /** + * @brief + * Removes all physics object in the manager. This is only meant to be called when + * the world is being destroyed or the scene is being changed. + */ + void RemoveAllObjects () noexcept; + + /** + * @brief Adds a rigidbody definition to add to the physics world. + * @param rigidBody + * The rigidbody component + */ + void AddRigidBodyDef (EntityID entityID) noexcept; + + /** + * @brief Adds a collider definition to add to the physics world. + * @param collider + * The collider component + */ + void AddColliderDef (EntityID entityID) noexcept; + + /** + * @brief Adds all loaded definitions into the physics world. + */ + void FlushDefinitions () noexcept; + + private: + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + using RigidBodyQueue = std::queue; + using ColliderQueue = std::queue; + + /*-----------------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------------*/ + + rp3d::PhysicsCommon* factory; + rp3d::PhysicsWorld* physicsWorld; + EntityObjectMap physicsObjects; + + RigidBodyQueue rigidBodyQueue; + ColliderQueue colliderQueue; + + /*-----------------------------------------------------------------------------------*/ + /* Member Functions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsObject* createPhysicsObject (EntityID entityID); + SHPhysicsObject* ensurePhysicsObject (EntityID entityID); + void destroyPhysicsObject (EntityID entityID); + + + }; + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index d7db2c64..15d01042 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -9,6 +9,7 @@ ****************************************************************************************/ #include +#include // Primary Header #include "SHColliderComponent.h" @@ -16,7 +17,9 @@ // Project Headers #include "ECS_Base/Managers/SHSystemManager.h" #include "Math/SHMathHelpers.h" -#include "Physics/System/SHPhysicsSystem.h" +#include "Physics/SHPhysicsEvents.h" +#include "Physics/Collision/Shapes/SHSphere.h" +#include "Physics/Collision/Shapes/SHBox.h" namespace SHADE { @@ -25,185 +28,237 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHColliderComponent::SHColliderComponent() noexcept - : system { nullptr } + : flags { ACTIVE_FLAG | MOVED_FLAG } + , collisionBody { nullptr } {} /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + bool SHColliderComponent::GetDebugDrawState() const noexcept + { + return flags & DRAW_FLAG; + } + + const SHTransform& SHColliderComponent::GetTransform() const noexcept + { + return transform; + } const SHVec3& SHColliderComponent::GetPosition() const noexcept { - return position; + return transform.position; } const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept { - return orientation; - } - - SHVec3 SHColliderComponent::GetRotation() const noexcept - { - return orientation.ToEuler(); + return transform.orientation; } const SHVec3& SHColliderComponent::GetScale() const noexcept { - return scale; + return transform.scale; } const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept { - return collisionShapes; + return shapes; } SHCollisionShape& SHColliderComponent::GetCollisionShape(int index) { - if (index < 0 || static_cast(index) >= collisionShapes.size()) - throw std::invalid_argument("Out-of-range access!"); + const int NUM_SHAPES = static_cast(shapes.size()); - return collisionShapes[index]; + if (index < 0 || index >= NUM_SHAPES) + throw std::invalid_argument("Out-of-range index!"); + + return *shapes[index]; + } + + /*-----------------------------------------------------------------------------------*/ + /* Setter Function Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHColliderComponent::SetDebugDrawState(bool state) noexcept + { + state ? flags |= DRAW_FLAG : flags &= ~(DRAW_FLAG); + + #ifdef SHEDITOR + + // Broadcast event for the Debug Draw system to catch + const SHColliderOnDebugDrawEvent EVENT_DATA + { + .entityID = GetEID() + , .debugDrawState = state + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_DRAW_EVENT); + + #endif + } + + void SHColliderComponent::SetFactory(rp3d::PhysicsCommon* physicsCommon) noexcept + { + factory = physicsCommon; + } + + void SHColliderComponent::SetCollisionBody(rp3d::CollisionBody* body) noexcept + { + collisionBody = body; + } + + void SHColliderComponent::SetTransform(const SHTransform& newTransform) noexcept + { + flags |= MOVED_FLAG; + transform = newTransform; + } + + void SHColliderComponent::SetPosition(const SHVec3& newPosition) noexcept + { + flags |= MOVED_FLAG; + transform.position = newPosition; + } + + void SHColliderComponent::SetOrientation(const SHQuaternion& newOrientation) noexcept + { + flags |= MOVED_FLAG; + transform.orientation = newOrientation; + } + + void SHColliderComponent::SetScale(const SHVec3& newScale) noexcept + { + flags |= MOVED_FLAG; + transform.scale = newScale; } /*-----------------------------------------------------------------------------------*/ /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHColliderComponent::OnCreate() + const SHMatrix& SHColliderComponent::ComputeTRS() noexcept { - auto* physicsSystem = SHSystemManager::GetSystem(); - if (!physicsSystem) - { - SHLOG_ERROR("Physics System does not exist to link with Physics Components!") - return; - } - - system = physicsSystem; - - // Sync with transform if one already exists - if (auto* transformComponent = SHComponentManager::GetComponent_s(GetEID()); transformComponent) - { - position = transformComponent->GetWorldPosition(); - orientation = transformComponent->GetWorldOrientation(); - scale = transformComponent->GetWorldScale(); - } + return transform.ComputeTRS(); } - void SHColliderComponent::OnDestroy() + int SHColliderComponent::AddSphereCollisionShape(float relativeRadius, const SHVec3& posOffset, const SHVec3& rotOffset) { + SHASSERT(factory, "Physics factory missing from Collider Component! Unable to add colliders!") + const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z })); + + // Create collision shape + shapes.emplace_back(new SHSphere{}); + auto* newSphere = dynamic_cast(shapes.back()); + + newSphere->collider = this; + newSphere->positionOffset = posOffset; + newSphere->rotationOffset = rotOffset; + newSphere->relativeRadius = relativeRadius; + newSphere->scale = SPHERE_SCALE; + + + rp3d::SphereShape* rp3dSphere = factory->createSphereShape(relativeRadius * SPHERE_SCALE * 0.5f); + + const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; + newSphere->rp3dCollider = collisionBody->addCollider(rp3dSphere, OFFSETS); + + const uint32_t NEW_INDEX = static_cast(shapes.size()); + + // Broadcast Event for adding a shape + const SHPhysicsColliderAddedEvent EVENT_DATA + { + .entityID = GetEID() + , .colliderType = SHCollisionShape::Type::BOX + , .colliderIndex = static_cast(NEW_INDEX) + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); + + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + + return static_cast(NEW_INDEX); } - void SHColliderComponent::RecomputeCollisionShapes() noexcept + int SHColliderComponent::AddBoxCollisionShape(const SHVec3& relativeExtents, const SHVec3& posOffset, const SHVec3& rotOffset) { - for (auto& collisionShape : collisionShapes) + SHASSERT(factory, "Physics factory missing from Collider Component! Unable to add colliders!") + + // Create collision shape + shapes.emplace_back(new SHBox{}); + auto* newBox = dynamic_cast(shapes.back()); + + newBox->collider = this; + newBox->positionOffset = posOffset; + newBox->rotationOffset = rotOffset; + newBox->relativeExtents = relativeExtents; + newBox->scale = SHVec3::Abs(transform.scale); + + + + rp3d::BoxShape* rp3dBox = factory->createBoxShape(relativeExtents * newBox->scale * 0.5f); + + const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; + newBox->rp3dCollider = collisionBody->addCollider(rp3dBox, OFFSETS); + + const uint32_t NEW_INDEX = static_cast(shapes.size()); + + // Broadcast Event for adding a shape + const SHPhysicsColliderAddedEvent EVENT_DATA { - switch (collisionShape.GetType()) + .entityID = GetEID() + , .colliderType = SHCollisionShape::Type::BOX + , .colliderIndex = static_cast(NEW_INDEX) + }; + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); + + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + + return static_cast(NEW_INDEX); + } + + void SHColliderComponent::RemoveCollisionShape(int index) + { + const int NUM_SHAPES = static_cast(shapes.size()); + + if (index < 0 || index >= NUM_SHAPES) + throw std::invalid_argument("Out-of-range index!"); + + int i = 0; + for (auto shapeIter = shapes.begin(); shapeIter != shapes.end(); ++i, ++shapeIter) + { + if (i == index) { - case SHCollisionShape::Type::BOX: + collisionBody->removeCollider((*shapeIter)->rp3dCollider); + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + + const SHPhysicsColliderRemovedEvent EVENT_DATA { - auto* box = reinterpret_cast(collisionShape.shape); - const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents(); + .entityID = GetEID() + , .colliderType = (*shapeIter)->GetType() + , .colliderIndex = index + }; - // Recompute world extents based on new scale and fixed relative extents + // Broadcast Event for removing a shape + SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT); - const SHVec3 WORLD_EXTENTS = RELATIVE_EXTENTS * (scale * 0.5f); - box->SetWorldExtents(WORLD_EXTENTS); + SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, GetEID()) - continue; - } - case SHCollisionShape::Type::SPHERE: - { - auto* sphere = reinterpret_cast(collisionShape.shape); - const float RELATIVE_RADIUS = sphere->GetRelativeRadius(); - - // Recompute world radius based on new scale and fixed radius - - const float MAX_SCALE = SHMath::Max({ scale.x, scale.y, scale.z }); - const float WORLD_RADIUS = RELATIVE_RADIUS * MAX_SCALE * 0.5f; - sphere->SetWorldRadius(WORLD_RADIUS); - - continue; - } - default: continue; + delete *shapeIter; + shapeIter = shapes.erase(shapeIter); + return; } } } - int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept + void SHColliderComponent::Update() noexcept { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!") - return -1; - } - - static constexpr auto TYPE = SHCollisionShape::Type::BOX; - - auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE }); - - collider.entityID = GetEID(); - collider.SetPositionOffset(posOffset); - collider.SetRotationOffset(rotOffset); - collider.SetBoundingBox(halfExtents); - - // Notify Physics System - const int NEW_SHAPE_INDEX = static_cast(collisionShapes.size()) - 1; - - system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); - return NEW_SHAPE_INDEX; + for (auto& shape : shapes) + shape->Update(); } - int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept - { - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!") - return -1; - } - static constexpr auto TYPE = SHCollisionShape::Type::SPHERE; - - auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE }); - - collider.entityID = GetEID(); - collider.SetPositionOffset(posOffset); - collider.SetBoundingSphere(radius); - - // Notify Physics System - const int NEW_SHAPE_INDEX = static_cast(collisionShapes.size()) - 1; - - system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX); - return NEW_SHAPE_INDEX; - } - - void SHColliderComponent::RemoveCollider(int index) - { - if (index < 0 || static_cast(index) >= collisionShapes.size()) - throw std::invalid_argument("Out-of-range access!"); - - int idx = 0; - auto it = collisionShapes.begin(); - for (; it != collisionShapes.end(); ++it) - { - if (idx == index) - break; - - ++idx; - } - - it = collisionShapes.erase(it); - - // Notify Physics System - if (!system) - { - SHLOG_ERROR("Physics system does not exist, unable to remove Collider!") - return; - } - - system->RemoveCollisionShape(GetEID(), index); - } } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 0781f3cf..63a59e55 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -10,18 +10,24 @@ #pragma once +#include + #include // Project Headers #include "ECS_Base/Components/SHComponent.h" -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "SHCollisionShape.h" +#include "Math/Transform/SHTransform.h" +#include "Physics/Collision/Shapes/SHCollisionShape.h" -//namespace SHADE -//{ -// class SHPhysicsSystem; -//} +/*-------------------------------------------------------------------------------------*/ +/* Forward Declarations */ +/*-------------------------------------------------------------------------------------*/ + +namespace reactphysics3d +{ + class PhysicsCommon; + class CollisionBody; +} namespace SHADE { @@ -37,13 +43,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; - friend class SHPhysicsObject; + friend class SHPhysicsObjectManager; /*---------------------------------------------------------------------------------*/ /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using CollisionShapes = std::vector; + using CollisionShapes = std::vector; public: @@ -67,29 +73,88 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; + [[nodiscard]] bool GetDebugDrawState () const noexcept; - [[nodiscard]] const SHVec3& GetPosition () const noexcept; - [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; - [[nodiscard]] SHVec3 GetRotation () const noexcept; - [[nodiscard]] const SHVec3& GetScale () const noexcept; + [[nodiscard]] const SHTransform& GetTransform () const noexcept; + [[nodiscard]] const SHVec3& GetPosition () const noexcept; + [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; + [[nodiscard]] const SHVec3& GetScale () const noexcept; - [[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept; - [[nodiscard]] SHCollisionShape& GetCollisionShape (int index); + [[nodiscard]] const CollisionShapes& GetCollisionShapes () const noexcept; + [[nodiscard]] SHCollisionShape& GetCollisionShape (int index); + + /*---------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*---------------------------------------------------------------------------------*/ + + void SetDebugDrawState (bool state) noexcept; + + void SetFactory (reactphysics3d::PhysicsCommon* physicsCommon) noexcept; + void SetCollisionBody (reactphysics3d::CollisionBody* body) noexcept; + + void SetTransform (const SHTransform& newTransform) noexcept; + void SetPosition (const SHVec3& newPosition) noexcept; + void SetOrientation (const SHQuaternion& newOrientation) noexcept; + void SetScale (const SHVec3& newScale) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - void OnCreate () override; - void OnDestroy () override; + /** + * @brief + * Computes the TRS for the collider's transform + * @return + * The computed TRS. + */ + const SHMatrix& ComputeTRS() noexcept; - void RecomputeCollisionShapes () noexcept; + /** + * @brief + * Adds a sphere collision shape. + * @param relativeRadius + * The relative radius is constructed with respect to the world scale.
+ * Radius = max(scale.x, scale.y, scale.z) * 0.5 * relativeRadius + * @param posOffset + * The position offset of the sphere from the center of the collider. Defaults to a Zero Vector. + * @param rotOffset + * The rotation offset of the sphere from the rotation of the collider. Defaults to a Zero Vector. + * @return + * The index of the newly added shape. + */ + int AddSphereCollisionShape (float relativeRadius, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero); - void RemoveCollider (int index); + /** + * @brief + * Adds a box collision shape. + * @param relativeExtents + * The relative extents are constructed with respect to the world scale.
+ * Extents = scale * 0.5 * relativeExtents + * @param posOffset + * The position offset of the box from the center of the collider. Defaults to a Zero Vector. + * @param rotOffset + * The rotation offset of the box from the rotation of the collider. Defaults to a Zero Vector. + * @return + * The index of the newly added shape. + */ + int AddBoxCollisionShape (const SHVec3& relativeExtents, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero); - int AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero) noexcept; - int AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept; + /** + * @brief + * Removes a shape from the container. Removal reduces the size of the container. + * If removing all, perform removal from back to front. + * @param index + * The index of the shape to remove. + * @throws + * Invalid argument for out-of-range indices. + */ + void RemoveCollisionShape (int index); + + /** + * @brief + * Recomputes the transforms for all shapes in this composite collider. + */ + void Update () noexcept; private: @@ -97,12 +162,15 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - SHPhysicsSystem* system; + static constexpr uint8_t ACTIVE_FLAG = 1U << 0; + static constexpr uint8_t DRAW_FLAG = 1U << 1; + static constexpr uint8_t MOVED_FLAG = 1U << 2; - SHVec3 position; - SHQuaternion orientation; - SHVec3 scale; - CollisionShapes collisionShapes; + uint8_t flags; // 0 0 0 0 0 hasMoved debugDraw active + reactphysics3d::PhysicsCommon* factory; + reactphysics3d::CollisionBody* collisionBody; + SHTransform transform; + CollisionShapes shapes; RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp deleted file mode 100644 index f597077f..00000000 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************************** - * \file SHCollider.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Collider. - * - * \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 "SHCollisionShape.h" -// Project Headers -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "Math/SHMathHelpers.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" -#include "Reflection/SHReflectionMetadata.h" -#include "SHColliderComponent.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial) - : type { colliderType } - , entityID { eid } - , isTrigger { false } - , dirty { true } - , shape { nullptr } - , material { physicsMaterial } - , collisionTag { SHCollisionTagMatrix::GetTag(0) } - { - switch (type) - { - case Type::BOX: - { - shape = new SHBox{ SHVec3::Zero, SHVec3::One }; - break; - } - case Type::SPHERE: - { - shape = new SHSphere{ SHVec3::Zero, 0.5f }; - break; - } - default: break; - } - } - - SHCollisionShape::SHCollisionShape(const SHCollisionShape& rhs) noexcept - : type { rhs.type} - , entityID { rhs.entityID } - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - , material { rhs.material } - , positionOffset { rhs.positionOffset } - , rotationOffset { rhs.rotationOffset } - , collisionTag { rhs.collisionTag } - { - CopyShape(rhs.shape); - } - - SHCollisionShape::SHCollisionShape(SHCollisionShape&& rhs) noexcept - : type { rhs.type} - , entityID { rhs.entityID } - , isTrigger { rhs.isTrigger } - , dirty { true } - , shape { nullptr } - , material { rhs.material } - , positionOffset { rhs.positionOffset } - , rotationOffset { rhs.rotationOffset } - , collisionTag { rhs.collisionTag } - { - CopyShape(rhs.shape); - } - - SHCollisionShape::~SHCollisionShape() noexcept - { - shape = nullptr; - } - - /*-----------------------------------------------------------------------------------*/ - /* Operator Overload Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHCollisionShape& SHCollisionShape::operator=(const SHCollisionShape& rhs) noexcept - { - if (this == &rhs) - return *this; - - type = rhs.type; - entityID = rhs.entityID; - isTrigger = rhs.isTrigger; - dirty = true; - material = rhs.material; - positionOffset = rhs.positionOffset; - rotationOffset = rhs.rotationOffset; - collisionTag = rhs.collisionTag; - - delete shape; - CopyShape(rhs.shape); - - return *this; - } - - SHCollisionShape& SHCollisionShape::operator=(SHCollisionShape&& rhs) noexcept - { - type = rhs.type; - entityID = rhs.entityID; - isTrigger = rhs.isTrigger; - dirty = true; - material = rhs.material; - positionOffset = rhs.positionOffset; - rotationOffset = rhs.rotationOffset; - collisionTag = rhs.collisionTag; - - delete shape; - CopyShape(rhs.shape); - - return *this; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - bool SHCollisionShape::HasChanged() const noexcept - { - return dirty; - } - - bool SHCollisionShape::IsTrigger() const noexcept - { - return isTrigger; - } - - SHCollisionShape::Type SHCollisionShape::GetType() const noexcept - { - return type; - } - - const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept - { - return *collisionTag; - } - - float SHCollisionShape::GetFriction() const noexcept - { - return material.GetFriction(); - } - - float SHCollisionShape::GetBounciness() const noexcept - { - return material.GetBounciness(); - } - - float SHCollisionShape::GetDensity() const noexcept - { - return material.GetDensity(); - } - - const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept - { - return material; - } - - const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept - { - return positionOffset; - } - - const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept - { - return rotationOffset; - } - - const SHShape* SHCollisionShape::GetShape() const noexcept - { - return shape; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents) - { - dirty = true; - - const auto* COLLIDER = SHComponentManager::GetComponent(entityID); - auto* box = reinterpret_cast(shape); - - SHVec3 correctedHalfExtents = halfExtents; - - // Get current relative halfExtents for error checking. 0 is ignored - const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents(); - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - if (SHMath::CompareFloat(halfExtents[i], 0.0f)) - correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i]; - } - - // Set the half extents relative to world scale - const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f; - - if (type != Type::BOX) - { - type = Type::BOX; - - delete shape; - shape = new SHBox{ positionOffset, WORLD_EXTENTS }; - } - - box->SetWorldExtents(WORLD_EXTENTS); - box->SetRelativeExtents(correctedHalfExtents); - } - - void SHCollisionShape::SetBoundingSphere(float radius) - { - dirty = true; - - auto* sphere = reinterpret_cast(shape); - const auto* COLLIDER = SHComponentManager::GetComponent(entityID); - - // Get current relative halfExtents for error checking. 0 is ignored - const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius(); - if (SHMath::CompareFloat(radius, 0.0f)) - radius = CURRENT_RELATIVE_RADIUS; - - // Set the radius relative to world scale - const SHVec3 WORLD_SCALE = COLLIDER->GetScale(); - const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z }); - const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f; - - if (type != Type::SPHERE) - { - type = Type::SPHERE; - - delete shape; - shape = new SHSphere{ positionOffset, WORLD_RADIUS }; - } - - sphere->SetWorldRadius(WORLD_RADIUS); - sphere->SetRelativeRadius(radius); - } - - void SHCollisionShape::SetIsTrigger(bool trigger) noexcept - { - dirty = true; - isTrigger = trigger; - } - - void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept - { - dirty = true; - collisionTag = newCollisionTag; - } - - void SHCollisionShape::SetFriction(float friction) noexcept - { - dirty = true; - material.SetFriction(friction); - } - - void SHCollisionShape::SetBounciness(float bounciness) noexcept - { - dirty = true; - material.SetBounciness(bounciness); - } - - void SHCollisionShape::SetDensity(float density) noexcept - { - dirty = true; - material.SetDensity(density); - } - - void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept - { - dirty = true; - material = newMaterial; - } - - void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept - { - dirty = true; - positionOffset = posOffset; - - switch (type) - { - case Type::BOX: - { - reinterpret_cast(shape)->SetCenter(positionOffset); - break; - } - case Type::SPHERE: - { - reinterpret_cast(shape)->SetCenter(positionOffset); - break; - } - default: break; - } - } - - void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept - { - dirty = true; - rotationOffset = rotOffset; - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHCollisionShape::CopyShape(const SHShape* rhs) - { - switch (type) - { - case Type::BOX: - { - const auto* RHS_BOX = reinterpret_cast(rhs); - - shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() }; - auto* lhsBox = reinterpret_cast(shape); - lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents()); - - break; - } - case Type::SPHERE: - { - const auto* RHS_SPHERE = reinterpret_cast(rhs); - - shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() }; - auto* lhsSphere = reinterpret_cast(shape); - lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius()); - - break; - } - default: break; - } - } - -} // namespace SHADE - -RTTR_REGISTRATION -{ - using namespace SHADE; - using namespace rttr; - - registration::enumeration("Collider Type") - ( - value("Box", SHCollisionShape::Type::BOX), - value("Sphere", SHCollisionShape::Type::SPHERE) - // TODO(Diren): Add More Shapes - ); - - registration::class_("Collider") - .property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger ) - .property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction ) - .property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness ) - .property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity ) - .property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset) - .property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true)); -} \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h b/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h deleted file mode 100644 index 597814a6..00000000 --- a/SHADE_Engine/src/Physics/Interface/SHCollisionShape.h +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************************** - * \file SHCollider.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Collider. - * - * \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 - -// Project Headers -#include "ECS_Base/Entity/SHEntity.h" -#include "Math/Geometry/SHShape.h" -#include "Math/SHQuaternion.h" -#include "SHPhysicsMaterial.h" -#include "Physics/Collision/SHCollisionTags.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------------*/ - - class SH_API SHCollisionShape - { - private: - - /*---------------------------------------------------------------------------------*/ - /* Friends */ - /*---------------------------------------------------------------------------------*/ - - friend class SHColliderComponent; - friend class SHPhysicsObject; - - public: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - enum class Type - { - BOX - , SPHERE - , CAPSULE - }; - - /*---------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*---------------------------------------------------------------------------------*/ - - SHCollisionShape (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT); - - SHCollisionShape (const SHCollisionShape& rhs) noexcept; - SHCollisionShape (SHCollisionShape&& rhs) noexcept; - ~SHCollisionShape () noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - - SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept; - SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Getter Functions */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] bool HasChanged () const noexcept; - - [[nodiscard]] bool IsTrigger () const noexcept; - - [[nodiscard]] Type GetType () const noexcept; - - [[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept; - - [[nodiscard]] float GetFriction () const noexcept; - [[nodiscard]] float GetBounciness () const noexcept; - [[nodiscard]] float GetDensity () const noexcept; - [[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept; - - [[nodiscard]] const SHVec3& GetPositionOffset () const noexcept; - [[nodiscard]] const SHVec3& GetRotationOffset () const noexcept; - - [[nodiscard]] const SHShape* GetShape () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetBoundingBox (const SHVec3& halfExtents); - void SetBoundingSphere (float radius); - - void SetIsTrigger (bool isTrigger) noexcept; - void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; - void SetFriction (float friction) noexcept; - void SetBounciness (float bounciness) noexcept; - void SetDensity (float density) noexcept; - void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; - - void SetPositionOffset (const SHVec3& posOffset) noexcept; - void SetRotationOffset (const SHVec3& rotOffset) noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - Type type; - EntityID entityID; // The entity this collider belongs to - bool isTrigger; - bool dirty; - - SHShape* shape; - SHPhysicsMaterial material; - - SHVec3 positionOffset; - SHVec3 rotationOffset; - - SHCollisionTag* collisionTag; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void CopyShape(const SHShape* rhs); - - RTTR_ENABLE() - }; - -} // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index 330c3abe..a374665d 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -20,6 +20,7 @@ #include "ECS_Base/Managers/SHSystemManager.h" #include "Math/SHMathHelpers.h" #include "Physics/System/SHPhysicsSystem.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { @@ -29,99 +30,78 @@ namespace SHADE SHRigidBodyComponent::SHRigidBodyComponent() noexcept : type { Type::DYNAMIC } + , interpolate { true } , flags { 0 } - , dirtyFlags { std::numeric_limits::max() } - , mass { 1.0f } , drag { 0.01f } - , angularDrag { 0.01f } - , system { nullptr } + , angularDrag { 0.1f } + , rigidBody { nullptr } { - // Initialise default flags - flags |= 1U << 0; // Gravity set to true - flags |= 1U << 1; // Sleeping allowed - flags |= 1U << 8; // Interpolate by default + // Default flags + flags |= 1U << 0; // enable gravity } /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHRigidBodyComponent::IsGravityEnabled() const noexcept - { - static constexpr int FLAG_POS = 0; - return flags & (1U << FLAG_POS); - } - - bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept - { - static constexpr int FLAG_POS = 1; - return flags & (1U << FLAG_POS); - } - - bool SHRigidBodyComponent::IsInterpolating() const noexcept - { - static constexpr int FLAG_POS = 8; - return flags & (1U << FLAG_POS); - } - - bool SHRigidBodyComponent::GetIsSleeping() const noexcept - { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - return physicsObject->GetRigidBody()->isSleeping(); - - return false; - } - SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept { return type; } + bool SHRigidBodyComponent::IsGravityEnabled() const noexcept + { + return flags & SHUtilities::ConvertEnum(Flags::GRAVITY); + } + + bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept + { + return flags & SHUtilities::ConvertEnum(Flags::SLEEPING); + } + + bool SHRigidBodyComponent::IsInterpolating() const noexcept + { + return interpolate; + } + + bool SHRigidBodyComponent::IsSleeping() const noexcept + { + return rigidBody ? rigidBody->isSleeping() : false; + } + bool SHRigidBodyComponent::GetFreezePositionX() const noexcept { - static constexpr int FLAG_POS = 2; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::LINEAR_X); } bool SHRigidBodyComponent::GetFreezePositionY() const noexcept { - static constexpr int FLAG_POS = 3; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::LINEAR_Y); } bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept { - static constexpr int FLAG_POS = 4; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::LINEAR_Z); } bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept { - static constexpr int FLAG_POS = 5; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_X); } bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept { - static constexpr int FLAG_POS = 6; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_Y); } bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept { - static constexpr int FLAG_POS = 7; - return flags & (1U << FLAG_POS); + return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_Z); } - //bool SHRigidBodyComponent::GetAutoMass() const noexcept - //{ - // static constexpr int FLAG_POS = 9; - // return flags & (1U << FLAG_POS); - //} - - float SHRigidBodyComponent::GetMass() const noexcept + float SHRigidBodyComponent::GetMass() const noexcept { - return mass; + return rigidBody ? rigidBody->getMass() : 0.0f; } float SHRigidBodyComponent::GetDrag() const noexcept @@ -136,49 +116,32 @@ namespace SHADE SHVec3 SHRigidBodyComponent::GetForce() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - return physicsObject->GetRigidBody()->getForce(); - - return SHVec3::Zero; + return rigidBody ? SHVec3{ rigidBody->getForce() } : SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetTorque() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - return physicsObject->GetRigidBody()->getTorque(); - - return SHVec3::Zero; + return rigidBody ? SHVec3{ rigidBody->getTorque() } : SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - return physicsObject->GetRigidBody()->getLinearVelocity(); - - return SHVec3::Zero; + return rigidBody ? SHVec3{ rigidBody->getLinearVelocity() } : SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - return physicsObject->GetRigidBody()->getAngularVelocity(); - - return SHVec3::Zero; + return rigidBody ? SHVec3{ rigidBody->getAngularVelocity() } : SHVec3::Zero; } - const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept + SHVec3 SHRigidBodyComponent::GetPosition() const noexcept { - return position; - } - - const SHQuaternion& SHRigidBodyComponent::GetOrientation() const noexcept - { - return orientation; + return rigidBody ? SHVec3{ rigidBody->getTransform().getPosition() } : SHVec3::Zero; } SHVec3 SHRigidBodyComponent::GetRotation() const noexcept { - return orientation.ToEuler(); + return rigidBody ? SHQuaternion{ rigidBody->getTransform().getOrientation() }.ToEuler() : SHVec3::Zero; } /*-----------------------------------------------------------------------------------*/ @@ -187,224 +150,174 @@ namespace SHADE void SHRigidBodyComponent::SetType(Type newType) noexcept { - static constexpr int FLAG_POS = 8; - if (type == newType) return; type = newType; - dirtyFlags |= 1U << FLAG_POS; + + SHASSERT(rigidBody, "Unable to find rp3dBody on RigidBodyComponent!") + + switch (type) + { + case Type::STATIC: + rigidBody->setType(rp3d::BodyType::STATIC); + break; + case Type::KINEMATIC: + rigidBody->setType(rp3d::BodyType::KINEMATIC); + break; + case Type::DYNAMIC: + rigidBody->setType(rp3d::BodyType::DYNAMIC); + break; + default: + break; + } } + void SHRigidBodyComponent::SetRigidBody(rp3d::RigidBody* body) noexcept + { + rigidBody = body; + } + + void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept { - static constexpr int FLAG_POS = 0; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::GRAVITY); + enableGravity ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type != Type::DYNAMIC) - { - SHLOG_WARNING("Cannot enable gravity of a non-dynamic object {}", GetEID()) - return; - } - - dirtyFlags |= 1U << FLAG_POS; - enableGravity ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); + if (rigidBody) + rigidBody->enableGravity(enableGravity); } void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept { - static constexpr int FLAG_POS = 1; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::SLEEPING); + isAllowedToSleep ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type != Type::DYNAMIC) - { - SHLOG_WARNING("Cannot enable sleeping of a non-dynamic object {}", GetEID()) - return; - } - - dirtyFlags |= 1U << FLAG_POS; - isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); + if (rigidBody) + rigidBody->setIsAllowedToSleep(isAllowedToSleep); } void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept { - static constexpr int FLAG_POS = 2; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_X); + freezePositionX ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor(); + linearLock.x = freezePositionX ? 0.0f : 1.0f; + rigidBody->setLinearLockAxisFactor(linearLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept { - static constexpr int FLAG_POS = 3; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_Y); + freezePositionY ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor(); + linearLock.y = freezePositionY ? 0.0f : 1.0f; + rigidBody->setLinearLockAxisFactor(linearLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept { - static constexpr int FLAG_POS = 4; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_Z); + freezePositionZ ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor(); + linearLock.z = freezePositionZ ? 0.0f : 1.0f; + rigidBody->setLinearLockAxisFactor(linearLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept { - static constexpr int FLAG_POS = 5; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_X); + freezeRotationX ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor(); + angularLock.x = freezeRotationX ? 0.0f : 1.0f; + rigidBody->setAngularLockAxisFactor(angularLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept { - static constexpr int FLAG_POS = 6; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_Y); + freezeRotationY ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor(); + angularLock.y = freezeRotationY ? 0.0f : 1.0f; + rigidBody->setAngularLockAxisFactor(angularLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept { - static constexpr int FLAG_POS = 7; + constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_Z); + freezeRotationZ ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - if (type == Type::STATIC) + if (rigidBody) { - SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID()) - return; + rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor(); + angularLock.z = freezeRotationZ ? 0.0f : 1.0f; + rigidBody->setAngularLockAxisFactor(angularLock); } - - dirtyFlags |= 1U << FLAG_POS; - freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); } void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept { - static constexpr int FLAG_POS = 8; - allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); + interpolate = allowInterpolation; } - //void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept - //{ - // static constexpr int FLAG_POS = 9; - // autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS); - - // dirtyFlags |= 1U << FLAG_POS; - //} - - //void SHRigidBodyComponent::SetMass(float newMass) noexcept - //{ - // static constexpr int FLAG_POS = 9; - - // if (newMass < 0.0f) - // return; - - // if (type != Type::DYNAMIC) - // { - // SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID()) - // return; - // } - - // dirtyFlags |= 1U << FLAG_POS; - // mass = newMass; - - // // Turn off automass - // flags &= ~(1U << FLAG_POS); - //} - void SHRigidBodyComponent::SetDrag(float newDrag) noexcept { - static constexpr int FLAG_POS = 10; - - if (type != Type::DYNAMIC) - { - SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID()) - return; - } - - dirtyFlags |= 1U << FLAG_POS; drag = newDrag; + + if (rigidBody) + rigidBody->setLinearDamping(newDrag); } void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept { - static constexpr int FLAG_POS = 11; - - if (type != Type::DYNAMIC) - { - SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID()) - return; - } - - dirtyFlags |= 1U << FLAG_POS; angularDrag = newAngularDrag; + + if (rigidBody) + rigidBody->setAngularDamping(newAngularDrag); } void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept { - if (type == Type::STATIC) { SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID()) return; } - auto* physicsObject = system->GetPhysicsObject(GetEID()); - if (!physicsObject) - { - SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID()) - return; - } - physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity); + if (rigidBody) + rigidBody->setLinearVelocity(newLinearVelocity); } void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept { - static constexpr int FLAG_POS = 13; - if (type == Type::STATIC) { SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID()) return; } - auto* physicsObject = system->GetPhysicsObject(GetEID()); - if (!physicsObject) - { - SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID()) - return; - } - physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity); + if (rigidBody) + rigidBody->setAngularVelocity(newAngularVelocity); } /*-----------------------------------------------------------------------------------*/ @@ -413,81 +326,67 @@ namespace SHADE void SHRigidBodyComponent::OnCreate() { - auto* physicsSystem = SHSystemManager::GetSystem(); - if (!physicsSystem) - { - SHLOG_ERROR("Physics System does not exist to link with Physics Components!") - return; - } - system = physicsSystem; - - // Sync with transform if one already exists - if (auto* transformComponent = SHComponentManager::GetComponent_s(GetEID()); transformComponent) - { - position = transformComponent->GetWorldPosition(); - orientation = transformComponent->GetWorldOrientation(); - } } void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyWorldForceAtCenterOfMass(force); + if (rigidBody) + rigidBody->applyWorldForceAtCenterOfMass(force); } void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos); + if (rigidBody) + rigidBody->applyWorldForceAtLocalPosition(force, localPos); } void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos); + if (rigidBody) + rigidBody->applyWorldForceAtWorldPosition(force, worldPos); } void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce); + if (rigidBody) + rigidBody->applyLocalForceAtCenterOfMass(relativeForce); } void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos); + if (rigidBody) + rigidBody->applyLocalForceAtLocalPosition(relativeForce, localPos); } void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos); + if (rigidBody) + rigidBody->applyLocalForceAtWorldPosition(relativeForce, worldPos); } void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyWorldTorque(torque); + if (rigidBody) + rigidBody->applyWorldTorque(torque); } void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->applyLocalTorque(relativeTorque); + if (rigidBody) + rigidBody->applyLocalTorque(relativeTorque); } void SHRigidBodyComponent::ClearForces() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->resetForce(); + if (rigidBody) + rigidBody->resetForce(); } void SHRigidBodyComponent::ClearTorque() const noexcept { - if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) - physicsObject->GetRigidBody()->resetTorque(); + if (rigidBody) + rigidBody->resetTorque(); } } // namespace SHADE @@ -506,13 +405,11 @@ RTTR_REGISTRATION registration::class_("RigidBody Component") .property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType ) - //.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass ) .property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag ) .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate ) .property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep) - //.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass ) .property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX ) .property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY ) .property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ ) diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index 532b3312..5fe49dbe 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -17,6 +17,15 @@ #include "Math/Vector/SHVec3.h" #include "Math/SHQuaternion.h" +/*-------------------------------------------------------------------------------------*/ +/* Forward Declarations */ +/*-------------------------------------------------------------------------------------*/ + +namespace reactphysics3d +{ + class RigidBody; +} + namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -31,7 +40,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; - friend class SHPhysicsObject; + friend class SHPhysicsObjectManager; public: /*---------------------------------------------------------------------------------*/ @@ -67,35 +76,31 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool IsGravityEnabled () const noexcept; - [[nodiscard]] bool IsAllowedToSleep () const noexcept; - [[nodiscard]] bool IsInterpolating () const noexcept; + [[nodiscard]] Type GetType () const noexcept; - [[nodiscard]] bool GetIsSleeping () const noexcept; + [[nodiscard]] bool IsGravityEnabled () const noexcept; + [[nodiscard]] bool IsAllowedToSleep () const noexcept; + [[nodiscard]] bool IsInterpolating () const noexcept; + [[nodiscard]] bool IsSleeping () const noexcept; - [[nodiscard]] Type GetType () const noexcept; + [[nodiscard]] bool GetFreezePositionX () const noexcept; + [[nodiscard]] bool GetFreezePositionY () const noexcept; + [[nodiscard]] bool GetFreezePositionZ () const noexcept; + [[nodiscard]] bool GetFreezeRotationX () const noexcept; + [[nodiscard]] bool GetFreezeRotationY () const noexcept; + [[nodiscard]] bool GetFreezeRotationZ () const noexcept; - [[nodiscard]] bool GetFreezePositionX () const noexcept; - [[nodiscard]] bool GetFreezePositionY () const noexcept; - [[nodiscard]] bool GetFreezePositionZ () const noexcept; - [[nodiscard]] bool GetFreezeRotationX () const noexcept; - [[nodiscard]] bool GetFreezeRotationY () const noexcept; - [[nodiscard]] bool GetFreezeRotationZ () const noexcept; + [[nodiscard]] float GetMass () const noexcept; + [[nodiscard]] float GetDrag () const noexcept; + [[nodiscard]] float GetAngularDrag () const noexcept; - //[[nodiscard]] bool GetAutoMass () const noexcept; + [[nodiscard]] SHVec3 GetForce () const noexcept; + [[nodiscard]] SHVec3 GetTorque () const noexcept; + [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; + [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept; - [[nodiscard]] float GetMass () const noexcept; - [[nodiscard]] float GetDrag () const noexcept; - [[nodiscard]] float GetAngularDrag () const noexcept; - - [[nodiscard]] SHVec3 GetForce () const noexcept; - [[nodiscard]] SHVec3 GetTorque () const noexcept; - [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; - [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept; - - [[nodiscard]] const SHVec3& GetPosition () const noexcept; - [[nodiscard]] const SHQuaternion& GetOrientation () const noexcept; - [[nodiscard]] SHVec3 GetRotation () const noexcept; + [[nodiscard]] SHVec3 GetPosition () const noexcept; + [[nodiscard]] SHVec3 GetRotation () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ @@ -103,8 +108,11 @@ namespace SHADE void SetType (Type newType) noexcept; + void SetRigidBody (reactphysics3d::RigidBody* body) noexcept; + void SetGravityEnabled (bool enableGravity) noexcept; void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept; + void SetFreezePositionX (bool freezePositionX) noexcept; void SetFreezePositionY (bool freezePositionY) noexcept; void SetFreezePositionZ (bool freezePositionZ) noexcept; @@ -112,9 +120,7 @@ namespace SHADE void SetFreezeRotationY (bool freezeRotationY) noexcept; void SetFreezeRotationZ (bool freezeRotationZ) noexcept; void SetInterpolate (bool allowInterpolation) noexcept; - //void SetAutoMass (bool autoMass) noexcept; - //void SetMass (float newMass) noexcept; void SetDrag (float newDrag) noexcept; void SetAngularDrag (float newAngularDrag) noexcept; @@ -140,29 +146,42 @@ namespace SHADE void ClearTorque () const noexcept; private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + enum class Flags : uint8_t + { + GRAVITY = 0x0 + , SLEEPING = 0x1 + , LINEAR_X = 0x2 + , LINEAR_Y = 0x4 + , LINEAR_Z = 0x8 + , ANGULAR_X = 0x10 + , ANGULAR_Y = 0x20 + , ANGULAR_Z = 0x30 + }; + /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - static constexpr size_t NUM_FLAGS = 8; - static constexpr size_t NUM_DIRTY_FLAGS = 12; + static constexpr size_t NUM_FLAGS = 8; - Type type; + Type type; + bool interpolate; - uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g - uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g + // Used for storing serialised data + uint8_t flags; // aZ aY aX lZ lY lX sleepEnabled gravity + float drag; + float angularDrag; - float mass; - float drag; - float angularDrag; + // For interpolation - SHVec3 linearVelocity; - SHVec3 angularVelocity; + SHVec3 position; + SHQuaternion orientation; - SHPhysicsSystem* system; - - SHVec3 position; - SHQuaternion orientation; + reactphysics3d::RigidBody* rigidBody; RTTR_ENABLE() }; diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp deleted file mode 100644 index 71b08831..00000000 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsObject.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Physics Object. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#include - -// Primary Header -#include "SHPhysicsObject.h" - -// Project Headers -#include "ECS_Base/Managers/SHSystemManager.h" -#include "ECS_Base/Managers/SHComponentManager.h" -#include "Scene/SHSceneManager.h" - - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept - : entityID { eid } - , collidersActive { true } - , factory { physicsFactory } - , world { physicsWorld } - , rp3dBody { nullptr } - { - // Implicitly create a static body. - - const auto* TRANSFORM = SHComponentManager::GetComponent(eid); - - const rp3d::Transform RP3D_TRANSFORM { TRANSFORM->GetWorldPosition(), TRANSFORM->GetWorldOrientation() }; - - rp3dBody = world->createRigidBody(RP3D_TRANSFORM); - rp3dBody->setType(rp3d::BodyType::STATIC); - } - - SHPhysicsObject::~SHPhysicsObject() noexcept - { - factory = nullptr; - world = nullptr; - rp3dBody = nullptr; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHVec3 SHPhysicsObject::GetPosition() const noexcept - { - return rp3dBody->getTransform().getPosition(); - } - - SHQuaternion SHPhysicsObject::GetOrientation() const noexcept - { - return rp3dBody->getTransform().getOrientation(); - } - - SHVec3 SHPhysicsObject::GetRotation() const noexcept - { - return SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler(); - } - - rp3d::CollisionBody* SHPhysicsObject::GetCollisionBody() const noexcept - { - return rp3dBody; - } - - rp3d::RigidBody* SHPhysicsObject::GetRigidBody() const noexcept - { - return rp3dBody; - } - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsObject::SetStaticBody() const noexcept - { - if (!rp3dBody) - return; - - rp3dBody->setType(rp3d::BodyType::STATIC); - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - int SHPhysicsObject::AddCollisionShape(int index) - { - // Get collider component - auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - if (!colliderComponent) - { - SHLOGV_ERROR("Unable to add Collision Shape to Entity {} due to Missing Collider Component!", entityID) - return -1; - } - - auto& collisionShape = colliderComponent->GetCollisionShape(index); - switch (collisionShape.GetType()) - { - // TODO(Diren): Add more collider shapes - - case SHCollisionShape::Type::BOX: - { - addBoxShape(collisionShape); - break; - } - - case SHCollisionShape::Type::SPHERE: - { - addSphereShape(collisionShape); - break; - } - default: break; - } - - auto* rp3dCollider = rp3dBody->getCollider(rp3dBody->getNbColliders() - 1); - syncColliderProperties(collisionShape, rp3dCollider); - - if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC) - { - rp3dBody->updateMassPropertiesFromColliders(); - - if (auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); rigidBodyComponent) - rigidBodyComponent->mass = rp3dBody->getMass(); - } - - return index; - } - - void SHPhysicsObject::RemoveCollisionShape(int index) - { - const int NUM_COLLIDERS = static_cast(rp3dBody->getNbColliders()); - if (NUM_COLLIDERS == 0) - return; - - if (index < 0 || index >= NUM_COLLIDERS) - throw std::invalid_argument("Index out of range!"); - - auto* collider = rp3dBody->getCollider(index); - rp3dBody->removeCollider(collider); - - if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC) - { - rp3dBody->updateMassPropertiesFromColliders(); - - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - if (rigidBodyComponent) - rigidBodyComponent->mass = rp3dBody->getMass(); - } - } - - void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept - { - int numColliders = static_cast(rp3dBody->getNbColliders()); - if (numColliders == 0) - return; - - while (numColliders - 1 >= 0) - { - auto* collider = rp3dBody->getCollider(numColliders - 1); - rp3dBody->removeCollider(collider); - - --numColliders; - } - } - - void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept - { - // This state is synced in the pre-update routine - if (!rp3dBody->isActive()) - return; - - if (component.dirtyFlags == 0) - return; - - for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i) - { - if (const bool IS_DIRTY = component.dirtyFlags & (1U << i); IS_DIRTY) - { - switch (i) - { - case 0: // Gravity - { - const bool IS_ENABLED = component.flags & (1U << i); - rp3dBody->enableGravity(IS_ENABLED); - - break; - } - case 1: // Sleeping - { - const bool IS_ENABLED = component.flags & (1U << i); - rp3dBody->setIsAllowedToSleep(IS_ENABLED); - - break; - } - case 2: // Lock Position X - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto positionLock = rp3dBody->getLinearLockAxisFactor(); - positionLock.x = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(positionLock); - - break; - } - case 3: // Lock Position Y - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto positionLock = rp3dBody->getLinearLockAxisFactor(); - positionLock.y = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(positionLock); - - break; - } - case 4: // Lock Position Z - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto positionLock = rp3dBody->getLinearLockAxisFactor(); - positionLock.z = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setLinearLockAxisFactor(positionLock); - - break; - } - case 5: // Lock Rotation X - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto rotationLock = rp3dBody->getAngularLockAxisFactor(); - rotationLock.x = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(rotationLock); - - break; - } - case 6: // Lock Rotation Y - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto rotationLock = rp3dBody->getAngularLockAxisFactor(); - rotationLock.y = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(rotationLock); - - break; - } - case 7: // Lock Rotation Z - { - const bool IS_ENABLED = component.flags & (1U << i); - - auto rotationLock = rp3dBody->getAngularLockAxisFactor(); - rotationLock.z = IS_ENABLED ? 0.0f : 1.0f; - rp3dBody->setAngularLockAxisFactor(rotationLock); - - break; - } - case 8: // Type - { - rp3dBody->setType(static_cast(component.type)); - - break; - } - case 9: // Mass - { - //rp3dBody->setMass(component.mass); - - //if (component.GetAutoMass()) - //{ - // rp3dBody->updateMassPropertiesFromColliders(); - // component.mass = rp3dBody->getMass(); - //} - //else - //{ - // rp3dBody->setMass(component.mass); - // rp3dBody->updateLocalCenterOfMassFromColliders(); - // rp3dBody->updateLocalInertiaTensorFromColliders(); - //} - - break; - } - case 10: // Drag - { - rp3dBody->setLinearDamping(component.drag); - - break; - } - case 11: // Angular Drag - { - rp3dBody->setAngularDamping(component.angularDrag); - - break; - } - default: break; - } - } - } - - component.dirtyFlags = 0; - } - - void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept - { - // This state is synced in the pre-update routine - if (!rp3dBody->isActive()) - return; - - const int NUM_SHAPES = static_cast(rp3dBody->getNbColliders()); - for (int i = 0; i < NUM_SHAPES; ++i) - { - auto& collisionShape = component.collisionShapes[i]; - - if (!collisionShape.dirty) - continue; - - switch (collisionShape.GetType()) - { - case SHCollisionShape::Type::BOX: syncBoxShape(i, collisionShape); break; - case SHCollisionShape::Type::SPHERE: syncSphereShape(i, collisionShape); break; - default: break; - } - - auto* rp3dCollider = rp3dBody->getCollider(i); - syncColliderProperties(collisionShape, rp3dCollider); - - collisionShape.dirty = false; - } - - // Set rigidbody mass if dynamic - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - if (rigidBodyComponent) - { - // This is generally expensive, will be optimised in the future with my own engine. - rp3dBody->updateMassPropertiesFromColliders(); - rigidBodyComponent->mass = rp3dBody->getMass(); - } - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsObject::syncColliderProperties(const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept - { - rp3dCollider->setIsTrigger(collisionShape.IsTrigger()); - - auto& rp3dMaterial = rp3dCollider->getMaterial(); - - rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction()); - rp3dMaterial.setBounciness(collisionShape.GetBounciness()); - rp3dMaterial.setMassDensity(collisionShape.GetDensity()); - - const unsigned short MASK_BITS = collisionShape.GetCollisionTag(); - rp3dCollider->setCollisionCategoryBits(MASK_BITS); - rp3dCollider->setCollideWithMaskBits(MASK_BITS); - } - - void SHPhysicsObject::addBoxShape(const SHCollisionShape& boxShape) const noexcept - { - const rp3d::Transform OFFSETS - { - boxShape.GetPositionOffset() - , boxShape.GetRotationOffset() - }; - - const auto* BOX = reinterpret_cast(boxShape.GetShape()); - rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents()); - - rp3dBody->addCollider(newBox, OFFSETS); - } - - void SHPhysicsObject::syncBoxShape(int index, const SHCollisionShape& boxShape) const noexcept - { - const auto* BOX = reinterpret_cast(boxShape.GetShape()); - - auto* rp3dCollider = rp3dBody->getCollider(index); - auto* rp3dBox = reinterpret_cast(rp3dCollider->getCollisionShape()); - - const rp3d::Transform OFFSETS - { - boxShape.GetPositionOffset() - , boxShape.GetRotationOffset() - }; - - rp3dCollider->setIsTrigger(boxShape.IsTrigger()); - rp3dCollider->setLocalToBodyTransform(OFFSETS); - - rp3dBox->setHalfExtents(BOX->GetWorldExtents()); - } - - void SHPhysicsObject::addSphereShape(const SHCollisionShape& sphereShape) const noexcept - { - const rp3d::Transform OFFSETS - { - sphereShape.GetPositionOffset() - , sphereShape.GetRotationOffset() - }; - - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); - rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius()); - - rp3dBody->addCollider(newSphere, OFFSETS); - } - - void SHPhysicsObject::syncSphereShape(int index, const SHCollisionShape& sphereShape) const noexcept - { - const auto* SPHERE = reinterpret_cast(sphereShape.GetShape()); - - auto* rp3dCollider = rp3dBody->getCollider(index); - auto* rp3dSphere = reinterpret_cast(rp3dCollider->getCollisionShape()); - - const rp3d::Transform OFFSETS - { - sphereShape.GetPositionOffset() - , sphereShape.GetRotationOffset() - }; - - rp3dCollider->setIsTrigger(sphereShape.IsTrigger()); - rp3dCollider->setLocalToBodyTransform(OFFSETS); - - rp3dSphere->setRadius(SPHERE->GetWorldRadius()); - } -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h deleted file mode 100644 index c572ca2e..00000000 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObject.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsObject.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Physics Object. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#pragma once - -#include - -// Project Headers -#include "Math/Transform/SHTransformComponent.h" -#include "Physics/Interface/SHRigidBodyComponent.h" -#include "Physics/Interface/SHColliderComponent.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------------*/ - - class SH_API SHPhysicsObject - { - private: - /*---------------------------------------------------------------------------------*/ - /* Friends */ - /*---------------------------------------------------------------------------------*/ - - friend class SHPhysicsSystem; - friend class SHPhysicsObjectManager; - - public: - /*---------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsObject (EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept; - SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default; - SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default; - virtual ~SHPhysicsObject () noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept = default; - SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept = default; - - /*---------------------------------------------------------------------------------*/ - /* Getter Functions */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] SHVec3 GetPosition () const noexcept; - [[nodiscard]] SHQuaternion GetOrientation () const noexcept; - [[nodiscard]] SHVec3 GetRotation () const noexcept; - - [[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept; - [[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetStaticBody () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - int AddCollisionShape (int index); - void RemoveCollisionShape (int index); - void RemoveAllCollisionShapes () const noexcept; - - void SyncRigidBody (SHRigidBodyComponent& component) const noexcept; - void SyncColliders (SHColliderComponent& component) const noexcept; - - private: - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - EntityID entityID; - bool collidersActive; // Only used to sync with SHADE components - - rp3d::PhysicsCommon* factory; - rp3d::PhysicsWorld* world; - - rp3d::RigidBody* rp3dBody; - rp3d::Transform prevTransform; // Cached transform for interpolation - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void syncColliderProperties (const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept; - - // Box Shapes - - void addBoxShape (const SHCollisionShape& boxShape) const noexcept; - void syncBoxShape (int index, const SHCollisionShape& boxShape) const noexcept; - - // Sphere Shapes - - void addSphereShape (const SHCollisionShape& sphereShape) const noexcept; - void syncSphereShape (int index, const SHCollisionShape& sphereShape) const noexcept; - }; -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp deleted file mode 100644 index 7c111a2d..00000000 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsObjectManager.cpp - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for a Physics Object Manager. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#include - -// Primary Header -#include "SHPhysicsObjectManager.h" - -// Project Headers -#include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/Utilities/SHUtilities.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Static Data Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[3][2] - { - addRigidBody , addCollider , addCollisionShape - , removeRigidBody , removeCollider , removeCollisionShape - }; - - /*-----------------------------------------------------------------------------------*/ - /* Setter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon& physicsFactory) noexcept - { - factory = &physicsFactory; - } - - void SHPhysicsObjectManager::SetWorld(rp3d::PhysicsWorld* physicsWorld) noexcept - { - world = physicsWorld; - } - - /*-----------------------------------------------------------------------------------*/ - /* Getter Function Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID eid) noexcept - { - const auto it = physicsObjects.find(eid); - if (it == physicsObjects.end()) - return nullptr; - - return &it->second; - } - - const SHPhysicsObjectManager::PhysicsObjectEntityMap SHPhysicsObjectManager::GetPhysicsObjects() const noexcept - { - return physicsObjects; - } - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsObjectManager::AddRigidBody(EntityID eid) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::ADD - , .component = PhysicsComponents::RIGID_BODY - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::AddCollider(EntityID eid) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::ADD - , .component = PhysicsComponents::COLLIDER - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::AddCollisionShape(EntityID eid, int shapeIndex) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::ADD - , .component = PhysicsComponents::COLLISION_SHAPE - , .shapeIndex = shapeIndex - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::RemoveRigidBody(EntityID eid) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::REMOVE - , .component = PhysicsComponents::RIGID_BODY - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::RemoveCollider(EntityID eid) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::REMOVE - , .component = PhysicsComponents::COLLIDER - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::RemoveCollisionShape(EntityID eid, int shapeIndex) noexcept - { - const QueueCommand NEW_QUEUE_COMMAND - { - .eid = eid - , .command = QueueCommand::Command::REMOVE - , .component = PhysicsComponents::COLLISION_SHAPE - , .shapeIndex = shapeIndex - }; - - commandQueue.push(NEW_QUEUE_COMMAND); - } - - void SHPhysicsObjectManager::UpdateCommands() - { - if (commandQueue.empty()) - return; - - while (!commandQueue.empty()) - { - const QueueCommand COMMAND = commandQueue.front(); - commandQueue.pop(); - - // Check validity of command - if (COMMAND.command == QueueCommand::Command::INVALID || COMMAND.component == PhysicsComponents::INVALID) - continue; - - // Get physics components - const PhysicsComponentGroup COMPONENT_GROUP - { - .eid = COMMAND.eid - , .rigidBodyComponent = SHComponentManager::GetComponent_s(COMMAND.eid) - , .colliderComponent = SHComponentManager::GetComponent_s(COMMAND.eid) - }; - - // Delete any object that is missing both components - // We infer that a remove command has been pushed for these, but we will ignore those if both components have already been removed. - if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent) - { - destroyPhysicsObject(COMMAND.eid); - wakeAllObjects(); - continue; - } - - // Find the physics Object. If none found and attempting to add, create an object. - SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid); - if (!physicsObject && COMMAND.command == QueueCommand::Command::ADD) - physicsObject = createPhysicsObject(COMMAND.eid); - - componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP); - - // If any removal was done, wake all objects - if (COMMAND.command == QueueCommand::Command::REMOVE) - wakeAllObjects(); - } - } - - void SHPhysicsObjectManager::RemoveAllObjects() - { - // Destroy all objects and clear - for (auto& physicsObject : physicsObjects | std::views::values) - { - world->destroyRigidBody(physicsObject.GetRigidBody()); - physicsObject.rp3dBody = nullptr; - } - - physicsObjects.clear(); - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept - { - // Force transforms to sync - SHVec3 worldPos = SHVec3::Zero; - SHQuaternion worldRot = SHQuaternion::Identity; - - const SHTransformComponent* TRANSFORM = nullptr; - if (SHEntityManager::IsValidEID(eid)) - TRANSFORM = SHComponentManager::GetComponent_s(eid); - - if (TRANSFORM) - { - worldPos = TRANSFORM->GetWorldPosition(); - worldRot = TRANSFORM->GetWorldOrientation(); - } - - const rp3d::Transform RP3D_TRANSFORM{ worldPos, worldRot }; - - auto& newPhysicsObject = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }).first->second; - newPhysicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - newPhysicsObject.prevTransform = RP3D_TRANSFORM; - - return &newPhysicsObject; - } - - void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept - { - const auto ITER = physicsObjects.find(eid); - if (ITER == physicsObjects.end()) - { - // Assume the object has already been successfully destroyed - return; - } - - world->destroyRigidBody(ITER->second.GetRigidBody()); - ITER->second.rp3dBody = nullptr; - - physicsObjects.erase(eid); - } - - void SHPhysicsObjectManager::addRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to add body!") - - if (!componentGroup.rigidBodyComponent) - { - SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid) - return; - } - - // A static rigid body is implicitly created on creation of a physics object. - // Nothing is needed here. - } - - void SHPhysicsObjectManager::addCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to add collider!") - - if (!componentGroup.colliderComponent) - { - SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid) - return; - } - - //const int NUM_SHAPES = static_cast(componentGroup.colliderComponent->GetCollisionShapes().size()); - //for (int i = 0; i < NUM_SHAPES; ++i) - // physicsObject->AddCollisionShape(i); - - physicsObject->SyncColliders(*componentGroup.colliderComponent); - } - - void SHPhysicsObjectManager::removeRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!") - - if (componentGroup.colliderComponent) - physicsObject->SetStaticBody(); - } - - void SHPhysicsObjectManager::removeCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!") - - physicsObject->RemoveAllCollisionShapes(); - } - - void SHPhysicsObjectManager::addCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!") - - physicsObject->AddCollisionShape(command.shapeIndex); - } - - void SHPhysicsObjectManager::removeCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&) - { - SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!") - - physicsObject->RemoveCollisionShape(command.shapeIndex); - } - - void SHPhysicsObjectManager::wakeAllObjects() noexcept - { - for (auto& physicsObject : physicsObjects | std::views::values) - physicsObject.GetRigidBody()->setIsSleeping(false); - } - - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h deleted file mode 100644 index f41c62ad..00000000 --- a/SHADE_Engine/src/Physics/PhysicsObject/SHPhysicsObjectManager.h +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsObjectManager.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Interface for a Physics Object Manager. - * - * \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or - * disclosure of this file or its contents without the prior written consent - * of DigiPen Institute of Technology is prohibited. -****************************************************************************************/ - -#pragma once - -#include -#include - -#include - -// Project Headers -#include "SHPhysicsObject.h" - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-----------------------------------------------------------------------------------*/ - - class SH_API SHPhysicsObjectManager - { - private: - /*---------------------------------------------------------------------------------*/ - /* Friends */ - /*---------------------------------------------------------------------------------*/ - - friend class SHPhysicsSystem; - - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - using PhysicsObjectEntityMap = std::unordered_map; - - public: - - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - enum class PhysicsComponents - { - RIGID_BODY - , COLLIDER - , COLLISION_SHAPE - - , TOTAL - , INVALID = -1 - }; - - /*---------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsObjectManager () = default; - ~SHPhysicsObjectManager () = default; - - SHPhysicsObjectManager (const SHPhysicsObjectManager&) = delete; - SHPhysicsObjectManager (SHPhysicsObjectManager&&) = delete; - - /*---------------------------------------------------------------------------------*/ - /* Operator Overloads */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsObjectManager& operator=(const SHPhysicsObjectManager&) = delete; - SHPhysicsObjectManager& operator=(SHPhysicsObjectManager&&) = delete; - - /*---------------------------------------------------------------------------------*/ - /* Getter Functions */ - /*---------------------------------------------------------------------------------*/ - - [[nodiscard]] SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept; - [[nodiscard]] const PhysicsObjectEntityMap GetPhysicsObjects () const noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Setter Functions */ - /*---------------------------------------------------------------------------------*/ - - void SetFactory (rp3d::PhysicsCommon& physicsFactory) noexcept; - void SetWorld (rp3d::PhysicsWorld* physicsWorld) noexcept; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - void AddRigidBody (EntityID eid) noexcept; - void AddCollider (EntityID eid) noexcept; - void AddCollisionShape (EntityID eid, int shapeIndex) noexcept; - - void RemoveRigidBody (EntityID eid) noexcept; - void RemoveCollider (EntityID eid) noexcept; - void RemoveCollisionShape (EntityID eid, int shapeIndex) noexcept; - - void UpdateCommands (); - void RemoveAllObjects (); - - private: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - - struct QueueCommand - { - /*-------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*-------------------------------------------------------------------------------*/ - - enum class Command - { - ADD - , REMOVE - - , INVALID = -1 - }; - - /*-------------------------------------------------------------------------------*/ - /* Data Members */ - /*-------------------------------------------------------------------------------*/ - - EntityID eid = MAX_EID; - Command command = Command::INVALID; - PhysicsComponents component = PhysicsComponents::INVALID; - int shapeIndex = -1; // Only used when adding & removing collision shapes - }; - - struct PhysicsComponentGroup - { - public: - - /*-------------------------------------------------------------------------------*/ - /* Data Members */ - /*-------------------------------------------------------------------------------*/ - - - EntityID eid = MAX_EID; - SHRigidBodyComponent* rigidBodyComponent = nullptr; - SHColliderComponent* colliderComponent = nullptr; - }; - - using CommandFunctionPtr = void(*)(const QueueCommand&, SHPhysicsObject*, const PhysicsComponentGroup&); - - /*---------------------------------------------------------------------------------*/ - /* Data Members */ - /*---------------------------------------------------------------------------------*/ - - static CommandFunctionPtr componentFunc[3][2]; // 3 components, 2 commands - - rp3d::PhysicsCommon* factory = nullptr; - rp3d::PhysicsWorld* world = nullptr; - - PhysicsObjectEntityMap physicsObjects; - std::queue commandQueue; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept; - void destroyPhysicsObject (EntityID eid) noexcept; - - void wakeAllObjects () noexcept; - - static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - static void removeCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - - static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup); - - - }; - -} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp b/SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.cpp similarity index 94% rename from SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp rename to SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.cpp index 3e485153..98f6bdc1 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.cpp +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.cpp @@ -15,7 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHEntityManager.h" -#include "Physics/PhysicsObject/SHPhysicsObject.h" +#include "Physics/Interface/PhysicsObject/SHPhysicsObject.h" #include "Physics/System/SHPhysicsSystem.h" #include "Scene/SHSceneManager.h" @@ -25,9 +25,9 @@ uint32_t matchColliders(const SHADE::SHPhysicsObject&physicsObject, const rp3d::Entity colliderID) { - for (uint32_t i = 0; i < physicsObject.GetCollisionBody()->getNbColliders(); ++i) + for (uint32_t i = 0; i < physicsObject.body->getNbColliders(); ++i) { - const auto* collider = physicsObject.GetCollisionBody()->getCollider(i); + const auto* collider = physicsObject.body->getCollider(i); if (collider->getEntity() == colliderID) return i; } @@ -178,10 +178,10 @@ namespace SHADE bool matched[2] = { false, false }; - for (auto& [entityID, physicsObject] : system->GetPhysicsObjects()) + for (auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects()) { // Match body 1 - if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1) + if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.body->getEntity() == body1) { cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID; cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1); @@ -190,7 +190,7 @@ namespace SHADE } // Match body 2 - if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2) + if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.body->getEntity() == body2) { cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID; cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2); @@ -222,10 +222,10 @@ namespace SHADE bool matched[2] = { false, false }; - for (auto& [entityID, physicsObject] : system->GetPhysicsObjects()) + for (auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects()) { // Match body 1 - if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1) + if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.body->getEntity() == body1) { cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID; cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1); @@ -234,7 +234,7 @@ namespace SHADE } // Match body 2 - if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2) + if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.body->getEntity() == body2) { cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID; cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2); diff --git a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h b/SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.h similarity index 98% rename from SHADE_Engine/src/Physics/Collision/SHCollisionListener.h rename to SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.h index 62882556..6aa09fe4 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollisionListener.h +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHCollisionListener.h @@ -15,7 +15,7 @@ // Project Headers #include "SH_API.h" -#include "SHCollisionInfo.h" +#include "Physics/Collision/SHCollisionInfo.h" namespace SHADE { diff --git a/SHADE_Engine/src/Physics/SHPhysicsWorld.cpp b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.cpp similarity index 100% rename from SHADE_Engine/src/Physics/SHPhysicsWorld.cpp rename to SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.cpp diff --git a/SHADE_Engine/src/Physics/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h similarity index 97% rename from SHADE_Engine/src/Physics/SHPhysicsWorld.h rename to SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h index c5152c44..09a2b260 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsWorld.h +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHPhysicsWorld.h @@ -13,8 +13,7 @@ #include // Project Headers -#include "Math/SHMath.h" -#include "SH_API.h" +#include "Math/Vector/SHVec3.h" namespace SHADE { diff --git a/SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.cpp b/SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.cpp new file mode 100644 index 00000000..c420d208 --- /dev/null +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.cpp @@ -0,0 +1,132 @@ +/**************************************************************************************** + * \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 "SHRaycaster.h" + +#include "Physics/System/SHPhysicsSystem.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 */ + /*-----------------------------------------------------------------------------------*/ + + SHRaycaster::SHRaycaster() noexcept + : system { nullptr } + , world { nullptr } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHRaycaster::BindToSystem(SHPhysicsSystem* physicsSystem) noexcept + { + system = physicsSystem; + } + + void SHRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept + { + world = physicsWorld; + } + + const SHRaycaster::RaycastResults& SHRaycaster::Raycast(const RaycastInfo& info) noexcept + { + results.clear(); + currentInfo = info; + + SHASSERT(world, "Physics World missing link with Raycaster!") + + // Clamp distance to 2km + const float DISTANCE = std::clamp(info.distance, 0.0f, SHRay::MAX_RAYCAST_DIST); + + const rp3d::Ray RP3D_RAY = { info.ray.position, info.ray.position + info.ray.direction * DISTANCE }; + world->raycast(RP3D_RAY, this, info.layers); + + // Reset + currentInfo.reset(); + + return results; + } + + rp3d::decimal SHRaycaster::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) + { + SHASSERT(system, "Physics System unlinked with Raycaster!") + + SHPhysicsRaycastResult result; + + // Compare body IDs to find the matching physics object + const auto HIT_BODY_EID = raycastInfo.body->getEntity(); + + for (const auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects()) + { + // Match rp3d bodies + if (physicsObject.body->getEntity() != HIT_BODY_EID) + continue; + + // Skip ignored entity + if (currentInfo->colliderEntityID.has_value()) + if (entityID == currentInfo->colliderEntityID) + return 1.0f; + + result.entityHit = entityID; + + // Find collider index + if (const int INDEX = findColliderIndex(physicsObject.body, raycastInfo.collider->getEntity()); INDEX > -1) + { + result.shapeIndex = INDEX; + break; + } + } + + result.hit = true; + result.position = raycastInfo.worldPoint; + result.normal = raycastInfo.worldNormal; + result.distance = SHVec3::Distance(currentInfo->ray.position, result.position); + result.angle = SHVec3::Angle(currentInfo->ray.position, result.position); + + results.emplace_back(result); + + if (currentInfo->continuous) + return 1.0f; + + return 0.0f; + } + + /*-----------------------------------------------------------------------------------*/ + /* Private Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + int SHRaycaster::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/RP3DWrapper/SHRaycaster.h b/SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.h new file mode 100644 index 00000000..280ccb37 --- /dev/null +++ b/SHADE_Engine/src/Physics/RP3DWrapper/SHRaycaster.h @@ -0,0 +1,133 @@ +/**************************************************************************************** + * \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 "Math/SHRay.h" +#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" +#include "Physics/Collision/SHPhysicsRaycastResult.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + + class SHPhysicsSystem; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ + + class SH_API SHRaycaster : public reactphysics3d::RaycastCallback + { + private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + using RaycastResults = std::vector; + + public: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + struct RaycastInfo + { + private: + /*-------------------------------------------------------------------------------*/ + /* Friends */ + /*-------------------------------------------------------------------------------*/ + + friend class SHRaycaster; + + public: + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + bool continuous = false; + uint16_t layers = static_cast(SHCollisionTag::Layer::ALL); + float distance = std::numeric_limits::infinity(); + SHRay ray; + + /*-------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*-------------------------------------------------------------------------------*/ + + /** + * @brief + * Sets the collider ID for the raycast. Setting this specifies that the ray + * should ignore this collider. + * @param eid + * The entity ID of the collider. + */ + void SetColliderID(EntityID eid) noexcept { colliderEntityID = eid; } + + private: + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + std::optional colliderEntityID; + }; + + /*---------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*---------------------------------------------------------------------------------*/ + + SHRaycaster() noexcept; + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + void BindToSystem (SHPhysicsSystem* physicsSystem) noexcept; + void BindToWorld (rp3d::PhysicsWorld* physicsWorld) noexcept; + + rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override; + + /** + * @brief + * Casts a ray into the physics world. + * @param info + * Contains the information for the raycast. + * @return + * A container of the objects hit by the ray. If nothing was hit, the container + * will be empty. + */ + [[nodiscard]] const RaycastResults& Raycast(const RaycastInfo& info) noexcept; + + private: + /*---------------------------------------------------------------------------------*/ + /* Data Members */ + /*---------------------------------------------------------------------------------*/ + + SHPhysicsSystem* system; + rp3d::PhysicsWorld* world; + RaycastResults results; // Holds the temporary result after casting into the world + std::optional currentInfo; // Hold the state of the current raycast. + + /*---------------------------------------------------------------------------------*/ + /* Function Members */ + /*---------------------------------------------------------------------------------*/ + + 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/SHPhysicsEvents.h b/SHADE_Engine/src/Physics/SHPhysicsEvents.h index ae48a75b..a192ec3f 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsEvents.h +++ b/SHADE_Engine/src/Physics/SHPhysicsEvents.h @@ -11,8 +11,7 @@ #pragma once // Project Headers -#include "Interface/SHCollisionShape.h" - +#include "Collision/Shapes/SHCollisionShape.h" namespace SHADE { @@ -28,9 +27,16 @@ namespace SHADE }; struct SHPhysicsColliderRemovedEvent + { + EntityID entityID; + SHCollisionShape::Type colliderType; + int colliderIndex; + }; + + struct SHColliderOnDebugDrawEvent { EntityID entityID; - int colliderIndex; + bool debugDrawState; }; diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp new file mode 100644 index 00000000..469e835d --- /dev/null +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp @@ -0,0 +1,113 @@ +/**************************************************************************************** + * \file SHPhysicsDebugDrawRutine.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics Debut Draw Routine + * + * \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 "Physics/System/SHPhysicsDebugDrawSystem.h" + +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Physics/System/SHPhysicsSystem.h" +#include "Tools/Utilities/SHUtilities.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsDebugDrawSystem::PhysicsDebugDraw::PhysicsDebugDraw() + : SHSystemRoutine { "Physics Debug-Draw", true } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsDebugDrawSystem::PhysicsDebugDraw::Execute(double) noexcept + { + auto* physicsDebugDrawSystem = reinterpret_cast(GetSystem()); + + if (!physicsDebugDrawSystem->IsDebugDrawActive()) + return; + + auto* debugDrawSystem = SHSystemManager::GetSystem(); + + const bool DRAW_COLLIDERS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::COLLIDERS); + const bool DRAW_CONTACTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::CONTACTS); + const bool DRAW_RAYCASTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::RAYCASTS); +\ + // If draw all colliders is active, get all colliders from the dense set and draw. + // Else we check if any colliders have been flagged for drawing. + if (DRAW_COLLIDERS) + { + const auto& COLLIDER_COMPONENT_DENSE = SHComponentManager::GetDense(); + for (const auto& COLLIDER_COMPONENT : COLLIDER_COMPONENT_DENSE) + drawCollider(debugDrawSystem, COLLIDER_COMPONENT); + } + else if (!physicsDebugDrawSystem->collidersToDraw.empty()) + { + for (const auto EID : physicsDebugDrawSystem->collidersToDraw) + drawCollider(debugDrawSystem, *SHComponentManager::GetComponent(EID)); + } + + auto* physicsSystem = SHSystemManager::GetSystem(); + if (!physicsSystem) + return; + + rp3d::DebugRenderer* rp3dRenderer = nullptr; + if (physicsSystem->worldState.world) + rp3dRenderer = &physicsSystem->worldState.world->getDebugRenderer(); + + // No world exists, nothing else to be drawn + if (!rp3dRenderer) + return; + + rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, DRAW_CONTACTS); + rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, DRAW_CONTACTS); + + if (DRAW_CONTACTS) + { + const SHColour& CONTACT_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::CONTACT)]; + + const int NUM_TRIS = static_cast(rp3dRenderer->getNbTriangles()); + if (NUM_TRIS == 0) // No contact points + return; + + // Draw contacts + const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray(); + for (int i = 0; i < NUM_TRIS; ++i) + debugDrawSystem->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, CONTACT_COLOUR, true); + + // Draw normals + const int NUM_LINES = static_cast(rp3dRenderer->getNbLines()); + + const auto& LINE_ARRAY = rp3dRenderer->getLinesArray(); + for (int i = 0; i < NUM_LINES; ++i) + debugDrawSystem->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, CONTACT_COLOUR, true); + } + + if (DRAW_RAYCASTS) + { + const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)]; + + const auto& RAYS = physicsSystem->raycastHits; + for (const auto& hit : RAYS) + debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true); + + // Clear rays for the physics system + physicsSystem->raycastHits.clear(); + } + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp new file mode 100644 index 00000000..5f97daaf --- /dev/null +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPostUpdateRoutine.cpp @@ -0,0 +1,120 @@ +/**************************************************************************************** + * \file SHPhysicsPostUpdateRoutine.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics Post-Update Routine + * + * \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 "Physics/System/SHPhysicsSystem.h" + +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Scene/SHSceneManager.h" +#include "Scripting/SHScriptEngine.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate() + : SHSystemRoutine { "Physics Post-Update", false } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + auto* scriptingSystem = SHSystemManager::GetSystem(); + + if (scriptingSystem == nullptr) + { + SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!"); + } + + const float FACTOR = static_cast(physicsSystem->interpolationFactor); + + // Interpolate transforms for rendering. + // Only rigid bodies can move due to physics, so we run through the rigid body component dense set. + if (physicsSystem->worldUpdated) + { + for (auto& [entityID, physicsObject] : physicsSystem->objectManager.GetPhysicsObjects()) + { + // Skip missing transforms + auto* transformComponent = SHComponentManager::GetComponent_s(entityID); + if (!transformComponent) + continue; + + auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); + + // Skip invalid bodies (Should not occur) + if (!rigidBodyComponent || !rigidBodyComponent->rigidBody) + continue; + + // Skip inactive bodies + const bool IS_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); + if (!IS_ACTIVE || rigidBodyComponent->type == SHRigidBodyComponent::Type::STATIC) + continue; + + const rp3d::Transform& CURRENT_TF = physicsObject.body->getTransform(); + + if (rigidBodyComponent->IsInterpolating()) + { + const rp3d::Transform PREV_TF + { + rigidBodyComponent->position + , rigidBodyComponent->orientation + }; + + const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(FACTOR)); + + const SHVec3 RENDER_POSITION = INTERPOLATED_TF.getPosition(); + const SHQuaternion RENDER_ORIENTATION = INTERPOLATED_TF.getOrientation(); + + transformComponent->SetWorldPosition(RENDER_POSITION); + transformComponent->SetWorldOrientation(RENDER_ORIENTATION); + } + else + { + transformComponent->SetWorldPosition(CURRENT_TF.getPosition()); + transformComponent->SetWorldOrientation(CURRENT_TF.getOrientation()); + } + + rigidBodyComponent->position = CURRENT_TF.getPosition(); + rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); + + // Set colliders transform if exists + if (auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); colliderComponent) + { + colliderComponent->transform.position = CURRENT_TF.getPosition(); + colliderComponent->transform.orientation = CURRENT_TF.getOrientation(); + } + + /* + * TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. + */ + } + + // Since this function never runs when editor in not in play, execute the function anyway + physicsSystem->collisionListener.CleanContainers(); + } + + + + // Collision & Trigger messages + if (scriptingSystem != nullptr) + scriptingSystem->ExecuteCollisionFunctions(); + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp new file mode 100644 index 00000000..3a085dd0 --- /dev/null +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp @@ -0,0 +1,95 @@ +/**************************************************************************************** + * \file SHPhysicsPreUpdateRoutine.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics Pre-Update Routine + * + * \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 "Physics/System/SHPhysicsSystem.h" + +// Project Headers +#include "ECS_Base/Managers/SHComponentManager.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Scene/SHSceneManager.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate() + : SHSystemRoutine { "Physics Pre-Update", true } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + + // Get all physics objects & sync transforms + auto& physicsObjects = physicsSystem->objectManager.GetPhysicsObjects(); + for (auto& [entityID, physicsObject] : physicsObjects) + { + const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s(entityID); + // Assume transform is always active + const bool UPDATE_TRANSFORM = TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged(); + + if (!UPDATE_TRANSFORM) + continue; + + // We assume that all engine components and physics object components have been successfully linked + + if (!physicsObject.body) + continue; + + // Set body transform + const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation(); + + const rp3d::Transform NEW_TRANSFORM{ WORLD_POS, WORLD_ROT }; + physicsObject.body->setTransform(NEW_TRANSFORM); + + // Sync rigid body active states if one exists + if (auto* shadeBody = SHComponentManager::GetComponent_s(entityID); shadeBody) + { + const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); + const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive(); + + if (SHADE_BODY_ACTIVE != RP3D_BODY_ACTIVE) + physicsObject.body->setIsActive(SHADE_BODY_ACTIVE); + + shadeBody->position = WORLD_POS; + shadeBody->orientation = WORLD_ROT; + } + + // Sync collider active states if one exists + if (auto* shadeCollider = SHComponentManager::GetComponent_s(entityID); shadeCollider) + { + const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); + const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG; + + // Modify the static body's active state + // The collision listener & raycaster will handle culling inactive colliders. + if (SHADE_COLLIDER_ACTIVE != RP3D_COLLIDERS_ACTIVE) + physicsObject.body->setIsActive(SHADE_COLLIDER_ACTIVE); + + shadeCollider->transform.position = WORLD_POS; + shadeCollider->transform.orientation = WORLD_ROT; + shadeCollider->transform.scale = TRANSFORM_COMPONENT->GetWorldScale(); + + shadeCollider->Update(); + } + } + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsUpdateRoutine.cpp new file mode 100644 index 00000000..d4f6d623 --- /dev/null +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsUpdateRoutine.cpp @@ -0,0 +1,66 @@ +/**************************************************************************************** + * \file SHPhysicsUpdateRoutine.cpp + * \author Diren D Bharwani, diren.dbharwani, 390002520 + * \brief Implementation for the Physics Update Routine + * + * \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 "Physics/System/SHPhysicsSystem.h" + +// Project Headers +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Scripting/SHScriptEngine.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* Constructors & Destructor Definitions */ + /*-----------------------------------------------------------------------------------*/ + + SHPhysicsSystem::PhysicsUpdate::PhysicsUpdate() + : SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics Update", false } + {} + + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHPhysicsSystem::PhysicsUpdate::Execute(double dt) noexcept + { + auto* physicsSystem = reinterpret_cast(GetSystem()); + + auto* scriptEngine = SHSystemManager::GetSystem(); + if (!scriptEngine) + { + SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing ScriptEngine!") + } + + const double FIXED_DT = physicsSystem->fixedDT; + accumulatedTime += dt; + + int count = 0; + while (accumulatedTime > FIXED_DT) + { + if (scriptEngine) + scriptEngine->ExecuteFixedUpdates(); + + if (physicsSystem->worldState.world) + physicsSystem->worldState.world->update(static_cast(FIXED_DT)); + + accumulatedTime -= FIXED_DT; + ++count; + } + + stats.numSteps = count; + physicsSystem->worldUpdated = count > 0; + + physicsSystem->interpolationFactor = physicsSystem->worldUpdated ? accumulatedTime / FIXED_DT : 0.0; + } + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index 96af5e39..226ba2f9 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -13,79 +13,59 @@ // Primary Header #include "SHPhysicsDebugDrawSystem.h" -// Project Headers +// Project Header #include "ECS_Base/Managers/SHSystemManager.h" -#include "Editor/SHEditor.h" -#include "Scene/SHSceneManager.h" +#include "Math/Transform/SHTransformComponent.h" +#include "Physics/SHPhysicsEvents.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { - /*-----------------------------------------------------------------------------------*/ - /* Static Data Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] = + const SHColour SHPhysicsDebugDrawSystem::DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::COUNT)] { - drawColliders - , drawColliderAABBs - , drawBroadPhaseAABBs - , drawContactPoints - , drawContactNormals - , drawRaycasts + SHColour::GREEN // Colliders + , SHColour::PURPLE // Triggers + , SHColour::RED // Contacts + , SHColour::ORANGE // Raycasts }; - SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES]; - /*-----------------------------------------------------------------------------------*/ /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept - : debugDrawFlags { 0 } - , physicsSystem { nullptr } + : flags { 0 } { - 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; + collidersToDraw.clear(); } - SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine() - : SHSystemRoutine { "Physics Debug Draw", true } - {} - /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - bool SHPhysicsDebugDrawSystem::GetDebugDrawFlag(DebugDrawFlags flag) const noexcept + bool SHPhysicsDebugDrawSystem::IsDebugDrawActive() const noexcept { - const auto INT_FLAG = SHUtilities::ConvertEnum(flag); - if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS) - { - SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to get debug draw state!", INT_FLAG) - return false; - } + return flags & ACTIVE_FLAG; + } - return debugDrawFlags & 1U << SHUtilities::ConvertEnum(flag); + bool SHPhysicsDebugDrawSystem::GetFlagState(DebugDrawFlags flag) const noexcept + { + const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag); + return flags & ENUM_VALUE; } /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsDebugDrawSystem::SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept + void SHPhysicsDebugDrawSystem::SetFlagState(DebugDrawFlags flag, bool state) noexcept { - const auto INT_FLAG = SHUtilities::ConvertEnum(flag); - if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS) - { - SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to set debug draw state!", INT_FLAG) - return; - } + const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag); + state ? flags |= ENUM_VALUE : flags &= ~ENUM_VALUE; - value ? (debugDrawFlags |= 1U << INT_FLAG) : (debugDrawFlags &= ~(1U << INT_FLAG)); + // If no other debug drawing state is active, turn active off. Otherwise, we maintain + // the active state. + flags == ACTIVE_FLAG ? flags = 0 : flags |= ACTIVE_FLAG; } /*-----------------------------------------------------------------------------------*/ @@ -96,240 +76,76 @@ namespace SHADE { SystemFamily::GetID(); - SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!") - physicsSystem = SHSystemManager::GetSystem(); + // Register collider draw event + const std::shared_ptr EVENT_RECEIVER = std::make_shared>(this, &SHPhysicsDebugDrawSystem::onColliderDraw); + const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast(EVENT_RECEIVER); - // Generate shapes - generateBox(); + //SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_DRAW_EVENT, EVENT_RECEIVER_PTR); } void SHPhysicsDebugDrawSystem::Exit() { - physicsSystem = nullptr; + } - void SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::Execute(double) noexcept + void SHPhysicsDebugDrawSystem::AddRaycast(const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept { - 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; - } - - rp3d::DebugRenderer* rp3dRenderer = nullptr; - if (system->physicsSystem->worldState.world) - rp3dRenderer = &system->physicsSystem->worldState.world->getDebugRenderer(); - - for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i) - { - const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0; - if (DRAW) - { - drawFunctions[i](debugDrawSystem, rp3dRenderer); - } - else - { - if (rp3dRenderer && (i == 3 || i == 4)) - { - rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_POINT, false); - rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_NORMAL, false); - } - } - - } - - // Automatically clear the container of raycasts despite debug drawing state - // TODO(Diren): Move this somewhere else - system->physicsSystem->raycaster.ClearFrame(); + } /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept + SHEventHandle SHPhysicsDebugDrawSystem::onColliderDraw(SHEventPtr onColliderDrawEvent) { - const auto& COLLIDER_SET = SHComponentManager::GetDense(); - for (const auto& COLLIDER : COLLIDER_SET) - { - // Skip inactive colliders - if (!SHSceneManager::CheckNodeAndComponentsActive(COLLIDER.GetEID())) - continue; + const auto& EVENT_DATA = reinterpret_cast*>(onColliderDrawEvent.get())->data; - for (auto& collisionShape : COLLIDER.GetCollisionShapes()) + // Add to the container to draw all colliders + if (EVENT_DATA->debugDrawState) + { + if (collidersToDraw.empty()) + flags |= ACTIVE_FLAG; + + collidersToDraw.emplace(EVENT_DATA->entityID); + } + else + { + collidersToDraw.erase(EVENT_DATA->entityID); + + // if no colliders queued for drawing and no other debug drawing is enabled, disable debug drawing + if (collidersToDraw.empty() && flags == ACTIVE_FLAG) + flags = 0; + } + + return onColliderDrawEvent.get()->handle; + } + + void SHPhysicsDebugDrawSystem::drawCollider(SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept + { + for (const auto& SHAPE : collider.GetCollisionShapes()) + { + const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(SHAPE->IsTrigger() ? Colours::TRIGGER : Colours::COLLIDER)]; + + switch (SHAPE->GetType()) { - switch (collisionShape.GetType()) + case SHCollisionShape::Type::SPHERE: { - case SHCollisionShape::Type::BOX: debugDrawBox(debugRenderer, COLLIDER, collisionShape); break; - case SHCollisionShape::Type::SPHERE: debugDrawSphere(debugRenderer, COLLIDER, collisionShape); break; - default: break; + debugDrawSystem->DrawWireSphere(SHAPE->GetTRS(), DRAW_COLOUR, true); + break; } + case SHCollisionShape::Type::BOX: + { + debugDrawSystem->DrawWireCube(SHAPE->GetTRS(), DRAW_COLOUR, true); + break; + } + //case SHCollisionShape::Type::CAPSULE: + //{ + // break; + //} + default: break; } } } - void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept - { - - } - - void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept - { - - } - - void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept - { - #ifdef SHEDITOR - - const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - { - rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true); - const int NUM_TRIS = static_cast(rp3dRenderer->getNbTriangles()); - if (NUM_TRIS == 0) - return; - - const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray(); - for (int i = 0; i < NUM_TRIS; ++i) - debugRenderer->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, SHColour::RED); - } - - #else - - rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true); - const int NUM_TRIS = static_cast(rp3dRenderer->getNbTriangles()); - if (NUM_TRIS == 0) - return; - - const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray(); - for (int i = 0; i < NUM_TRIS; ++i) - debugRenderer->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, SHColour::RED); - - #endif - } - - void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept - { - #ifdef SHEDITOR - const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - { - rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true); - const int NUM_LINES = static_cast(rp3dRenderer->getNbLines()); - if (NUM_LINES == 0) - return; - - const auto& LINE_ARRAY = rp3dRenderer->getLinesArray(); - for (int i = 0; i < NUM_LINES; ++i) - debugRenderer->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, SHColour::RED); - } - - #else - - rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true); - const int NUM_LINES = static_cast(rp3dRenderer->getNbLines()); - if (NUM_LINES == 0) - return; - - const auto& LINE_ARRAY = rp3dRenderer->getLinesArray(); - for (int i = 0; i < NUM_LINES; ++i) - debugRenderer->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, SHColour::RED); - - #endif - } - - void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) 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.position, END_POS, RAY_COLOUR); - } - } - - - void SHPhysicsDebugDrawSystem::generateBox() noexcept - { - boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK - boxVertices[1] = { -0.5f, 0.5f, -0.5f }; // TOP_LEFT_BACK - boxVertices[2] = { 0.5f, -0.5f, -0.5f }; // BTM_RIGHT_BACK - boxVertices[3] = { -0.5f, -0.5f, -0.5f }; // BTM_LEFT_BACK - boxVertices[4] = { 0.5f, 0.5f, 0.5f }; // TOP_RIGHT_FRONT - boxVertices[5] = { -0.5f, 0.5f, 0.5f }; // TOP_LEFT_FRONT - boxVertices[6] = { 0.5f, -0.5f, 0.5f }; // BTM_RIGHT_FRONT - boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT - } - - void SHPhysicsDebugDrawSystem::debugDrawBox(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept - { - auto* BOX = reinterpret_cast(collisionShape.GetShape()); - - // Calculate final position & orientation - const SHVec3 COLLIDER_POS = colliderComponent.GetPosition(); - const SHVec3 BOX_POS = collisionShape.GetPositionOffset(); - const SHQuaternion COLLIDER_ROT = colliderComponent.GetOrientation(); - const SHQuaternion BOX_ROT = SHQuaternion::FromEuler(collisionShape.GetRotationOffset()); - - - const SHMatrix COLLIDER_TR = SHMatrix::Rotate(COLLIDER_ROT) * SHMatrix::Translate(COLLIDER_POS); - const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(BOX_ROT) * SHMatrix::Translate(BOX_POS); - - const SHMatrix FINAL_TRS = BOX_TRS * COLLIDER_TR; - - const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; - - std::array transformedVertices; - for (uint32_t i = 0; i < NUM_BOX_VERTICES / 2; ++i) - { - const uint32_t IDX1 = i; - const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2; - - transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], FINAL_TRS); - transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS); - - // Draw 4 line to connect the quads - debugRenderer->DrawLine(transformedVertices[IDX1], transformedVertices[IDX2], COLLIDER_COLOUR); - } - - // A, B, C, D - std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] }; - debugRenderer->DrawLineLoop(backQuad.begin(), backQuad.end(), COLLIDER_COLOUR); - - // E, F, G, H - std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] }; - debugRenderer->DrawLineLoop(frontQuad.begin(), frontQuad.end(), COLLIDER_COLOUR); - } - - void SHPhysicsDebugDrawSystem::debugDrawSphere(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept - { - auto* SPHERE = reinterpret_cast(collisionShape.GetShape()); - - const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN; - - // Calculate final position & orientation - const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset()); - const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition()); - - /* #KWFix */ - //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 dc703092..8c2c9b78 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.h @@ -10,14 +10,16 @@ #pragma once -#include +#include // Project Headers +#include "ECS_Base/Entity/SHEntity.h" +#include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystemRoutine.h" +#include "Events/SHEvent.h" #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" -#include "Math/SHColour.h" -#include "SHPhysicsSystem.h" -#include "Tools/Utilities/SHUtilities.h" +#include "Physics/Interface/SHColliderComponent.h" +#include "Physics/Collision/SHPhysicsRaycastResult.h" namespace SHADE { @@ -28,63 +30,54 @@ namespace SHADE class SH_API SHPhysicsDebugDrawSystem final : public SHSystem { public: - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ - enum class DebugDrawFlags + enum class DebugDrawFlags : uint8_t { - COLLIDER - , COLLIDER_AABB - , BROAD_PHASE_AABB - , CONTACT_POINTS - , CONTACT_NORMALS - , RAYCASTS - - , NUM_FLAGS + COLLIDERS = 0x02 + , CONTACTS = 0x04 + , RAYCASTS = 0x08 }; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHPhysicsDebugDrawSystem() noexcept; + SHPhysicsDebugDrawSystem () noexcept; + ~SHPhysicsDebugDrawSystem() noexcept = default; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - bool GetDebugDrawFlag(DebugDrawFlags flag) const noexcept; - + [[nodiscard]] bool IsDebugDrawActive () const noexcept; + [[nodiscard]] bool GetFlagState (DebugDrawFlags flag) const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept; + void SetFlagState (DebugDrawFlags flag, bool state) noexcept; /*---------------------------------------------------------------------------------*/ - /* Function Members */ + /* Member Functions */ /*---------------------------------------------------------------------------------*/ - void Init() override; - void Exit() override; + void Init () override; + void Exit () override; + + void AddRaycast (const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept; /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ - class SH_API PhysicsDebugDrawRoutine final : public SHSystemRoutine + /** + * @brief + * If the editor is enabled, this routine invokes debug drawing for colliders and collision information. + */ + class SH_API PhysicsDebugDraw final : public SHSystemRoutine { public: - /*-------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*-------------------------------------------------------------------------------*/ - - PhysicsDebugDrawRoutine(); - - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ + PhysicsDebugDraw(); void Execute(double dt) noexcept override; }; @@ -93,46 +86,58 @@ namespace SHADE /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using DebugDrawFunction = void(*)(SHDebugDrawSystem*, rp3d::DebugRenderer*) noexcept; + union DebugDrawInfo + { + struct Contact + { + SHVec3 worldPos; + SHVec3 normal; + } contact; + + struct Raycast + { + SHVec3 start; + SHVec3 end; + } raycast; + }; + + using Colliders = std::unordered_set; + using Raycasts = std::vector; + using Contacts = std::vector; + + enum class Colours + { + COLLIDER + , TRIGGER + , CONTACT + , RAYCAST + + , COUNT + }; /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); - static const DebugDrawFunction drawFunctions[NUM_FLAGS]; + static constexpr uint8_t ACTIVE_FLAG = 0x01; - // SHAPES INFO + static const SHColour DEBUG_DRAW_COLOURS[static_cast(Colours::COUNT)]; - static constexpr size_t NUM_BOX_VERTICES = 8; - static SHVec3 boxVertices[NUM_BOX_VERTICES]; + // 0 0 0 drawBroadphase drawRaycasts drawContacts drawAllColliders debugDrawActive + uint8_t flags; + + Colliders collidersToDraw; + + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent); + + static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept; + static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept; - - uint8_t debugDrawFlags; - SHPhysicsSystem* physicsSystem; - SHColour debugColours[NUM_FLAGS]; - - /*---------------------------------------------------------------------------------*/ - /* Function Members */ - /*---------------------------------------------------------------------------------*/ - - // Generic Draw Functions - - static void drawColliders (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - static void drawContactPoints (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - static void drawContactNormals (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - static void drawRaycasts (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept; - - // Shape Generation Functions - - static void generateBox () noexcept; - - // Shape Draw Functions - - static void debugDrawBox (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept; - static void debugDrawSphere (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept; }; -} // namespace SHADE + +} // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 768c9b77..22a51c41 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -19,8 +19,9 @@ #include "ECS_Base/Managers/SHEntityManager.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Editor/SHEditor.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" -#include "Physics/SHPhysicsEvents.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" +#include "Physics/Interface/SHRigidBodyComponent.h" +#include "Physics/Interface/SHColliderComponent.h" #include "Scene/SHSceneManager.h" #include "Scripting/SHScriptEngine.h" @@ -30,11 +31,23 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHPhysicsSystem::SHPhysicsSystem() + SHPhysicsSystem::SHPhysicsSystem() noexcept : worldUpdated { false } , interpolationFactor { 0.0 } , fixedDT { DEFAULT_FIXED_STEP } - {} + { + // Add more events here to register them + + eventFunctions[0] = { &SHPhysicsSystem::onComponentAdded , SH_COMPONENT_ADDED_EVENT }; + eventFunctions[1] = { &SHPhysicsSystem::onComponentRemoved, SH_COMPONENT_REMOVED_EVENT }; + eventFunctions[2] = { &SHPhysicsSystem::onSceneInit , SH_SCENE_INIT_POST }; + eventFunctions[3] = { &SHPhysicsSystem::onSceneExit , SH_SCENE_EXIT_POST }; + } + + SHPhysicsSystem::~SHPhysicsSystem() + { + worldState.DestroyWorld(factory); + } /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ @@ -45,9 +58,9 @@ namespace SHADE return 1.0 / fixedDT; } - const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept + double SHPhysicsSystem::GetFixedDT() const noexcept { - return worldState.settings; + return fixedDT; } const std::vector& SHPhysicsSystem::GetAllCollisionInfo() const noexcept @@ -60,30 +73,43 @@ namespace SHADE return collisionListener.GetTriggerInfoContainer(); } - const SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept - { - return objectManager.GetPhysicsObject(eid); - } - - - const SHPhysicsObjectManager::PhysicsObjectEntityMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept - { - return objectManager.physicsObjects; - } - /*-----------------------------------------------------------------------------------*/ /* Setter Function Definitions */ /*-----------------------------------------------------------------------------------*/ void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept { + // Handle invalid input + if (fixedUpdateRate <= 0.0) + { + SHLOGV_WARNING("Invalid value for setting fixed update rate! Fixed update rate unchanged.") + return; + } + fixedDT = 1.0 / fixedUpdateRate; + + // Handle potential incorrect / unintended input + if (fixedDT > 1.0) + { + SHLOGV_WARNING("Fixed Update Rate Time is set below 1. This may result in undesirable behaviour.") + } } - void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept + void SHPhysicsSystem::SetFixedDT(double fixedDt) noexcept { - worldState.settings = settings; - worldState.UpdateSettings(); + if (fixedDt <= 0.0) + { + SHLOGV_WARNING("Invalid value for setting fixed delta time! Fixed delta time unchanged.") + return; + } + + fixedDT = fixedDt; + + // Handle potential incorrect / unintended input + if (fixedDT > 1.0) + { + SHLOGV_WARNING("Fixed Delta Time is set above 1. This may result in undesirable behaviour.") + } } /*-----------------------------------------------------------------------------------*/ @@ -92,40 +118,23 @@ namespace SHADE void SHPhysicsSystem::Init() { + // TODO(Diren): Consider using a non-static collision tag matrix. // Initialise collision tags std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT }; defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig"); SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath); - // Link Physics Object Manager with System & Raycaster - objectManager.SetFactory(factory); - raycaster.SetObjectManager(&objectManager); + // Register Events + for (int i = 0; i < NUM_EVENT_FUNCTIONS; ++i) + { + const std::shared_ptr EVENT_RECEIVER = std::make_shared>(this, eventFunctions[i].first); + const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast(EVENT_RECEIVER); - // Link Collision Listener with System - collisionListener.BindToSystem(this); + SHEventManager::SubscribeTo(eventFunctions[i].second, EVENT_RECEIVER_PTR); + } - // Subscribe to component events - const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::addPhysicsComponent) }; - const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(ADD_COMPONENT_RECEIVER); - SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR); - - const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::removePhysicsComponent) }; - const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast(REMOVE_COMPONENT_RECEIVER); - SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR); - - #ifdef SHEDITOR - - // Subscribe to Editor State Change Events - const std::shared_ptr ON_PLAY_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::onPlay) }; - const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast(ON_PLAY_RECEIVER); - SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR); - - const std::shared_ptr ON_STOP_RECEIVER { std::make_shared>(this, &SHPhysicsSystem::onStop) }; - const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast(ON_STOP_RECEIVER); - SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR); - - #endif - + objectManager.SetFactory(&factory); + raycaster.BindToSystem(this); } void SHPhysicsSystem::Exit() @@ -138,344 +147,165 @@ namespace SHADE SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath); } - void SHPhysicsSystem::BuildScene(SHSceneGraph& sceneGraph) + const std::vector& SHPhysicsSystem::Raycast(const SHRaycaster::RaycastInfo& info) noexcept { - static const auto BUILD_NEW_SCENE_PHYSICS_OBJECT = [&](SHSceneNode* node) - { - const EntityID EID = node->GetEntityID(); + auto& results = raycaster.Raycast(info); - if (SHComponentManager::HasComponent(EID)) - objectManager.AddRigidBody(EID); + // Load start and end points into the container for debug drawing + #ifdef SHEDITOR - if (SHComponentManager::HasComponent(EID)) - { - objectManager.AddCollider(EID); + SHVec3 endPos = info.ray.position + info.ray.direction * SHRay::MAX_RAYCAST_DIST; - auto* COLLIDER = SHComponentManager::GetComponent(EID); - for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i) - objectManager.AddCollisionShape(EID, i); - } + if (!results.empty()) + endPos = results.back().position; - }; + raycastHits.emplace_back(info.ray.position, endPos); + + #endif - //////////////////////////////// - - // Destroy an existing world - if (worldState.world != nullptr) - { - objectManager.RemoveAllObjects(); - objectManager.SetWorld(nullptr); - - collisionListener.ClearContainers(); - raycaster.ClearFrame(); - - worldState.DestroyWorld(factory); - } - - worldState.CreateWorld(factory); -#ifdef _PUBLISH - worldState.world->setIsDebugRenderingEnabled(false); -#else - worldState.world->setIsDebugRenderingEnabled(true); -#endif - - // Link Collision Listener & Raycaster - collisionListener.BindToWorld(worldState.world); - raycaster.BindToWorld(worldState.world); - - // Link with object manager & create all physics objects - objectManager.SetWorld(worldState.world); - - // When building a scene, clear the object manager command queue and build scene objects again. - // This is done to avoid duplicate adds. - while (!objectManager.commandQueue.empty()) - objectManager.commandQueue.pop(); - - sceneGraph.Traverse(BUILD_NEW_SCENE_PHYSICS_OBJECT); - objectManager.UpdateCommands(); + return results; } - void SHPhysicsSystem::ForceBuild(SHSceneGraph& sceneGraph) - { - // HACK: Band-aid fix. To be removed. - objectManager.UpdateCommands(); - } - - - void SHPhysicsSystem::ForceUpdate() - { - if (!worldState.world) - { - SHLOGV_ERROR("Unable to force update without a Physics world!") - return; - } - - auto* scriptingSystem = SHSystemManager::GetSystem(); - if (scriptingSystem == nullptr) - { - SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); - } - - // Force the physics world to update once - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteFixedUpdates(); - - worldState.world->update(static_cast(fixedDT)); - - // Sync transforms. No interpolation applied here - for (auto& [entityID, physicsObject] : objectManager.physicsObjects) - { - auto* transformComponent = SHComponentManager::GetComponent_s(entityID); - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - - const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); - const auto& RENDER_POS = CURRENT_TF.getPosition(); - const auto& RENDER_ROT = CURRENT_TF.getOrientation(); - - // Cache transform - physicsObject.prevTransform = CURRENT_TF; - - // Sync with physics components - if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(entityID)) - { - rigidBodyComponent->position = RENDER_POS; - rigidBodyComponent->orientation = RENDER_ROT; - } - - if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(entityID)) - { - colliderComponent->position = RENDER_POS; - colliderComponent->orientation = RENDER_ROT; - } - - // Set transform for rendering - if (transformComponent) - { - transformComponent->SetWorldPosition(RENDER_POS); - transformComponent->SetWorldOrientation(RENDER_ROT); - } - } - } - - SHPhysicsRaycastResult SHPhysicsSystem::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept - { - return raycaster.Raycast(ray, distance, collisionTag); - } - - SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept - { - return raycaster.Linecast(start, end, collisionTag); - } - - SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept - { - return raycaster.ColliderRaycast(eid, ray, distance); - } - - SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept - { - return raycaster.ColliderRaycast(eid, shapeIndex, ray, distance); - } - - SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept - { - return raycaster.ColliderLinecast(eid, start, end); - } - - SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept - { - return raycaster.ColliderLinecast(eid, shapeIndex, start, end); - } - - void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex) - { - static const auto ADD_SHAPE = [&](EntityID entityID, int index) - { - objectManager.AddCollisionShape(entityID, index); - - auto* colliderComponent = SHComponentManager::GetComponent(entityID); - auto& collisionShape = colliderComponent->GetCollisionShape(index); - - const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA - { - .entityID = entityID - , .colliderType = collisionShape.GetType() - , .colliderIndex = index - }; - - SHEventManager::BroadcastEvent(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); - }; - - #ifdef SHEDITOR - - const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - ADD_SHAPE(eid, shapeIndex); - - #else - - ADD_SHAPE(eid, shapeIndex); - - #endif - } - - void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex) - { - static const auto REMOVE_SHAPE = [&](EntityID entityID, int index) - { - objectManager.RemoveCollisionShape(entityID, index); - - const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA - { - .entityID = entityID - , .colliderIndex = index - }; - - SHEventManager::BroadcastEvent(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT); - }; - - #ifdef SHEDITOR - - const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - REMOVE_SHAPE(eid, shapeIndex); - - #else - - REMOVE_SHAPE(eid, shapeIndex); - - #endif - } /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHEventHandle SHPhysicsSystem::addPhysicsComponent(SHEventPtr addComponentEvent) noexcept + SHEventHandle SHPhysicsSystem::onSceneInit(SHEventPtr onSceneInitEvent) { - const auto& EVENT_DATA = reinterpret_cast*>(addComponentEvent.get()); + /* + * If a world already exists, destroy it + * Recreate the world. + * + * If there is an editor and editor mode is already playing, link all entities with the world immediately. + */ - static const auto RIGID_BODY_ID = ComponentFamily::GetID(); - static const auto COLLIDER_ID = ComponentFamily::GetID(); - - const auto ADDED_ID = EVENT_DATA->data->addedComponentType; - const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID; - if (IS_PHYSICS_COMPONENT) + // Destroy an existing world if there is one. + //! This should almost never happen. + if (worldState.world) { - const EntityID EID = EVENT_DATA->data->eid; - - // We only add tell the physics object manager to add a component if the scene is played - - #ifdef SHEDITOR - - const auto* EDITOR = SHSystemManager::GetSystem(); - - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID); - - #else - - ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID); - - #endif - } - - return EVENT_DATA->handle; - } - - SHEventHandle SHPhysicsSystem::removePhysicsComponent(SHEventPtr removeComponentEvent) noexcept - { - const auto& EVENT_DATA = reinterpret_cast*>(removeComponentEvent.get()); - - static const auto RIGID_BODY_ID = ComponentFamily::GetID(); - static const auto COLLIDER_ID = ComponentFamily::GetID(); - - const auto REMOVED_ID = EVENT_DATA->data->removedComponentType; - const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID; - if (IS_PHYSICS_COMPONENT) - { - const EntityID EID = EVENT_DATA->data->eid; - - // We only add tell the physics object manager to remove a component if the scene is played - - #ifdef SHEDITOR - - const auto* EDITOR = SHSystemManager::GetSystem(); - - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID); - - #else - - REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID); - - #endif - } - - return EVENT_DATA->handle; - } - - SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent) - { - static const auto BUILD_PHYSICS_OBJECT = [&](SHSceneNode* node) - { - const EntityID EID = node->GetEntityID(); - - if (SHComponentManager::HasComponent(EID)) - objectManager.AddRigidBody(EID); - - if (SHComponentManager::HasComponent(EID)) + // Remove all references of physics objects from the world + for (const auto& PHYSICS_OBJECT : objectManager.GetPhysicsObjects() | std::views::values) { - objectManager.AddCollider(EID); + if (PHYSICS_OBJECT.body) + { + // Remove all colliders and destroy world + int32_t numShapes = static_cast(PHYSICS_OBJECT.body->getNbColliders()); + while (--numShapes >= 0) + { + auto* rp3dCollider = PHYSICS_OBJECT.body->getCollider(numShapes); + PHYSICS_OBJECT.body->removeCollider(rp3dCollider); + } - auto* COLLIDER = SHComponentManager::GetComponent(EID); - for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i) - objectManager.AddCollisionShape(EID, i); + worldState.world->destroyRigidBody(PHYSICS_OBJECT.body); + } } - }; - //////////////////////////////// - - // Create physics world - if (worldState.world != nullptr) - return onPlayEvent->handle; + worldState.DestroyWorld(factory); + } + // Create the physics world & collision space worldState.CreateWorld(factory); -#ifdef _PUBLISH - worldState.world->setIsDebugRenderingEnabled(false); -#else - worldState.world->setIsDebugRenderingEnabled(true); -#endif - // Link Collision Listener & Raycaster + // Link with managers + objectManager.SetPhysicsWorld(worldState.world); + objectManager.FlushDefinitions(); + collisionListener.BindToWorld(worldState.world); - raycaster.BindToWorld(worldState.world); - // Link with object manager & create all physics objects - objectManager.SetWorld(worldState.world); - - // Build scene - SHSceneManager::GetCurrentSceneGraph().Traverse(BUILD_PHYSICS_OBJECT); - objectManager.UpdateCommands(); - - return onPlayEvent->handle; + return onSceneInitEvent.get()->handle; } - SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent) + SHEventHandle SHPhysicsSystem::onSceneExit(SHEventPtr onSceneExitEvent) { - // Remove all physics objects - objectManager.RemoveAllObjects(); - objectManager.SetWorld(nullptr); + /* + * Destroy the physics world. + * Destroy all physics objects. + */ - // Clear all collision info - // Collision listener is automatically unbound when world is destroyed - collisionListener.ClearContainers(); - raycaster.ClearFrame(); + if (worldState.world) + { + // Remove all references of physics objects from the world + for (const auto& PHYSICS_OBJECT : objectManager.GetPhysicsObjects() | std::views::values) + { + if (PHYSICS_OBJECT.body) + worldState.world->destroyRigidBody(PHYSICS_OBJECT.body); + } - // Destroy the world - worldState.DestroyWorld(factory); + worldState.DestroyWorld(factory); + } - return onStopEvent->handle; + // Unlink with managers + objectManager.SetPhysicsWorld(nullptr); + + return onSceneExitEvent.get()->handle; } + + SHEventHandle SHPhysicsSystem::onComponentAdded(SHEventPtr onComponentAddedEvent) + { + static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID(); + static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID(); + + const auto& EVENT_DATA = reinterpret_cast*>(onComponentAddedEvent.get())->data; + + const auto ADDED_ID = EVENT_DATA->addedComponentType; + + const bool IS_RIGID_BODY = ADDED_ID == RIGID_BODY_COMPONENT_ID; + const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID; + + // Check if its a physics component + const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER; + if (!IS_PHYSICS_COMPONENT) + return onComponentAddedEvent.get()->handle; + + const EntityID EID = EVENT_DATA->eid; + + // Link engine components with physics object component + if (IS_RIGID_BODY) + { + if (worldState.world) + objectManager.AddRigidBody(EID); + else + objectManager.AddRigidBodyDef(EID); + } + + if (IS_COLLIDER) + { + if (worldState.world) + objectManager.AddCollider(EID); + else + objectManager.AddColliderDef(EID); + } + + return onComponentAddedEvent.get()->handle; + } + + SHEventHandle SHPhysicsSystem::onComponentRemoved(SHEventPtr onComponentRemovedEvent) + { + static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID(); + static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID(); + + const auto& EVENT_DATA = reinterpret_cast*>(onComponentRemovedEvent.get())->data; + + const auto REMOVED_DATA = EVENT_DATA->removedComponentType; + + const bool IS_RIGID_BODY = REMOVED_DATA == RIGID_BODY_COMPONENT_ID; + const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID; + + // Check if its a physics component + const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER; + if (!IS_PHYSICS_COMPONENT) + return onComponentRemovedEvent.get()->handle; + + const EntityID EID = EVENT_DATA->eid; + + if (IS_RIGID_BODY) + objectManager.RemoveRigidBody(EID); + + if (IS_COLLIDER) + objectManager.RemoveCollider(EID); + + return onComponentRemovedEvent.get()->handle; + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index 99db493e..312c3625 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -10,8 +10,7 @@ #pragma once -#include -#include +#include // External Dependencies #include @@ -19,14 +18,11 @@ // Project Headers #include "ECS_Base/System/SHSystemRoutine.h" #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/SHPhysicsWorld.h" +#include "Physics/Collision/SHCollisionInfo.h" +#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h" +#include "Physics/RP3DWrapper/SHPhysicsWorld.h" +#include "Physics/RP3DWrapper/SHCollisionListener.h" +#include "Physics/RP3DWrapper/SHRaycaster.h" #include "Scene/SHSceneGraph.h" namespace SHADE @@ -43,254 +39,150 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsDebugDrawSystem; + friend class SHCollisionListener; + friend class SHRaycaster; public: + + /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHPhysicsSystem(); + SHPhysicsSystem () noexcept; + ~SHPhysicsSystem() noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedUpdateRate () const noexcept; - [[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept; + [[nodiscard]] double GetFixedUpdateRate () const noexcept; + [[nodiscard]] double GetFixedDT () const noexcept; - [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; - [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllTriggerInfo () const noexcept; + [[nodiscard]] const std::vector& GetAllCollisionInfo () const noexcept; - [[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept; - [[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFixedUpdateRate (double fixedUpdateRate) noexcept; - void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept; - + void SetFixedUpdateRate (double fixedUpdateRate) noexcept; + void SetFixedDT (double fixedDt) noexcept; /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - void Init () override; - void Exit () override; - - void BuildScene (SHSceneGraph& sceneGraph); - void ForceBuild (SHSceneGraph& sceneGraph); - void ForceUpdate (); + /** + * @brief + * - Initialises the static collision tag matrix. + * - Registers the system to catch specific events. + */ + void Init() override; + void Exit() override; /** - * @brief Casts a ray into the world. - * @param ray The ray to cast. - * @param distance The distance to cast the ray. Defaults to infinity. - * @param collisionTag The collision tag to use for filtering the raycast. - * @return The result of the raycast. - */ - SHPhysicsRaycastResult Raycast - ( - const SHRay& ray - , float distance = std::numeric_limits::infinity() - , const SHCollisionTag& collisionTag = SHCollisionTag{} - ) noexcept; - - /** - * @brief Casts a bounded ray into the world. - * @param start The starting point of the ray. - * @param end The end point of the ray. - * @param collisionTag The collision tag to use for filtering the bounded raycast. - * @return The result of the raycast. - */ - SHPhysicsRaycastResult Linecast - ( - const SHVec3& start - , const SHVec3& end - , const SHCollisionTag& collisionTag = SHCollisionTag{} - ) noexcept; - - /** - * @brief Casts a ray at a body with colliders. - * @param eid The entity to cast to. - * @param ray The ray to cast. - * @param distance The distance to cast the ray. Defaults to infinity. - * @return The result of the raycast. - */ - SHPhysicsRaycastResult ColliderRaycast - ( - EntityID eid - , const SHRay& ray - , float distance = std::numeric_limits::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() - ) noexcept; - - /** - * @brief Casts a bounded ray at a body with colliders. - * @param eid - * @param start - * @param end - * @return The result of the raycast. - */ - SHPhysicsRaycastResult ColliderLinecast - ( - EntityID eid - , const SHVec3& start - , const SHVec3& end - ) noexcept; - - /** - * @brief - * @param eid - * @param shapeIndex - * @param start - * @param end - * @return The result of the raycast. - */ - SHPhysicsRaycastResult ColliderLinecast - ( - EntityID eid - , int shapeIndex - , const SHVec3& start - , const SHVec3& end - ) noexcept; - - // Specific Handling for Collision Shapes as they are not under the Component System. - // This is done as events need to be sent out. - // TODO(Diren): Consider using a static method through the ColliderComponent. - - void AddCollisionShape (EntityID eid, int shapeIndex); - void RemoveCollisionShape (EntityID eid, int shapeIndex); + * @brief + * Casts a ray into the collision space. + * @param info + * Contains the information for the raycast. + * @return + * A container of the objects hit by the ray. If nothing was hit, the container + * will be empty. + */ + [[nodiscard]] const std::vector& Raycast(const SHRaycaster::RaycastInfo& info) noexcept; /*---------------------------------------------------------------------------------*/ /* System Routines */ /*---------------------------------------------------------------------------------*/ + /** + * @brief + * The physics update routine that runs before the simulation is updated. + * This is always running, regardless of the editor state. + *
+ * This update game logic is applied before the simulation runs. + */ class SH_API PhysicsPreUpdate final : public SHSystemRoutine { public: - /*-------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*-------------------------------------------------------------------------------*/ - PhysicsPreUpdate(); - - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - void Execute(double dt) noexcept override; - - private: - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - - void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; - void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; - static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; - - static void preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent* transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept; }; - class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine + /** + * @brief + * The physics update routine that runs at a fixed rate. This is where the main + * simulation runs. If delta time is large enough, this may run more than once per + * frame. If delta time is small enough, this may not run at all. + */ + class SH_API PhysicsUpdate final : public SHFixedSystemRoutine { public: - /*-------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*-------------------------------------------------------------------------------*/ - - PhysicsFixedUpdate(); - - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - - void Execute (double dt) noexcept override; + PhysicsUpdate(); + void Execute(double dt) noexcept override; }; + /** + * @brief + * The physics update that runs after the simulation. This sets the rendering + * transforms and sends messages to scripting system for collision & trigger events.
+ * + */ class SH_API PhysicsPostUpdate final : public SHSystemRoutine { public: - /*-------------------------------------------------------------------------------*/ - /* Constructors & Destructor */ - /*-------------------------------------------------------------------------------*/ - PhysicsPostUpdate(); - - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - void Execute(double dt) noexcept override; - - private: - - /*-------------------------------------------------------------------------------*/ - /* Function Members */ - /*-------------------------------------------------------------------------------*/ - - static void postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent* transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept; }; private: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + using EventFunctionPair = std::pair; + + struct RaycastHit + { + SHVec3 start; + SHVec3 end; + }; + /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ - // System data + static constexpr int NUM_EVENT_FUNCTIONS = 4; + // Event function container for cleanly registering to events + EventFunctionPair eventFunctions[NUM_EVENT_FUNCTIONS]; + + // System data bool worldUpdated; double interpolationFactor; double fixedDT; - // rp3d + // Sub-systems / managers rp3d::PhysicsCommon factory; - - // Interface objects - SHPhysicsWorldState worldState; SHPhysicsObjectManager objectManager; SHCollisionListener collisionListener; - SHPhysicsRaycaster raycaster; + SHRaycaster raycaster; + + // For the debug drawer to draw rays + #ifdef SHEDITOR + std::vector raycastHits; + #endif /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept; - SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept; + SHEventHandle onSceneInit (SHEventPtr onSceneInitEvent); + SHEventHandle onSceneExit (SHEventPtr onSceneExitEvent); - SHEventHandle onPlay (SHEventPtr onPlayEvent); - SHEventHandle onStop (SHEventPtr onStopEvent); - SHEventHandle buildScene (SHEventPtr onSceneChangeEvent); + SHEventHandle onComponentAdded (SHEventPtr onComponentAddedEvent); + SHEventHandle onComponentRemoved (SHEventPtr onComponentRemovedEvent); }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp index 1fb11274..f1326bed 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.cpp @@ -52,85 +52,43 @@ namespace SHADE double SHPhysicsSystemInterface::GetFixedDT() noexcept { - auto phySystem = SHSystemManager::GetSystem(); - if (phySystem) - { - return 1.0 / phySystem->GetFixedUpdateRate(); - } + auto* physicsSystem = SHSystemManager::GetSystem(); + if (physicsSystem) + return physicsSystem->GetFixedDT(); SHLOGV_WARNING("Failed to get fixed delta time. 0.0 returned instead."); return 0.0; } - SHPhysicsRaycastResult SHPhysicsSystemInterface::Raycast(const SHRay& ray, float distance) noexcept + int SHPhysicsSystemInterface::GetFixedUpdateRate() noexcept { auto* physicsSystem = SHSystemManager::GetSystem(); if (physicsSystem) - { - return physicsSystem->Raycast(ray, distance); - } + return physicsSystem->GetFixedUpdateRate(); - SHLOGV_WARNING("Failed to get the physics system. No ray was casted."); - return SHPhysicsRaycastResult{}; + SHLOGV_WARNING("Failed to get fixed update rate. 0.0 returned instead."); + return 0.0; } - SHPhysicsRaycastResult SHPhysicsSystemInterface::Linecast(const SHVec3& start, const SHVec3& end) noexcept + const std::vector& SHPhysicsSystemInterface::Raycast(const RaycastInfo& info) noexcept { + static std::vector emptyVec; + auto* physicsSystem = SHSystemManager::GetSystem(); if (physicsSystem) { - return physicsSystem->Linecast(start, end); + SHRaycaster::RaycastInfo raycastInfo; + raycastInfo.continuous = info.continuous; + raycastInfo.distance = info.distance; + raycastInfo.layers = info.layers; + raycastInfo.ray = info.ray; + + if (info.colliderEntityID.has_value()) + raycastInfo.SetColliderID(info.colliderEntityID.value()); + + return physicsSystem->Raycast(raycastInfo); } - 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{}; + return emptyVec; } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h index 0065aee3..8815e674 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystemInterface.h @@ -12,11 +12,13 @@ of DigiPen Institute of Technology is prohibited. #pragma once // STL Includes +#include #include // Project Headers #include "ECS_Base/Entity/SHEntity.h" - +#include "Math/SHRay.h" +#include "Physics/Collision/CollisionTags/SHCollisionTags.h" namespace SHADE { @@ -25,11 +27,8 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ class SHCollisionInfo; - class SHVec3; - struct SHRay; struct SHPhysicsRaycastResult; - /*-----------------------------------------------------------------------------------*/ /* Type Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -39,7 +38,49 @@ namespace SHADE /// class SH_API SHPhysicsSystemInterface final { + public: + + struct RaycastInfo + { + private: + /*-------------------------------------------------------------------------------*/ + /* Friends */ + /*-------------------------------------------------------------------------------*/ + + friend class SHPhysicsSystemInterface; + public: + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + bool continuous = false; + uint16_t layers = static_cast(SHCollisionTag::Layer::ALL); + float distance = std::numeric_limits::infinity(); + SHRay ray; + + /*-------------------------------------------------------------------------------*/ + /* Setter Functions */ + /*-------------------------------------------------------------------------------*/ + + /** + * @brief + * Sets the collider ID for the raycast. Setting this specifies that the ray + * should ignore this collider. + * @param eid + * The entity ID of the collider. + */ + void SetColliderID(EntityID eid) noexcept { colliderEntityID = eid; } + + private: + /*-------------------------------------------------------------------------------*/ + /* Data Members */ + /*-------------------------------------------------------------------------------*/ + + std::optional colliderEntityID; + }; + + /*---------------------------------------------------------------------------------*/ /* Constructor */ /*---------------------------------------------------------------------------------*/ @@ -49,15 +90,11 @@ 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 int GetFixedUpdateRate () noexcept; + [[nodiscard]] static const std::vector& Raycast (const RaycastInfo& info) 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_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp deleted file mode 100644 index a5ca957a..00000000 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystemRoutines.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/**************************************************************************************** - * \file SHPhysicsSystemRoutines.h - * \author Diren D Bharwani, diren.dbharwani, 390002520 - * \brief Implementation for the Physics System Routines - * - * \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 "SHPhysicsSystem.h" -// Project Headers -#include "ECS_Base/Managers/SHEntityManager.h" -#include "ECS_Base/Managers/SHSystemManager.h" -#include "Editor/SHEditor.h" -#include "Scene/SHSceneManager.h" -#include "Scripting/SHScriptEngine.h" - -#include "Input/SHInputManager.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" - -/*-------------------------------------------------------------------------------------*/ -/* Local Functions */ -/*-------------------------------------------------------------------------------------*/ - -void testFunction(); - -///////////////////////////////////////////////////////////////////////////////////////// - -namespace SHADE -{ - /*-----------------------------------------------------------------------------------*/ - /* Constructors & Destructor Definitions */ - /*-----------------------------------------------------------------------------------*/ - - SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate() - : SHSystemRoutine { "Physics PreUpdate", true } - {} - - SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate() - : SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false } - {} - - SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate() - : SHSystemRoutine { "Physics PostUpdate", false } - {} - - /*-----------------------------------------------------------------------------------*/ - /* Public Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept - { - auto* physicsSystem = reinterpret_cast(GetSystem()); - - #ifdef SHEDITOR - - // Only Sync on Play. - // Otherwise, Components are only holding data until the world is built on play. - const auto* EDITOR = SHSystemManager::GetSystem(); - if (EDITOR && EDITOR->editorState != SHEditor::State::STOP) - { - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - // Sync active states between SHADE & RP3D - syncRigidBodyActive(entityID, physicsObject); - syncColliderActive(entityID, physicsObject); - - syncOnPlay(entityID, physicsObject); - } - } - else - { - auto& rigidBodyDense = SHComponentManager::GetDense(); - auto& colliderDense = SHComponentManager::GetDense(); - - for (auto& rigidBodyComponent : rigidBodyDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(rigidBodyComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - rigidBodyComponent.position = TRANSFORM->GetWorldPosition(); - rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation(); - } - } - - for (auto& colliderComponent : colliderDense) - { - const auto* TRANSFORM = SHComponentManager::GetComponent_s(colliderComponent.GetEID()); - - if (TRANSFORM && TRANSFORM->HasChanged()) - { - colliderComponent.position = TRANSFORM->GetWorldPosition(); - colliderComponent.orientation = TRANSFORM->GetWorldOrientation(); - colliderComponent.scale = TRANSFORM->GetWorldScale(); - - colliderComponent.RecomputeCollisionShapes(); - } - } - } - - #else - - // Always sync Rigid Body & Collider Components with Physics Objects - // Do not check for an editor here - - physicsSystem->objectManager.UpdateCommands(); - - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - // Ensure a valid physics Object - if (physicsObject.rp3dBody == nullptr) - continue; - - syncRigidBodyActive(entityID, physicsObject); - syncColliderActive(entityID, physicsObject); - - syncOnPlay(entityID, physicsObject); - } - - #endif - } - - void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept - { - auto* physicsSystem = reinterpret_cast(GetSystem()); - auto* scriptingSystem = SHSystemManager::GetSystem(); - if (scriptingSystem == nullptr) - { - SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!"); - } - - const double FIXED_DT = physicsSystem->fixedDT; - // HACK: Clamp DT here to prevent a ridiculous amount of updates. This limits updates from large dt to 2. - // HACK: This should be done by the FRC and not here for predictable behaviour. - - accumulatedTime += dt; - - //testFunction(); - - int count = 0; - while (accumulatedTime > FIXED_DT) - { - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteFixedUpdates(); - - physicsSystem->worldState.world->update(static_cast(FIXED_DT)); - - accumulatedTime -= FIXED_DT; - ++count; - } - - stats.numSteps = count; - physicsSystem->worldUpdated = count > 0; - - physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep; - } - - void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept - { - auto* physicsSystem = reinterpret_cast(GetSystem()); - auto* scriptingSystem = SHSystemManager::GetSystem(); - - if (scriptingSystem == nullptr) - { - SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!"); - } - - // Interpolate transforms for rendering - if (physicsSystem->worldUpdated) - { - for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects) - { - auto* transformComponent = SHComponentManager::GetComponent_s(entityID); - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(entityID); - auto* colliderComponent = SHComponentManager::GetComponent_s(entityID); - - postUpdateSyncTransforms - ( - physicsObject - , transformComponent - , rigidBodyComponent - , colliderComponent - , physicsSystem->interpolationFactor - ); - } - - // Collision & Trigger messages - if (scriptingSystem != nullptr) - scriptingSystem->ExecuteCollisionFunctions(); - - // Since this function never runs when editor in not in play, execute the function anyway - physicsSystem->collisionListener.CleanContainers(); - } - } - - /*-----------------------------------------------------------------------------------*/ - /* Private Function Member Definitions */ - /*-----------------------------------------------------------------------------------*/ - - void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept - { - if (!SHComponentManager::HasComponent(eid)) - return; - - const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); - const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive(); - - if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE) - physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE); - } - - void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept - { - const auto* COLLIDER = SHComponentManager::GetComponent_s(eid); - if (!COLLIDER) - return; - - const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive(eid); - const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive; - - if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE) - { - // HACK: If active state turned off, remove all collision shapes. If turned on, add them back. - auto* physicsSystem = reinterpret_cast(GetSystem()); - - const int NUM_SHAPES = static_cast(COLLIDER->GetCollisionShapes().size()); - if (IS_ACTIVE_IN_SCENE) - { - for (int i = 0; i < NUM_SHAPES; ++i) - physicsSystem->objectManager.AddCollisionShape(eid, i); - } - else - { - for (int i = NUM_SHAPES - 1; i >= 0; --i) - physicsSystem->objectManager.RemoveCollisionShape(eid, i); - } - - physicsObject.collidersActive = IS_ACTIVE_IN_SCENE; - } - } - - void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept - { - auto* transformComponent = SHComponentManager::GetComponent_s(eid); - auto* rigidBodyComponent = SHComponentManager::GetComponent_s(eid); - auto* colliderComponent = SHComponentManager::GetComponent_s(eid); - - // Sync transforms & physics components transforms - if (transformComponent && transformComponent->HasChanged()) - { - physicsObject.GetRigidBody()->setIsSleeping(false); - - preUpdateSyncTransform - ( - physicsObject - , transformComponent - , rigidBodyComponent - , colliderComponent - ); - } - - // Sync Rigid Bodies - if (rigidBodyComponent) - physicsObject.SyncRigidBody(*rigidBodyComponent); - - // Sync Colliders - if (colliderComponent) - physicsObject.SyncColliders(*colliderComponent); - } - - void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform - ( - SHPhysicsObject& physicsObject - , SHTransformComponent* transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - ) noexcept - { - if (!transformComponent) - return; - - const SHVec3& WORLD_POS = transformComponent->GetWorldPosition(); - const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation(); - const SHVec3& WORLD_SCL = transformComponent->GetWorldScale(); - - const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT }; - physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM); - physicsObject.prevTransform = RP3D_TRANSFORM; - - if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) - { - rigidBodyComponent->position = WORLD_POS; - rigidBodyComponent->orientation = WORLD_ROT; - } - - if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) - { - colliderComponent->position = WORLD_POS; - colliderComponent->orientation = WORLD_ROT; - colliderComponent->scale = WORLD_SCL; - - colliderComponent->RecomputeCollisionShapes(); - } - } - - void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms - ( - SHPhysicsObject& physicsObject - , SHTransformComponent* transformComponent - , SHRigidBodyComponent* rigidBodyComponent - , SHColliderComponent* colliderComponent - , double interpolationFactor - ) noexcept - { - const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform(); - auto renderPos = CURRENT_TF.getPosition(); - auto renderRot = CURRENT_TF.getOrientation(); - - // Cache transforms - if (physicsObject.GetRigidBody()->isActive()) - physicsObject.prevTransform = CURRENT_TF; - - // Sync with rigid bodies - if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) - { - // Skip static bodies - if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC) - return; - - // Check if transform should be interpolated - if (rigidBodyComponent->IsInterpolating()) - { - // Interpolate transforms between current and predicted next transform - - const rp3d::Transform PREV_TF = physicsObject.prevTransform; - const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast(interpolationFactor)); - - renderPos = INTERPOLATED_TF.getPosition(); - renderRot = INTERPOLATED_TF.getOrientation(); - } - - rigidBodyComponent->position = CURRENT_TF.getPosition(); - rigidBodyComponent->orientation = CURRENT_TF.getOrientation(); - - // Sync with colliders - if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive(physicsObject.entityID)) - { - // Skip colliders without rigidbody components. If any transform was updated, it was done in pre-update. - - colliderComponent->position = CURRENT_TF.getPosition(); - colliderComponent->orientation = CURRENT_TF.getOrientation(); - } - - // Set transform for rendering - if (transformComponent) - { - transformComponent->SetWorldPosition(renderPos); - transformComponent->SetWorldOrientation(renderRot); - } - } - } -} // namespace SHADE - -///////////////////////////////////////////////////////////////////////////////////////// - -void testFunction() -{ - using namespace SHADE; - - // Test movement - const float forceModifier = 25.0f; - EntityID eid = 65538; - - if (SHEntityManager::IsValidEID(eid)) - { - auto* rb = SHComponentManager::GetComponent_s(eid); - if (rb) - { - if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W)) - rb->AddForce(SHVec3::UnitZ * forceModifier); - - if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A)) - rb->AddForce(-SHVec3::UnitX * forceModifier); - - if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S)) - rb->AddForce(-SHVec3::UnitZ * forceModifier); - - if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D)) - rb->AddForce(SHVec3::UnitX * forceModifier); - } - } - - // Cast rays - auto* tag = SHCollisionTagMatrix::GetTag(1); - tag->SetLayerState(SHCollisionTag::Layer::_1, false); - tag->SetLayerState(SHCollisionTag::Layer::_2, true); - - SHRay ray { SHVec3{3.0f, 3.5f, 0.0f}, -SHVec3::UnitX }; - auto* physicsSystem = SHSystemManager::GetSystem(); - physicsSystem->Raycast(ray, std::numeric_limits::infinity(), *tag); -} diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index fb35ea2c..6c019874 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -3,9 +3,8 @@ #include "Physics/Interface/SHColliderComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" -#include "Math/Geometry/SHBox.h" -#include "Math/Geometry/SHSphere.h" -#include "Physics/Interface/SHCollisionShape.h" +#include "Physics/Collision/Shapes/SHSphere.h" +#include "Physics/Collision/Shapes/SHBox.h" #include "Resource/SHResourceManager.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" @@ -15,7 +14,7 @@ #include "SHSerializationTools.h" #include "Graphics/MiddleEnd/TextRendering/SHFont.h" #include "Animation/SHAnimatorComponent.h" -#include "Physics/Collision/SHCollisionTagMatrix.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" namespace YAML { @@ -149,17 +148,17 @@ namespace YAML { case SHCollisionShape::Type::BOX: { - const auto* BOX = reinterpret_cast(rhs.GetShape()); - node[HalfExtents] = BOX->GetRelativeExtents(); + const auto& BOX_SHAPE = dynamic_cast(rhs); + node[HalfExtents] = BOX_SHAPE.GetRelativeExtents(); } break; case SHCollisionShape::Type::SPHERE: { - const auto* SPHERE = reinterpret_cast(rhs.GetShape()); - node[Radius] = SPHERE->GetRelativeRadius(); + const auto& SPHERE_SHAPE = dynamic_cast(rhs); + node[Radius] = SPHERE_SHAPE.GetRelativeRadius(); } break; - case SHCollisionShape::Type::CAPSULE: break; + //case SHCollisionShape::Type::CAPSULE: break; default:; } @@ -192,16 +191,16 @@ namespace YAML case SHCollisionShape::Type::BOX: { if (node[HalfExtents].IsDefined()) - rhs.SetBoundingBox(node[HalfExtents].as()); + dynamic_cast(rhs).SetRelativeExtents(node[HalfExtents].as()); } break; case SHCollisionShape::Type::SPHERE: { if (node[Radius].IsDefined()) - rhs.SetBoundingSphere(node[Radius].as()); + dynamic_cast(rhs).SetRelativeRadius(node[Radius].as()); } break; - case SHCollisionShape::Type::CAPSULE: break; + //case SHCollisionShape::Type::CAPSULE: break; default:; } if (node[Friction].IsDefined()) @@ -254,9 +253,9 @@ namespace YAML switch (colliderType) { - case SHCollisionShape::Type::BOX: rhs.AddBoundingBox(); break; - case SHCollisionShape::Type::SPHERE: rhs.AddBoundingSphere(); break; - case SHCollisionShape::Type::CAPSULE: break; + case SHCollisionShape::Type::BOX: rhs.AddBoxCollisionShape(SHVec3::One); break; + case SHCollisionShape::Type::SPHERE: rhs.AddSphereCollisionShape(1.0f); break; + //case SHCollisionShape::Type::CAPSULE: break; default:; } YAML::convert::decode(colliderNode, rhs.GetCollisionShape(numColliders++)); diff --git a/SHADE_Managed/src/Components/Collider.cxx b/SHADE_Managed/src/Components/Collider.cxx index b5f1444f..ac191cdd 100644 --- a/SHADE_Managed/src/Components/Collider.cxx +++ b/SHADE_Managed/src/Components/Collider.cxx @@ -4,7 +4,6 @@ \par email: kahwei.tng\@digipen.edu \date Oct 20, 2022 \brief Contains the definition of the functions of the managed Collider class. - Note: This file is written in C++17/CLI. Copyright (C) 2022 DigiPen Institute of Technology. @@ -15,11 +14,14 @@ of DigiPen Institute of Technology is prohibited. #include "SHpch.h" // Primary Header #include "Collider.hxx" + +#include "Physics/Collision/Shapes/SHBox.h" +#include "Physics/Collision/Shapes/SHSphere.h" #include "Utility/Debug.hxx" namespace SHADE { - /*---------------------------------------------------------------------------------*/ + /*---------------------------------------------------------------------------------*/ /* CollisionShape - Constructors */ /*---------------------------------------------------------------------------------*/ CollisionShape::CollisionShape(int arrayIdx, Entity attachedEntity) @@ -120,7 +122,7 @@ namespace SHADE /* BoxCollider - Constructors */ /*---------------------------------------------------------------------------------*/ BoxCollider::BoxCollider(int arrayIdx, Entity attachedEntity) - : CollisionShape { arrayIndex, attachedEntity } + : CollisionShape { arrayIdx, attachedEntity } {} /*---------------------------------------------------------------------------------*/ @@ -128,35 +130,20 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 BoxCollider::Center::get() { - return Convert::ToCLI(getNativeCollisionShape().GetCenter()); - } - void BoxCollider::Center::set(Vector3 value) - { - getNativeCollisionShape().SetCenter(Convert::ToNative(value)); + return Convert::ToCLI(getNativeCollisionShape().GetWorldCentroid()); } Vector3 BoxCollider::HalfExtents::get() { - return Convert::ToCLI(getNativeCollisionShape().GetWorldExtents()); + return Convert::ToCLI(getNativeCollisionShape().GetWorldExtents()); } void BoxCollider::HalfExtents::set(Vector3 value) { - getNativeCollisionShape().SetWorldExtents(Convert::ToNative(value)); + getNativeCollisionShape().SetWorldExtents(Convert::ToNative(value)); } - Vector3 BoxCollider::Min::get() + Quaternion BoxCollider::Orientation::get() { - return Convert::ToCLI(getNativeCollisionShape().GetMin()); - } - void BoxCollider::Min::set(Vector3 value) - { - getNativeCollisionShape().SetMin(Convert::ToNative(value)); - } - Vector3 BoxCollider::Max::get() - { - return Convert::ToCLI(getNativeCollisionShape().GetMax()); - } - void BoxCollider::Max::set(Vector3 value) - { - getNativeCollisionShape().SetMax(Convert::ToNative(value)); + //return Convert::ToCLI(getNativeCollisionShape().GetWorldOrientation()); + return Quaternion::Identity; } /*---------------------------------------------------------------------------------*/ @@ -164,11 +151,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool BoxCollider::TestPoint(Vector3 point) { - return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + //return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + return false; } bool BoxCollider::Raycast(Ray ray, float maxDistance) { - return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + //return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + return false; } /*---------------------------------------------------------------------------------*/ @@ -176,19 +165,15 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ Vector3 SphereCollider::Center::get() { - return Convert::ToCLI(getNativeCollisionShape().GetCenter()); - } - void SphereCollider::Center::set(Vector3 value) - { - getNativeCollisionShape().SetCenter(Convert::ToNative(value)); + return Convert::ToCLI(getNativeCollisionShape().GetWorldCentroid()); } float SphereCollider::Radius::get() { - return getNativeCollisionShape().GetWorldRadius(); + return getNativeCollisionShape().GetWorldRadius(); } void SphereCollider::Radius::set(float value) { - getNativeCollisionShape().SetWorldRadius(value); + getNativeCollisionShape().SetWorldRadius(value); } /*---------------------------------------------------------------------------------*/ @@ -196,11 +181,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ bool SphereCollider::TestPoint(Vector3 point) { - return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + //return getNativeCollisionShape().TestPoint(Convert::ToNative(point)); + return false; } bool SphereCollider::Raycast(Ray ray, float maxDistance) { - return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + //return getNativeCollisionShape().Raycast(Convert::ToNative(ray)); + return false; } /*---------------------------------------------------------------------------------*/ @@ -231,7 +218,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ int Collider::CollisionShapeCount::get() { - return static_cast(GetNativeComponent()->GetCollisionShapes().size()); + if (const auto* nativeComponent = GetNativeComponent(); nativeComponent) + return static_cast(nativeComponent->GetCollisionShapes().size()); + + return -1; } /*---------------------------------------------------------------------------------*/ @@ -314,7 +304,7 @@ namespace SHADE for (const auto& collider : GetNativeComponent()->GetCollisionShapes()) { CollisionShape^ bound = nullptr; - switch (collider.GetType()) + switch (collider->GetType()) { case SHCollisionShape::Type::BOX: bound = gcnew BoxCollider(i, Owner.GetEntity()); @@ -322,9 +312,9 @@ namespace SHADE case SHCollisionShape::Type::SPHERE: bound = gcnew SphereCollider(i, Owner.GetEntity()); break; - case SHCollisionShape::Type::CAPSULE: - // TODO - break; + //case SHCollisionShape::Type::CAPSULE: + // // TODO + // break; default: Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping."); break; @@ -335,4 +325,4 @@ namespace SHADE subColliderList->Add(bound); } } -} +} \ No newline at end of file diff --git a/SHADE_Managed/src/Components/Collider.h++ b/SHADE_Managed/src/Components/Collider.h++ index 8ea648aa..b16e8063 100644 --- a/SHADE_Managed/src/Components/Collider.h++ +++ b/SHADE_Managed/src/Components/Collider.h++ @@ -31,7 +31,7 @@ namespace SHADE if (shape.GetType() != SHCollisionShape::Type::BOX) throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); - return reinterpret_cast(shape); + return dynamic_cast(shape); } catch (std::invalid_argument&) { diff --git a/SHADE_Managed/src/Components/Collider.hxx b/SHADE_Managed/src/Components/Collider.hxx index a649483f..3c7b060e 100644 --- a/SHADE_Managed/src/Components/Collider.hxx +++ b/SHADE_Managed/src/Components/Collider.hxx @@ -1,7 +1,9 @@ /************************************************************************************//*! \file Collider.hxx \author Tng Kah Wei, kahwei.tng, 390009620 + Diren D Bharwani, diren.dbharwani, 390002520 \par email: kahwei.tng\@digipen.edu + email: diren.dbharwani\@digipen.edu \date Oct 20, 2022 \brief Contains the definition of the managed Collider class with the declaration of functions for working with it. @@ -142,15 +144,14 @@ namespace SHADE /* Properties */ /*-----------------------------------------------------------------------------*/ /// - /// Center of the Bounding Box formed by this bound. + /// Center of the box collider. /// property Vector3 Center { Vector3 get(); - void set(Vector3 value); } /// - /// Half of the scale of the Bounding Box formed by this bound. + /// Half of the scale of the box collider. /// property Vector3 HalfExtents { @@ -158,22 +159,11 @@ namespace SHADE void set(Vector3 value); } /// - /// Position of the bottom left back corner of the Bounding Box formed by this - /// bound. + /// The orientation of the box. /// - property Vector3 Min + property Quaternion Orientation { - Vector3 get(); - void set(Vector3 value); - } - /// - /// Position of the top right front corner of the Bounding Box formed by this - /// bound. - /// - property Vector3 Max - { - Vector3 get(); - void set(Vector3 value); + Quaternion get(); } /*-----------------------------------------------------------------------------*/ @@ -201,12 +191,11 @@ namespace SHADE /* Properties */ /*-----------------------------------------------------------------------------*/ /// - /// Center of the Bounding Sphere formed by this bound. + /// Center of the sphere. /// property Vector3 Center { Vector3 get(); - void set(Vector3 value); } /// /// Radius of the Bounding Sphere formed by this bound. diff --git a/SHADE_Managed/src/Physics/Physics.cxx b/SHADE_Managed/src/Physics/Physics.cxx index 9e2c1413..e5c376d2 100644 --- a/SHADE_Managed/src/Physics/Physics.cxx +++ b/SHADE_Managed/src/Physics/Physics.cxx @@ -15,10 +15,14 @@ // External Dependencies #include "Physics/System/SHPhysicsSystemInterface.h" // Project Header +#include "Components/Collider.hxx" +#include "Components/Transform.hxx" #include "Engine/GameObject.hxx" #include "Utility/Convert.hxx" #include "Utility/Debug.hxx" +using namespace System::Collections::Generic; + namespace SHADE { /*-----------------------------------------------------------------------------------*/ @@ -41,49 +45,262 @@ namespace SHADE /* Raycast Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - RaycastHit Physics::Raycast(Ray ray) + List^ Physics::Raycast(Ray ray, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray))); + List^ results = gcnew List(); + + // Cast natively + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.continuous = continuous; + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::Raycast(Ray ray, float distance) + List^ Physics::Raycast(Ray ray, float distance, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray), distance)); + List^ results = gcnew List(); + + // Cast natively + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.distance = distance; + raycastInfo.continuous = continuous; + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::Linecast(Vector3 start, Vector3 end) + List^ Physics::Linecast(Vector3 start, Vector3 end, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::Linecast(Convert::ToNative(start), Convert::ToNative(end))); + List^ results = gcnew List(); + + // Cast natively + Vector3 direction = end - start; + direction.Normalise(); + const Ray CLI_RAY( start, direction ); + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(CLI_RAY); + raycastInfo.distance = (end - start).GetMagnitude(); + raycastInfo.continuous = continuous; + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray) + List^ Physics::ColliderRaycast(GameObject object, Ray ray, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray))); + List^ results = gcnew List(); + + // Get the collider's position (same as the transform) + Transform^ managedTransform = object.GetComponent(); + if (!managedTransform) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform."); + + const Vector3 COLLIDER_POS = managedTransform->GlobalPosition; + ray.Position += COLLIDER_POS; + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.continuous = continuous; + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray, float distance) + List^ Physics::ColliderRaycast(GameObject object, Ray ray, float distance, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray), distance)); + List^ results = gcnew List(); + + // Get the collider's position (same as the transform) + Transform^ managedTransform = object.GetComponent(); + if (!managedTransform) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform."); + + const Vector3 COLLIDER_POS = managedTransform->GlobalPosition; + ray.Position += COLLIDER_POS; + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.distance = distance; + raycastInfo.continuous = continuous; + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray) + List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray))); + List^ results = gcnew List(); + + // Get the collider's position + Vector3 shapePos = Vector3::Zero; + Collider^ managedCollider = object.GetComponent(); + if (!managedCollider) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider."); + + CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex); + if (!managedShape) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); + + const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape(); + shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid()); + + ray.Position += shapePos; + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.continuous = continuous; + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance) + List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray), distance)); + List^ results = gcnew List(); + + // Get the collider's position + Vector3 shapePos = Vector3::Zero; + Collider^ managedCollider = object.GetComponent(); + if (!managedCollider) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider."); + + CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex); + if (!managedShape) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); + + const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape(); + shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid()); + + ray.Position += shapePos; + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(ray); + raycastInfo.continuous = continuous; + raycastInfo.distance = distance; + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end) + List^ Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, Convert::ToNative(start), Convert::ToNative(end))); + List^ results = gcnew List(); + + // Get the collider's position (same as the transform) + Transform^ managedTransform = object.GetComponent(); + if (!managedTransform) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform."); + + const Vector3 COLLIDER_POS = managedTransform->GlobalPosition; + start += COLLIDER_POS; + + Vector3 direction = end - start; + direction.Normalise(); + const Ray CLI_RAY( start, direction ); + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(CLI_RAY); + raycastInfo.distance = (end - start).GetMagnitude(); + raycastInfo.continuous = continuous; + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } - RaycastHit Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end) + List^ Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous) { - return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, shapeIndex, Convert::ToNative(start), Convert::ToNative(end))); + List^ results = gcnew List(); + + // Get the collider's position + Vector3 shapePos = Vector3::Zero; + Collider^ managedCollider = object.GetComponent(); + if (!managedCollider) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider."); + + CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex); + if (!managedShape) + throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape."); + + const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape(); + shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid()); + + start += shapePos; + + Vector3 direction = end - start; + direction.Normalise(); + const Ray CLI_RAY( start, direction ); + + SHPhysicsSystemInterface::RaycastInfo raycastInfo; + raycastInfo.ray = Convert::ToNative(CLI_RAY); + raycastInfo.continuous = continuous; + raycastInfo.distance = (end - start).GetMagnitude(); + raycastInfo.SetColliderID(object.EntityId); + + const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); + if (!NATIVE_RESULTS.empty()) + { + for (const auto& nativeResult : NATIVE_RESULTS) + results->Add(Convert::ToCLI(nativeResult)); + } + + return results; } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Physics/Physics.hxx b/SHADE_Managed/src/Physics/Physics.hxx index f13e5952..573d8cad 100644 --- a/SHADE_Managed/src/Physics/Physics.hxx +++ b/SHADE_Managed/src/Physics/Physics.hxx @@ -40,82 +40,143 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /// - /// Casts an infinite ray into the world. + /// Casts an infinite ray into the world.
+ /// This raycast will stop at the first object hit. ///
/// The ray to cast. - /// The result of the raycast. - static RaycastHit Raycast (Ray ray); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ Raycast (Ray ray, bool continuous); /// /// 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); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ Raycast (Ray ray, float distance, bool continuous); /// /// 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); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ Linecast (Vector3 start, Vector3 end, bool continuous); /// /// 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); + /// + /// The ray to cast.
+ /// The position of the ray is offset from the collider's position. + /// + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, bool continuous); /// /// Casts a ray for a given distance w.r.t a GameObject. /// /// The GameObject to cast the ray to. - /// The ray to cast. + /// + /// The ray to cast.
+ /// The position of the ray is offset from the collider's position. + /// /// The distance to cast the ray. - /// The result of the raycast. - static RaycastHit ColliderRaycast (GameObject object, Ray ray, float distance); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, float distance, bool continuous); /// /// 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); + /// + /// The ray to cast.
+ /// The position of the ray is offset from the collider's position. + /// + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, bool continuous); /// /// 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 ray to cast.
+ /// The position of the ray is offset from the collider's position. + /// /// The distance to cast the ray. - /// The result of the raycast. - static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance, bool continuous); /// /// Casts a bounded ray w.r.t a GameObject. /// /// The GameObject to cast the ray to. - /// The start of the bounded ray. + /// + /// The start of the bounded ray.
+ /// The start of the ray is offset from the collider's position. /// - /// The result of the raycast. - static RaycastHit ColliderLineCast (GameObject object, Vector3 start, Vector3 end); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned. + /// + static System::Collections::Generic::List^ ColliderLineCast (GameObject object, Vector3 start, Vector3 end, bool continuous); /// /// 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 start of the bounded ray.
+ /// The start of the ray is offset from the collider's position. /// The end of the bounded ray. - /// The result of the raycast. - static RaycastHit ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end); + /// + /// Whether or not the raycast should stop at the first object hit. + /// + /// + /// The results of the raycast. If nothing was hit, an empty list is returned./// + static System::Collections::Generic::List^ ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous); private: /*---------------------------------------------------------------------------------*/ From 71f4cdd29e1cc8ec183c01a1ecffd9510c8f4104 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 19:23:42 +0800 Subject: [PATCH 2/9] Fixed rigidbody serialisation --- Assets/Editor/Editor.SHConfig | 2 +- Assets/Scenes/x.shade | 6 +++--- Assets/Scenes/x.shade.shmeta | 2 +- .../PhysicsObject/SHPhysicsObjectManager.cpp | 17 ++++++++--------- .../PhysicsObject/SHPhysicsObjectManager.h | 1 - .../Physics/Interface/SHRigidBodyComponent.h | 16 ++++++++-------- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Assets/Editor/Editor.SHConfig b/Assets/Editor/Editor.SHConfig index c56772c9..09efea23 100644 --- a/Assets/Editor/Editor.SHConfig +++ b/Assets/Editor/Editor.SHConfig @@ -1,4 +1,4 @@ Start Maximized: true -Working Scene ID: 97402985 +Working Scene ID: 84373000 Window Size: {x: 1920, y: 1013} Style: 0 \ No newline at end of file diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade index ae4767bc..7a59d350 100644 --- a/Assets/Scenes/x.shade +++ b/Assets/Scenes/x.shade @@ -1,4 +1,4 @@ -- EID: 65536 +- EID: 0 Name: Default IsActive: true NumberOfChildren: 0 @@ -12,9 +12,9 @@ Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 - Use Gravity: false + Use Gravity: true Interpolate: true - Sleeping Enabled: true + Sleeping Enabled: false Freeze Position X: false Freeze Position Y: false Freeze Position Z: false diff --git a/Assets/Scenes/x.shade.shmeta b/Assets/Scenes/x.shade.shmeta index 2e00ee43..06a5e721 100644 --- a/Assets/Scenes/x.shade.shmeta +++ b/Assets/Scenes/x.shade.shmeta @@ -1,3 +1,3 @@ Name: x -ID: 91446183 +ID: 84373000 Type: 5 diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index 9fc403f8..8aec29b1 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -216,7 +216,6 @@ namespace SHADE { .entityID = rigidBody->GetEID() , .bodyType = rigidBody->type - , .flags = rigidBody->flags , .interpolate = rigidBody->interpolate , .drag = rigidBody->drag , .angularDrag = rigidBody->angularDrag @@ -309,14 +308,14 @@ namespace SHADE // Re-set properties - rigidBodyComponent->SetGravityEnabled (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::GRAVITY)); - rigidBodyComponent->SetIsAllowedToSleep (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::SLEEPING)); - rigidBodyComponent->SetFreezePositionX (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_X)); - rigidBodyComponent->SetFreezePositionY (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_Y)); - rigidBodyComponent->SetFreezePositionZ (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::LINEAR_Z)); - rigidBodyComponent->SetFreezeRotationX (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_X)); - rigidBodyComponent->SetFreezeRotationY (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_Y)); - rigidBodyComponent->SetFreezeRotationZ (DEF.flags & SHUtilities::ConvertEnum(SHRigidBodyComponent::Flags::ANGULAR_Z)); + rigidBodyComponent->SetGravityEnabled (rigidBodyComponent->IsGravityEnabled()); + rigidBodyComponent->SetIsAllowedToSleep (rigidBodyComponent->IsAllowedToSleep()); + rigidBodyComponent->SetFreezePositionX (rigidBodyComponent->GetFreezePositionX()); + rigidBodyComponent->SetFreezePositionY (rigidBodyComponent->GetFreezePositionY()); + rigidBodyComponent->SetFreezePositionZ (rigidBodyComponent->GetFreezePositionZ()); + rigidBodyComponent->SetFreezeRotationX (rigidBodyComponent->GetFreezeRotationX()); + rigidBodyComponent->SetFreezeRotationY (rigidBodyComponent->GetFreezeRotationY()); + rigidBodyComponent->SetFreezeRotationZ (rigidBodyComponent->GetFreezeRotationZ()); rigidBodyComponent->SetInterpolate (DEF.interpolate); rigidBodyComponent->SetDrag (DEF.drag); diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h index 3c333ff9..10c8dcfa 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h @@ -47,7 +47,6 @@ namespace SHADE { EntityID entityID = MAX_EID; SHRigidBodyComponent::Type bodyType = SHRigidBodyComponent::Type::STATIC; - uint8_t flags = 0; // aZ aY aX lZ lY lX sleepEnabled gravity bool interpolate = true; float drag = 0.0f; float angularDrag = 0.0f; diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index 5fe49dbe..a75256b8 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -152,14 +152,14 @@ namespace SHADE enum class Flags : uint8_t { - GRAVITY = 0x0 - , SLEEPING = 0x1 - , LINEAR_X = 0x2 - , LINEAR_Y = 0x4 - , LINEAR_Z = 0x8 - , ANGULAR_X = 0x10 - , ANGULAR_Y = 0x20 - , ANGULAR_Z = 0x30 + GRAVITY = 0x1 + , SLEEPING = 0x2 + , LINEAR_X = 0x4 + , LINEAR_Y = 0x8 + , LINEAR_Z = 0x10 + , ANGULAR_X = 0x20 + , ANGULAR_Y = 0x30 + , ANGULAR_Z = 0x40 }; /*---------------------------------------------------------------------------------*/ From 3593df3ada5fb8ac8f8448bb0955f0848bb26628 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 20:15:59 +0800 Subject: [PATCH 3/9] Fixed collider shape serialisation --- Assets/Scenes/x.shade | 31 +++++++++- SHADE_Engine/src/Camera/SHCameraSystem.cpp | 10 +--- .../src/Math/Transform/SHTransformSystem.cpp | 2 - .../src/Physics/Collision/Shapes/SHBox.cpp | 14 +++-- .../Collision/Shapes/SHCollisionShape.cpp | 33 +++++++---- .../Collision/Shapes/SHCollisionShape.h | 1 + .../src/Physics/Collision/Shapes/SHSphere.cpp | 14 +++-- .../PhysicsObject/SHPhysicsObjectManager.cpp | 40 +++++++++---- .../Physics/Interface/SHColliderComponent.cpp | 59 ++++++++++++------- .../Physics/Interface/SHColliderComponent.h | 2 +- 10 files changed, 144 insertions(+), 62 deletions(-) diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade index 7a59d350..d7aaee0e 100644 --- a/Assets/Scenes/x.shade +++ b/Assets/Scenes/x.shade @@ -12,7 +12,7 @@ Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 - Use Gravity: true + Use Gravity: false Interpolate: true Sleeping Enabled: false Freeze Position X: false @@ -22,4 +22,33 @@ Freeze Rotation Y: false Freeze Rotation Z: false IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Sphere + Radius: 1 + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true + Scripts: ~ +- EID: 1 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Camera Component: + Position: {x: 0, y: 0, z: -10} + Pitch: 0 + Yaw: 0 + Roll: 0 + Width: 1920 + Height: 1080 + Near: 0.00999999978 + Far: 10000 + Perspective: true + IsActive: true Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Camera/SHCameraSystem.cpp b/SHADE_Engine/src/Camera/SHCameraSystem.cpp index b31345cd..01c599ca 100644 --- a/SHADE_Engine/src/Camera/SHCameraSystem.cpp +++ b/SHADE_Engine/src/Camera/SHCameraSystem.cpp @@ -161,9 +161,6 @@ namespace SHADE SHTransformComponent* transform = SHComponentManager::GetComponent_s(pivot.GetEID()); auto physicsSystem = SHSystemManager::GetSystem(); - - - if (camera == nullptr || transform == nullptr) return; @@ -179,13 +176,12 @@ namespace SHADE camera->dirtyView = true; }*/ - pivot.ray.position = camera->GetPosition() + pivot.targetOffset; pivot.ray.direction = SHVec3::Normalise((camera->position + offset)- pivot.ray.position); - //SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z) + //SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z) - //auto result = physicsSystem->Raycast(pivot.ray ); + //auto result = physicsSystem->Raycast(pivot.ray); //if (result && result.distance < pivot.GetArmLength()) //{ // @@ -203,7 +199,7 @@ namespace SHADE // // - //// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); + // pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix); } diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 03de360d..0a0ec092 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -246,8 +246,6 @@ namespace SHADE tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); - - if (convertRotation) { tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp index 1e2a4a22..f8049451 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp @@ -44,7 +44,10 @@ namespace SHADE SHVec3 SHBox::GetWorldExtents() const noexcept { - return SHVec3{ dynamic_cast(rp3dCollider->getCollisionShape())->getHalfExtents() }; + if (rp3dCollider) + return SHVec3{ dynamic_cast(rp3dCollider->getCollisionShape())->getHalfExtents() }; + + return relativeExtents * scale * 0.5f; } SHVec3 SHBox::GetRelativeExtents() const noexcept @@ -65,7 +68,8 @@ namespace SHADE void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept { - dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(newWorldExtents); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(newWorldExtents); // Recompute Relative radius relativeExtents = 2.0f * newWorldExtents / scale; @@ -76,7 +80,8 @@ namespace SHADE relativeExtents = newRelativeExtents; // Recompute world radius - dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); } void SHBox::SetScale(const SHVec3& newScale) noexcept @@ -84,7 +89,8 @@ namespace SHADE scale = SHVec3::Abs(newScale); // Recompute world radius - dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp index 2acffe29..8147c94a 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp @@ -123,29 +123,38 @@ namespace SHADE void SHCollisionShape::SetFriction(float friction) noexcept { material.SetFriction(friction); - rp3dCollider->getMaterial().setFrictionCoefficient(material.GetFriction()); + + if (rp3dCollider) + rp3dCollider->getMaterial().setFrictionCoefficient(material.GetFriction()); } void SHCollisionShape::SetBounciness(float bounciness) noexcept { material.SetBounciness(bounciness); - rp3dCollider->getMaterial().setBounciness(material.GetBounciness()); + + if (rp3dCollider) + rp3dCollider->getMaterial().setBounciness(material.GetBounciness()); } void SHCollisionShape::SetDensity(float density) noexcept { material.SetDensity(density); - rp3dCollider->getMaterial().setMassDensity(material.GetDensity()); + + if (rp3dCollider) + rp3dCollider->getMaterial().setMassDensity(material.GetDensity()); } void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept { material = newMaterial; - auto& rp3dMaterial = rp3dCollider->getMaterial(); - rp3dMaterial.setFrictionCoefficient(material.GetFriction()); - rp3dMaterial.setBounciness(material.GetBounciness()); - rp3dMaterial.setMassDensity(material.GetDensity()); + if (rp3dCollider) + { + auto& rp3dMaterial = rp3dCollider->getMaterial(); + rp3dMaterial.setFrictionCoefficient(material.GetFriction()); + rp3dMaterial.setBounciness(material.GetBounciness()); + rp3dMaterial.setMassDensity(material.GetDensity()); + } } void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept @@ -167,7 +176,8 @@ namespace SHADE isTrigger ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; - rp3dCollider->setIsTrigger(isTrigger); + if (rp3dCollider) + rp3dCollider->setIsTrigger(isTrigger); } /*-----------------------------------------------------------------------------------*/ @@ -176,8 +186,11 @@ namespace SHADE void SHCollisionShape::Update() noexcept { - const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; - rp3dCollider->setLocalToBodyTransform(OFFSETS); + if (rp3dCollider) + { + const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; + rp3dCollider->setLocalToBodyTransform(OFFSETS); + } } SHMatrix SHCollisionShape::GetTRS() const noexcept diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h index 44c4d479..b9b42daa 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h @@ -41,6 +41,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ friend class SHPhysicsSystem; + friend class SHPhysicsObjectManager; friend class SHColliderComponent; public: diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp index f8c73f90..46fbc7db 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp @@ -45,7 +45,10 @@ namespace SHADE float SHSphere::GetWorldRadius() const noexcept { - return dynamic_cast(rp3dCollider->getCollisionShape())->getRadius(); + if (rp3dCollider) + return dynamic_cast(rp3dCollider->getCollisionShape())->getRadius(); + + return relativeRadius * scale * 0.5f; } float SHSphere::GetRelativeRadius() const noexcept @@ -66,7 +69,8 @@ namespace SHADE void SHSphere::SetWorldRadius(float newWorldRadius) noexcept { - dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius); // Recompute Relative radius relativeRadius = 2.0f * newWorldRadius / scale; @@ -77,7 +81,8 @@ namespace SHADE relativeRadius = newRelativeRadius; // Recompute world radius - dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); } void SHSphere::SetScale(float maxScale) noexcept @@ -85,7 +90,8 @@ namespace SHADE scale = std::fabs(maxScale); // Recompute world radius - dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); + if (rp3dCollider) + dynamic_cast(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index 8aec29b1..8c88e4ae 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -176,8 +176,6 @@ namespace SHADE void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept { - auto* colliderComponent = SHComponentManager::GetComponent(entityID); - const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID); if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end()) { @@ -189,13 +187,8 @@ namespace SHADE { auto* rp3dCollider = physicsObject->body->getCollider(numShapes); physicsObject->body->removeCollider(rp3dCollider); - - delete colliderComponent->shapes[numShapes]; - colliderComponent->shapes[numShapes] = nullptr; } - colliderComponent->shapes.clear(); - // Destroy if no rigidbody component if (!SHComponentManager::GetComponent_s(entityID)) destroyPhysicsObject(entityID); @@ -356,25 +349,48 @@ namespace SHADE colliderComponent->SetCollisionBody(physicsObject->body); // Add all shapes - for (auto& shapeDef : DEF.shapes) + for (size_t i = 0; i < colliderComponent->shapes.size(); ++i) { - switch (shapeDef.type) + // Get the currrent shape + auto& collisionShape = colliderComponent->shapes[i]; + + // Add the rp3d collider to the shade collision shape + switch (collisionShape->GetType()) { case SHCollisionShape::Type::SPHERE: { - colliderComponent->AddSphereCollisionShape(shapeDef.size.x); + auto* sphereShape = dynamic_cast(collisionShape); + + const float SPHERE_SCALE = std::fabs(SHMath::Max({ colliderComponent->transform.scale.x, colliderComponent->transform.scale.y, colliderComponent->transform.scale.z })); + + rp3d::SphereShape* rp3dSphere = factory->createSphereShape(sphereShape->GetRelativeRadius() * SPHERE_SCALE * 0.5f); + + const rp3d::Transform OFFSETS{ sphereShape->GetPositionOffset(), SHQuaternion::FromEuler(sphereShape->GetRotationOffset()) }; + sphereShape->rp3dCollider = physicsObject->body->addCollider(rp3dSphere, OFFSETS); + sphereShape->rp3dCollider->setIsTrigger(sphereShape->IsTrigger()); + break; } case SHCollisionShape::Type::BOX: { - colliderComponent->AddBoxCollisionShape(shapeDef.size); + auto* boxShape = dynamic_cast(collisionShape); + + rp3d::BoxShape* rp3dBox = factory->createBoxShape(boxShape->GetRelativeExtents() * colliderComponent->transform.scale * 0.5f); + + const rp3d::Transform OFFSETS{ boxShape->GetPositionOffset(), SHQuaternion::FromEuler(boxShape->GetRotationOffset()) }; + boxShape->rp3dCollider = physicsObject->body->addCollider(rp3dBox, OFFSETS); + boxShape->rp3dCollider->setIsTrigger(boxShape->IsTrigger()); + break; } default: break; } } - } + physicsObject->body->updateMassPropertiesFromColliders(); + + colliderQueue.pop(); + } } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 15d01042..36af4592 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -29,9 +29,23 @@ namespace SHADE SHColliderComponent::SHColliderComponent() noexcept : flags { ACTIVE_FLAG | MOVED_FLAG } + , factory { nullptr } , collisionBody { nullptr } {} + SHColliderComponent::~SHColliderComponent() + { + int32_t numShapes = static_cast(shapes.size()); + while (--numShapes >= 0) + { + delete shapes[numShapes]; + shapes[numShapes] = nullptr; + } + + shapes.clear(); + } + + /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -143,10 +157,10 @@ namespace SHADE int SHColliderComponent::AddSphereCollisionShape(float relativeRadius, const SHVec3& posOffset, const SHVec3& rotOffset) { - SHASSERT(factory, "Physics factory missing from Collider Component! Unable to add colliders!") - const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z })); + const uint32_t NEW_INDEX = static_cast(shapes.size()); + // Create collision shape shapes.emplace_back(new SHSphere{}); auto* newSphere = dynamic_cast(shapes.back()); @@ -156,14 +170,6 @@ namespace SHADE newSphere->rotationOffset = rotOffset; newSphere->relativeRadius = relativeRadius; newSphere->scale = SPHERE_SCALE; - - - rp3d::SphereShape* rp3dSphere = factory->createSphereShape(relativeRadius * SPHERE_SCALE * 0.5f); - - const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; - newSphere->rp3dCollider = collisionBody->addCollider(rp3dSphere, OFFSETS); - - const uint32_t NEW_INDEX = static_cast(shapes.size()); // Broadcast Event for adding a shape const SHPhysicsColliderAddedEvent EVENT_DATA @@ -175,7 +181,17 @@ namespace SHADE SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); - dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + // Only link with react if a factory is present. + // Otherwise, it will be linked through the physics object manager once the definitions are flushed. + if (factory) + { + rp3d::SphereShape* rp3dSphere = factory->createSphereShape(relativeRadius * SPHERE_SCALE * 0.5f); + + const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; + newSphere->rp3dCollider = collisionBody->addCollider(rp3dSphere, OFFSETS); + + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + } return static_cast(NEW_INDEX); } @@ -184,6 +200,8 @@ namespace SHADE { SHASSERT(factory, "Physics factory missing from Collider Component! Unable to add colliders!") + const uint32_t NEW_INDEX = static_cast(shapes.size()); + // Create collision shape shapes.emplace_back(new SHBox{}); auto* newBox = dynamic_cast(shapes.back()); @@ -194,15 +212,6 @@ namespace SHADE newBox->relativeExtents = relativeExtents; newBox->scale = SHVec3::Abs(transform.scale); - - - rp3d::BoxShape* rp3dBox = factory->createBoxShape(relativeExtents * newBox->scale * 0.5f); - - const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; - newBox->rp3dCollider = collisionBody->addCollider(rp3dBox, OFFSETS); - - const uint32_t NEW_INDEX = static_cast(shapes.size()); - // Broadcast Event for adding a shape const SHPhysicsColliderAddedEvent EVENT_DATA { @@ -213,7 +222,15 @@ namespace SHADE SHEventManager::BroadcastEvent(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT); - dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + if (factory) + { + rp3d::BoxShape* rp3dBox = factory->createBoxShape(relativeExtents * newBox->scale * 0.5f); + + const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) }; + newBox->rp3dCollider = collisionBody->addCollider(rp3dBox, OFFSETS); + + dynamic_cast(collisionBody)->updateMassPropertiesFromColliders(); + } return static_cast(NEW_INDEX); } diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 63a59e55..6b971e23 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -60,7 +60,7 @@ namespace SHADE SHColliderComponent () noexcept; SHColliderComponent (const SHColliderComponent& rhs) noexcept = default; SHColliderComponent (SHColliderComponent&& rhs) noexcept = default; - ~SHColliderComponent () override = default; + ~SHColliderComponent () override; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ From 931ed58287fa5b2127adf5d35032cc2767e13dc5 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 20:19:21 +0800 Subject: [PATCH 4/9] Added individual collider debug drawing --- SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index 226ba2f9..cff3933e 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -80,7 +80,7 @@ namespace SHADE const std::shared_ptr EVENT_RECEIVER = std::make_shared>(this, &SHPhysicsDebugDrawSystem::onColliderDraw); const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast(EVENT_RECEIVER); - //SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_DRAW_EVENT, EVENT_RECEIVER_PTR); + SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_DRAW_EVENT, EVENT_RECEIVER_PTR); } void SHPhysicsDebugDrawSystem::Exit() From d5c731dd203db0e9b3db87032dfd818314c23843 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 20:48:32 +0800 Subject: [PATCH 5/9] Fixed collision shape debug drawing and more serialisation bugs --- Assets/Scenes/PhysicsTest.shade | 16 +++--- Assets/Scenes/x.shade | 52 +++++++++++++++++-- .../src/Physics/Collision/Shapes/SHBox.cpp | 13 +++++ .../src/Physics/Collision/Shapes/SHBox.h | 1 + .../Collision/Shapes/SHCollisionShape.h | 2 +- .../src/Physics/Collision/Shapes/SHSphere.cpp | 17 +++++- .../src/Physics/Collision/Shapes/SHSphere.h | 1 + .../Physics/Interface/SHColliderComponent.cpp | 27 +++++----- .../Physics/Interface/SHColliderComponent.h | 4 +- .../Interface/SHRigidBodyComponent.cpp | 29 ++++++----- .../Physics/Interface/SHRigidBodyComponent.h | 4 +- .../src/Physics/System/SHPhysicsSystem.cpp | 1 + 12 files changed, 120 insertions(+), 47 deletions(-) diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade index b3fda265..155f6263 100644 --- a/Assets/Scenes/PhysicsTest.shade +++ b/Assets/Scenes/PhysicsTest.shade @@ -4,14 +4,14 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0, y: 7, z: 0} + Translate: {x: 0, y: 7, z: -0.5} Rotate: {x: 0, y: 0, z: 0.785398185} Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523} IsActive: true RigidBody Component: Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -34,11 +34,7 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true - Scripts: - - Type: PhysicsTestObj - Enabled: true - forceAmount: 200 - torqueAmount: 5 + Scripts: ~ - EID: 1 Name: Default IsActive: true @@ -70,7 +66,7 @@ Camera Component: Position: {x: 0, y: 2, z: 7} Pitch: 0 - Yaw: 95 + Yaw: 0 Roll: 0 Width: 1920 Height: 1080 @@ -182,9 +178,9 @@ Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: - Type: Static + Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade index d7aaee0e..b7f3c00f 100644 --- a/Assets/Scenes/x.shade +++ b/Assets/Scenes/x.shade @@ -4,7 +4,7 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0, y: 0, z: 0} + Translate: {x: 2, y: 0, z: 0} Rotate: {x: 0, y: 0, z: 0} Scale: {x: 1, y: 1, z: 1} IsActive: true @@ -12,7 +12,7 @@ Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 - Use Gravity: false + Use Gravity: true Interpolate: true Sleeping Enabled: false Freeze Position X: false @@ -41,7 +41,7 @@ NumberOfChildren: 0 Components: Camera Component: - Position: {x: 0, y: 0, z: -10} + Position: {x: 0, y: 0, z: 5} Pitch: 0 Yaw: 0 Roll: 0 @@ -51,4 +51,50 @@ Far: 10000 Perspective: true IsActive: true + Scripts: ~ +- EID: 2 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -3, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + RigidBody Component: + Type: Dynamic + Drag: 0.00999999978 + Angular Drag: 0.100000001 + Use Gravity: false + Interpolate: true + Sleeping Enabled: false + Freeze Position X: true + Freeze Position Y: true + Freeze Position Z: true + Freeze Rotation X: false + Freeze Rotation Y: false + Freeze Rotation Z: false + IsActive: true + Collider Component: + Colliders: + - Is Trigger: false + Collision Tag: 1 + Type: Sphere + Radius: 1 + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 0, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + - Is Trigger: false + Collision Tag: 1 + Type: Box + Half Extents: {x: 1, y: 1, z: 1} + Friction: 0.400000006 + Bounciness: 0 + Density: 1 + Position Offset: {x: 2, y: 0, z: 0} + Rotation Offset: {x: 0, y: 0, z: 0} + IsActive: true Scripts: ~ \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp index f8049451..3a47a5cf 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp @@ -97,6 +97,19 @@ namespace SHADE /* Public Member Function Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHBox::Update() noexcept + { + const SHTransform& PARENT_TRANSFORM = collider->GetTransform(); + SetScale(PARENT_TRANSFORM.scale); + + if (rp3dCollider) + { + const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; + rp3dCollider->setLocalToBodyTransform(OFFSETS); + } + } + + SHMatrix SHBox::GetTRS() const noexcept { const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h index 5fa394d9..7cb425d5 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.h @@ -65,6 +65,7 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ + void Update () noexcept override; [[nodiscard]] SHMatrix GetTRS () const noexcept override; private: diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h index b9b42daa..3f7bf10c 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h @@ -127,7 +127,7 @@ namespace SHADE * @brief * Computes the transform of the shape. */ - void Update() noexcept; + virtual void Update() noexcept; /** * @brief diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp index 46fbc7db..ec753542 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp @@ -98,10 +98,25 @@ namespace SHADE /* Public Member Function Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHSphere::Update() noexcept + { + const SHTransform& PARENT_TRANSFORM = collider->GetTransform(); + + const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z })); + SetScale(SPHERE_SCALE); + + if (rp3dCollider) + { + const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; + rp3dCollider->setLocalToBodyTransform(OFFSETS); + } + } + + SHMatrix SHSphere::GetTRS() const noexcept { const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset); - const SHVec3 SCALE = GetWorldRadius() * 2.0f; + const SHVec3 SCALE = GetWorldRadius(); const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position); const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS); diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h index bf9301fe..a1e65f3f 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.h @@ -65,6 +65,7 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ + void Update () noexcept override; [[nodiscard]] SHMatrix GetTRS () const noexcept override; private: diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 36af4592..32acaabe 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -33,19 +33,6 @@ namespace SHADE , collisionBody { nullptr } {} - SHColliderComponent::~SHColliderComponent() - { - int32_t numShapes = static_cast(shapes.size()); - while (--numShapes >= 0) - { - delete shapes[numShapes]; - shapes[numShapes] = nullptr; - } - - shapes.clear(); - } - - /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ @@ -150,6 +137,18 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHColliderComponent::OnDestroy() + { + int32_t numShapes = static_cast(shapes.size()); + while (--numShapes >= 0) + { + delete shapes[numShapes]; + shapes[numShapes] = nullptr; + } + + shapes.clear(); + } + const SHMatrix& SHColliderComponent::ComputeTRS() noexcept { return transform.ComputeTRS(); @@ -198,8 +197,6 @@ namespace SHADE int SHColliderComponent::AddBoxCollisionShape(const SHVec3& relativeExtents, const SHVec3& posOffset, const SHVec3& rotOffset) { - SHASSERT(factory, "Physics factory missing from Collider Component! Unable to add colliders!") - const uint32_t NEW_INDEX = static_cast(shapes.size()); // Create collision shape diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 6b971e23..7dcde150 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -60,7 +60,7 @@ namespace SHADE SHColliderComponent () noexcept; SHColliderComponent (const SHColliderComponent& rhs) noexcept = default; SHColliderComponent (SHColliderComponent&& rhs) noexcept = default; - ~SHColliderComponent () override; + ~SHColliderComponent () override = default; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -101,6 +101,8 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ + void OnDestroy() override; + /** * @brief * Computes the TRS for the collider's transform diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp index a374665d..ee4db90d 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.cpp @@ -155,21 +155,22 @@ namespace SHADE type = newType; - SHASSERT(rigidBody, "Unable to find rp3dBody on RigidBodyComponent!") - - switch (type) + if (rigidBody) { - case Type::STATIC: - rigidBody->setType(rp3d::BodyType::STATIC); - break; - case Type::KINEMATIC: - rigidBody->setType(rp3d::BodyType::KINEMATIC); - break; - case Type::DYNAMIC: - rigidBody->setType(rp3d::BodyType::DYNAMIC); - break; - default: - break; + switch (type) + { + case Type::STATIC: + rigidBody->setType(rp3d::BodyType::STATIC); + break; + case Type::KINEMATIC: + rigidBody->setType(rp3d::BodyType::KINEMATIC); + break; + case Type::DYNAMIC: + rigidBody->setType(rp3d::BodyType::DYNAMIC); + break; + default: + break; + } } } diff --git a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h index a75256b8..6332d1e6 100644 --- a/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHRigidBodyComponent.h @@ -158,8 +158,8 @@ namespace SHADE , LINEAR_Y = 0x8 , LINEAR_Z = 0x10 , ANGULAR_X = 0x20 - , ANGULAR_Y = 0x30 - , ANGULAR_Z = 0x40 + , ANGULAR_Y = 0x40 + , ANGULAR_Z = 0x80 }; /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 22a51c41..3fd441b4 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -134,6 +134,7 @@ namespace SHADE } objectManager.SetFactory(&factory); + collisionListener.BindToSystem(this); raycaster.BindToSystem(this); } From 931f6fe5e24e03dde8710fd166bd57a621ef085b Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 2 Feb 2023 20:56:55 +0800 Subject: [PATCH 6/9] Fixed almost everything. Ray debug drawing has a small bug --- Assets/Scenes/PhysicsTest.shade | 6 +- .../Implemented/LeafNodes/LeafSearch.cs | 2 +- .../Gameplay/Player/SC_PickAndThrow.cs | 28 +++-- Assets/Scripts/Tests/PhysicsTestObj.cs | 119 ++++++++++++++++++ Assets/Scripts/Tests/PhysicsTestObj.cs.shmeta | 3 + .../src/Physics/System/SHPhysicsSystem.cpp | 1 + 6 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 Assets/Scripts/Tests/PhysicsTestObj.cs create mode 100644 Assets/Scripts/Tests/PhysicsTestObj.cs.shmeta diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade index 155f6263..77953a18 100644 --- a/Assets/Scenes/PhysicsTest.shade +++ b/Assets/Scenes/PhysicsTest.shade @@ -34,7 +34,11 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} IsActive: true - Scripts: ~ + Scripts: + - Type: PhysicsTestObj + Enabled: true + forceAmount: 50 + torqueAmount: 500 - EID: 1 Name: Default IsActive: true diff --git a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs index 7c68712c..b5b03629 100644 --- a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -159,7 +159,7 @@ public partial class LeafSearch : BehaviourTreeNode //Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset; Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition); - RaycastHit sightRayHit = Physics.Raycast(sightRay); + RaycastHit sightRayHit = Physics.Raycast(sightRay, false)[0]; //As of November 2022, RaycastHit contains only the FIRST object hit by //the ray in the Other GameObject data member //Diren may likely add ALL objects hit by the ray over December diff --git a/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs b/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs index 9c879314..855f3d54 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs @@ -1,6 +1,7 @@ using SHADE; using SHADE_Scripting; using System; +using System.Collections.Generic; using static PlayerController; using static Item; @@ -199,14 +200,25 @@ public class PickAndThrow : Script { if (pc != null) { - Vector3 dirNor = pc.tranform.Forward; - Vector3 playerRayPos = pc.tranform.GlobalPosition; - playerRayPos.y += 0.05f; - dirNor.Normalise(); - RaycastHit ray1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance); - RaycastHit ray2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance); - RaycastHit ray3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f); - inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3); + Vector3 dirNor = pc.tranform.Forward; + Vector3 playerRayPos = pc.tranform.GlobalPosition; + playerRayPos.y += 0.05f; + dirNor.Normalise(); + List rayList1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance, false); + List rayList2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance, false); + List rayList3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f, false); + + if (rayList1.Count > 0 && rayList2.Count > 0 && rayList3.Count > 0) + { + RaycastHit ray1 = rayList1[0]; + RaycastHit ray2 = rayList2[0]; + RaycastHit ray3 = rayList3[0]; + inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3); + } + else + { + inRange = false; + } } } diff --git a/Assets/Scripts/Tests/PhysicsTestObj.cs b/Assets/Scripts/Tests/PhysicsTestObj.cs new file mode 100644 index 00000000..781d0b11 --- /dev/null +++ b/Assets/Scripts/Tests/PhysicsTestObj.cs @@ -0,0 +1,119 @@ +using SHADE; +using System; +using System.Collections.Generic; +using static Item; + + +public class PhysicsTestObj : Script +{ + public RigidBody body { get; set; } + public Collider collider { get; set; } + + // Movement input booleans + public enum Direction + { + UP, + DOWN, + FORWARD, + BACK, + LEFT, + RIGHT + }; + + internal bool[] move = new bool[6]; + internal bool[] rotate = new bool[6]; + + internal Vector3[] moveVec = new Vector3[6] + { + Vector3.Up, + Vector3.Down, + Vector3.Back, + Vector3.Forward, + Vector3.Left, + Vector3.Right + }; + + internal Vector3[] rotateVec = new Vector3[6] + { + Vector3.Right, + Vector3.Left, + Vector3.Forward, + Vector3.Down, + Vector3.Up, + Vector3.Down + }; + + internal Input.KeyCode[] moveInputKeys = new Input.KeyCode[6] + { + Input.KeyCode.Space, + Input.KeyCode.LeftControl, + Input.KeyCode.W, + Input.KeyCode.S, + Input.KeyCode.A, + Input.KeyCode.D + }; + + internal Input.KeyCode[] rotateInputKeys = new Input.KeyCode[6] + { + Input.KeyCode.I, + Input.KeyCode.K, + Input.KeyCode.U, + Input.KeyCode.O, + Input.KeyCode.J, + Input.KeyCode.L + }; + + public float forceAmount = 50.0f; + public float torqueAmount = 500.0f; + + protected override void awake() + { + body = GetComponent(); + collider = GetComponent(); + + for (int i = 0; i < 6; ++i) + { + move[i] = false; + rotate[i] = false; + } + } + + protected override void update() + { + Ray colliderRay = new Ray(); + colliderRay.Direction = Vector3.Right; + Physics.ColliderRaycast(collider.Owner, colliderRay, false); + + for (int i = 0; i < 6; ++i) + { + if (Input.GetKeyDown(moveInputKeys[i])) + move[i] = true; + + if (Input.GetKeyDown(rotateInputKeys[i])) + rotate[i] = true; + } + } + + protected override void fixedUpdate() + { + for (int i = 0; i < 6; ++i) + { + bool shouldMove = move[i]; + bool shouldRotate = rotate[i]; + + if (shouldMove) + { + //Vector3 offset = new Vector3(0.25f, 0.0f, 0.0f); + //rb.AddForceAtLocalPos(moveVec[i] * forceAmount, offset); + body.AddForce(moveVec[i] * forceAmount); + move[i] = false; + } + + if (shouldRotate) + { + body.AddTorque(rotateVec[i] * torqueAmount); + rotate[i] = false; + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Tests/PhysicsTestObj.cs.shmeta b/Assets/Scripts/Tests/PhysicsTestObj.cs.shmeta new file mode 100644 index 00000000..d18fa860 --- /dev/null +++ b/Assets/Scripts/Tests/PhysicsTestObj.cs.shmeta @@ -0,0 +1,3 @@ +Name: PhysicsTestObj +ID: 163401492 +Type: 9 diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 3fd441b4..0a016c6f 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -213,6 +213,7 @@ namespace SHADE objectManager.FlushDefinitions(); collisionListener.BindToWorld(worldState.world); + raycaster.BindToWorld(worldState.world); return onSceneInitEvent.get()->handle; } From b6d91d54922a47adcb772527f398797e486ed6c8 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 3 Feb 2023 01:37:45 +0800 Subject: [PATCH 7/9] Fixed bug with collision tags not behaving as intended Why the damn hell must react's system be so confusing?? --- Assets/CollisionTags.SHConfig | 32 +- Assets/Scenes/MainGameWithAIFixed.shade | 300 +++++++++++++++++- Assets/Scenes/x.shade | 12 +- .../CollisionTags/SHCollisionTagMatrix.cpp | 69 +++- .../CollisionTags/SHCollisionTagMatrix.h | 24 +- .../CollisionTags/SHCollisionTags.cpp | 19 +- .../Collision/CollisionTags/SHCollisionTags.h | 9 + .../src/Physics/Collision/Shapes/SHBox.cpp | 6 +- .../Collision/Shapes/SHCollisionShape.cpp | 10 + .../Collision/Shapes/SHCollisionShape.h | 6 + .../src/Physics/Collision/Shapes/SHSphere.cpp | 6 +- .../PhysicsObject/SHPhysicsObjectManager.cpp | 6 + .../Physics/Interface/SHColliderComponent.cpp | 6 + .../Physics/Interface/SHColliderComponent.h | 6 + .../Routines/SHPhysicsPreUpdateRoutine.cpp | 80 +++-- 15 files changed, 499 insertions(+), 92 deletions(-) diff --git a/Assets/CollisionTags.SHConfig b/Assets/CollisionTags.SHConfig index d3ebe7e2..f29443f5 100644 --- a/Assets/CollisionTags.SHConfig +++ b/Assets/CollisionTags.SHConfig @@ -1,16 +1,16 @@ -0 1 -1 2 -2 3 -3 4 -4 5 -5 6 -6 7 -7 8 -8 9 -9 10 -10 11 -11 12 -12 13 -13 14 -14 15 -15 16 +0 1 3 +1 2 65535 +2 3 65534 +3 4 65534 +4 5 65534 +5 6 65534 +6 7 65534 +7 8 65534 +8 9 65534 +9 10 65534 +10 11 65534 +11 12 65534 +12 13 65534 +13 14 65534 +14 15 65534 +15 16 65534 diff --git a/Assets/Scenes/MainGameWithAIFixed.shade b/Assets/Scenes/MainGameWithAIFixed.shade index d30799bc..e2326de0 100644 --- a/Assets/Scenes/MainGameWithAIFixed.shade +++ b/Assets/Scenes/MainGameWithAIFixed.shade @@ -474,6 +474,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 10, y: 0.0500000007, z: 18} Friction: 0.400000006 @@ -511,6 +512,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.200000003, z: 0.25} Friction: 0.400000006 @@ -519,6 +521,7 @@ Position Offset: {x: 0, y: 2.0999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.899999976, z: 0.25} Friction: 0.400000006 @@ -527,6 +530,7 @@ Position Offset: {x: 0, y: 0.449999988, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -535,6 +539,7 @@ Position Offset: {x: -0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -561,6 +566,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.10000002, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -569,6 +575,7 @@ Position Offset: {x: 0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.25, y: 2.20000005, z: 1.10000002} Friction: 0.400000006 @@ -595,6 +602,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -621,6 +629,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -647,6 +656,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -673,6 +683,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -699,6 +710,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -725,6 +737,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.10000002, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -733,6 +746,7 @@ Position Offset: {x: 0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.25, y: 2.20000005, z: 1.10000002} Friction: 0.400000006 @@ -759,6 +773,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -785,6 +800,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -811,6 +827,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -837,6 +854,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.150000006, z: 0.25} Friction: 0.400000006 @@ -845,6 +863,7 @@ Position Offset: {x: 0, y: 2.125, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -853,6 +872,7 @@ Position Offset: {x: -0.455000013, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -897,6 +917,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.800000012, y: 2, z: 0.0350000001} Friction: 0.400000006 @@ -923,6 +944,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -949,6 +971,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.10000002, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -957,6 +980,7 @@ Position Offset: {x: 0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.25, y: 2.20000005, z: 1.10000002} Friction: 0.400000006 @@ -983,6 +1007,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1009,6 +1034,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1035,6 +1061,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1061,6 +1088,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1087,6 +1115,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1113,6 +1142,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.150000006, z: 0.25} Friction: 0.400000006 @@ -1121,6 +1151,7 @@ Position Offset: {x: 0, y: 2.125, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1129,6 +1160,7 @@ Position Offset: {x: -0.455000013, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1173,6 +1205,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.800000012, y: 2, z: 0.0350000001} Friction: 0.400000006 @@ -1199,6 +1232,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1225,6 +1259,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1251,6 +1286,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1277,6 +1313,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1303,6 +1340,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -1351,6 +1389,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1377,6 +1416,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1403,6 +1443,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1429,6 +1470,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1455,6 +1497,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1492,6 +1535,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1518,6 +1562,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1544,6 +1589,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1570,6 +1616,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1596,6 +1643,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1633,6 +1681,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1659,6 +1708,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1685,6 +1735,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1711,6 +1762,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1737,6 +1789,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1774,6 +1827,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1800,6 +1854,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1826,6 +1881,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1852,6 +1908,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1878,6 +1935,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1915,6 +1973,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1941,6 +2000,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1967,6 +2027,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -1993,6 +2054,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2019,6 +2081,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2171,6 +2234,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2197,6 +2261,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2234,6 +2299,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2260,6 +2326,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.0500000007, z: 2} Friction: 0.400000006 @@ -2297,6 +2364,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.10000002, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2305,6 +2373,7 @@ Position Offset: {x: 0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.25, y: 2.20000005, z: 1.10000002} Friction: 0.400000006 @@ -2331,6 +2400,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.10000002, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2339,6 +2409,7 @@ Position Offset: {x: 0.449999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.25, y: 2.20000005, z: 1.10000002} Friction: 0.400000006 @@ -2365,6 +2436,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.200000003, z: 0.25} Friction: 0.400000006 @@ -2373,6 +2445,7 @@ Position Offset: {x: 0, y: 2.0999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 0.899999976, z: 0.25} Friction: 0.400000006 @@ -2381,6 +2454,7 @@ Position Offset: {x: 0, y: 0.449999988, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2389,6 +2463,7 @@ Position Offset: {x: -0.949999988, y: 1.10000002, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2415,6 +2490,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2441,6 +2517,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 2, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2467,6 +2544,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2493,6 +2571,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 2.20000005, z: 0.25} Friction: 0.400000006 @@ -2519,6 +2598,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -2527,6 +2607,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -2575,6 +2656,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -2601,6 +2683,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -2627,6 +2710,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -2653,6 +2737,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -2661,6 +2746,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -2669,6 +2755,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -2677,6 +2764,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -2685,6 +2773,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -2711,6 +2800,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -2719,6 +2809,7 @@ Position Offset: {x: -0.310000002, y: -0.219999999, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2727,6 +2818,7 @@ Position Offset: {x: 0.147, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2735,6 +2827,7 @@ Position Offset: {x: -0.757000029, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2743,6 +2836,7 @@ Position Offset: {x: -0.310000002, y: -0.0700000003, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2769,6 +2863,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -2777,6 +2872,7 @@ Position Offset: {x: -0.310000002, y: -0.219999999, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2785,6 +2881,7 @@ Position Offset: {x: 0.147, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2793,6 +2890,7 @@ Position Offset: {x: -0.757000029, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2801,6 +2899,7 @@ Position Offset: {x: -0.310000002, y: -0.0700000003, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2827,6 +2926,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -2835,6 +2935,7 @@ Position Offset: {x: -0.310000002, y: -0.219999999, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2843,6 +2944,7 @@ Position Offset: {x: 0.147, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -2851,6 +2953,7 @@ Position Offset: {x: -0.757000029, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2859,6 +2962,7 @@ Position Offset: {x: -0.310000002, y: -0.0700000003, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -2885,6 +2989,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -2911,6 +3016,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.725000024, z: 0.850000024} Friction: 0.400000006 @@ -2952,6 +3058,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.800000012, y: 0.0500000007, z: 0.800000012} Friction: 0.400000006 @@ -2978,6 +3085,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -2986,6 +3094,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -2994,6 +3103,7 @@ Position Offset: {x: 0, y: 0.860000014, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3002,6 +3112,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3010,6 +3121,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3018,6 +3130,7 @@ Position Offset: {x: -0.444999993, y: 0.600000024, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 1} Friction: 0.400000006 @@ -3026,6 +3139,7 @@ Position Offset: {x: 0.444999993, y: 1.04999995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3034,6 +3148,7 @@ Position Offset: {x: 0, y: 1.04999995, z: 0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3042,6 +3157,7 @@ Position Offset: {x: 0, y: 1.04999995, z: -0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3068,6 +3184,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.07500005, z: 0.925000012} Friction: 0.400000006 @@ -3094,6 +3211,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3102,6 +3220,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3110,6 +3229,7 @@ Position Offset: {x: 0, y: 0.860000014, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3118,6 +3238,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3126,6 +3247,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3134,6 +3256,7 @@ Position Offset: {x: -0.444999993, y: 0.600000024, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 1} Friction: 0.400000006 @@ -3142,6 +3265,7 @@ Position Offset: {x: 0.444999993, y: 1.04999995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3150,6 +3274,7 @@ Position Offset: {x: 0, y: 1.04999995, z: 0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3158,6 +3283,7 @@ Position Offset: {x: 0, y: 1.04999995, z: -0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3184,6 +3310,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.07500005, z: 0.925000012} Friction: 0.400000006 @@ -3210,6 +3337,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3236,6 +3364,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 1.29999995, z: 1} Friction: 0.400000006 @@ -3244,6 +3373,7 @@ Position Offset: {x: 0, y: 0.699999988, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.600000024, y: 1.70000005, z: 0.0700000003} Friction: 0.400000006 @@ -3252,6 +3382,7 @@ Position Offset: {x: 0, y: 0.850000024, z: -0.5} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.600000024, y: 1.70000005, z: 0.0700000003} Friction: 0.400000006 @@ -3278,6 +3409,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.300000012, y: 0.800000012, z: 0.300000012} Friction: 0.400000006 @@ -3315,6 +3447,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.699999988, y: 0.0500000007, z: 1.20000005} Friction: 0.400000006 @@ -3323,6 +3456,7 @@ Position Offset: {x: 0, y: 0.77700001, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -3331,6 +3465,7 @@ Position Offset: {x: -0.449999988, y: 0.400000006, z: -0.850000024} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -3339,6 +3474,7 @@ Position Offset: {x: -0.449999988, y: 0.400000006, z: 0.850000024} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -3347,6 +3483,7 @@ Position Offset: {x: 0.449999988, y: 0.400000006, z: 0.850000024} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -3373,6 +3510,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -3381,6 +3519,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -3407,6 +3546,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -3415,6 +3555,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -3441,6 +3582,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -3449,6 +3591,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -3475,6 +3618,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -3483,6 +3627,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -3520,6 +3665,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3528,6 +3674,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3536,6 +3683,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3544,6 +3692,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3552,6 +3701,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3578,6 +3728,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3586,6 +3737,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3594,6 +3746,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3602,6 +3755,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3610,6 +3764,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3636,6 +3791,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3644,6 +3800,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3652,6 +3809,7 @@ Position Offset: {x: 0, y: 0.860000014, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3660,6 +3818,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3668,6 +3827,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3676,6 +3836,7 @@ Position Offset: {x: -0.444999993, y: 0.600000024, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 1} Friction: 0.400000006 @@ -3684,6 +3845,7 @@ Position Offset: {x: 0.444999993, y: 1.04999995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3692,6 +3854,7 @@ Position Offset: {x: 0, y: 1.04999995, z: 0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3700,6 +3863,7 @@ Position Offset: {x: 0, y: 1.04999995, z: -0.444999993} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.100000001, y: 0.300000012, z: 0.100000001} Friction: 0.400000006 @@ -3726,6 +3890,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.07500005, z: 0.462500006} Friction: 0.400000006 @@ -3752,6 +3917,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.07500005, z: 0.462500006} Friction: 0.400000006 @@ -3778,6 +3944,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3786,6 +3953,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3794,6 +3962,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3802,6 +3971,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3810,6 +3980,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -3836,6 +4007,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -3844,6 +4016,7 @@ Position Offset: {x: -0.310000002, y: -0.519999981, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.699999988, z: 0.870000005} Friction: 0.400000006 @@ -3852,6 +4025,7 @@ Position Offset: {x: 0.147, y: -0.170000002, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.699999988, z: 0.870000005} Friction: 0.400000006 @@ -3860,6 +4034,7 @@ Position Offset: {x: -0.757000029, y: -0.170000002, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.699999988, z: 0.0450000018} Friction: 0.400000006 @@ -3868,6 +4043,7 @@ Position Offset: {x: -0.310000002, y: -0.170000002, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.699999988, z: 0.0450000018} Friction: 0.400000006 @@ -3894,6 +4070,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -3902,6 +4079,7 @@ Position Offset: {x: -0.310000002, y: -0.219999999, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -3910,6 +4088,7 @@ Position Offset: {x: 0.147, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -3918,6 +4097,7 @@ Position Offset: {x: -0.757000029, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -3926,6 +4106,7 @@ Position Offset: {x: -0.310000002, y: -0.0700000003, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -3952,6 +4133,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3960,6 +4142,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -3968,6 +4151,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3976,6 +4160,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -3984,6 +4169,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4010,6 +4196,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4036,6 +4223,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4062,6 +4250,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4088,6 +4277,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4114,6 +4304,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4140,6 +4331,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.725000024, z: 0.850000024} Friction: 0.400000006 @@ -4181,6 +4373,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.800000012, y: 0.0500000007, z: 0.800000012} Friction: 0.400000006 @@ -4207,6 +4400,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4233,6 +4427,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.725000024, z: 0.850000024} Friction: 0.400000006 @@ -4274,6 +4469,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.800000012, y: 0.0500000007, z: 0.800000012} Friction: 0.400000006 @@ -4300,6 +4496,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4308,6 +4505,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4316,6 +4514,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4324,6 +4523,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4332,6 +4532,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4358,6 +4559,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4366,6 +4568,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4374,6 +4577,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4382,6 +4586,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4390,6 +4595,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4416,6 +4622,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4424,6 +4631,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4432,6 +4640,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4440,6 +4649,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4448,6 +4658,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4474,6 +4685,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4482,6 +4694,7 @@ Position Offset: {x: 0, y: 0.0250000004, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.0500000007, z: 1} Friction: 0.400000006 @@ -4490,6 +4703,7 @@ Position Offset: {x: 0, y: 1.17499995, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4498,6 +4712,7 @@ Position Offset: {x: 0, y: 0.600000024, z: 0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1.20000005, z: 0.0500000007} Friction: 0.400000006 @@ -4506,6 +4721,7 @@ Position Offset: {x: 0, y: 0.600000024, z: -0.474999994} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 1.20000005, z: 1} Friction: 0.400000006 @@ -4532,6 +4748,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -4540,6 +4757,7 @@ Position Offset: {x: -0.310000002, y: -0.519999981, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.699999988, z: 0.870000005} Friction: 0.400000006 @@ -4548,6 +4766,7 @@ Position Offset: {x: 0.147, y: -0.170000002, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.699999988, z: 0.870000005} Friction: 0.400000006 @@ -4556,6 +4775,7 @@ Position Offset: {x: -0.757000029, y: -0.170000002, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.699999988, z: 0.0450000018} Friction: 0.400000006 @@ -4564,6 +4784,7 @@ Position Offset: {x: -0.310000002, y: -0.170000002, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.699999988, z: 0.0450000018} Friction: 0.400000006 @@ -4590,6 +4811,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.970000029, y: 0.0250000004, z: 0.870000005} Friction: 0.400000006 @@ -4598,6 +4820,7 @@ Position Offset: {x: -0.310000002, y: -0.219999999, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -4606,6 +4829,7 @@ Position Offset: {x: 0.147, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0450000018, y: 0.349999994, z: 0.870000005} Friction: 0.400000006 @@ -4614,6 +4838,7 @@ Position Offset: {x: -0.757000029, y: -0.0700000003, z: 0.00499999989} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -4622,6 +4847,7 @@ Position Offset: {x: -0.310000002, y: -0.0700000003, z: -0.425000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.959999979, y: 0.349999994, z: 0.0450000018} Friction: 0.400000006 @@ -4648,6 +4874,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.300000012, y: 0.800000012, z: 0.300000012} Friction: 0.400000006 @@ -4685,6 +4912,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -4711,6 +4939,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -4737,6 +4966,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -4763,6 +4993,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.899999976, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -4789,6 +5020,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -4797,6 +5029,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -4823,6 +5056,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -4831,6 +5065,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -4857,6 +5092,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -4865,6 +5101,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -4902,6 +5139,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -4928,6 +5166,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -4954,6 +5193,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -4980,6 +5220,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.899999976, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -5006,6 +5247,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5014,6 +5256,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5040,6 +5283,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5048,6 +5292,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5085,6 +5330,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -5111,6 +5357,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -5137,6 +5384,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -5163,6 +5411,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.899999976, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -5189,6 +5438,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5197,6 +5447,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5223,6 +5474,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5231,6 +5483,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5257,6 +5510,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.699999988, y: 0.0500000007, z: 1.20000005} Friction: 0.400000006 @@ -5265,6 +5519,7 @@ Position Offset: {x: 0, y: 0.77700001, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -5273,6 +5528,7 @@ Position Offset: {x: -0.25, y: 0.400000006, z: -0.550000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -5281,6 +5537,7 @@ Position Offset: {x: -0.25, y: 0.400000006, z: 0.550000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -5289,6 +5546,7 @@ Position Offset: {x: 0.25, y: 0.400000006, z: 0.550000012} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0500000007, y: 0.800000012, z: 0.0500000007} Friction: 0.400000006 @@ -5315,6 +5573,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.439999998, z: 0.400000006} Friction: 0.400000006 @@ -5323,6 +5582,7 @@ Position Offset: {x: 0, y: 0.219999999, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.0399999991, y: 1, z: 0.400000006} Friction: 0.400000006 @@ -5360,6 +5620,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -5386,6 +5647,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1.20000005, y: 0.100000001, z: 2.20000005} Friction: 0.400000006 @@ -5412,6 +5674,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 0.100000001, z: 1.89999998} Friction: 0.400000006 @@ -5438,6 +5701,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -5446,6 +5710,7 @@ Position Offset: {x: 0, y: 0.5, z: -0.954999983} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.100000001} Friction: 0.400000006 @@ -8221,7 +8486,7 @@ RigidBody Component: Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -8235,6 +8500,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.200000003, y: 0.200000003, z: 0.200000003} Friction: 0.400000006 @@ -8243,6 +8509,7 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: true + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.400000006, z: 0.400000006} Friction: 0.400000006 @@ -8273,7 +8540,7 @@ RigidBody Component: Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -8287,6 +8554,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.5, y: 0.150000006, z: 0.5} Friction: 0.400000006 @@ -8295,6 +8563,7 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: true + Collision Tag: 1 Type: Box Half Extents: {x: 0.699999988, y: 0.300000012, z: 0.75} Friction: 0.400000006 @@ -8325,7 +8594,7 @@ RigidBody Component: Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -8339,6 +8608,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.300000012, y: 0.300000012, z: 0.300000012} Friction: 0.400000006 @@ -8347,6 +8617,7 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: true + Collision Tag: 1 Type: Box Half Extents: {x: 0.5, y: 0.5, z: 0.5} Friction: 0.400000006 @@ -8377,9 +8648,9 @@ Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: - Type: Static + Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -8393,6 +8664,7 @@ Collider Component: Colliders: - Is Trigger: true + Collision Tag: 1 Type: Box Half Extents: {x: 1.79999995, y: 1, z: 0.200000003} Friction: 0.400000006 @@ -8415,9 +8687,9 @@ Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: - Type: Static + Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true Interpolate: true Sleeping Enabled: true @@ -8431,6 +8703,7 @@ Collider Component: Colliders: - Is Trigger: true + Collision Tag: 1 Type: Box Half Extents: {x: 1, y: 1, z: 0.200000003} Friction: 0.400000006 @@ -8518,7 +8791,7 @@ IsActive: true RigidBody Component: Type: Dynamic - Drag: 1 + Drag: 0.00999999978 Angular Drag: 0.100000001 Use Gravity: false Interpolate: true @@ -8533,6 +8806,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 0.5, z: 0.300000012} Friction: 0.400000006 @@ -8559,8 +8833,11 @@ - Type: PickAndThrow Enabled: true throwForce: [50, 50, 50] + cameraArmOffSet: [0, 0.25, 0] delayTimer: 1 aimingLength: 0.5 + throwItem: false + rayDistance: 1 - EID: 3 Name: HoldingPoint IsActive: true @@ -8608,6 +8885,8 @@ turnSpeedPitch: 0.300000012 turnSpeedYaw: 0.5 pitchClamp: 45 + inverseXControls: false + inverseYControls: false - EID: 9 Name: PlayerBag IsActive: true @@ -8651,9 +8930,9 @@ RigidBody Component: Type: Dynamic Drag: 0.00999999978 - Angular Drag: 0.00999999978 + Angular Drag: 0.100000001 Use Gravity: true - Interpolate: false + Interpolate: true Sleeping Enabled: true Freeze Position X: false Freeze Position Y: false @@ -8665,6 +8944,7 @@ Collider Component: Colliders: - Is Trigger: false + Collision Tag: 1 Type: Box Half Extents: {x: 0.400000006, y: 1.79999995, z: 0.400000006} Friction: 0.400000006 diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade index b7f3c00f..959e4982 100644 --- a/Assets/Scenes/x.shade +++ b/Assets/Scenes/x.shade @@ -4,8 +4,8 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 2, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} + Translate: {x: 2, y: 2, z: 0} + Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: @@ -58,8 +58,8 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0, y: -3, z: 0} - Rotate: {x: 0, y: 0, z: 0} + Translate: {x: 0, y: 0, z: 0} + Rotate: {x: -0, y: 0, z: -0} Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: @@ -79,7 +79,7 @@ Collider Component: Colliders: - Is Trigger: false - Collision Tag: 1 + Collision Tag: 3 Type: Sphere Radius: 1 Friction: 0.400000006 @@ -88,7 +88,7 @@ Position Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0} - Is Trigger: false - Collision Tag: 1 + Collision Tag: 2 Type: Box Half Extents: {x: 1, y: 1, z: 1} Friction: 0.400000006 diff --git a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp index b687c6ca..9b2effbd 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.cpp @@ -14,18 +14,36 @@ // Primary Header #include "SHCollisionTagMatrix.h" +#include "Tools/Utilities/SHUtilities.h" + namespace SHADE { /*-----------------------------------------------------------------------------------*/ /* Static Data Member Definitions */ /*-----------------------------------------------------------------------------------*/ - SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS]; + bool SHCollisionTagMatrix::dirty = true; + SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS]; /*-----------------------------------------------------------------------------------*/ /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + bool SHCollisionTagMatrix::IsDirty() noexcept + { + // Check if any collision tag is dirty + for (auto& tag : collisionTags) + { + if (tag.IsDirty()) + { + dirty = true; + break; + } + } + + return dirty; + } + const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex) { if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) @@ -91,6 +109,8 @@ namespace SHADE if (collisionTag.GetName() != tagName) continue; + dirty = true; + collisionTag = newTag; return; } @@ -105,6 +125,8 @@ namespace SHADE if (collisionTag.GetName() != tagName) continue; + dirty = true; + collisionTag.SetMask(mask); return; } @@ -125,6 +147,8 @@ namespace SHADE if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) throw std::invalid_argument("Index out of range!"); + dirty = true; + collisionTags[tagIndex] = newTag; } @@ -133,6 +157,8 @@ namespace SHADE if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) throw std::invalid_argument("Index out of range!"); + dirty = true; + collisionTags[tagIndex].SetMask(mask); } @@ -145,8 +171,9 @@ namespace SHADE /** * I HATE FILE IO * - * Each line in the file should be "indextag name". - * If the line fails to follow this format, use the default tag name (index + 1) + * Each line in the file should be "indextag namemask". + * If the line fails to follow this format, use the default tag name (index + 1) and default mask. + * If no mask was read, use a default mask. */ // Populate tag names with default @@ -187,18 +214,40 @@ namespace SHADE { SHLOG_ERROR ( - "Collision tag file line {} does not match the required format of 'indextag name'. Default tag used for index {}" + "Collision tag file line {} does not match the required format of 'indextag namemask'. Default tag used for index {}" , linesRead + 1 , tagIndex ) // Use default collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1)); + collisionTags[tagIndex].SetMask(SHUtilities::ConvertEnum(SHCollisionTag::Layer::ALL)); continue; } collisionTags[tagIndex].SetName(tagName); + // Next element is the mask value + std::string maskString; + ss >> maskString; + + uint16_t mask = std::numeric_limits::max(); + if (maskString.empty()) + { + SHLOG_ERROR + ( + "Collision tag file line {} does not match the required format of 'indextag namemask'. Default mask used for index {}" + , linesRead + 1 + , tagIndex + ) + } + else + { + mask = static_cast(std::stoi(maskString)); + } + + collisionTags[tagIndex].SetMask(mask); + ss.clear(); } @@ -215,9 +264,19 @@ namespace SHADE return; } + // Index Name Mask for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i) - collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl; + collisionTagNamesFile << i << " " << collisionTags[i].GetName() << " " << collisionTags[i].GetMask() << std::endl; collisionTagNamesFile.close(); } + + void SHCollisionTagMatrix::Clear() noexcept + { + dirty = false; + + for (auto& tag : collisionTags) + tag.dirty = false; + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h index 90018fe4..6ece83ac 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTagMatrix.h @@ -29,6 +29,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ + [[nodiscard]] static bool IsDirty () noexcept; [[nodiscard]] static const std::string& GetTagName (int tagIndex); [[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept; @@ -39,29 +40,36 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept; - static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept; - static void SetTag (const std::string& tagName, uint16_t mask) noexcept; + static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept; + static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept; + static void SetTag (const std::string& tagName, uint16_t mask) noexcept; // Unsafe Setters: Can throw exceptions - static void SetTagName (int tagIndex, const std::string& newTagName); - static void SetTag (int tagIndex, const SHCollisionTag& newTag); - static void SetTag (int tagIndex, uint16_t mask); + static void SetTagName (int tagIndex, const std::string& newTagName); + static void SetTag (int tagIndex, const SHCollisionTag& newTag); + static void SetTag (int tagIndex, uint16_t mask); /*---------------------------------------------------------------------------------*/ /* Function Members */ /*---------------------------------------------------------------------------------*/ - static void Init (const std::filesystem::path& tagNameFilePath) noexcept; - static void Exit (const std::filesystem::path& tagNameFilePath) noexcept; + static void Init (const std::filesystem::path& tagNameFilePath) noexcept; + static void Exit (const std::filesystem::path& tagNameFilePath) noexcept; + + /** + * @brief + * Clears the dirty flag. + */ + static void Clear () noexcept; private: /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ + static bool dirty; static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS]; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp index b1d2d5fc..0716e68d 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.cpp @@ -23,15 +23,18 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHCollisionTag::SHCollisionTag() noexcept - : mask { SHUtilities::ConvertEnum(Layer::ALL) } + : dirty { true } + , mask { SHUtilities::ConvertEnum(Layer::ALL) } {} SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept - : mask { _mask } + : dirty { true } + , mask { _mask } {} SHCollisionTag::SHCollisionTag(Layer layer) noexcept - : mask { SHUtilities::ConvertEnum(layer) } + : dirty { true } + , mask { SHUtilities::ConvertEnum(layer) } {} /*-----------------------------------------------------------------------------------*/ @@ -57,6 +60,11 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + bool SHCollisionTag::IsDirty() const noexcept + { + return dirty; + } + uint16_t SHCollisionTag::GetMask() const noexcept { return mask; @@ -86,6 +94,7 @@ namespace SHADE void SHCollisionTag::SetMask(uint16_t newMask) noexcept { + dirty = true; mask = newMask; } @@ -96,6 +105,8 @@ namespace SHADE void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept { + dirty = true; + const auto VALUE = SHUtilities::ConvertEnum(layer); state ? mask |= VALUE : mask &= ~(VALUE); } @@ -105,6 +116,8 @@ namespace SHADE if (layerIndex < 0 || layerIndex > NUM_LAYERS) throw std::invalid_argument("Index out of range!"); + dirty = true; + const auto VALUE = 1U << layerIndex; state ? mask |= (VALUE) : mask &= ~(VALUE); } diff --git a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h index 9c7b4364..ac68d6da 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionTags/SHCollisionTags.h @@ -23,6 +23,13 @@ namespace SHADE class SH_API SHCollisionTag { + private: + /*---------------------------------------------------------------------------------*/ + /* Friends */ + /*---------------------------------------------------------------------------------*/ + + friend class SHCollisionTagMatrix; + public: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ @@ -82,6 +89,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ + [[nodiscard]] bool IsDirty () const noexcept; [[nodiscard]] uint16_t GetMask () const noexcept; [[nodiscard]] const std::string& GetName () const noexcept; [[nodiscard]] bool GetLayerState (Layer layer) const noexcept; @@ -101,6 +109,7 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ + bool dirty; uint16_t mask; std::string name; }; diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp index 3a47a5cf..e45d6ef3 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHBox.cpp @@ -102,11 +102,7 @@ namespace SHADE const SHTransform& PARENT_TRANSFORM = collider->GetTransform(); SetScale(PARENT_TRANSFORM.scale); - if (rp3dCollider) - { - const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; - rp3dCollider->setLocalToBodyTransform(OFFSETS); - } + SHCollisionShape::Update(); } diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp index 8147c94a..61dc6516 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.cpp @@ -118,6 +118,9 @@ namespace SHADE void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept { collisionTag = newCollisionTag; + + if (rp3dCollider) + rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask()); } void SHCollisionShape::SetFriction(float friction) noexcept @@ -184,6 +187,13 @@ namespace SHADE /* Public Member Function Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHCollisionShape::UpdateCollisionTags() noexcept + { + if (collisionTag->IsDirty()) + rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask()); + } + + void SHCollisionShape::Update() noexcept { if (rp3dCollider) diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h index 3f7bf10c..8c5fdc22 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHCollisionShape.h @@ -123,6 +123,12 @@ namespace SHADE /* Member Functions */ /*---------------------------------------------------------------------------------*/ + /** + * @brief + * Re-sets the collision tags if it is dirty. + */ + void UpdateCollisionTags() noexcept; + /** * @brief * Computes the transform of the shape. diff --git a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp index ec753542..0108da27 100644 --- a/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp +++ b/SHADE_Engine/src/Physics/Collision/Shapes/SHSphere.cpp @@ -105,11 +105,7 @@ namespace SHADE const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z })); SetScale(SPHERE_SCALE); - if (rp3dCollider) - { - const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) }; - rp3dCollider->setLocalToBodyTransform(OFFSETS); - } + SHCollisionShape::Update(); } diff --git a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp index 8c88e4ae..61e5897c 100644 --- a/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp +++ b/SHADE_Engine/src/Physics/Interface/PhysicsObject/SHPhysicsObjectManager.cpp @@ -15,6 +15,7 @@ // Project Headers #include "Math/Transform/SHTransformComponent.h" +#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h" #include "Physics/Collision/Shapes/SHSphere.h" #include "Physics/Collision/Shapes/SHBox.h" #include "Physics/Interface/SHColliderComponent.h" @@ -385,6 +386,11 @@ namespace SHADE } default: break; } + + collisionShape->SetMaterial(collisionShape->GetMaterial()); + + const auto& COLLISION_TAG = collisionShape->GetCollisionTag(); + collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(COLLISION_TAG.GetName())); } physicsObject->body->updateMassPropertiesFromColliders(); diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp index 32acaabe..895f57d0 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.cpp @@ -272,6 +272,12 @@ namespace SHADE shape->Update(); } + void SHColliderComponent::UpdateCollisionTags() noexcept + { + for (auto& shape : shapes) + shape->UpdateCollisionTags(); + } + } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h index 7dcde150..896c1905 100644 --- a/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h +++ b/SHADE_Engine/src/Physics/Interface/SHColliderComponent.h @@ -158,6 +158,12 @@ namespace SHADE */ void Update () noexcept; + /** + * @brief + * Re-sets any dirty collision tags on collision shapes. + */ + void UpdateCollisionTags () noexcept; + private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp index 3a085dd0..9b7a350a 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp @@ -36,6 +36,9 @@ namespace SHADE { auto* physicsSystem = reinterpret_cast(GetSystem()); + // Update colliders since collision tag has changed + const bool UPDATE_COLLISION_TAGS = SHCollisionTagMatrix::IsDirty(); + // Get all physics objects & sync transforms auto& physicsObjects = physicsSystem->objectManager.GetPhysicsObjects(); for (auto& [entityID, physicsObject] : physicsObjects) @@ -44,52 +47,61 @@ namespace SHADE // Assume transform is always active const bool UPDATE_TRANSFORM = TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged(); - if (!UPDATE_TRANSFORM) - continue; - // We assume that all engine components and physics object components have been successfully linked if (!physicsObject.body) continue; - // Set body transform - const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); - const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation(); + auto* shadeBody = SHComponentManager::GetComponent_s(entityID); + auto* shadeCollider = SHComponentManager::GetComponent_s(entityID); - const rp3d::Transform NEW_TRANSFORM{ WORLD_POS, WORLD_ROT }; - physicsObject.body->setTransform(NEW_TRANSFORM); - - // Sync rigid body active states if one exists - if (auto* shadeBody = SHComponentManager::GetComponent_s(entityID); shadeBody) + if (UPDATE_TRANSFORM) { - const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); - const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive(); + // Set body transform + const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); + const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation(); - if (SHADE_BODY_ACTIVE != RP3D_BODY_ACTIVE) - physicsObject.body->setIsActive(SHADE_BODY_ACTIVE); + const rp3d::Transform NEW_TRANSFORM{ WORLD_POS, WORLD_ROT }; + physicsObject.body->setTransform(NEW_TRANSFORM); - shadeBody->position = WORLD_POS; - shadeBody->orientation = WORLD_ROT; + // Sync rigid body active states if one exists + if (shadeBody) + { + const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); + const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive(); + + if (SHADE_BODY_ACTIVE != RP3D_BODY_ACTIVE) + physicsObject.body->setIsActive(SHADE_BODY_ACTIVE); + + shadeBody->position = WORLD_POS; + shadeBody->orientation = WORLD_ROT; + } + + // Sync collider active states if one exists + if (shadeCollider) + { + const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); + const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG; + + // Modify the static body's active state + // The collision listener & raycaster will handle culling inactive colliders. + if (SHADE_COLLIDER_ACTIVE != RP3D_COLLIDERS_ACTIVE) + physicsObject.body->setIsActive(SHADE_COLLIDER_ACTIVE); + + shadeCollider->transform.position = WORLD_POS; + shadeCollider->transform.orientation = WORLD_ROT; + shadeCollider->transform.scale = TRANSFORM_COMPONENT->GetWorldScale(); + + shadeCollider->Update(); + } } - // Sync collider active states if one exists - if (auto* shadeCollider = SHComponentManager::GetComponent_s(entityID); shadeCollider) - { - const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive(entityID); - const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG; - - // Modify the static body's active state - // The collision listener & raycaster will handle culling inactive colliders. - if (SHADE_COLLIDER_ACTIVE != RP3D_COLLIDERS_ACTIVE) - physicsObject.body->setIsActive(SHADE_COLLIDER_ACTIVE); - - shadeCollider->transform.position = WORLD_POS; - shadeCollider->transform.orientation = WORLD_ROT; - shadeCollider->transform.scale = TRANSFORM_COMPONENT->GetWorldScale(); - - shadeCollider->Update(); - } + if (UPDATE_COLLISION_TAGS && shadeCollider) + shadeCollider->UpdateCollisionTags(); } + + // Clear collision tag dirty flags + SHCollisionTagMatrix::Clear(); } } // namespace SHADE \ No newline at end of file From c73275f2d3201253ad9e0af0f2bcbec195298c1b Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 3 Feb 2023 16:11:30 +0800 Subject: [PATCH 8/9] Added temporary use of collision layers to C# and fixed raycast drawing --- Assets/Application.SHConfig | 2 +- Assets/Editor/Editor.SHConfig | 2 +- Assets/Editor/Layouts/UserLayout.ini | 68 ++++++------ Assets/Scenes/PhysicsTest.shade | 6 +- Assets/Scenes/Test.shade | 42 -------- Assets/Scenes/Test.shade.shmeta | 3 - Assets/Scenes/x.shade | 100 ------------------ Assets/Scenes/x.shade.shmeta | 3 - .../Implemented/LeafNodes/LeafSearch.cs | 2 +- .../Gameplay/Player/SC_PickAndThrow.cs | 6 +- Assets/Scripts/Tests/PhysicsTestObj.cs | 2 +- .../Routines/SHPhysicsDebugDrawRoutine.cpp | 24 ++--- SHADE_Managed/src/Physics/Physics.cxx | 27 +++-- SHADE_Managed/src/Physics/Physics.hxx | 21 ++-- 14 files changed, 87 insertions(+), 221 deletions(-) delete mode 100644 Assets/Scenes/Test.shade delete mode 100644 Assets/Scenes/Test.shade.shmeta delete mode 100644 Assets/Scenes/x.shade delete mode 100644 Assets/Scenes/x.shade.shmeta diff --git a/Assets/Application.SHConfig b/Assets/Application.SHConfig index 5673556d..61857f68 100644 --- a/Assets/Application.SHConfig +++ b/Assets/Application.SHConfig @@ -1,4 +1,4 @@ Start in Fullscreen: false -Starting Scene ID: 97158628 +Starting Scene ID: 97086054 Window Size: {x: 1920, y: 1080} Window Title: SHADE Engine \ No newline at end of file diff --git a/Assets/Editor/Editor.SHConfig b/Assets/Editor/Editor.SHConfig index 09efea23..7a7c92f8 100644 --- a/Assets/Editor/Editor.SHConfig +++ b/Assets/Editor/Editor.SHConfig @@ -1,4 +1,4 @@ Start Maximized: true -Working Scene ID: 84373000 +Working Scene ID: 97086054 Window Size: {x: 1920, y: 1013} Style: 0 \ No newline at end of file diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 7c2df9e0..9a8687ca 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -20,8 +20,8 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1604,48 -Size=316,941 +Pos=1434,48 +Size=486,941 Collapsed=0 DockId=0x00000006,0 @@ -76,7 +76,7 @@ DockId=0x0000000B,0 [Window][ Viewport] Pos=302,48 -Size=1300,836 +Size=1130,705 Collapsed=0 DockId=0x0000000B,0 @@ -93,14 +93,14 @@ Collapsed=0 DockId=0x0000000A,0 [Window][ Asset Browser] -Pos=302,886 -Size=1300,103 +Pos=302,755 +Size=1130,234 Collapsed=0 DockId=0x0000000C,0 [Window][Material Inspector] -Pos=1604,48 -Size=316,941 +Pos=1434,48 +Size=486,941 Collapsed=0 DockId=0x00000006,1 @@ -115,14 +115,16 @@ Size=464,144 Collapsed=0 [Window][Collider Tag Panel] -Pos=60,60 -Size=625,744 +Pos=302,48 +Size=1130,705 Collapsed=0 +DockId=0x0000000B,1 [Window][Input Bindings Panel] -Pos=60,60 -Size=154,204 +Pos=1434,48 +Size=486,941 Collapsed=0 +DockId=0x00000006,2 [Window][Save Scene As] Pos=877,444 @@ -130,36 +132,36 @@ Size=165,120 Collapsed=0 [Table][0x9D40AE32,17] -Column 0 Weight=1.0000 -Column 1 Weight=1.0000 -Column 2 Weight=1.0000 -Column 3 Weight=1.0000 -Column 4 Weight=1.0000 -Column 5 Weight=1.0000 -Column 6 Weight=1.0000 -Column 7 Weight=1.0000 -Column 8 Weight=1.0000 -Column 9 Weight=1.0000 -Column 10 Weight=1.0000 -Column 11 Weight=1.0000 -Column 12 Weight=1.0000 -Column 13 Weight=1.0000 -Column 14 Weight=1.0000 -Column 15 Weight=1.0000 -Column 16 Weight=1.0000 +Column 0 Weight=0.9945 +Column 1 Weight=0.9945 +Column 2 Weight=0.9945 +Column 3 Weight=0.9945 +Column 4 Weight=0.9945 +Column 5 Weight=0.9945 +Column 6 Weight=0.9945 +Column 7 Weight=0.9945 +Column 8 Weight=0.9945 +Column 9 Weight=0.9945 +Column 10 Weight=0.9945 +Column 11 Weight=0.9945 +Column 12 Weight=1.0132 +Column 13 Weight=0.8444 +Column 14 Weight=0.9945 +Column 15 Weight=1.2009 +Column 16 Weight=1.0132 [Docking][Data] DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,941 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1602,1036 Split=X + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1432,1036 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=300,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1300,1036 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1130,1036 Split=Y Selected=0xB41284E7 DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7 DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7 - DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,836 CentralNode=1 Selected=0xB41284E7 - DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,103 Selected=0xB128252A + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,705 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,234 Selected=0xB128252A DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=316,1036 Selected=0xE7039252 + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=486,1036 Selected=0xE7039252 diff --git a/Assets/Scenes/PhysicsTest.shade b/Assets/Scenes/PhysicsTest.shade index 77953a18..5e3a2986 100644 --- a/Assets/Scenes/PhysicsTest.shade +++ b/Assets/Scenes/PhysicsTest.shade @@ -4,15 +4,15 @@ NumberOfChildren: 0 Components: Transform Component: - Translate: {x: 0, y: 7, z: -0.5} - Rotate: {x: 0, y: 0, z: 0.785398185} + Translate: {x: 0, y: 7, z: 0} + Rotate: {x: 0, y: 0, z: 0} Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523} IsActive: true RigidBody Component: Type: Dynamic Drag: 0.00999999978 Angular Drag: 0.100000001 - Use Gravity: true + Use Gravity: false Interpolate: true Sleeping Enabled: true Freeze Position X: false diff --git a/Assets/Scenes/Test.shade b/Assets/Scenes/Test.shade deleted file mode 100644 index 4b831802..00000000 --- a/Assets/Scenes/Test.shade +++ /dev/null @@ -1,42 +0,0 @@ -- EID: 0 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Camera Component: - Position: {x: 0, y: 0, z: 0} - Pitch: 0 - Yaw: 0 - Roll: 0 - Width: 1920 - Height: 1080 - Near: 0.00999999978 - Far: 10000 - Perspective: true - IsActive: true - Scripts: ~ -- EID: 1 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - IsActive: true - RigidBody Component: - Type: Dynamic - Drag: 0.00999999978 - Angular Drag: 0.100000001 - Use Gravity: false - Interpolate: true - Sleeping Enabled: true - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - IsActive: true - Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/Test.shade.shmeta b/Assets/Scenes/Test.shade.shmeta deleted file mode 100644 index d5ded40c..00000000 --- a/Assets/Scenes/Test.shade.shmeta +++ /dev/null @@ -1,3 +0,0 @@ -Name: Test -ID: 97979840 -Type: 5 diff --git a/Assets/Scenes/x.shade b/Assets/Scenes/x.shade deleted file mode 100644 index 959e4982..00000000 --- a/Assets/Scenes/x.shade +++ /dev/null @@ -1,100 +0,0 @@ -- EID: 0 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 2, y: 2, z: 0} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 1, y: 1, z: 1} - IsActive: true - RigidBody Component: - Type: Dynamic - Drag: 0.00999999978 - Angular Drag: 0.100000001 - Use Gravity: true - Interpolate: true - Sleeping Enabled: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - IsActive: true - Collider Component: - Colliders: - - Is Trigger: false - Collision Tag: 1 - Type: Sphere - Radius: 1 - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Rotation Offset: {x: 0, y: 0, z: 0} - IsActive: true - Scripts: ~ -- EID: 1 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Camera Component: - Position: {x: 0, y: 0, z: 5} - Pitch: 0 - Yaw: 0 - Roll: 0 - Width: 1920 - Height: 1080 - Near: 0.00999999978 - Far: 10000 - Perspective: true - IsActive: true - Scripts: ~ -- EID: 2 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 1, y: 1, z: 1} - IsActive: true - RigidBody Component: - Type: Dynamic - Drag: 0.00999999978 - Angular Drag: 0.100000001 - Use Gravity: false - Interpolate: true - Sleeping Enabled: false - Freeze Position X: true - Freeze Position Y: true - Freeze Position Z: true - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - IsActive: true - Collider Component: - Colliders: - - Is Trigger: false - Collision Tag: 3 - Type: Sphere - Radius: 1 - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Rotation Offset: {x: 0, y: 0, z: 0} - - Is Trigger: false - Collision Tag: 2 - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 2, y: 0, z: 0} - Rotation Offset: {x: 0, y: 0, z: 0} - IsActive: true - Scripts: ~ \ No newline at end of file diff --git a/Assets/Scenes/x.shade.shmeta b/Assets/Scenes/x.shade.shmeta deleted file mode 100644 index 06a5e721..00000000 --- a/Assets/Scenes/x.shade.shmeta +++ /dev/null @@ -1,3 +0,0 @@ -Name: x -ID: 84373000 -Type: 5 diff --git a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs index b5b03629..a48ffcf7 100644 --- a/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs +++ b/Assets/Scripts/Gameplay/AIBehaviour/Implemented/LeafNodes/LeafSearch.cs @@ -159,7 +159,7 @@ public partial class LeafSearch : BehaviourTreeNode //Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset; Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition); - RaycastHit sightRayHit = Physics.Raycast(sightRay, false)[0]; + RaycastHit sightRayHit = Physics.Raycast(sightRay, false, (ushort)65535)[0]; //As of November 2022, RaycastHit contains only the FIRST object hit by //the ray in the Other GameObject data member //Diren may likely add ALL objects hit by the ray over December diff --git a/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs b/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs index 2c5e95ac..f933f9bc 100644 --- a/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs +++ b/Assets/Scripts/Gameplay/Player/SC_PickAndThrow.cs @@ -204,9 +204,9 @@ public class PickAndThrow : Script Vector3 playerRayPos = pc.tranform.GlobalPosition; playerRayPos.y += 0.05f; dirNor.Normalise(); - List rayList1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance, false); - List rayList2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance, false); - List rayList3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f, false); + List rayList1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance, false, (ushort)65535); + List rayList2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance, false, (ushort)65535); + List rayList3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f, false, (ushort)65535); if (rayList1.Count > 0 && rayList2.Count > 0 && rayList3.Count > 0) { diff --git a/Assets/Scripts/Tests/PhysicsTestObj.cs b/Assets/Scripts/Tests/PhysicsTestObj.cs index 781d0b11..82929888 100644 --- a/Assets/Scripts/Tests/PhysicsTestObj.cs +++ b/Assets/Scripts/Tests/PhysicsTestObj.cs @@ -82,7 +82,7 @@ public class PhysicsTestObj : Script { Ray colliderRay = new Ray(); colliderRay.Direction = Vector3.Right; - Physics.ColliderRaycast(collider.Owner, colliderRay, false); + Physics.ColliderRaycast(collider.Owner, colliderRay, false, 8); for (int i = 0; i < 6; ++i) { diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp index 469e835d..0d61a494 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp @@ -65,6 +65,18 @@ namespace SHADE if (!physicsSystem) return; + if (DRAW_RAYCASTS) + { + const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)]; + + const auto& RAYS = physicsSystem->raycastHits; + for (const auto& hit : RAYS) + debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true); + + // Clear rays for the physics system + physicsSystem->raycastHits.clear(); + } + rp3d::DebugRenderer* rp3dRenderer = nullptr; if (physicsSystem->worldState.world) rp3dRenderer = &physicsSystem->worldState.world->getDebugRenderer(); @@ -96,18 +108,6 @@ namespace SHADE for (int i = 0; i < NUM_LINES; ++i) debugDrawSystem->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, CONTACT_COLOUR, true); } - - if (DRAW_RAYCASTS) - { - const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)]; - - const auto& RAYS = physicsSystem->raycastHits; - for (const auto& hit : RAYS) - debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true); - - // Clear rays for the physics system - physicsSystem->raycastHits.clear(); - } } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Managed/src/Physics/Physics.cxx b/SHADE_Managed/src/Physics/Physics.cxx index e5c376d2..7b2349a6 100644 --- a/SHADE_Managed/src/Physics/Physics.cxx +++ b/SHADE_Managed/src/Physics/Physics.cxx @@ -45,7 +45,7 @@ namespace SHADE /* Raycast Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - List^ Physics::Raycast(Ray ray, bool continuous) + List^ Physics::Raycast(Ray ray, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -53,6 +53,7 @@ namespace SHADE SHPhysicsSystemInterface::RaycastInfo raycastInfo; raycastInfo.ray = Convert::ToNative(ray); raycastInfo.continuous = continuous; + raycastInfo.layers = layer; const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); if (!NATIVE_RESULTS.empty()) @@ -64,7 +65,7 @@ namespace SHADE return results; } - List^ Physics::Raycast(Ray ray, float distance, bool continuous) + List^ Physics::Raycast(Ray ray, float distance, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -73,6 +74,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(ray); raycastInfo.distance = distance; raycastInfo.continuous = continuous; + raycastInfo.layers = layer; const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); if (!NATIVE_RESULTS.empty()) @@ -84,7 +86,7 @@ namespace SHADE return results; } - List^ Physics::Linecast(Vector3 start, Vector3 end, bool continuous) + List^ Physics::Linecast(Vector3 start, Vector3 end, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -97,6 +99,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(CLI_RAY); raycastInfo.distance = (end - start).GetMagnitude(); raycastInfo.continuous = continuous; + raycastInfo.layers = layer; const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); if (!NATIVE_RESULTS.empty()) @@ -108,7 +111,7 @@ namespace SHADE return results; } - List^ Physics::ColliderRaycast(GameObject object, Ray ray, bool continuous) + List^ Physics::ColliderRaycast(GameObject object, Ray ray, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -123,6 +126,7 @@ namespace SHADE SHPhysicsSystemInterface::RaycastInfo raycastInfo; raycastInfo.ray = Convert::ToNative(ray); raycastInfo.continuous = continuous; + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); @@ -135,7 +139,7 @@ namespace SHADE return results; } - List^ Physics::ColliderRaycast(GameObject object, Ray ray, float distance, bool continuous) + List^ Physics::ColliderRaycast(GameObject object, Ray ray, float distance, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -151,6 +155,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(ray); raycastInfo.distance = distance; raycastInfo.continuous = continuous; + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); @@ -163,7 +168,7 @@ namespace SHADE return results; } - List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, bool continuous) + List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -185,6 +190,7 @@ namespace SHADE SHPhysicsSystemInterface::RaycastInfo raycastInfo; raycastInfo.ray = Convert::ToNative(ray); raycastInfo.continuous = continuous; + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); @@ -197,7 +203,7 @@ namespace SHADE return results; } - List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance, bool continuous) + List^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -220,6 +226,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(ray); raycastInfo.continuous = continuous; raycastInfo.distance = distance; + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); @@ -232,7 +239,7 @@ namespace SHADE return results; } - List^ Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end, bool continuous) + List^ Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -252,6 +259,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(CLI_RAY); raycastInfo.distance = (end - start).GetMagnitude(); raycastInfo.continuous = continuous; + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); @@ -264,7 +272,7 @@ namespace SHADE return results; } - List^ Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous) + List^ Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous, unsigned short layer) { List^ results = gcnew List(); @@ -291,6 +299,7 @@ namespace SHADE raycastInfo.ray = Convert::ToNative(CLI_RAY); raycastInfo.continuous = continuous; raycastInfo.distance = (end - start).GetMagnitude(); + raycastInfo.layers = layer; raycastInfo.SetColliderID(object.EntityId); const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo); diff --git a/SHADE_Managed/src/Physics/Physics.hxx b/SHADE_Managed/src/Physics/Physics.hxx index 573d8cad..7f5e1609 100644 --- a/SHADE_Managed/src/Physics/Physics.hxx +++ b/SHADE_Managed/src/Physics/Physics.hxx @@ -47,10 +47,13 @@ namespace SHADE /// /// Whether or not the raycast should stop at the first object hit. /// + /// + /// The layers to cast the ray on. + /// /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ Raycast (Ray ray, bool continuous); + static System::Collections::Generic::List^ Raycast (Ray ray, bool continuous, unsigned short layer); /// /// Casts a ray for a given distance into the world. @@ -63,7 +66,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ Raycast (Ray ray, float distance, bool continuous); + static System::Collections::Generic::List^ Raycast (Ray ray, float distance, bool continuous, unsigned short layer); /// /// Casts a bounded ray into the world. @@ -76,7 +79,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ Linecast (Vector3 start, Vector3 end, bool continuous); + static System::Collections::Generic::List^ Linecast (Vector3 start, Vector3 end, bool continuous, unsigned short layer); /// /// Casts an infinite ray w.r.t a GameObject. @@ -92,7 +95,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, bool continuous); + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, bool continuous, unsigned short layer); /// /// Casts a ray for a given distance w.r.t a GameObject. @@ -109,7 +112,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, float distance, bool continuous); + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, Ray ray, float distance, bool continuous, unsigned short layer); /// /// Casts an infinite ray w.r.t a specific collider on a GameObject. @@ -126,7 +129,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, bool continuous); + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, bool continuous, unsigned short layer); /// /// Casts a ray for a given distance w.r.t a specific collider on a GameObject. @@ -144,7 +147,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance, bool continuous); + static System::Collections::Generic::List^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance, bool continuous, unsigned short layer); /// /// Casts a bounded ray w.r.t a GameObject. @@ -160,7 +163,7 @@ namespace SHADE /// /// The results of the raycast. If nothing was hit, an empty list is returned. /// - static System::Collections::Generic::List^ ColliderLineCast (GameObject object, Vector3 start, Vector3 end, bool continuous); + static System::Collections::Generic::List^ ColliderLineCast (GameObject object, Vector3 start, Vector3 end, bool continuous, unsigned short layer); /// /// Casts a bounded ray w.r.t a specific collider on a GameObject. @@ -176,7 +179,7 @@ namespace SHADE /// /// /// The results of the raycast. If nothing was hit, an empty list is returned./// - static System::Collections::Generic::List^ ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous); + static System::Collections::Generic::List^ ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous, unsigned short layer); private: /*---------------------------------------------------------------------------------*/ From 4cf17c16b526ba502e7d3818f4571eb617f1b43b Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Fri, 3 Feb 2023 16:54:35 +0800 Subject: [PATCH 9/9] Fixed bug where shmeta files in folders would still appear in SHADE_Scripting.csproj's solution explorer --- SHADE_Engine/src/Scripting/SHScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 435cb6fb..8b836d2a 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -261,6 +261,7 @@ namespace SHADE net5.0\n\ x64\n\ Release;Debug\n\ + $(DefaultItemExcludes);**/*.shmeta\n\ \n\ \n\ .\\bin\\Release\n\ @@ -283,7 +284,6 @@ namespace SHADE \n\ \n\ \n\ - \n\ \n\ \n\ \n";