Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import org.bukkit.Material;
- import org.bukkit.util.Vector;
- import java.util.Random;
- /**
- * Utility and fast math functions.
- * <p>
- * Thanks to Riven on JavaGaming.org for the basis of sin/cos/atan2/floor/ceil.
- *
- * @author Nathan Sweet
- */
- public final class MathUtils {
- /**
- * Value of a nanosecond.
- */
- static public final float nanoToSec = 1 / 1000000000f;
- /**
- * Default float rounding tolerance.
- */
- static public final float FLOAT_ROUNDING_ERROR = 0.000001f; // 32 bits
- /**
- * PI constant, or the ratio of
- * a circle's circumference to its diameter.
- */
- static public final float PI = 3.1415926535897932384626f;
- /**
- * Twice PI constant.
- */
- static public final float PI2 = PI * 2;
- /**
- * Square root of 3.
- */
- static public final float SQRT_3 = 1.73205080757f;
- /**
- * e constant, which represents
- * the unique positive number a
- * such that the graph of the
- * function y = ax has unit
- * slope at x = 0.
- */
- static public final float E = 2.71828182846f;
- static private final int SIN_BITS = 14; // 16KB. Adjust for accuracy.
- static private final int SIN_MASK = ~(-1 << SIN_BITS);
- static private final int SIN_COUNT = SIN_MASK + 1;
- /**
- * Represents the number of radians in a circle. (2*π)
- */
- static private final float radFull = PI2;
- /**
- * Amount of degrees in a circle.
- */
- static private final float degFull = 360;
- static private final float radToIndex = SIN_COUNT / radFull;
- static private final float degToIndex = SIN_COUNT / degFull;
- /**
- * multiply by this to convert from radians to degrees
- */
- static public final float radiansToDegrees = 180f / PI;
- /**
- * Copy, alias of radiansToDegrees.
- */
- static public final float radDeg = radiansToDegrees;
- /**
- * multiply by this to convert from degrees to radians
- */
- static public final float degreesToRadians = PI / 180;
- /**
- * Copy, alias of degreesToRadians.
- */
- static public final float degRad = degreesToRadians;
- static private class Sin {
- static final float[] table = new float[SIN_COUNT];
- static {
- for (int i = 0; i < SIN_COUNT; i++)
- table[i] = (float) Math.sin((i + 0.5f) / SIN_COUNT * radFull);
- for (int i = 0; i < 360; i += 90)
- table[(int) (i * degToIndex) & SIN_MASK] = (float) Math.sin(i * degreesToRadians);
- }
- }
- /**
- * Returns the sine in radians from a lookup table.
- */
- static public final float sin(float radians) {
- return Sin.table[(int) (radians * radToIndex) & SIN_MASK];
- }
- /**
- * Returns the cosine in radians from a lookup table.
- */
- static public final float cos(float radians) {
- return Sin.table[(int) ((radians + PI / 2) * radToIndex) & SIN_MASK];
- }
- /**
- * Returns the sine in radians from a lookup table.
- */
- static public final float sinDeg(float degrees) {
- return Sin.table[(int) (degrees * degToIndex) & SIN_MASK];
- }
- /**
- * Returns the cosine in radians from a lookup table.
- */
- static public final float cosDeg(float degrees) {
- return Sin.table[(int) ((degrees + 90) * degToIndex) & SIN_MASK];
- }
- static private final int ATAN2_BITS = 7; // Adjust for accuracy.
- static private final int ATAN2_BITS2 = ATAN2_BITS << 1;
- static private final int ATAN2_MASK = ~(-1 << ATAN2_BITS2);
- static private final int ATAN2_COUNT = ATAN2_MASK + 1;
- static final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT);
- static private final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1);
- static private class Atan2 {
- static final float[] table = new float[ATAN2_COUNT];
- static {
- for (int i = 0; i < ATAN2_DIM; i++)
- for (int j = 0; j < ATAN2_DIM; j++) {
- float x0 = (float) i / ATAN2_DIM;
- float y0 = (float) j / ATAN2_DIM;
- table[j * ATAN2_DIM + i] = (float) Math.atan2(y0, x0);
- }
- }
- }
- /**
- * Returns atan2 in radians from a lookup table.
- */
- static public final float atan2(float y, float x) {
- float add, mul;
- if (x < 0) {
- if (y < 0) {
- y = -y;
- mul = 1;
- } else
- mul = -1;
- x = -x;
- add = -PI;
- } else {
- if (y < 0) {
- y = -y;
- mul = -1;
- } else
- mul = 1;
- add = 0;
- }
- float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);
- if (invDiv == Float.POSITIVE_INFINITY) {
- return ((float) Math.atan2(y, x) + add) * mul;
- }
- int xi = (int) (x * invDiv);
- int yi = (int) (y * invDiv);
- return (Atan2.table[yi * ATAN2_DIM + xi] + add) * mul;
- }
- static public Random random = new Random();
- /**
- * Returns a random number between 0 (inclusive) and the specified value (inclusive).
- */
- static public final int random(int range) {
- return random.nextInt(range + 1);
- }
- /**
- * Returns a random number between start (inclusive) and end (inclusive).
- */
- static public final int random(int start, int end) {
- return start + random.nextInt(end - start + 1);
- }
- /**
- * Returns a random boolean value.
- */
- static public final boolean randomBoolean() {
- return random.nextBoolean();
- }
- /**
- * Returns true if a random value between 0 and 1 is less than the specified value.
- */
- static public final boolean randomBoolean(float chance) {
- return MathUtils.random() < chance;
- }
- /**
- * Returns random number between 0.0 (inclusive) and 1.0 (exclusive).
- */
- static public final float random() {
- return random.nextFloat();
- }
- /**
- * Returns a random number between 0 (inclusive) and the specified value (exclusive).
- */
- static public final float random(float range) {
- return random.nextFloat() * range;
- }
- /**
- * Returns a random number between start (inclusive) and end (exclusive).
- */
- static public final float random(float start, float end) {
- return start + random.nextFloat() * (end - start);
- }
- /**
- * Returns the next power of two. Returns the specified value if the value is already a power of two.
- */
- static public int nextPowerOfTwo(int value) {
- if (value == 0)
- return 1;
- value--;
- value |= value >> 1;
- value |= value >> 2;
- value |= value >> 4;
- value |= value >> 8;
- value |= value >> 16;
- return value + 1;
- }
- /**
- * Checks if value is a power of two. (2, 4, 8, 16, 32, 64, ...)
- * @param value The value to check.
- * @return {@code true} if value is a power of two, {@code false} otherwise.
- */
- static public boolean isPowerOfTwo(int value) {
- return value != 0 && (value & value - 1) == 0;
- }
- static public int clamp(int value, int min, int max) {
- if (value < min)
- return min;
- if (value > max)
- return max;
- return value;
- }
- static public short clamp(short value, short min, short max) {
- if (value < min)
- return min;
- if (value > max)
- return max;
- return value;
- }
- static public float clamp(float value, float min, float max) {
- if (value < min)
- return min;
- if (value > max)
- return max;
- return value;
- }
- static private final int BIG_ENOUGH_INT = 16 * 1024;
- static private final double BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT;
- static private final double CEIL = 0.9999999;
- static private final double BIG_ENOUGH_CEIL = 16384.999999999996;
- static private final double BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5f;
- /**
- * Returns the largest integer less than or equal to the specified float. This method will only properly floor floats from
- * -(2^14) to (Float.MAX_VALUE - 2^14).
- */
- static public int floor(float x) {
- return (int) (x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT;
- }
- /**
- * Returns the largest integer less than or equal to the specified float. This method will only properly floor floats that are
- * positive. Note this method simply casts the float to int.
- */
- static public int floorPositive(float x) {
- return (int) x;
- }
- /**
- * Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats from
- * -(2^14) to (Float.MAX_VALUE - 2^14).
- */
- static public int ceil(float x) {
- return (int) (x + BIG_ENOUGH_CEIL) - BIG_ENOUGH_INT;
- }
- /**
- * Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats that
- * are positive.
- */
- static public int ceilPositive(float x) {
- return (int) (x + CEIL);
- }
- /**
- * Returns the closest integer to the specified float. This method will only properly round floats from -(2^14) to
- * (Float.MAX_VALUE - 2^14).
- */
- static public int round(float x) {
- return (int) (x + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT;
- }
- /**
- * Returns the closest integer to the specified float. This method will only properly round floats that are positive.
- */
- static public int roundPositive(float x) {
- return (int) (x + 0.5f);
- }
- /**
- * Returns true if the value is zero (using the default tolerance as upper bound)
- */
- static public boolean isZero(float value) {
- return Math.abs(value) <= FLOAT_ROUNDING_ERROR;
- }
- /**
- * Returns true if the value is zero.
- *
- * @param tolerance represent an upper bound below which the value is considered zero.
- */
- static public boolean isZero(float value, float tolerance) {
- return Math.abs(value) <= tolerance;
- }
- /**
- * Returns true if a is nearly equal to b. The function uses the default floating error tolerance.
- *
- * @param a the first value.
- * @param b the second value.
- */
- static public boolean isEqual(float a, float b) {
- return Math.abs(a - b) <= FLOAT_ROUNDING_ERROR;
- }
- /**
- * Returns true if a is nearly equal to b.
- *
- * @param a the first value.
- * @param b the second value.
- * @param tolerance represent an upper bound below which the two values are considered equal.
- */
- static public boolean isEqual(float a, float b, float tolerance) {
- return Math.abs(a - b) <= tolerance;
- }
- // Vector Utils part.
- /**
- * Gets a random vector.
- *
- * @return a random vector.
- */
- public static Vector getRandomVector() {
- double x, y, z;
- x = random.nextDouble() * 2 - 1;
- y = random.nextDouble() * 2 - 1;
- z = random.nextDouble() * 2 - 1;
- return new Vector(x, y, z).normalize();
- }
- /**
- * Gets a random circle vector. (y = 0)
- *
- * @return A random circle vector (y = 0)
- */
- public static Vector getRandomCircleVector() {
- double rnd, x, z;
- rnd = random.nextDouble() * 2 * Math.PI;
- x = Math.cos(rnd);
- z = Math.sin(rnd);
- return new Vector(x, 0, z);
- }
- /**
- * Gets a random material of a material array.
- *
- * @param materials The array of materials.
- * @return A random element from the given array.
- */
- public static Material getRandomMaterial(Material[] materials) {
- return materials[random.nextInt(materials.length)];
- }
- /**
- * Gets a random angle in radians.
- *
- * @return a random angle in radians.
- */
- public static double getRandomAngle() {
- return random.nextDouble() * 2 * Math.PI;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement