FreshRSS

Normální zobrazení

Jsou dostupné nové články, klikněte pro obnovení stránky.
PředevčíremHlavní kanál
  • ✇Recent Questions - Game Development Stack Exchange
  • Fixed timestep graphics jitterMike F
    I'm trying to implement the https://gafferongames.com/post/fix_your_timestep article but I have jitter on the position interpolation. video of the problem I have the following PhysX manager class update method : const float fixedTimeStep = 1.0f / 60.0f; // 60Hz float deltaTime = TimeManager::GetInstance()->DeltaTimeF(); if (deltaTime > 0.25f) deltaTime = 0.25f; accumulator += deltaTime; static std::unordered_map<PxRigidDynamic*, PhysXState> statesBefore{}; static
     

Fixed timestep graphics jitter

I'm trying to implement the https://gafferongames.com/post/fix_your_timestep article but I have jitter on the position interpolation.

video of the problem

I have the following PhysX manager class update method :

 const float fixedTimeStep = 1.0f / 60.0f; // 60Hz
 float deltaTime = TimeManager::GetInstance()->DeltaTimeF();        
 if (deltaTime > 0.25f)
     deltaTime = 0.25f;
 accumulator += deltaTime;

 static std::unordered_map<PxRigidDynamic*, PhysXState> statesBefore{};
 static std::unordered_map<PxRigidDynamic*, PhysXState> statesAfter{};

 if (statesBefore.empty()) {
     RetrieveCurrentState(statesBefore);
     RetrieveCurrentState(statesAfter);
 }

 while (accumulator >= fixedTimeStep)
 {
     statesBefore = statesAfter;

     mScene->simulate(fixedTimeStep, nullptr, GSimulateScratchMemory, GSimulateScratchMemorySize);
     accumulator = std::max(accumulator - fixedTimeStep, 0.f);
     mScene->fetchResults(true);

     RetrieveCurrentState(statesAfter);
 }

 // Calculate the interpolation factor for rendering
 float alpha = accumulator / fixedTimeStep;

 for (const auto& [body, stateBefore] : statesBefore) {
     if (statesAfter.find(body) != statesAfter.end()) {
         const auto& stateAfter = statesAfter.at(body);
         PhysXState interpolatedState{};
         InterpolateStates(stateBefore, stateAfter, alpha, interpolatedState);

         // Update the interpolated state in the body userptr moveable body
         auto userPtr = static_cast<CollisionParam*>(body->userData);
         if (userPtr && userPtr->Body) {
             userPtr->Body->SetInterpolatedState(interpolatedState);
         }
     }
 } 

This is how I retrieve the current state:

void RetrieveCurrentState(std::unordered_map<PxRigidDynamic*, PhysXState>& states) {
    states.clear();
    for (auto rigidBody : mRigidBodies) {
        PhysXState state;

        physx::PxTransform transform = rigidBody->getGlobalPose();
        state.Position = glm::vec3(transform.p.x, transform.p.y, transform.p.z);
        state.Orientation = glm::quat(transform.q.w, transform.q.x, transform.q.y, transform.q.z);

        physx::PxVec3 linearVelocity = rigidBody->getLinearVelocity();
        state.Velocity = glm::vec3(linearVelocity.x, linearVelocity.y, linearVelocity.z);

        physx::PxVec3 angularVelocity = rigidBody->getAngularVelocity();
        state.AngularVelocity = glm::vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z);

        states[rigidBody] = state;
    }
}

And here is how I interpolate:

void InterpolateStates(const PhysXState& previous, const PhysXState& current, float alpha, PhysXState& interpolated)
{
    interpolated.Position = glm::mix(previous.Position, current.Position, alpha);
    interpolated.Orientation = glm::slerp(previous.Orientation, current.Orientation, alpha);
    interpolated.Velocity = glm::mix(previous.Velocity, current.Velocity, alpha);
    interpolated.AngularVelocity = glm::mix(previous.AngularVelocity, current.AngularVelocity, alpha);
}

Finally here is how I retrieve the interpolated position (currently using only the position as a test phase) to feed it into the graphics module:

prop.Transform.setLocalPosition(prop.MoveableBody->GetInterpolatedPosition());

What could be wrong and the movement is shaky/jittery ? Let me know if you need to see more code.

❌
❌