FastMath.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. /*
  2. * Copyright (c) 2009-2010 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.math;
  33. import java.util.Random;
  34. /**
  35. * <code>FastMath</code> provides 'fast' math approximations and float equivalents of Math
  36. * functions. These are all used as static values and functions.
  37. *
  38. * @author Various
  39. * @version $Id: FastMath.java,v 1.45 2007/08/26 08:44:20 irrisor Exp $
  40. */
  41. final public class FastMath {
  42. private FastMath() {
  43. }
  44. /** A "close to zero" double epsilon value for use*/
  45. public static final double DBL_EPSILON = 2.220446049250313E-16d;
  46. /** A "close to zero" float epsilon value for use*/
  47. public static final float FLT_EPSILON = 1.1920928955078125E-7f;
  48. /** A "close to zero" float epsilon value for use*/
  49. public static final float ZERO_TOLERANCE = 0.0001f;
  50. public static final float ONE_THIRD = 1f / 3f;
  51. /** The value PI as a float. (180 degrees) */
  52. public static final float PI = (float) Math.PI;
  53. /** The value 2PI as a float. (360 degrees) */
  54. public static final float TWO_PI = 2.0f * PI;
  55. /** The value PI/2 as a float. (90 degrees) */
  56. public static final float HALF_PI = 0.5f * PI;
  57. /** The value PI/4 as a float. (45 degrees) */
  58. public static final float QUARTER_PI = 0.25f * PI;
  59. /** The value 1/PI as a float. */
  60. public static final float INV_PI = 1.0f / PI;
  61. /** The value 1/(2PI) as a float. */
  62. public static final float INV_TWO_PI = 1.0f / TWO_PI;
  63. /** A value to multiply a degree value by, to convert it to radians. */
  64. public static final float DEG_TO_RAD = PI / 180.0f;
  65. /** A value to multiply a radian value by, to convert it to degrees. */
  66. public static final float RAD_TO_DEG = 180.0f / PI;
  67. /** A precreated random object for random numbers. */
  68. public static final Random rand = new Random(System.currentTimeMillis());
  69. /**
  70. * Returns true if the number is a power of 2 (2,4,8,16...)
  71. *
  72. * A good implementation found on the Java boards. note: a number is a power
  73. * of two if and only if it is the smallest number with that number of
  74. * significant bits. Therefore, if you subtract 1, you know that the new
  75. * number will have fewer bits, so ANDing the original number with anything
  76. * less than it will give 0.
  77. *
  78. * @param number
  79. * The number to test.
  80. * @return True if it is a power of two.
  81. */
  82. public static boolean isPowerOfTwo(int number) {
  83. return (number > 0) && (number & (number - 1)) == 0;
  84. }
  85. public static int nearestPowerOfTwo(int number) {
  86. return (int) Math.pow(2, Math.ceil(Math.log(number) / Math.log(2)));
  87. }
  88. /**
  89. * Linear interpolation from startValue to endValue by the given percent.
  90. * Basically: ((1 - percent) * startValue) + (percent * endValue)
  91. *
  92. * @param scale
  93. * scale value to use. if 1, use endValue, if 0, use startValue.
  94. * @param startValue
  95. * Begining value. 0% of f
  96. * @param endValue
  97. * ending value. 100% of f
  98. * @return The interpolated value between startValue and endValue.
  99. */
  100. public static float interpolateLinear(float scale, float startValue, float endValue) {
  101. if (startValue == endValue) {
  102. return startValue;
  103. }
  104. if (scale <= 0f) {
  105. return startValue;
  106. }
  107. if (scale >= 1f) {
  108. return endValue;
  109. }
  110. return ((1f - scale) * startValue) + (scale * endValue);
  111. }
  112. /**
  113. * Linear interpolation from startValue to endValue by the given percent.
  114. * Basically: ((1 - percent) * startValue) + (percent * endValue)
  115. *
  116. * @param scale
  117. * scale value to use. if 1, use endValue, if 0, use startValue.
  118. * @param startValue
  119. * Begining value. 0% of f
  120. * @param endValue
  121. * ending value. 100% of f
  122. * @param store a vector3f to store the result
  123. * @return The interpolated value between startValue and endValue.
  124. */
  125. public static Vector3f interpolateLinear(float scale, Vector3f startValue, Vector3f endValue, Vector3f store) {
  126. if (store == null) {
  127. store = new Vector3f();
  128. }
  129. store.x = interpolateLinear(scale, startValue.x, endValue.x);
  130. store.y = interpolateLinear(scale, startValue.y, endValue.y);
  131. store.z = interpolateLinear(scale, startValue.z, endValue.z);
  132. return store;
  133. }
  134. /**
  135. * Linear interpolation from startValue to endValue by the given percent.
  136. * Basically: ((1 - percent) * startValue) + (percent * endValue)
  137. *
  138. * @param scale
  139. * scale value to use. if 1, use endValue, if 0, use startValue.
  140. * @param startValue
  141. * Begining value. 0% of f
  142. * @param endValue
  143. * ending value. 100% of f
  144. * @return The interpolated value between startValue and endValue.
  145. */
  146. public static Vector3f interpolateLinear(float scale, Vector3f startValue, Vector3f endValue) {
  147. return interpolateLinear(scale, startValue, endValue, null);
  148. }
  149. /**
  150. * Linear extrapolation from startValue to endValue by the given scale.
  151. * if scale is between 0 and 1 this method returns the same result as interpolateLinear
  152. * if the scale is over 1 the value is linearly extrapolated.
  153. * Note that the end value is the value for a scale of 1.
  154. * @param scale the scale for extrapolation
  155. * @param startValue the starting value (scale = 0)
  156. * @param endValue the end value (scale = 1)
  157. * @return an extrapolation for the given parameters
  158. */
  159. public static float extrapolateLinear(float scale, float startValue, float endValue) {
  160. // if (scale <= 0f) {
  161. // return startValue;
  162. // }
  163. return ((1f - scale) * startValue) + (scale * endValue);
  164. }
  165. /**
  166. * Linear extrapolation from startValue to endValue by the given scale.
  167. * if scale is between 0 and 1 this method returns the same result as interpolateLinear
  168. * if the scale is over 1 the value is linearly extrapolated.
  169. * Note that the end value is the value for a scale of 1.
  170. * @param scale the scale for extrapolation
  171. * @param startValue the starting value (scale = 0)
  172. * @param endValue the end value (scale = 1)
  173. * @param store an initialized vector to store the return value
  174. * @return an extrapolation for the given parameters
  175. */
  176. public static Vector3f extrapolateLinear(float scale, Vector3f startValue, Vector3f endValue, Vector3f store) {
  177. if (store == null) {
  178. store = new Vector3f();
  179. }
  180. // if (scale <= 1f) {
  181. // return interpolateLinear(scale, startValue, endValue, store);
  182. // }
  183. store.x = extrapolateLinear(scale, startValue.x, endValue.x);
  184. store.y = extrapolateLinear(scale, startValue.y, endValue.y);
  185. store.z = extrapolateLinear(scale, startValue.z, endValue.z);
  186. return store;
  187. }
  188. /**
  189. * Linear extrapolation from startValue to endValue by the given scale.
  190. * if scale is between 0 and 1 this method returns the same result as interpolateLinear
  191. * if the scale is over 1 the value is linearly extrapolated.
  192. * Note that the end value is the value for a scale of 1.
  193. * @param scale the scale for extrapolation
  194. * @param startValue the starting value (scale = 0)
  195. * @param endValue the end value (scale = 1)
  196. * @return an extrapolation for the given parameters
  197. */
  198. public static Vector3f extrapolateLinear(float scale, Vector3f startValue, Vector3f endValue) {
  199. return extrapolateLinear(scale, startValue, endValue, null);
  200. }
  201. /**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
  202. * here is the interpolation matrix
  203. * m = [ 0.0 1.0 0.0 0.0 ]
  204. * [-T 0.0 T 0.0 ]
  205. * [ 2T T-3 3-2T -T ]
  206. * [-T 2-T T-2 T ]
  207. * where T is the curve tension
  208. * the result is a value between p1 and p2, t=0 for p1, t=1 for p2
  209. * @param u value from 0 to 1
  210. * @param T The tension of the curve
  211. * @param p0 control point 0
  212. * @param p1 control point 1
  213. * @param p2 control point 2
  214. * @param p3 control point 3
  215. * @return catmull-Rom interpolation
  216. */
  217. public static float interpolateCatmullRom(float u, float T, float p0, float p1, float p2, float p3) {
  218. float c1, c2, c3, c4;
  219. c1 = p1;
  220. c2 = -1.0f * T * p0 + T * p2;
  221. c3 = 2 * T * p0 + (T - 3) * p1 + (3 - 2 * T) * p2 + -T * p3;
  222. c4 = -T * p0 + (2 - T) * p1 + (T - 2) * p2 + T * p3;
  223. return (float) (((c4 * u + c3) * u + c2) * u + c1);
  224. }
  225. /**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
  226. * here is the interpolation matrix
  227. * m = [ 0.0 1.0 0.0 0.0 ]
  228. * [-T 0.0 T 0.0 ]
  229. * [ 2T T-3 3-2T -T ]
  230. * [-T 2-T T-2 T ]
  231. * where T is the tension of the curve
  232. * the result is a value between p1 and p2, t=0 for p1, t=1 for p2
  233. * @param u value from 0 to 1
  234. * @param T The tension of the curve
  235. * @param p0 control point 0
  236. * @param p1 control point 1
  237. * @param p2 control point 2
  238. * @param p3 control point 3
  239. * @param store a Vector3f to store the result
  240. * @return catmull-Rom interpolation
  241. */
  242. public static Vector3f interpolateCatmullRom(float u, float T, Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3, Vector3f store) {
  243. if (store == null) {
  244. store = new Vector3f();
  245. }
  246. store.x = interpolateCatmullRom(u, T, p0.x, p1.x, p2.x, p3.x);
  247. store.y = interpolateCatmullRom(u, T, p0.y, p1.y, p2.y, p3.y);
  248. store.z = interpolateCatmullRom(u, T, p0.z, p1.z, p2.z, p3.z);
  249. return store;
  250. }
  251. /**Interpolate a spline between at least 4 control points following the Catmull-Rom equation.
  252. * here is the interpolation matrix
  253. * m = [ 0.0 1.0 0.0 0.0 ]
  254. * [-T 0.0 T 0.0 ]
  255. * [ 2T T-3 3-2T -T ]
  256. * [-T 2-T T-2 T ]
  257. * where T is the tension of the curve
  258. * the result is a value between p1 and p2, t=0 for p1, t=1 for p2
  259. * @param u value from 0 to 1
  260. * @param T The tension of the curve
  261. * @param p0 control point 0
  262. * @param p1 control point 1
  263. * @param p2 control point 2
  264. * @param p3 control point 3
  265. * @return catmull-Rom interpolation
  266. */
  267. public static Vector3f interpolateCatmullRom(float u, float T, Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3) {
  268. return interpolateCatmullRom(u, T, p0, p1, p2, p3, null);
  269. }
  270. /**Interpolate a spline between at least 4 control points following the Bezier equation.
  271. * here is the interpolation matrix
  272. * m = [ -1.0 3.0 -3.0 1.0 ]
  273. * [ 3.0 -6.0 3.0 0.0 ]
  274. * [ -3.0 3.0 0.0 0.0 ]
  275. * [ 1.0 0.0 0.0 0.0 ]
  276. * where T is the curve tension
  277. * the result is a value between p1 and p3, t=0 for p1, t=1 for p3
  278. * @param u value from 0 to 1
  279. * @param p0 control point 0
  280. * @param p1 control point 1
  281. * @param p2 control point 2
  282. * @param p3 control point 3
  283. * @return Bezier interpolation
  284. */
  285. public static float interpolateBezier(float u, float p0, float p1, float p2, float p3) {
  286. float oneMinusU = 1.0f - u;
  287. float oneMinusU2 = oneMinusU * oneMinusU;
  288. float u2 = u * u;
  289. return p0 * oneMinusU2 * oneMinusU
  290. + 3.0f * p1 * u * oneMinusU2
  291. + 3.0f * p2 * u2 * oneMinusU
  292. + p3 * u2 * u;
  293. }
  294. /**Interpolate a spline between at least 4 control points following the Bezier equation.
  295. * here is the interpolation matrix
  296. * m = [ -1.0 3.0 -3.0 1.0 ]
  297. * [ 3.0 -6.0 3.0 0.0 ]
  298. * [ -3.0 3.0 0.0 0.0 ]
  299. * [ 1.0 0.0 0.0 0.0 ]
  300. * where T is the tension of the curve
  301. * the result is a value between p1 and p3, t=0 for p1, t=1 for p3
  302. * @param u value from 0 to 1
  303. * @param p0 control point 0
  304. * @param p1 control point 1
  305. * @param p2 control point 2
  306. * @param p3 control point 3
  307. * @param store a Vector3f to store the result
  308. * @return Bezier interpolation
  309. */
  310. public static Vector3f interpolateBezier(float u, Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3, Vector3f store) {
  311. if (store == null) {
  312. store = new Vector3f();
  313. }
  314. store.x = interpolateBezier(u, p0.x, p1.x, p2.x, p3.x);
  315. store.y = interpolateBezier(u, p0.y, p1.y, p2.y, p3.y);
  316. store.z = interpolateBezier(u, p0.z, p1.z, p2.z, p3.z);
  317. return store;
  318. }
  319. /**Interpolate a spline between at least 4 control points following the Bezier equation.
  320. * here is the interpolation matrix
  321. * m = [ -1.0 3.0 -3.0 1.0 ]
  322. * [ 3.0 -6.0 3.0 0.0 ]
  323. * [ -3.0 3.0 0.0 0.0 ]
  324. * [ 1.0 0.0 0.0 0.0 ]
  325. * where T is the tension of the curve
  326. * the result is a value between p1 and p3, t=0 for p1, t=1 for p3
  327. * @param u value from 0 to 1
  328. * @param p0 control point 0
  329. * @param p1 control point 1
  330. * @param p2 control point 2
  331. * @param p3 control point 3
  332. * @return Bezier interpolation
  333. */
  334. public static Vector3f interpolateBezier(float u, Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3) {
  335. return interpolateBezier(u, p0, p1, p2, p3, null);
  336. }
  337. /**
  338. * Compute the lenght on a catmull rom spline between control point 1 and 2
  339. * @param p0 control point 0
  340. * @param p1 control point 1
  341. * @param p2 control point 2
  342. * @param p3 control point 3
  343. * @param startRange the starting range on the segment (use 0)
  344. * @param endRange the end range on the segment (use 1)
  345. * @param curveTension the curve tension
  346. * @return the length of the segment
  347. */
  348. public static float getCatmullRomP1toP2Length(Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3, float startRange, float endRange, float curveTension) {
  349. float epsilon = 0.001f;
  350. float middleValue = (startRange + endRange) * 0.5f;
  351. Vector3f start = p1.clone();
  352. if (startRange != 0) {
  353. FastMath.interpolateCatmullRom(startRange, curveTension, p0, p1, p2, p3, start);
  354. }
  355. Vector3f end = p2.clone();
  356. if (endRange != 1) {
  357. FastMath.interpolateCatmullRom(endRange, curveTension, p0, p1, p2, p3, end);
  358. }
  359. Vector3f middle = FastMath.interpolateCatmullRom(middleValue, curveTension, p0, p1, p2, p3);
  360. float l = end.subtract(start).length();
  361. float l1 = middle.subtract(start).length();
  362. float l2 = end.subtract(middle).length();
  363. float len = l1 + l2;
  364. if (l + epsilon < len) {
  365. l1 = getCatmullRomP1toP2Length(p0, p1, p2, p3, startRange, middleValue, curveTension);
  366. l2 = getCatmullRomP1toP2Length(p0, p1, p2, p3, middleValue, endRange, curveTension);
  367. }
  368. l = l1 + l2;
  369. return l;
  370. }
  371. /**
  372. * Compute the lenght on a bezier spline between control point 1 and 2
  373. * @param p0 control point 0
  374. * @param p1 control point 1
  375. * @param p2 control point 2
  376. * @param p3 control point 3
  377. * @return the length of the segment
  378. */
  379. public static float getBezierP1toP2Length(Vector3f p0, Vector3f p1, Vector3f p2, Vector3f p3) {
  380. float delta = 0.02f, t = 0.0f, result = 0.0f;
  381. Vector3f v1 = p0.clone(), v2 = new Vector3f();
  382. while (t <= 1.0f) {
  383. FastMath.interpolateBezier(t, p0, p1, p2, p3, v2);
  384. result += v1.subtractLocal(v2).length();
  385. v1.set(v2);
  386. t += delta;
  387. }
  388. return result;
  389. }
  390. /**
  391. * Returns the arc cosine of an angle given in radians.<br>
  392. * Special cases:
  393. * <ul><li>If fValue is smaller than -1, then the result is PI.
  394. * <li>If the argument is greater than 1, then the result is 0.</ul>
  395. * @param fValue The angle, in radians.
  396. * @return fValue's acos
  397. * @see java.lang.Math#acos(double)
  398. */
  399. public static float acos(float fValue) {
  400. if (-1.0f < fValue) {
  401. if (fValue < 1.0f) {
  402. return (float) Math.acos(fValue);
  403. }
  404. return 0.0f;
  405. }
  406. return PI;
  407. }
  408. /**
  409. * Returns the arc sine of an angle given in radians.<br>
  410. * Special cases:
  411. * <ul><li>If fValue is smaller than -1, then the result is -HALF_PI.
  412. * <li>If the argument is greater than 1, then the result is HALF_PI.</ul>
  413. * @param fValue The angle, in radians.
  414. * @return fValue's asin
  415. * @see java.lang.Math#asin(double)
  416. */
  417. public static float asin(float fValue) {
  418. if (-1.0f < fValue) {
  419. if (fValue < 1.0f) {
  420. return (float) Math.asin(fValue);
  421. }
  422. return HALF_PI;
  423. }
  424. return -HALF_PI;
  425. }
  426. /**
  427. * Returns the arc tangent of an angle given in radians.<br>
  428. * @param fValue The angle, in radians.
  429. * @return fValue's atan
  430. * @see java.lang.Math#atan(double)
  431. */
  432. public static float atan(float fValue) {
  433. return (float) Math.atan(fValue);
  434. }
  435. /**
  436. * A direct call to Math.atan2.
  437. * @param fY
  438. * @param fX
  439. * @return Math.atan2(fY,fX)
  440. * @see java.lang.Math#atan2(double, double)
  441. */
  442. public static float atan2(float fY, float fX) {
  443. return (float) Math.atan2(fY, fX);
  444. }
  445. /**
  446. * Rounds a fValue up. A call to Math.ceil
  447. * @param fValue The value.
  448. * @return The fValue rounded up
  449. * @see java.lang.Math#ceil(double)
  450. */
  451. public static float ceil(float fValue) {
  452. return (float) Math.ceil(fValue);
  453. }
  454. /**
  455. * Fast Trig functions for x86. This forces the trig functiosn to stay
  456. * within the safe area on the x86 processor (-45 degrees to +45 degrees)
  457. * The results may be very slightly off from what the Math and StrictMath
  458. * trig functions give due to rounding in the angle reduction but it will be
  459. * very very close.
  460. *
  461. * note: code from wiki posting on java.net by jeffpk
  462. */
  463. public static float reduceSinAngle(float radians) {
  464. radians %= TWO_PI; // put us in -2PI to +2PI space
  465. if (Math.abs(radians) > PI) { // put us in -PI to +PI space
  466. radians = radians - (TWO_PI);
  467. }
  468. if (Math.abs(radians) > HALF_PI) {// put us in -PI/2 to +PI/2 space
  469. radians = PI - radians;
  470. }
  471. return radians;
  472. }
  473. /**
  474. * Returns sine of a value.
  475. *
  476. * note: code from wiki posting on java.net by jeffpk
  477. *
  478. * @param fValue
  479. * The value to sine, in radians.
  480. * @return The sine of fValue.
  481. * @see java.lang.Math#sin(double)
  482. */
  483. public static float sin2(float fValue) {
  484. fValue = reduceSinAngle(fValue); // limits angle to between -PI/2 and +PI/2
  485. if (Math.abs(fValue) <= Math.PI / 4) {
  486. return (float) Math.sin(fValue);
  487. }
  488. return (float) Math.cos(Math.PI / 2 - fValue);
  489. }
  490. /**
  491. * Returns cos of a value.
  492. *
  493. * @param fValue
  494. * The value to cosine, in radians.
  495. * @return The cosine of fValue.
  496. * @see java.lang.Math#cos(double)
  497. */
  498. public static float cos2(float fValue) {
  499. return sin2(fValue + HALF_PI);
  500. }
  501. public static float cos(float v) {
  502. return (float) Math.cos(v);
  503. }
  504. public static float sin(float v) {
  505. return (float) Math.sin(v);
  506. }
  507. /**
  508. * Returns E^fValue
  509. * @param fValue Value to raise to a power.
  510. * @return The value E^fValue
  511. * @see java.lang.Math#exp(double)
  512. */
  513. public static float exp(float fValue) {
  514. return (float) Math.exp(fValue);
  515. }
  516. /**
  517. * Returns Absolute value of a float.
  518. * @param fValue The value to abs.
  519. * @return The abs of the value.
  520. * @see java.lang.Math#abs(float)
  521. */
  522. public static float abs(float fValue) {
  523. if (fValue < 0) {
  524. return -fValue;
  525. }
  526. return fValue;
  527. }
  528. /**
  529. * Returns a number rounded down.
  530. * @param fValue The value to round
  531. * @return The given number rounded down
  532. * @see java.lang.Math#floor(double)
  533. */
  534. public static float floor(float fValue) {
  535. return (float) Math.floor(fValue);
  536. }
  537. /**
  538. * Returns 1/sqrt(fValue)
  539. * @param fValue The value to process.
  540. * @return 1/sqrt(fValue)
  541. * @see java.lang.Math#sqrt(double)
  542. */
  543. public static float invSqrt(float fValue) {
  544. return (float) (1.0f / Math.sqrt(fValue));
  545. }
  546. public static float fastInvSqrt(float x) {
  547. float xhalf = 0.5f * x;
  548. int i = Float.floatToIntBits(x); // get bits for floating value
  549. i = 0x5f375a86 - (i >> 1); // gives initial guess y0
  550. x = Float.intBitsToFloat(i); // convert bits back to float
  551. x = x * (1.5f - xhalf * x * x); // Newton step, repeating increases accuracy
  552. return x;
  553. }
  554. /**
  555. * Returns the log base E of a value.
  556. * @param fValue The value to log.
  557. * @return The log of fValue base E
  558. * @see java.lang.Math#log(double)
  559. */
  560. public static float log(float fValue) {
  561. return (float) Math.log(fValue);
  562. }
  563. /**
  564. * Returns the logarithm of value with given base, calculated as log(value)/log(base),
  565. * so that pow(base, return)==value (contributed by vear)
  566. * @param value The value to log.
  567. * @param base Base of logarithm.
  568. * @return The logarithm of value with given base
  569. */
  570. public static float log(float value, float base) {
  571. return (float) (Math.log(value) / Math.log(base));
  572. }
  573. /**
  574. * Returns a number raised to an exponent power. fBase^fExponent
  575. * @param fBase The base value (IE 2)
  576. * @param fExponent The exponent value (IE 3)
  577. * @return base raised to exponent (IE 8)
  578. * @see java.lang.Math#pow(double, double)
  579. */
  580. public static float pow(float fBase, float fExponent) {
  581. return (float) Math.pow(fBase, fExponent);
  582. }
  583. /**
  584. * Returns the value squared. fValue ^ 2
  585. * @param fValue The vaule to square.
  586. * @return The square of the given value.
  587. */
  588. public static float sqr(float fValue) {
  589. return fValue * fValue;
  590. }
  591. /**
  592. * Returns the square root of a given value.
  593. * @param fValue The value to sqrt.
  594. * @return The square root of the given value.
  595. * @see java.lang.Math#sqrt(double)
  596. */
  597. public static float sqrt(float fValue) {
  598. return (float) Math.sqrt(fValue);
  599. }
  600. /**
  601. * Returns the tangent of a value. If USE_FAST_TRIG is enabled, an approximate value
  602. * is returned. Otherwise, a direct value is used.
  603. * @param fValue The value to tangent, in radians.
  604. * @return The tangent of fValue.
  605. * @see java.lang.Math#tan(double)
  606. */
  607. public static float tan(float fValue) {
  608. return (float) Math.tan(fValue);
  609. }
  610. /**
  611. * Returns 1 if the number is positive, -1 if the number is negative, and 0 otherwise
  612. * @param iValue The integer to examine.
  613. * @return The integer's sign.
  614. */
  615. public static int sign(int iValue) {
  616. if (iValue > 0) {
  617. return 1;
  618. }
  619. if (iValue < 0) {
  620. return -1;
  621. }
  622. return 0;
  623. }
  624. /**
  625. * Returns 1 if the number is positive, -1 if the number is negative, and 0 otherwise
  626. * @param fValue The float to examine.
  627. * @return The float's sign.
  628. */
  629. public static float sign(float fValue) {
  630. return Math.signum(fValue);
  631. }
  632. /**
  633. * Given 3 points in a 2d plane, this function computes if the points going from A-B-C
  634. * are moving counter clock wise.
  635. * @param p0 Point 0.
  636. * @param p1 Point 1.
  637. * @param p2 Point 2.
  638. * @return 1 If they are CCW, -1 if they are not CCW, 0 if p2 is between p0 and p1.
  639. */
  640. public static int counterClockwise(Vector2f p0, Vector2f p1, Vector2f p2) {
  641. float dx1, dx2, dy1, dy2;
  642. dx1 = p1.x - p0.x;
  643. dy1 = p1.y - p0.y;
  644. dx2 = p2.x - p0.x;
  645. dy2 = p2.y - p0.y;
  646. if (dx1 * dy2 > dy1 * dx2) {
  647. return 1;
  648. }
  649. if (dx1 * dy2 < dy1 * dx2) {
  650. return -1;
  651. }
  652. if ((dx1 * dx2 < 0) || (dy1 * dy2 < 0)) {
  653. return -1;
  654. }
  655. if ((dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * dy2)) {
  656. return 1;
  657. }
  658. return 0;
  659. }
  660. /**
  661. * Test if a point is inside a triangle. 1 if the point is on the ccw side,
  662. * -1 if the point is on the cw side, and 0 if it is on neither.
  663. * @param t0 First point of the triangle.
  664. * @param t1 Second point of the triangle.
  665. * @param t2 Third point of the triangle.
  666. * @param p The point to test.
  667. * @return Value 1 or -1 if inside triangle, 0 otherwise.
  668. */
  669. public static int pointInsideTriangle(Vector2f t0, Vector2f t1, Vector2f t2, Vector2f p) {
  670. int val1 = counterClockwise(t0, t1, p);
  671. if (val1 == 0) {
  672. return 1;
  673. }
  674. int val2 = counterClockwise(t1, t2, p);
  675. if (val2 == 0) {
  676. return 1;
  677. }
  678. if (val2 != val1) {
  679. return 0;
  680. }
  681. int val3 = counterClockwise(t2, t0, p);
  682. if (val3 == 0) {
  683. return 1;
  684. }
  685. if (val3 != val1) {
  686. return 0;
  687. }
  688. return val3;
  689. }
  690. /**
  691. * A method that computes normal for a triangle defined by three vertices.
  692. * @param v1 first vertex
  693. * @param v2 second vertex
  694. * @param v3 third vertex
  695. * @return a normal for the face
  696. */
  697. public static Vector3f computeNormal(Vector3f v1, Vector3f v2, Vector3f v3) {
  698. Vector3f a1 = v1.subtract(v2);
  699. Vector3f a2 = v3.subtract(v2);
  700. return a2.crossLocal(a1).normalizeLocal();
  701. }
  702. /**
  703. * Returns the determinant of a 4x4 matrix.
  704. */
  705. public static float determinant(double m00, double m01, double m02,
  706. double m03, double m10, double m11, double m12, double m13,
  707. double m20, double m21, double m22, double m23, double m30,
  708. double m31, double m32, double m33) {
  709. double det01 = m20 * m31 - m21 * m30;
  710. double det02 = m20 * m32 - m22 * m30;
  711. double det03 = m20 * m33 - m23 * m30;
  712. double det12 = m21 * m32 - m22 * m31;
  713. double det13 = m21 * m33 - m23 * m31;
  714. double det23 = m22 * m33 - m23 * m32;
  715. return (float) (m00 * (m11 * det23 - m12 * det13 + m13 * det12) - m01
  716. * (m10 * det23 - m12 * det03 + m13 * det02) + m02
  717. * (m10 * det13 - m11 * det03 + m13 * det01) - m03
  718. * (m10 * det12 - m11 * det02 + m12 * det01));
  719. }
  720. /**
  721. * Returns a random float between 0 and 1.
  722. *
  723. * @return A random float between <tt>0.0f</tt> (inclusive) to
  724. * <tt>1.0f</tt> (exclusive).
  725. */
  726. public static float nextRandomFloat() {
  727. return rand.nextFloat();
  728. }
  729. /**
  730. * Returns a random float between min and max.
  731. *
  732. * @return A random int between <tt>min</tt> (inclusive) to
  733. * <tt>max</tt> (inclusive).
  734. */
  735. public static int nextRandomInt(int min, int max) {
  736. return (int) (nextRandomFloat() * (max - min + 1)) + min;
  737. }
  738. public static int nextRandomInt() {
  739. return rand.nextInt();
  740. }
  741. /**
  742. * Converts a point from Spherical coordinates to Cartesian (using positive
  743. * Y as up) and stores the results in the store var.
  744. */
  745. public static Vector3f sphericalToCartesian(Vector3f sphereCoords,
  746. Vector3f store) {
  747. store.y = sphereCoords.x * FastMath.sin(sphereCoords.z);
  748. float a = sphereCoords.x * FastMath.cos(sphereCoords.z);
  749. store.x = a * FastMath.cos(sphereCoords.y);
  750. store.z = a * FastMath.sin(sphereCoords.y);
  751. return store;
  752. }
  753. /**
  754. * Converts a point from Cartesian coordinates (using positive Y as up) to
  755. * Spherical and stores the results in the store var. (Radius, Azimuth,
  756. * Polar)
  757. */
  758. public static Vector3f cartesianToSpherical(Vector3f cartCoords,
  759. Vector3f store) {
  760. float x = cartCoords.x;
  761. if (x == 0) {
  762. x = FastMath.FLT_EPSILON;
  763. }
  764. store.x = FastMath.sqrt((x * x)
  765. + (cartCoords.y * cartCoords.y)
  766. + (cartCoords.z * cartCoords.z));
  767. store.y = FastMath.atan(cartCoords.z / x);
  768. if (x < 0) {
  769. store.y += FastMath.PI;
  770. }
  771. store.z = FastMath.asin(cartCoords.y / store.x);
  772. return store;
  773. }
  774. /**
  775. * Converts a point from Spherical coordinates to Cartesian (using positive
  776. * Z as up) and stores the results in the store var.
  777. */
  778. public static Vector3f sphericalToCartesianZ(Vector3f sphereCoords,
  779. Vector3f store) {
  780. store.z = sphereCoords.x * FastMath.sin(sphereCoords.z);
  781. float a = sphereCoords.x * FastMath.cos(sphereCoords.z);
  782. store.x = a * FastMath.cos(sphereCoords.y);
  783. store.y = a * FastMath.sin(sphereCoords.y);
  784. return store;
  785. }
  786. /**
  787. * Converts a point from Cartesian coordinates (using positive Z as up) to
  788. * Spherical and stores the results in the store var. (Radius, Azimuth,
  789. * Polar)
  790. */
  791. public static Vector3f cartesianZToSpherical(Vector3f cartCoords,
  792. Vector3f store) {
  793. float x = cartCoords.x;
  794. if (x == 0) {
  795. x = FastMath.FLT_EPSILON;
  796. }
  797. store.x = FastMath.sqrt((x * x)
  798. + (cartCoords.y * cartCoords.y)
  799. + (cartCoords.z * cartCoords.z));
  800. store.z = FastMath.atan(cartCoords.z / x);
  801. if (x < 0) {
  802. store.z += FastMath.PI;
  803. }
  804. store.y = FastMath.asin(cartCoords.y / store.x);
  805. return store;
  806. }
  807. /**
  808. * Takes an value and expresses it in terms of min to max.
  809. *
  810. * @param val -
  811. * the angle to normalize (in radians)
  812. * @return the normalized angle (also in radians)
  813. */
  814. public static float normalize(float val, float min, float max) {
  815. if (Float.isInfinite(val) || Float.isNaN(val)) {
  816. return 0f;
  817. }
  818. float range = max - min;
  819. while (val > max) {
  820. val -= range;
  821. }
  822. while (val < min) {
  823. val += range;
  824. }
  825. return val;
  826. }
  827. /**
  828. * @param x
  829. * the value whose sign is to be adjusted.
  830. * @param y
  831. * the value whose sign is to be used.
  832. * @return x with its sign changed to match the sign of y.
  833. */
  834. public static float copysign(float x, float y) {
  835. if (y >= 0 && x <= -0) {
  836. return -x;
  837. } else if (y < 0 && x >= 0) {
  838. return -x;
  839. } else {
  840. return x;
  841. }
  842. }
  843. /**
  844. * Take a float input and clamp it between min and max.
  845. *
  846. * @param input
  847. * @param min
  848. * @param max
  849. * @return clamped input
  850. */
  851. public static float clamp(float input, float min, float max) {
  852. return (input < min) ? min : (input > max) ? max : input;
  853. }
  854. /**
  855. * Clamps the given float to be between 0 and 1.
  856. *
  857. * @param input
  858. * @return input clamped between 0 and 1.
  859. */
  860. public static float saturate(float input) {
  861. return clamp(input, 0f, 1f);
  862. }
  863. /**
  864. * Converts a single precision (32 bit) floating point value
  865. * into half precision (16 bit).
  866. *
  867. * <p>Source: <a href="http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf">
  868. * http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf</a><br><strong>broken link</strong>
  869. *
  870. * @param half The half floating point value as a short.
  871. * @return floating point value of the half.
  872. */
  873. public static float convertHalfToFloat(short half) {
  874. switch ((int) half) {
  875. case 0x0000:
  876. return 0f;
  877. case 0x8000:
  878. return -0f;
  879. case 0x7c00:
  880. return Float.POSITIVE_INFINITY;
  881. case 0xfc00:
  882. return Float.NEGATIVE_INFINITY;
  883. // TODO: Support for NaN?
  884. default:
  885. return Float.intBitsToFloat(((half & 0x8000) << 16)
  886. | (((half & 0x7c00) + 0x1C000) << 13)
  887. | ((half & 0x03FF) << 13));
  888. }
  889. }
  890. public static short convertFloatToHalf(float flt) {
  891. if (Float.isNaN(flt)) {
  892. throw new UnsupportedOperationException("NaN to half conversion not supported!");
  893. } else if (flt == Float.POSITIVE_INFINITY) {
  894. return (short) 0x7c00;
  895. } else if (flt == Float.NEGATIVE_INFINITY) {
  896. return (short) 0xfc00;
  897. } else if (flt == 0f) {
  898. return (short) 0x0000;
  899. } else if (flt == -0f) {
  900. return (short) 0x8000;
  901. } else if (flt > 65504f) {
  902. // max value supported by half float
  903. return 0x7bff;
  904. } else if (flt < -65504f) {
  905. return (short) (0x7bff | 0x8000);
  906. } else if (flt > 0f && flt < 5.96046E-8f) {
  907. return 0x0001;
  908. } else if (flt < 0f && flt > -5.96046E-8f) {
  909. return (short) 0x8001;
  910. }
  911. int f = Float.floatToIntBits(flt);
  912. return (short) (((f >> 16) & 0x8000)
  913. | ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
  914. | ((f >> 13) & 0x03ff));
  915. }
  916. }