diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp index d0706ed0..5dd17d35 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.cpp @@ -25,9 +25,10 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHCollisionShape::SHCollisionShape(SHCollisionShapeID id, Type colliderType) - : id { id } - , flags { 0 } - , collisionTag { SHCollisionTagMatrix::GetTag(0) } + : id { id } + , flags { 0 } + , parentTransform { nullptr } + , collisionTag { SHCollisionTagMatrix::GetTag(0) } { flags |= 1U << SHUtilities::ConvertEnum(colliderType); } @@ -58,7 +59,7 @@ namespace SHADE const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept { - return positionOffset; + return transform.position; } const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept @@ -95,15 +96,6 @@ 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; @@ -125,26 +117,32 @@ 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::SetParentTransform(SHTransform& parentTF) noexcept + { + parentTransform = &parentTF; + } + void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept { - setDirty(true); - positionOffset = posOffset; + transform.position = posOffset; + + ComputeTransforms(); } void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept { - setDirty(true); rotationOffset = rotOffset; + transform.orientation = SHQuaternion::FromEuler(rotationOffset); + + ComputeTransforms(); } void SHCollisionShape::SetIsTrigger(bool isTrigger) noexcept @@ -160,28 +158,6 @@ 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 90020727..3c08e21a 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHCollisionShape.h @@ -14,11 +14,10 @@ // Project Headers #include "ECS_Base/Entity/SHEntity.h" -#include "Math/Geometry/SHShape.h" -#include "Math/SHQuaternion.h" #include "Physics/Collision/CollisionTags/SHCollisionTags.h" #include "Physics/Collision/SHPhysicsMaterial.h" #include "SHCollisionShapeID.h" +#include "Math/Transform/SHTransform.h" namespace SHADE { @@ -91,7 +90,6 @@ 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; @@ -104,6 +102,8 @@ namespace SHADE void SetDensity (float density) noexcept; void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept; + void SetParentTransform (SHTransform& parentTF) noexcept; + void SetPositionOffset (const SHVec3& posOffset) noexcept; void SetRotationOffset (const SHVec3& rotOffset) noexcept; @@ -117,13 +117,9 @@ namespace SHADE /* Member Functions */ /*---------------------------------------------------------------------------------*/ - /** - * @brief - * Clears the dirty flag of the collider. - */ - void ClearDirty () noexcept; - - [[nodiscard]] virtual SHMatrix GetInertiaTensor (float mass) const noexcept = 0; + virtual void ComputeTransforms () noexcept = 0; + [[nodiscard]] virtual SHMatrix GetInertiaTensor (float mass) const noexcept = 0; + [[nodiscard]] virtual SHMatrix ComputeWorldTransform () const noexcept = 0; protected: /*---------------------------------------------------------------------------------*/ @@ -134,20 +130,16 @@ namespace SHADE SHPhysicsMaterial material; - SHVec3 positionOffset; + SHTransform* parentTransform; + SHTransform transform; + + // Needed for conversion to euler angles SHVec3 rotationOffset; - uint8_t flags; // 0 dirty wasColliding isColliding trigger capsule sphere box + uint8_t flags; // 0 0 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.cpp b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp index 40671a96..e4bf68c3 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.cpp @@ -14,6 +14,7 @@ #include "SHSphereCollisionShape.h" // Project Headers +#include "Math/SHMathHelpers.h" #include "Math/SHMatrix.h" namespace SHADE @@ -37,7 +38,8 @@ namespace SHADE { material = rhs.material; - positionOffset = rhs.positionOffset; + parentTransform = rhs.parentTransform; + transform = rhs.transform; rotationOffset = rhs.rotationOffset; flags = rhs.flags; // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. @@ -52,7 +54,8 @@ namespace SHADE { material = rhs.material; - positionOffset = rhs.positionOffset; + parentTransform = rhs.parentTransform; + transform = rhs.transform; rotationOffset = rhs.rotationOffset; flags = rhs.flags; // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. @@ -72,7 +75,8 @@ namespace SHADE id = rhs.id; material = rhs.material; - positionOffset = rhs.positionOffset; + parentTransform = rhs.parentTransform; + transform = rhs.transform; rotationOffset = rhs.rotationOffset; flags = rhs.flags; // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. @@ -97,7 +101,8 @@ namespace SHADE id = rhs.id; material = rhs.material; - positionOffset = rhs.positionOffset; + parentTransform = rhs.parentTransform; + transform = rhs.transform; rotationOffset = rhs.rotationOffset; flags = rhs.flags; // Since all collision tags are taken from the matrix, we do not need to do a deep copy here. @@ -172,6 +177,18 @@ namespace SHADE /* Public Member Function Definitions */ /*-----------------------------------------------------------------------------------*/ + void SHSphereCollisionShape::ComputeTransforms() noexcept + { + const float SPHERE_SCALE = std::fabs(SHMath::Max({ parentTransform->scale.x, parentTransform->scale.y, parentTransform->scale.z })); + SetScale(SPHERE_SCALE); + + // Recompute center + const SHQuaternion FINAL_ROT = parentTransform->orientation * transform.orientation; + const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(parentTransform->position); + + Center = SHVec3::Transform(transform.position, TRS); + } + bool SHSphereCollisionShape::TestPoint(const SHVec3& point) const noexcept { return SHSphere::TestPoint(point); @@ -193,6 +210,18 @@ namespace SHADE return result; } + SHMatrix SHSphereCollisionShape::ComputeWorldTransform() const noexcept + { + const SHQuaternion ROTATION = parentTransform->orientation * transform.orientation; + const SHVec3 SCALE{ Radius }; + + return SHMatrix::Transform + ( + Center + , ROTATION + , SCALE +); + } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h index 8276578e..798c70b6 100644 --- a/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h +++ b/SHADE_Engine/src/Physics/Collision/CollisionShapes/SHSphereCollisionShape.h @@ -88,6 +88,12 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ + /** + * @brief + * Recomputes the transform of this sphere. + */ + void ComputeTransforms () noexcept override; + /** * @brief * Tests if a point is inside the sphere. @@ -96,7 +102,7 @@ namespace SHADE * @return * True if the point is inside the sphere. */ - [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; + [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override; /** * @brief @@ -107,7 +113,7 @@ namespace SHADE * An object holding the results of the raycast.
* See the corresponding header for the contents of the object. */ - [[nodiscard]] SHRaycastResult Raycast (const SHRay& ray) const noexcept override; + [[nodiscard]] SHRaycastResult Raycast (const SHRay& ray) const noexcept override; /** * @brief @@ -117,9 +123,9 @@ namespace SHADE * @return * The inertia tensor of the sphere. */ - [[nodiscard]] SHMatrix GetInertiaTensor (float mass) const noexcept override; + [[nodiscard]] SHMatrix GetInertiaTensor (float mass) const noexcept override; - + [[nodiscard]] SHMatrix ComputeWorldTransform () const noexcept override; private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.cpp b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp index 9aedef16..a6527e48 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollider.cpp +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.cpp @@ -30,19 +30,15 @@ namespace SHADE : entityID { eid } , shapeIDCounter { 0 } , debugDraw { false } - , dirty { true } , rigidBody { nullptr } , shapeFactory { nullptr } , transform { worldTransform } - { - - } + {} SHCollider::SHCollider(const SHCollider& rhs) noexcept : entityID { rhs.entityID } , shapeIDCounter { rhs.shapeIDCounter } , debugDraw { rhs.debugDraw } - , dirty { rhs.dirty } , rigidBody { rhs.rigidBody } , shapeFactory { rhs.shapeFactory } , transform { rhs.transform } @@ -60,7 +56,6 @@ namespace SHADE : entityID { rhs.entityID } , shapeIDCounter { rhs.shapeIDCounter } , debugDraw { rhs.debugDraw } - , dirty { rhs.dirty } , rigidBody { rhs.rigidBody } , shapeFactory { rhs.shapeFactory } , transform { rhs.transform } @@ -103,7 +98,6 @@ namespace SHADE entityID = rhs.entityID; debugDraw = rhs.debugDraw; - dirty = rhs.dirty; rigidBody = rhs.rigidBody; shapeFactory = rhs.shapeFactory; transform = rhs.transform; @@ -123,7 +117,6 @@ namespace SHADE entityID = rhs.entityID; debugDraw = rhs.debugDraw; - dirty = rhs.dirty; rigidBody = rhs.rigidBody; shapeFactory = rhs.shapeFactory; transform = rhs.transform; @@ -206,25 +199,21 @@ 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; } @@ -272,8 +261,9 @@ namespace SHADE ++shapeIDCounter; // Set offsets - sphere->positionOffset = posOffset; - sphere->rotationOffset = rotOffset; + sphere->SetParentTransform(transform); + sphere->SetPositionOffset(posOffset); + sphere->SetRotationOffset(rotOffset); shapes.emplace_back(sphere); @@ -293,28 +283,6 @@ 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) @@ -360,7 +328,7 @@ namespace SHADE void SHCollider::RecomputeShapes() noexcept { for (auto* shape : shapes) - recomputeShape(shape); + shape->ComputeTransforms(); } /*-----------------------------------------------------------------------------------*/ @@ -416,47 +384,4 @@ 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 - const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z })); - sphere->SetScale(SPHERE_SCALE); - - // Recompute center - const SHQuaternion FINAL_ROT = transform.orientation * SHQuaternion::FromEuler(sphere->rotationOffset); - const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(transform.position); - - const SHVec3 NEW_CENTER = SHVec3::Transform(sphere->positionOffset, TRS); - - sphere->SetCenter(NEW_CENTER); - } - - } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Physics/Collision/SHCollider.h b/SHADE_Engine/src/Physics/Collision/SHCollider.h index 8a183dcc..566bae3e 100644 --- a/SHADE_Engine/src/Physics/Collision/SHCollider.h +++ b/SHADE_Engine/src/Physics/Collision/SHCollider.h @@ -132,12 +132,6 @@ 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. @@ -164,7 +158,6 @@ namespace SHADE uint32_t shapeIDCounter; // This increments everytime a shape is added to differentiate shapes. bool debugDraw; - bool dirty; SHRigidBody* rigidBody; SHCollisionShapeFactory* shapeFactory; @@ -179,9 +172,6 @@ namespace SHADE void copyShapes (const SHCollider& rhsCollider); void copyShape (const SHCollisionShape* rhsShape); - - 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 0094153e..88ea8d79 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) + if (!TRANSFORM_COMPONENT || !TRANSFORM_COMPONENT->HasChanged()) 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 && TRANSFORM_COMPONENT->HasChanged()) + if (physicsObject.rigidBody) { SHMotionState& motionState = physicsObject.rigidBody->GetMotionState(); @@ -60,14 +60,11 @@ namespace SHADE if (physicsObject.collider) { - if (TRANSFORM_COMPONENT->HasChanged()) - { - physicsObject.collider->SetPosition(WORLD_POS); - physicsObject.collider->SetOrientation(WORLD_ROT); - physicsObject.collider->SetScale(WORLD_SCL); - } + physicsObject.collider->SetPosition(WORLD_POS); + physicsObject.collider->SetOrientation(WORLD_ROT); + physicsObject.collider->SetScale(WORLD_SCL); - physicsObject.collider->Update(); + physicsObject.collider->RecomputeShapes(); } } } diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp index dda437bc..958ac61a 100644 --- a/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Physics/System/SHPhysicsDebugDrawSystem.cpp @@ -122,17 +122,7 @@ namespace SHADE { case SHCollisionShape::Type::SPHERE: { - const SHSphereCollisionShape* SPHERE = dynamic_cast(SHAPE); - - // Compute transforms of sphere - const SHVec3 POSITION = SPHERE->GetCenter(); // Position offset is already computed here - const SHVec3 ROTATION = collider.GetOrientation().ToEuler() + SPHERE->GetRotationOffset(); - const SHVec3 SCALE { SPHERE->GetWorldRadius() }; - - // Compute TRS for the sphere - const SHMatrix TRS = SHMatrix::Transform(POSITION, ROTATION, SCALE); - - debugDrawSystem->DrawWireSphere(TRS, DRAW_COLOUR, true); + debugDrawSystem->DrawWireSphere(SHAPE->ComputeWorldTransform(), DRAW_COLOUR, true); break; }