enmath.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. /**
  2. * \defgroup Math Math library
  3. * @{
  4. */
  5. class Math
  6. {
  7. private void Math() {}
  8. private void ~Math() {}
  9. static const float EULER = 2.7182818284590452353;
  10. static const float PI = 3.14159265358979;
  11. static const float PI2 = 6.28318530717958;
  12. static const float PI_HALF = 1.570796326794;
  13. static const float RAD2DEG = 57.2957795130823208768;
  14. static const float DEG2RAD = 0.01745329251994329577;
  15. //! returns the number of bits set in a bitmask i
  16. proto static int GetNumberOfSetBits(int i);
  17. //! returns the the index of n-th bit set in a bit mask counting from the right, for instance, in a mask ..0110 1000 , the 0th set bit(right-most bit set to 1) is at 3th position(starting at 0), 1st bit is at 5th position, 2nd bit is at 6th position etc..
  18. proto static int GetNthBitSet(int value, int n);
  19. /**
  20. \brief Returns a random \p int number between and min [inclusive] and max [exclusive].
  21. \param min \p int Range starts [inclusive]
  22. \param max \p int Range ends [exclusive]
  23. \return \p int - Random number in range
  24. @code
  25. Print( Math.RandomInt(0, 1) ); // only 0
  26. Print( Math.RandomInt(0, 2) ); // 0 or 1
  27. >> 0
  28. >> 1
  29. @endcode
  30. */
  31. proto static int RandomInt(int min, int max);
  32. /**
  33. \brief Returns a random \p int number between and min [inclusive] and max [inclusive].
  34. \param min \p int Range starts [inclusive]
  35. \param max \p int Range ends [inclusive]
  36. \return \p int - Random number in range
  37. @code
  38. Print( Math.RandomIntInclusive(0, 1) ); // 0 or 1
  39. Print( Math.RandomIntInclusive(0, 2) ); // 0, 1, 2
  40. >> 1
  41. >> 2
  42. @endcode
  43. */
  44. static int RandomIntInclusive(int min, int max)
  45. {
  46. return Math.RandomInt(min, max+1);
  47. }
  48. /**
  49. \brief Returns a random \p bool .
  50. \return \p bool - Random bool either 0 or 1
  51. @code
  52. Print( Math.RandomBool() );
  53. Print( Math.RandomBool() );
  54. Print( Math.RandomBool() );
  55. >> true
  56. >> true
  57. >> false
  58. @endcode
  59. */
  60. static bool RandomBool()
  61. {
  62. return RandomIntInclusive(0,1);
  63. }
  64. /**
  65. \brief Returns a random \p float number between and min[inclusive] and max[exclusive].
  66. \param min \p float Range starts [inclusive]
  67. \param max \p float Range ends [exclusive]
  68. \return \p float - Random number in range
  69. @code
  70. Print( Math.RandomFloat(0,1) );
  71. Print( Math.RandomFloat(0,2) );
  72. >> 0.597561
  73. >> 1.936456
  74. @endcode
  75. */
  76. proto static float RandomFloat(float min, float max);
  77. /**
  78. \brief Returns a random \p float number between and min [inclusive] and max [inclusive].
  79. \param min \p float Range starts [inclusive]
  80. \param max \p float Range ends [inclusive]
  81. \return \p float - Random number in range
  82. @code
  83. Print( Math.RandomFloatInclusive(0, 1) ); // 0.0 .. 1.0
  84. Print( Math.RandomFloatInclusive(1, 2) ); // 1.0 .. 2.0
  85. >> 0.3
  86. >> 2.0
  87. @endcode
  88. */
  89. static float RandomFloatInclusive(float min, float max)
  90. {
  91. int max_range = Math.Pow(2, 30); //max range
  92. int random_int = Math.RandomInt(0, max_range);
  93. float rand_float = (float)random_int / (float)max_range;
  94. float range = max - min;
  95. return min + (rand_float * range); //rand float
  96. }
  97. /**
  98. \brief Returns a random \p float number between and min [inclusive] and max [inclusive].
  99. \return \p float - Random number in range 0.0 .. 1.0
  100. @code
  101. Print( Math.RandomFloat01() ); // 0.0 .. 1.0
  102. >> 0.3
  103. >> 1.0
  104. @endcode
  105. */
  106. static float RandomFloat01()
  107. {
  108. return RandomFloatInclusive(0, 1);
  109. }
  110. /**
  111. \brief Sets the seed for the random number generator.
  112. \param seed \p int New seed for the random number generator, -1 will use time
  113. \return \p int - Returns new seed
  114. @code
  115. Print( Math.Randomize(5) );
  116. >> 5
  117. @endcode
  118. */
  119. proto static int Randomize(int seed);
  120. /**
  121. \brief Normalizes the angle (0...360)
  122. \param ang \p float Angle for normalizing
  123. \return \p float - Normalized angle
  124. @code
  125. Print( Math.NormalizeAngle(390) );
  126. Print( Math.NormalizeAngle(-90) );
  127. >> 30
  128. >> 270
  129. @endcode
  130. */
  131. proto static float NormalizeAngle(float ang);
  132. /**
  133. \brief Return relative difference between angles
  134. \param angle1 \p float
  135. \param angle2 \p float
  136. \return \p float Difference between angles (angle1 - angle2)
  137. @code
  138. Print( Math.DiffAngle(-45, 45) );
  139. Print( Math.DiffAngle(90, 80) );
  140. >> -90
  141. >> 10
  142. @endcode
  143. */
  144. proto static float DiffAngle(float angle1, float angle2);
  145. /**
  146. \brief Return power of v ^ power
  147. \param v \p float Value
  148. \param power \p float Power
  149. \return \p float - The result of raising v to the given power
  150. @code
  151. Print( Math.Pow(2, 4) ); // (2*2*2*2)=16
  152. >> 16
  153. @endcode
  154. */
  155. proto static float Pow(float v, float power);
  156. /**
  157. \brief Returns the floating-point remainder of x/y rounded towards zero
  158. \param x \p float Value of the quotient numerator
  159. \param y \p float Value of the quotient denominator
  160. \return \p float - The remainder of dividing the arguments
  161. @code
  162. Print( Math.ModFloat(5.3, 2) );
  163. Print( Math.ModFloat(18.5, 4.2) );
  164. >> 1.3
  165. >> 1.7
  166. @endcode
  167. */
  168. proto static float ModFloat(float x, float y);
  169. /**
  170. \brief Returns the floating-point remainder of x/y rounded to nearest
  171. \param x \p float Value of the quotient numerator
  172. \param y \p float Value of the quotient denominator
  173. \return \p float - The remainder of dividing the arguments
  174. @code
  175. Print( Math.RemainderFloat(5.3, 2) );
  176. Print( Math.RemainderFloat(18.5, 4.2) );
  177. >> -0.7
  178. >> 1.7
  179. @endcode
  180. */
  181. proto static float RemainderFloat(float x, float y);
  182. /**
  183. \brief Returns absolute value
  184. \param f \p float Value
  185. \return \p float - Absolute value
  186. @code
  187. Print( Math.AbsFloat(-12.5) );
  188. >> 12.5
  189. @endcode
  190. */
  191. proto static float AbsFloat(float f);
  192. /**
  193. \brief Returns absolute value
  194. \param i \p int Value
  195. \return \p int - Absolute value
  196. @code
  197. Print( Math.AbsInt(-12) );
  198. >> 12
  199. @endcode
  200. */
  201. proto static int AbsInt(int i);
  202. /**
  203. \brief Returns sign of given value
  204. \param f \p float Value
  205. \return \p float - Sign of given value
  206. @code
  207. Print( Math.SignFloat(-12.0) );
  208. Print( Math.SignFloat(0.0) );
  209. Print( Math.SignFloat(12.0) );
  210. >> -1.0
  211. >> 0
  212. >> 1.0
  213. @endcode
  214. */
  215. proto static float SignFloat(float f);
  216. /**
  217. \brief Returns sign of given value
  218. \param i \p int Value
  219. \return \p int - Sign of given value
  220. @code
  221. Print( Math.SignFloat(-12) );
  222. Print( Math.SignFloat(0) );
  223. Print( Math.SignFloat(12) );
  224. >> -1
  225. >> 0
  226. >> 1
  227. @endcode
  228. */
  229. proto static int SignInt(int i);
  230. /**
  231. \brief Returns squared value
  232. \param f \p float Value
  233. \return \p float - Squared value
  234. @code
  235. Print( Math.SqrFloat(12.5) );
  236. >> 156.25
  237. @endcode
  238. */
  239. proto static float SqrFloat(float f);
  240. /**
  241. \brief Returns squared value
  242. \param i \p int Value
  243. \return \p int - Squared value
  244. @code
  245. Print( Math.SqrInt(12) );
  246. >> 144
  247. @endcode
  248. */
  249. proto static int SqrInt(int i);
  250. /**
  251. \brief Returns square root
  252. \param val \p float Value
  253. \return \p float - Square of value
  254. @code
  255. Print( Math.Sqrt(25));
  256. >> 5
  257. @endcode
  258. */
  259. proto static float Sqrt(float val);
  260. /**
  261. \brief Returns the binary (base-2) logarithm of x.
  262. \param x \p float Value whose logarithm is calculated.
  263. \return \p float The binary logarithm of x: log2x.
  264. \n If x is negative, it causes a domain error:
  265. \n If x is zero, it may cause a pole error (depending on the library implementation).
  266. @code
  267. Print( Math.Log2(1.0) );
  268. >> 0.0
  269. @endcode
  270. */
  271. proto static float Log2(float x);
  272. /**
  273. \brief Returns sinus of angle in radians
  274. \param angle \p float Angle in radians
  275. \return \p float - Sinus of angle
  276. @code
  277. Print( Math.Sin(0.785398) ); // (45)
  278. >> 0.707107
  279. @endcode
  280. */
  281. proto static float Sin(float angle);
  282. /**
  283. \brief Returns cosinus of angle in radians
  284. \param angle \p float Angle in radians
  285. \return \p float - Cosinus of angle
  286. @code
  287. Print( Math.Cos(0.785398) ); // (45)
  288. >> 0.707107
  289. @endcode
  290. */
  291. proto static float Cos(float angle);
  292. /**
  293. \brief Returns tangent of angle in radians
  294. \param angle \p float Angle in radians
  295. \return \p float - Tangens of angle
  296. @code
  297. Print( Math.Tan(0.785398) ); // (45)
  298. >> 1
  299. @endcode
  300. */
  301. proto static float Tan(float angle);
  302. /**
  303. \brief Returns angle in radians from sinus
  304. \param s \p float Sinus
  305. \return \p float - Angle in radians
  306. @code
  307. Print( Math.Asin(0.707107) ); // (sinus 45)
  308. >> 0.785398
  309. @endcode
  310. */
  311. proto static float Asin(float s);
  312. /**
  313. \brief Returns angle in radians from cosinus
  314. \param c \p float Cosinus
  315. \return \p float - Angle in radians
  316. @code
  317. Print( Math.Acos(0.707107) ); // (cosinus 45)
  318. >> 0.785398
  319. @endcode
  320. */
  321. proto static float Acos(float c);
  322. /**
  323. \brief Returns angle in radians from tangent
  324. \param x \p float Tangent
  325. \return \p float - Angle in radians
  326. */
  327. proto static float Atan(float x);
  328. /**
  329. \brief Returns angle in radians from tangent
  330. \param y \p float Tangent
  331. \param x \p float Tangent
  332. \return \p float - Angle in radians
  333. @code
  334. Print ( Math.Atan2(1, 1) );
  335. >> 0.785398
  336. @endcode
  337. */
  338. proto static float Atan2(float y, float x);
  339. /**
  340. \brief Returns mathematical round of value
  341. \param f \p float Value
  342. \return \p float - closest whole number to 'f'
  343. @code
  344. Print( Math.Round(5.3) );
  345. Print( Math.Round(5.8) );
  346. >> 5
  347. >> 6
  348. @endcode
  349. */
  350. proto static float Round(float f);
  351. /**
  352. \brief Returns floor of value
  353. \param f \p float Value
  354. \return \p float - Floor of value
  355. @code
  356. Print( Math.Floor(5.3) );
  357. Print( Math.Floor(5.8) );
  358. >> 5
  359. >> 5
  360. @endcode
  361. */
  362. proto static float Floor(float f);
  363. /**
  364. \brief Returns ceil of value
  365. \param f \p float Value
  366. \return \p float - Ceil of value
  367. @code
  368. Print( Math.Ceil(5.3) );
  369. Print( Math.Ceil(5.8) );
  370. >> 6
  371. >> 6
  372. @endcode
  373. */
  374. proto static float Ceil(float f);
  375. /**
  376. \brief Returns wrap number to specified interval [min, max[
  377. \param f \p float Value
  378. \param min \p float Minimum
  379. \param max \p float Maximum
  380. \return \p float - number in specified interval [min, max[
  381. @code
  382. Print( Math.WrapFloat(9.0, 1.0, 9.0) );
  383. >> 1.0
  384. @endcode
  385. */
  386. proto static float WrapFloat(float f, float min, float max);
  387. /**
  388. \brief Returns wrap number to specified interval, inclusive [min, max]
  389. \param f \p float Value
  390. \param min \p float Minimum
  391. \param max \p float Maximum
  392. \return \p float - number in specified interval [min, max]
  393. @code
  394. Print( Math.WrapFloatInclusive(9.0, 1.0, 9.0) );
  395. >> 9.0
  396. @endcode
  397. */
  398. proto static float WrapFloatInclusive(float f, float min, float max);
  399. /**
  400. \brief Returns wrap number to specified interval [0, max[
  401. \param f \p float Value
  402. \param max \p float Maximum
  403. \return \p float - number in specified interval [0, max[
  404. @code
  405. Print( Math.WrapFloat0X(9.0, 9.0) );
  406. >> 0.0
  407. @endcode
  408. */
  409. proto static float WrapFloat0X(float f, float max);
  410. /**
  411. \brief Returns wrap number to specified interval, inclusive [0, max]
  412. \param f \p float Value
  413. \param max \p float Maximum
  414. \return \p float - number in specified interval [0, max]
  415. @code
  416. Print( Math.WrapFloat0XInclusive(9.0, 9.0) );
  417. >> 9.0
  418. @endcode
  419. */
  420. proto static float WrapFloat0XInclusive(float f, float max);
  421. /**
  422. \brief Returns wrap number to specified interval [min, max[
  423. \param i \p int Value
  424. \param min \p float Minimum
  425. \param max \p int Maximum
  426. \return \p int - number in specified interval [min, max[
  427. @code
  428. Print( Math.WrapInt(9, 1, 9) );
  429. >> 1
  430. @endcode
  431. */
  432. proto static int WrapInt(int i, int min, int max);
  433. /**
  434. \brief Returns wrap number to specified interval [0, max[
  435. \param i \p int Value
  436. \param max \p int Maximum
  437. \return \p int - number in specified interval [0, max[
  438. @code
  439. Print( Math.WrapInt0X(9, 9) );
  440. >> 0
  441. @endcode
  442. */
  443. proto static int WrapInt0X(int i, int max);
  444. /**
  445. \brief Clamps 'value' to 'min' if it is lower than 'min', or to 'max' if it is higher than 'max'
  446. \param value \p float Value
  447. \param min \p float Minimum value
  448. \param max \p float Maximum value
  449. \return \p float - Clamped value
  450. @code
  451. Print( Math.Clamp(-0.1, 0, 1) );
  452. Print( Math.Clamp(2, 0, 1) );
  453. Print( Math.Clamp(0.5, 0, 1) );
  454. >> 0
  455. >> 1
  456. >> 0.5
  457. @endcode
  458. */
  459. proto static float Clamp(float value, float min, float max);
  460. /**
  461. \brief Returns smaller of two given values
  462. \param x \p float Value
  463. \param y \p float Value
  464. \return \p float - min value
  465. @code
  466. Print( Math.Min(5.3, 2.8) );
  467. >> 2.8
  468. @endcode
  469. */
  470. proto static float Min(float x, float y);
  471. /**
  472. \brief Returns bigger of two given values
  473. \param x \p float Value
  474. \param y \p float Value
  475. \return \p float - max value
  476. @code
  477. Print( Math.Max(5.3, 2.8) );
  478. >> 5.3
  479. @endcode
  480. */
  481. proto static float Max(float x, float y);
  482. /**
  483. \brief Returns if value is between min and max (inclusive)
  484. \param v \p float Value
  485. \param min \p float Minimum value
  486. \param max \p float Maximum value
  487. \return \p bool - if value is within range [min,max]
  488. @code
  489. Print( Math.IsInRange(6.9, 3.6, 9.3) );
  490. >> true
  491. @endcode
  492. */
  493. proto static bool IsInRange(float v, float min, float max);
  494. /**
  495. \brief Returns if value is between min and max (inclusive)
  496. \param v \p int Value
  497. \param min \p int Minimum value
  498. \param max \p int Maximum value
  499. \return \p bool - if value is within range [min,max]
  500. @code
  501. Print( Math.IsInRangeInt(6, 3, 9) );
  502. >> true
  503. @endcode
  504. */
  505. proto static bool IsInRangeInt(int v, int min, int max);
  506. /**
  507. \brief Linearly interpolates between 'a' and 'b' given 'time'.
  508. \param a \p float Start
  509. \param b \p float End
  510. \param time \p float Time [value needs to be between 0..1 for correct results, no auto clamp applied]
  511. \return \p float - The interpolated result between the two float values.
  512. @code
  513. Print( Math.Lerp(3, 7, 0.5) );
  514. >> 5
  515. @endcode
  516. */
  517. proto static float Lerp(float a, float b, float time);
  518. /**
  519. \brief Calculates the linear value that produces the interpolant value within the range [a, b], it's an inverse of Lerp.
  520. \param a \p float Start
  521. \param b \p float End
  522. \param value \p float value
  523. \return \p float - the time given the position between 'a' and 'b' given 'value', there is no clamp on 'value', to stay between [0..1] use 'value' between 'a' and 'b'
  524. @code
  525. Print( Math.InverseLerp(3, 7, 5) );
  526. >> 0.5
  527. @endcode
  528. */
  529. proto static float InverseLerp(float a, float b, float value);
  530. /**
  531. \brief Returns area of a right triangle
  532. \param s \p float Length of adjacent leg
  533. \param a \p float Angle of corner bordering adjacent which is not the right corner (in radians)
  534. \return \p float - Area
  535. */
  536. proto static float AreaOfRightTriangle(float s, float a);
  537. /**
  538. \brief Returns hypotenus of a right triangle
  539. \param s \p float Length of adjacent leg
  540. \param a \p float Angle of corner bordering adjacent which is not the right corner (in radians)
  541. \return \p float - hypotenus
  542. */
  543. proto static float HypotenuseOfRightTriangle(float s, float a);
  544. /**
  545. \brief Returns if point is inside circle
  546. \param c \p vector Center of circle ([0] and [2] will be used, as a circle is 2D)
  547. \param r \p float Radius of circle
  548. \param p \p vector Point ([0] and [2] will be used, as a circle is 2D)
  549. \return \p bool - True when point is in circle
  550. */
  551. proto static bool IsPointInCircle(vector c, float r, vector p);
  552. /**
  553. \brief Returns if point is inside rectangle
  554. \param mi \p vector Minimums of rectangle ([0] and [2] will be used, as a rectangle is 2D)
  555. \param ma \p vector Maximums of rectangle ([0] and [2] will be used, as a rectangle is 2D)
  556. \param p \p vector Point ([0] and [2] will be used, as a rectangle is 2D)
  557. \return \p bool - True when point is in rectangle
  558. */
  559. proto static bool IsPointInRectangle(vector mi, vector ma, vector p);
  560. //--------------------------------------------------------------------------
  561. //-------------------------------- filters ---------------------------------
  562. //--------------------------------------------------------------------------
  563. /**
  564. \brief Does the CD smoothing function - easy in | easy out / S shaped smoothing
  565. \param val \p actual value
  566. \param target \p value we are reaching for -> Target
  567. \param velocity \p float[1] - array of ONE member - some kind of memory and actual accel/decel rate, need to be zeroed when filter is about to be reset
  568. \param smoothTime \p smoothing parameter, 0.1 .. 0.4 are resonable values, 0.1 is sharp, 0.4 is very smooth
  569. \param maxVelocity \p maximal value change when multiplied by dt
  570. \param dt \p delta time
  571. \return \p float smoothed/filtered value
  572. @code
  573. val = EnfMath.SmoothCD(val, varTarget, valVelocity, 0.3, 1000, dt);
  574. @endcode
  575. */
  576. proto static float SmoothCD(float val, float target, inout float velocity[], float smoothTime, float maxVelocity, float dt);
  577. static float SmoothCDPI2PI(float val, float target, inout float velocity[], float smoothTime, float maxVelocity, float dt)
  578. {
  579. float diff = target - val;
  580. if (diff < -Math.PI)
  581. {
  582. target += Math.PI2;
  583. }
  584. else if (diff > Math.PI)
  585. {
  586. target -= Math.PI2;
  587. }
  588. float retVal = SmoothCD(val, target, velocity, smoothTime, maxVelocity, dt);
  589. while (retVal > Math.PI)
  590. {
  591. retVal -= Math.PI2;
  592. }
  593. while (retVal < -Math.PI)
  594. {
  595. retVal += Math.PI2;
  596. }
  597. return retVal;
  598. }
  599. //! occurences values above '12' will cause Factorial to overflow int.
  600. static float Poisson(float mean, int occurences)
  601. {
  602. return Pow(mean, occurences) * Pow(EULER,-mean) / Factorial(occurences);
  603. }
  604. //! values above '12' will cause int overflow
  605. static int Factorial(int val)
  606. {
  607. if (val > 12)
  608. {
  609. ErrorEx("Values above '12' cause int overflow! Returning '1'",ErrorExSeverity.INFO);
  610. return 1;
  611. }
  612. int res = 1;
  613. while (val > 1)
  614. {
  615. res *= val--;
  616. }
  617. return res;
  618. }
  619. /**
  620. \brief Returns given value remaped from input range into output range
  621. \param inputMin \p float Minimal value of given input range
  622. \param inputMax \p float Maximal value of given input range
  623. \param outputMin \p float Minimal value of given output range
  624. \param outputMax \p float Maximal value of given input range
  625. \param inputValue \p float Value we want to remap
  626. \param clampedOutput\p bool If value should stay in that range, otherwise it will be extrapolated
  627. \return \p float - Remapped value
  628. */
  629. static float Remap(float inputMin, float inputMax, float outputMin, float outputMax, float inputValue, bool clampedOutput = true)
  630. {
  631. float tempValue = Math.InverseLerp(inputMin, inputMax, inputValue);
  632. float remapped = Math.Lerp(outputMin, outputMax, tempValue);
  633. if (clampedOutput)
  634. return Math.Clamp(remapped, outputMin, outputMax);
  635. return remapped;
  636. }
  637. static vector CenterOfRectangle(vector min, vector max)
  638. {
  639. float x = (min[0] + max[0]) * 0.5;
  640. float z = (min[2] + max[2]) * 0.5;
  641. return Vector(x, 0.0, z);
  642. }
  643. }
  644. //@}