mirror of
https://github.com/id-Software/wolf3d-browser.git
synced 2024-11-10 07:22:05 +00:00
329 lines
12 KiB
JavaScript
329 lines
12 KiB
JavaScript
|
/*
|
||
|
* ===========================================================================
|
||
|
*
|
||
|
* Wolf3D Browser Version GPL Source Code
|
||
|
* Copyright (C) 2012 id Software LLC, a ZeniMax Media company.
|
||
|
*
|
||
|
* This file is part of the Wolf3D Browser Version GPL Source Code ("Wolf3D Browser Source Code").
|
||
|
*
|
||
|
* Wolf3D Browser Source Code is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* Wolf3D Browser Source Code is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License version 2
|
||
|
* along with Wolf3D Browser Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
* ===========================================================================
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @namespace
|
||
|
* @description Math functions and lookup tables
|
||
|
*/
|
||
|
Wolf.Math = (function() {
|
||
|
|
||
|
// ------------------------- * LUTs * -------------------------
|
||
|
var SinTable = [], // [ ANG_360 + ANG_90 + 1 ],
|
||
|
CosTable = [], // SinTable + ANG_90,
|
||
|
TanTable = [], //[ ANG_360 + 1 ];
|
||
|
|
||
|
XnextTable = [], //[ ANG_360 + 1 ],
|
||
|
YnextTable = [], //[ ANG_360 + 1 ],
|
||
|
|
||
|
ColumnAngle = [], // [ 640 ]; // ViewAngle=PlayerAngle+ColumnAngle[curcolumn]; /in fines/
|
||
|
|
||
|
// Angle Direction Types & LUTs (Hard Coded! Please do not mess them)
|
||
|
q_first = 0, q_second = 1, q_third = 2, q_fourth = 3, // quadrant;
|
||
|
dir4_east = 0, dir4_north = 1, dir4_west = 2, dir4_south = 3, dir4_nodir = 4, // dir4type;
|
||
|
|
||
|
dir8_east = 0, dir8_northeast = 1, dir8_north = 2, dir8_northwest = 3, dir8_west = 4,
|
||
|
dir8_southwest = 5, dir8_south = 6, dir8_southeast = 7, dir8_nodir = 8, // dir8type;
|
||
|
|
||
|
dx4dir = [1, 0, -1, 0, 0], // dx & dy based on direction
|
||
|
dy4dir = [0, 1, 0, -1, 0],
|
||
|
dx8dir = [1, 1, 0, -1, -1, -1, 0, 1, 0], // dx & dy based on direction
|
||
|
dy8dir = [0, 1, 1, 1, 0, -1, -1, -1, 0],
|
||
|
opposite4 = [2, 3, 0, 1, 4],
|
||
|
opposite8 = [4, 5, 6, 7, 0, 1, 2, 3, 8],
|
||
|
dir4to8 = [0, 2, 4, 6, 8],
|
||
|
diagonal = [
|
||
|
/* east */ [dir8_nodir, dir8_nodir, dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southeast, dir8_nodir, dir8_nodir],
|
||
|
[dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
/* north */ [dir8_northeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
[dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
/* west */ [dir8_nodir, dir8_nodir, dir8_northwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir],
|
||
|
[dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
/* south */ [dir8_southeast, dir8_nodir, dir8_nodir, dir8_nodir, dir8_southwest, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
[dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir],
|
||
|
[dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir, dir8_nodir]
|
||
|
],
|
||
|
|
||
|
// dir of delta tooks dx{-1|0|1}+1 & dy{-1|0|1}+1 and give direction
|
||
|
dir4d = [
|
||
|
[dir4_nodir, dir4_west , dir4_nodir],
|
||
|
[dir4_south, dir4_nodir, dir4_north],
|
||
|
[dir4_nodir, dir4_east , dir4_nodir]
|
||
|
],
|
||
|
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];
|
||
|
dir4angle = [Wolf.ANG_0, Wolf.ANG_90, Wolf.ANG_180, Wolf.ANG_270, Wolf.ANG_0];
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @private
|
||
|
* @description Build LUTs, etc.
|
||
|
*/
|
||
|
function buildTables() {
|
||
|
var angle, tanfov2, tanval, value,
|
||
|
n;
|
||
|
|
||
|
for (n = 0; n <= Wolf.ANG_90 ; ++n) {
|
||
|
angle = Wolf.FINE2RAD(n);
|
||
|
value = Math.sin(angle);
|
||
|
SinTable[n] = SinTable[Wolf.ANG_180 - n] = SinTable[n + Wolf.ANG_360] = value;
|
||
|
SinTable[Wolf.ANG_180 + n] = SinTable[Wolf.ANG_360 - n] = -value;
|
||
|
}
|
||
|
|
||
|
for (n = 0; n <= SinTable.length - Wolf.ANG_90; ++n) {
|
||
|
CosTable[n] = SinTable[n + Wolf.ANG_90];
|
||
|
}
|
||
|
|
||
|
for (n = 0; n <= Wolf.ANG_360 ; ++n) {
|
||
|
angle = Wolf.FINE2RAD(n); //angle is in radians, n is in FINEs
|
||
|
|
||
|
if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
|
||
|
TanTable[n] = Math.tan(Wolf.FINE2RAD(n - 0.5)); // infinity
|
||
|
YnextTable[n] = (Wolf.FLOATTILE * Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // infinity
|
||
|
} else {
|
||
|
TanTable[n] = Math.tan(angle);
|
||
|
YnextTable[n] = (Wolf.FLOATTILE * Math.tan(angle))>>0;
|
||
|
}
|
||
|
|
||
|
if(n == Wolf.ANG_0 || n == Wolf.ANG_360) {
|
||
|
XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n + 0.5)))>>0; // infinity
|
||
|
} else if (n == Wolf.ANG_180) {
|
||
|
XnextTable[n] = (Wolf.FLOATTILE / Math.tan(Wolf.FINE2RAD(n - 0.5)))>>0; // -infinity
|
||
|
} else if (n == Wolf.ANG_90 || n == Wolf.ANG_270) {
|
||
|
XnextTable[n] = 0;
|
||
|
} else {
|
||
|
XnextTable[n] = (Wolf.FLOATTILE / Math.tan(angle))>>0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
tanfov2 = (Math.tan(Wolf.DEG2RAD((calcFov(75, Wolf.XRES, Wolf.YRES) / 2.0)))) * (Wolf.XRES / Wolf.YRES);
|
||
|
for (n = 0; n < Wolf.XRES; ++n) {
|
||
|
tanval = tanfov2 * (-1.0 + 2.0 * n / (Wolf.XRES-1));
|
||
|
ColumnAngle[n] = Wolf.RAD2FINE(Math.atan(tanval)) >> 0;
|
||
|
}
|
||
|
|
||
|
Wolf.Random.init(1); // random number generators
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @description Calculate the field of view.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} fovX Must be within 1 and 179 degrees.
|
||
|
* @param {number} width Width of viewing area.
|
||
|
* @param {number} height Height of viewing area.
|
||
|
* @returns {number} The field of view in degrees.
|
||
|
*/
|
||
|
|
||
|
function calcFov(fovX, width, height) {
|
||
|
if (fovX < 1 || fovX > 179) {
|
||
|
throw Error("Bad fov: " + fovX );
|
||
|
}
|
||
|
|
||
|
return Wolf.RAD2DEG(Math.atan(height / (width / Math.tan(fovX / 360 * Math.PI)))) * 2;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @description Clips angle to [0..360] bounds.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} alpha Angle in degrees.
|
||
|
* @returns {number} Normalized angle.
|
||
|
*/
|
||
|
function normalizeAngle(alpha) {
|
||
|
if (alpha > Wolf.ANG_360) {
|
||
|
alpha %= Wolf.ANG_360;
|
||
|
}
|
||
|
if (alpha < Wolf.ANG_0) {
|
||
|
alpha = Wolf.ANG_360 - (-alpha) % Wolf.ANG_360;
|
||
|
}
|
||
|
return alpha;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @description Get quadrant.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} angle Radian angle.
|
||
|
* @returns {number}
|
||
|
*/
|
||
|
function getQuadrant(angle) {
|
||
|
angle = Wolf.Angle.normalize(angle);
|
||
|
|
||
|
if (angle < Math.PI / 2) {
|
||
|
return q_first;
|
||
|
} else if (angle < Math.PI) {
|
||
|
return q_second;
|
||
|
} else if (angle < 3 * Math.PI / 2) {
|
||
|
return q_third;
|
||
|
} else {
|
||
|
return q_fourth;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @description Get 4 point direction.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} angle Radian angle.
|
||
|
* @returns {number} Directional point.
|
||
|
*/
|
||
|
function get4dir(angle) {
|
||
|
angle = Wolf.Angle.normalize(angle + Math.PI / 4);
|
||
|
|
||
|
if (angle < Math.PI / 2) {
|
||
|
return dir4_east;
|
||
|
} else if( angle < Math.PI ) {
|
||
|
return dir4_north;
|
||
|
} else if( angle < 3 * Math.PI / 2 ) {
|
||
|
return dir4_west;
|
||
|
} else {
|
||
|
return dir4_south;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @description Get 8 point direction.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} angle Radian angle.
|
||
|
* @returns {number} Directional point.
|
||
|
*/
|
||
|
function get8dir(angle) {
|
||
|
angle = Wolf.Angle.normalize(angle + Math.PI / 12);
|
||
|
|
||
|
if ( angle <= (Math.PI / 4)) {
|
||
|
return dir8_east;
|
||
|
} else if (angle < (Math.PI / 2)) {
|
||
|
return dir8_northeast;
|
||
|
} else if (angle <= (3 * Math.PI / 4)) {
|
||
|
return dir8_north;
|
||
|
} else if (angle < Math.PI) {
|
||
|
return dir8_northwest;
|
||
|
} else if (angle <= (5 * Math.PI / 4)) {
|
||
|
return dir8_west;
|
||
|
} else if (angle < (3 * Math.PI / 2)) {
|
||
|
return dir8_southwest;
|
||
|
} else if (angle <= (7 * Math.PI / 4)) {
|
||
|
return dir8_south;
|
||
|
} else {
|
||
|
return dir8_southeast;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @description calculates distance between a point (x, y) and a line.
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} x X coord of point
|
||
|
* @param {number} y Y coord of point
|
||
|
* @param {number} a Line angle in degrees
|
||
|
* @returns {number} Distance
|
||
|
*/
|
||
|
function point2LineDist(x, y, a) {
|
||
|
return Math.abs( (x * SinTable[a] - y * CosTable[a]) >> 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @description Calculates line length to the point nearest to (poin).
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} x X coord of point
|
||
|
* @param {number} y Y coord of point
|
||
|
* @param {number} a Line angle in degrees
|
||
|
* @returns {number} Distance
|
||
|
*/
|
||
|
function lineLen2Point( x, y, a) {
|
||
|
return (x * CosTable[a] + y * SinTable[a]) >> 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
point2 = {x,y}
|
||
|
/ |
|
||
|
/ |
|
||
|
/ |
|
||
|
/a______|----------> x
|
||
|
point1 = {x, y}
|
||
|
*/
|
||
|
/**
|
||
|
* @description Returns angle in radians
|
||
|
* @memberOf Wolf.Math
|
||
|
* @param {number} x X coord of point
|
||
|
* @param {number} y Y coord of point
|
||
|
* @param {number} a Line angle in degrees
|
||
|
* @returns {number} Distance
|
||
|
*/
|
||
|
function transformPoint(point1X, point1Y, point2X, point2Y) {
|
||
|
var angle = Math.atan2(point1Y - point2Y, point1X - point2X);
|
||
|
return Wolf.Angle.normalize(angle);
|
||
|
}
|
||
|
|
||
|
|
||
|
buildTables();
|
||
|
|
||
|
return {
|
||
|
calcFov : calcFov,
|
||
|
normalizeAngle : normalizeAngle,
|
||
|
getQuadrant : getQuadrant,
|
||
|
get4dir : get4dir,
|
||
|
get8dir : get8dir,
|
||
|
point2LineDist : point2LineDist,
|
||
|
lineLen2Point : lineLen2Point,
|
||
|
transformPoint : transformPoint,
|
||
|
|
||
|
SinTable : SinTable,
|
||
|
CosTable : CosTable,
|
||
|
TanTable : TanTable,
|
||
|
XnextTable : XnextTable,
|
||
|
YnextTable : YnextTable,
|
||
|
ColumnAngle : ColumnAngle,
|
||
|
|
||
|
dir4_east : dir4_east,
|
||
|
dir4_north : dir4_north,
|
||
|
dir4_west : dir4_west,
|
||
|
dir4_south : dir4_south,
|
||
|
dir4_nodir : dir4_nodir,
|
||
|
dir8_east : dir8_east,
|
||
|
dir8_northeast : dir8_northeast,
|
||
|
dir8_north : dir8_north,
|
||
|
dir8_northwest : dir8_northwest,
|
||
|
dir8_west : dir8_west,
|
||
|
dir8_southwest : dir8_southwest,
|
||
|
dir8_south : dir8_south,
|
||
|
dir8_southeast : dir8_southeast,
|
||
|
dir8_nodir : dir8_nodir,
|
||
|
dx4dir : dx4dir,
|
||
|
dy4dir : dy4dir,
|
||
|
dx8dir : dx8dir,
|
||
|
dy8dir : dy8dir,
|
||
|
dir4angle : dir4angle,
|
||
|
dir8angle : dir8angle,
|
||
|
dir4to8 : dir4to8,
|
||
|
opposite4 : opposite4,
|
||
|
opposite8 : opposite8,
|
||
|
diagonal : diagonal
|
||
|
};
|
||
|
|
||
|
})();
|