PageRenderTime 29ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/quake3/trunk/code/game/q_math.c

#
C | 1308 lines | 936 code | 173 blank | 199 comment | 73 complexity | cf096cd4413d11546bfd0dd3c01ed9d7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. //
  19. // q_math.c -- stateless support routines that are included in each code module
  20. #include "q_shared.h"
  21. vec3_t vec3_origin = {0,0,0};
  22. vec3_t axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
  23. vec4_t colorBlack = {0, 0, 0, 1};
  24. vec4_t colorRed = {1, 0, 0, 1};
  25. vec4_t colorGreen = {0, 1, 0, 1};
  26. vec4_t colorBlue = {0, 0, 1, 1};
  27. vec4_t colorYellow = {1, 1, 0, 1};
  28. vec4_t colorMagenta= {1, 0, 1, 1};
  29. vec4_t colorCyan = {0, 1, 1, 1};
  30. vec4_t colorWhite = {1, 1, 1, 1};
  31. vec4_t colorLtGrey = {0.75, 0.75, 0.75, 1};
  32. vec4_t colorMdGrey = {0.5, 0.5, 0.5, 1};
  33. vec4_t colorDkGrey = {0.25, 0.25, 0.25, 1};
  34. vec4_t g_color_table[8] =
  35. {
  36. {0.0, 0.0, 0.0, 1.0},
  37. {1.0, 0.0, 0.0, 1.0},
  38. {0.0, 1.0, 0.0, 1.0},
  39. {1.0, 1.0, 0.0, 1.0},
  40. {0.0, 0.0, 1.0, 1.0},
  41. {0.0, 1.0, 1.0, 1.0},
  42. {1.0, 0.0, 1.0, 1.0},
  43. {1.0, 1.0, 1.0, 1.0},
  44. };
  45. vec3_t bytedirs[NUMVERTEXNORMALS] =
  46. {
  47. {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
  48. {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
  49. {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
  50. {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
  51. {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
  52. {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
  53. {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
  54. {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
  55. {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},
  56. {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},
  57. {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},
  58. {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
  59. {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
  60. {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
  61. {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
  62. {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
  63. {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
  64. {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
  65. {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
  66. {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},
  67. {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},
  68. {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
  69. {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
  70. {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
  71. {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
  72. {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
  73. {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
  74. {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},
  75. {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
  76. {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
  77. {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
  78. {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
  79. {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
  80. {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},
  81. {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
  82. {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
  83. {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
  84. {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
  85. {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
  86. {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
  87. {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
  88. {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
  89. {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
  90. {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
  91. {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
  92. {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
  93. {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
  94. {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
  95. {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
  96. {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
  97. {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
  98. {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
  99. {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
  100. {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
  101. {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
  102. {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
  103. {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
  104. {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
  105. {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
  106. {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
  107. {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
  108. {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
  109. {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
  110. {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
  111. {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
  112. {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
  113. {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
  114. {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
  115. {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
  116. {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
  117. {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
  118. {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
  119. {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
  120. {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
  121. {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
  122. {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
  123. {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
  124. {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
  125. {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
  126. {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
  127. {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
  128. };
  129. //==============================================================
  130. int Q_rand( int *seed ) {
  131. *seed = (69069 * *seed + 1);
  132. return *seed;
  133. }
  134. float Q_random( int *seed ) {
  135. return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
  136. }
  137. float Q_crandom( int *seed ) {
  138. return 2.0 * ( Q_random( seed ) - 0.5 );
  139. }
  140. #ifdef __LCC__
  141. int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
  142. if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
  143. return 0;
  144. }
  145. return 1;
  146. }
  147. vec_t VectorLength( const vec3_t v ) {
  148. return (vec_t)sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  149. }
  150. vec_t VectorLengthSquared( const vec3_t v ) {
  151. return (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  152. }
  153. vec_t Distance( const vec3_t p1, const vec3_t p2 ) {
  154. vec3_t v;
  155. VectorSubtract (p2, p1, v);
  156. return VectorLength( v );
  157. }
  158. vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ) {
  159. vec3_t v;
  160. VectorSubtract (p2, p1, v);
  161. return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  162. }
  163. // fast vector normalize routine that does not check to make sure
  164. // that length != 0, nor does it return length, uses rsqrt approximation
  165. void VectorNormalizeFast( vec3_t v )
  166. {
  167. float ilength;
  168. ilength = Q_rsqrt( DotProduct( v, v ) );
  169. v[0] *= ilength;
  170. v[1] *= ilength;
  171. v[2] *= ilength;
  172. }
  173. void VectorInverse( vec3_t v ){
  174. v[0] = -v[0];
  175. v[1] = -v[1];
  176. v[2] = -v[2];
  177. }
  178. void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) {
  179. cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
  180. cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
  181. cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
  182. }
  183. #endif
  184. //=======================================================
  185. signed char ClampChar( int i ) {
  186. if ( i < -128 ) {
  187. return -128;
  188. }
  189. if ( i > 127 ) {
  190. return 127;
  191. }
  192. return i;
  193. }
  194. signed short ClampShort( int i ) {
  195. if ( i < -32768 ) {
  196. return -32768;
  197. }
  198. if ( i > 0x7fff ) {
  199. return 0x7fff;
  200. }
  201. return i;
  202. }
  203. // this isn't a real cheap function to call!
  204. int DirToByte( vec3_t dir ) {
  205. int i, best;
  206. float d, bestd;
  207. if ( !dir ) {
  208. return 0;
  209. }
  210. bestd = 0;
  211. best = 0;
  212. for (i=0 ; i<NUMVERTEXNORMALS ; i++)
  213. {
  214. d = DotProduct (dir, bytedirs[i]);
  215. if (d > bestd)
  216. {
  217. bestd = d;
  218. best = i;
  219. }
  220. }
  221. return best;
  222. }
  223. void ByteToDir( int b, vec3_t dir ) {
  224. if ( b < 0 || b >= NUMVERTEXNORMALS ) {
  225. VectorCopy( vec3_origin, dir );
  226. return;
  227. }
  228. VectorCopy (bytedirs[b], dir);
  229. }
  230. unsigned ColorBytes3 (float r, float g, float b) {
  231. unsigned i;
  232. ( (byte *)&i )[0] = r * 255;
  233. ( (byte *)&i )[1] = g * 255;
  234. ( (byte *)&i )[2] = b * 255;
  235. return i;
  236. }
  237. unsigned ColorBytes4 (float r, float g, float b, float a) {
  238. unsigned i;
  239. ( (byte *)&i )[0] = r * 255;
  240. ( (byte *)&i )[1] = g * 255;
  241. ( (byte *)&i )[2] = b * 255;
  242. ( (byte *)&i )[3] = a * 255;
  243. return i;
  244. }
  245. float NormalizeColor( const vec3_t in, vec3_t out ) {
  246. float max;
  247. max = in[0];
  248. if ( in[1] > max ) {
  249. max = in[1];
  250. }
  251. if ( in[2] > max ) {
  252. max = in[2];
  253. }
  254. if ( !max ) {
  255. VectorClear( out );
  256. } else {
  257. out[0] = in[0] / max;
  258. out[1] = in[1] / max;
  259. out[2] = in[2] / max;
  260. }
  261. return max;
  262. }
  263. /*
  264. =====================
  265. PlaneFromPoints
  266. Returns false if the triangle is degenrate.
  267. The normal will point out of the clock for clockwise ordered points
  268. =====================
  269. */
  270. qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
  271. vec3_t d1, d2;
  272. VectorSubtract( b, a, d1 );
  273. VectorSubtract( c, a, d2 );
  274. CrossProduct( d2, d1, plane );
  275. if ( VectorNormalize( plane ) == 0 ) {
  276. return qfalse;
  277. }
  278. plane[3] = DotProduct( a, plane );
  279. return qtrue;
  280. }
  281. /*
  282. ===============
  283. RotatePointAroundVector
  284. This is not implemented very well...
  285. ===============
  286. */
  287. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
  288. float degrees ) {
  289. float m[3][3];
  290. float im[3][3];
  291. float zrot[3][3];
  292. float tmpmat[3][3];
  293. float rot[3][3];
  294. int i;
  295. vec3_t vr, vup, vf;
  296. float rad;
  297. vf[0] = dir[0];
  298. vf[1] = dir[1];
  299. vf[2] = dir[2];
  300. PerpendicularVector( vr, dir );
  301. CrossProduct( vr, vf, vup );
  302. m[0][0] = vr[0];
  303. m[1][0] = vr[1];
  304. m[2][0] = vr[2];
  305. m[0][1] = vup[0];
  306. m[1][1] = vup[1];
  307. m[2][1] = vup[2];
  308. m[0][2] = vf[0];
  309. m[1][2] = vf[1];
  310. m[2][2] = vf[2];
  311. memcpy( im, m, sizeof( im ) );
  312. im[0][1] = m[1][0];
  313. im[0][2] = m[2][0];
  314. im[1][0] = m[0][1];
  315. im[1][2] = m[2][1];
  316. im[2][0] = m[0][2];
  317. im[2][1] = m[1][2];
  318. memset( zrot, 0, sizeof( zrot ) );
  319. zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
  320. rad = DEG2RAD( degrees );
  321. zrot[0][0] = cos( rad );
  322. zrot[0][1] = sin( rad );
  323. zrot[1][0] = -sin( rad );
  324. zrot[1][1] = cos( rad );
  325. MatrixMultiply( m, zrot, tmpmat );
  326. MatrixMultiply( tmpmat, im, rot );
  327. for ( i = 0; i < 3; i++ ) {
  328. dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
  329. }
  330. }
  331. /*
  332. ===============
  333. RotateAroundDirection
  334. ===============
  335. */
  336. void RotateAroundDirection( vec3_t axis[3], float yaw ) {
  337. // create an arbitrary axis[1]
  338. PerpendicularVector( axis[1], axis[0] );
  339. // rotate it around axis[0] by yaw
  340. if ( yaw ) {
  341. vec3_t temp;
  342. VectorCopy( axis[1], temp );
  343. RotatePointAroundVector( axis[1], axis[0], temp, yaw );
  344. }
  345. // cross to get axis[2]
  346. CrossProduct( axis[0], axis[1], axis[2] );
  347. }
  348. void vectoangles( const vec3_t value1, vec3_t angles ) {
  349. float forward;
  350. float yaw, pitch;
  351. if ( value1[1] == 0 && value1[0] == 0 ) {
  352. yaw = 0;
  353. if ( value1[2] > 0 ) {
  354. pitch = 90;
  355. }
  356. else {
  357. pitch = 270;
  358. }
  359. }
  360. else {
  361. if ( value1[0] ) {
  362. yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
  363. }
  364. else if ( value1[1] > 0 ) {
  365. yaw = 90;
  366. }
  367. else {
  368. yaw = 270;
  369. }
  370. if ( yaw < 0 ) {
  371. yaw += 360;
  372. }
  373. forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
  374. pitch = ( atan2(value1[2], forward) * 180 / M_PI );
  375. if ( pitch < 0 ) {
  376. pitch += 360;
  377. }
  378. }
  379. angles[PITCH] = -pitch;
  380. angles[YAW] = yaw;
  381. angles[ROLL] = 0;
  382. }
  383. /*
  384. =================
  385. AnglesToAxis
  386. =================
  387. */
  388. void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
  389. vec3_t right;
  390. // angle vectors returns "right" instead of "y axis"
  391. AngleVectors( angles, axis[0], right, axis[2] );
  392. VectorSubtract( vec3_origin, right, axis[1] );
  393. }
  394. void AxisClear( vec3_t axis[3] ) {
  395. axis[0][0] = 1;
  396. axis[0][1] = 0;
  397. axis[0][2] = 0;
  398. axis[1][0] = 0;
  399. axis[1][1] = 1;
  400. axis[1][2] = 0;
  401. axis[2][0] = 0;
  402. axis[2][1] = 0;
  403. axis[2][2] = 1;
  404. }
  405. void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
  406. VectorCopy( in[0], out[0] );
  407. VectorCopy( in[1], out[1] );
  408. VectorCopy( in[2], out[2] );
  409. }
  410. void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  411. {
  412. float d;
  413. vec3_t n;
  414. float inv_denom;
  415. inv_denom = DotProduct( normal, normal );
  416. #ifndef Q3_VM
  417. assert( Q_fabs(inv_denom) != 0.0f ); // bk010122 - zero vectors get here
  418. #endif
  419. inv_denom = 1.0f / inv_denom;
  420. d = DotProduct( normal, p ) * inv_denom;
  421. n[0] = normal[0] * inv_denom;
  422. n[1] = normal[1] * inv_denom;
  423. n[2] = normal[2] * inv_denom;
  424. dst[0] = p[0] - d * n[0];
  425. dst[1] = p[1] - d * n[1];
  426. dst[2] = p[2] - d * n[2];
  427. }
  428. /*
  429. ================
  430. MakeNormalVectors
  431. Given a normalized forward vector, create two
  432. other perpendicular vectors
  433. ================
  434. */
  435. void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
  436. float d;
  437. // this rotate and negate guarantees a vector
  438. // not colinear with the original
  439. right[1] = -forward[0];
  440. right[2] = forward[1];
  441. right[0] = forward[2];
  442. d = DotProduct (right, forward);
  443. VectorMA (right, -d, forward, right);
  444. VectorNormalize (right);
  445. CrossProduct (right, forward, up);
  446. }
  447. void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
  448. {
  449. out[0] = DotProduct( in, matrix[0] );
  450. out[1] = DotProduct( in, matrix[1] );
  451. out[2] = DotProduct( in, matrix[2] );
  452. }
  453. //============================================================================
  454. #if !idppc
  455. /*
  456. ** float q_rsqrt( float number )
  457. */
  458. float Q_rsqrt( float number )
  459. {
  460. long i;
  461. float x2, y;
  462. const float threehalfs = 1.5F;
  463. x2 = number * 0.5F;
  464. y = number;
  465. i = * ( long * ) &y; // evil floating point bit level hacking
  466. i = 0x5f3759df - ( i >> 1 ); // what the fuck?
  467. y = * ( float * ) &i;
  468. y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  469. // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  470. #ifndef Q3_VM
  471. #ifdef __linux__
  472. assert( !isnan(y) ); // bk010122 - FPE?
  473. #endif
  474. #endif
  475. return y;
  476. }
  477. float Q_fabs( float f ) {
  478. int tmp = * ( int * ) &f;
  479. tmp &= 0x7FFFFFFF;
  480. return * ( float * ) &tmp;
  481. }
  482. #endif
  483. //============================================================
  484. /*
  485. ===============
  486. LerpAngle
  487. ===============
  488. */
  489. float LerpAngle (float from, float to, float frac) {
  490. float a;
  491. if ( to - from > 180 ) {
  492. to -= 360;
  493. }
  494. if ( to - from < -180 ) {
  495. to += 360;
  496. }
  497. a = from + frac * (to - from);
  498. return a;
  499. }
  500. /*
  501. =================
  502. AngleSubtract
  503. Always returns a value from -180 to 180
  504. =================
  505. */
  506. float AngleSubtract( float a1, float a2 ) {
  507. float a;
  508. a = a1 - a2;
  509. while ( a > 180 ) {
  510. a -= 360;
  511. }
  512. while ( a < -180 ) {
  513. a += 360;
  514. }
  515. return a;
  516. }
  517. void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
  518. v3[0] = AngleSubtract( v1[0], v2[0] );
  519. v3[1] = AngleSubtract( v1[1], v2[1] );
  520. v3[2] = AngleSubtract( v1[2], v2[2] );
  521. }
  522. float AngleMod(float a) {
  523. a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
  524. return a;
  525. }
  526. /*
  527. =================
  528. AngleNormalize360
  529. returns angle normalized to the range [0 <= angle < 360]
  530. =================
  531. */
  532. float AngleNormalize360 ( float angle ) {
  533. return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
  534. }
  535. /*
  536. =================
  537. AngleNormalize180
  538. returns angle normalized to the range [-180 < angle <= 180]
  539. =================
  540. */
  541. float AngleNormalize180 ( float angle ) {
  542. angle = AngleNormalize360( angle );
  543. if ( angle > 180.0 ) {
  544. angle -= 360.0;
  545. }
  546. return angle;
  547. }
  548. /*
  549. =================
  550. AngleDelta
  551. returns the normalized delta from angle1 to angle2
  552. =================
  553. */
  554. float AngleDelta ( float angle1, float angle2 ) {
  555. return AngleNormalize180( angle1 - angle2 );
  556. }
  557. //============================================================
  558. /*
  559. =================
  560. SetPlaneSignbits
  561. =================
  562. */
  563. void SetPlaneSignbits (cplane_t *out) {
  564. int bits, j;
  565. // for fast box on planeside test
  566. bits = 0;
  567. for (j=0 ; j<3 ; j++) {
  568. if (out->normal[j] < 0) {
  569. bits |= 1<<j;
  570. }
  571. }
  572. out->signbits = bits;
  573. }
  574. /*
  575. ==================
  576. BoxOnPlaneSide
  577. Returns 1, 2, or 1 + 2
  578. // this is the slow, general version
  579. int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  580. {
  581. int i;
  582. float dist1, dist2;
  583. int sides;
  584. vec3_t corners[2];
  585. for (i=0 ; i<3 ; i++)
  586. {
  587. if (p->normal[i] < 0)
  588. {
  589. corners[0][i] = emins[i];
  590. corners[1][i] = emaxs[i];
  591. }
  592. else
  593. {
  594. corners[1][i] = emins[i];
  595. corners[0][i] = emaxs[i];
  596. }
  597. }
  598. dist1 = DotProduct (p->normal, corners[0]) - p->dist;
  599. dist2 = DotProduct (p->normal, corners[1]) - p->dist;
  600. sides = 0;
  601. if (dist1 >= 0)
  602. sides = 1;
  603. if (dist2 < 0)
  604. sides |= 2;
  605. return sides;
  606. }
  607. ==================
  608. */
  609. #if !( (defined __linux__ || __FreeBSD__) && (defined __i386__) && (!defined C_ONLY)) // rb010123
  610. #if defined __LCC__ || defined C_ONLY || !id386 || defined __VECTORC
  611. int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  612. {
  613. float dist1, dist2;
  614. int sides;
  615. // fast axial cases
  616. if (p->type < 3)
  617. {
  618. if (p->dist <= emins[p->type])
  619. return 1;
  620. if (p->dist >= emaxs[p->type])
  621. return 2;
  622. return 3;
  623. }
  624. // general case
  625. switch (p->signbits)
  626. {
  627. case 0:
  628. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  629. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  630. break;
  631. case 1:
  632. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  633. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  634. break;
  635. case 2:
  636. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  637. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  638. break;
  639. case 3:
  640. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  641. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  642. break;
  643. case 4:
  644. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  645. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  646. break;
  647. case 5:
  648. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  649. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  650. break;
  651. case 6:
  652. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  653. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  654. break;
  655. case 7:
  656. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  657. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  658. break;
  659. default:
  660. dist1 = dist2 = 0; // shut up compiler
  661. break;
  662. }
  663. sides = 0;
  664. if (dist1 >= p->dist)
  665. sides = 1;
  666. if (dist2 < p->dist)
  667. sides |= 2;
  668. return sides;
  669. }
  670. #else
  671. #pragma warning( disable: 4035 )
  672. __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  673. {
  674. static int bops_initialized;
  675. static int Ljmptab[8];
  676. __asm {
  677. push ebx
  678. cmp bops_initialized, 1
  679. je initialized
  680. mov bops_initialized, 1
  681. mov Ljmptab[0*4], offset Lcase0
  682. mov Ljmptab[1*4], offset Lcase1
  683. mov Ljmptab[2*4], offset Lcase2
  684. mov Ljmptab[3*4], offset Lcase3
  685. mov Ljmptab[4*4], offset Lcase4
  686. mov Ljmptab[5*4], offset Lcase5
  687. mov Ljmptab[6*4], offset Lcase6
  688. mov Ljmptab[7*4], offset Lcase7
  689. initialized:
  690. mov edx,dword ptr[4+12+esp]
  691. mov ecx,dword ptr[4+4+esp]
  692. xor eax,eax
  693. mov ebx,dword ptr[4+8+esp]
  694. mov al,byte ptr[17+edx]
  695. cmp al,8
  696. jge Lerror
  697. fld dword ptr[0+edx]
  698. fld st(0)
  699. jmp dword ptr[Ljmptab+eax*4]
  700. Lcase0:
  701. fmul dword ptr[ebx]
  702. fld dword ptr[0+4+edx]
  703. fxch st(2)
  704. fmul dword ptr[ecx]
  705. fxch st(2)
  706. fld st(0)
  707. fmul dword ptr[4+ebx]
  708. fld dword ptr[0+8+edx]
  709. fxch st(2)
  710. fmul dword ptr[4+ecx]
  711. fxch st(2)
  712. fld st(0)
  713. fmul dword ptr[8+ebx]
  714. fxch st(5)
  715. faddp st(3),st(0)
  716. fmul dword ptr[8+ecx]
  717. fxch st(1)
  718. faddp st(3),st(0)
  719. fxch st(3)
  720. faddp st(2),st(0)
  721. jmp LSetSides
  722. Lcase1:
  723. fmul dword ptr[ecx]
  724. fld dword ptr[0+4+edx]
  725. fxch st(2)
  726. fmul dword ptr[ebx]
  727. fxch st(2)
  728. fld st(0)
  729. fmul dword ptr[4+ebx]
  730. fld dword ptr[0+8+edx]
  731. fxch st(2)
  732. fmul dword ptr[4+ecx]
  733. fxch st(2)
  734. fld st(0)
  735. fmul dword ptr[8+ebx]
  736. fxch st(5)
  737. faddp st(3),st(0)
  738. fmul dword ptr[8+ecx]
  739. fxch st(1)
  740. faddp st(3),st(0)
  741. fxch st(3)
  742. faddp st(2),st(0)
  743. jmp LSetSides
  744. Lcase2:
  745. fmul dword ptr[ebx]
  746. fld dword ptr[0+4+edx]
  747. fxch st(2)
  748. fmul dword ptr[ecx]
  749. fxch st(2)
  750. fld st(0)
  751. fmul dword ptr[4+ecx]
  752. fld dword ptr[0+8+edx]
  753. fxch st(2)
  754. fmul dword ptr[4+ebx]
  755. fxch st(2)
  756. fld st(0)
  757. fmul dword ptr[8+ebx]
  758. fxch st(5)
  759. faddp st(3),st(0)
  760. fmul dword ptr[8+ecx]
  761. fxch st(1)
  762. faddp st(3),st(0)
  763. fxch st(3)
  764. faddp st(2),st(0)
  765. jmp LSetSides
  766. Lcase3:
  767. fmul dword ptr[ecx]
  768. fld dword ptr[0+4+edx]
  769. fxch st(2)
  770. fmul dword ptr[ebx]
  771. fxch st(2)
  772. fld st(0)
  773. fmul dword ptr[4+ecx]
  774. fld dword ptr[0+8+edx]
  775. fxch st(2)
  776. fmul dword ptr[4+ebx]
  777. fxch st(2)
  778. fld st(0)
  779. fmul dword ptr[8+ebx]
  780. fxch st(5)
  781. faddp st(3),st(0)
  782. fmul dword ptr[8+ecx]
  783. fxch st(1)
  784. faddp st(3),st(0)
  785. fxch st(3)
  786. faddp st(2),st(0)
  787. jmp LSetSides
  788. Lcase4:
  789. fmul dword ptr[ebx]
  790. fld dword ptr[0+4+edx]
  791. fxch st(2)
  792. fmul dword ptr[ecx]
  793. fxch st(2)
  794. fld st(0)
  795. fmul dword ptr[4+ebx]
  796. fld dword ptr[0+8+edx]
  797. fxch st(2)
  798. fmul dword ptr[4+ecx]
  799. fxch st(2)
  800. fld st(0)
  801. fmul dword ptr[8+ecx]
  802. fxch st(5)
  803. faddp st(3),st(0)
  804. fmul dword ptr[8+ebx]
  805. fxch st(1)
  806. faddp st(3),st(0)
  807. fxch st(3)
  808. faddp st(2),st(0)
  809. jmp LSetSides
  810. Lcase5:
  811. fmul dword ptr[ecx]
  812. fld dword ptr[0+4+edx]
  813. fxch st(2)
  814. fmul dword ptr[ebx]
  815. fxch st(2)
  816. fld st(0)
  817. fmul dword ptr[4+ebx]
  818. fld dword ptr[0+8+edx]
  819. fxch st(2)
  820. fmul dword ptr[4+ecx]
  821. fxch st(2)
  822. fld st(0)
  823. fmul dword ptr[8+ecx]
  824. fxch st(5)
  825. faddp st(3),st(0)
  826. fmul dword ptr[8+ebx]
  827. fxch st(1)
  828. faddp st(3),st(0)
  829. fxch st(3)
  830. faddp st(2),st(0)
  831. jmp LSetSides
  832. Lcase6:
  833. fmul dword ptr[ebx]
  834. fld dword ptr[0+4+edx]
  835. fxch st(2)
  836. fmul dword ptr[ecx]
  837. fxch st(2)
  838. fld st(0)
  839. fmul dword ptr[4+ecx]
  840. fld dword ptr[0+8+edx]
  841. fxch st(2)
  842. fmul dword ptr[4+ebx]
  843. fxch st(2)
  844. fld st(0)
  845. fmul dword ptr[8+ecx]
  846. fxch st(5)
  847. faddp st(3),st(0)
  848. fmul dword ptr[8+ebx]
  849. fxch st(1)
  850. faddp st(3),st(0)
  851. fxch st(3)
  852. faddp st(2),st(0)
  853. jmp LSetSides
  854. Lcase7:
  855. fmul dword ptr[ecx]
  856. fld dword ptr[0+4+edx]
  857. fxch st(2)
  858. fmul dword ptr[ebx]
  859. fxch st(2)
  860. fld st(0)
  861. fmul dword ptr[4+ecx]
  862. fld dword ptr[0+8+edx]
  863. fxch st(2)
  864. fmul dword ptr[4+ebx]
  865. fxch st(2)
  866. fld st(0)
  867. fmul dword ptr[8+ecx]
  868. fxch st(5)
  869. faddp st(3),st(0)
  870. fmul dword ptr[8+ebx]
  871. fxch st(1)
  872. faddp st(3),st(0)
  873. fxch st(3)
  874. faddp st(2),st(0)
  875. LSetSides:
  876. faddp st(2),st(0)
  877. fcomp dword ptr[12+edx]
  878. xor ecx,ecx
  879. fnstsw ax
  880. fcomp dword ptr[12+edx]
  881. and ah,1
  882. xor ah,1
  883. add cl,ah
  884. fnstsw ax
  885. and ah,1
  886. add ah,ah
  887. add cl,ah
  888. pop ebx
  889. mov eax,ecx
  890. ret
  891. Lerror:
  892. int 3
  893. }
  894. }
  895. #pragma warning( default: 4035 )
  896. #endif
  897. #endif
  898. /*
  899. =================
  900. RadiusFromBounds
  901. =================
  902. */
  903. float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
  904. int i;
  905. vec3_t corner;
  906. float a, b;
  907. for (i=0 ; i<3 ; i++) {
  908. a = fabs( mins[i] );
  909. b = fabs( maxs[i] );
  910. corner[i] = a > b ? a : b;
  911. }
  912. return VectorLength (corner);
  913. }
  914. void ClearBounds( vec3_t mins, vec3_t maxs ) {
  915. mins[0] = mins[1] = mins[2] = 99999;
  916. maxs[0] = maxs[1] = maxs[2] = -99999;
  917. }
  918. void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
  919. if ( v[0] < mins[0] ) {
  920. mins[0] = v[0];
  921. }
  922. if ( v[0] > maxs[0]) {
  923. maxs[0] = v[0];
  924. }
  925. if ( v[1] < mins[1] ) {
  926. mins[1] = v[1];
  927. }
  928. if ( v[1] > maxs[1]) {
  929. maxs[1] = v[1];
  930. }
  931. if ( v[2] < mins[2] ) {
  932. mins[2] = v[2];
  933. }
  934. if ( v[2] > maxs[2]) {
  935. maxs[2] = v[2];
  936. }
  937. }
  938. vec_t VectorNormalize( vec3_t v ) {
  939. // NOTE: TTimo - Apple G4 altivec source uses double?
  940. float length, ilength;
  941. length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  942. length = sqrt (length);
  943. if ( length ) {
  944. ilength = 1/length;
  945. v[0] *= ilength;
  946. v[1] *= ilength;
  947. v[2] *= ilength;
  948. }
  949. return length;
  950. }
  951. vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
  952. float length, ilength;
  953. length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  954. length = sqrt (length);
  955. if (length)
  956. {
  957. #ifndef Q3_VM // bk0101022 - FPE related
  958. // assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
  959. #endif
  960. ilength = 1/length;
  961. out[0] = v[0]*ilength;
  962. out[1] = v[1]*ilength;
  963. out[2] = v[2]*ilength;
  964. } else {
  965. #ifndef Q3_VM // bk0101022 - FPE related
  966. // assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) );
  967. #endif
  968. VectorClear( out );
  969. }
  970. return length;
  971. }
  972. void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
  973. vecc[0] = veca[0] + scale*vecb[0];
  974. vecc[1] = veca[1] + scale*vecb[1];
  975. vecc[2] = veca[2] + scale*vecb[2];
  976. }
  977. vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
  978. return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
  979. }
  980. void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
  981. out[0] = veca[0]-vecb[0];
  982. out[1] = veca[1]-vecb[1];
  983. out[2] = veca[2]-vecb[2];
  984. }
  985. void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
  986. out[0] = veca[0]+vecb[0];
  987. out[1] = veca[1]+vecb[1];
  988. out[2] = veca[2]+vecb[2];
  989. }
  990. void _VectorCopy( const vec3_t in, vec3_t out ) {
  991. out[0] = in[0];
  992. out[1] = in[1];
  993. out[2] = in[2];
  994. }
  995. void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
  996. out[0] = in[0]*scale;
  997. out[1] = in[1]*scale;
  998. out[2] = in[2]*scale;
  999. }
  1000. void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
  1001. out[0] = in[0]*scale;
  1002. out[1] = in[1]*scale;
  1003. out[2] = in[2]*scale;
  1004. out[3] = in[3]*scale;
  1005. }
  1006. int Q_log2( int val ) {
  1007. int answer;
  1008. answer = 0;
  1009. while ( ( val>>=1 ) != 0 ) {
  1010. answer++;
  1011. }
  1012. return answer;
  1013. }
  1014. /*
  1015. =================
  1016. PlaneTypeForNormal
  1017. =================
  1018. */
  1019. /*
  1020. int PlaneTypeForNormal (vec3_t normal) {
  1021. if ( normal[0] == 1.0 )
  1022. return PLANE_X;
  1023. if ( normal[1] == 1.0 )
  1024. return PLANE_Y;
  1025. if ( normal[2] == 1.0 )
  1026. return PLANE_Z;
  1027. return PLANE_NON_AXIAL;
  1028. }
  1029. */
  1030. /*
  1031. ================
  1032. MatrixMultiply
  1033. ================
  1034. */
  1035. void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
  1036. out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  1037. in1[0][2] * in2[2][0];
  1038. out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  1039. in1[0][2] * in2[2][1];
  1040. out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  1041. in1[0][2] * in2[2][2];
  1042. out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  1043. in1[1][2] * in2[2][0];
  1044. out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  1045. in1[1][2] * in2[2][1];
  1046. out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  1047. in1[1][2] * in2[2][2];
  1048. out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  1049. in1[2][2] * in2[2][0];
  1050. out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  1051. in1[2][2] * in2[2][1];
  1052. out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  1053. in1[2][2] * in2[2][2];
  1054. }
  1055. void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
  1056. float angle;
  1057. static float sr, sp, sy, cr, cp, cy;
  1058. // static to help MS compiler fp bugs
  1059. angle = angles[YAW] * (M_PI*2 / 360);
  1060. sy = sin(angle);
  1061. cy = cos(angle);
  1062. angle = angles[PITCH] * (M_PI*2 / 360);
  1063. sp = sin(angle);
  1064. cp = cos(angle);
  1065. angle = angles[ROLL] * (M_PI*2 / 360);
  1066. sr = sin(angle);
  1067. cr = cos(angle);
  1068. if (forward)
  1069. {
  1070. forward[0] = cp*cy;
  1071. forward[1] = cp*sy;
  1072. forward[2] = -sp;
  1073. }
  1074. if (right)
  1075. {
  1076. right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  1077. right[1] = (-1*sr*sp*sy+-1*cr*cy);
  1078. right[2] = -1*sr*cp;
  1079. }
  1080. if (up)
  1081. {
  1082. up[0] = (cr*sp*cy+-sr*-sy);
  1083. up[1] = (cr*sp*sy+-sr*cy);
  1084. up[2] = cr*cp;
  1085. }
  1086. }
  1087. /*
  1088. ** assumes "src" is normalized
  1089. */
  1090. void PerpendicularVector( vec3_t dst, const vec3_t src )
  1091. {
  1092. int pos;
  1093. int i;
  1094. float minelem = 1.0F;
  1095. vec3_t tempvec;
  1096. /*
  1097. ** find the smallest magnitude axially aligned vector
  1098. */
  1099. for ( pos = 0, i = 0; i < 3; i++ )
  1100. {
  1101. if ( fabs( src[i] ) < minelem )
  1102. {
  1103. pos = i;
  1104. minelem = fabs( src[i] );
  1105. }
  1106. }
  1107. tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  1108. tempvec[pos] = 1.0F;
  1109. /*
  1110. ** project the point onto the plane defined by src
  1111. */
  1112. ProjectPointOnPlane( dst, tempvec, src );
  1113. /*
  1114. ** normalize the result
  1115. */
  1116. VectorNormalize( dst );
  1117. }