Skip to content

Fix applyTorque world matrix mismatch#3561

Open
Doliman100 wants to merge 1 commit intowiremod:masterfrom
Doliman100:patch-1
Open

Fix applyTorque world matrix mismatch#3561
Doliman100 wants to merge 1 commit intowiremod:masterfrom
Doliman100:patch-1

Conversation

@Doliman100
Copy link
Copy Markdown

@Doliman100 Doliman100 commented Mar 26, 2026

Fix issue #3560.

PhysObj:ApplyTorqueCenter replaced with PhysObj:AddAngleVelocity since it accepts a local space input and doesn't convert it to world space internally. No more world matrix mismatch problem. Here is a full inlined code of both functions for comparison. As you can see, there is no difference but an ApplyTorqueCenter input is world space and an AddAngleVelocity input is local space. Another small difference is ApplyTorqueCenter multiplies a local space input by inv_rot_inertia and AddAngleVelocity doesn't, but this can be easily fixed in Lua.

void CPhysicsObject::ApplyTorqueCenter(const AngularImpulse &torqueImpulse) {
  if (!IsMoveable())
    return;
  IVP_U_Float_Point ivpTorque;
  ConvertAngularImpulseToIVP(torqueImpulse, ivpTorque);
  IVP_Core *core = m_pObject->get_core();

  // the difference; ivpAngularVelocity = ivpTorque * m_world_f_core * inv_rot_inertia
  const IVP_U_Matrix *m_world_f_core = core->get_m_world_f_core_PSI();
  IVP_U_Float_Point angular_impulse_cs;
  m_world_f_core->vimult3(&ivpTorque, &angular_impulse_cs);
  IVP_U_Float_Point ivpAngularVelocity;
  ivpAngularVelocity.set_pairwise_mult(&angular_impulse_cs, core->get_inv_rot_inertia());

  core->rot_speed_change.add(&ivpAngularVelocity);
  Wake();
  ClampVelocity();
}

void CPhysicsObject::AddVelocity(const AngularImpulse *angularVelocity) {
  if (!IsMoveable())
    return;
  IVP_Core *core = m_pObject->get_core();
  Wake();
  IVP_U_Float_Point ivpAngularVelocity;
  ConvertAngularImpulseToIVP(*angularVelocity, ivpAngularVelocity);

  core->rot_speed_change.add(&ivpAngularVelocity);
  ClampVelocity();
}

I tested it with the default tickrate and -tickrate 33, it works fine in both cases. The sample chip code is located at the initial issue message. After applying this fix, the sample works in an opposite way. Now the bad case provides right behavior and the good case provides wrong behavior.

`PhysObj:ApplyTorqueCenter` expects input multiplied by `q_world_f_core_last_psi`, but `PhysObj:LocalToWorldVector` multiplies input by a matrix interpolated between `q_world_f_core_last_psi` and `q_world_f_core_next_psi`.
`AddAngleVelocity` expects local space input which matches the Wiremod `applyTorque` input. We only need to convert torque to velocity dividing it by `rot_inertia`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants