Fix spectator hand jumping when rotating across 0 yaw boundary, take 2

The `yaw` value of non-client-players is constraint to [0; 360), so when that
boundary is crossed, the `renderYaw` starts interpolating to its goal the
incorrect way round (instead of crossing the 360 boundary as well).

To fix that, we now add the difference between the current `renderYaw` and the
desired one, modulo 360 (but with range (-180; 180]), to the current
`renderYaw`. That way we always take the short way round.
Additionally, because for rendering MC looks at the difference without modulo,
afterwards (and when a new `yaw` is set) we wrap the result around such that the
actual difference is always less than 180 and therefore rendered as intended.
This commit is contained in:
Jonas Herzig
2021-12-07 16:08:44 +01:00
parent 51aa07e01e
commit 1b18b5c952

View File

@@ -248,6 +248,7 @@ public class CameraEntity
this.lastRenderX = to.lastRenderX;
this.lastRenderY = to.lastRenderY + yOffset;
this.lastRenderZ = to.lastRenderZ;
this.wrapArmYaw();
updateBoundingBox();
}
@@ -703,7 +704,35 @@ public class CameraEntity
this.lastRenderYaw = this.renderYaw;
this.lastRenderPitch = this.renderPitch;
this.renderPitch = this.renderPitch + (this.pitch - this.renderPitch) * 0.5f;
this.renderYaw = this.renderYaw + (this.yaw - this.renderYaw) * 0.5f;
this.renderYaw = this.renderYaw + wrapDegrees(this.yaw - this.renderYaw) * 0.5f;
this.wrapArmYaw();
}
/**
* Minecraft renders the arm offset based on the difference between {@link #yaw} and {@link #renderYaw}. It does not
* wrap around the difference though, so if {@link #yaw} just wrapped around from 350 to 10 but {@link #renderYaw}
* is still at 355, then the difference will be inappropriately large. To fix this, we always wrap the
* {@link #renderYaw} such that it is no more than 180 degrees away from {@link #yaw}, even if that requires going
* outside the normal range.
*/
private void wrapArmYaw() {
this.renderYaw = wrapDegreesTo(this.renderYaw, this.yaw);
this.lastRenderYaw = wrapDegreesTo(this.lastRenderYaw, this.renderYaw);
}
private static float wrapDegreesTo(float value, float towardsValue) {
while (towardsValue - value < -180) {
value -= 360;
}
while (towardsValue - value >= 180) {
value += 360;
}
return value;
}
private static float wrapDegrees(float value) {
value %= 360;
return wrapDegreesTo(value, 0);
}
public boolean canSpectate(Entity e) {