Rotate complete armorstand model

Discussion in 'Plugin Development' started by CraterHater, Aug 17, 2017.

Thread Status:
Not open for further replies.
  1. Offline

    CraterHater

    Hey there,

    I am trying to rotate this entire armorstand model:
    [​IMG]
    [​IMG]
    2017-08-17_08.57.42.png

    I've got a list of armorstands in this model and a center locations. I already tried the following:

    Code:
    public void rotate(ArrayList<ArmorStand> armors, int degree){  
            Location center = ast.getCenterOfMultipleLocations(armors);
      
            for(ArmorStand a : armors){
                double xoffset = round(a.getLocation().getX()-center.getX(),4);
                double yoffset = round(a.getLocation().getY()-center.getY(),4);
                double zoffset = round(a.getLocation().getZ()-center.getZ(),4);
          
                Location loc = getLocationAroundCircle(center, center.distance(inc(center,xoffset,yoffset,zoffset)), degree);
                a.setGravity(true);
                a.setVelocity(new Vector(1, 0, 0));
                a.teleport(loc);
                a.setGravity(false);
            }
        }
         public Location inc(Location loc, double x, double y, double z) {
             return new Location(loc.getWorld(), loc.getX() + x, loc.getY() + y, loc.getZ() + z);
         }
        public Location getLocationAroundCircle(Location center, double radius, double angleInRadian) {
            double x = center.getX() + radius * Math.cos(angleInRadian);
            double z = center.getZ() + radius * Math.sin(angleInRadian);
            double y = center.getY();
    
            Location loc = new Location(center.getWorld(), x, y, z);
            Vector difference = center.toVector().clone().subtract(loc.toVector());
            loc.setDirection(difference);
    
            return loc;
        }
        }
    But this simply folds the model like so:
    [​IMG]
    2017-08-17_08.59.29.png
    Hope to get some help soon!

    Thanks!
     
  2. Offline

    Zombie_Striker

    @CraterHater
    The issue is that your math is wrong; The X and Z is not just cos and sin by themselves, but
    Code:
      double x = v.getX() * cos + v.getZ() * sin;
            double z = v.getX() * -sin + v.getZ() * cos;
    Where V is the relative vector for the center of the object.

    You can read more about rotating complex objects in this thread:
    https://www.spigotmc.org/threads/rotating-particle-effects.166854/
     
  3. Offline

    CraterHater

    @Zombie_Striker

    Right now it is 90 degrees off. Like so:


    Code:
    public void rotate(ArrayList<ArmorStand> armors, int degree){ 
            Location center = ast.getCenterOfMultipleLocations(armors);
     
            center.getBlock().setType(Material.DIAMOND_BLOCK);
           
            final double radius = (float) center.distance(armors.get(0).getLocation());
            final float radPerSec = 1.5f;
            final float radPerTick = radPerSec / 20f;
    
            final ArmorStand stand = armors.get(0);
            stand.setGravity(false);
    
            new BukkitRunnable() {
                int tick = 0;
                public void run() {
                    ++tick;
    
                    Location loc = getLocationAroundCircle(center, radius, radPerTick * tick);
                    stand.setVelocity(new Vector(1, 0, 0));
                    stand.teleport(loc);
                }
            }.runTaskTimer(main, 0L, 1L);
        }
         public Location inc(Location loc, double x, double y, double z) {
             return new Location(loc.getWorld(), loc.getX() + x, loc.getY() + y, loc.getZ() + z);
         }
         public Location getLocationAroundCircle(Location center, double radius, double angleInRadian) {
                double x = center.getX() + radius * Math.cos(angleInRadian);
                double z = center.getZ() + radius * Math.sin(angleInRadian);
                double y = center.getY();
    
                Location loc = new Location(center.getWorld(), x, y, z);
                Vector difference = center.toVector().clone().subtract(loc.toVector());
               
                loc.setDirection(difference);
    
                return loc;
            }
     
  4. Offline

    Zombie_Striker

    @CraterHater
    The math is still wrong. It does not look like you made any changes to the rotation code at all. Again, to get the offset for the X and Z, use
    Code:
    double x = v.getX() * cos + v.getZ() * sin;
            double z = v.getX() * -sin + v.getZ() * cos;
    Where v is the offset of the location relative to the center.
     
  5. Offline

    CraterHater

    @Zombie_Striker

    That's because I didn't understand that. What do you mean with 'Where v is the offset of the location relative to the center.'
     
  6. Offline

    Zombie_Striker

    @CraterHater
    Relative to the center of the object (what you are referring to as "center" in your code), find the difference in the X and Z direction for the armorstand. For example, if that part that was rotating the video is at (0,0,1) and if center is at (0,0,0), the difference in the X direction would be 0, and the difference in Z would be 1. Then, using the code posted above, you would replace "v.getX" with that 0 and "v.getZ" with 1.
     
  7. Offline

    CraterHater

    @Zombie_Striker

    Alright, got it to sort of work with your maths but it didn't really do any different. I know what is causing it to now face the center though and that is because the head position isn't normal, I somehow have to change the direction of the last vector so that it faces the center.
    Code:
    public void rotate(ArrayList<ArmorStand> armors, int degree){ 
            Location center = ast.getCenterOfMultipleLocations(armors);
     
            center.getBlock().setType(Material.DIAMOND_BLOCK);
           
            final double radius = (float) center.distance(armors.get(0).getLocation());
            final float radPerSec = 1.5f;
            final float radPerTick = radPerSec / 20f;
    
            final ArmorStand stand = armors.get(0);
            stand.setGravity(false);
    
            Vector v = new Vector(stand.getLocation().getX()-center.getX(),0,stand.getLocation().getZ()-center.getZ());
           
            new BukkitRunnable() {
                int tick = 0;
                public void run() {
                    ++tick;
    
                    Location loc = getLocationAroundCircle(v, center, radius, radPerTick * tick);
                    stand.setVelocity(new Vector(1, 0, 0));
                    stand.teleport(loc);
                }
            }.runTaskTimer(main, 0L, 1L);
        }
         public Location inc(Location loc, double x, double y, double z) {
             return new Location(loc.getWorld(), loc.getX() + x, loc.getY() + y, loc.getZ() + z);
         }
         public Location getLocationAroundCircle(Vector v, Location center, double radius, double angleInRadian) {
                double x = v.getX() * Math.cos(angleInRadian) + v.getZ() * Math.sin(angleInRadian);
                double z = v.getX() * -Math.sin(angleInRadian) + v.getZ() * Math.cos(angleInRadian);
                double y = center.getY();
               
                Location loc = inc(center,x,y,z);
               
                Vector difference = center.toVector().clone().subtract(loc.toVector());
                  
                loc.setDirection(difference);
    
                return loc;
            }
    }
     
  8. Offline

    Zombie_Striker

    @CraterHater
    Are you sure that the center is located at the middle of the iron block? From the video, it seem the corner closest to you is favored more than the other side. Can you post the code you use for getting the center?
     
  9. Offline

    CraterHater

    @Zombie_Striker
    Code:
    public Location getCenterOfMultipleLocations(ArrayList<ArmorStand> armors){
            ArrayList<Location> locs = new ArrayList<Location>();
            for(ArmorStand a : armors){
                locs.add(a.getLocation());
            }
            double xs = 0;
            double ys = 0;
            double zs = 0;
           
            for(Location loc : locs){
                xs += loc.getX();
                ys += loc.getY();
                zs += loc.getZ();
            }
           
            xs /= locs.size();
            ys /= locs.size();
            zs /= locs.size();
           
            return new Location(locs.get(0).getWorld(),xs,ys,zs);
        }
     
Thread Status:
Not open for further replies.

Share This Page