Moved collider interface into physics object. Added support for removing rigidbodies
This commit is contained in:
parent
e68ef89c00
commit
ff9b504bc5
|
@ -104,8 +104,7 @@ namespace Sandbox
|
||||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
|
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
|
||||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||||
|
|
||||||
auto* box = collider.AddBoundingBox();
|
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
||||||
box->SetHalfExtents(transform.GetWorldScale() * 0.5f);
|
|
||||||
|
|
||||||
stressTestObjects.emplace_back(entity);
|
stressTestObjects.emplace_back(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHColliderComponent::SHColliderComponent() noexcept
|
SHColliderComponent::SHColliderComponent() noexcept
|
||||||
: system { nullptr }
|
: system { nullptr }
|
||||||
|
, colliders {}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -87,12 +88,17 @@ namespace SHADE
|
||||||
system->RemoveCollider(GetEID());
|
system->RemoveCollider(GetEID());
|
||||||
}
|
}
|
||||||
|
|
||||||
SHBoundingBox* SHColliderComponent::AddBoundingBox() noexcept
|
SHBoundingBox* SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset) noexcept
|
||||||
{
|
{
|
||||||
const auto TYPE = SHCollider::Type::BOX;
|
const auto TYPE = SHCollider::Type::BOX;
|
||||||
|
|
||||||
const auto BOX_PAIR = std::make_pair(SHCollider{TYPE}, true);
|
auto boxPair = std::make_pair(SHCollider{TYPE}, true);
|
||||||
auto& collider = colliders.emplace_back(BOX_PAIR).first;
|
auto& collider = colliders.emplace_back(boxPair).first;
|
||||||
|
|
||||||
|
const auto* tf = SHComponentManager::GetComponent<SHTransformComponent>(GetEID());
|
||||||
|
|
||||||
|
collider.SetPositionOffset(posOffset);
|
||||||
|
collider.SetAsBoundingBox(tf->GetWorldScale() * halfExtents);
|
||||||
|
|
||||||
if (!system)
|
if (!system)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +107,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify Physics System
|
// Notify Physics System
|
||||||
system->AddCollisionShape(GetEID(), collider.GetShape());
|
system->AddCollisionShape(GetEID(), &collider);
|
||||||
|
|
||||||
return reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
return reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace SHADE
|
||||||
void OnCreate () override;
|
void OnCreate () override;
|
||||||
void OnDestroy () override;
|
void OnDestroy () override;
|
||||||
|
|
||||||
SHBoundingBox* AddBoundingBox () noexcept;
|
SHBoundingBox* AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
||||||
|
|
||||||
void RemoveCollider (int index);
|
void RemoveCollider (int index);
|
||||||
|
|
||||||
|
|
|
@ -29,25 +29,23 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollider::SHCollider(const SHCollider& rhs) noexcept
|
SHCollider::SHCollider(const SHCollider& rhs) noexcept
|
||||||
: type { rhs.type}
|
: type { rhs.type}
|
||||||
, isTrigger { rhs.isTrigger }
|
, isTrigger { rhs.isTrigger }
|
||||||
, dirty { true }
|
, dirty { true }
|
||||||
, shape { nullptr }
|
, shape { nullptr }
|
||||||
|
, positionOffset { rhs.positionOffset }
|
||||||
{
|
{
|
||||||
CreateShape();
|
CreateShape();
|
||||||
|
|
||||||
// TODO(Diren): Copy transform data over
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollider::SHCollider(SHCollider&& rhs) noexcept
|
SHCollider::SHCollider(SHCollider&& rhs) noexcept
|
||||||
: type { rhs.type}
|
: type { rhs.type}
|
||||||
, isTrigger { rhs.isTrigger }
|
, isTrigger { rhs.isTrigger }
|
||||||
, dirty { true }
|
, dirty { true }
|
||||||
, shape { nullptr }
|
, shape { nullptr }
|
||||||
|
, positionOffset { rhs.positionOffset }
|
||||||
{
|
{
|
||||||
CreateShape();
|
CreateShape();
|
||||||
|
|
||||||
// TODO(Diren): Copy transform data over
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollider::~SHCollider() noexcept
|
SHCollider::~SHCollider() noexcept
|
||||||
|
@ -61,27 +59,26 @@ namespace SHADE
|
||||||
|
|
||||||
SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept
|
SHCollider& SHCollider::operator=(const SHCollider& rhs) noexcept
|
||||||
{
|
{
|
||||||
type = rhs.type;
|
if (this == &rhs)
|
||||||
isTrigger = rhs.isTrigger;
|
return *this;
|
||||||
dirty = true;
|
|
||||||
|
type = rhs.type;
|
||||||
|
isTrigger = rhs.isTrigger;
|
||||||
|
dirty = true;
|
||||||
|
positionOffset = rhs.positionOffset;
|
||||||
|
|
||||||
CreateShape();
|
CreateShape();
|
||||||
|
|
||||||
// TODO(Diren): Copy transform data over
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept
|
SHCollider& SHCollider::operator=(SHCollider&& rhs) noexcept
|
||||||
{
|
{
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
isTrigger = rhs.isTrigger;
|
isTrigger = rhs.isTrigger;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
positionOffset = rhs.positionOffset;
|
||||||
|
|
||||||
CreateShape();
|
CreateShape();
|
||||||
|
|
||||||
// TODO(Diren): Copy transform data over
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,11 +101,6 @@ namespace SHADE
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHShape* SHCollider::GetShape() const noexcept
|
|
||||||
{
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
float SHCollider::GetFriction() const noexcept
|
float SHCollider::GetFriction() const noexcept
|
||||||
{
|
{
|
||||||
// TODO(Diren): Fix after implementing materials
|
// TODO(Diren): Fix after implementing materials
|
||||||
|
@ -126,38 +118,41 @@ namespace SHADE
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHCollider::GetPosition() const noexcept
|
|
||||||
{
|
|
||||||
// TODO(Diren): Fix after linking transform data
|
|
||||||
return SHVec3::Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SHVec3& SHCollider::GetPositionOffset() const noexcept
|
const SHVec3& SHCollider::GetPositionOffset() const noexcept
|
||||||
{
|
{
|
||||||
return positionOffset;
|
return positionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion SHCollider::GetOrientation() const noexcept
|
SHShape* SHCollider::GetShape() noexcept
|
||||||
{
|
{
|
||||||
// TODO(Diren): Fix after linking transform data
|
dirty = true;
|
||||||
return SHQuaternion::Identity;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Function Definitions */
|
/* Setter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHCollider::SetType(Type newType) noexcept
|
void SHCollider::SetAsBoundingBox(const SHVec3& halfExtents)
|
||||||
{
|
{
|
||||||
if (type == newType)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
type = Type::BOX;
|
||||||
|
|
||||||
type = newType;
|
delete shape;
|
||||||
CreateShape();
|
shape = new SHBoundingBox{ positionOffset, halfExtents };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHCollider::SetAsBoundingSphere(float radius)
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
type = Type::SPHERE;
|
||||||
|
|
||||||
|
// TODO(Diren): Add Sphere
|
||||||
|
delete shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SHCollider::SetIsTrigger(bool trigger) noexcept
|
void SHCollider::SetIsTrigger(bool trigger) noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
@ -191,25 +186,22 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCollider::CreateShape()
|
void SHCollider::CreateShape()
|
||||||
{
|
{
|
||||||
// Remove current shape
|
|
||||||
delete shape;
|
delete shape;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Type::BOX: CreateBoundingBox(); break;
|
case Type::BOX:
|
||||||
case Type::SPHERE: CreateSphere(); break;
|
{
|
||||||
|
SetAsBoundingBox(SHVec3::One);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type::SPHERE:
|
||||||
|
{
|
||||||
|
SetAsBoundingSphere(1.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCollider::CreateBoundingBox()
|
|
||||||
{
|
|
||||||
shape = new SHBoundingBox{ SHVec3::Zero, SHVec3::One };
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHCollider::CreateSphere()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -32,8 +32,6 @@ namespace SHADE
|
||||||
BOX
|
BOX
|
||||||
, SPHERE
|
, SPHERE
|
||||||
, CAPSULE
|
, CAPSULE
|
||||||
, CONVEX_HULL
|
|
||||||
, CONVEX_MESH
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -62,28 +60,28 @@ namespace SHADE
|
||||||
[[nodiscard]] bool IsTrigger () const noexcept;
|
[[nodiscard]] bool IsTrigger () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] Type GetType () const noexcept;
|
[[nodiscard]] Type GetType () const noexcept;
|
||||||
[[nodiscard]] SHShape* GetShape () const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] float GetFriction () const noexcept;
|
[[nodiscard]] float GetFriction () const noexcept;
|
||||||
[[nodiscard]] float GetBounciness () const noexcept;
|
[[nodiscard]] float GetBounciness () const noexcept;
|
||||||
[[nodiscard]] float GetDensity () const noexcept;
|
[[nodiscard]] float GetDensity () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
|
||||||
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
||||||
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
|
||||||
|
[[nodiscard]] SHShape* GetShape () noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SetType (Type newType) noexcept;
|
void SetAsBoundingBox (const SHVec3& halfExtents);
|
||||||
|
void SetAsBoundingSphere (float radius);
|
||||||
|
|
||||||
void SetIsTrigger (bool isTrigger) noexcept;
|
void SetIsTrigger (bool isTrigger) noexcept;
|
||||||
void SetFriction (float friction) noexcept;
|
void SetFriction (float friction) noexcept;
|
||||||
void SetBounciness (float bounciness) noexcept;
|
void SetBounciness (float bounciness) noexcept;
|
||||||
void SetDensity (float density) noexcept;
|
void SetDensity (float density) noexcept;
|
||||||
|
|
||||||
void SetPositionOffset (const SHVec3& positionOffset) noexcept;
|
void SetPositionOffset (const SHVec3& positionOffset) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -101,8 +99,6 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void CreateShape ();
|
void CreateShape ();
|
||||||
void CreateBoundingBox ();
|
|
||||||
void CreateSphere ();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c)
|
void SHPhysicsObject::CreateRigidBody(const SHTransformComponent* tf, SHRigidBodyComponent* rb, SHColliderComponent* c)
|
||||||
{
|
{
|
||||||
// If collider already exists
|
// If collider already exists, recreate the collision body as a rigid body
|
||||||
if (hasColliders)
|
if (hasColliders)
|
||||||
world->destroyCollisionBody(rp3dBody);
|
world->destroyCollisionBody(rp3dBody);
|
||||||
|
|
||||||
|
@ -141,31 +141,91 @@ namespace SHADE
|
||||||
|
|
||||||
rb->position = tf->GetWorldPosition();
|
rb->position = tf->GetWorldPosition();
|
||||||
rb->orientation = tf->GetWorldRotation();
|
rb->orientation = tf->GetWorldRotation();
|
||||||
|
|
||||||
|
if (hasColliders)
|
||||||
|
{
|
||||||
|
c->position = tf->GetWorldPosition();
|
||||||
|
c->orientation = tf->GetWorldRotation();
|
||||||
|
// Get array of colliders and add them back into the rigidbody
|
||||||
|
for (auto& collider : c->colliders | std::views::keys)
|
||||||
|
AddCollider(&collider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c)
|
void SHPhysicsObject::CreateCollisionBody(const SHTransformComponent* tf, SHColliderComponent* c)
|
||||||
{
|
{
|
||||||
|
if (rp3dBody == nullptr)
|
||||||
|
rp3dBody = world->createCollisionBody(rp3d::Transform{ tf->GetWorldPosition(), tf->GetWorldRotation() });
|
||||||
|
|
||||||
|
hasColliders = true;
|
||||||
|
|
||||||
|
c->position = tf->GetWorldPosition();
|
||||||
|
c->orientation = tf->GetWorldRotation();
|
||||||
|
|
||||||
|
for (auto& collider : c->colliders | std::views::keys)
|
||||||
|
AddCollider(&collider);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHPhysicsObject::AddCollider(SHCollider* collider)
|
int SHPhysicsObject::AddCollider(SHCollider* collider)
|
||||||
{
|
{
|
||||||
return 0;
|
switch (collider->GetType())
|
||||||
|
{
|
||||||
|
case SHCollider::Type::BOX:
|
||||||
|
{
|
||||||
|
const auto* box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
||||||
|
rp3d::BoxShape* newBox = factory->createBoxShape(box->GetHalfExtents());
|
||||||
|
|
||||||
|
// TODO(Diren): Handle offsets
|
||||||
|
rp3dBody->addCollider(newBox, rp3d::Transform{ collider->GetPositionOffset(), SHQuaternion::Identity });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHCollider::Type::SPHERE:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// TODO(Diren): Add more collider shapes
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(rp3dBody->getNbColliders()) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::DestroyRigidBody() noexcept
|
void SHPhysicsObject::DestroyRigidBody(SHColliderComponent* c) noexcept
|
||||||
{
|
{
|
||||||
|
world->destroyRigidBody(reinterpret_cast<rp3d::RigidBody*>(rp3dBody));
|
||||||
|
|
||||||
|
if (hasColliders)
|
||||||
|
{
|
||||||
|
// Preserve colliders as a collision body
|
||||||
|
rp3dBody = world->createCollisionBody(rp3d::Transform{ c->position, c->orientation });
|
||||||
|
for (auto& collider : c->colliders | std::views::keys)
|
||||||
|
AddCollider(&collider);
|
||||||
|
}
|
||||||
|
|
||||||
|
isRigidBody = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::DestroyCollisionBody() noexcept
|
void SHPhysicsObject::DestroyCollisionBody() noexcept
|
||||||
{
|
{
|
||||||
|
// Remove all colliders
|
||||||
|
for (uint32_t i = 0; i < rp3dBody->getNbColliders(); ++i)
|
||||||
|
{
|
||||||
|
auto* collider = rp3dBody->getCollider(i);
|
||||||
|
rp3dBody->removeCollider(collider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::RemoveCollider(int index) noexcept
|
void SHPhysicsObject::RemoveCollider(int index)
|
||||||
{
|
{
|
||||||
|
const int NUM_COLLIDERS = static_cast<int>(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept
|
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent* rb) const noexcept
|
||||||
|
@ -260,7 +320,37 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
|
void SHPhysicsObject::SyncColliders(SHColliderComponent* c) const noexcept
|
||||||
{
|
{
|
||||||
|
int index = 0;
|
||||||
|
for (auto& [collider, dirty] : c->colliders)
|
||||||
|
{
|
||||||
|
if (!dirty)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update offsets
|
||||||
|
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||||
|
rp3dCollider->setLocalToBodyTransform(rp3d::Transform(collider.GetPositionOffset(), SHQuaternion::Identity));
|
||||||
|
|
||||||
|
switch (collider.GetType())
|
||||||
|
{
|
||||||
|
case SHCollider::Type::BOX:
|
||||||
|
{
|
||||||
|
const auto* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
||||||
|
|
||||||
|
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
||||||
|
rp3dBoxShape->setHalfExtents(box->GetHalfExtents());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHCollider::Type::SPHERE:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirty = false;
|
||||||
|
++index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -73,8 +73,8 @@ namespace SHADE
|
||||||
void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c);
|
void CreateCollisionBody (const SHTransformComponent* tf, SHColliderComponent* c);
|
||||||
int AddCollider (SHCollider* collider);
|
int AddCollider (SHCollider* collider);
|
||||||
|
|
||||||
void DestroyRigidBody () noexcept;
|
void DestroyRigidBody (SHColliderComponent* c) noexcept;
|
||||||
void RemoveCollider (int index) noexcept;
|
void RemoveCollider (int index);
|
||||||
void DestroyCollisionBody () noexcept;
|
void DestroyCollisionBody () noexcept;
|
||||||
|
|
||||||
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
|
void SyncRigidBody (SHRigidBodyComponent* rb) const noexcept;
|
||||||
|
|
|
@ -202,46 +202,14 @@ namespace SHADE
|
||||||
SHLOG_INFO("Adding a Rigidbody to the Physics World.")
|
SHLOG_INFO("Adding a Rigidbody to the Physics World.")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if entity is already a physics object
|
auto* physicsObject = CreatePhysicsObject(entityID);
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
|
||||||
|
|
||||||
if (!physicsObject)
|
physicsObject->CreateRigidBody
|
||||||
physicsObject = CreatePhysicsObject(entityID);
|
(
|
||||||
|
EnsureTransform(entityID),
|
||||||
// Get components transform
|
SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID),
|
||||||
auto* transformComponent = EnsureTransform(entityID);
|
SHComponentManager::GetComponent_s<SHColliderComponent>(entityID)
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
);
|
||||||
|
|
||||||
physicsObject->CreateRigidBody(transformComponent, rigidBodyComponent, nullptr);
|
|
||||||
|
|
||||||
// Recreate colliders
|
|
||||||
const rp3d::Transform RP3D_TF { transformComponent->GetWorldPosition(), transformComponent->GetWorldRotation() };
|
|
||||||
if (physicsObject->hasColliders)
|
|
||||||
{
|
|
||||||
const auto& COLLIDERS = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetColliders();
|
|
||||||
for (const auto& collider : COLLIDERS | std::views::keys)
|
|
||||||
{
|
|
||||||
switch (collider.GetType())
|
|
||||||
{
|
|
||||||
case SHCollider::Type::BOX:
|
|
||||||
{
|
|
||||||
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
|
||||||
rp3d::BoxShape* newBox = factory.createBoxShape(box->GetHalfExtents());
|
|
||||||
|
|
||||||
// TODO(Diren): Handle offsets
|
|
||||||
physicsObject->rp3dBody->addCollider(newBox, RP3D_TF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollider::Type::SPHERE:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO(Diren): Add more collider shapes
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept
|
void SHPhysicsSystem::AddCollider(EntityID entityID) noexcept
|
||||||
|
@ -250,43 +218,13 @@ namespace SHADE
|
||||||
SHLOG_INFO("Adding a Collider to the Physics World.")
|
SHLOG_INFO("Adding a Collider to the Physics World.")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if entity is already a physics object
|
auto* physicsObject = CreatePhysicsObject(entityID);
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
|
||||||
if (!physicsObject)
|
|
||||||
physicsObject = CreatePhysicsObject(entityID);
|
|
||||||
|
|
||||||
// Get entity transform
|
physicsObject->CreateCollisionBody
|
||||||
auto const* TF = EnsureTransform(entityID);
|
(
|
||||||
const rp3d::Transform RP3D_TF { TF->GetWorldPosition(), TF->GetWorldRotation() };
|
EnsureTransform(entityID),
|
||||||
|
SHComponentManager::GetComponent<SHColliderComponent>(entityID)
|
||||||
// No rb
|
);
|
||||||
if (!physicsObject->isRigidBody)
|
|
||||||
physicsObject->rp3dBody = world->createCollisionBody(RP3D_TF);
|
|
||||||
|
|
||||||
const auto& COLLIDERS = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetColliders();
|
|
||||||
for (const auto& collider : COLLIDERS | std::views::keys)
|
|
||||||
{
|
|
||||||
switch (collider.GetType())
|
|
||||||
{
|
|
||||||
case SHCollider::Type::BOX:
|
|
||||||
{
|
|
||||||
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
|
||||||
rp3d::BoxShape* newBox = factory.createBoxShape(box->GetHalfExtents());
|
|
||||||
|
|
||||||
// TODO(Diren): Handle offsets
|
|
||||||
physicsObject->rp3dBody->addCollider(newBox, RP3D_TF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollider::Type::SPHERE:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO(Diren): Add more collider shapes
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
physicsObject->hasColliders = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept
|
void SHPhysicsSystem::RemoveRigidBody(EntityID entityID) noexcept
|
||||||
|
@ -295,6 +233,13 @@ namespace SHADE
|
||||||
SHLOG_INFO("Removing a Rigidbody from the Physics World.")
|
SHLOG_INFO("Removing a Rigidbody from the Physics World.")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto* physicsObject = GetPhysicsObject(entityID);
|
||||||
|
SHASSERT(physicsObject != nullptr, "Physics object has been lost from the world!")
|
||||||
|
|
||||||
|
physicsObject->DestroyRigidBody(SHComponentManager::GetComponent_s<SHColliderComponent>(entityID));
|
||||||
|
|
||||||
|
if (physicsObject->rp3dBody == nullptr)
|
||||||
|
DestroyPhysicsObject(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept
|
void SHPhysicsSystem::RemoveCollider(EntityID entityID) noexcept
|
||||||
|
@ -344,30 +289,10 @@ namespace SHADE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHShape* shape)
|
void SHPhysicsSystem::AddCollisionShape(EntityID entityID, SHCollider* collider)
|
||||||
{
|
{
|
||||||
auto* physicsObject = GetPhysicsObject(entityID);
|
auto* physicsObject = GetPhysicsObject(entityID);
|
||||||
|
physicsObject->AddCollider(collider);
|
||||||
switch (shape->GetType())
|
|
||||||
{
|
|
||||||
case SHShape::Type::BOX:
|
|
||||||
{
|
|
||||||
auto* box = reinterpret_cast<SHBoundingBox*>(shape);
|
|
||||||
rp3d::BoxShape* newBox = factory.createBoxShape(box->GetHalfExtents());
|
|
||||||
|
|
||||||
// TODO(Diren): Handle offsets
|
|
||||||
|
|
||||||
rp3d::Transform tf = rp3d::Transform::identity();
|
|
||||||
physicsObject->rp3dBody->addCollider(newBox, tf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHShape::Type::SPHERE:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// TODO(Diren): Add more collider shapes
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
void SHPhysicsSystem::RemoveCollisionShape(EntityID entityID, int index)
|
||||||
|
@ -424,6 +349,7 @@ namespace SHADE
|
||||||
if (system->worldUpdated)
|
if (system->worldUpdated)
|
||||||
{
|
{
|
||||||
system->SyncTransforms();
|
system->SyncTransforms();
|
||||||
|
|
||||||
// TODO(Diren): Handle trigger messages for scripting
|
// TODO(Diren): Handle trigger messages for scripting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,8 +360,14 @@ namespace SHADE
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept
|
SHPhysicsObject* SHPhysicsSystem::CreatePhysicsObject(EntityID entityID) noexcept
|
||||||
{
|
{
|
||||||
auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second;
|
const auto it = map.find(entityID);
|
||||||
return newPhysicsObject;
|
if (it == map.end())
|
||||||
|
{
|
||||||
|
auto* newPhysicsObject = &map.emplace(entityID, SHPhysicsObject{entityID, &factory, world}).first->second;
|
||||||
|
return newPhysicsObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept
|
SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID entityID) noexcept
|
||||||
|
@ -450,6 +382,11 @@ namespace SHADE
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHPhysicsSystem::DestroyPhysicsObject(EntityID entityID) noexcept
|
||||||
|
{
|
||||||
|
map.erase(entityID);
|
||||||
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept
|
void SHPhysicsSystem::SyncActiveStates(SHPhysicsObject* physicsObject, bool componentActive) noexcept
|
||||||
{
|
{
|
||||||
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive();
|
const bool RP3D_ACTIVE = physicsObject->rp3dBody->isActive();
|
||||||
|
@ -500,17 +437,14 @@ namespace SHADE
|
||||||
if (!COMPONENT_ACTIVE)
|
if (!COMPONENT_ACTIVE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SyncCollider(physicsObject, &comp);
|
physicsObject->SyncColliders(&comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncTransforms() noexcept
|
void SHPhysicsSystem::SyncTransforms() noexcept
|
||||||
{
|
{
|
||||||
for (auto& pair : map)
|
for (auto& [entityID, physicsObject] : map)
|
||||||
{
|
{
|
||||||
const EntityID ENTITY_ID = pair.first;
|
|
||||||
SHPhysicsObject& physicsObject = pair.second;
|
|
||||||
|
|
||||||
rp3d::Vector3 rp3dPos;
|
rp3d::Vector3 rp3dPos;
|
||||||
rp3d::Quaternion rp3dRot;
|
rp3d::Quaternion rp3dRot;
|
||||||
|
|
||||||
|
@ -520,7 +454,7 @@ namespace SHADE
|
||||||
|
|
||||||
if (physicsObject.isRigidBody)
|
if (physicsObject.isRigidBody)
|
||||||
{
|
{
|
||||||
auto const* rbComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(ENTITY_ID);
|
auto* rbComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
||||||
if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
if (rbComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -538,6 +472,16 @@ namespace SHADE
|
||||||
rp3dPos = CURRENT_TF.getPosition();
|
rp3dPos = CURRENT_TF.getPosition();
|
||||||
rp3dRot = CURRENT_TF.getOrientation();
|
rp3dRot = CURRENT_TF.getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rbComponent->position = CURRENT_TF.getPosition();
|
||||||
|
rbComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
|
|
||||||
|
if (physicsObject.hasColliders)
|
||||||
|
{
|
||||||
|
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||||
|
colliderComponent->position = CURRENT_TF.getPosition();
|
||||||
|
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -546,145 +490,16 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert RP3D Transform to SHADE
|
// Convert RP3D Transform to SHADE
|
||||||
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(ENTITY_ID);
|
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||||
tfComponent->SetWorldPosition(rp3dPos);
|
tfComponent->SetWorldPosition(rp3dPos);
|
||||||
tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler());
|
tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler());
|
||||||
|
|
||||||
|
|
||||||
// Cache transforms
|
// Cache transforms
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
physicsObject.prevTransform = CURRENT_TF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncRigidBody(SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept
|
|
||||||
{
|
|
||||||
auto* rigidBody = reinterpret_cast<rp3d::RigidBody*>(physicsObject->rp3dBody);
|
|
||||||
|
|
||||||
const uint16_t RB_FLAGS = comp->dirtyFlags;
|
|
||||||
const size_t NUM_FLAGS = sizeof(RB_FLAGS) * 8U;
|
|
||||||
for (size_t i = 0; i < NUM_FLAGS; ++i)
|
|
||||||
{
|
|
||||||
// Check if current dirty flag has been set to true
|
|
||||||
if (RB_FLAGS & 1U << i)
|
|
||||||
{
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0: // Gravity
|
|
||||||
{
|
|
||||||
rigidBody->enableGravity(comp->IsGravityEnabled());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // Sleeping
|
|
||||||
{
|
|
||||||
rigidBody->setIsAllowedToSleep(comp->IsAllowedToSleep());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: // Linear Constraints
|
|
||||||
{
|
|
||||||
SetRP3DLinearConstraints(rigidBody, comp->flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // Angular Constraints
|
|
||||||
{
|
|
||||||
SetRP3DAngularConstraints(rigidBody, comp->flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // Type
|
|
||||||
{
|
|
||||||
rigidBody->setType(static_cast<rp3d::BodyType>(comp->GetType()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5: // Mass
|
|
||||||
{
|
|
||||||
rigidBody->setMass(comp->GetMass());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 6: // Drag
|
|
||||||
{
|
|
||||||
rigidBody->setLinearDamping(comp->GetDrag());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 7: // Angular Drag
|
|
||||||
{
|
|
||||||
rigidBody->setAngularDamping(comp->GetAngularDrag());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8: // Linear Velocity
|
|
||||||
{
|
|
||||||
rigidBody->setLinearVelocity(comp->GetLinearVelocity());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 9: // Angular Velocity
|
|
||||||
{
|
|
||||||
rigidBody->setAngularVelocity(comp->GetAngularVelocity());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetRP3DLinearConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept
|
|
||||||
{
|
|
||||||
const rp3d::Vector3 CONSTRAINTS
|
|
||||||
{
|
|
||||||
rbFlags & 1U << 2 ? 0.0f : 1.0f,
|
|
||||||
rbFlags & 1U << 3 ? 0.0f : 1.0f,
|
|
||||||
rbFlags & 1U << 4 ? 0.0f : 1.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
rp3dRigidBody->setLinearLockAxisFactor(CONSTRAINTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SetRP3DAngularConstraints(rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept
|
|
||||||
{
|
|
||||||
const rp3d::Vector3 CONSTRAINTS
|
|
||||||
{
|
|
||||||
rbFlags & 1U << 5 ? 0.0f : 1.0f,
|
|
||||||
rbFlags & 1U << 6 ? 0.0f : 1.0f,
|
|
||||||
rbFlags & 1U << 7 ? 0.0f : 1.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
rp3dRigidBody->setAngularLockAxisFactor(CONSTRAINTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHPhysicsSystem::SyncCollider(SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept
|
|
||||||
{
|
|
||||||
int index = 0;
|
|
||||||
for (auto& [collider, dirty] : comp->colliders)
|
|
||||||
{
|
|
||||||
if (!dirty)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (collider.GetType())
|
|
||||||
{
|
|
||||||
case SHCollider::Type::BOX:
|
|
||||||
{
|
|
||||||
SHBoundingBox* box = reinterpret_cast<SHBoundingBox*>(collider.GetShape());
|
|
||||||
|
|
||||||
auto* rp3dBoxShape = reinterpret_cast<rp3d::BoxShape*>(physicsObject->rp3dBody->getCollider(index)->getCollisionShape());
|
|
||||||
rp3dBoxShape->setHalfExtents(box->GetHalfExtents());
|
|
||||||
|
|
||||||
if (rp3dBoxShape)
|
|
||||||
{
|
|
||||||
SHLOG_INFO("Updating box things")
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SHCollider::Type::SPHERE:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirty = false;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID)
|
SHTransformComponent* SHPhysicsSystem::EnsureTransform(EntityID entityID)
|
||||||
{
|
{
|
||||||
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||||
|
|
|
@ -82,8 +82,8 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void Init () override;
|
void Init () override;
|
||||||
void Exit () override;
|
void Exit () override;
|
||||||
|
|
||||||
void AddRigidBody (EntityID entityID) noexcept;
|
void AddRigidBody (EntityID entityID) noexcept;
|
||||||
void AddCollider (EntityID entityID) noexcept;
|
void AddCollider (EntityID entityID) noexcept;
|
||||||
|
@ -101,7 +101,7 @@ namespace SHADE
|
||||||
void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept;
|
void AddTorque (EntityID entityID, const SHVec3& torque) const noexcept;
|
||||||
void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept;
|
void AddRelativeTorque (EntityID entityID, const SHVec3& relativeTorque) const noexcept;
|
||||||
|
|
||||||
void AddCollisionShape (EntityID entityID, SHShape* shape);
|
void AddCollisionShape (EntityID entityID, SHCollider* collider);
|
||||||
void RemoveCollisionShape (EntityID entityID, int index);
|
void RemoveCollisionShape (EntityID entityID, int index);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -188,6 +188,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept;
|
SHPhysicsObject* CreatePhysicsObject (EntityID entityID) noexcept;
|
||||||
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
||||||
|
void DestroyPhysicsObject (EntityID entityID) noexcept;
|
||||||
|
|
||||||
void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept;
|
void SyncActiveStates (SHPhysicsObject* physicsObject, bool componentActive) noexcept;
|
||||||
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
|
void SyncRigidBodyComponents (std::vector<SHRigidBodyComponent>& denseArray) noexcept;
|
||||||
|
@ -195,12 +196,6 @@ namespace SHADE
|
||||||
void SyncTransforms () noexcept;
|
void SyncTransforms () noexcept;
|
||||||
// TODO(Diren): Trigger handling
|
// TODO(Diren): Trigger handling
|
||||||
|
|
||||||
static void SyncRigidBody (SHPhysicsObject const* physicsObject, const SHRigidBodyComponent* comp) noexcept;
|
|
||||||
static void SetRP3DLinearConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept;
|
|
||||||
static void SetRP3DAngularConstraints (rp3d::RigidBody const* rp3dRigidBody, uint8_t rbFlags) noexcept;
|
|
||||||
|
|
||||||
static void SyncCollider (SHPhysicsObject const* physicsObject, SHColliderComponent* comp) noexcept;
|
|
||||||
|
|
||||||
// TODO(Diren): Remove when responsibility shifted to editor
|
// TODO(Diren): Remove when responsibility shifted to editor
|
||||||
SHTransformComponent* EnsureTransform (EntityID entityID);
|
SHTransformComponent* EnsureTransform (EntityID entityID);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue