diff --git a/Assets/Scenes/PhysicsSandbox.shade b/Assets/Scenes/PhysicsSandbox.shade index 8817b62e..21840aca 100644 --- a/Assets/Scenes/PhysicsSandbox.shade +++ b/Assets/Scenes/PhysicsSandbox.shade @@ -14,7 +14,7 @@ Mass: 10 Drag: 1 Angular Drag: 1 - Use Gravity: false + Use Gravity: true Gravity Scale: 1 Interpolate: true Sleeping Enabled: true @@ -48,7 +48,7 @@ NumberOfChildren: 0 Components: Camera Component: - Position: {x: 0, y: 2, z: 5} + Position: {x: 0, y: 2, z: 3} Pitch: 0 Yaw: 0 Roll: 0 @@ -70,12 +70,12 @@ Scale: {x: 1, y: 1, z: 1} IsActive: true RigidBody Component: - Type: Static + Type: Dynamic Auto Mass: false - Mass: .inf + Mass: 1 Drag: 0.00999999978 Angular Drag: 0.00999999978 - Use Gravity: true + Use Gravity: false Gravity Scale: 1 Interpolate: true Sleeping Enabled: true diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index aa5a4f0e..8607702d 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -185,6 +185,13 @@ namespace Sandbox #endif SHSceneManager::SceneUpdate(0.016f); #ifdef SHEDITOR + static bool drawBP = false; + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::RIGHT_CTRL)) + { + drawBP = !drawBP; + SHSystemManager::GetSystem()->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::BROADPHASE, drawBP); + } + SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, SHFrameRateController::GetRawDeltaTime()); editor->PollPicking(); #else diff --git a/SHADE_Engine/src/Math/Geometry/SHBox.cpp b/SHADE_Engine/src/Math/Geometry/SHBox.cpp index 7261749b..05595fe1 100644 --- a/SHADE_Engine/src/Math/Geometry/SHBox.cpp +++ b/SHADE_Engine/src/Math/Geometry/SHBox.cpp @@ -199,7 +199,7 @@ namespace SHADE bool SHBox::Contains(const SHBox& rhs) const noexcept { - return BoundingBox::Contains(rhs); + return BoundingBox::Contains(rhs) == CONTAINS; } float SHBox::Volume() const noexcept diff --git a/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.cpp b/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.cpp index db30222b..540d5375 100644 --- a/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.cpp +++ b/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.cpp @@ -107,7 +107,7 @@ namespace SHADE const std::vector& SHAABBTree::GetAABBs() const noexcept { - static std::vector aabbs; + static AABBs aabbs; static std::stack nodeIndices; aabbs.clear(); diff --git a/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.h b/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.h index 973631a1..f23fd946 100644 --- a/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.h +++ b/SHADE_Engine/src/Physics/Collision/Broadphase/SHDynamicAABBTree.h @@ -28,6 +28,12 @@ namespace SHADE class SH_API SHAABBTree { public: + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + + using AABBs = std::vector; + /*---------------------------------------------------------------------------------*/ /* Data Members */ /*---------------------------------------------------------------------------------*/ @@ -55,7 +61,7 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] const std::vector& GetAABBs () const noexcept; + [[nodiscard]] const AABBs& GetAABBs () const noexcept; /*---------------------------------------------------------------------------------*/ /* Member Functions */ @@ -116,7 +122,7 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - static constexpr float AABB_EXTENSION = 0.2f; + static constexpr float AABB_EXTENSION = 0.1f; // For quick access std::unordered_map nodeMap; diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp index a871a5eb..b1110489 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp @@ -125,7 +125,7 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ - const SHVec3& SHSphereCollisionShape::GetCenter() const noexcept + SHVec3 SHSphereCollisionShape::GetCenter() const noexcept { return Center; } diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h index 1325fc56..eb41f93c 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h @@ -72,9 +72,9 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] const SHVec3& GetCenter () const noexcept; - [[nodiscard]] float GetWorldRadius () const noexcept; - [[nodiscard]] float GetRelativeRadius () const noexcept; + [[nodiscard]] SHVec3 GetCenter () const noexcept; + [[nodiscard]] float GetWorldRadius () const noexcept; + [[nodiscard]] float GetRelativeRadius () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ diff --git a/SHADE_Engine/src/Physics/Collision/Contacts/SHManifold.h b/SHADE_Engine/src/Physics/Collision/Contacts/SHManifold.h index da6fe233..0534f749 100644 --- a/SHADE_Engine/src/Physics/Collision/Contacts/SHManifold.h +++ b/SHADE_Engine/src/Physics/Collision/Contacts/SHManifold.h @@ -35,12 +35,13 @@ namespace SHADE SHCollisionShape* A = nullptr; SHCollisionShape* B = nullptr; + uint32_t numContacts = 0; + SHCollisionState state = SHCollisionState::INVALID; + SHVec3 normal; SHVec3 tangents[SHContact::NUM_TANGENTS]; - SHContact contacts[MAX_NUM_CONTACTS]; - uint32_t numContacts = 0; - SHCollisionState state; + }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/Narrowphase/SHSphereVsSphere.cpp b/SHADE_Engine/src/Physics/Collision/Narrowphase/SHSphereVsSphere.cpp index b26a33dd..8b529241 100644 --- a/SHADE_Engine/src/Physics/Collision/Narrowphase/SHSphereVsSphere.cpp +++ b/SHADE_Engine/src/Physics/Collision/Narrowphase/SHSphereVsSphere.cpp @@ -25,8 +25,8 @@ namespace SHADE bool SHCollision::SphereVsSphere(const SHCollisionShape& A, const SHCollisionShape& B) noexcept { - const SHSphereCollisionShape& SPHERE_A = dynamic_cast(A); - const SHSphereCollisionShape& SPHERE_B = dynamic_cast(B); + const SHSphereCollisionShape& SPHERE_A = reinterpret_cast(A); + const SHSphereCollisionShape& SPHERE_B = reinterpret_cast(B); return SHSphere::Intersect(SPHERE_A, SPHERE_B); } @@ -34,10 +34,10 @@ namespace SHADE bool SHCollision::SphereVsSphere(SHManifold& manifold, const SHCollisionShape& A, const SHCollisionShape& B) noexcept { // Convert to spheres - const SHSphereCollisionShape& SPHERE_A = dynamic_cast(A); - const SHSphereCollisionShape& SPHERE_B = dynamic_cast(B); + const SHSphereCollisionShape& SPHERE_A = reinterpret_cast(A); + const SHSphereCollisionShape& SPHERE_B = reinterpret_cast(B); - const SHVec3 A_TO_B = SPHERE_B.GetCenter() - SPHERE_A.GetCenter(); + const SHVec3 A_TO_B = SPHERE_B.GetCenter() - SPHERE_A.GetCenter(); const float DISTANCE_BETWEEN_CENTERS_SQUARED = A_TO_B.LengthSquared(); const float COMBINED_RADIUS = (SPHERE_A.GetWorldRadius() + SPHERE_B.GetWorldRadius()); diff --git a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp index 4ff94b7d..ff362d69 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp +++ b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.cpp @@ -39,6 +39,11 @@ namespace SHADE /* Getter Functions Definitions */ /*-----------------------------------------------------------------------------------*/ + const SHAABBTree::AABBs& SHPhysicsWorld::GetBroadphaseAABBs() const noexcept + { + return broadphase.GetAABBs(); + } + const SHPhysicsWorld::TriggerEvents& SHPhysicsWorld::GetTriggerEvents() const noexcept { static TriggerEvents triggerEvents; @@ -153,8 +158,13 @@ namespace SHADE * Get collider's rigid body * Run through the rigid body's contact graph and wake all of its non-static bodies that are asleep */ + } - + void SHPhysicsWorld::UpdateBroadphase(SHCollider* collider) noexcept + { + auto& shapes = collider->GetCollisionShapes(); + for (auto* shape : shapes) + broadphase.Update(shape->id, shape->ComputeAABB()); } void SHPhysicsWorld::Step(float dt) @@ -367,6 +377,9 @@ namespace SHADE void SHPhysicsWorld::runNarrowphase() noexcept { + if (narrowphaseBatch.empty()) + return; + for (auto& [id, narrowphasePair] : narrowphaseBatch) { const bool IS_A_TRIGGER = narrowphasePair.A->IsTrigger(); @@ -378,6 +391,9 @@ namespace SHADE else collideManifolds(id, narrowphasePair); } + + // Clear every frame + narrowphaseBatch.clear(); } void SHPhysicsWorld::collideTriggers(const SHCollisionID& id, NarrowphasePair& narrowphasePair) noexcept @@ -432,10 +448,18 @@ namespace SHADE void SHPhysicsWorld::updateCollisionState(bool isColliding, SHCollisionState& state) noexcept { - if (isColliding) + if (isColliding) + { + // New states start at invalid. In the first frame of collision, move to enter. + // If it already in enter, move to stay state = state == SHCollisionState::INVALID ? SHCollisionState::ENTER : SHCollisionState::STAY; + } else - state = SHCollisionState::EXIT; + { + // New states start at invalid. In false positive, remain unchanged. + // If previously colliding, move to exit. + state = state == SHCollisionState::INVALID ? SHCollisionState::INVALID : SHCollisionState::EXIT; + } } void SHPhysicsWorld::updateEvents() noexcept diff --git a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h index f0d2cd5b..e0e4f796 100644 --- a/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h +++ b/SHADE_Engine/src/Physics/Dynamics/SHPhysicsWorld.h @@ -71,8 +71,10 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - const TriggerEvents& GetTriggerEvents () const noexcept; - const CollisionEvents& GetCollisionEvents () const noexcept; + const SHAABBTree::AABBs& GetBroadphaseAABBs () const noexcept; + + const TriggerEvents& GetTriggerEvents () const noexcept; + const CollisionEvents& GetCollisionEvents () const noexcept; /*---------------------------------------------------------------------------------*/ /* Member Functions */ @@ -84,6 +86,14 @@ namespace SHADE void AddCollider (SHCollider* collider) noexcept; void RemoveCollider (SHCollider* collider) noexcept; + /** + * @brief + * Invoke this method to update the broadphase of a collider while the simulation + * is not running. + * @param collider + * The collider to update. + */ + void UpdateBroadphase (SHCollider* collider) noexcept; void Step (float dt); private: diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp index 72b2aad5..b43b5b77 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsDebugDrawRoutine.cpp @@ -18,6 +18,7 @@ #include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h" #include "Math/Transform/SHTransformComponent.h" #include "Physics/System/SHPhysicsSystem.h" +#include "Tools/Utilities/SHUtilities.h" namespace SHADE { @@ -40,7 +41,6 @@ namespace SHADE if (!physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::ACTIVE)) return; - auto* physicsSystem = SHSystemManager::GetSystem(); auto* debugDrawSystem = SHSystemManager::GetSystem(); const bool DRAW_COLLIDERS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::COLLIDERS); @@ -68,6 +68,10 @@ namespace SHADE } } + auto* physicsSystem = SHSystemManager::GetSystem(); + if (!physicsSystem) + return; + if (DRAW_CONTACTS) { // TODO @@ -81,7 +85,16 @@ namespace SHADE if (DRAW_BROADPHASE) { - // TODO + const SHColour& AABB_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::BROADPHASE)]; + + auto& broadphaseAABBs = physicsSystem->GetWorld()->GetBroadphaseAABBs(); + + for (auto& aabb : broadphaseAABBs) + { + // Compute AABB Transform + const SHMatrix TRS = SHMatrix::Transform(aabb.GetCenter(), SHQuaternion::Identity, aabb.GetWorldExtents() * 2.0f); + debugDrawSystem->DrawWireCube(TRS, AABB_COLOUR); + } } } diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp index 88ea8d79..178a6120 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp @@ -65,6 +65,8 @@ namespace SHADE physicsObject.collider->SetScale(WORLD_SCL); physicsObject.collider->RecomputeShapes(); + + physicsSystem->physicsWorld->UpdateBroadphase(physicsObject.collider); } } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp index 20084ebe..975c561b 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp @@ -41,9 +41,9 @@ namespace SHADE eventFunctions[2] = { &SHPhysicsSystem::onSceneInit , SH_SCENE_INIT_POST }; eventFunctions[3] = { &SHPhysicsSystem::onSceneExit , SH_SCENE_EXIT_POST }; - #ifdef SHEDITOR - eventFunctions[4] = { &SHPhysicsSystem::onEditorPlay , SH_EDITOR_ON_PLAY_EVENT }; - #endif + //#ifdef SHEDITOR + // eventFunctions[4] = { &SHPhysicsSystem::onEditorPlay , SH_EDITOR_ON_PLAY_EVENT }; + //#endif } SHPhysicsSystem::~SHPhysicsSystem() noexcept @@ -55,6 +55,11 @@ namespace SHADE /* Getter Function Definitions */ /*-----------------------------------------------------------------------------------*/ + const SHPhysicsWorld* SHPhysicsSystem::GetWorld() const noexcept + { + return physicsWorld; + } + double SHPhysicsSystem::GetFixedUpdateRate() const noexcept { return 1.0 / fixedDT; @@ -173,15 +178,6 @@ namespace SHADE // Create the physics world physicsWorld = new SHPhysicsWorld; - #ifdef SHEDITOR - - // Link all entities with the world if editor is already playing. - // This is for handling scene changes while the editor is active. - - const auto* EDITOR = SHSystemManager::GetSystem(); - if (!EDITOR || EDITOR->editorState != SHEditor::State::PLAY) - return onSceneInitEvent.get()->handle; - for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values) { if (PHYSICS_OBJECT.rigidBody) @@ -191,7 +187,25 @@ namespace SHADE physicsWorld->AddCollider(PHYSICS_OBJECT.collider); } - #endif + //#ifdef SHEDITOR + + // // Link all entities with the world if editor is already playing. + // // This is for handling scene changes while the editor is active. + // + // const auto* EDITOR = SHSystemManager::GetSystem(); + // if (!EDITOR || EDITOR->editorState != SHEditor::State::PLAY) + // return onSceneInitEvent.get()->handle; + + // for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values) + // { + // if (PHYSICS_OBJECT.rigidBody) + // physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody); + + // if (PHYSICS_OBJECT.collider) + // physicsWorld->AddCollider(PHYSICS_OBJECT.collider); + // } + + //#endif return onSceneInitEvent.get()->handle; } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h index ce1f1396..f9866ebe 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h +++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h @@ -45,8 +45,9 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] double GetFixedUpdateRate() const noexcept; - [[nodiscard]] double GetFixedDT() const noexcept; + [[nodiscard]] const SHPhysicsWorld* GetWorld () const noexcept; + [[nodiscard]] double GetFixedUpdateRate() const noexcept; + [[nodiscard]] double GetFixedDT () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ @@ -123,11 +124,11 @@ namespace SHADE /* Data Members */ /*---------------------------------------------------------------------------------*/ - #ifdef SHEDITOR - static constexpr int NUM_EVENT_FUNCTIONS = 5; - #else + //#ifdef SHEDITOR + // static constexpr int NUM_EVENT_FUNCTIONS = 5; + //#else static constexpr int NUM_EVENT_FUNCTIONS = 4; - #endif + //#endif // Event function container for cleanly registering to events EventFunctionPair eventFunctions[NUM_EVENT_FUNCTIONS];