Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Generals/Code/GameEngine/Include/GameClient/Drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,13 @@ class Drawable : public Thing,
Real m_totalYaw; ///< Current total yaw for this frame
Real m_totalZ;

PhysicsXformInfo() : m_totalPitch(0), m_totalRoll(0), m_totalYaw(0), m_totalZ(0) { }
Real m_prevTotalPitch;
Real m_prevTotalRoll;
Real m_prevTotalYaw;
Real m_prevTotalZ;

PhysicsXformInfo() : m_totalPitch(0), m_totalRoll(0), m_totalYaw(0), m_totalZ(0),
m_prevTotalPitch(0), m_prevTotalRoll(0), m_prevTotalYaw(0), m_prevTotalZ(0) { }
};

Bool calcPhysicsXform(PhysicsXformInfo& info);
Expand Down
27 changes: 21 additions & 6 deletions Generals/Code/GameEngine/Source/GameClient/Drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1349,17 +1349,32 @@ void Drawable::applyPhysicsXform(Matrix3D* mtx)
{
if (m_physicsXform != nullptr)
{
// TheSuperHackers @tweak Update the physics transform on every WW Sync only.
// All calculations are originally catered to a 30 fps logic step.
// TheSuperHackers @tweak bobtista 16/09/2026 Advance physics only on WW Sync frames using the 30 fps constants.
if (WW3D::Get_Sync_Frame_Time() != 0)
{
m_physicsXform->m_prevTotalPitch = m_physicsXform->m_totalPitch;
m_physicsXform->m_prevTotalRoll = m_physicsXform->m_totalRoll;
m_physicsXform->m_prevTotalYaw = m_physicsXform->m_totalYaw;
m_physicsXform->m_prevTotalZ = m_physicsXform->m_totalZ;

calcPhysicsXform(*m_physicsXform);
}

mtx->Translate(0.0f, 0.0f, m_physicsXform->m_totalZ);
mtx->Rotate_Y( m_physicsXform->m_totalPitch );
mtx->Rotate_X( -m_physicsXform->m_totalRoll );
mtx->Rotate_Z( m_physicsXform->m_totalYaw );
// TheSuperHackers @tweak bobtista 14/09/2026 Interpolate the rendered transform between
// logic frames, so the motion stays smooth when the render rate is above the logic rate.
// The fractional sync time accumulates in logic time, so a full logic step is always MSEC_PER_LOGICFRAME_REAL.
const Real fractionalMs = (Real)WW3D::Get_Fractional_Sync_Milliseconds();
const Real t = clamp(0.0f, fractionalMs / MSEC_PER_LOGICFRAME_REAL, 1.0f);

const Real interpPitch = m_physicsXform->m_prevTotalPitch + t * (m_physicsXform->m_totalPitch - m_physicsXform->m_prevTotalPitch);
const Real interpRoll = m_physicsXform->m_prevTotalRoll + t * (m_physicsXform->m_totalRoll - m_physicsXform->m_prevTotalRoll);
const Real interpYaw = m_physicsXform->m_prevTotalYaw + t * (m_physicsXform->m_totalYaw - m_physicsXform->m_prevTotalYaw);
const Real interpZ = m_physicsXform->m_prevTotalZ + t * (m_physicsXform->m_totalZ - m_physicsXform->m_prevTotalZ);

mtx->Translate(0.0f, 0.0f, interpZ);
mtx->Rotate_Y( interpPitch );
mtx->Rotate_X( -interpRoll );
mtx->Rotate_Z( interpYaw );
}
}

Expand Down
8 changes: 7 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,13 @@ class Drawable : public Thing,
Real m_totalYaw; ///< Current total yaw for this frame
Real m_totalZ;

PhysicsXformInfo() : m_totalPitch(0), m_totalRoll(0), m_totalYaw(0), m_totalZ(0) { }
Real m_prevTotalPitch;
Real m_prevTotalRoll;
Real m_prevTotalYaw;
Real m_prevTotalZ;

PhysicsXformInfo() : m_totalPitch(0), m_totalRoll(0), m_totalYaw(0), m_totalZ(0),
m_prevTotalPitch(0), m_prevTotalRoll(0), m_prevTotalYaw(0), m_prevTotalZ(0) { }
};

Bool calcPhysicsXform(PhysicsXformInfo& info);
Expand Down
27 changes: 21 additions & 6 deletions GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,17 +1351,32 @@ void Drawable::applyPhysicsXform(Matrix3D* mtx)
{
if (m_physicsXform != nullptr)
{
// TheSuperHackers @tweak Update the physics transform on every WW Sync only.
// All calculations are originally catered to a 30 fps logic step.
// TheSuperHackers @tweak bobtista 16/09/2026 Advance physics only on WW Sync frames using the 30 fps constants.
if (WW3D::Get_Sync_Frame_Time() != 0)
{
m_physicsXform->m_prevTotalPitch = m_physicsXform->m_totalPitch;
m_physicsXform->m_prevTotalRoll = m_physicsXform->m_totalRoll;
m_physicsXform->m_prevTotalYaw = m_physicsXform->m_totalYaw;
m_physicsXform->m_prevTotalZ = m_physicsXform->m_totalZ;

calcPhysicsXform(*m_physicsXform);
}

mtx->Translate(0.0f, 0.0f, m_physicsXform->m_totalZ);
mtx->Rotate_Y( m_physicsXform->m_totalPitch );
mtx->Rotate_X( -m_physicsXform->m_totalRoll );
mtx->Rotate_Z( m_physicsXform->m_totalYaw );
// TheSuperHackers @tweak bobtista 14/09/2026 Interpolate the rendered transform between
// logic frames, so the motion stays smooth when the render rate is above the logic rate.
// The fractional sync time accumulates in logic time, so a full logic step is always MSEC_PER_LOGICFRAME_REAL.
const Real fractionalMs = (Real)WW3D::Get_Fractional_Sync_Milliseconds();
const Real t = clamp(0.0f, fractionalMs / MSEC_PER_LOGICFRAME_REAL, 1.0f);

const Real interpPitch = m_physicsXform->m_prevTotalPitch + t * (m_physicsXform->m_totalPitch - m_physicsXform->m_prevTotalPitch);
const Real interpRoll = m_physicsXform->m_prevTotalRoll + t * (m_physicsXform->m_totalRoll - m_physicsXform->m_prevTotalRoll);
const Real interpYaw = m_physicsXform->m_prevTotalYaw + t * (m_physicsXform->m_totalYaw - m_physicsXform->m_prevTotalYaw);
const Real interpZ = m_physicsXform->m_prevTotalZ + t * (m_physicsXform->m_totalZ - m_physicsXform->m_prevTotalZ);

mtx->Translate(0.0f, 0.0f, interpZ);
mtx->Rotate_Y( interpPitch );
mtx->Rotate_X( -interpRoll );
mtx->Rotate_Z( interpYaw );
}
}

Expand Down
Loading