From a6e1064e64dcc8515a76c445e95f9349d6e9f706 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 16 Dec 2022 15:03:55 +0800 Subject: [PATCH] Fixed bug where collider offsets were not recomputed --- .../CollisionShapes/SHCollisionShape.cpp | 31 ++++++++ .../CollisionShapes/SHCollisionShape.h | 35 ++++++--- .../CollisionShapes/SHSphereCollisionShape.h | 4 +- .../src/Physics/Collision/SHCollider.cpp | 78 ++++++++++++++----- .../src/Physics/Collision/SHCollider.h | 10 ++- .../Routines/SHPhysicsPreUpdateRoutine.cpp | 15 ++-- 6 files changed, 135 insertions(+), 38 deletions(-) diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp index 2f4e3819..d0706ed0 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp @@ -95,6 +95,15 @@ namespace SHADE return flags & FLAG_VALUE; } + bool SHCollisionShape::IsDirty() const noexcept + { + static constexpr int FLAG_POS = 6; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + return flags & FLAG_VALUE; + } + + const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept { return *collisionTag; @@ -116,21 +125,25 @@ namespace SHADE void SHCollisionShape::SetDensity(float density) noexcept { + setDirty(true); material.SetDensity(density); } void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept { + setDirty(true); material = newMaterial; } void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept { + setDirty(true); positionOffset = posOffset; } void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept { + setDirty(true); rotationOffset = rotOffset; } @@ -147,10 +160,28 @@ namespace SHADE collisionTag = newCollisionTag; } + /*-----------------------------------------------------------------------------------*/ + /* Public Function Member Definitions */ + /*-----------------------------------------------------------------------------------*/ + + void SHCollisionShape::ClearDirty() noexcept + { + setDirty(false); + } + /*-----------------------------------------------------------------------------------*/ /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHCollisionShape::setDirty(bool isDirty) noexcept + { + static constexpr int FLAG_POS = 6; + static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS; + + isDirty ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE; + } + + } // namespace SHADE RTTR_REGISTRATION diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h index 6a08f940..90020727 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h @@ -91,6 +91,7 @@ namespace SHADE [[nodiscard]] Type GetType () const noexcept; [[nodiscard]] bool IsTrigger () const noexcept; [[nodiscard]] bool IsColliding () const noexcept; + [[nodiscard]] bool IsDirty () const noexcept; [[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept; @@ -98,24 +99,31 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetFriction (float friction) noexcept; - void SetBounciness (float bounciness) noexcept; - void SetDensity (float density) noexcept; - void SetMaterial (const SHPhysicsMaterial& newMaterial) 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; + void SetPositionOffset (const SHVec3& posOffset) noexcept; + void SetRotationOffset (const SHVec3& rotOffset) noexcept; // Flags - void SetIsTrigger (bool isTrigger) noexcept; + + void SetIsTrigger (bool isTrigger) noexcept; - void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; + void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; /*---------------------------------------------------------------------------------*/ /* Member Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] virtual SHMatrix GetInertiaTensor (float mass) const noexcept = 0; + /** + * @brief + * Clears the dirty flag of the collider. + */ + void ClearDirty () noexcept; + + [[nodiscard]] virtual SHMatrix GetInertiaTensor (float mass) const noexcept = 0; protected: /*---------------------------------------------------------------------------------*/ @@ -129,10 +137,17 @@ namespace SHADE SHVec3 positionOffset; SHVec3 rotationOffset; - uint8_t flags; // 0 0 wasColliding isColliding trigger capsule sphere box + uint8_t flags; // 0 dirty wasColliding isColliding trigger capsule sphere box SHCollisionTag* collisionTag; RTTR_ENABLE() + + private: + /*---------------------------------------------------------------------------------*/ + /* Member Functions */ + /*---------------------------------------------------------------------------------*/ + + void setDirty (bool isDirty) noexcept; }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h index 72ea05f5..8276578e 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h @@ -37,8 +37,8 @@ namespace SHADE * @brief * Encapsulate a Sphere Collision Shape used for Physics Simulations. */ - class SH_API SHSphereCollisionShape : public SHCollisionShape - , private SHSphere + class SH_API SHSphereCollisionShape final : public SHCollisionShape + , private SHSphere { private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.cpp b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp index d7ca4b14..9aedef16 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollider.cpp +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp @@ -30,6 +30,7 @@ namespace SHADE : entityID { eid } , shapeIDCounter { 0 } , debugDraw { false } + , dirty { true } , rigidBody { nullptr } , shapeFactory { nullptr } , transform { worldTransform } @@ -41,6 +42,7 @@ namespace SHADE : entityID { rhs.entityID } , shapeIDCounter { rhs.shapeIDCounter } , debugDraw { rhs.debugDraw } + , dirty { rhs.dirty } , rigidBody { rhs.rigidBody } , shapeFactory { rhs.shapeFactory } , transform { rhs.transform } @@ -58,6 +60,7 @@ namespace SHADE : entityID { rhs.entityID } , shapeIDCounter { rhs.shapeIDCounter } , debugDraw { rhs.debugDraw } + , dirty { rhs.dirty } , rigidBody { rhs.rigidBody } , shapeFactory { rhs.shapeFactory } , transform { rhs.transform } @@ -100,6 +103,7 @@ namespace SHADE entityID = rhs.entityID; debugDraw = rhs.debugDraw; + dirty = rhs.dirty; rigidBody = rhs.rigidBody; shapeFactory = rhs.shapeFactory; transform = rhs.transform; @@ -119,6 +123,7 @@ namespace SHADE entityID = rhs.entityID; debugDraw = rhs.debugDraw; + dirty = rhs.dirty; rigidBody = rhs.rigidBody; shapeFactory = rhs.shapeFactory; transform = rhs.transform; @@ -201,21 +206,25 @@ namespace SHADE void SHCollider::SetTransform(const SHTransform& newTransform) noexcept { + dirty = true; transform = newTransform; } void SHCollider::SetPosition(const SHVec3& newPosition) noexcept { + dirty = true; transform.position = newPosition; } void SHCollider::SetOrientation(const SHQuaternion& newOrientation) noexcept { + dirty = true; transform.orientation = newOrientation; } void SHCollider::SetScale(const SHVec3& newScale) noexcept { + dirty = true; transform.scale = newScale; } @@ -284,6 +293,28 @@ namespace SHADE return static_cast(shapes.size()); } + void SHCollider::Update() + { + // Forcefully recompute everything since the transform was changed + if (dirty) + { + RecomputeShapes(); + dirty = false; + return; + } + + // Recompute any shapes set to dirty + for (auto* shape : shapes) + { + if (shape->IsDirty()) + { + recomputeShape(shape); + shape->ClearDirty(); + } + } + } + + void SHCollider::RemoveCollisionShape(int index) { if (!shapeFactory) @@ -329,25 +360,7 @@ namespace SHADE void SHCollider::RecomputeShapes() noexcept { for (auto* shape : shapes) - { - switch (shape->GetType()) - { - case SHCollisionShape::Type::SPHERE: - { - recomputeSphere(dynamic_cast(shape)); - break; - } - case SHCollisionShape::Type::BOX: - { - break; - } - case SHCollisionShape::Type::CAPSULE: - { - break; - } - default: break; - } - } + recomputeShape(shape); } /*-----------------------------------------------------------------------------------*/ @@ -403,6 +416,33 @@ namespace SHADE ++shapeIDCounter; } + void SHCollider::recomputeShape(SHCollisionShape* shape) noexcept + { + if (!shape) + { + SHLOGV_ERROR_D("Shape missing from Collider {}", entityID) + return; + } + + switch (shape->GetType()) + { + case SHCollisionShape::Type::SPHERE: + { + recomputeSphere(dynamic_cast(shape)); + break; + } + case SHCollisionShape::Type::BOX: + { + break; + } + case SHCollisionShape::Type::CAPSULE: + { + break; + } + default: break; + } + } + void SHCollider::recomputeSphere(SHSphereCollisionShape* sphere) noexcept { // Recompute world radius diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.h b/SHADE_Engine/src/Physics/Collision/SHCollider.h index 927c6155..8a183dcc 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollider.h +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.h @@ -132,6 +132,12 @@ namespace SHADE // TODO: Add Box & Capsule + /** + * @brief + * Recomputes any shapes that were set to dirty. + */ + void Update (); + /** * @brief * Removes a shape from the container. Removal reduces the size of the container. @@ -158,6 +164,7 @@ namespace SHADE uint32_t shapeIDCounter; // This increments everytime a shape is added to differentiate shapes. bool debugDraw; + bool dirty; SHRigidBody* rigidBody; SHCollisionShapeFactory* shapeFactory; @@ -173,7 +180,8 @@ namespace SHADE void copyShapes (const SHCollider& rhsCollider); void copyShape (const SHCollisionShape* rhsShape); - void recomputeSphere (SHSphereCollisionShape* sphere) noexcept; + void recomputeShape (SHCollisionShape* shape) noexcept; + void recomputeSphere (SHSphereCollisionShape* sphere) noexcept; }; } // namespace SHADE diff --git a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp index 88ea8d79..0094153e 100644 --- a/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp +++ b/SHADE_Engine/src/Physics/System/Routines/SHPhysicsPreUpdateRoutine.cpp @@ -41,7 +41,7 @@ namespace SHADE { const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s(entityID); - if (!TRANSFORM_COMPONENT || !TRANSFORM_COMPONENT->HasChanged()) + if (!TRANSFORM_COMPONENT) continue; const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); @@ -50,7 +50,7 @@ namespace SHADE // We assume that all engine components and physics object components have been successfully linked - if (physicsObject.rigidBody) + if (physicsObject.rigidBody && TRANSFORM_COMPONENT->HasChanged()) { SHMotionState& motionState = physicsObject.rigidBody->GetMotionState(); @@ -60,11 +60,14 @@ namespace SHADE if (physicsObject.collider) { - physicsObject.collider->SetPosition(WORLD_POS); - physicsObject.collider->SetOrientation(WORLD_ROT); - physicsObject.collider->SetScale(WORLD_SCL); + if (TRANSFORM_COMPONENT->HasChanged()) + { + physicsObject.collider->SetPosition(WORLD_POS); + physicsObject.collider->SetOrientation(WORLD_ROT); + physicsObject.collider->SetScale(WORLD_SCL); + } - physicsObject.collider->RecomputeShapes(); + physicsObject.collider->Update(); } } }