package codechicken.lib.vec; import codechicken.lib.math.MathHelper; import codechicken.lib.util.Copyable; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockPos; import net.minecraft.util.Vec3; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector3f; import org.lwjgl.util.vector.Vector4f; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; public class Vector3 implements Copyable<Vector3> { public static Vector3 zero = new Vector3(); public static Vector3 one = new Vector3(1, 1, 1); public static Vector3 center = new Vector3(0.5, 0.5, 0.5); public double x; public double y; public double z; public Vector3() { } public Vector3(double d, double d1, double d2) { x = d; y = d1; z = d2; } public Vector3(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; } public Vector3(double[] da) { this(da[0], da[1], da[2]); } public Vector3(Vec3 vec) { x = vec.xCoord; y = vec.yCoord; z = vec.zCoord; } public Vector3(BlockCoord coord) { x = coord.x; y = coord.y; z = coord.z; } public Vector3(BlockPos pos) { x = pos.getX(); y = pos.getY(); z = pos.getZ(); } public Vector3 copy() { return new Vector3(this); } public static Vector3 fromEntity(Entity e) { return new Vector3(e.posX, e.posY, e.posZ); } public static Vector3 fromEntityCenter(Entity e) { return new Vector3(e.posX, e.posY - e.getYOffset() + e.height / 2, e.posZ); } public static Vector3 fromTile(TileEntity tile) { return new Vector3(tile.getPos()); } public static Vector3 fromTileCenter(TileEntity tile) { return fromTile(tile).add(0.5); } public static Vector3 fromAxes(double[] da) { return new Vector3(da[2], da[0], da[1]); } public Vector3 set(double d, double d1, double d2) { x = d; y = d1; z = d2; return this; } public Vector3 set(Vector3 vec) { x = vec.x; y = vec.y; z = vec.z; return this; } public double getSide(int side) { switch (side) { case 0: case 1: return y; case 2: case 3: return z; case 4: case 5: return x; } throw new IndexOutOfBoundsException("Switch Falloff"); } public Vector3 setSide(int s, double v) { switch (s) { case 0: case 1: y = v; break; case 2: case 3: z = v; break; case 4: case 5: x = v; break; default: throw new IndexOutOfBoundsException("Switch Falloff"); } return this; } public double dotProduct(Vector3 vec) { double d = vec.x * x + vec.y * y + vec.z * z; if (d > 1 && d < 1.00001) { d = 1; } else if (d < -1 && d > -1.00001) { d = -1; } return d; } public double dotProduct(double d, double d1, double d2) { return d * x + d1 * y + d2 * z; } public Vector3 crossProduct(Vector3 vec) { double d = y * vec.z - z * vec.y; double d1 = z * vec.x - x * vec.z; double d2 = x * vec.y - y * vec.x; x = d; y = d1; z = d2; return this; } public Vector3 add(double d, double d1, double d2) { x += d; y += d1; z += d2; return this; } public Vector3 add(Vector3 vec) { x += vec.x; y += vec.y; z += vec.z; return this; } public Vector3 add(double d) { return add(d, d, d); } public Vector3 sub(Vector3 vec) { return subtract(vec); } public Vector3 subtract(Vector3 vec) { x -= vec.x; y -= vec.y; z -= vec.z; return this; } public Vector3 negate(Vector3 vec) { x = -x; y = -y; z = -z; return this; } public Vector3 multiply(double d) { x *= d; y *= d; z *= d; return this; } public Vector3 multiply(Vector3 f) { x *= f.x; y *= f.y; z *= f.z; return this; } public Vector3 multiply(double fx, double fy, double fz) { x *= fx; y *= fy; z *= fz; return this; } public double mag() { return Math.sqrt(x * x + y * y + z * z); } public double magSquared() { return x * x + y * y + z * z; } public Vector3 normalize() { double d = mag(); if (d != 0) { multiply(1 / d); } return this; } public String toString() { MathContext cont = new MathContext(4, RoundingMode.HALF_UP); return "Vector3(" + new BigDecimal(x, cont) + ", " + new BigDecimal(y, cont) + ", " + new BigDecimal(z, cont) + ")"; } public Vector3 perpendicular() { if (z == 0) { return zCrossProduct(); } return xCrossProduct(); } public Vector3 xCrossProduct() { double d = z; double d1 = -y; x = 0; y = d; z = d1; return this; } public Vector3 zCrossProduct() { double d = y; double d1 = -x; x = d; y = d1; z = 0; return this; } public Vector3 yCrossProduct() { double d = -z; double d1 = x; x = d; y = 0; z = d1; return this; } public Vector3 rotate(double angle, Vector3 axis) { Quat.aroundAxis(axis.copy().normalize(), angle).rotate(this); return this; } public Vector3 rotate(Quat rotator) { rotator.rotate(this); return this; } public Vec3 vec3() { return new Vec3(x, y, z); } public double angle(Vector3 vec) { return Math.acos(copy().normalize().dotProduct(vec.copy().normalize())); } public boolean isZero() { return x == 0 && y == 0 && z == 0; } public boolean isAxial() { return x == 0 ? (y == 0 || z == 0) : (y == 0 && z == 0); } @SideOnly(Side.CLIENT) public Vector3f vector3f() { return new Vector3f((float) x, (float) y, (float) z); } @SideOnly(Side.CLIENT) public Vector4f vector4f() { return new Vector4f((float) x, (float) y, (float) z, 1); } @SideOnly(Side.CLIENT) public void glVertex() { GL11.glVertex3d(x, y, z); } public Vector3 YZintercept(Vector3 end, double px) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; if (dx == 0) { return null; } double d = (px - x) / dx; if (MathHelper.between(-1E-5, d, 1E-5)) { return this; } if (!MathHelper.between(0, d, 1)) { return null; } x = px; y += d * dy; z += d * dz; return this; } public Vector3 XZintercept(Vector3 end, double py) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; if (dy == 0) { return null; } double d = (py - y) / dy; if (MathHelper.between(-1E-5, d, 1E-5)) { return this; } if (!MathHelper.between(0, d, 1)) { return null; } x += d * dx; y = py; z += d * dz; return this; } public Vector3 XYintercept(Vector3 end, double pz) { double dx = end.x - x; double dy = end.y - y; double dz = end.z - z; if (dz == 0) { return null; } double d = (pz - z) / dz; if (MathHelper.between(-1E-5, d, 1E-5)) { return this; } if (!MathHelper.between(0, d, 1)) { return null; } x += d * dx; y += d * dy; z = pz; return this; } public Vector3 negate() { x = -x; y = -y; z = -z; return this; } public Translation translation() { return new Translation(this); } public double scalarProject(Vector3 b) { double l = b.mag(); return l == 0 ? 0 : dotProduct(b) / l; } public Vector3 project(Vector3 b) { double l = b.magSquared(); if (l == 0) { set(0, 0, 0); return this; } double m = dotProduct(b) / l; set(b).multiply(m); return this; } @Override public boolean equals(Object o) { if (!(o instanceof Vector3)) { return false; } Vector3 v = (Vector3) o; return x == v.x && y == v.y && z == v.z; } /** * Equals method with tolerance * * @return true if this is equal to v within +-1E-5 */ public boolean equalsT(Vector3 v) { return MathHelper.between(x - 1E-5, v.x, x + 1E-5) && MathHelper.between(y - 1E-5, v.y, y + 1E-5) && MathHelper.between(z - 1E-5, v.z, z + 1E-5); } public Vector3 apply(Transformation t) { t.apply(this); return this; } public Vector3 $tilde() { return normalize(); } public Vector3 unary_$tilde() { return normalize(); } public Vector3 $plus(Vector3 v) { return add(v); } public Vector3 $minus(Vector3 v) { return subtract(v); } public Vector3 $times(double d) { return multiply(d); } public Vector3 $div(double d) { return multiply(1 / d); } public Vector3 $times(Vector3 v) { return crossProduct(v); } public double $dot$times(Vector3 v) { return dotProduct(v); } }