Advertisement
iSach

MathUtils.

Dec 2nd, 2015
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.24 KB | None | 0 0
  1. import org.bukkit.Material;
  2. import org.bukkit.util.Vector;
  3.  
  4. import java.util.Random;
  5.  
  6. /**
  7. * Utility and fast math functions.
  8. * <p>
  9. * Thanks to Riven on JavaGaming.org for the basis of sin/cos/atan2/floor/ceil.
  10. *
  11. * @author Nathan Sweet
  12. */
  13. public final class MathUtils {
  14.  
  15. /**
  16. * Value of a nanosecond.
  17. */
  18. static public final float nanoToSec = 1 / 1000000000f;
  19.  
  20. /**
  21. * Default float rounding tolerance.
  22. */
  23. static public final float FLOAT_ROUNDING_ERROR = 0.000001f; // 32 bits
  24.  
  25. /**
  26. * PI constant, or the ratio of
  27. * a circle's circumference to its diameter.
  28. */
  29. static public final float PI = 3.1415926535897932384626f;
  30.  
  31. /**
  32. * Twice PI constant.
  33. */
  34. static public final float PI2 = PI * 2;
  35.  
  36. /**
  37. * Square root of 3.
  38. */
  39. static public final float SQRT_3 = 1.73205080757f;
  40.  
  41. /**
  42. * e constant, which represents
  43. * the unique positive number a
  44. * such that the graph of the
  45. * function y = ax has unit
  46. * slope at x = 0.
  47. */
  48. static public final float E = 2.71828182846f;
  49.  
  50. static private final int SIN_BITS = 14; // 16KB. Adjust for accuracy.
  51.  
  52. static private final int SIN_MASK = ~(-1 << SIN_BITS);
  53.  
  54. static private final int SIN_COUNT = SIN_MASK + 1;
  55.  
  56. /**
  57. * Represents the number of radians in a circle. (2*π)
  58. */
  59. static private final float radFull = PI2;
  60.  
  61. /**
  62. * Amount of degrees in a circle.
  63. */
  64. static private final float degFull = 360;
  65.  
  66. static private final float radToIndex = SIN_COUNT / radFull;
  67.  
  68. static private final float degToIndex = SIN_COUNT / degFull;
  69.  
  70. /**
  71. * multiply by this to convert from radians to degrees
  72. */
  73. static public final float radiansToDegrees = 180f / PI;
  74.  
  75. /**
  76. * Copy, alias of radiansToDegrees.
  77. */
  78. static public final float radDeg = radiansToDegrees;
  79. /**
  80. * multiply by this to convert from degrees to radians
  81. */
  82. static public final float degreesToRadians = PI / 180;
  83.  
  84. /**
  85. * Copy, alias of degreesToRadians.
  86. */
  87. static public final float degRad = degreesToRadians;
  88.  
  89. static private class Sin {
  90.  
  91. static final float[] table = new float[SIN_COUNT];
  92.  
  93. static {
  94. for (int i = 0; i < SIN_COUNT; i++)
  95. table[i] = (float) Math.sin((i + 0.5f) / SIN_COUNT * radFull);
  96. for (int i = 0; i < 360; i += 90)
  97. table[(int) (i * degToIndex) & SIN_MASK] = (float) Math.sin(i * degreesToRadians);
  98. }
  99. }
  100.  
  101. /**
  102. * Returns the sine in radians from a lookup table.
  103. */
  104. static public final float sin(float radians) {
  105. return Sin.table[(int) (radians * radToIndex) & SIN_MASK];
  106. }
  107.  
  108. /**
  109. * Returns the cosine in radians from a lookup table.
  110. */
  111. static public final float cos(float radians) {
  112. return Sin.table[(int) ((radians + PI / 2) * radToIndex) & SIN_MASK];
  113. }
  114.  
  115. /**
  116. * Returns the sine in radians from a lookup table.
  117. */
  118. static public final float sinDeg(float degrees) {
  119. return Sin.table[(int) (degrees * degToIndex) & SIN_MASK];
  120. }
  121.  
  122. /**
  123. * Returns the cosine in radians from a lookup table.
  124. */
  125. static public final float cosDeg(float degrees) {
  126. return Sin.table[(int) ((degrees + 90) * degToIndex) & SIN_MASK];
  127. }
  128.  
  129. static private final int ATAN2_BITS = 7; // Adjust for accuracy.
  130.  
  131. static private final int ATAN2_BITS2 = ATAN2_BITS << 1;
  132.  
  133. static private final int ATAN2_MASK = ~(-1 << ATAN2_BITS2);
  134.  
  135. static private final int ATAN2_COUNT = ATAN2_MASK + 1;
  136.  
  137. static final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT);
  138.  
  139. static private final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1);
  140.  
  141. static private class Atan2 {
  142.  
  143. static final float[] table = new float[ATAN2_COUNT];
  144.  
  145. static {
  146. for (int i = 0; i < ATAN2_DIM; i++)
  147. for (int j = 0; j < ATAN2_DIM; j++) {
  148. float x0 = (float) i / ATAN2_DIM;
  149. float y0 = (float) j / ATAN2_DIM;
  150. table[j * ATAN2_DIM + i] = (float) Math.atan2(y0, x0);
  151. }
  152. }
  153. }
  154.  
  155. /**
  156. * Returns atan2 in radians from a lookup table.
  157. */
  158. static public final float atan2(float y, float x) {
  159. float add, mul;
  160. if (x < 0) {
  161. if (y < 0) {
  162. y = -y;
  163. mul = 1;
  164. } else
  165. mul = -1;
  166. x = -x;
  167. add = -PI;
  168. } else {
  169. if (y < 0) {
  170. y = -y;
  171. mul = -1;
  172. } else
  173. mul = 1;
  174. add = 0;
  175. }
  176. float invDiv = 1 / ((x < y ? y : x) * INV_ATAN2_DIM_MINUS_1);
  177.  
  178. if (invDiv == Float.POSITIVE_INFINITY) {
  179. return ((float) Math.atan2(y, x) + add) * mul;
  180. }
  181.  
  182. int xi = (int) (x * invDiv);
  183. int yi = (int) (y * invDiv);
  184. return (Atan2.table[yi * ATAN2_DIM + xi] + add) * mul;
  185. }
  186.  
  187. static public Random random = new Random();
  188.  
  189. /**
  190. * Returns a random number between 0 (inclusive) and the specified value (inclusive).
  191. */
  192. static public final int random(int range) {
  193. return random.nextInt(range + 1);
  194. }
  195.  
  196. /**
  197. * Returns a random number between start (inclusive) and end (inclusive).
  198. */
  199. static public final int random(int start, int end) {
  200. return start + random.nextInt(end - start + 1);
  201. }
  202.  
  203. /**
  204. * Returns a random boolean value.
  205. */
  206. static public final boolean randomBoolean() {
  207. return random.nextBoolean();
  208. }
  209.  
  210. /**
  211. * Returns true if a random value between 0 and 1 is less than the specified value.
  212. */
  213. static public final boolean randomBoolean(float chance) {
  214. return MathUtils.random() < chance;
  215. }
  216.  
  217. /**
  218. * Returns random number between 0.0 (inclusive) and 1.0 (exclusive).
  219. */
  220. static public final float random() {
  221. return random.nextFloat();
  222. }
  223.  
  224. /**
  225. * Returns a random number between 0 (inclusive) and the specified value (exclusive).
  226. */
  227. static public final float random(float range) {
  228. return random.nextFloat() * range;
  229. }
  230.  
  231. /**
  232. * Returns a random number between start (inclusive) and end (exclusive).
  233. */
  234. static public final float random(float start, float end) {
  235. return start + random.nextFloat() * (end - start);
  236. }
  237.  
  238.  
  239. /**
  240. * Returns the next power of two. Returns the specified value if the value is already a power of two.
  241. */
  242. static public int nextPowerOfTwo(int value) {
  243. if (value == 0)
  244. return 1;
  245. value--;
  246. value |= value >> 1;
  247. value |= value >> 2;
  248. value |= value >> 4;
  249. value |= value >> 8;
  250. value |= value >> 16;
  251. return value + 1;
  252. }
  253.  
  254. /**
  255. * Checks if value is a power of two. (2, 4, 8, 16, 32, 64, ...)
  256. * @param value The value to check.
  257. * @return {@code true} if value is a power of two, {@code false} otherwise.
  258. */
  259. static public boolean isPowerOfTwo(int value) {
  260. return value != 0 && (value & value - 1) == 0;
  261. }
  262.  
  263. static public int clamp(int value, int min, int max) {
  264. if (value < min)
  265. return min;
  266. if (value > max)
  267. return max;
  268. return value;
  269. }
  270.  
  271. static public short clamp(short value, short min, short max) {
  272. if (value < min)
  273. return min;
  274. if (value > max)
  275. return max;
  276. return value;
  277. }
  278.  
  279. static public float clamp(float value, float min, float max) {
  280. if (value < min)
  281. return min;
  282. if (value > max)
  283. return max;
  284. return value;
  285. }
  286.  
  287. static private final int BIG_ENOUGH_INT = 16 * 1024;
  288.  
  289. static private final double BIG_ENOUGH_FLOOR = BIG_ENOUGH_INT;
  290.  
  291. static private final double CEIL = 0.9999999;
  292.  
  293. static private final double BIG_ENOUGH_CEIL = 16384.999999999996;
  294.  
  295. static private final double BIG_ENOUGH_ROUND = BIG_ENOUGH_INT + 0.5f;
  296.  
  297. /**
  298. * Returns the largest integer less than or equal to the specified float. This method will only properly floor floats from
  299. * -(2^14) to (Float.MAX_VALUE - 2^14).
  300. */
  301. static public int floor(float x) {
  302. return (int) (x + BIG_ENOUGH_FLOOR) - BIG_ENOUGH_INT;
  303. }
  304.  
  305. /**
  306. * Returns the largest integer less than or equal to the specified float. This method will only properly floor floats that are
  307. * positive. Note this method simply casts the float to int.
  308. */
  309. static public int floorPositive(float x) {
  310. return (int) x;
  311. }
  312.  
  313. /**
  314. * Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats from
  315. * -(2^14) to (Float.MAX_VALUE - 2^14).
  316. */
  317. static public int ceil(float x) {
  318. return (int) (x + BIG_ENOUGH_CEIL) - BIG_ENOUGH_INT;
  319. }
  320.  
  321. /**
  322. * Returns the smallest integer greater than or equal to the specified float. This method will only properly ceil floats that
  323. * are positive.
  324. */
  325. static public int ceilPositive(float x) {
  326. return (int) (x + CEIL);
  327. }
  328.  
  329. /**
  330. * Returns the closest integer to the specified float. This method will only properly round floats from -(2^14) to
  331. * (Float.MAX_VALUE - 2^14).
  332. */
  333. static public int round(float x) {
  334. return (int) (x + BIG_ENOUGH_ROUND) - BIG_ENOUGH_INT;
  335. }
  336.  
  337. /**
  338. * Returns the closest integer to the specified float. This method will only properly round floats that are positive.
  339. */
  340. static public int roundPositive(float x) {
  341. return (int) (x + 0.5f);
  342. }
  343.  
  344. /**
  345. * Returns true if the value is zero (using the default tolerance as upper bound)
  346. */
  347. static public boolean isZero(float value) {
  348. return Math.abs(value) <= FLOAT_ROUNDING_ERROR;
  349. }
  350.  
  351. /**
  352. * Returns true if the value is zero.
  353. *
  354. * @param tolerance represent an upper bound below which the value is considered zero.
  355. */
  356. static public boolean isZero(float value, float tolerance) {
  357. return Math.abs(value) <= tolerance;
  358. }
  359.  
  360. /**
  361. * Returns true if a is nearly equal to b. The function uses the default floating error tolerance.
  362. *
  363. * @param a the first value.
  364. * @param b the second value.
  365. */
  366. static public boolean isEqual(float a, float b) {
  367. return Math.abs(a - b) <= FLOAT_ROUNDING_ERROR;
  368. }
  369.  
  370. /**
  371. * Returns true if a is nearly equal to b.
  372. *
  373. * @param a the first value.
  374. * @param b the second value.
  375. * @param tolerance represent an upper bound below which the two values are considered equal.
  376. */
  377. static public boolean isEqual(float a, float b, float tolerance) {
  378. return Math.abs(a - b) <= tolerance;
  379. }
  380.  
  381. // Vector Utils part.
  382.  
  383. /**
  384. * Gets a random vector.
  385. *
  386. * @return a random vector.
  387. */
  388. public static Vector getRandomVector() {
  389. double x, y, z;
  390. x = random.nextDouble() * 2 - 1;
  391. y = random.nextDouble() * 2 - 1;
  392. z = random.nextDouble() * 2 - 1;
  393.  
  394. return new Vector(x, y, z).normalize();
  395. }
  396.  
  397. /**
  398. * Gets a random circle vector. (y = 0)
  399. *
  400. * @return A random circle vector (y = 0)
  401. */
  402. public static Vector getRandomCircleVector() {
  403. double rnd, x, z;
  404. rnd = random.nextDouble() * 2 * Math.PI;
  405. x = Math.cos(rnd);
  406. z = Math.sin(rnd);
  407.  
  408. return new Vector(x, 0, z);
  409. }
  410.  
  411. /**
  412. * Gets a random material of a material array.
  413. *
  414. * @param materials The array of materials.
  415. * @return A random element from the given array.
  416. */
  417. public static Material getRandomMaterial(Material[] materials) {
  418. return materials[random.nextInt(materials.length)];
  419. }
  420.  
  421. /**
  422. * Gets a random angle in radians.
  423. *
  424. * @return a random angle in radians.
  425. */
  426. public static double getRandomAngle() {
  427. return random.nextDouble() * 2 * Math.PI;
  428. }
  429.  
  430. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement