Moved collider interface into physics object. Added support for removing rigidbodies

This commit is contained in:
Diren D Bharwani 2022-10-11 01:26:12 +08:00
parent e68ef89c00
commit ff9b504bc5
9 changed files with 227 additions and 334 deletions

View File

@ -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);
} }

View File

@ -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());
} }

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}; };