1 /** 2 * @file 3 */ 4 5 /* 6 Copyright (C) 1997-2001 Id Software, Inc. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 17 See the GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23 */ 24 25 #pragma once 26 27 #include "ufotypes.h" 28 #include "defines.h" 29 #include <algorithm> 30 #include <cmath> 31 32 #ifndef M_PI 33 #define M_PI 3.14159265358979323846 /* matches value in gcc v2 math.h */ 34 #endif 35 36 #define EQUAL_EPSILON 0.001 37 38 bool Q_IsPowerOfTwo(int i); 39 40 /* Compare floats with custom epsilon error */ 41 #define EQUAL2(a,b,epsilon) (fabs((a)-(b))<epsilon) 42 43 /* microsoft's fabs seems to be ungodly slow... */ 44 #define Q_ftol(f) (long) (f) 45 46 #define torad (M_PI/180.0f) 47 #define todeg (180.0f/M_PI) 48 49 /* angle indexes */ 50 #define PITCH 0 /* rotation around y axis - up / down (-90 up to 90 degree) */ 51 #define YAW 1 /* rotation around z axis - left / right (0 up to 360 degree) */ 52 #define ROLL 2 /* rotation around x axis - fall over */ 53 54 /* axis */ 55 #define AXIS_FORWARD 0 56 #define AXIS_RIGHT 1 57 #define AXIS_UP 2 58 59 /* earth map data */ 60 /* values of sinus and cosinus of earth inclination (23,5 degrees) for faster day and night calculations */ 61 #define SIN_ALPHA 0.39875 62 #define COS_ALPHA 0.91706 63 #define HIGH_LAT +1.0 64 #define LOW_LAT -1.0 65 #define CENTER_LAT 0.0 66 #define SIZE_LAT 2.0 67 68 /** 69 * @brief Number of angles from a position (2-dimensional) 70 * @sa dvecs (in q_shared.c) for a description of its use. 71 * @sa AngleToDV. 72 * @sa BASE_DIRECTIONS 73 */ 74 #define DIRECTIONS 8 75 76 /** 77 * @brief Number of direct connected fields for a position 78 * @sa DIRECTIONS. 79 */ 80 #define BASE_DIRECTIONS 4 /* Only the standard N,S,E,W directions */ 81 82 /* game/g_ai.c, game/g_spawn.c, common/routing.c, ufo2map/routing.c, client/cl_actor.c, common/cmodel.c, shared/typedefs.h */ 83 #define PATHFINDING_DIRECTIONS 40 /* total number of directions */ 84 #define CORE_DIRECTIONS 8 /* The standard N,S,E,W directions plus diagonals. */ 85 #define FLYING_DIRECTIONS 16 /* starting number of directions available only to fliers */ 86 87 extern const vec4_t dvecs[PATHFINDING_DIRECTIONS]; 88 extern const float dvecsn[CORE_DIRECTIONS][2]; 89 extern const float directionAngles[CORE_DIRECTIONS]; 90 91 extern const byte dvright[CORE_DIRECTIONS]; 92 extern const byte dvleft[CORE_DIRECTIONS]; 93 94 /** @brief Map boundary is +/- MAX_WORLD_WIDTH - to get into the positive area we add the 95 * possible max negative value and divide by the size of a grid unit field */ 96 #define VecToPos(v, p) ( \ 97 (p)[0] = ((int)(v)[0] + MAX_WORLD_WIDTH) / UNIT_SIZE, \ 98 (p)[1] = ((int)(v)[1] + MAX_WORLD_WIDTH) / UNIT_SIZE, \ 99 (p)[2] = std::min((PATHFINDING_HEIGHT - 1), ((int)(v)[2] / UNIT_HEIGHT)) \ 100 ) 101 /** @brief Pos boundary size is +/- 128 - to get into the positive area we add 102 * the possible max negative value and multiply with the grid unit size to get 103 * back the vector coordinates - now go into the middle of the grid field 104 * by adding the half of the grid unit size to this value 105 * @sa PATHFINDING_WIDTH */ 106 #define PosToVec(p, v) ( \ 107 (v)[0] = ((int)(p)[0] - GRID_WIDTH) * UNIT_SIZE + UNIT_SIZE / 2, \ 108 (v)[1] = ((int)(p)[1] - GRID_WIDTH) * UNIT_SIZE + UNIT_SIZE / 2, \ 109 (v)[2] = (int)(p)[2] * UNIT_HEIGHT + UNIT_HEIGHT / 2 \ 110 ) 111 112 #include "vector.h" 113 #include "line.h" 114 #include "aabb.h" 115 116 class GridBox { 117 public: 118 static const GridBox EMPTY; 119 GridBox(const pos3_t mini,const pos3_t maxi)120 GridBox(const pos3_t mini, const pos3_t maxi) { 121 VectorCopy(mini, mins); 122 VectorCopy(maxi, maxs); 123 } 124 GridBox(const vec3_t mini,const vec3_t maxi)125 GridBox(const vec3_t mini, const vec3_t maxi) { 126 VecToPos(mini, mins); 127 VecToPos(maxi, maxs); 128 } 129 GridBox(const AABB & aabb)130 GridBox(const AABB& aabb) { 131 VecToPos(aabb.getMins(), mins); 132 VecToPos(aabb.getMaxs(), maxs); 133 } 134 isZero()135 inline bool isZero() const { 136 return VectorIntZero(mins) && VectorIntZero(maxs); 137 } 138 /** @brief expand the box in four directions, but clip them to the maximum boundaries 139 * @note this is pretty much nonsense with the current setting of PATHFINDING_WIDTH 140 * and the data type of pos3_t, but who knows the future... */ expandXY(const int byVal)141 inline void expandXY(const int byVal) { 142 mins[0] = std::max(mins[0] - byVal, 0); 143 mins[1] = std::max(mins[1] - byVal, 0); 144 maxs[0] = std::min(maxs[0] + byVal, PATHFINDING_WIDTH - 1); 145 maxs[1] = std::min(maxs[1] + byVal, PATHFINDING_WIDTH - 1); 146 } addOneZ()147 inline void addOneZ () { 148 maxs[2] = std::min(maxs[2] + 1, PATHFINDING_HEIGHT - 1); 149 } clipToMaxBoundaries()150 inline void clipToMaxBoundaries() { 151 return; /* do nothing, see above */ 152 } set(const pos3_t mini,const pos3_t maxi)153 inline void set(const pos3_t mini, const pos3_t maxi) { 154 VectorCopy(mini, mins); 155 VectorCopy(maxi, maxs); 156 } 157 158 pos3_t mins; 159 pos3_t maxs; 160 }; 161 162 /** @brief The direction vector tells us where the actor came from (in his previous step). 163 * The pathing table holds about a million of these dvecs, so we save quite some memory by squeezing 164 * three informations into a short value: 165 * - the direction where he came from 166 * - the z-level he came from 167 * - *how* he moved. There are three special crouching conditions 168 * -- autocrouch: standing upright in the previous cell, now crouch and stay crouched 169 * -- autocrouched: being already autocrouched in the previous cell, stand up if you get the chance 170 * -- autodive: we can stand in both cells, but there is just a small hole in the wall between them 171 */ 172 typedef short dvec_t; 173 #define DV_FLAGS_BIT_SHIFT 4 /**< This is the bit shift needed to store the 'how' component of a DV value */ 174 #define DV_DIR_BIT_SHIFT 8 /**< This is the bit shift needed to store the dir component of a DV value */ 175 #define DV_Z_BIT_MASK 0x0007 /**< The mask to retrieve the z component of a DV value */ 176 #define DV_FLAGS_BIT_MASK 0x00F0 /**< The mask to retrieve the 'how' component of a DV value */ 177 #define DV_DIR_BIT_MASK 0xFF00 /**< The mask to retrieve the dir component of a DV value */ 178 179 #define DV_FLAG_AUTOCROUCH 0x01 180 #define DV_FLAG_AUTOCROUCHED 0x02 181 #define DV_FLAG_AUTODIVE 0x04 182 183 #define makeDV(dir, z) (((dir) << DV_DIR_BIT_SHIFT) | ((z) & DV_Z_BIT_MASK)) 184 #define setDVz(dv, z) (((dv) & (~DV_Z_BIT_MASK)) | ((z) & DV_Z_BIT_MASK)) 185 #define getDVdir(dv) ((dv) >> DV_DIR_BIT_SHIFT) 186 #define getDVflags(dv) (((dv) & DV_FLAGS_BIT_MASK) >> DV_FLAGS_BIT_SHIFT) 187 #define getDVz(dv) ((dv) & DV_Z_BIT_MASK) 188 189 #define PosAddDV(p, crouch, dv) ((p)[0]+=dvecs[getDVdir(dv)][0], (p)[1]+=dvecs[getDVdir(dv)][1], (p)[2]=getDVz(dv), (crouch)+=dvecs[getDVdir(dv)][3]) 190 #define PosSubDV(p, crouch, dv) ((p)[0]-=dvecs[getDVdir(dv)][0], (p)[1]-=dvecs[getDVdir(dv)][1], (p)[2]=getDVz(dv), (crouch)-=dvecs[getDVdir(dv)][3]) 191 192 int AngleToDir(int angle); 193 #define AngleToDV(x) (AngleToDir(x) << DV_DIR_BIT_SHIFT) 194 195 void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector); 196 void VectorClampMA(vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc); 197 void VectorMix(const vec3_t v1, const vec3_t v2, const float mix, vec3_t out); 198 199 void MatrixMultiply(const vec3_t a[3], const vec3_t b[3], vec3_t c[3]); 200 void GLMatrixAssemble(const vec3_t origin, const vec3_t angles, float* matrix); 201 void GLMatrixMultiply(const float a[16], const float b[16], float c[16]); 202 void GLVectorTransform(const float m[16], const vec4_t in, vec4_t out); 203 void GLPositionTransform(const float m[16], const vec3_t in, vec3_t out); 204 void VectorRotate(vec3_t m[3], const vec3_t va, vec3_t vb); 205 206 void ClearBounds(vec3_t mins, vec3_t maxs); 207 void AddPointToBounds(const vec3_t v, vec3_t mins, vec3_t maxs); 208 int VectorCompareEps(const vec3_t v1, const vec3_t v2, float epsilon); 209 bool VectorNearer(const vec3_t v1, const vec3_t v2, const vec3_t comp); 210 vec_t VectorLength(const vec3_t v); 211 void CrossProduct(const vec3_t v1, const vec3_t v2, vec3_t cross); 212 vec_t VectorNormalize(vec3_t v); /* returns vector length */ 213 void VectorNormalizeFast(vec3_t v); 214 vec_t VectorNormalize2(const vec3_t v, vec3_t out); 215 void VectorInverse(vec3_t v); 216 void VectorMidpoint(const vec3_t point1, const vec3_t point2, vec3_t midpoint); 217 int Q_log2(int val); 218 219 double GetDistanceOnGlobe(const vec2_t pos1, const vec2_t pos2); 220 221 void VectorCenterFromMinsMaxs(const vec3_t mins, const vec3_t maxs, vec3_t center); 222 void VectorCalcMinsMaxs(const vec3_t center, const vec3_t size, vec3_t mins, vec3_t maxs); 223 float VectorAngleBetween(const vec3_t vec1, const vec3_t vec2); 224 225 void VecToAngles(const vec3_t vec, vec3_t angles); 226 227 void Print2Vector(const vec2_t v, const char* text); 228 void Print3Vector(const vec3_t v, const char* text); 229 230 void VecToPolar(const vec3_t v, vec2_t a); 231 void PolarToVec(const vec2_t a, vec3_t v); 232 233 void CalculateMinsMaxs(const vec3_t angles, const vec3_t mins, const vec3_t maxs, const vec3_t origin, vec3_t absmin, vec3_t absmax); 234 235 void VectorCreateRotationMatrix(const vec3_t angles, vec3_t matrix[3]); 236 void VectorRotatePoint(vec3_t point, vec3_t matrix[3]); 237 238 void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); 239 float AngleNormalize360(float angle); 240 float AngleNormalize180(float angle); 241 242 float LerpAngle(float a1, float a2, float frac); 243 244 bool FrustumVis(const vec3_t origin, int dir, const vec3_t point); 245 246 void PerpendicularVector(vec3_t dst, const vec3_t src); 247 void RotatePointAroundVector(vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); 248 249 float frand(void); /* 0 to 1 */ 250 float crand(void); /* -1 to 1 */ 251 void gaussrand(float* gauss1, float* gauss2); /* -inf to +inf, median 0, stdev 1 */ 252 253 vec_t Q_rint(const vec_t in); 254 vec_t ColorNormalize(const vec3_t in, vec3_t out); 255 256 void TangentVectors(const vec3_t normal, const vec3_t sdir, const vec3_t tdir, vec4_t tangent, vec3_t binormal); 257 258 void Orthogonalize(vec3_t v1, const vec3_t v2); 259 void MatrixTranspose(const vec3_t m[3], vec3_t t[3]); 260 261 bool RayIntersectAABB(const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs); 262