diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp
index 787a9f78..2e5f5c2c 100644
--- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp
+++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.cpp
@@ -274,6 +274,7 @@ namespace SHADE
// Invert the inertia
for (size_t i = 0; i < SHVec3::SIZE; ++i)
localInvInertia[i] = 1.0f / localInvInertia[i];
+
// Build raycast layer from colliders. If none exist....then this never stops simulating technically.
@@ -297,16 +298,17 @@ namespace SHADE
raycastInfo.continuous = false;
raycastInfo.layers = raycastLayers;
- bool terminate = true;
+ bool terminate = true;
+ int iterationCounter = simInfo.maxSteps;
do
{
raycastInfo.distance = linearVelocity.Length();
raycastInfo.ray.position = bodyPosition;
raycastInfo.ray.direction = SHVec3::Normalise(linearVelocity);
- terminate = !Raycast(raycastInfo).empty();
+ terminate = !Raycast(raycastInfo).empty() || iterationCounter == 0;
if (terminate)
- break;
+ return;
// Compute world space data
const SHMatrix R = SHMatrix::Rotate(bodyOrientation);
@@ -348,7 +350,7 @@ namespace SHADE
const SHQuaternion QV = SHQuaternion{ angularVelocity.x * simInfo.timeStep, angularVelocity.y * simInfo.timeStep, angularVelocity.z * simInfo.timeStep, 0.0f } * 0.5f;
bodyPosition += linearVelocity * simInfo.timeStep;
- bodyOrientation += bodyOrientation * QV;
+ bodyOrientation += bodyOrientation * QV * SHQuaternion::FromEuler(ANGULAR_LOCK);
bodyOrientation = SHQuaternion::Normalise(bodyOrientation);
// Clear forces after the first frame
@@ -362,6 +364,8 @@ namespace SHADE
positions.emplace_back(bodyPosition);
+ --iterationCounter;
+
} while (true);
}
diff --git a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h
index d95203b9..f466481d 100644
--- a/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h
+++ b/SHADE_Engine/src/Physics/System/SHPhysicsSystem.h
@@ -50,19 +50,39 @@ namespace SHADE
/**
* @brief
- * Used to simulate the motion of a rigid body until it hits something.
+ * Used to simulate the motion of a rigid body, ignoring collision detection and response.
+ * @param bodyEID
+ * The EntityID of the Rigid Body to simulate.
+ * @param force
+ * The force applied onto the Rigid Body.
+ * @param forceOffset
+ * The position to apply the force onto the body relative to it's local Center of Mass.
+ * @param torque
+ * The torque to apply onto the Rigid Body.
+ * @param continuousForce
+ * If the force should be applied every step throughout the simulation. Defaults to false.
+ * True : The force indicated is added to the body every step, therefore it has constant acceleration.
+ * False: The force is applied only in the first step, therefore it has constant speed.
+ * @param timeStep
+ * The timestep for each step of the simulation. Defaults to 0.016s (The default Fixed DT)
+ * @param maxSteps
+ * The number of steps to run the simulation for. Defaults to -1.
+ * < 0 : Runs until the object may hit something. Hit detection is done through raycasting.
+ * = 0 : Runs only the current step and checks if it may hit something.
+ * > 0 : Runs for the given number of steps or until it may hit something.
*/
struct SimulateBodyInfo
{
- EntityID bodyEID = MAX_EID;
+ EntityID bodyEID = MAX_EID;
- SHVec3 force = SHVec3::Zero;
- SHVec3 forceOffset = SHVec3::Zero;
- SHVec3 torque = SHVec3::Zero;
+ SHVec3 force = SHVec3::Zero;
+ SHVec3 forceOffset = SHVec3::Zero;
+ SHVec3 torque = SHVec3::Zero;
// Whether or not to clear the force after the first iteration
- bool continuousForce = false;
- float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT);
+ bool continuousForce = false;
+ float timeStep = static_cast(SHPhysicsConstants::DEFAULT_FIXED_DT);
+ int maxSteps = -1;
};