Java tutorial
/******************************************************************************* * HellFirePvP / Astral Sorcery 2017 * * This project is licensed under GNU GENERAL PUBLIC LICENSE Version 3. * The source code is available on github: https://github.com/HellFirePvP/AstralSorcery * For further details, see the License file there. ******************************************************************************/ package hellfirepvp.astralsorcery.common.util.data; import io.netty.buffer.ByteBuf; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; import java.util.Random; /** * This class is part of the Astral Sorcery Mod * The complete source code for this mod can be found on github. * Class: Vector3 * Created by HellFirePvP * Date: 17.11.2015 / 18:40 */ public class Vector3 { private static final Random RAND = new Random(); protected double x; protected double y; protected double z; public Vector3() { this.x = 0.0D; this.y = 0.0D; this.z = 0.0D; } public Vector3(Vector3 copy) { this.x = copy.x; this.y = copy.y; this.z = copy.z; } public Vector3(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public Vector3(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } public Vector3(BlockPos pos) { this(pos.getX(), pos.getY(), pos.getZ()); } public Vector3(Entity entity) { this(entity.posX - entity.width / 2, entity.posY + entity.height / 2D, entity.posZ - entity.width / 2); } public Vector3(Entity entity, boolean unused_NoAdjustment) { this(entity.posX, entity.posY, entity.posZ); } public Vector3(TileEntity te) { this(te.getPos().getX(), te.getPos().getY(), te.getPos().getZ()); } public Vector3(Vec3d vec) { this(vec.xCoord, vec.yCoord, vec.zCoord); } public Vector3 add(Vec3i vec) { this.x += vec.getX(); this.y += vec.getY(); this.z += vec.getZ(); return this; } public Vector3 add(Vector3 vec) { this.x += vec.x; this.y += vec.y; this.z += vec.z; return this; } public Vector3 add(double x, double y, double z) { this.x += x; this.y += y; this.z += z; return this; } public Vector3 addX(double x) { this.x += x; return this; } public Vector3 addY(double y) { this.y += y; return this; } public Vector3 addZ(double z) { this.z += z; return this; } public Vector3 subtract(double vX, double vY, double vZ) { this.x -= vX; this.y -= vY; this.z -= vZ; return this; } public Vector3 subtract(Entity e) { this.x -= e.posX; this.y -= e.posY; this.z -= e.posZ; return this; } public Vector3 subtract(Vec3i vec) { this.x -= vec.getX(); this.y -= vec.getY(); this.z -= vec.getZ(); return this; } public Vector3 subtract(Vector3 vec) { this.x -= vec.x; this.y -= vec.y; this.z -= vec.z; return this; } public Vector3 multiply(Vector3 vec) { this.x *= vec.x; this.y *= vec.y; this.z *= vec.z; return this; } public Vector3 divide(Vector3 vec) { this.x /= vec.x; this.y /= vec.y; this.z /= vec.z; return this; } public Vector3 divide(double divisor) { this.x /= divisor; this.y /= divisor; this.z /= divisor; return this; } public Vector3 negate() { this.x *= -1; this.y *= -1; this.z *= -1; return this; } public Vector3 copy(Vector3 vec) { this.x = vec.x; this.y = vec.y; this.z = vec.z; return this; } public double length() { return Math.sqrt(lengthSquared()); } public double lengthSquared() { return x * x + y * y + z * z; } public double distance(Vector3 o) { return Math.sqrt(distanceSquared(o)); } public double distanceSquared(Vector3 o) { double difX = x - o.x; double difY = y - o.y; double difZ = z - o.z; return difX * difX + difY * difY + difZ * difZ; } public double distance(Vec3i o) { return Math.sqrt(distanceSquared(o)); } public double distanceSquared(Vec3i o) { double difX = x - o.getX(); double difY = y - o.getY(); double difZ = z - o.getZ(); return difX * difX + difY * difY + difZ * difZ; } public double distance(Vec3d o) { return Math.sqrt(distanceSquared(o)); } public double distanceSquared(Vec3d o) { double difX = x - o.xCoord; double difY = y - o.yCoord; double difZ = z - o.zCoord; return difX * difX + difY * difY + difZ * difZ; } public float angle(Vector3 other) { double dot = dot(other) / (length() * other.length()); return (float) Math.acos(dot); } public Vector3 midpoint(Vector3 other) { this.x = ((this.x + other.x) / 2.0D); this.y = ((this.y + other.y) / 2.0D); this.z = ((this.z + other.z) / 2.0D); return this; } public Vector3 getMidpoint(Vector3 other) { double x = (this.x + other.x) / 2.0D; double y = (this.y + other.y) / 2.0D; double z = (this.z + other.z) / 2.0D; return new Vector3(x, y, z); } public Vector3 multiply(int m) { this.x *= m; this.y *= m; this.z *= m; return this; } public Vector3 multiply(double m) { this.x *= m; this.y *= m; this.z *= m; return this; } public Vector3 multiply(float m) { this.x *= m; this.y *= m; this.z *= m; return this; } public double dot(Vector3 other) { return this.x * other.x + this.y * other.y + this.z * other.z; } public Vector3 crossProduct(Vector3 o) { double newX = this.y * o.z - o.y * this.z; double newY = this.z * o.x - o.z * this.x; double newZ = this.x * o.y - o.x * this.y; this.x = newX; this.y = newY; this.z = newZ; return this; } public Vector3 perpendicular() { if (this.z == 0.0D) { return zCrossProduct(); } return xCrossProduct(); } public Vector3 xCrossProduct() { double d = this.z; double d1 = -this.y; this.x = 0.0D; this.y = d; this.z = d1; return this; } public Vector3 zCrossProduct() { double d = this.y; double d1 = -this.x; this.x = d; this.y = d1; this.z = 0.0D; return this; } public Vector3 yCrossProduct() { double d = -this.z; double d1 = this.x; this.x = d; this.y = 0.0D; this.z = d1; return this; } //In rad's public Vector3 rotate(double angle, Vector3 axis) { Quat.buildQuatFrom3DVector(axis.clone().normalize(), angle).rotateWithMagnitude(this); return this; } public Vector3 normalize() { double length = length(); this.x /= length; this.y /= length; this.z /= length; return this; } public Vector3 fastLowAccNormalize() { double lengthSq = lengthSquared(); lengthSq = fastInvSqrt(lengthSq); this.x *= lengthSq; this.y *= lengthSq; this.z *= lengthSq; return this; } //x -> about 1/sqrt(x) //~50% faster than 1/Math.sqrt(x) in its ~3-4th iterations for about the same numbers. public static double fastInvSqrt(double x) { double xhalf = 0.5d * x; long i = Double.doubleToLongBits(x); i = 0x5fe6ec85e7de30daL - (i >> 1); x = Double.longBitsToDouble(i); for (int it = 0; it < 4; it++) { x = x * (1.5d - xhalf * x * x); } return x; } public Vector3 zero() { this.x = 0.0D; this.y = 0.0D; this.z = 0.0D; return this; } public void toBytes(ByteBuf buf) { buf.writeDouble(this.x); buf.writeDouble(this.y); buf.writeDouble(this.z); } public static Vector3 fromBytes(ByteBuf buf) { return new Vector3(buf.readDouble(), buf.readDouble(), buf.readDouble()); } public static Vector3 random() { return new Vector3(RAND.nextDouble() * (RAND.nextBoolean() ? 1 : -1), RAND.nextDouble() * (RAND.nextBoolean() ? 1 : -1), RAND.nextDouble() * (RAND.nextBoolean() ? 1 : -1)); } public static Vector3 random(Random rand) { return new Vector3(rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), rand.nextDouble() * (rand.nextBoolean() ? 1 : -1)); } public static Vector3 positiveYRandom() { Vector3 rand = random(); return rand.setY(Math.abs(rand.getY())); } public static Vector3 positiveYRandom(Random r) { Vector3 rand = random(r); return rand.setY(Math.abs(rand.getY())); } //RIP ChunkCoordinates BibleThump /*public static Vector3 fromCC(ChunkCoordinates cc) { return new Vector3(cc.posX, cc.posY, cc.posZ); } public ChunkCoordinates getAsFloatCC() { return new ChunkCoordinates(Float.floatToIntBits((float) this.x), Float.floatToIntBits((float) this.y), Float.floatToIntBits((float) this.z)); } public static Vector3 getFromFloatCC(ChunkCoordinates cc) { return new Vector3(Float.intBitsToFloat(cc.posX), Float.intBitsToFloat(cc.posY), Float.intBitsToFloat(cc.posZ)); }*/ public boolean isInAABB(Vector3 min, Vector3 max) { return (this.x >= min.x) && (this.x <= max.x) && (this.y >= min.y) && (this.y <= max.y) && (this.z >= min.z) && (this.z <= max.z); } public boolean isInSphere(Vector3 origin, double radius) { double difX = origin.x - this.x; double difY = origin.y - this.y; double difZ = origin.z - this.z; return (difX * difX + difY * difY + difZ * difZ) <= (radius * radius); } public Vec3d toVec3d() { return new Vec3d(x, y, z); } public BlockPos toBlockPos() { return new BlockPos(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)); } public Vector3 vectorFromHereTo(Vector3 target) { return new Vector3(target.x - x, target.y - y, target.z - z); } public Vector3 vectorFromHereTo(double tX, double tY, double tZ) { return new Vector3(tX - x, tY - y, tZ - z); } //copy & converts to polar coordinates (in degrees) //Order: Distance, Theta, Phi public Vector3 copyToPolar() { double length = length(); double theta = Math.acos(y / length); double phi = Math.atan2(x, z); theta = Math.toDegrees(theta); phi = 180 + Math.toDegrees(phi); return new Vector3(length, theta, phi); } public Vector3 copyInterpolateWith(Vector3 next, float partial) { return new Vector3((x == next.x ? x : x + ((next.x - x) * partial)), (y == next.y ? y : y + ((next.y - y) * partial)), (z == next.z ? z : z + ((next.z - z) * partial))); } public double getX() { return this.x; } public int getBlockX() { return (int) Math.floor(this.x); } public double getY() { return this.y; } public int getBlockY() { return (int) Math.floor(this.y); } public double getZ() { return this.z; } public int getBlockZ() { return (int) Math.floor(this.z); } public Vector3 setX(int x) { this.x = x; return this; } public Vector3 setX(double x) { this.x = x; return this; } public Vector3 setX(float x) { this.x = x; return this; } public Vector3 setY(int y) { this.y = y; return this; } public Vector3 setY(double y) { this.y = y; return this; } public Vector3 setY(float y) { this.y = y; return this; } public Vector3 setZ(int z) { this.z = z; return this; } public Vector3 setZ(double z) { this.z = z; return this; } public Vector3 setZ(float z) { this.z = z; return this; } public boolean equals(Object obj) { if (!(obj instanceof Vector3)) { return false; } Vector3 other = (Vector3) obj; return (Math.abs(this.x - other.x) < 1.0E-004D) && (Math.abs(this.y - other.y) < 1.0E-004D) && (Math.abs(this.z - other.z) < 1.0E-004D) && (getClass().equals(obj.getClass())); } public int hashCode() { int hash = 7; hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ Double.doubleToLongBits(this.x) >>> 32); hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ Double.doubleToLongBits(this.y) >>> 32); hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ Double.doubleToLongBits(this.z) >>> 32); return hash; } public Vector3 clone() { return new Vector3(x, y, z); } public String toString() { return this.x + "," + this.y + "," + this.z; } public static class Quat { public double i; public double j; public double k; public double s; public Quat() { this(1D); } public Quat(double zeroMag) { this.s = zeroMag; this.i = 0D; this.j = 0D; this.k = 0D; } public Quat(Quat quat) { this.i = quat.i; this.j = quat.j; this.k = quat.k; this.s = quat.s; } public Quat(double w, double i, double j, double k) { this.i = i; this.j = j; this.k = k; this.s = w; } public void set(Quat quat) { this.i = quat.i; this.j = quat.j; this.k = quat.k; this.s = quat.s; } public static Quat buildQuatWithAngle(double ax, double ay, double az, double angle) { angle *= 0.5D; double d4 = Math.sin(angle); return new Quat(Math.cos(angle), ax * d4, ay * d4, az * d4); } public void leftMultiply(Quat quat) { double d = this.s * quat.s - this.i * quat.i - this.j * quat.j - this.k * quat.k; double d1 = this.s * quat.i + this.i * quat.s - this.j * quat.k + this.k * quat.j; double d2 = this.s * quat.j + this.i * quat.k + this.j * quat.s - this.k * quat.i; double d3 = this.s * quat.k - this.i * quat.j + this.j * quat.i + this.k * quat.s; this.s = d; this.i = d1; this.j = d2; this.k = d3; } public void rightMultiply(Quat quat) { double d = this.s * quat.s - this.i * quat.i - this.j * quat.j - this.k * quat.k; double d1 = this.s * quat.i + this.i * quat.s + this.j * quat.k - this.k * quat.j; double d2 = this.s * quat.j - this.i * quat.k + this.j * quat.s + this.k * quat.i; double d3 = this.s * quat.k + this.i * quat.j - this.j * quat.i + this.k * quat.s; this.s = d; this.i = d1; this.j = d2; this.k = d3; } public double mag() { return Math.sqrt(this.i * this.i + this.j * this.j + this.k * this.k + this.s * this.s); } public void normalize() { double d = mag(); if (d == 0.0D) { return; } d = 1.0D / d; this.i *= d; this.j *= d; this.k *= d; this.s *= d; } public void rotateWithMagnitude(Vector3 vec) { double d = -this.i * vec.x - this.j * vec.y - this.k * vec.z; double d1 = this.s * vec.x + this.j * vec.z - this.k * vec.y; double d2 = this.s * vec.y - this.i * vec.z + this.k * vec.x; double d3 = this.s * vec.z + this.i * vec.y - this.j * vec.x; vec.x = (d1 * this.s - d * this.i - d2 * this.k + d3 * this.j); vec.y = (d2 * this.s - d * this.j + d1 * this.k - d3 * this.i); vec.z = (d3 * this.s - d * this.k - d1 * this.j + d2 * this.i); } public String toString() { return String.format("Quaternion: { s=%f, i=%f, j=%f, k=%f }", this.s, this.i, this.j, this.k); } public static Quat buildQuatFrom3DVector(Vector3 axis, double angle) { return buildQuatWithAngle(axis.x, axis.y, axis.z, angle); } } public static class RotAxis { public static final Vector3 X_AXIS = new Vector3(1, 0, 0); public static final Vector3 Y_AXIS = new Vector3(0, 1, 0); public static final Vector3 Z_AXIS = new Vector3(0, 0, 1); } }