Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-124195

Left hand swing animation does not perfectly mirror right hand

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Resolution: Unresolved
    • Affects Version/s: Minecraft 1.12.2, Minecraft 18w02a, Minecraft 1.13.1, Minecraft 18w50a
    • Fix Version/s: None
    • Confirmation Status:
      Confirmed
    • Category:
      (Unassigned)

      Description

      The bug

      When swinging with your left hand, the animation is not perfectly mirrored to swinging with your right hand. There is a very slight mismatch.

      How to reproduce

      1. /tp @s ~ ~ ~ 0 0
      2. /effect give @p mining_fatigue 10000 15 true (to slow down the swinging animation)
      3. Go in third person to look at yourself from the front
      4. Hit with your right hand, notice that the corner of your hand goes past the center of your body
      5. Also notice that your left hand will shake a little
      6. Hit with your left hand by switching your main hand, notice that the corner of your hand does not go past the center of your body
      7. Also notice that your right hand does NOT shake at all

      Code analysis

      The following is based on a decompiled version of Minecraft 1.12 using MCP 9.40
      The reason is likely due to an oversight in net.minecraft.client.model.ModelBiped.setRotationAngles(). In the section calculating animations based off swingProgress, the line:

      this.bipedLeftArm.rotateAngleX += this.bipedBody.rotateAngleY;

      appears to add an offset to the left arm when the right arm is swinging. This line should instead subtract the value from the X angle and switch to modifying the right hand when the main hand is the left hand.

      Additionally, in the same section, the line:

      modelrenderer.rotateAngleZ += MathHelper.sin(this.swingProgress * (float)Math.PI) * -0.4F;

      does not apply the angle correctly when on the left hand as the Z angle should be mirrored. Instead it should subtract the value from the Z angle.

      Potential fix

              if (this.swingProgress > 0.0F)
              {
                  EnumHandSide enumhandside = this.getMainHand(entityIn);
                  ModelRenderer modelrenderer = this.getArmForSide(enumhandside);
                  float f1 = this.swingProgress;
                  this.bipedBody.rotateAngleY = MathHelper.sin(MathHelper.sqrt(f1) * ((float)Math.PI * 2F)) * 0.2F;
      
                  if (enumhandside == EnumHandSide.LEFT)
                  {
                      this.bipedBody.rotateAngleY *= -1.0F;
                  }
      
                  this.bipedRightArm.rotationPointZ = MathHelper.sin(this.bipedBody.rotateAngleY) * 5.0F;
                  this.bipedRightArm.rotationPointX = -MathHelper.cos(this.bipedBody.rotateAngleY) * 5.0F;
                  this.bipedLeftArm.rotationPointZ = -MathHelper.sin(this.bipedBody.rotateAngleY) * 5.0F;
                  this.bipedLeftArm.rotationPointX = MathHelper.cos(this.bipedBody.rotateAngleY) * 5.0F;
                  this.bipedRightArm.rotateAngleY += this.bipedBody.rotateAngleY;
                  this.bipedLeftArm.rotateAngleY += this.bipedBody.rotateAngleY;
      
                  /**
                    * this.bipedBody.rotateAngleY is negated when hand side is left
                    * thus it must be subtracted from this.bipedRightArm.rotateAngleX
                    * to make it positive again as X angles aren't affected by mirroring
                    */
                  if (enumhandside == EnumHandSide.LEFT)
                  {
                      this.bipedRightArm.rotateAngleX -= this.bipedBody.rotateAngleY;
                  }
                  else
                  {
                      this.bipedLeftArm.rotateAngleX += this.bipedBody.rotateAngleY;
                  }
      
                  f1 = 1.0F - this.swingProgress;
                  f1 = f1 * f1;
                  f1 = f1 * f1;
                  f1 = 1.0F - f1;
                  float f2 = MathHelper.sin(f1 * (float)Math.PI);
                  float f3 = MathHelper.sin(this.swingProgress * (float)Math.PI) * -(this.bipedHead.rotateAngleX - 0.7F) * 0.75F;
                  modelrenderer.rotateAngleX = (float)((double)modelrenderer.rotateAngleX - ((double)f2 * 1.2D + (double)f3));
                  modelrenderer.rotateAngleY += this.bipedBody.rotateAngleY * 2.0F;
      
                  /**
                    * Used 0.4F instead of -0.4F here. Right hand subtracts and left hand adds
                    * since Z angles must apply opposite on left versus right hand to correctly mirror
                    */
                  if (enumhandside == EnumHandSide.LEFT)
                  {
                      modelrenderer.rotateAngleZ += MathHelper.sin(this.swingProgress * (float)Math.PI) * 0.4F;
                  }
                  else
                  {
                      modelrenderer.rotateAngleZ -= MathHelper.sin(this.swingProgress * (float)Math.PI) * 0.4F;
                  }
              }
      

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              onnowhere Onnowhere
            • Votes:
              2 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                CHK: