Fixed various Physics bugs #217

Merged
direnbharwani merged 14 commits from SP3-2-Physics into main 2022-11-17 17:13:02 +08:00
6 changed files with 203 additions and 144 deletions
Showing only changes of commit f172ccb744 - Show all commits

View File

@ -29,7 +29,6 @@ namespace SHADE
SHRigidBodyComponent::SHRigidBodyComponent() noexcept SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::DYNAMIC } : type { Type::DYNAMIC }
, interpolate { true }
, flags { 0 } , flags { 0 }
, dirtyFlags { std::numeric_limits<uint16_t>::max() } , dirtyFlags { std::numeric_limits<uint16_t>::max() }
, mass { 1.0f } , mass { 1.0f }
@ -40,6 +39,7 @@ namespace SHADE
// Initialise default flags // Initialise default flags
flags |= 1U << 0; // Gravity set to true flags |= 1U << 0; // Gravity set to true
flags |= 1U << 1; // Sleeping allowed flags |= 1U << 1; // Sleeping allowed
flags |= 1U << 8; // Interpolate by default
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -60,7 +60,16 @@ namespace SHADE
bool SHRigidBodyComponent::IsInterpolating() const noexcept bool SHRigidBodyComponent::IsInterpolating() const noexcept
{ {
return interpolate; static constexpr int FLAG_POS = 8;
return flags & (1U << FLAG_POS);
}
bool SHRigidBodyComponent::GetIsSleeping() const noexcept
{
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
return physicsObject->GetRigidBody()->isSleeping();
return false;
} }
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
@ -68,21 +77,6 @@ namespace SHADE
return type; return type;
} }
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
}
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{ {
static constexpr int FLAG_POS = 2; static constexpr int FLAG_POS = 2;
@ -119,6 +113,27 @@ namespace SHADE
return flags & (1U << FLAG_POS); return flags & (1U << FLAG_POS);
} }
bool SHRigidBodyComponent::GetAutoMass() const noexcept
{
static constexpr int FLAG_POS = 9;
return flags & (1U << FLAG_POS);
}
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
}
SHVec3 SHRigidBodyComponent::GetForce() const noexcept SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{ {
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject) if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
@ -295,9 +310,19 @@ namespace SHADE
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
{ {
interpolate = allowInterpolation; static constexpr int FLAG_POS = 8;
allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
} }
void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept
{
static constexpr int FLAG_POS = 9;
autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
dirtyFlags |= 1U << FLAG_POS;
}
void SHRigidBodyComponent::SetMass(float newMass) noexcept void SHRigidBodyComponent::SetMass(float newMass) noexcept
{ {
static constexpr int FLAG_POS = 9; static constexpr int FLAG_POS = 9;
@ -313,6 +338,9 @@ namespace SHADE
dirtyFlags |= 1U << FLAG_POS; dirtyFlags |= 1U << FLAG_POS;
mass = newMass; mass = newMass;
// Turn off automass
flags &= ~(1U << FLAG_POS);
} }
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
@ -467,6 +495,8 @@ RTTR_REGISTRATION
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag ) .property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled ) .property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate ) .property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep)
.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass )
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX ) .property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY ) .property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ ) .property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )

View File

