diff --git a/src/main/java/com/tocard/cam/Camera.java b/src/main/java/com/tocard/cam/Camera.java index 944faea..5d98940 100644 --- a/src/main/java/com/tocard/cam/Camera.java +++ b/src/main/java/com/tocard/cam/Camera.java @@ -18,8 +18,8 @@ import org.bukkit.inventory.ItemStack; public class Camera extends JavaPlugin implements Listener { - public static ArrayList curve = new ArrayList<>(); - public static ArrayList controlPoints = new ArrayList<>(); + public static ArrayList curve = new ArrayList<>(); + public static ArrayList controlPoints = new ArrayList<>(); public static Logger logger; public static Plugin plugin; private static float dt = 0.01f; @@ -64,7 +64,7 @@ public class Camera extends JavaPlugin implements Listener { if (nControlPoints <= 4) { for (float t = 0; t < 1; t += dt) { - ArrayList P = new ArrayList<>(controlPoints); + ArrayList P = new ArrayList<>(controlPoints); int N = P.size(); for (int k = N - 1; k > 0; k--) { @@ -82,7 +82,7 @@ public class Camera extends JavaPlugin implements Listener { int nBezier = (nControlPoints - 1) / 3; for (int iBezier = 0; iBezier < nBezier; iBezier++) { for (float t = 0; t < 1; t += dt) { - ArrayList P = new ArrayList<>(); + ArrayList P = new ArrayList<>(); for (int k = 0; k < 4; k++) { P.add(controlPoints.get(3 * iBezier + k).clone()); } @@ -105,7 +105,7 @@ public class Camera extends JavaPlugin implements Listener { Bukkit.broadcastMessage(msg); } - public static String prettyLocation(LocationQuaternion2 point) { + public static String prettyLocation(LocationQuaternion point) { point.updateEulerAngles(); return String.format("X=%05.2f, Y=%05.2f, Z=%05.2f, P=%05.2f, Y=%05.2f", point.getX(), point.getY(), point.getZ(), diff --git a/src/main/java/com/tocard/cam/ExecuteTraveling.java b/src/main/java/com/tocard/cam/ExecuteTraveling.java index 9de28df..1033841 100644 --- a/src/main/java/com/tocard/cam/ExecuteTraveling.java +++ b/src/main/java/com/tocard/cam/ExecuteTraveling.java @@ -11,7 +11,7 @@ import java.util.Iterator; public class ExecuteTraveling implements CommandExecutor { private static int taskID = -1; - private static Iterator curveIterator; + private static Iterator curveIterator; @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { @@ -33,7 +33,7 @@ public class ExecuteTraveling implements CommandExecutor { public void run() { // Teleport to next point if (curveIterator.hasNext()) { - LocationQuaternion2 loc = curveIterator.next(); + LocationQuaternion loc = curveIterator.next(); Camera.broadlog(Camera.prettyLocation(loc)); player.teleport(loc); return; diff --git a/src/main/java/com/tocard/cam/ListPoints.java b/src/main/java/com/tocard/cam/ListPoints.java index 69541a0..0154ff7 100644 --- a/src/main/java/com/tocard/cam/ListPoints.java +++ b/src/main/java/com/tocard/cam/ListPoints.java @@ -9,7 +9,7 @@ import org.bukkit.entity.Player; public class ListPoints implements CommandExecutor { - private static ListIterator points; + private static ListIterator points; @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { diff --git a/src/main/java/com/tocard/cam/LocationQuaternion.java b/src/main/java/com/tocard/cam/LocationQuaternion.java index 7c2cb89..5157ba8 100644 --- a/src/main/java/com/tocard/cam/LocationQuaternion.java +++ b/src/main/java/com/tocard/cam/LocationQuaternion.java @@ -11,6 +11,7 @@ public class LocationQuaternion extends Location { private float roll = 0; private static final float deg2grad = (float) Math.PI / 180.0f; + private static final float grad2deg = 1 / deg2grad; // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_code public LocationQuaternion(Location location) { @@ -18,8 +19,8 @@ public class LocationQuaternion extends Location { location.getX(), location.getY(), location.getZ(), - location.getYaw() * deg2grad, - location.getPitch() * deg2grad); + location.getYaw(), + location.getPitch()); this.updateQuaternionAngles(); } @@ -28,54 +29,105 @@ public class LocationQuaternion extends Location { // roll (x-axis rotation) double sinr_cosp = 2 * (qw * qx + qy * qz); double cosr_cosp = 1 - 2 * (qx * qx + qy * qy); - this.roll = (float) Math.atan2(sinr_cosp, cosr_cosp); + roll = (float) Math.atan2(sinr_cosp, cosr_cosp) * grad2deg; // pitch (y-axis rotation) + double pitch; double sinp = 2 * (qw * qy - qz * qx); if (Math.abs(sinp) >= 1) { - this.setPitch((float) Math.copySign(Math.PI / 2, sinp)); // use 90 degrees if out of range + pitch = Math.copySign(Math.PI / 2, sinp); // use 90 degrees if out of range } else { - this.setPitch((float) Math.asin(sinp)); + pitch = Math.asin(sinp); } + setPitch((float) pitch * grad2deg); // yaw (z-axis rotation) double siny_cosp = 2 * (qw * qz + qx * qy); double cosy_cosp = 1 - 2 * (qy * qy + qz * qz); - this.setYaw((float) Math.atan2(siny_cosp, cosy_cosp)); + double yaw = Math.atan2(siny_cosp, cosy_cosp); + setYaw((float) yaw * grad2deg); + } public void updateQuaternionAngles() { - double cy = Math.cos(getYaw() * 0.5); - double sy = Math.sin(getYaw() * 0.5); - double cp = Math.cos(getPitch() * 0.5); - double sp = Math.sin(getPitch() * 0.5); - double cr = Math.cos(getRoll() * 0.5); - double sr = Math.sin(getRoll() * 0.5); + float yaw = getYaw() * deg2grad; + float pitch = getPitch() * deg2grad; - this.qw = cr * cp * cy + sr * sp * sy; - this.qx = sr * cp * cy - cr * sp * sy; - this.qy = cr * sp * cy + sr * cp * sy; - this.qz = cr * cp * sy - sr * sp * cy; + double cy = Math.cos(yaw * 0.5); + double sy = Math.sin(yaw * 0.5); + double cp = Math.cos(pitch * 0.5); + double sp = Math.sin(pitch * 0.5); + double cr = Math.cos(roll * 0.5); + double sr = Math.sin(roll * 0.5); + + qw = cr * cp * cy + sr * sp * sy; + qx = sr * cp * cy - cr * sp * sy; + qy = cr * sp * cy + sr * cp * sy; + qz = cr * cp * sy - sr * sp * cy; } - public double dot(LocationQuaternion loc) { - return this.qw * loc.qw + this.qx * loc.qx + this.qy * loc.qy + this.qz * loc.qz; + public LocationQuaternion patchYaw(LocationQuaternion previousLocation) { + float A = previousLocation.getYaw(); + float B = getYaw(); + float b = B % 360; + int wholePart = 360 * (int) (A / 360); + + float minDist = -1; + float sol = 0; + for (int i = -1; i < 2; i++) { + float val = wholePart + b + i * 360; + float dist = Math.abs(val - A); + if (minDist == -1 || dist < minDist) { + sol = val; + minDist = dist; + } + } + + setYaw(sol); + + updateQuaternionAngles(); + return this; + } + + public LocationQuaternion add(LocationQuaternion loc) { + super.add(loc); + + qw += loc.qw; + qx += loc.qx; + qy += loc.qy; + qz += loc.qz; + + updateEulerAngles(); + return this; + } + + public LocationQuaternion subtract(LocationQuaternion loc) { + super.subtract(loc); + + qw -= loc.qw; + qx -= loc.qx; + qy -= loc.qy; + qz -= loc.qz; + + updateEulerAngles(); + return this; + } + + public LocationQuaternion multiply(double m) { + super.multiply(m); + + qw *= m; + qx += m; + qy += m; + qz += m; + + updateEulerAngles(); + return this; } @Override public LocationQuaternion clone() { - LocationQuaternion cloned = (LocationQuaternion) super.clone(); - - cloned.roll = this.roll; - cloned.qw = this.qw; - cloned.qx = this.qx; - cloned.qy = this.qy; - cloned.qz = this.qz; - + LocationQuaternion cloned = new LocationQuaternion(this); return cloned; } - - public float getRoll() { - return this.roll; - } } diff --git a/src/main/java/com/tocard/cam/LocationQuaternion2.java b/src/main/java/com/tocard/cam/LocationQuaternion2.java deleted file mode 100644 index 06cdd8a..0000000 --- a/src/main/java/com/tocard/cam/LocationQuaternion2.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.tocard.cam; - -import org.bukkit.Location; - -public class LocationQuaternion2 extends Location { - - private double qw; - private double qx; - private double qy; - private double qz; - private float roll = 0; - - private static final float deg2grad = (float) Math.PI / 180.0f; - private static final float grad2deg = 1 / deg2grad; - - // https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Source_code - public LocationQuaternion2(Location location) { - super(location.getWorld(), - location.getX(), - location.getY(), - location.getZ(), - location.getYaw(), - location.getPitch()); - - this.updateQuaternionAngles(); - } - - public void updateEulerAngles() { - // roll (x-axis rotation) - double sinr_cosp = 2 * (qw * qx + qy * qz); - double cosr_cosp = 1 - 2 * (qx * qx + qy * qy); - roll = (float) Math.atan2(sinr_cosp, cosr_cosp) * grad2deg; - - // pitch (y-axis rotation) - double pitch; - double sinp = 2 * (qw * qy - qz * qx); - if (Math.abs(sinp) >= 1) { - pitch = Math.copySign(Math.PI / 2, sinp); // use 90 degrees if out of range - } else { - pitch = Math.asin(sinp); - } - setPitch((float) pitch * grad2deg); - - // yaw (z-axis rotation) - double siny_cosp = 2 * (qw * qz + qx * qy); - double cosy_cosp = 1 - 2 * (qy * qy + qz * qz); - double yaw = Math.atan2(siny_cosp, cosy_cosp); - setYaw((float) yaw * grad2deg); - - } - - public void updateQuaternionAngles() { - float yaw = getYaw() * deg2grad; - float pitch = getPitch() * deg2grad; - - double cy = Math.cos(yaw * 0.5); - double sy = Math.sin(yaw * 0.5); - double cp = Math.cos(pitch * 0.5); - double sp = Math.sin(pitch * 0.5); - double cr = Math.cos(roll * 0.5); - double sr = Math.sin(roll * 0.5); - - qw = cr * cp * cy + sr * sp * sy; - qx = sr * cp * cy - cr * sp * sy; - qy = cr * sp * cy + sr * cp * sy; - qz = cr * cp * sy - sr * sp * cy; - } - - public LocationQuaternion2 patchYaw(LocationQuaternion2 previousLocation) { - float A = previousLocation.getYaw(); - float B = getYaw(); - float b = B % 360; - int wholePart = 360 * (int) (A / 360); - - float minDist = -1; - float sol = 0; - for (int i = -1; i < 2; i++) { - float val = wholePart + b + i * 360; - float dist = Math.abs(val - A); - if (minDist == -1 || dist < minDist) { - sol = val; - minDist = dist; - } - } - - setYaw(sol); - - updateQuaternionAngles(); - return this; - } - - public LocationQuaternion2 add(LocationQuaternion2 loc) { - super.add(loc); - - qw += loc.qw; - qx += loc.qx; - qy += loc.qy; - qz += loc.qz; - - updateEulerAngles(); - return this; - } - - public LocationQuaternion2 subtract(LocationQuaternion2 loc) { - super.subtract(loc); - - qw -= loc.qw; - qx -= loc.qx; - qy -= loc.qy; - qz -= loc.qz; - - updateEulerAngles(); - return this; - } - - public LocationQuaternion2 multiply(double m) { - super.multiply(m); - - qw *= m; - qx += m; - qy += m; - qz += m; - - updateEulerAngles(); - return this; - } - - @Override - public LocationQuaternion2 clone() { - LocationQuaternion2 cloned = new LocationQuaternion2(this); - return cloned; - } -} diff --git a/src/main/java/com/tocard/cam/NewPoint.java b/src/main/java/com/tocard/cam/NewPoint.java index fe3f035..7345cec 100644 --- a/src/main/java/com/tocard/cam/NewPoint.java +++ b/src/main/java/com/tocard/cam/NewPoint.java @@ -16,13 +16,13 @@ public class NewPoint implements CommandExecutor { Player player = (Player) sender; switch (args[0]) { case "add": - add(args, new LocationQuaternion2(player.getLocation()), player.getWorld()); + add(args, new LocationQuaternion(player.getLocation()), player.getWorld()); break; case "rm": rm(args, null, null); break; case "set": - set(args, new LocationQuaternion2(player.getLocation()), player.getWorld()); + set(args, new LocationQuaternion(player.getLocation()), player.getWorld()); break; default: break; @@ -38,34 +38,34 @@ public class NewPoint implements CommandExecutor { return true; } - public static void addPoint(LocationQuaternion2 point, World world) { + public static void addPoint(LocationQuaternion point, World world) { Camera.controlPoints.add(point); ShowCurve.add(point, world); Camera.broadlog("Point added: " + Camera.prettyLocation(point)); } - public static void setPoint(int index, LocationQuaternion2 point, World world) { + public static void setPoint(int index, LocationQuaternion point, World world) { Camera.controlPoints.set(index, point); ShowCurve.set(index, point, world); Camera.broadlog("Point n°" + index + " set: " + Camera.prettyLocation(point)); } public static void rmPoint(int index) { - LocationQuaternion2 location = Camera.controlPoints.remove(index); + LocationQuaternion location = Camera.controlPoints.remove(index); ShowCurve.rm(index); Camera.broadlog("Point deleted: " + Camera.prettyLocation(location)); } - public static void add(String[] args, LocationQuaternion2 location, World world) { + public static void add(String[] args, LocationQuaternion location, World world) { int n = Camera.controlPoints.size(); if (n < 4) { addPoint(location, world); } else { - LocationQuaternion2 P2 = Camera.controlPoints.get(n - 2); - LocationQuaternion2 P3 = Camera.controlPoints.get(n - 1); - LocationQuaternion2 P4 = P3.clone().multiply(2).subtract(P2); - LocationQuaternion2 P5 = location.clone().add(P4).multiply(0.5); + LocationQuaternion P2 = Camera.controlPoints.get(n - 2); + LocationQuaternion P3 = Camera.controlPoints.get(n - 1); + LocationQuaternion P4 = P3.clone().multiply(2).subtract(P2); + LocationQuaternion P5 = location.clone().add(P4).multiply(0.5); addPoint(P4, world); addPoint(P5, world); @@ -74,7 +74,7 @@ public class NewPoint implements CommandExecutor { } @Deprecated - public static void ins(String[] args, LocationQuaternion2 location, World world) { + public static void ins(String[] args, LocationQuaternion location, World world) { int index = Integer.parseInt(args[1]); Camera.controlPoints.add(index, location); Camera.broadlog("Point added: " + Camera.prettyLocation(location)); @@ -106,7 +106,7 @@ public class NewPoint implements CommandExecutor { } - public static void set(String[] args, LocationQuaternion2 location, World world) { + public static void set(String[] args, LocationQuaternion location, World world) { int n = Camera.controlPoints.size(); int index = Integer.parseInt(args[1]); @@ -118,7 +118,7 @@ public class NewPoint implements CommandExecutor { switch (index % 3) { case 0: // Anchor point - LocationQuaternion2 shift = location.clone().subtract(Camera.controlPoints.get(index)); + LocationQuaternion shift = location.clone().subtract(Camera.controlPoints.get(index)); for (int i = 0; i < 3; i++) { try { setPoint(index + i - 1, Camera.controlPoints.get(index + i - 1).clone().add(shift), world); @@ -131,12 +131,12 @@ public class NewPoint implements CommandExecutor { // Control point after an anchor if (index - 2 >= 0) { // Get anchor-location direction - LocationQuaternion2 anchor = Camera.controlPoints.get(index - 1); + LocationQuaternion anchor = Camera.controlPoints.get(index - 1); double currentDistance = anchor.distance(location); - LocationQuaternion2 currentVect = anchor.clone().subtract(location).multiply(1 / currentDistance); + LocationQuaternion currentVect = anchor.clone().subtract(location).multiply(1 / currentDistance); // Get anchor-corresponding distance - LocationQuaternion2 correspondingControl = Camera.controlPoints.get(index - 2); + LocationQuaternion correspondingControl = Camera.controlPoints.get(index - 2); double correspondingDistance = anchor.distance(correspondingControl); // Keep correcponding at the same distance @@ -150,12 +150,12 @@ public class NewPoint implements CommandExecutor { // Control point before an anchor if (index + 2 < n) { // Get anchor-location direction - LocationQuaternion2 anchor = Camera.controlPoints.get(index + 1); + LocationQuaternion anchor = Camera.controlPoints.get(index + 1); double currentDistance = anchor.distance(location); - LocationQuaternion2 currentVect = anchor.clone().subtract(location).multiply(1 / currentDistance); + LocationQuaternion currentVect = anchor.clone().subtract(location).multiply(1 / currentDistance); // Get anchor-corresponding distance - LocationQuaternion2 correspondingControl = Camera.controlPoints.get(index + 2); + LocationQuaternion correspondingControl = Camera.controlPoints.get(index + 2); double correspondingDistance = anchor.distance(correspondingControl); // Keep correcponding at the same distance diff --git a/src/main/java/com/tocard/cam/ShowCurve.java b/src/main/java/com/tocard/cam/ShowCurve.java index a0dfa53..918dd8f 100644 --- a/src/main/java/com/tocard/cam/ShowCurve.java +++ b/src/main/java/com/tocard/cam/ShowCurve.java @@ -61,7 +61,7 @@ public class ShowCurve implements CommandExecutor { @Override public void run() { // Get curve iterator - Iterator curveIterator = Camera.curve.iterator(); + Iterator curveIterator = Camera.curve.iterator(); // Draw path while (curveIterator.hasNext()) { @@ -101,7 +101,7 @@ public class ShowCurve implements CommandExecutor { return true; } - public static void add(LocationQuaternion2 point, World world) { + public static void add(LocationQuaternion point, World world) { ArmorStand as = world.spawn(point, ArmorStand.class); as.setGravity(false); as.setVisible(false); @@ -120,7 +120,7 @@ public class ShowCurve implements CommandExecutor { } @Deprecated - public static void insert(int index, LocationQuaternion2 point, World world) { + public static void insert(int index, LocationQuaternion point, World world) { ArmorStand as = world.spawn(point, ArmorStand.class); as.setGravity(false); as.setVisible(false); @@ -135,7 +135,7 @@ public class ShowCurve implements CommandExecutor { controlPointsArmorStands.add(index, as); } - public static void set(int index, LocationQuaternion2 point, World world) { + public static void set(int index, LocationQuaternion point, World world) { controlPointsArmorStands.get(index).setHeadPose(new EulerAngle(point.getPitch() / 180 * Math.PI, 0, 0)); controlPointsArmorStands.get(index).teleport(point); }