886 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			886 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.util;
 | |
| 
 | |
| import java.util.Locale;
 | |
| import java.util.UUID;
 | |
| import java.util.function.IntPredicate;
 | |
| import java.util.stream.IntStream;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.core.Vec3i;
 | |
| import net.minecraft.world.phys.AABB;
 | |
| import net.minecraft.world.phys.Vec3;
 | |
| import org.apache.commons.lang3.math.Fraction;
 | |
| import org.apache.commons.lang3.math.NumberUtils;
 | |
| import org.joml.Quaternionf;
 | |
| import org.joml.Vector3f;
 | |
| 
 | |
| public class Mth {
 | |
| 	private static final long UUID_VERSION = 61440L;
 | |
| 	private static final long UUID_VERSION_TYPE_4 = 16384L;
 | |
| 	private static final long UUID_VARIANT = -4611686018427387904L;
 | |
| 	private static final long UUID_VARIANT_2 = Long.MIN_VALUE;
 | |
| 	public static final float PI = (float) Math.PI;
 | |
| 	public static final float HALF_PI = (float) (Math.PI / 2);
 | |
| 	public static final float TWO_PI = (float) (Math.PI * 2);
 | |
| 	public static final float DEG_TO_RAD = (float) (Math.PI / 180.0);
 | |
| 	public static final float RAD_TO_DEG = 180.0F / (float)Math.PI;
 | |
| 	public static final float EPSILON = 1.0E-5F;
 | |
| 	public static final float SQRT_OF_TWO = sqrt(2.0F);
 | |
| 	private static final float SIN_SCALE = 10430.378F;
 | |
| 	public static final Vector3f Y_AXIS = new Vector3f(0.0F, 1.0F, 0.0F);
 | |
| 	public static final Vector3f X_AXIS = new Vector3f(1.0F, 0.0F, 0.0F);
 | |
| 	public static final Vector3f Z_AXIS = new Vector3f(0.0F, 0.0F, 1.0F);
 | |
| 	private static final float[] SIN = Util.make(new float[65536], fs -> {
 | |
| 		for (int ix = 0; ix < fs.length; ix++) {
 | |
| 			fs[ix] = (float)Math.sin(ix * Math.PI * 2.0 / 65536.0);
 | |
| 		}
 | |
| 	});
 | |
| 	private static final RandomSource RANDOM = RandomSource.createThreadSafe();
 | |
| 	/**
 | |
| 	 * Though it looks like an array, this is really more like a mapping. Key (index of this array) is the upper 5 bits of the result of multiplying a 32-bit unsigned integer by the B(2, 5) De Bruijn sequence 0x077CB531. Value (value stored in the array) is the unique index (from the right) of the leftmo
 | |
| 	 */
 | |
| 	private static final int[] MULTIPLY_DE_BRUIJN_BIT_POSITION = new int[]{
 | |
| 		0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
 | |
| 	};
 | |
| 	private static final double ONE_SIXTH = 0.16666666666666666;
 | |
| 	private static final int FRAC_EXP = 8;
 | |
| 	private static final int LUT_SIZE = 257;
 | |
| 	private static final double FRAC_BIAS = Double.longBitsToDouble(4805340802404319232L);
 | |
| 	private static final double[] ASIN_TAB = new double[257];
 | |
| 	private static final double[] COS_TAB = new double[257];
 | |
| 
 | |
| 	/**
 | |
| 	 * sin looked up in a table
 | |
| 	 */
 | |
| 	public static float sin(float value) {
 | |
| 		return SIN[(int)(value * 10430.378F) & 65535];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * cos looked up in the sin table with the appropriate offset
 | |
| 	 */
 | |
| 	public static float cos(float value) {
 | |
| 		return SIN[(int)(value * 10430.378F + 16384.0F) & 65535];
 | |
| 	}
 | |
| 
 | |
| 	public static float sqrt(float value) {
 | |
| 		return (float)Math.sqrt(value);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the greatest integer less than or equal to the float argument}
 | |
| 	 */
 | |
| 	public static int floor(float value) {
 | |
| 		int i = (int)value;
 | |
| 		return value < i ? i - 1 : i;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the greatest integer less than or equal to the double argument}
 | |
| 	 */
 | |
| 	public static int floor(double value) {
 | |
| 		int i = (int)value;
 | |
| 		return value < i ? i - 1 : i;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Long version of floor()
 | |
| 	 */
 | |
| 	public static long lfloor(double value) {
 | |
| 		long l = (long)value;
 | |
| 		return value < l ? l - 1L : l;
 | |
| 	}
 | |
| 
 | |
| 	public static float abs(float value) {
 | |
| 		return Math.abs(value);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the unsigned value of an int}
 | |
| 	 */
 | |
| 	public static int abs(int value) {
 | |
| 		return Math.abs(value);
 | |
| 	}
 | |
| 
 | |
| 	public static int ceil(float value) {
 | |
| 		int i = (int)value;
 | |
| 		return value > i ? i + 1 : i;
 | |
| 	}
 | |
| 
 | |
| 	public static int ceil(double value) {
 | |
| 		int i = (int)value;
 | |
| 		return value > i ? i + 1 : i;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the given value if between the lower and the upper bound. If the value is less than the lower bound, returns the lower bound} If the value is greater than the upper bound, returns the upper bound.
 | |
| 	 * 
 | |
| 	 * @param value The value that is clamped.
 | |
| 	 * @param min The lower bound for the clamp.
 | |
| 	 * @param max The upper bound for the clamp.
 | |
| 	 */
 | |
| 	public static int clamp(int value, int min, int max) {
 | |
| 		return Math.min(Math.max(value, min), max);
 | |
| 	}
 | |
| 
 | |
| 	public static long clamp(long value, long min, long max) {
 | |
| 		return Math.min(Math.max(value, min), max);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the given value if between the lower and the upper bound. If the value is less than the lower bound, returns the lower bound} If the value is greater than the upper bound, returns the upper bound.
 | |
| 	 * 
 | |
| 	 * @param value The value that is clamped.
 | |
| 	 * @param min The lower bound for the clamp.
 | |
| 	 * @param max The upper bound for the clamp.
 | |
| 	 */
 | |
| 	public static float clamp(float value, float min, float max) {
 | |
| 		return value < min ? min : Math.min(value, max);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the given value if between the lower and the upper bound. If the value is less than the lower bound, returns the lower bound} If the value is greater than the upper bound, returns the upper bound.
 | |
| 	 * 
 | |
| 	 * @param value The value that is clamped.
 | |
| 	 * @param min The lower bound for the clamp.
 | |
| 	 * @param max The upper bound for the clamp.
 | |
| 	 */
 | |
| 	public static double clamp(double value, double min, double max) {
 | |
| 		return value < min ? min : Math.min(value, max);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Method for linear interpolation of doubles.
 | |
| 	 * 
 | |
| 	 * @param start Start value for the lerp.
 | |
| 	 * @param end End value for the lerp.
 | |
| 	 * @param delta A value between 0 and 1 that indicates the percentage of the lerp. (0 will give the start value and 1 will give the end value) If the value is not between 0 and 1, it is clamped.
 | |
| 	 */
 | |
| 	public static double clampedLerp(double start, double end, double delta) {
 | |
| 		if (delta < 0.0) {
 | |
| 			return start;
 | |
| 		} else {
 | |
| 			return delta > 1.0 ? end : lerp(delta, start, end);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Method for linear interpolation of floats.
 | |
| 	 * 
 | |
| 	 * @param start Start value for the lerp.
 | |
| 	 * @param end End value for the lerp.
 | |
| 	 * @param delta A value between 0 and 1 that indicates the percentage of the lerp. (0 will give the start value and 1 will give the end value) If the value is not between 0 and 1, it is clamped.
 | |
| 	 */
 | |
| 	public static float clampedLerp(float start, float end, float delta) {
 | |
| 		if (delta < 0.0F) {
 | |
| 			return start;
 | |
| 		} else {
 | |
| 			return delta > 1.0F ? end : lerp(delta, start, end);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the maximum of the absolute value of two numbers}
 | |
| 	 */
 | |
| 	public static double absMax(double x, double y) {
 | |
| 		if (x < 0.0) {
 | |
| 			x = -x;
 | |
| 		}
 | |
| 
 | |
| 		if (y < 0.0) {
 | |
| 			y = -y;
 | |
| 		}
 | |
| 
 | |
| 		return Math.max(x, y);
 | |
| 	}
 | |
| 
 | |
| 	public static int floorDiv(int dividend, int divisor) {
 | |
| 		return Math.floorDiv(dividend, divisor);
 | |
| 	}
 | |
| 
 | |
| 	public static int nextInt(RandomSource random, int minimum, int maximum) {
 | |
| 		return minimum >= maximum ? minimum : random.nextInt(maximum - minimum + 1) + minimum;
 | |
| 	}
 | |
| 
 | |
| 	public static float nextFloat(RandomSource random, float minimum, float maximum) {
 | |
| 		return minimum >= maximum ? minimum : random.nextFloat() * (maximum - minimum) + minimum;
 | |
| 	}
 | |
| 
 | |
| 	public static double nextDouble(RandomSource random, double minimum, double maximum) {
 | |
| 		return minimum >= maximum ? minimum : random.nextDouble() * (maximum - minimum) + minimum;
 | |
| 	}
 | |
| 
 | |
| 	public static boolean equal(float x, float y) {
 | |
| 		return Math.abs(y - x) < 1.0E-5F;
 | |
| 	}
 | |
| 
 | |
| 	public static boolean equal(double x, double y) {
 | |
| 		return Math.abs(y - x) < 1.0E-5F;
 | |
| 	}
 | |
| 
 | |
| 	public static int positiveModulo(int x, int y) {
 | |
| 		return Math.floorMod(x, y);
 | |
| 	}
 | |
| 
 | |
| 	public static float positiveModulo(float numerator, float denominator) {
 | |
| 		return (numerator % denominator + denominator) % denominator;
 | |
| 	}
 | |
| 
 | |
| 	public static double positiveModulo(double numerator, double denominator) {
 | |
| 		return (numerator % denominator + denominator) % denominator;
 | |
| 	}
 | |
| 
 | |
| 	public static boolean isMultipleOf(int number, int multiple) {
 | |
| 		return number % multiple == 0;
 | |
| 	}
 | |
| 
 | |
| 	public static byte packDegrees(float degrees) {
 | |
| 		return (byte)floor(degrees * 256.0F / 360.0F);
 | |
| 	}
 | |
| 
 | |
| 	public static float unpackDegrees(byte degrees) {
 | |
| 		return degrees * 360 / 256.0F;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Adjust the angle so that its value is in the range [-180;180)
 | |
| 	 */
 | |
| 	public static int wrapDegrees(int angle) {
 | |
| 		int i = angle % 360;
 | |
| 		if (i >= 180) {
 | |
| 			i -= 360;
 | |
| 		}
 | |
| 
 | |
| 		if (i < -180) {
 | |
| 			i += 360;
 | |
| 		}
 | |
| 
 | |
| 		return i;
 | |
| 	}
 | |
| 
 | |
| 	public static float wrapDegrees(long angle) {
 | |
| 		float f = (float)(angle % 360L);
 | |
| 		if (f >= 180.0F) {
 | |
| 			f -= 360.0F;
 | |
| 		}
 | |
| 
 | |
| 		if (f < -180.0F) {
 | |
| 			f += 360.0F;
 | |
| 		}
 | |
| 
 | |
| 		return f;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * The angle is reduced to an angle between -180 and +180 by mod, and a 360 check.
 | |
| 	 */
 | |
| 	public static float wrapDegrees(float value) {
 | |
| 		float f = value % 360.0F;
 | |
| 		if (f >= 180.0F) {
 | |
| 			f -= 360.0F;
 | |
| 		}
 | |
| 
 | |
| 		if (f < -180.0F) {
 | |
| 			f += 360.0F;
 | |
| 		}
 | |
| 
 | |
| 		return f;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * The angle is reduced to an angle between -180 and +180 by mod, and a 360 check.
 | |
| 	 */
 | |
| 	public static double wrapDegrees(double value) {
 | |
| 		double d = value % 360.0;
 | |
| 		if (d >= 180.0) {
 | |
| 			d -= 360.0;
 | |
| 		}
 | |
| 
 | |
| 		if (d < -180.0) {
 | |
| 			d += 360.0;
 | |
| 		}
 | |
| 
 | |
| 		return d;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the difference between two angles in degrees}
 | |
| 	 */
 | |
| 	public static float degreesDifference(float start, float end) {
 | |
| 		return wrapDegrees(end - start);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the absolute of the difference between two angles in degrees}
 | |
| 	 */
 | |
| 	public static float degreesDifferenceAbs(float start, float end) {
 | |
| 		return abs(degreesDifference(start, end));
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Takes a rotation and compares it to another rotation.
 | |
| 	 * If the difference is greater than a given maximum, clamps the original rotation between to have at most the given difference to the actual rotation.
 | |
| 	 * This is used to match the body rotation of entities to their head rotation.
 | |
| 	 * @return The new value for the rotation that was adjusted
 | |
| 	 */
 | |
| 	public static float rotateIfNecessary(float rotationToAdjust, float actualRotation, float maxDifference) {
 | |
| 		float f = degreesDifference(rotationToAdjust, actualRotation);
 | |
| 		float g = clamp(f, -maxDifference, maxDifference);
 | |
| 		return actualRotation - g;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Changes value by stepSize towards the limit and returns the result.
 | |
| 	 * If value is smaller than limit, the result will never be bigger than limit.
 | |
| 	 * If value is bigger than limit, the result will never be smaller than limit.
 | |
| 	 */
 | |
| 	public static float approach(float value, float limit, float stepSize) {
 | |
| 		stepSize = abs(stepSize);
 | |
| 		return value < limit ? clamp(value + stepSize, value, limit) : clamp(value - stepSize, limit, value);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Changes the angle by stepSize towards the limit in the direction where the distance is smaller.
 | |
| 	 * {@see #approach(float, float, float)}
 | |
| 	 */
 | |
| 	public static float approachDegrees(float angle, float limit, float stepSize) {
 | |
| 		float f = degreesDifference(angle, limit);
 | |
| 		return approach(angle, angle + f, stepSize);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Parses the string as an integer or returns the second parameter if it fails.
 | |
| 	 */
 | |
| 	public static int getInt(String value, int defaultValue) {
 | |
| 		return NumberUtils.toInt(value, defaultValue);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * {@return the input value rounded up to the next highest power of two}
 | |
| 	 */
 | |
| 	public static int smallestEncompassingPowerOfTwo(int value) {
 | |
| 		int i = value - 1;
 | |
| 		i |= i >> 1;
 | |
| 		i |= i >> 2;
 | |
| 		i |= i >> 4;
 | |
| 		i |= i >> 8;
 | |
| 		i |= i >> 16;
 | |
| 		return i + 1;
 | |
| 	}
 | |
| 
 | |
| 	public static int smallestSquareSide(int itemCount) {
 | |
| 		if (itemCount < 0) {
 | |
| 			throw new IllegalArgumentException("itemCount must be greater than or equal to zero");
 | |
| 		} else {
 | |
| 			return ceil(Math.sqrt(itemCount));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Is the given value a power of two?  (1, 2, 4, 8, 16, ...)
 | |
| 	 */
 | |
| 	public static boolean isPowerOfTwo(int value) {
 | |
| 		return value != 0 && (value & value - 1) == 0;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Uses a B(2, 5) De Bruijn sequence and a lookup table to efficiently calculate the log-base-two of the given value. Optimized for cases where the input value is a power-of-two. If the input value is not a power-of-two, then subtract 1 from the return value.
 | |
| 	 */
 | |
| 	public static int ceillog2(int value) {
 | |
| 		value = isPowerOfTwo(value) ? value : smallestEncompassingPowerOfTwo(value);
 | |
| 		return MULTIPLY_DE_BRUIJN_BIT_POSITION[(int)(value * 125613361L >> 27) & 31];
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Efficiently calculates the floor of the base-2 log of an integer value.  This is effectively the index of the highest bit that is set.  For example, if the number in binary is 0...100101, this will return 5.
 | |
| 	 */
 | |
| 	public static int log2(int value) {
 | |
| 		return ceillog2(value) - (isPowerOfTwo(value) ? 0 : 1);
 | |
| 	}
 | |
| 
 | |
| 	public static float frac(float number) {
 | |
| 		return number - floor(number);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets the decimal portion of the given double. For instance, {@code frac(5.5)} returns {@code .5}.
 | |
| 	 */
 | |
| 	public static double frac(double number) {
 | |
| 		return number - lfloor(number);
 | |
| 	}
 | |
| 
 | |
| 	@Deprecated
 | |
| 	public static long getSeed(Vec3i pos) {
 | |
| 		return getSeed(pos.getX(), pos.getY(), pos.getZ());
 | |
| 	}
 | |
| 
 | |
| 	@Deprecated
 | |
| 	public static long getSeed(int x, int y, int z) {
 | |
| 		long l = x * 3129871 ^ z * 116129781L ^ y;
 | |
| 		l = l * l * 42317861L + l * 11L;
 | |
| 		return l >> 16;
 | |
| 	}
 | |
| 
 | |
| 	public static UUID createInsecureUUID(RandomSource random) {
 | |
| 		long l = random.nextLong() & -61441L | 16384L;
 | |
| 		long m = random.nextLong() & 4611686018427387903L | Long.MIN_VALUE;
 | |
| 		return new UUID(l, m);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Generates a random UUID using the shared random
 | |
| 	 */
 | |
| 	public static UUID createInsecureUUID() {
 | |
| 		return createInsecureUUID(RANDOM);
 | |
| 	}
 | |
| 
 | |
| 	public static double inverseLerp(double delta, double start, double end) {
 | |
| 		return (delta - start) / (end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static float inverseLerp(float delta, float start, float end) {
 | |
| 		return (delta - start) / (end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static boolean rayIntersectsAABB(Vec3 start, Vec3 end, AABB boundingBox) {
 | |
| 		double d = (boundingBox.minX + boundingBox.maxX) * 0.5;
 | |
| 		double e = (boundingBox.maxX - boundingBox.minX) * 0.5;
 | |
| 		double f = start.x - d;
 | |
| 		if (Math.abs(f) > e && f * end.x >= 0.0) {
 | |
| 			return false;
 | |
| 		} else {
 | |
| 			double g = (boundingBox.minY + boundingBox.maxY) * 0.5;
 | |
| 			double h = (boundingBox.maxY - boundingBox.minY) * 0.5;
 | |
| 			double i = start.y - g;
 | |
| 			if (Math.abs(i) > h && i * end.y >= 0.0) {
 | |
| 				return false;
 | |
| 			} else {
 | |
| 				double j = (boundingBox.minZ + boundingBox.maxZ) * 0.5;
 | |
| 				double k = (boundingBox.maxZ - boundingBox.minZ) * 0.5;
 | |
| 				double l = start.z - j;
 | |
| 				if (Math.abs(l) > k && l * end.z >= 0.0) {
 | |
| 					return false;
 | |
| 				} else {
 | |
| 					double m = Math.abs(end.x);
 | |
| 					double n = Math.abs(end.y);
 | |
| 					double o = Math.abs(end.z);
 | |
| 					double p = end.y * l - end.z * i;
 | |
| 					if (Math.abs(p) > h * o + k * n) {
 | |
| 						return false;
 | |
| 					} else {
 | |
| 						p = end.z * f - end.x * l;
 | |
| 						if (Math.abs(p) > e * o + k * m) {
 | |
| 							return false;
 | |
| 						} else {
 | |
| 							p = end.x * i - end.y * f;
 | |
| 							return Math.abs(p) < e * n + h * m;
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static double atan2(double y, double x) {
 | |
| 		double d = x * x + y * y;
 | |
| 		if (Double.isNaN(d)) {
 | |
| 			return Double.NaN;
 | |
| 		} else {
 | |
| 			boolean bl = y < 0.0;
 | |
| 			if (bl) {
 | |
| 				y = -y;
 | |
| 			}
 | |
| 
 | |
| 			boolean bl2 = x < 0.0;
 | |
| 			if (bl2) {
 | |
| 				x = -x;
 | |
| 			}
 | |
| 
 | |
| 			boolean bl3 = y > x;
 | |
| 			if (bl3) {
 | |
| 				double e = x;
 | |
| 				x = y;
 | |
| 				y = e;
 | |
| 			}
 | |
| 
 | |
| 			double e = fastInvSqrt(d);
 | |
| 			x *= e;
 | |
| 			y *= e;
 | |
| 			double f = FRAC_BIAS + y;
 | |
| 			int i = (int)Double.doubleToRawLongBits(f);
 | |
| 			double g = ASIN_TAB[i];
 | |
| 			double h = COS_TAB[i];
 | |
| 			double j = f - FRAC_BIAS;
 | |
| 			double k = y * h - x * j;
 | |
| 			double l = (6.0 + k * k) * k * 0.16666666666666666;
 | |
| 			double m = g + l;
 | |
| 			if (bl3) {
 | |
| 				m = (Math.PI / 2) - m;
 | |
| 			}
 | |
| 
 | |
| 			if (bl2) {
 | |
| 				m = Math.PI - m;
 | |
| 			}
 | |
| 
 | |
| 			if (bl) {
 | |
| 				m = -m;
 | |
| 			}
 | |
| 
 | |
| 			return m;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static float invSqrt(float number) {
 | |
| 		return org.joml.Math.invsqrt(number);
 | |
| 	}
 | |
| 
 | |
| 	public static double invSqrt(double number) {
 | |
| 		return org.joml.Math.invsqrt(number);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Computes 1/sqrt(n) using <a href="https://en.wikipedia.org/wiki/Fast_inverse_square_root">the fast inverse square root</a> with a constant of 0x5FE6EB50C7B537AA.
 | |
| 	 */
 | |
| 	@Deprecated
 | |
| 	public static double fastInvSqrt(double number) {
 | |
| 		double d = 0.5 * number;
 | |
| 		long l = Double.doubleToRawLongBits(number);
 | |
| 		l = 6910469410427058090L - (l >> 1);
 | |
| 		number = Double.longBitsToDouble(l);
 | |
| 		return number * (1.5 - d * number * number);
 | |
| 	}
 | |
| 
 | |
| 	public static float fastInvCubeRoot(float number) {
 | |
| 		int i = Float.floatToIntBits(number);
 | |
| 		i = 1419967116 - i / 3;
 | |
| 		float f = Float.intBitsToFloat(i);
 | |
| 		f = 0.6666667F * f + 1.0F / (3.0F * f * f * number);
 | |
| 		return 0.6666667F * f + 1.0F / (3.0F * f * f * number);
 | |
| 	}
 | |
| 
 | |
| 	public static int hsvToRgb(float hue, float saturation, float value) {
 | |
| 		return hsvToArgb(hue, saturation, value, 0);
 | |
| 	}
 | |
| 
 | |
| 	public static int hsvToArgb(float hue, float saturation, float value, int alpha) {
 | |
| 		int i = (int)(hue * 6.0F) % 6;
 | |
| 		float f = hue * 6.0F - i;
 | |
| 		float g = value * (1.0F - saturation);
 | |
| 		float h = value * (1.0F - f * saturation);
 | |
| 		float j = value * (1.0F - (1.0F - f) * saturation);
 | |
| 		float k;
 | |
| 		float l;
 | |
| 		float m;
 | |
| 		switch (i) {
 | |
| 			case 0:
 | |
| 				k = value;
 | |
| 				l = j;
 | |
| 				m = g;
 | |
| 				break;
 | |
| 			case 1:
 | |
| 				k = h;
 | |
| 				l = value;
 | |
| 				m = g;
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				k = g;
 | |
| 				l = value;
 | |
| 				m = j;
 | |
| 				break;
 | |
| 			case 3:
 | |
| 				k = g;
 | |
| 				l = h;
 | |
| 				m = value;
 | |
| 				break;
 | |
| 			case 4:
 | |
| 				k = j;
 | |
| 				l = g;
 | |
| 				m = value;
 | |
| 				break;
 | |
| 			case 5:
 | |
| 				k = value;
 | |
| 				l = g;
 | |
| 				m = h;
 | |
| 				break;
 | |
| 			default:
 | |
| 				throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + hue + ", " + saturation + ", " + value);
 | |
| 		}
 | |
| 
 | |
| 		return ARGB.color(alpha, clamp((int)(k * 255.0F), 0, 255), clamp((int)(l * 255.0F), 0, 255), clamp((int)(m * 255.0F), 0, 255));
 | |
| 	}
 | |
| 
 | |
| 	public static int murmurHash3Mixer(int input) {
 | |
| 		input ^= input >>> 16;
 | |
| 		input *= -2048144789;
 | |
| 		input ^= input >>> 13;
 | |
| 		input *= -1028477387;
 | |
| 		return input ^ input >>> 16;
 | |
| 	}
 | |
| 
 | |
| 	public static int binarySearch(int min, int max, IntPredicate isTargetBeforeOrAt) {
 | |
| 		int i = max - min;
 | |
| 
 | |
| 		while (i > 0) {
 | |
| 			int j = i / 2;
 | |
| 			int k = min + j;
 | |
| 			if (isTargetBeforeOrAt.test(k)) {
 | |
| 				i = j;
 | |
| 			} else {
 | |
| 				min = k + 1;
 | |
| 				i -= j + 1;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return min;
 | |
| 	}
 | |
| 
 | |
| 	public static int lerpInt(float delta, int start, int end) {
 | |
| 		return start + floor(delta * (end - start));
 | |
| 	}
 | |
| 
 | |
| 	public static int lerpDiscrete(float delta, int start, int end) {
 | |
| 		int i = end - start;
 | |
| 		return start + floor(delta * (i - 1)) + (delta > 0.0F ? 1 : 0);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Method for linear interpolation of floats
 | |
| 	 * 
 | |
| 	 * @param delta A value usually between 0 and 1 that indicates the percentage of the lerp. (0 will give the start value and 1 will give the end value)
 | |
| 	 * @param start Start value for the lerp
 | |
| 	 * @param end End value for the lerp
 | |
| 	 */
 | |
| 	public static float lerp(float delta, float start, float end) {
 | |
| 		return start + delta * (end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static Vec3 lerp(double delta, Vec3 start, Vec3 end) {
 | |
| 		return new Vec3(lerp(delta, start.x, end.x), lerp(delta, start.y, end.y), lerp(delta, start.z, end.z));
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Method for linear interpolation of doubles
 | |
| 	 * 
 | |
| 	 * @param delta A value usually between 0 and 1 that indicates the percentage of the lerp. (0 will give the start value and 1 will give the end value)
 | |
| 	 * @param start Start value for the lerp
 | |
| 	 * @param end End value for the lerp
 | |
| 	 */
 | |
| 	public static double lerp(double delta, double start, double end) {
 | |
| 		return start + delta * (end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static double lerp2(double delta1, double delta2, double start1, double end1, double start2, double end2) {
 | |
| 		return lerp(delta2, lerp(delta1, start1, end1), lerp(delta1, start2, end2));
 | |
| 	}
 | |
| 
 | |
| 	public static double lerp3(
 | |
| 		double delta1, double delta2, double delta3, double start1, double end1, double start2, double end2, double start3, double end3, double start4, double end4
 | |
| 	) {
 | |
| 		return lerp(delta3, lerp2(delta1, delta2, start1, end1, start2, end2), lerp2(delta1, delta2, start3, end3, start4, end4));
 | |
| 	}
 | |
| 
 | |
| 	public static float catmullrom(float delta, float controlPoint1, float controlPoint2, float controlPoint3, float controlPoint4) {
 | |
| 		return 0.5F
 | |
| 			* (
 | |
| 				2.0F * controlPoint2
 | |
| 					+ (controlPoint3 - controlPoint1) * delta
 | |
| 					+ (2.0F * controlPoint1 - 5.0F * controlPoint2 + 4.0F * controlPoint3 - controlPoint4) * delta * delta
 | |
| 					+ (3.0F * controlPoint2 - controlPoint1 - 3.0F * controlPoint3 + controlPoint4) * delta * delta * delta
 | |
| 			);
 | |
| 	}
 | |
| 
 | |
| 	public static double smoothstep(double input) {
 | |
| 		return input * input * input * (input * (input * 6.0 - 15.0) + 10.0);
 | |
| 	}
 | |
| 
 | |
| 	public static double smoothstepDerivative(double input) {
 | |
| 		return 30.0 * input * input * (input - 1.0) * (input - 1.0);
 | |
| 	}
 | |
| 
 | |
| 	public static int sign(double x) {
 | |
| 		if (x == 0.0) {
 | |
| 			return 0;
 | |
| 		} else {
 | |
| 			return x > 0.0 ? 1 : -1;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Linearly interpolates an angle between the start between the start and end values given as degrees.
 | |
| 	 * 
 | |
| 	 * @param delta A value between 0 and 1 that indicates the percentage of the lerp. (0 will give the start value and 1 will give the end value)
 | |
| 	 */
 | |
| 	public static float rotLerp(float delta, float start, float end) {
 | |
| 		return start + delta * wrapDegrees(end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static double rotLerp(double delta, double start, double end) {
 | |
| 		return start + delta * wrapDegrees(end - start);
 | |
| 	}
 | |
| 
 | |
| 	public static float rotLerpRad(float delta, float start, float end) {
 | |
| 		float f = end - start;
 | |
| 
 | |
| 		while (f < (float) -Math.PI) {
 | |
| 			f += (float) (Math.PI * 2);
 | |
| 		}
 | |
| 
 | |
| 		while (f >= (float) Math.PI) {
 | |
| 			f -= (float) (Math.PI * 2);
 | |
| 		}
 | |
| 
 | |
| 		return start + delta * f;
 | |
| 	}
 | |
| 
 | |
| 	public static float triangleWave(float input, float period) {
 | |
| 		return (Math.abs(input % period - period * 0.5F) - period * 0.25F) / (period * 0.25F);
 | |
| 	}
 | |
| 
 | |
| 	public static float square(float value) {
 | |
| 		return value * value;
 | |
| 	}
 | |
| 
 | |
| 	public static double square(double value) {
 | |
| 		return value * value;
 | |
| 	}
 | |
| 
 | |
| 	public static int square(int value) {
 | |
| 		return value * value;
 | |
| 	}
 | |
| 
 | |
| 	public static long square(long value) {
 | |
| 		return value * value;
 | |
| 	}
 | |
| 
 | |
| 	public static double clampedMap(double input, double inputMin, double inputMax, double outputMin, double outputMax) {
 | |
| 		return clampedLerp(outputMin, outputMax, inverseLerp(input, inputMin, inputMax));
 | |
| 	}
 | |
| 
 | |
| 	public static float clampedMap(float input, float inputMin, float inputMax, float outputMin, float outputMax) {
 | |
| 		return clampedLerp(outputMin, outputMax, inverseLerp(input, inputMin, inputMax));
 | |
| 	}
 | |
| 
 | |
| 	public static double map(double input, double inputMin, double inputMax, double outputMin, double outputMax) {
 | |
| 		return lerp(inverseLerp(input, inputMin, inputMax), outputMin, outputMax);
 | |
| 	}
 | |
| 
 | |
| 	public static float map(float input, float inputMin, float inputMax, float outputMin, float outputMax) {
 | |
| 		return lerp(inverseLerp(input, inputMin, inputMax), outputMin, outputMax);
 | |
| 	}
 | |
| 
 | |
| 	public static double wobble(double input) {
 | |
| 		return input + (2.0 * RandomSource.create(floor(input * 3000.0)).nextDouble() - 1.0) * 1.0E-7 / 2.0;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Rounds the given value up to a multiple of factor.
 | |
| 	 * @return The smallest integer multiple of factor that is greater than or equal to the value
 | |
| 	 */
 | |
| 	public static int roundToward(int value, int factor) {
 | |
| 		return positiveCeilDiv(value, factor) * factor;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the smallest (closest to negative infinity) int value that is greater than or equal to the algebraic quotient.
 | |
| 	 * @see java.lang.Math#floorDiv(int, int)
 | |
| 	 */
 | |
| 	public static int positiveCeilDiv(int x, int y) {
 | |
| 		return -Math.floorDiv(-x, y);
 | |
| 	}
 | |
| 
 | |
| 	public static int randomBetweenInclusive(RandomSource random, int minInclusive, int maxInclusive) {
 | |
| 		return random.nextInt(maxInclusive - minInclusive + 1) + minInclusive;
 | |
| 	}
 | |
| 
 | |
| 	public static float randomBetween(RandomSource random, float minInclusive, float maxExclusive) {
 | |
| 		return random.nextFloat() * (maxExclusive - minInclusive) + minInclusive;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Generates a value from a normal distribution with the given mean and deviation.
 | |
| 	 */
 | |
| 	public static float normal(RandomSource random, float mean, float deviation) {
 | |
| 		return mean + (float)random.nextGaussian() * deviation;
 | |
| 	}
 | |
| 
 | |
| 	public static double lengthSquared(double xDistance, double yDistance) {
 | |
| 		return xDistance * xDistance + yDistance * yDistance;
 | |
| 	}
 | |
| 
 | |
| 	public static double length(double xDistance, double yDistance) {
 | |
| 		return Math.sqrt(lengthSquared(xDistance, yDistance));
 | |
| 	}
 | |
| 
 | |
| 	public static float length(float xDistance, float yDistance) {
 | |
| 		return (float)Math.sqrt(lengthSquared(xDistance, yDistance));
 | |
| 	}
 | |
| 
 | |
| 	public static double lengthSquared(double xDistance, double yDistance, double zDistance) {
 | |
| 		return xDistance * xDistance + yDistance * yDistance + zDistance * zDistance;
 | |
| 	}
 | |
| 
 | |
| 	public static double length(double xDistance, double yDistance, double zDistance) {
 | |
| 		return Math.sqrt(lengthSquared(xDistance, yDistance, zDistance));
 | |
| 	}
 | |
| 
 | |
| 	public static float lengthSquared(float xDistance, float yDistance, float zDistance) {
 | |
| 		return xDistance * xDistance + yDistance * yDistance + zDistance * zDistance;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets the value closest to zero that is not closer to zero than the given value and is a multiple of the factor.
 | |
| 	 */
 | |
| 	public static int quantize(double value, int factor) {
 | |
| 		return floor(value / factor) * factor;
 | |
| 	}
 | |
| 
 | |
| 	public static IntStream outFromOrigin(int input, int lowerBound, int upperBound) {
 | |
| 		return outFromOrigin(input, lowerBound, upperBound, 1);
 | |
| 	}
 | |
| 
 | |
| 	public static IntStream outFromOrigin(int input, int lowerBound, int upperBound, int steps) {
 | |
| 		if (lowerBound > upperBound) {
 | |
| 			throw new IllegalArgumentException(String.format(Locale.ROOT, "upperbound %d expected to be > lowerBound %d", upperBound, lowerBound));
 | |
| 		} else if (steps < 1) {
 | |
| 			throw new IllegalArgumentException(String.format(Locale.ROOT, "steps expected to be >= 1, was %d", steps));
 | |
| 		} else {
 | |
| 			return input >= lowerBound && input <= upperBound ? IntStream.iterate(input, l -> {
 | |
| 				int m = Math.abs(input - l);
 | |
| 				return input - m >= lowerBound || input + m <= upperBound;
 | |
| 			}, m -> {
 | |
| 				boolean bl = m <= input;
 | |
| 				int n = Math.abs(input - m);
 | |
| 				boolean bl2 = input + n + steps <= upperBound;
 | |
| 				if (!bl || !bl2) {
 | |
| 					int o = input - n - (bl ? steps : 0);
 | |
| 					if (o >= lowerBound) {
 | |
| 						return o;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return input + n + steps;
 | |
| 			}) : IntStream.empty();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static Quaternionf rotationAroundAxis(Vector3f axis, Quaternionf cameraOrientation, Quaternionf output) {
 | |
| 		float f = axis.dot(cameraOrientation.x, cameraOrientation.y, cameraOrientation.z);
 | |
| 		return output.set(axis.x * f, axis.y * f, axis.z * f, cameraOrientation.w).normalize();
 | |
| 	}
 | |
| 
 | |
| 	public static int mulAndTruncate(Fraction fraction, int factor) {
 | |
| 		return fraction.getNumerator() * factor / fraction.getDenominator();
 | |
| 	}
 | |
| 
 | |
| 	public static float easeInOutSine(float value) {
 | |
| 		return -(cos((float) Math.PI * value) - 1.0F) / 2.0F;
 | |
| 	}
 | |
| 
 | |
| 	static {
 | |
| 		for (int i = 0; i < 257; i++) {
 | |
| 			double d = i / 256.0;
 | |
| 			double e = Math.asin(d);
 | |
| 			COS_TAB[i] = Math.cos(e);
 | |
| 			ASIN_TAB[i] = e;
 | |
| 		}
 | |
| 	}
 | |
| }
 |