@ -71,19 +71,23 @@ namespace SHADE
[[nodiscard]] bool IsAllowedToSleep () const noexcept; [[nodiscard]] bool IsAllowedToSleep () const noexcept;
[[nodiscard]] bool IsInterpolating () const noexcept; [[nodiscard]] bool IsInterpolating () const noexcept;
[[nodiscard]] bool GetIsSleeping () const noexcept;
[[nodiscard]] Type GetType () const noexcept; [[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] bool GetFreezePositionX () const noexcept; [[nodiscard]] bool GetFreezePositionX () const noexcept;
[[nodiscard]] bool GetFreezePositionY () const noexcept; [[nodiscard]] bool GetFreezePositionY () const noexcept;
[[nodiscard]] bool GetFreezePositionZ () const noexcept; [[nodiscard]] bool GetFreezePositionZ () const noexcept;
[[nodiscard]] bool GetFreezeRotationX () const noexcept; [[nodiscard]] bool GetFreezeRotationX () const noexcept;
[[nodiscard]] bool GetFreezeRotationY () const noexcept; [[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept; [[nodiscard]] bool GetFreezeRotationZ () const noexcept;
[[nodiscard]] bool GetAutoMass () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] SHVec3 GetForce () const noexcept; [[nodiscard]] SHVec3 GetForce () const noexcept;
[[nodiscard]] SHVec3 GetTorque () const noexcept; [[nodiscard]] SHVec3 GetTorque () const noexcept;
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept; [[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
@ -108,6 +112,7 @@ namespace SHADE
void SetFreezeRotationY (bool freezeRotationY) noexcept; void SetFreezeRotationY (bool freezeRotationY) noexcept;
void SetFreezeRotationZ (bool freezeRotationZ) noexcept; void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
void SetInterpolate (bool allowInterpolation) noexcept; void SetInterpolate (bool allowInterpolation) noexcept;
void SetAutoMass (bool autoMass) noexcept;
void SetMass (float newMass) noexcept; void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept; void SetDrag (float newDrag) noexcept;
@ -144,8 +149,7 @@ namespace SHADE
Type type; Type type;
bool interpolate; uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g
uint8_t flags; // aZ aY aX lZ lY lX slp g
uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g
float mass; float mass;

View File

@ -245,9 +245,17 @@ namespace SHADE
} }
case 9: // Mass case 9: // Mass
{ {
rp3dBody->setMass(component.mass); if (component.GetAutoMass())
rp3dBody->updateLocalCenterOfMassFromColliders(); {
rp3dBody->updateLocalInertiaTensorFromColliders(); rp3dBody->updateMassPropertiesFromColliders();
component.mass = rp3dBody->getMass();
}
else
{
rp3dBody->setMass(component.mass);
rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders();
}
break; break;
} }

View File

@ -154,14 +154,32 @@ namespace SHADE
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID); auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
postUpdateSyncTransforms const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
( const auto& RENDER_POS = CURRENT_TF.getPosition();
physicsObject const auto& RENDER_ROT = CURRENT_TF.getOrientation();
, transformComponent
, rigidBodyComponent // Cache transform
, colliderComponent physicsObject.prevTransform = CURRENT_TF;
, 1.0 // We use 1.0 here to avoid any interpolation
); // Sync with physics components
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID))
{
rigidBodyComponent->position = RENDER_POS;
rigidBodyComponent->orientation = RENDER_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID))
{
colliderComponent->position = RENDER_POS;
colliderComponent->orientation = RENDER_ROT;
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(RENDER_POS);
transformComponent->SetWorldOrientation(RENDER_ROT);
}
} }
} }
@ -337,93 +355,4 @@ namespace SHADE
return onStopEvent->handle; return onStopEvent->handle;
} }
void SHPhysicsSystem::preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept
{
if (!transformComponent)
return;
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT;
colliderComponent->scale = WORLD_SCL;
colliderComponent->RecomputeCollisionShapes();
}
}
void SHPhysicsSystem::postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept
{
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
auto renderPos = CURRENT_TF.getPosition();
auto renderRot = CURRENT_TF.getOrientation();
// Cache transforms
if (physicsObject.GetRigidBody()->isActive())
physicsObject.prevTransform = CURRENT_TF;
// Sync with rigid bodies
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
// Skip static bodies
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
return;
// Check if transform should be interpolated
if (rigidBodyComponent->IsInterpolating())
{
// Interpolate transforms between current and predicted next transform
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
renderPos = INTERPOLATED_TF.getPosition();
renderRot = INTERPOLATED_TF.getOrientation();
}
rigidBodyComponent->position = CURRENT_TF.getPosition();
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
}
// Sync with colliders
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = CURRENT_TF.getPosition();
colliderComponent->orientation = CURRENT_TF.getOrientation();
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(renderPos);
transformComponent->SetWorldOrientation(renderRot);
}
}
} // namespace SHADE } // namespace SHADE

View File

@ -113,6 +113,23 @@ namespace SHADE
void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept; void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept; static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept;
static void preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept;
static void postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept;
}; };
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
@ -178,24 +195,5 @@ namespace SHADE
SHEventHandle onPlay (SHEventPtr onPlayEvent); SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent); SHEventHandle onStop (SHEventPtr onStopEvent);
static void preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept;
static void postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept;
}; };
} // namespace SHADE } // namespace SHADE

View File

@ -262,4 +262,94 @@ namespace SHADE
if (colliderComponent) if (colliderComponent)
physicsObject.SyncColliders(*colliderComponent); physicsObject.SyncColliders(*colliderComponent);
} }
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept
{
if (!transformComponent)
return;
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
physicsObject.prevTransform = RP3D_TRANSFORM;
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT;
colliderComponent->scale = WORLD_SCL;
colliderComponent->RecomputeCollisionShapes();
}
}
void SHPhysicsSystem::PhysicsPreUpdate::postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept
{
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
auto renderPos = CURRENT_TF.getPosition();
auto renderRot = CURRENT_TF.getOrientation();
// Cache transforms
if (physicsObject.GetRigidBody()->isActive())
physicsObject.prevTransform = CURRENT_TF;
// Sync with rigid bodies
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
// Skip static bodies
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
return;
// Check if transform should be interpolated
if (rigidBodyComponent->IsInterpolating())
{
// Interpolate transforms between current and predicted next transform
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
renderPos = INTERPOLATED_TF.getPosition();
renderRot = INTERPOLATED_TF.getOrientation();
}
rigidBodyComponent->position = CURRENT_TF.getPosition();
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
}
// Sync with colliders
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = CURRENT_TF.getPosition();
colliderComponent->orientation = CURRENT_TF.getOrientation();
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(renderPos);
transformComponent->SetWorldOrientation(renderRot);
}
}
} // namespace SHADE } // namespace SHADE