math.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * ===========================================================================
  3. *
  4. * Wolf3D Browser Version GPL Source Code
  5. * Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
  6. *
  7. * This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
  8. *
  9. * Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Wolf3D Browser Source Code is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License version 2
  20. * along with Wolf3D Browser Source Code. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * If you have questions concerning this license, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  23. *
  24. * ===========================================================================
  25. */
  26. /**
  27. * @namespace
  28. * @description Math functions and lookup tables
  29. */
  30. Wolf.Math = (function() {
  31. // ------------------------- * LUTs * -------------------------
  32. var SinTable = [], // [ ANG_360 + ANG_90 + 1 ],
  33. CosTable = [], // SinTable + ANG_90,
  34. TanTable = [], //[ ANG_360 + 1 ];
  35. XnextTable = [], //[ ANG_360 + 1 ],
  36. YnextTable = [], //[ ANG_360 + 1 ],
  37. ColumnAngle = [], // [ 640 ]; // ViewAngle=PlayerAngle+ColumnAngle[curcolumn]; /in fines/
  38. // Angle Direction Types & LUTs (Hard Coded! Please do not mess them)
  39. q_first = 0, q_second = 1, q_third = 2, q_fourth = 3, // quadrant;
  40. dir4_east = 0, dir4_north = 1, dir4_west = 2, dir4_south = 3, dir4_nodir = 4, // dir4type;
  41. dir8_east = 0, dir8_northeast = 1, dir8_north = 2, dir8_northwest = 3, dir8_west = 4,
  42. dir8_southwest = 5, dir8_south = 6, dir8_southeast = 7, dir8_nodir = 8, // dir8type;
  43. dx4dir = [1, 0, -1, 0, 0], // dx & dy based on direction
  44. dy4dir = [0, 1, 0, -1, 0],
  45. dx8dir = [1, 1, 0, -1, -1, -1, 0, 1, 0], // dx & dy based on direction
  46. dy8dir = [0, 1, 1, 1, 0, -1, -1, -1, 0],
  47. opposite4 = [2, 3, 0, 1, 4],
  48. opposite8 = [4, 5, 6, 7, 0, 1, 2, 3, 8],
  49. dir4to8 = [0, 2, 4, 6, 8],
  50. diagonal = [
  51. /* east */ [dir8_nodir, dir8_nodir, dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southeast, dir8_nodir, dir8_nodir],
  52. [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  53. /* north */ [dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  54. [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  55. /* west */ [dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir],
  56. [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  57. /* south */ [dir8_southeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  58. [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
  59. [dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir]
  60. ],
  61. // dir of delta tooks dx{-1|0|1}+1 & dy{-1|0|1}+1 and give direction
  62. dir4d = [
  63. [dir4_nodir, dir4_west , dir4_nodir],
  64. [dir4_south, dir4_nodir, dir4_north],
  65. [dir4_nodir, dir4_east , dir4_nodir]
  66. ],
  67. dir8angle = [Wolf.ANG_0, Wolf.ANG_45, Wolf.ANG_90, Wolf.ANG_135, Wolf.ANG_180, Wolf.ANG_225, Wolf.ANG_270, Wolf.ANG_315, Wolf.ANG_0];
  68. dir4angle = [Wolf.ANG_0, Wolf.ANG_90, Wolf.ANG_180, Wolf.ANG_270, Wolf.ANG_0];
  69. /**
  70. * @private
  71. * @description Build LUTs, etc.
  72. */
  73. function buildTables() {
  74. var angle, tanfov2, tanval, value,
  75. n;
  76. for (n = 0; n <= Wolf.ANG_90 ; ++n) {
  77. angle = Wolf.FINE2RAD(n);
  78. value = Math.sin(angle);
  79. SinTable[n] = SinTable[Wolf.ANG_180 - n] = SinTable[n + Wolf.ANG_360] = value;
  80. SinTable[Wolf.ANG_180 + n] = SinTable[Wolf.ANG_360 - n] = -value;
  81. }
  82. for (n = 0; n <= SinTable.length - Wolf.ANG_90; ++n) {
  83. CosTable[n] = SinTable[n + Wolf.ANG_90];
  84. }
  85. for (n = 0; n <= Wolf.ANG_360 ; ++n) {
  86. angle = Wolf.FINE2RAD(n); //angle is in radians, n is in FINEs
  87. if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
  88. TanTable[n] = Math.tan(Wolf.FINE2RAD(n - 0.5)); // infinity
  89. YnextTable[n] = (Wolf.FLOATTILE * Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // infinity
  90. } else {
  91. TanTable[n] = Math.tan(angle);
  92. YnextTable[n] = (Wolf.FLOATTILE * Math.tan(angle))>>0;
  93. }
  94. if(n == Wolf.ANG_0 || n == Wolf.ANG_360) {
  95. XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n + 0.5)))>>0; // infinity
  96. } else if (n == Wolf.ANG_180) {
  97. XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // -infinity
  98. } else if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
  99. XnextTable[n] = 0;
  100. } else {
  101. XnextTable[n] = (Wolf.FLOATTILE / Math.tan(angle))>>0;
  102. }
  103. }
  104. tanfov2 = (Math.tan(Wolf.DEG2RAD((calcFov(75, Wolf.XRES, Wolf.YRES) / 2.0)))) * (Wolf.XRES / Wolf.YRES);
  105. for (n = 0; n < Wolf.XRES; ++n) {
  106. tanval = tanfov2 * (-1.0 + 2.0 * n / (Wolf.XRES-1));
  107. ColumnAngle[n] = Wolf.RAD2FINE(Math.atan(tanval)) >> 0;
  108. }
  109. Wolf.Random.init(1); // random number generators
  110. return 1;
  111. }
  112. /**
  113. * @description Calculate the field of view.
  114. * @memberOf Wolf.Math
  115. * @param {number} fovX Must be within 1 and 179 degrees.
  116. * @param {number} width Width of viewing area.
  117. * @param {number} height Height of viewing area.
  118. * @returns {number} The field of view in degrees.
  119. */
  120. function calcFov(fovX, width, height) {
  121. if (fovX < 1 || fovX > 179) {
  122. throw Error("Bad fov: " + fovX );
  123. }
  124. return Wolf.RAD2DEG(Math.atan(height / (width / Math.tan(fovX / 360 * Math.PI)))) * 2;
  125. }
  126. /**
  127. * @description Clips angle to [0..360] bounds.
  128. * @memberOf Wolf.Math
  129. * @param {number} alpha Angle in degrees.
  130. * @returns {number} Normalized angle.
  131. */
  132. function normalizeAngle(alpha) {
  133. if (alpha > Wolf.ANG_360) {
  134. alpha %= Wolf.ANG_360;
  135. }
  136. if (alpha < Wolf.ANG_0) {
  137. alpha = Wolf.ANG_360 - (-alpha) % Wolf.ANG_360;
  138. }
  139. return alpha;
  140. }
  141. /**
  142. * @description Get quadrant.
  143. * @memberOf Wolf.Math
  144. * @param {number} angle Radian angle.
  145. * @returns {number}
  146. */
  147. function getQuadrant(angle) {
  148. angle = Wolf.Angle.normalize(angle);
  149. if (angle < Math.PI / 2) {
  150. return q_first;
  151. } else if (angle < Math.PI) {
  152. return q_second;
  153. } else if (angle < 3 * Math.PI / 2) {
  154. return q_third;
  155. } else {
  156. return q_fourth;
  157. }
  158. }
  159. /**
  160. * @description Get 4 point direction.
  161. * @memberOf Wolf.Math
  162. * @param {number} angle Radian angle.
  163. * @returns {number} Directional point.
  164. */
  165. function get4dir(angle) {
  166. angle = Wolf.Angle.normalize(angle + Math.PI / 4);
  167. if (angle < Math.PI / 2) {
  168. return dir4_east;
  169. } else if( angle < Math.PI ) {
  170. return dir4_north;
  171. } else if( angle < 3 * Math.PI / 2 ) {
  172. return dir4_west;
  173. } else {
  174. return dir4_south;
  175. }
  176. }
  177. /**
  178. * @description Get 8 point direction.
  179. * @memberOf Wolf.Math
  180. * @param {number} angle Radian angle.
  181. * @returns {number} Directional point.
  182. */
  183. function get8dir(angle) {
  184. angle = Wolf.Angle.normalize(angle + Math.PI / 12);
  185. if ( angle <= (Math.PI / 4)) {
  186. return dir8_east;
  187. } else if (angle < (Math.PI / 2)) {
  188. return dir8_northeast;
  189. } else if (angle <= (3 * Math.PI / 4)) {
  190. return dir8_north;
  191. } else if (angle < Math.PI) {
  192. return dir8_northwest;
  193. } else if (angle <= (5 * Math.PI / 4)) {
  194. return dir8_west;
  195. } else if (angle < (3 * Math.PI / 2)) {
  196. return dir8_southwest;
  197. } else if (angle <= (7 * Math.PI / 4)) {
  198. return dir8_south;
  199. } else {
  200. return dir8_southeast;
  201. }
  202. }
  203. /**
  204. * @description calculates distance between a point (x, y) and a line.
  205. * @memberOf Wolf.Math
  206. * @param {number} x X coord of point
  207. * @param {number} y Y coord of point
  208. * @param {number} a Line angle in degrees
  209. * @returns {number} Distance
  210. */
  211. function point2LineDist(x, y, a) {
  212. return Math.abs( (x * SinTable[a] - y * CosTable[a]) >> 0);
  213. }
  214. /**
  215. * @description Calculates line length to the point nearest to (poin).
  216. * @memberOf Wolf.Math
  217. * @param {number} x X coord of point
  218. * @param {number} y Y coord of point
  219. * @param {number} a Line angle in degrees
  220. * @returns {number} Distance
  221. */
  222. function lineLen2Point( x, y, a) {
  223. return (x * CosTable[a] + y * SinTable[a]) >> 0;
  224. }
  225. /*
  226. point2 = {x,y}
  227. / |
  228. / |
  229. / |
  230. /a______|----------> x
  231. point1 = {x, y}
  232. */
  233. /**
  234. * @description Returns angle in radians
  235. * @memberOf Wolf.Math
  236. * @param {number} x X coord of point
  237. * @param {number} y Y coord of point
  238. * @param {number} a Line angle in degrees
  239. * @returns {number} Distance
  240. */
  241. function transformPoint(point1X, point1Y, point2X, point2Y) {
  242. var angle = Math.atan2(point1Y - point2Y, point1X - point2X);
  243. return Wolf.Angle.normalize(angle);
  244. }
  245. buildTables();
  246. return {
  247. calcFov : calcFov,
  248. normalizeAngle : normalizeAngle,
  249. getQuadrant : getQuadrant,
  250. get4dir : get4dir,
  251. get8dir : get8dir,
  252. point2LineDist : point2LineDist,
  253. lineLen2Point : lineLen2Point,
  254. transformPoint : transformPoint,
  255. SinTable : SinTable,
  256. CosTable : CosTable,
  257. TanTable : TanTable,
  258. XnextTable : XnextTable,
  259. YnextTable : YnextTable,
  260. ColumnAngle : ColumnAngle,
  261. dir4_east : dir4_east,
  262. dir4_north : dir4_north,
  263. dir4_west : dir4_west,
  264. dir4_south : dir4_south,
  265. dir4_nodir : dir4_nodir,
  266. dir8_east : dir8_east,
  267. dir8_northeast : dir8_northeast,
  268. dir8_north : dir8_north,
  269. dir8_northwest : dir8_northwest,
  270. dir8_west : dir8_west,
  271. dir8_southwest : dir8_southwest,
  272. dir8_south : dir8_south,
  273. dir8_southeast : dir8_southeast,
  274. dir8_nodir : dir8_nodir,
  275. dx4dir : dx4dir,
  276. dy4dir : dy4dir,
  277. dx8dir : dx8dir,
  278. dy8dir : dy8dir,
  279. dir4angle : dir4angle,
  280. dir8angle : dir8angle,
  281. dir4to8 : dir4to8,
  282. opposite4 : opposite4,
  283. opposite8 : opposite8,
  284. diagonal : diagonal
  285. };
  286. })();