Solved How to calculate armorstand arm tip location

Discussion in 'Spigot Plugin Development' started by TerZer, Jul 31, 2018.

  1. I need to get armorstands arm tip location, I guess it is possible with some kind of calculation with
    Code (Java):
    #.getRightArmPose()
    but me and my friend tried to do something, but that didn't worked out:

    Code (Java):
    public static Location getRightArmPivot(ArmorStand as) {
            final double armRadius = -0.3125;
            double pointX = as.getLocation().getX();
            double pointZ = as.getLocation().getZ();

            float rotation = as.getLocation().getYaw();

            double x = pointX + (armRadius * Math.cos(rotation));
            double z = pointZ + (armRadius * Math.sin(rotation));

            return new Location(as.getWorld(), x, as.getLocation().getY() + 1.5D, z);
        }

        public Location getRightArmTip(ArmorStand as) {
            Location shoulder = getRightArmPivot(as);
            Vector unit = new Vector(1, 0, 0);
            EulerAngle ea = as.getRightArmPose();

            return shoulder.clone().add(RotationUtil.rotate(unit, ea.getY(), ea.getX(), ea.getZ()));
        }
     
  2. I haven't worked with armor stands, but is getHeadLocation what you're looking for?
     
  3. For testing purposes why don't you spawn a stationary particle at the location you calculated?
     
  4. Also while I don't remember exactly wasn't the sine function supposed to take the x?
     
  5. @Blutkrone I spawn particle and it was in a bad location. As long as I know you can calculate sin from any number.
     
  6. The angles of your armor stand arm is an Euler Angle, and the x and y of the Euler Angle is Yaw and Pitch. It should be pretty straightforward after that. You just need to calculate the offset (FYI arm is 2x12x2, and the rotation point is at the closest point to shoulder joint, middle of the arm, and at the 10th pixel counting from the tip of the hand)

    Edit: and sorry if this didn't help you. I'm currently walking while reading and typing so it's hard to read your code. Gimme a moment and I will re-read the questions
     
    #8 Ticxo, Aug 2, 2018
    Last edited: Aug 2, 2018
  7. I'm surprised no one replied while I'm away XD, anyway here's how you do it:

    Getting the shoulder location:
    The shoulder is 22 pixels above the armor stand's location, and 5 pixels to the side.
    1) Get the location of armor stand and add 90 to the location, that way you are "pointing" at the shoulder.
    2) Get the direction of location. use #getDirection.
    3) Offset the location to where the shoulder is.

    Getting the arm tip location:
    The arm tip is 10 pixels away from the rotational point of shoulder.
    1) Get the EulerAngle of your arm (I'm using right arm).
    2) Convert the EulerAngle to Vector. This thread may help you. Remember, the Y of EulerAngle is Yaw and X of it is Pitch.
    3) Offset the location by 10 pixels.

    Something to point out:
    Try not to use the Z value of the EulerAngle, as all direction can be represented only using X and Y

    Code (Java):
    @EventHandler
        public void onAttack(EntityDamageByEntityEvent event) {
            if(event.getDamager() instanceof Player && event.getEntity() instanceof ArmorStand) {
               
                event.setCancelled(true);
                //Get Shoulder Location
                ArmorStand as = (ArmorStand) event.getEntity();
                Location asl = as.getLocation();
                asl.setYaw(asl.getYaw() + 90f);
                Vector dir = asl.getDirection();
                asl.setX(asl.getX() + 5f/16f * dir.getX());
                asl.setY(asl.getY() + 22f/16f);
                asl.setZ(asl.getZ() + 5f/16f * dir.getZ());
                asl.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, asl, 1);
                //Get Hand Location
                EulerAngle ea = as.getRightArmPose();
                Vector armDir = getDirection(ea.getY(), ea.getX());
                asl.setX(asl.getX() + 10f/16f * armDir.getX());
                asl.setY(asl.getY() + 10f/16f * armDir.getY());
                asl.setZ(asl.getZ() + 10f/16f * armDir.getZ());
               
                asl.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, asl, 1);
               
            }
        }
       
        public Vector getDirection(Double yaw, Double pitch) {

            yaw = Math.toRadians(Math.toDegrees(yaw) + 90);
            pitch = Math.toRadians(Math.toDegrees(pitch) + 180);

            Double x = Math.sin(pitch) * Math.cos(yaw);
            Double y = Math.sin(pitch) * Math.sin(yaw);
            Double z = Math.cos(pitch);

            return new Vector(x, z, y);
        }

    How it looks:
    armorstand.png
     
    • Agree Agree x 2
    • Winner Winner x 1
  8. @Ticxo that code you gave me did not worked, I checked it somehow messes up with Y. If I replace x with y, then it rotates normally, but rotation sometimes goes in opposite direction. Direction of starting rotation then messes up
     
  9. Right answer by @MCGamer00000 :


    Code (Java):

        public static Location getArmTip(ArmorStand as) {
            // Gets shoulder location
            Location asl = as.getLocation().clone();
            asl.setYaw(asl.getYaw() + 90f);
            Vector dir = asl.getDirection();
            asl.setX(asl.getX() + 5f / 16f * dir.getX());
            asl.setY(asl.getY() + 22f / 16f);
            asl.setZ(asl.getZ() + 5f / 16f * dir.getZ());
            asl.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, asl, 1);
            // Get Hand Location
         
            EulerAngle ea = as.getRightArmPose();
            Vector armDir = getDirection(ea.getY(), ea.getX(), -ea.getZ());
            armDir = rotateAroundAxisY(armDir, Math.toRadians(asl.getYaw()-90f));
            asl.setX(asl.getX() + 10f / 16f * armDir.getX());
            asl.setY(asl.getY() + 10f / 16f * armDir.getY());
            asl.setZ(asl.getZ() + 10f / 16f * armDir.getZ());

            asl.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, asl, 1);
            return asl;
        }

        public static Vector getDirection(Double yaw, Double pitch, Double roll) {
            Vector v = new Vector(0, -1, 0);
            v = rotateAroundAxisX(v, pitch);
            v = rotateAroundAxisY(v, yaw);
            v = rotateAroundAxisZ(v, roll);
            return v;
        }
     
        private static Vector rotateAroundAxisX(Vector v, double angle) {
            double y, z, cos, sin;
            cos = Math.cos(angle);
            sin = Math.sin(angle);
            y = v.getY() * cos - v.getZ() * sin;
            z = v.getY() * sin + v.getZ() * cos;
            return v.setY(y).setZ(z);
        }

        private static Vector rotateAroundAxisY(Vector v, double angle) {
            angle = -angle;
            double x, z, cos, sin;
            cos = Math.cos(angle);
            sin = Math.sin(angle);
            x = v.getX() * cos + v.getZ() * sin;
            z = v.getX() * -sin + v.getZ() * cos;
            return v.setX(x).setZ(z);
        }

        private static Vector rotateAroundAxisZ(Vector v, double angle) {
            double x, y, cos, sin;
            cos = Math.cos(angle);
            sin = Math.sin(angle);
            x = v.getX() * cos - v.getY() * sin;
            y = v.getX() * sin + v.getY() * cos;
            return v.setX(x).setY(y);
        }