Added a forced update to the physics system
This commit is contained in:
parent
c98693c6bc
commit
d36d70e3eb
|
@ -16,6 +16,7 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
|
@ -148,6 +149,10 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept
|
||||
{
|
||||
// This state is synced in the pre-update routine
|
||||
if (!rp3dBody->isActive())
|
||||
return;
|
||||
|
||||
if (component.dirtyFlags == 0)
|
||||
return;
|
||||
|
||||
|
@ -267,6 +272,10 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept
|
||||
{
|
||||
// This state is synced in the pre-update routine
|
||||
if (!rp3dBody->isActive())
|
||||
return;
|
||||
|
||||
int index = 0;
|
||||
for (auto& collisionShape : component.collisionShapes)
|
||||
{
|
||||
|
|
|
@ -167,6 +167,7 @@ namespace SHADE
|
|||
if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent)
|
||||
{
|
||||
destroyPhysicsObject(COMMAND.eid);
|
||||
wakeAllObjects();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -176,6 +177,10 @@ namespace SHADE
|
|||
physicsObject = createPhysicsObject(COMMAND.eid);
|
||||
|
||||
componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP);
|
||||
|
||||
// If any removal was done, wake all objects
|
||||
if (COMMAND.command == QueueCommand::Command::REMOVE)
|
||||
wakeAllObjects();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,5 +302,11 @@ namespace SHADE
|
|||
physicsObject->RemoveCollisionShape(command.shapeIndex);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::wakeAllObjects() noexcept
|
||||
{
|
||||
for (auto& physicsObject : physicsObjects | std::views::values)
|
||||
physicsObject.GetRigidBody()->setIsSleeping(false);
|
||||
}
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -165,6 +165,8 @@ namespace SHADE
|
|||
SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept;
|
||||
void destroyPhysicsObject (EntityID eid) noexcept;
|
||||
|
||||
void wakeAllObjects () noexcept;
|
||||
|
||||
static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
|
@ -172,6 +174,8 @@ namespace SHADE
|
|||
|
||||
static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -20,6 +20,7 @@
|
|||
#include "Editor/SHEditor.h"
|
||||
#include "Physics/SHPhysicsEvents.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Local Helper Functions */
|
||||
|
@ -34,16 +35,16 @@ namespace SHADE
|
|||
SHPhysicsSystem::SHPhysicsSystem()
|
||||
: worldUpdated { false }
|
||||
, interpolationFactor { 0.0 }
|
||||
, fixedDT { 60.0 }
|
||||
, fixedDT { DEFAULT_FIXED_STEP }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
double SHPhysicsSystem::GetFixedDT() const noexcept
|
||||
double SHPhysicsSystem::GetFixedUpdateRate() const noexcept
|
||||
{
|
||||
return fixedDT;
|
||||
return 1.0 / fixedDT;
|
||||
}
|
||||
|
||||
const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept
|
||||
|
@ -76,9 +77,9 @@ namespace SHADE
|
|||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::SetFixedDT(double fixedUpdateRate) noexcept
|
||||
void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept
|
||||
{
|
||||
fixedDT = fixedUpdateRate;
|
||||
fixedDT = 1.0 / fixedUpdateRate;
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept
|
||||
|
@ -126,6 +127,45 @@ namespace SHADE
|
|||
worldState.DestroyWorld(factory);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::ForceUpdate()
|
||||
{
|
||||
if (!worldState.world)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to force update without a Physics world!")
|
||||
return;
|
||||
}
|
||||
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (scriptingSystem == nullptr)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
// Force the physics world to update once
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteFixedUpdates();
|
||||
|
||||
worldState.world->update(static_cast<rp3d::decimal>(fixedDT));
|
||||
|
||||
// Sync transforms. No interpolation applied here
|
||||
for (auto& [entityID, physicsObject] : objectManager.physicsObjects)
|
||||
{
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
|
||||
postUpdateSyncTransforms
|
||||
(
|
||||
physicsObject
|
||||
, transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
, 1.0 // We use 1.0 here to avoid any interpolation
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
||||
{
|
||||
static const auto ADD_SHAPE = [&](EntityID entityID, int index)
|
||||
|
@ -339,5 +379,92 @@ namespace SHADE
|
|||
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)
|
||||
{
|
||||
rigidBodyComponent->position = WORLD_POS;
|
||||
rigidBodyComponent->orientation = WORLD_ROT;
|
||||
}
|
||||
|
||||
if (colliderComponent)
|
||||
{
|
||||
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.rp3dBody->getTransform();
|
||||
auto renderPos = CURRENT_TF.getPosition();
|
||||
auto renderRot = CURRENT_TF.getOrientation();
|
||||
|
||||
// Cache transforms
|
||||
physicsObject.prevTransform = CURRENT_TF;
|
||||
|
||||
// Sync with rigid bodies
|
||||
if (rigidBodyComponent)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
colliderComponent->position = CURRENT_TF.getPosition();
|
||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
// Set transform for rendering
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldPosition(renderPos);
|
||||
transformComponent->SetWorldOrientation(renderRot);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -55,7 +55,7 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] double GetFixedDT () const noexcept;
|
||||
[[nodiscard]] double GetFixedUpdateRate () const noexcept;
|
||||
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
||||
|
||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
||||
|
@ -67,8 +67,8 @@ namespace SHADE
|
|||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetFixedDT (double fixedUpdateRate) noexcept;
|
||||
void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept;
|
||||
void SetFixedUpdateRate (double fixedUpdateRate) noexcept;
|
||||
void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
|
@ -77,6 +77,8 @@ namespace SHADE
|
|||
void Init () override;
|
||||
void Exit () override;
|
||||
|
||||
void ForceUpdate ();
|
||||
|
||||
// Specific Handling for Collision Shapes as they are not under the Component System
|
||||
|
||||
void AddCollisionShape (EntityID eid, int shapeIndex);
|
||||
|
@ -121,14 +123,6 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
static void syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept;
|
||||
|
||||
static void preUpdateSyncTransform
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent& transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
) noexcept;
|
||||
};
|
||||
|
||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||
|
@ -161,20 +155,6 @@ namespace SHADE
|
|||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
void Execute(double dt) noexcept override;
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
static void postUpdateSyncTransforms
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent& transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
, double interpolationFactor
|
||||
) noexcept;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -208,5 +188,24 @@ namespace SHADE
|
|||
SHEventHandle onPlay (SHEventPtr onPlayEvent);
|
||||
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
|
|
@ -55,7 +55,7 @@ namespace SHADE
|
|||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (phySystem)
|
||||
{
|
||||
return phySystem->GetFixedDT();
|
||||
return phySystem->GetFixedUpdateRate();
|
||||
}
|
||||
|
||||
SHLOG_WARNING("[SHPhysicsSystemInterface] Failed to get fixed delta time. 0.0 returned instead.");
|
||||
|
|
|
@ -125,18 +125,18 @@ namespace SHADE
|
|||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
|
||||
const double FIXED_DT = physicsSystem->fixedDT;
|
||||
accumulatedTime += dt;
|
||||
|
||||
int count = 0;
|
||||
while (accumulatedTime > fixedTimeStep)
|
||||
while (accumulatedTime > FIXED_DT)
|
||||
{
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteFixedUpdates();
|
||||
|
||||
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(fixedTimeStep));
|
||||
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(FIXED_DT));
|
||||
|
||||
accumulatedTime -= fixedTimeStep;
|
||||
accumulatedTime -= FIXED_DT;
|
||||
++count;
|
||||
}
|
||||
|
||||
|
@ -165,17 +165,14 @@ namespace SHADE
|
|||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
|
||||
if (transformComponent)
|
||||
{
|
||||
postUpdateSyncTransforms
|
||||
(
|
||||
physicsObject
|
||||
, *transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
, physicsSystem->interpolationFactor
|
||||
);
|
||||
}
|
||||
postUpdateSyncTransforms
|
||||
(
|
||||
physicsObject
|
||||
, transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
, physicsSystem->interpolationFactor
|
||||
);
|
||||
}
|
||||
|
||||
// Collision & Trigger messages
|
||||
|
@ -203,7 +200,7 @@ namespace SHADE
|
|||
preUpdateSyncTransform
|
||||
(
|
||||
physicsObject
|
||||
, *transformComponent
|
||||
, transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
);
|
||||
|
@ -217,99 +214,4 @@ namespace SHADE
|
|||
if (colliderComponent)
|
||||
physicsObject.SyncColliders(*colliderComponent);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent& transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
) noexcept
|
||||
{
|
||||
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)
|
||||
{
|
||||
rigidBodyComponent->position = WORLD_POS;
|
||||
rigidBodyComponent->orientation = WORLD_ROT;
|
||||
}
|
||||
|
||||
if (colliderComponent)
|
||||
{
|
||||
colliderComponent->position = WORLD_POS;
|
||||
colliderComponent->orientation = WORLD_ROT;
|
||||
colliderComponent->scale = WORLD_SCL;
|
||||
|
||||
colliderComponent->RecomputeCollisionShapes();
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent& transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
, double interpolationFactor
|
||||
) noexcept
|
||||
{
|
||||
rp3d::Vector3 rp3dPos;
|
||||
rp3d::Quaternion rp3dRot;
|
||||
|
||||
const rp3d::Transform CURRENT_TF = physicsObject.rp3dBody->getTransform();
|
||||
|
||||
// Check if transform should be interpolated
|
||||
|
||||
if (rigidBodyComponent)
|
||||
{
|
||||
// Skip static bodies
|
||||
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||
return;
|
||||
|
||||
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));
|
||||
|
||||
rp3dPos = INTERPOLATED_TF.getPosition();
|
||||
rp3dRot = INTERPOLATED_TF.getOrientation();
|
||||
}
|
||||
else
|
||||
{
|
||||
rp3dPos = CURRENT_TF.getPosition();
|
||||
rp3dRot = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||
|
||||
if (colliderComponent)
|
||||
{
|
||||
// Sync with colliders
|
||||
|
||||
colliderComponent->position = CURRENT_TF.getPosition();
|
||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rp3dPos = CURRENT_TF.getPosition();
|
||||
rp3dRot = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
// Convert RP3D Transform to SHADE
|
||||
transformComponent.SetWorldPosition(rp3dPos);
|
||||
transformComponent.SetWorldOrientation(rp3dRot);
|
||||
|
||||
// Cache transforms
|
||||
physicsObject.prevTransform = CURRENT_TF;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
Loading…
Reference in New Issue