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