# Rotate complete armorstand model

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

Not open for further replies.
1. Offline

### CraterHater

Hey there,

I am trying to rotate this entire armorstand model:

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:

Hope to get some help soon!

Thanks!

#1
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:

#2
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);
}
}
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;
}

#3
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.

#4
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.'

#5
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.

#6
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);
}
}
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;
}
}

#7
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?

#8
9. Offline

### CraterHater

@Zombie_Striker
Code:
public Location getCenterOfMultipleLocations(ArrayList<ArmorStand> armors){
ArrayList<Location> locs = new ArrayList<Location>();
for(ArmorStand a : armors){
}
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);
}

#9