PageRenderTime 30ms CodeModel.GetById 47ms RepoModel.GetById 17ms app.codeStats 1ms

/src/engine/qcommon/q_math.cpp

https://gitlab.com/TimePath/daemon2
C++ | 3891 lines | 2800 code | 597 blank | 494 comment | 226 complexity | 018fa050ef0edbe00f5394ed2477a948 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * ===========================================================================
  3. *
  4. * Daemon GPL Source Code
  5. * Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
  6. *
  7. * This file is part of the Daemon GPL Source Code (Daemon Source Code).
  8. *
  9. * Daemon 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 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Daemon 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
  20. * along with Daemon Source Code. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * In addition, the Daemon Source Code is also subject to certain additional terms.
  23. * You should have received a copy of these additional terms immediately following the
  24. * terms and conditions of the GNU General Public License which accompanied the Daemon
  25. * Source Code. If not, please request a copy in writing from id Software at the address
  26. * below.
  27. *
  28. * If you have questions concerning this license or the applicable additional terms, you
  29. * may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
  30. * Maryland 20850 USA.
  31. *
  32. * ===========================================================================
  33. */
  34. // q_math.c -- stateless support routines that are included in each code module
  35. #include "q_shared.h"
  36. // *INDENT-OFF*
  37. vec3_t vec3_origin = { 0, 0, 0 };
  38. vec3_t axisDefault[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
  39. matrix_t matrixIdentity = { 1, 0, 0, 0,
  40. 0, 1, 0, 0,
  41. 0, 0, 1, 0,
  42. 0, 0, 0, 1
  43. };
  44. quat_t quatIdentity = { 0, 0, 0, 1 };
  45. vec4_t colorBlack = { 0, 0, 0, 1 };
  46. vec4_t colorRed = { 1, 0, 0, 1 };
  47. vec4_t colorGreen = { 0, 1, 0, 1 };
  48. vec4_t colorBlue = { 0, 0, 1, 1 };
  49. vec4_t colorYellow = { 1, 1, 0, 1 };
  50. vec4_t colorOrange = { 1, 0.5, 0, 1 };
  51. vec4_t colorMagenta = { 1, 0, 1, 1 };
  52. vec4_t colorCyan = { 0, 1, 1, 1 };
  53. vec4_t colorWhite = { 1, 1, 1, 1 };
  54. vec4_t colorLtGrey = { 0.75, 0.75, 0.75, 1 };
  55. vec4_t colorMdGrey = { 0.5, 0.5, 0.5, 1 };
  56. vec4_t colorDkGrey = { 0.25, 0.25, 0.25, 1 };
  57. vec4_t colorMdRed = { 0.5, 0, 0, 1 };
  58. vec4_t colorMdGreen = { 0, 0.5, 0, 1 };
  59. vec4_t colorDkGreen = { 0, 0.20, 0, 1 };
  60. vec4_t colorMdCyan = { 0, 0.5, 0.5, 1 };
  61. vec4_t colorMdYellow = { 0.5, 0.5, 0, 1 };
  62. vec4_t colorMdOrange = { 0.5, 0.25, 0, 1 };
  63. vec4_t colorMdBlue = { 0, 0, 0.5, 1 };
  64. vec4_t clrBrown = { 0.68f, 0.68f, 0.56f, 1.f };
  65. vec4_t clrBrownDk = { 0.58f * 0.75f, 0.58f * 0.75f, 0.46f * 0.75f, 1.f };
  66. vec4_t clrBrownLine = { 0.0525f, 0.05f, 0.025f, 0.2f };
  67. vec4_t clrBrownLineFull = { 0.0525f, 0.05f, 0.025f, 1.f };
  68. vec4_t clrBrownTextLt2 = { 108 * 1.8 / 255.f, 88 * 1.8 / 255.f, 62 * 1.8 / 255.f, 1.f };
  69. vec4_t clrBrownTextLt = { 108 * 1.3 / 255.f, 88 * 1.3 / 255.f, 62 * 1.3 / 255.f, 1.f };
  70. vec4_t clrBrownText = { 108 / 255.f, 88 / 255.f, 62 / 255.f, 1.f };
  71. vec4_t clrBrownTextDk = { 20 / 255.f, 2 / 255.f, 0 / 255.f, 1.f };
  72. vec4_t clrBrownTextDk2 = { 108 * 0.75 / 255.f, 88 * 0.75 / 255.f, 62 * 0.75 / 255.f, 1.f };
  73. vec4_t g_color_table[ 32 ] =
  74. {
  75. { 0.2, 0.2, 0.2, 1.0 }, // 0 - black 0
  76. { 1.0, 0.0, 0.0, 1.0 }, // 1 - red 1
  77. { 0.0, 1.0, 0.0, 1.0 }, // 2 - green 2
  78. { 1.0, 1.0, 0.0, 1.0 }, // 3 - yellow 3
  79. { 0.0, 0.0, 1.0, 1.0 }, // 4 - blue 4
  80. { 0.0, 1.0, 1.0, 1.0 }, // 5 - cyan 5
  81. { 1.0, 0.0, 1.0, 1.0 }, // 6 - purple 6
  82. { 1.0, 1.0, 1.0, 1.0 }, // 7 - white 7
  83. { 1.0, 0.5, 0.0, 1.0 }, // 8 - orange 8
  84. { 0.5, 0.5, 0.5, 1.0 }, // 9 - md.grey 9
  85. { 0.75, 0.75, 0.75, 1.0 }, // : - lt.grey 10 // lt grey for names
  86. { 0.75, 0.75, 0.75, 1.0 }, // ; - lt.grey 11
  87. { 0.0, 0.5, 0.0, 1.0 }, // < - md.green 12
  88. { 0.5, 0.5, 0.0, 1.0 }, // = - md.yellow 13
  89. { 0.0, 0.0, 0.5, 1.0 }, // > - md.blue 14
  90. { 0.5, 0.0, 0.0, 1.0 }, // ? - md.red 15
  91. { 0.5, 0.25, 0.0, 1.0 }, // @ - md.orange 16
  92. { 1.0, 0.6f, 0.1f, 1.0 }, // A - lt.orange 17
  93. { 0.0, 0.5, 0.5, 1.0 }, // B - md.cyan 18
  94. { 0.5, 0.0, 0.5, 1.0 }, // C - md.purple 19
  95. { 0.0, 0.5, 1.0, 1.0 }, // D 20
  96. { 0.5, 0.0, 1.0, 1.0 }, // E 21
  97. { 0.2f, 0.6f, 0.8f, 1.0 }, // F 22
  98. { 0.8f, 1.0, 0.8f, 1.0 }, // G 23
  99. { 0.0, 0.4, 0.2f, 1.0 }, // H 24
  100. { 1.0, 0.0, 0.2f, 1.0 }, // I 25
  101. { 0.7f, 0.1f, 0.1f, 1.0 }, // J 26
  102. { 0.6f, 0.2f, 0.0, 1.0 }, // K 27
  103. { 0.8f, 0.6f, 0.2f, 1.0 }, // L 28
  104. { 0.6f, 0.6f, 0.2f, 1.0 }, // M 29
  105. { 1.0, 1.0, 0.75, 1.0 }, // N 30
  106. { 1.0, 1.0, 0.5, 1.0 }, // O 31
  107. };
  108. vec3_t bytedirs[ NUMVERTEXNORMALS ] =
  109. {
  110. { -0.525731, 0.000000, 0.850651 }, { -0.442863, 0.238856, 0.864188 },
  111. { -0.295242, 0.000000, 0.955423 }, { -0.309017, 0.500000, 0.809017 },
  112. { -0.162460, 0.262866, 0.951056 }, { 0.000000, 0.000000, 1.000000 },
  113. { 0.000000, 0.850651, 0.525731 }, { -0.147621, 0.716567, 0.681718 },
  114. { 0.147621, 0.716567, 0.681718 }, { 0.000000, 0.525731, 0.850651 },
  115. { 0.309017, 0.500000, 0.809017 }, { 0.525731, 0.000000, 0.850651 },
  116. { 0.295242, 0.000000, 0.955423 }, { 0.442863, 0.238856, 0.864188 },
  117. { 0.162460, 0.262866, 0.951056 }, { -0.681718, 0.147621, 0.716567 },
  118. { -0.809017, 0.309017, 0.500000 }, { -0.587785, 0.425325, 0.688191 },
  119. { -0.850651, 0.525731, 0.000000 }, { -0.864188, 0.442863, 0.238856 },
  120. { -0.716567, 0.681718, 0.147621 }, { -0.688191, 0.587785, 0.425325 },
  121. { -0.500000, 0.809017, 0.309017 }, { -0.238856, 0.864188, 0.442863 },
  122. { -0.425325, 0.688191, 0.587785 }, { -0.716567, 0.681718, -0.147621 },
  123. { -0.500000, 0.809017, -0.309017 }, { -0.525731, 0.850651, 0.000000 },
  124. { 0.000000, 0.850651, -0.525731 }, { -0.238856, 0.864188, -0.442863 },
  125. { 0.000000, 0.955423, -0.295242 }, { -0.262866, 0.951056, -0.162460 },
  126. { 0.000000, 1.000000, 0.000000 }, { 0.000000, 0.955423, 0.295242 },
  127. { -0.262866, 0.951056, 0.162460 }, { 0.238856, 0.864188, 0.442863 },
  128. { 0.262866, 0.951056, 0.162460 }, { 0.500000, 0.809017, 0.309017 },
  129. { 0.238856, 0.864188, -0.442863 }, { 0.262866, 0.951056, -0.162460 },
  130. { 0.500000, 0.809017, -0.309017 }, { 0.850651, 0.525731, 0.000000 },
  131. { 0.716567, 0.681718, 0.147621 }, { 0.716567, 0.681718, -0.147621 },
  132. { 0.525731, 0.850651, 0.000000 }, { 0.425325, 0.688191, 0.587785 },
  133. { 0.864188, 0.442863, 0.238856 }, { 0.688191, 0.587785, 0.425325 },
  134. { 0.809017, 0.309017, 0.500000 }, { 0.681718, 0.147621, 0.716567 },
  135. { 0.587785, 0.425325, 0.688191 }, { 0.955423, 0.295242, 0.000000 },
  136. { 1.000000, 0.000000, 0.000000 }, { 0.951056, 0.162460, 0.262866 },
  137. { 0.850651, -0.525731, 0.000000 }, { 0.955423, -0.295242, 0.000000 },
  138. { 0.864188, -0.442863, 0.238856 }, { 0.951056, -0.162460, 0.262866 },
  139. { 0.809017, -0.309017, 0.500000 }, { 0.681718, -0.147621, 0.716567 },
  140. { 0.850651, 0.000000, 0.525731 }, { 0.864188, 0.442863, -0.238856 },
  141. { 0.809017, 0.309017, -0.500000 }, { 0.951056, 0.162460, -0.262866 },
  142. { 0.525731, 0.000000, -0.850651 }, { 0.681718, 0.147621, -0.716567 },
  143. { 0.681718, -0.147621, -0.716567 }, { 0.850651, 0.000000, -0.525731 },
  144. { 0.809017, -0.309017, -0.500000 }, { 0.864188, -0.442863, -0.238856 },
  145. { 0.951056, -0.162460, -0.262866 }, { 0.147621, 0.716567, -0.681718 },
  146. { 0.309017, 0.500000, -0.809017 }, { 0.425325, 0.688191, -0.587785 },
  147. { 0.442863, 0.238856, -0.864188 }, { 0.587785, 0.425325, -0.688191 },
  148. { 0.688191, 0.587785, -0.425325 }, { -0.147621, 0.716567, -0.681718 },
  149. { -0.309017, 0.500000, -0.809017 }, { 0.000000, 0.525731, -0.850651 },
  150. { -0.525731, 0.000000, -0.850651 }, { -0.442863, 0.238856, -0.864188 },
  151. { -0.295242, 0.000000, -0.955423 }, { -0.162460, 0.262866, -0.951056 },
  152. { 0.000000, 0.000000, -1.000000 }, { 0.295242, 0.000000, -0.955423 },
  153. { 0.162460, 0.262866, -0.951056 }, { -0.442863, -0.238856, -0.864188 },
  154. { -0.309017, -0.500000, -0.809017 }, { -0.162460, -0.262866, -0.951056 },
  155. { 0.000000, -0.850651, -0.525731 }, { -0.147621, -0.716567, -0.681718 },
  156. { 0.147621, -0.716567, -0.681718 }, { 0.000000, -0.525731, -0.850651 },
  157. { 0.309017, -0.500000, -0.809017 }, { 0.442863, -0.238856, -0.864188 },
  158. { 0.162460, -0.262866, -0.951056 }, { 0.238856, -0.864188, -0.442863 },
  159. { 0.500000, -0.809017, -0.309017 }, { 0.425325, -0.688191, -0.587785 },
  160. { 0.716567, -0.681718, -0.147621 }, { 0.688191, -0.587785, -0.425325 },
  161. { 0.587785, -0.425325, -0.688191 }, { 0.000000, -0.955423, -0.295242 },
  162. { 0.000000, -1.000000, 0.000000 }, { 0.262866, -0.951056, -0.162460 },
  163. { 0.000000, -0.850651, 0.525731 }, { 0.000000, -0.955423, 0.295242 },
  164. { 0.238856, -0.864188, 0.442863 }, { 0.262866, -0.951056, 0.162460 },
  165. { 0.500000, -0.809017, 0.309017 }, { 0.716567, -0.681718, 0.147621 },
  166. { 0.525731, -0.850651, 0.000000 }, { -0.238856, -0.864188, -0.442863 },
  167. { -0.500000, -0.809017, -0.309017 }, { -0.262866, -0.951056, -0.162460 },
  168. { -0.850651, -0.525731, 0.000000 }, { -0.716567, -0.681718, -0.147621 },
  169. { -0.716567, -0.681718, 0.147621 }, { -0.525731, -0.850651, 0.000000 },
  170. { -0.500000, -0.809017, 0.309017 }, { -0.238856, -0.864188, 0.442863 },
  171. { -0.262866, -0.951056, 0.162460 }, { -0.864188, -0.442863, 0.238856 },
  172. { -0.809017, -0.309017, 0.500000 }, { -0.688191, -0.587785, 0.425325 },
  173. { -0.681718, -0.147621, 0.716567 }, { -0.442863, -0.238856, 0.864188 },
  174. { -0.587785, -0.425325, 0.688191 }, { -0.309017, -0.500000, 0.809017 },
  175. { -0.147621, -0.716567, 0.681718 }, { -0.425325, -0.688191, 0.587785 },
  176. { -0.162460, -0.262866, 0.951056 }, { 0.442863, -0.238856, 0.864188 },
  177. { 0.162460, -0.262866, 0.951056 }, { 0.309017, -0.500000, 0.809017 },
  178. { 0.147621, -0.716567, 0.681718 }, { 0.000000, -0.525731, 0.850651 },
  179. { 0.425325, -0.688191, 0.587785 }, { 0.587785, -0.425325, 0.688191 },
  180. { 0.688191, -0.587785, 0.425325 }, { -0.955423, 0.295242, 0.000000 },
  181. { -0.951056, 0.162460, 0.262866 }, { -1.000000, 0.000000, 0.000000 },
  182. { -0.850651, 0.000000, 0.525731 }, { -0.955423, -0.295242, 0.000000 },
  183. { -0.951056, -0.162460, 0.262866 }, { -0.864188, 0.442863, -0.238856 },
  184. { -0.951056, 0.162460, -0.262866 }, { -0.809017, 0.309017, -0.500000 },
  185. { -0.864188, -0.442863, -0.238856 }, { -0.951056, -0.162460, -0.262866 },
  186. { -0.809017, -0.309017, -0.500000 }, { -0.681718, 0.147621, -0.716567 },
  187. { -0.681718, -0.147621, -0.716567 }, { -0.850651, 0.000000, -0.525731 },
  188. { -0.688191, 0.587785, -0.425325 }, { -0.587785, 0.425325, -0.688191 },
  189. { -0.425325, 0.688191, -0.587785 }, { -0.425325, -0.688191, -0.587785 },
  190. { -0.587785, -0.425325, -0.688191 }, { -0.688191, -0.587785, -0.425325 }
  191. };
  192. // *INDENT-ON*
  193. //==============================================================
  194. int Q_rand( int *seed )
  195. {
  196. *seed = ( 69069 * *seed + 1 );
  197. return *seed;
  198. }
  199. // Range of [0,1]
  200. float Q_random( int *seed )
  201. {
  202. return ( Q_rand( seed ) & 0xffff ) / ( float ) 0x10000;
  203. }
  204. // Range of [-1,1]
  205. float Q_crandom( int *seed )
  206. {
  207. return 2.0 * ( Q_random( seed ) - 0.5 );
  208. }
  209. //=======================================================
  210. byte ClampByte( int i )
  211. {
  212. if ( i < 0 )
  213. {
  214. return 0;
  215. }
  216. if ( i > 255 )
  217. {
  218. return 255;
  219. }
  220. return i;
  221. }
  222. signed char ClampChar( int i )
  223. {
  224. if ( i < -128 )
  225. {
  226. return -128;
  227. }
  228. if ( i > 127 )
  229. {
  230. return 127;
  231. }
  232. return i;
  233. }
  234. signed short ClampShort( int i )
  235. {
  236. if ( i < -32768 )
  237. {
  238. return -32768;
  239. }
  240. if ( i > 0x7fff )
  241. {
  242. return 0x7fff;
  243. }
  244. return i;
  245. }
  246. // this isn't a real cheap function to call!
  247. int DirToByte( vec3_t dir )
  248. {
  249. int i, best;
  250. float d, bestd;
  251. if ( !dir )
  252. {
  253. return 0;
  254. }
  255. bestd = 0;
  256. best = 0;
  257. for ( i = 0; i < NUMVERTEXNORMALS; i++ )
  258. {
  259. d = DotProduct( dir, bytedirs[ i ] );
  260. if ( d > bestd )
  261. {
  262. bestd = d;
  263. best = i;
  264. }
  265. }
  266. return best;
  267. }
  268. void ByteToDir( int b, vec3_t dir )
  269. {
  270. if ( b < 0 || b >= NUMVERTEXNORMALS )
  271. {
  272. VectorCopy( vec3_origin, dir );
  273. return;
  274. }
  275. VectorCopy( bytedirs[ b ], dir );
  276. }
  277. unsigned ColorBytes3( float r, float g, float b )
  278. {
  279. unsigned i;
  280. ( ( byte * ) &i ) [ 0 ] = r * 255;
  281. ( ( byte * ) &i ) [ 1 ] = g * 255;
  282. ( ( byte * ) &i ) [ 2 ] = b * 255;
  283. return i;
  284. }
  285. unsigned ColorBytes4( float r, float g, float b, float a )
  286. {
  287. unsigned i;
  288. ( ( byte * ) &i ) [ 0 ] = r * 255;
  289. ( ( byte * ) &i ) [ 1 ] = g * 255;
  290. ( ( byte * ) &i ) [ 2 ] = b * 255;
  291. ( ( byte * ) &i ) [ 3 ] = a * 255;
  292. return i;
  293. }
  294. float NormalizeColor( const vec3_t in, vec3_t out )
  295. {
  296. float max;
  297. max = in[ 0 ];
  298. if ( in[ 1 ] > max )
  299. {
  300. max = in[ 1 ];
  301. }
  302. if ( in[ 2 ] > max )
  303. {
  304. max = in[ 2 ];
  305. }
  306. if ( !max )
  307. {
  308. VectorClear( out );
  309. }
  310. else
  311. {
  312. out[ 0 ] = in[ 0 ] / max;
  313. out[ 1 ] = in[ 1 ] / max;
  314. out[ 2 ] = in[ 2 ] / max;
  315. }
  316. return max;
  317. }
  318. void ClampColor( vec4_t color )
  319. {
  320. int i;
  321. for ( i = 0; i < 4; i++ )
  322. {
  323. if ( color[ i ] < 0 )
  324. {
  325. color[ i ] = 0;
  326. }
  327. if ( color[ i ] > 1 )
  328. {
  329. color[ i ] = 1;
  330. }
  331. }
  332. }
  333. vec_t PlaneNormalize( vec4_t plane )
  334. {
  335. vec_t length2, ilength;
  336. length2 = DotProduct( plane, plane );
  337. if ( length2 == 0.0f )
  338. {
  339. VectorClear( plane );
  340. return 0.0f;
  341. }
  342. ilength = Q_rsqrt( length2 );
  343. plane[ 0 ] = plane[ 0 ] * ilength;
  344. plane[ 1 ] = plane[ 1 ] * ilength;
  345. plane[ 2 ] = plane[ 2 ] * ilength;
  346. plane[ 3 ] = plane[ 3 ] * ilength;
  347. return length2 * ilength;
  348. }
  349. /*
  350. * =====================
  351. * PlaneFromPoints
  352. *
  353. * Returns false if the triangle is degenerate.
  354. * The normal will point out of the clock for clockwise ordered points
  355. * =====================
  356. */
  357. qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c )
  358. {
  359. vec3_t d1, d2;
  360. VectorSubtract( b, a, d1 );
  361. VectorSubtract( c, a, d2 );
  362. CrossProduct( d2, d1, plane );
  363. if ( VectorNormalize( plane ) == 0 )
  364. {
  365. return qfalse;
  366. }
  367. plane[ 3 ] = DotProduct( a, plane );
  368. return qtrue;
  369. }
  370. /*
  371. * =====================
  372. * PlaneFromPoints
  373. *
  374. * Returns false if the triangle is degenerate.
  375. * =====================
  376. */
  377. qboolean PlaneFromPointsOrder( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c, qboolean cw )
  378. {
  379. vec3_t d1, d2;
  380. VectorSubtract( b, a, d1 );
  381. VectorSubtract( c, a, d2 );
  382. if ( cw )
  383. {
  384. CrossProduct( d2, d1, plane );
  385. }
  386. else
  387. {
  388. CrossProduct( d1, d2, plane );
  389. }
  390. if ( VectorNormalize( plane ) == 0 )
  391. {
  392. return qfalse;
  393. }
  394. plane[ 3 ] = DotProduct( a, plane );
  395. return qtrue;
  396. }
  397. qboolean PlanesGetIntersectionPoint( const vec4_t plane1, const vec4_t plane2, const vec4_t plane3, vec3_t out )
  398. {
  399. // http://www.cgafaq.info/wiki/Intersection_of_three_planes
  400. vec3_t n1, n2, n3;
  401. vec3_t n1n2, n2n3, n3n1;
  402. vec_t denom;
  403. VectorNormalize2( plane1, n1 );
  404. VectorNormalize2( plane2, n2 );
  405. VectorNormalize2( plane3, n3 );
  406. CrossProduct( n1, n2, n1n2 );
  407. CrossProduct( n2, n3, n2n3 );
  408. CrossProduct( n3, n1, n3n1 );
  409. denom = DotProduct( n1, n2n3 );
  410. // check if the denominator is zero (which would mean that no intersection is to be found
  411. if ( denom == 0 )
  412. {
  413. // no intersection could be found, return <0,0,0>
  414. VectorClear( out );
  415. return qfalse;
  416. }
  417. VectorClear( out );
  418. VectorMA( out, plane1[ 3 ], n2n3, out );
  419. VectorMA( out, plane2[ 3 ], n3n1, out );
  420. VectorMA( out, plane3[ 3 ], n1n2, out );
  421. VectorScale( out, 1.0f / denom, out );
  422. return qtrue;
  423. }
  424. void PlaneIntersectRay( const vec3_t rayPos, const vec3_t rayDir, const vec4_t plane, vec3_t res )
  425. {
  426. vec3_t dir;
  427. float sect;
  428. VectorNormalize2( rayDir, dir );
  429. sect = - ( DotProduct( plane, rayPos ) - plane[ 3 ] ) / DotProduct( plane, rayDir );
  430. VectorScale( dir, sect, dir );
  431. VectorAdd( rayPos, dir, res );
  432. }
  433. /*
  434. * ===============
  435. * RotatePointAroundVector
  436. * ===============
  437. */
  438. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
  439. {
  440. float sind, cosd, expr;
  441. vec3_t dxp;
  442. degrees = DEG2RAD( degrees );
  443. sind = sin( degrees );
  444. cosd = cos( degrees );
  445. expr = ( 1 - cosd ) * DotProduct( dir, point );
  446. CrossProduct( dir, point, dxp );
  447. dst[ 0 ] = expr * dir[ 0 ] + cosd * point[ 0 ] + sind * dxp[ 0 ];
  448. dst[ 1 ] = expr * dir[ 1 ] + cosd * point[ 1 ] + sind * dxp[ 1 ];
  449. dst[ 2 ] = expr * dir[ 2 ] + cosd * point[ 2 ] + sind * dxp[ 2 ];
  450. }
  451. /*
  452. * ===============
  453. * RotatePointAroundVertex
  454. *
  455. * Rotate a point around a vertex
  456. * ===============
  457. */
  458. void RotatePointAroundVertex( vec3_t pnt, float rot_x, float rot_y, float rot_z, const vec3_t origin )
  459. {
  460. float tmp[ 11 ];
  461. //float rad_x, rad_y, rad_z;
  462. /*rad_x = DEG2RAD( rot_x );
  463. * rad_y = DEG2RAD( rot_y );
  464. * rad_z = DEG2RAD( rot_z ); */
  465. // move pnt to rel{0,0,0}
  466. VectorSubtract( pnt, origin, pnt );
  467. // init temp values
  468. tmp[ 0 ] = sin( rot_x );
  469. tmp[ 1 ] = cos( rot_x );
  470. tmp[ 2 ] = sin( rot_y );
  471. tmp[ 3 ] = cos( rot_y );
  472. tmp[ 4 ] = sin( rot_z );
  473. tmp[ 5 ] = cos( rot_z );
  474. tmp[ 6 ] = pnt[ 1 ] * tmp[ 5 ];
  475. tmp[ 7 ] = pnt[ 0 ] * tmp[ 4 ];
  476. tmp[ 8 ] = pnt[ 0 ] * tmp[ 5 ];
  477. tmp[ 9 ] = pnt[ 1 ] * tmp[ 4 ];
  478. tmp[ 10 ] = pnt[ 2 ] * tmp[ 3 ];
  479. // rotate point
  480. pnt[ 0 ] = ( tmp[ 3 ] * ( tmp[ 8 ] - tmp[ 9 ] ) + pnt[ 3 ] * tmp[ 2 ] );
  481. pnt[ 1 ] = ( tmp[ 0 ] * ( tmp[ 2 ] * tmp[ 8 ] - tmp[ 2 ] * tmp[ 9 ] - tmp[ 10 ] ) + tmp[ 1 ] * ( tmp[ 7 ] + tmp[ 6 ] ) );
  482. pnt[ 2 ] = ( tmp[ 1 ] * ( -tmp[ 2 ] * tmp[ 8 ] + tmp[ 2 ] * tmp[ 9 ] + tmp[ 10 ] ) + tmp[ 0 ] * ( tmp[ 7 ] + tmp[ 6 ] ) );
  483. // move pnt back
  484. VectorAdd( pnt, origin, pnt );
  485. }
  486. /*
  487. * ===============
  488. * RotateAroundDirection
  489. * ===============
  490. */
  491. void RotateAroundDirection( vec3_t axis[ 3 ], float yaw )
  492. {
  493. // create an arbitrary axis[1]
  494. PerpendicularVector( axis[ 1 ], axis[ 0 ] );
  495. // rotate it around axis[0] by yaw
  496. if ( yaw )
  497. {
  498. vec3_t temp;
  499. VectorCopy( axis[ 1 ], temp );
  500. RotatePointAroundVector( axis[ 1 ], axis[ 0 ], temp, yaw );
  501. }
  502. // cross to get axis[2]
  503. CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] );
  504. }
  505. /*
  506. * ================
  507. * Q_isnan
  508. *
  509. * Don't pass doubles to this
  510. * ================
  511. */
  512. int Q_isnan( float x )
  513. {
  514. return ( Q_floatBitsToUint( x ) & 0x7fffffff ) > 0x7f800000;
  515. }
  516. void vectoangles( const vec3_t value1, vec3_t angles )
  517. {
  518. float forward;
  519. float yaw, pitch;
  520. if ( value1[ 1 ] == 0 && value1[ 0 ] == 0 )
  521. {
  522. yaw = 0;
  523. if ( value1[ 2 ] > 0 )
  524. {
  525. pitch = 90;
  526. }
  527. else
  528. {
  529. pitch = 270;
  530. }
  531. }
  532. else
  533. {
  534. if ( value1[ 0 ] )
  535. {
  536. yaw = ( atan2( value1[ 1 ], value1[ 0 ] ) * 180 / M_PI );
  537. }
  538. else if ( value1[ 1 ] > 0 )
  539. {
  540. yaw = 90;
  541. }
  542. else
  543. {
  544. yaw = 270;
  545. }
  546. if ( yaw < 0 )
  547. {
  548. yaw += 360;
  549. }
  550. forward = sqrt( value1[ 0 ] * value1[ 0 ] + value1[ 1 ] * value1[ 1 ] );
  551. pitch = ( atan2( value1[ 2 ], forward ) * 180 / M_PI );
  552. if ( pitch < 0 )
  553. {
  554. pitch += 360;
  555. }
  556. }
  557. angles[ PITCH ] = -pitch;
  558. angles[ YAW ] = yaw;
  559. angles[ ROLL ] = 0;
  560. }
  561. /*
  562. * =================
  563. * AnglesToAxis
  564. * =================
  565. */
  566. void AnglesToAxis( const vec3_t angles, vec3_t axis[ 3 ] )
  567. {
  568. vec3_t right;
  569. // angle vectors returns "right" instead of "y axis"
  570. AngleVectors( angles, axis[ 0 ], right, axis[ 2 ] );
  571. VectorSubtract( vec3_origin, right, axis[ 1 ] );
  572. }
  573. void AxisClear( vec3_t axis[ 3 ] )
  574. {
  575. axis[ 0 ][ 0 ] = 1;
  576. axis[ 0 ][ 1 ] = 0;
  577. axis[ 0 ][ 2 ] = 0;
  578. axis[ 1 ][ 0 ] = 0;
  579. axis[ 1 ][ 1 ] = 1;
  580. axis[ 1 ][ 2 ] = 0;
  581. axis[ 2 ][ 0 ] = 0;
  582. axis[ 2 ][ 1 ] = 0;
  583. axis[ 2 ][ 2 ] = 1;
  584. }
  585. void AxisCopy( vec3_t in[ 3 ], vec3_t out[ 3 ] )
  586. {
  587. VectorCopy( in[ 0 ], out[ 0 ] );
  588. VectorCopy( in[ 1 ], out[ 1 ] );
  589. VectorCopy( in[ 2 ], out[ 2 ] );
  590. }
  591. void ProjectPointOnPlane( vec3_t dst, const vec3_t point, const vec3_t normal )
  592. {
  593. float d = -DotProduct( point, normal );
  594. VectorMA( point, d, normal, dst );
  595. }
  596. /*
  597. * ================
  598. * MakeNormalVectors
  599. *
  600. * Given a normalized forward vector, create two
  601. * other perpendicular vectors
  602. * ================
  603. */
  604. void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up )
  605. {
  606. float d;
  607. // this rotate and negate guarantees a vector
  608. // not colinear with the original
  609. right[ 1 ] = -forward[ 0 ];
  610. right[ 2 ] = forward[ 1 ];
  611. right[ 0 ] = forward[ 2 ];
  612. d = DotProduct( right, forward );
  613. VectorMA( right, -d, forward, right );
  614. VectorNormalize( right );
  615. CrossProduct( right, forward, up );
  616. }
  617. void VectorRotate( vec3_t in, vec3_t matrix[ 3 ], vec3_t out )
  618. {
  619. out[ 0 ] = DotProduct( in, matrix[ 0 ] );
  620. out[ 1 ] = DotProduct( in, matrix[ 1 ] );
  621. out[ 2 ] = DotProduct( in, matrix[ 2 ] );
  622. }
  623. /*
  624. ==================
  625. ProjectPointOntoRectangleOutwards
  626. Traces a ray from inside a rectangle and returns the point of
  627. intersection with the rectangle
  628. ==================
  629. */
  630. float ProjectPointOntoRectangleOutwards( vec2_t out, const vec2_t point, const vec2_t dir,
  631. const vec2_t bounds[ 2 ] )
  632. {
  633. float t, ty;
  634. qboolean dsign[ 2 ];
  635. dsign[ 0 ] = ( dir[ 0 ] < 0 );
  636. dsign[ 1 ] = ( dir[ 1 ] < 0.0 );
  637. t = ( bounds[ 1 - dsign[ 0 ] ][ 0 ] - point[ 0 ] ) / dir[ 0 ];
  638. ty = ( bounds[ 1 - dsign[ 1 ] ][ 1 ] - point[ 1 ] ) / dir[ 1 ];
  639. if( ty < t )
  640. t = ty;
  641. out[ 0 ] = point[ 0 ] + dir[ 0 ] * t;
  642. out[ 1 ] = point[ 1 ] + dir[ 1 ] * t;
  643. return t;
  644. }
  645. //============================================================
  646. /*
  647. =============
  648. ExponentialFade
  649. Fades one value towards another exponentially
  650. =============
  651. */
  652. void ExponentialFade( float *value, float target, float lambda, float timedelta )
  653. {
  654. *value = target + ( *value - target ) * exp( - lambda * timedelta );
  655. }
  656. /*
  657. * ===============
  658. * LerpAngle
  659. *
  660. * ===============
  661. */
  662. float LerpAngle( float from, float to, float frac )
  663. {
  664. if ( to - from > 180 )
  665. {
  666. to -= 360;
  667. }
  668. if ( to - from < -180 )
  669. {
  670. to += 360;
  671. }
  672. return ( from + frac * ( to - from ) );
  673. }
  674. /*
  675. * =================
  676. * LerpPosition
  677. *
  678. * =================
  679. */
  680. void LerpPosition( vec3_t start, vec3_t end, float frac, vec3_t out )
  681. {
  682. vec3_t dist;
  683. VectorSubtract( end, start, dist );
  684. VectorMA( start, frac, dist, out );
  685. }
  686. /*
  687. * =================
  688. * AngleSubtract
  689. *
  690. * Always returns a value from -180 to 180
  691. * =================
  692. */
  693. float AngleSubtract( float a1, float a2 )
  694. {
  695. float a = a1 - a2;
  696. return a - 360.0f * floor( ( a + 180.0f ) / 360.0f );
  697. }
  698. void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 )
  699. {
  700. v3[ 0 ] = AngleSubtract( v1[ 0 ], v2[ 0 ] );
  701. v3[ 1 ] = AngleSubtract( v1[ 1 ], v2[ 1 ] );
  702. v3[ 2 ] = AngleSubtract( v1[ 2 ], v2[ 2 ] );
  703. }
  704. float AngleMod( float a )
  705. {
  706. return ( ( 360.0 / 65536 ) * ( ( int )( a * ( 65536 / 360.0 ) ) & 65535 ) );
  707. }
  708. /*
  709. * =================
  710. * AngleNormalize2Pi
  711. *
  712. * returns angle normalized to the range [0 <= angle < 2*M_PI]
  713. * =================
  714. */
  715. float AngleNormalize2Pi( float angle )
  716. {
  717. return DEG2RAD( AngleNormalize360( RAD2DEG( angle ) ) );
  718. }
  719. /*
  720. * =================
  721. * AngleNormalize360
  722. *
  723. * returns angle normalized to the range [0 <= angle < 360]
  724. * =================
  725. */
  726. float AngleNormalize360( float angle )
  727. {
  728. return ( 360.0 / 65536 ) * ( ( int )( angle * ( 65536 / 360.0 ) ) & 65535 );
  729. }
  730. /*
  731. * =================
  732. * AngleNormalize180
  733. *
  734. * returns angle normalized to the range [-180 < angle <= 180]
  735. * =================
  736. */
  737. float AngleNormalize180( float angle )
  738. {
  739. angle = AngleNormalize360( angle );
  740. if ( angle > 180.0 )
  741. {
  742. angle -= 360.0;
  743. }
  744. return angle;
  745. }
  746. /*
  747. * =================
  748. * AngleDelta
  749. *
  750. * returns the normalized delta from angle1 to angle2
  751. * =================
  752. */
  753. float AngleDelta( float angle1, float angle2 )
  754. {
  755. return AngleNormalize180( angle1 - angle2 );
  756. }
  757. /*
  758. * =================
  759. * AngleBetweenVectors
  760. *
  761. * returns the angle between two vectors normalized to the range [0 <= angle <= 180]
  762. * =================
  763. */
  764. float AngleBetweenVectors( const vec3_t a, const vec3_t b )
  765. {
  766. vec_t alen, blen;
  767. alen = VectorLength( a );
  768. blen = VectorLength( b );
  769. if ( !alen || !blen )
  770. {
  771. return 0;
  772. }
  773. // complete dot product of two vectors a, b is |a| * |b| * cos(angle)
  774. // this results in:
  775. //
  776. // angle = acos( (a * b) / (|a| * |b|) )
  777. return RAD2DEG( acos( DotProduct( a, b ) / ( alen * blen ) ) );
  778. }
  779. //============================================================
  780. /*
  781. * =================
  782. * SetPlaneSignbits
  783. * =================
  784. */
  785. void SetPlaneSignbits( cplane_t *out )
  786. {
  787. int bits, j;
  788. // for fast box on planeside test
  789. bits = 0;
  790. for ( j = 0; j < 3; j++ )
  791. {
  792. if ( out->normal[ j ] < 0 )
  793. {
  794. bits |= 1 << j;
  795. }
  796. }
  797. out->signbits = bits;
  798. }
  799. /*
  800. * ==================
  801. * BoxOnPlaneSide
  802. *
  803. * Returns 1, 2, or 1 + 2
  804. * ==================
  805. */
  806. int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const struct cplane_s *p )
  807. {
  808. float dist[ 2 ];
  809. int sides, b, i;
  810. // fast axial cases
  811. if ( p->type < 3 )
  812. {
  813. if ( p->dist <= emins[ p->type ] )
  814. {
  815. return 1;
  816. }
  817. if ( p->dist >= emaxs[ p->type ] )
  818. {
  819. return 2;
  820. }
  821. return 3;
  822. }
  823. // general case
  824. dist[ 0 ] = dist[ 1 ] = 0;
  825. if ( p->signbits < 8 ) // >= 8: default case is original code (dist[0]=dist[1]=0)
  826. {
  827. for ( i = 0; i < 3; i++ )
  828. {
  829. b = ( p->signbits >> i ) & 1;
  830. dist[ b ] += p->normal[ i ] * emaxs[ i ];
  831. dist[ !b ] += p->normal[ i ] * emins[ i ];
  832. }
  833. }
  834. sides = 0;
  835. if ( dist[ 0 ] >= p->dist )
  836. {
  837. sides = 1;
  838. }
  839. if ( dist[ 1 ] < p->dist )
  840. {
  841. sides |= 2;
  842. }
  843. return sides;
  844. }
  845. /*
  846. * =================
  847. * RadiusFromBounds
  848. * =================
  849. */
  850. float RadiusFromBounds( const vec3_t mins, const vec3_t maxs )
  851. {
  852. int i;
  853. vec3_t corner;
  854. float a, b;
  855. for ( i = 0; i < 3; i++ )
  856. {
  857. a = Q_fabs( mins[ i ] );
  858. b = Q_fabs( maxs[ i ] );
  859. corner[ i ] = a > b ? a : b;
  860. }
  861. return VectorLength( corner );
  862. }
  863. void ZeroBounds( vec3_t mins, vec3_t maxs )
  864. {
  865. mins[ 0 ] = mins[ 1 ] = mins[ 2 ] = 0;
  866. maxs[ 0 ] = maxs[ 1 ] = maxs[ 2 ] = 0;
  867. }
  868. void ClearBounds( vec3_t mins, vec3_t maxs )
  869. {
  870. mins[ 0 ] = mins[ 1 ] = mins[ 2 ] = 99999;
  871. maxs[ 0 ] = maxs[ 1 ] = maxs[ 2 ] = -99999;
  872. }
  873. void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
  874. {
  875. if ( v[ 0 ] < mins[ 0 ] )
  876. {
  877. mins[ 0 ] = v[ 0 ];
  878. }
  879. if ( v[ 0 ] > maxs[ 0 ] )
  880. {
  881. maxs[ 0 ] = v[ 0 ];
  882. }
  883. if ( v[ 1 ] < mins[ 1 ] )
  884. {
  885. mins[ 1 ] = v[ 1 ];
  886. }
  887. if ( v[ 1 ] > maxs[ 1 ] )
  888. {
  889. maxs[ 1 ] = v[ 1 ];
  890. }
  891. if ( v[ 2 ] < mins[ 2 ] )
  892. {
  893. mins[ 2 ] = v[ 2 ];
  894. }
  895. if ( v[ 2 ] > maxs[ 2 ] )
  896. {
  897. maxs[ 2 ] = v[ 2 ];
  898. }
  899. }
  900. qboolean PointInBounds( const vec3_t v, const vec3_t mins, const vec3_t maxs )
  901. {
  902. if ( v[ 0 ] < mins[ 0 ] )
  903. {
  904. return qfalse;
  905. }
  906. if ( v[ 0 ] > maxs[ 0 ] )
  907. {
  908. return qfalse;
  909. }
  910. if ( v[ 1 ] < mins[ 1 ] )
  911. {
  912. return qfalse;
  913. }
  914. if ( v[ 1 ] > maxs[ 1 ] )
  915. {
  916. return qfalse;
  917. }
  918. if ( v[ 2 ] < mins[ 2 ] )
  919. {
  920. return qfalse;
  921. }
  922. if ( v[ 2 ] > maxs[ 2 ] )
  923. {
  924. return qfalse;
  925. }
  926. return qtrue;
  927. }
  928. void BoundsAdd( vec3_t mins, vec3_t maxs, const vec3_t mins2, const vec3_t maxs2 )
  929. {
  930. if ( mins2[ 0 ] < mins[ 0 ] )
  931. {
  932. mins[ 0 ] = mins2[ 0 ];
  933. }
  934. if ( mins2[ 1 ] < mins[ 1 ] )
  935. {
  936. mins[ 1 ] = mins2[ 1 ];
  937. }
  938. if ( mins2[ 2 ] < mins[ 2 ] )
  939. {
  940. mins[ 2 ] = mins2[ 2 ];
  941. }
  942. if ( maxs2[ 0 ] > maxs[ 0 ] )
  943. {
  944. maxs[ 0 ] = maxs2[ 0 ];
  945. }
  946. if ( maxs2[ 1 ] > maxs[ 1 ] )
  947. {
  948. maxs[ 1 ] = maxs2[ 1 ];
  949. }
  950. if ( maxs2[ 2 ] > maxs[ 2 ] )
  951. {
  952. maxs[ 2 ] = maxs2[ 2 ];
  953. }
  954. }
  955. qboolean BoundsIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t mins2, const vec3_t maxs2 )
  956. {
  957. if ( maxs[ 0 ] < mins2[ 0 ] ||
  958. maxs[ 1 ] < mins2[ 1 ] || maxs[ 2 ] < mins2[ 2 ] || mins[ 0 ] > maxs2[ 0 ] || mins[ 1 ] > maxs2[ 1 ] || mins[ 2 ] > maxs2[ 2 ] )
  959. {
  960. return qfalse;
  961. }
  962. return qtrue;
  963. }
  964. qboolean BoundsIntersectSphere( const vec3_t mins, const vec3_t maxs, const vec3_t origin, vec_t radius )
  965. {
  966. if ( origin[ 0 ] - radius > maxs[ 0 ] ||
  967. origin[ 0 ] + radius < mins[ 0 ] ||
  968. origin[ 1 ] - radius > maxs[ 1 ] ||
  969. origin[ 1 ] + radius < mins[ 1 ] || origin[ 2 ] - radius > maxs[ 2 ] || origin[ 2 ] + radius < mins[ 2 ] )
  970. {
  971. return qfalse;
  972. }
  973. return qtrue;
  974. }
  975. qboolean BoundsIntersectPoint( const vec3_t mins, const vec3_t maxs, const vec3_t origin )
  976. {
  977. if ( origin[ 0 ] > maxs[ 0 ] ||
  978. origin[ 0 ] < mins[ 0 ] || origin[ 1 ] > maxs[ 1 ] || origin[ 1 ] < mins[ 1 ] || origin[ 2 ] > maxs[ 2 ] || origin[ 2 ] < mins[ 2 ] )
  979. {
  980. return qfalse;
  981. }
  982. return qtrue;
  983. }
  984. float BoundsMaxExtent( const vec3_t mins, const vec3_t maxs ) {
  985. float result = Q_fabs( mins[0] );
  986. result = MAX( result, Q_fabs( mins[ 1 ] ) );
  987. result = MAX( result, Q_fabs( mins[ 2 ] ) );
  988. result = MAX( result, Q_fabs( maxs[ 0 ] ) );
  989. result = MAX( result, Q_fabs( maxs[ 1 ] ) );
  990. result = MAX( result, Q_fabs( maxs[ 2 ] ) );
  991. return result;
  992. }
  993. int VectorCompare( const vec3_t v1, const vec3_t v2 )
  994. {
  995. if ( v1[ 0 ] != v2[ 0 ] || v1[ 1 ] != v2[ 1 ] || v1[ 2 ] != v2[ 2 ] )
  996. {
  997. return 0;
  998. }
  999. return 1;
  1000. }
  1001. vec_t VectorNormalize( vec3_t v )
  1002. {
  1003. float length, ilength;
  1004. length = DotProduct( v, v );
  1005. if ( length != 0.0f )
  1006. {
  1007. ilength = Q_rsqrt( length );
  1008. /* sqrt(length) = length * (1 / sqrt(length)) */
  1009. length *= ilength;
  1010. VectorScale( v, ilength, v );
  1011. }
  1012. return length;
  1013. }
  1014. //
  1015. // fast vector normalize routine that does not check to make sure
  1016. // that length != 0, nor does it return length
  1017. //
  1018. void VectorNormalizeFast( vec3_t v )
  1019. {
  1020. float ilength;
  1021. ilength = Q_rsqrt( DotProduct( v, v ) );
  1022. VectorScale( v, ilength, v );
  1023. }
  1024. vec_t VectorNormalize2( const vec3_t v, vec3_t out )
  1025. {
  1026. float length, ilength;
  1027. length = v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ];
  1028. if ( length )
  1029. {
  1030. ilength = Q_rsqrt( length );
  1031. /* sqrt(length) = length * (1 / sqrt(length)) */
  1032. length *= ilength;
  1033. VectorScale( v, ilength, out );
  1034. }
  1035. else
  1036. {
  1037. VectorClear( out );
  1038. }
  1039. return length;
  1040. }
  1041. void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc )
  1042. {
  1043. vecc[ 0 ] = veca[ 0 ] + scale * vecb[ 0 ];
  1044. vecc[ 1 ] = veca[ 1 ] + scale * vecb[ 1 ];
  1045. vecc[ 2 ] = veca[ 2 ] + scale * vecb[ 2 ];
  1046. }
  1047. vec_t _DotProduct( const vec3_t v1, const vec3_t v2 )
  1048. {
  1049. return v1[ 0 ] * v2[ 0 ] + v1[ 1 ] * v2[ 1 ] + v1[ 2 ] * v2[ 2 ];
  1050. }
  1051. void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out )
  1052. {
  1053. out[ 0 ] = veca[ 0 ] - vecb[ 0 ];
  1054. out[ 1 ] = veca[ 1 ] - vecb[ 1 ];
  1055. out[ 2 ] = veca[ 2 ] - vecb[ 2 ];
  1056. }
  1057. void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out )
  1058. {
  1059. out[ 0 ] = veca[ 0 ] + vecb[ 0 ];
  1060. out[ 1 ] = veca[ 1 ] + vecb[ 1 ];
  1061. out[ 2 ] = veca[ 2 ] + vecb[ 2 ];
  1062. }
  1063. void _VectorCopy( const vec3_t in, vec3_t out )
  1064. {
  1065. out[ 0 ] = in[ 0 ];
  1066. out[ 1 ] = in[ 1 ];
  1067. out[ 2 ] = in[ 2 ];
  1068. }
  1069. void _VectorScale( const vec3_t in, vec_t scale, vec3_t out )
  1070. {
  1071. out[ 0 ] = in[ 0 ] * scale;
  1072. out[ 1 ] = in[ 1 ] * scale;
  1073. out[ 2 ] = in[ 2 ] * scale;
  1074. }
  1075. void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross )
  1076. {
  1077. cross[ 0 ] = v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ];
  1078. cross[ 1 ] = v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ];
  1079. cross[ 2 ] = v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ];
  1080. }
  1081. vec_t VectorLength( const vec3_t v )
  1082. {
  1083. return sqrt( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  1084. }
  1085. vec_t VectorLengthSquared( const vec3_t v )
  1086. {
  1087. return ( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  1088. }
  1089. vec_t Distance( const vec3_t p1, const vec3_t p2 )
  1090. {
  1091. vec3_t v;
  1092. VectorSubtract( p2, p1, v );
  1093. return VectorLength( v );
  1094. }
  1095. vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 )
  1096. {
  1097. vec3_t v;
  1098. VectorSubtract( p2, p1, v );
  1099. return v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ];
  1100. }
  1101. void VectorInverse( vec3_t v )
  1102. {
  1103. v[ 0 ] = -v[ 0 ];
  1104. v[ 1 ] = -v[ 1 ];
  1105. v[ 2 ] = -v[ 2 ];
  1106. }
  1107. void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out )
  1108. {
  1109. out[ 0 ] = in[ 0 ] * scale;
  1110. out[ 1 ] = in[ 1 ] * scale;
  1111. out[ 2 ] = in[ 2 ] * scale;
  1112. out[ 3 ] = in[ 3 ] * scale;
  1113. }
  1114. int NearestPowerOfTwo( int val )
  1115. {
  1116. int answer;
  1117. for ( answer = 1; answer < val; answer <<= 1 )
  1118. {
  1119. ;
  1120. }
  1121. return answer;
  1122. }
  1123. int Q_log2( int val )
  1124. {
  1125. int answer;
  1126. answer = 0;
  1127. while ( ( val >>= 1 ) != 0 )
  1128. {
  1129. answer++;
  1130. }
  1131. return answer;
  1132. }
  1133. /*
  1134. * =================
  1135. * PlaneTypeForNormal
  1136. * =================
  1137. */
  1138. /*
  1139. * int PlaneTypeForNormal (vec3_t normal) {
  1140. * if ( normal[0] == 1.0 )
  1141. * return PLANE_X;
  1142. * if ( normal[1] == 1.0 )
  1143. * return PLANE_Y;
  1144. * if ( normal[2] == 1.0 )
  1145. * return PLANE_Z;
  1146. *
  1147. * return PLANE_NON_AXIAL;
  1148. * }
  1149. */
  1150. /*
  1151. * ================
  1152. * AxisMultiply
  1153. * ================
  1154. */
  1155. void AxisMultiply( float in1[ 3 ][ 3 ], float in2[ 3 ][ 3 ], float out[ 3 ][ 3 ] )
  1156. {
  1157. out[ 0 ][ 0 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 0 ];
  1158. out[ 0 ][ 1 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 1 ];
  1159. out[ 0 ][ 2 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 2 ];
  1160. out[ 1 ][ 0 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 0 ];
  1161. out[ 1 ][ 1 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 1 ];
  1162. out[ 1 ][ 2 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 2 ];
  1163. out[ 2 ][ 0 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 0 ];
  1164. out[ 2 ][ 1 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 1 ];
  1165. out[ 2 ][ 2 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 2 ];
  1166. }
  1167. void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
  1168. {
  1169. float angle;
  1170. static float sr, sp, sy, cr, cp, cy;
  1171. // static to help MS compiler fp bugs
  1172. angle = angles[ YAW ] * ( M_PI * 2 / 360 );
  1173. sy = sin( angle );
  1174. cy = cos( angle );
  1175. angle = angles[ PITCH ] * ( M_PI * 2 / 360 );
  1176. sp = sin( angle );
  1177. cp = cos( angle );
  1178. angle = angles[ ROLL ] * ( M_PI * 2 / 360 );
  1179. sr = sin( angle );
  1180. cr = cos( angle );
  1181. if ( forward )
  1182. {
  1183. forward[ 0 ] = cp * cy;
  1184. forward[ 1 ] = cp * sy;
  1185. forward[ 2 ] = -sp;
  1186. }
  1187. if ( right )
  1188. {
  1189. right[ 0 ] = ( -1 * sr * sp * cy + -1 * cr * -sy );
  1190. right[ 1 ] = ( -1 * sr * sp * sy + -1 * cr * cy );
  1191. right[ 2 ] = -1 * sr * cp;
  1192. }
  1193. if ( up )
  1194. {
  1195. up[ 0 ] = ( cr * sp * cy + -sr * -sy );
  1196. up[ 1 ] = ( cr * sp * sy + -sr * cy );
  1197. up[ 2 ] = cr * cp;
  1198. }
  1199. }
  1200. /*
  1201. * =================
  1202. * PerpendicularVector
  1203. *
  1204. * assumes "src" is normalized
  1205. * =================
  1206. */
  1207. void PerpendicularVector( vec3_t dst, const vec3_t src )
  1208. {
  1209. int pos;
  1210. int i;
  1211. float minelem = 1.0F;
  1212. vec3_t tempvec;
  1213. /*
  1214. * * find the smallest magnitude axially aligned vector
  1215. */
  1216. for ( pos = 0, i = 0; i < 3; i++ )
  1217. {
  1218. if ( Q_fabs( src[ i ] ) < minelem )
  1219. {
  1220. pos = i;
  1221. minelem = Q_fabs( src[ i ] );
  1222. }
  1223. }
  1224. tempvec[ 0 ] = tempvec[ 1 ] = tempvec[ 2 ] = 0.0F;
  1225. tempvec[ pos ] = 1.0F;
  1226. /*
  1227. * * project the point onto the plane defined by src
  1228. */
  1229. ProjectPointOnPlane( dst, tempvec, src );
  1230. /*
  1231. * * normalize the result
  1232. */
  1233. VectorNormalize( dst );
  1234. }
  1235. // Ridah
  1236. /*
  1237. * =================
  1238. * GetPerpendicularViewVector
  1239. *
  1240. * Used to find an "up" vector for drawing a sprite so that it always faces the view as best as possible
  1241. * =================
  1242. */
  1243. void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up )
  1244. {
  1245. vec3_t v1, v2;
  1246. VectorSubtract( point, p1, v1 );
  1247. VectorNormalize( v1 );
  1248. VectorSubtract( point, p2, v2 );
  1249. VectorNormalize( v2 );
  1250. CrossProduct( v1, v2, up );
  1251. VectorNormalize( up );
  1252. }
  1253. /*
  1254. * ================
  1255. * ProjectPointOntoVector
  1256. * ================
  1257. */
  1258. void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
  1259. {
  1260. vec3_t pVec, vec;
  1261. VectorSubtract( point, vStart, pVec );
  1262. VectorSubtract( vEnd, vStart, vec );
  1263. VectorNormalize( vec );
  1264. // project onto the directional vector for this segment
  1265. VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
  1266. }
  1267. #define LINE_DISTANCE_EPSILON 1e-05f
  1268. /*
  1269. * ================
  1270. * DistanceBetweenLineSegmentsSquared
  1271. * Return the smallest distance between two line segments, squared
  1272. * ================
  1273. */
  1274. vec_t DistanceBetweenLineSegmentsSquared( const vec3_t sP0, const vec3_t sP1,
  1275. const vec3_t tP0, const vec3_t tP1, float *s, float *t )
  1276. {
  1277. vec3_t sMag, tMag, diff;
  1278. float a, b, c, d, e;
  1279. float D;
  1280. float sN, sD;
  1281. float tN, tD;
  1282. vec3_t separation;
  1283. VectorSubtract( sP1, sP0, sMag );
  1284. VectorSubtract( tP1, tP0, tMag );
  1285. VectorSubtract( sP0, tP0, diff );
  1286. a = DotProduct( sMag, sMag );
  1287. b = DotProduct( sMag, tMag );
  1288. c = DotProduct( tMag, tMag );
  1289. d = DotProduct( sMag, diff );
  1290. e = DotProduct( tMag, diff );
  1291. sD = tD = D = a * c - b * b;
  1292. if ( D < LINE_DISTANCE_EPSILON )
  1293. {
  1294. // the lines are almost parallel
  1295. sN = 0.0; // force using point P0 on segment S1
  1296. sD = 1.0; // to prevent possible division by 0.0 later
  1297. tN = e;
  1298. tD = c;
  1299. }
  1300. else
  1301. {
  1302. // get the closest points on the infinite lines
  1303. sN = ( b * e - c * d );
  1304. tN = ( a * e - b * d );
  1305. if ( sN < 0.0 )
  1306. {
  1307. // sN < 0 => the s=0 edge is visible
  1308. sN = 0.0;
  1309. tN = e;
  1310. tD = c;
  1311. }
  1312. else if ( sN > sD )
  1313. {
  1314. // sN > sD => the s=1 edge is visible
  1315. sN = sD;
  1316. tN = e + b;
  1317. tD = c;
  1318. }
  1319. }
  1320. if ( tN < 0.0 )
  1321. {
  1322. // tN < 0 => the t=0 edge is visible
  1323. tN = 0.0;
  1324. // recompute sN for this edge
  1325. if ( -d < 0.0 )
  1326. {
  1327. sN = 0.0;
  1328. }
  1329. else if ( -d > a )
  1330. {
  1331. sN = sD;
  1332. }
  1333. else
  1334. {
  1335. sN = -d;
  1336. sD = a;
  1337. }
  1338. }
  1339. else if ( tN > tD )
  1340. {
  1341. // tN > tD => the t=1 edge is visible
  1342. tN = tD;
  1343. // recompute sN for this edge
  1344. if ( ( -d + b ) < 0.0 )
  1345. {
  1346. sN = 0;
  1347. }
  1348. else if ( ( -d + b ) > a )
  1349. {
  1350. sN = sD;
  1351. }
  1352. else
  1353. {
  1354. sN = ( -d + b );
  1355. sD = a;
  1356. }
  1357. }
  1358. // finally do the division to get *s and *t
  1359. *s = ( fabs( sN ) < LINE_DISTANCE_EPSILON ? 0.0 : sN / sD );
  1360. *t = ( fabs( tN ) < LINE_DISTANCE_EPSILON ? 0.0 : tN / tD );
  1361. // get the difference of the two closest points
  1362. VectorScale( sMag, *s, sMag );
  1363. VectorScale( tMag, *t, tMag );
  1364. VectorAdd( diff, sMag, separation );
  1365. VectorSubtract( separation, tMag, separation );
  1366. return VectorLengthSquared( separation );
  1367. }
  1368. /*
  1369. * ================
  1370. * DistanceBetweenLineSegments
  1371. *
  1372. * Return the smallest distance between two line segments
  1373. * ================
  1374. */
  1375. vec_t DistanceBetweenLineSegments( const vec3_t sP0, const vec3_t sP1, const vec3_t tP0, const vec3_t tP1, float *s, float *t )
  1376. {
  1377. return ( vec_t ) sqrt( DistanceBetweenLineSegmentsSquared( sP0, sP1, tP0, tP1, s, t ) );
  1378. }
  1379. /*
  1380. * ================
  1381. * ProjectPointOntoVectorBounded
  1382. * ================
  1383. */
  1384. void ProjectPointOntoVectorBounded( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
  1385. {
  1386. vec3_t pVec, vec;
  1387. int j;
  1388. VectorSubtract( point, vStart, pVec );
  1389. VectorSubtract( vEnd, vStart, vec );
  1390. VectorNormalize( vec );
  1391. // project onto the directional vector for this segment
  1392. VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
  1393. // check bounds
  1394. for ( j = 0; j < 3; j++ )
  1395. {
  1396. if ( ( vProj[ j ] > vStart[ j ] && vProj[ j ] > vEnd[ j ] ) || ( vProj[ j ] < vStart[ j ] && vProj[ j ] < vEnd[ j ] ) )
  1397. {
  1398. break;
  1399. }
  1400. }
  1401. if ( j < 3 )
  1402. {
  1403. if ( Q_fabs( vProj[ j ] - vStart[ j ] ) < Q_fabs( vProj[ j ] - vEnd[ j ] ) )
  1404. {
  1405. VectorCopy( vStart, vProj );
  1406. }
  1407. else
  1408. {
  1409. VectorCopy( vEnd, vProj );
  1410. }
  1411. }
  1412. }
  1413. /*
  1414. * ================
  1415. * DistanceFromLineSquared
  1416. * ================
  1417. */
  1418. float DistanceFromLineSquared( vec3_t p, vec3_t lp1, vec3_t lp2 )
  1419. {
  1420. vec3_t proj, t;
  1421. int j;
  1422. ProjectPointOntoVector( p, lp1, lp2, proj );
  1423. for ( j = 0; j < 3; j++ )
  1424. {
  1425. if ( ( proj[ j ] > lp1[ j ] && proj[ j ] > lp2[ j ] ) || ( proj[ j ] < lp1[ j ] && proj[ j ] < lp2[ j ] ) )
  1426. {
  1427. break;
  1428. }
  1429. }
  1430. if ( j < 3 )
  1431. {
  1432. if ( Q_fabs( proj[ j ] - lp1[ j ] ) < Q_fabs( proj[ j ] - lp2[ j ] ) )
  1433. {
  1434. VectorSubtract( p, lp1, t );
  1435. }
  1436. else
  1437. {
  1438. VectorSubtract( p, lp2, t );
  1439. }
  1440. return VectorLengthSquared( t );
  1441. }
  1442. VectorSubtract( p, proj, t );
  1443. return VectorLengthSquared( t );
  1444. }
  1445. /*
  1446. * ================
  1447. * DistanceFromVectorSquared
  1448. * ================
  1449. */
  1450. float DistanceFromVectorSquared( vec3_t p, vec3_t lp1, vec3_t lp2 )
  1451. {
  1452. vec3_t proj, t;
  1453. ProjectPointOntoVector( p, lp1, lp2, proj );
  1454. VectorSubtract( p, proj, t );
  1455. return VectorLengthSquared( t );
  1456. }
  1457. float vectoyaw( const vec3_t vec )
  1458. {
  1459. float yaw;
  1460. if ( vec[ YAW ] == 0 && vec[ PITCH ] == 0 )
  1461. {
  1462. yaw = 0;
  1463. }
  1464. else
  1465. {
  1466. if ( vec[ PITCH ] )
  1467. {
  1468. yaw = ( atan2( vec[ YAW ], vec[ PITCH ] ) * 180 / M_PI );
  1469. }
  1470. else if ( vec[ YAW ] > 0 )
  1471. {
  1472. yaw = 90;
  1473. }
  1474. else
  1475. {
  1476. yaw = 270;
  1477. }
  1478. if ( yaw < 0 )
  1479. {
  1480. yaw += 360;
  1481. }
  1482. }
  1483. return yaw;
  1484. }
  1485. /*
  1486. * =================
  1487. * AxisToAngles
  1488. *
  1489. * Used to convert the MD3 tag axis to MDC tag angles, which are much smaller
  1490. *
  1491. * This doesn't have to be fast, since it's only used for conversion in utils, try to avoid
  1492. * using this during gameplay
  1493. * =================
  1494. */
  1495. void AxisToAngles( /*const*/ vec3_t axis[ 3 ], vec3_t angles )
  1496. {
  1497. float length1;
  1498. float yaw, pitch, roll = 0.0f;
  1499. if ( axis[ 0 ][ 1 ] == 0 && axis[ 0 ][ 0 ] == 0 )
  1500. {
  1501. yaw = 0;
  1502. if ( axis[ 0 ][ 2 ] > 0 )
  1503. {
  1504. pitch = 90;
  1505. }
  1506. else
  1507. {
  1508. pitch = 270;
  1509. }
  1510. }
  1511. else
  1512. {
  1513. if ( axis[ 0 ][ 0 ] )
  1514. {
  1515. yaw = ( atan2( axis[ 0 ][ 1 ], axis[ 0 ][ 0 ] ) * 180 / M_PI );
  1516. }
  1517. else if ( axis[ 0 ][ 1 ] > 0 )
  1518. {
  1519. yaw = 90;
  1520. }
  1521. else
  1522. {
  1523. yaw = 270;
  1524. }
  1525. if ( yaw < 0 )
  1526. {
  1527. yaw += 360;
  1528. }
  1529. length1 = sqrt( axis[ 0 ][ 0 ] * axis[ 0 ][ 0 ] + axis[ 0 ][ 1 ] * axis[ 0 ][ 1 ] );
  1530. pitch = ( atan2( axis[ 0 ][ 2 ], length1 ) * 180 / M_PI );
  1531. if ( pitch < 0 )
  1532. {
  1533. pitch += 360;
  1534. }
  1535. roll = ( atan2( axis[ 1 ][ 2 ], axis[ 2 ][ 2 ] ) * 180 / M_PI );
  1536. if ( roll < 0 )
  1537. {
  1538. roll += 360;
  1539. }
  1540. }
  1541. angles[ PITCH ] = -pitch;
  1542. angles[ YAW ] = yaw;
  1543. angles[ ROLL ] = roll;
  1544. }
  1545. float VectorDistance( vec3_t v1, vec3_t v2 )
  1546. {
  1547. vec3_t dir;
  1548. VectorSubtract( v2, v1, dir );
  1549. return VectorLength( dir );
  1550. }
  1551. float VectorDistanceSquared( vec3_t v1, vec3_t v2 )
  1552. {
  1553. vec3_t dir;
  1554. VectorSubtract( v2, v1, dir );
  1555. return VectorLengthSquared( dir );
  1556. }
  1557. // done.
  1558. /*
  1559. * ================
  1560. * VectorMaxComponent
  1561. *
  1562. * Return the biggest component of some vector
  1563. * ================
  1564. */
  1565. float VectorMaxComponent( vec3_t v )
  1566. {
  1567. float biggest = v[ 0 ];
  1568. if ( v[ 1 ] > biggest )
  1569. {
  1570. biggest = v[ 1 ];
  1571. }
  1572. if ( v[ 2 ] > biggest )
  1573. {
  1574. biggest = v[ 2 ];
  1575. }
  1576. return biggest;
  1577. }
  1578. /*
  1579. * ================
  1580. * VectorMinComponent
  1581. *
  1582. * Return the smallest component of some vector
  1583. * ================
  1584. */
  1585. float VectorMinComponent( vec3_t v )
  1586. {
  1587. float smallest = v[ 0 ];
  1588. if ( v[ 1 ] < smallest )
  1589. {
  1590. smallest = v[ 1 ];
  1591. }
  1592. if ( v[ 2 ] < smallest )
  1593. {
  1594. smallest = v[ 2 ];
  1595. }
  1596. return smallest;
  1597. }
  1598. //=============================================
  1599. // RB: XreaL matrix math functions
  1600. // *INDENT-OFF*
  1601. void MatrixIdentity( matrix_t m )
  1602. {
  1603. m[ 0 ] = 1;
  1604. m[ 4 ] = 0;
  1605. m[ 8 ] = 0;
  1606. m[ 12 ] = 0;
  1607. m[ 1 ] = 0;
  1608. m[ 5 ] = 1;
  1609. m[ 9 ] = 0;
  1610. m[ 13 ] = 0;
  1611. m[ 2 ] = 0;
  1612. m[ 6 ] = 0;
  1613. m[ 10 ] = 1;
  1614. m[ 14 ] = 0;
  1615. m[ 3 ] = 0;
  1616. m[ 7 ] = 0;
  1617. m[ 11 ] = 0;
  1618. m[ 15 ] = 1;
  1619. }
  1620. void MatrixClear( matrix_t m )
  1621. {
  1622. m[ 0 ] = 0;
  1623. m[ 4 ] = 0;
  1624. m[ 8 ] = 0;
  1625. m[ 12 ] = 0;
  1626. m[ 1 ] = 0;
  1627. m[ 5 ] = 0;
  1628. m[ 9 ] = 0;
  1629. m[ 13 ] = 0;
  1630. m[ 2 ] = 0;
  1631. m[ 6 ] = 0;
  1632. m[ 10 ] = 0;
  1633. m[ 14 ] = 0;
  1634. m[ 3 ] = 0;
  1635. m[ 7 ] = 0;
  1636. m[ 11 ] = 0;
  1637. m[ 15 ] = 0;
  1638. }
  1639. void MatrixCopy( const matrix_t in, matrix_t out )
  1640. {
  1641. out[ 0 ] = in[ 0 ];
  1642. out[ 4 ] = in[ 4 ];
  1643. out[ 8 ] = in[ 8 ];
  1644. out[ 12 ] = in[ 12 ];
  1645. out[ 1 ] = in[ 1 ];
  1646. out[ 5 ] = in[ 5 ];
  1647. out[ 9 ] = in[ 9 ];
  1648. out[ 13 ] = in[ 13 ];
  1649. out[ 2 ] = in[ 2 ];
  1650. out[ 6 ] = in[ 6 ];
  1651. out[ 10 ] = in[ 10 ];
  1652. out[ 14 ] = in[ 14 ];
  1653. out[ 3 ] = in[ 3 ];
  1654. out[ 7 ] = in[ 7 ];
  1655. out[ 11 ] = in[ 11 ];
  1656. out[ 15 ] = in[ 15 ];
  1657. }
  1658. qboolean MatrixCompare( const matrix_t a, const matrix_t b )
  1659. {
  1660. return ( a[ 0 ] == b[ 0 ] && a[ 4 ] == b[ 4 ] && a[ 8 ] == b[ 8 ] && a[ 12 ] == b[ 12 ] &&
  1661. a[ 1 ] == b[ 1 ] && a[ 5 ] == b[ 5 ] && a[ 9 ] == b[ 9 ] && a[ 13 ] == b[ 13 ] &&
  1662. a[ 2 ] == b[ 2 ] && a[ 6 ] == b[ 6 ] && a[ 10 ] == b[ 10 ] && a[ 14 ] == b[ 14 ] &&
  1663. a[ 3 ] == b[ 3 ] && a[ 7 ] == b[ 7 ] && a[ 11 ] == b[ 11 ] && a[ 15 ] == b[ 15 ] );
  1664. }
  1665. void MatrixTranspose( const matrix_t in, matrix_t out )
  1666. {
  1667. out[ 0 ] = in[ 0 ];
  1668. out[ 1 ] = in[ 4 ];
  1669. out[ 2 ] = in[ 8 ];
  1670. out[ 3 ] = in[ 12 ];
  1671. out[ 4 ] = in[ 1 ];
  1672. out[ 5 ] = in[ 5 ];
  1673. out[ 6 ] = in[ 9 ];
  1674. out[ 7 ] = in[ 13 ];
  1675. out[ 8 ] = in[ 2 ];
  1676. out[ 9 ] = in[ 6 ];
  1677. out[ 10 ] = in[ 10 ];
  1678. out[ 11 ] = in[ 14 ];
  1679. out[ 12 ] = in[ 3 ];
  1680. out[ 13 ] = in[ 7 ];
  1681. out[ 14 ] = in[ 11 ];
  1682. out[ 15 ] = in[ 15 ];
  1683. }
  1684. // helper functions for MatrixInverse from GtkRadiant C mathlib
  1685. static float m3_det( matrix3x3_t mat )
  1686. {
  1687. float det;
  1688. det = mat[ 0 ] * ( mat[ 4 ] * mat[ 8 ] - mat[ 7 ] * mat[ 5 ] )
  1689. - mat[ 1 ] * ( mat[ 3 ] * mat[ 8 ] - mat[ 6 ] * mat[ 5 ] )
  1690. + mat[ 2 ] * ( mat[ 3 ] * mat[ 7 ] - mat[ 6 ] * mat[ 4 ] );
  1691. return ( det );
  1692. }
  1693. /*static int m3_inverse( matrix3x3_t mr, matrix3x3_t ma )
  1694. * {
  1695. * float det = m3_det( ma );
  1696. *
  1697. * if (det == 0 )
  1698. * {
  1699. * return 1;
  1700. * }
  1701. *
  1702. *
  1703. * mr[0] = ma[4]*ma[8] - ma[5]*ma[7] / det;
  1704. * mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det;
  1705. * mr[2] = ma[1]*ma[5] - ma[4]*ma[2] / det;
  1706. *
  1707. * mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det;
  1708. * mr[4] = ma[0]*ma[8] - ma[6]*ma[2] / det;
  1709. * mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det;
  1710. *
  1711. * mr[6] = ma[3]*ma[7] - ma[6]*ma[4] / det;
  1712. * mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det;
  1713. * mr[8] = ma[0]*ma[4] - ma[1]*ma[3] / det;
  1714. *
  1715. * return 0;
  1716. * }*/
  1717. static void m4_submat( matrix_t mr, matrix3x3_t mb, int i, int j )
  1718. {
  1719. int ti, tj, idst = 0, jdst = 0;
  1720. for ( ti = 0; ti < 4; ti++ )
  1721. {
  1722. if ( ti < i )
  1723. {
  1724. idst = ti;
  1725. }
  1726. else if ( ti > i )
  1727. {
  1728. idst = ti - 1;
  1729. }
  1730. for ( tj = 0; tj < 4; tj++ )
  1731. {
  1732. if ( tj < j )
  1733. {
  1734. jdst = tj;
  1735. }
  1736. else if ( tj > j )
  1737. {
  1738. jdst = tj - 1;
  1739. }
  1740. if ( ti != i && tj != j )
  1741. {
  1742. mb[ idst * 3 + jdst ] = mr[ ti * 4 + tj ];
  1743. }
  1744. }
  1745. }
  1746. }
  1747. static float m4_det( matrix_t mr )
  1748. {
  1749. float det, result = 0, i = 1;
  1750. matrix3x3_t msub3;
  1751. int n;
  1752. for ( n = 0; n < 4; n++, i *= -1 )
  1753. {
  1754. m4_submat( mr, msub3, 0, n );
  1755. det = m3_det( msub3 );
  1756. result += mr[ n ] * det * i;
  1757. }
  1758. return result;
  1759. }
  1760. qboolean MatrixInverse( matrix_t matrix )
  1761. {
  1762. float mdet = m4_det( matrix );
  1763. matrix3x3_t mtemp;
  1764. int i, j, sign;
  1765. matrix_t m4x4_temp;
  1766. #if 0
  1767. if ( fabs( mdet ) < 0.0000000001 )
  1768. {
  1769. return qtrue;
  1770. }
  1771. #endif
  1772. MatrixCopy( matrix, m4x4_temp );
  1773. for ( i = 0; i < 4; i++ )
  1774. {
  1775. for ( j = 0; j < 4; j++ )
  1776. {
  1777. sign = 1 - ( ( i + j ) % 2 ) * 2;
  1778. m4_submat( m4x4_temp, mtemp, i, j );
  1779. // FIXME: try using * inverse det and see if speed/accuracy are good enough
  1780. matrix[ i + j * 4 ] = ( m3_det( mtemp ) * sign ) / mdet;
  1781. }
  1782. }
  1783. return qfalse;
  1784. }
  1785. void MatrixSetupXRotation( matrix_t m, vec_t degrees )
  1786. {
  1787. vec_t a = DEG2RAD( degrees );
  1788. m[ 0 ] = 1;
  1789. m[ 4 ] = 0;
  1790. m[ 8 ] = 0;
  1791. m[ 12 ] = 0;
  1792. m[ 1 ] = 0;
  1793. m[ 5 ] = cos( a );
  1794. m[ 9 ] = -sin( a );
  1795. m[ 13 ] = 0;
  1796. m[ 2 ] = 0;
  1797. m[ 6 ] = sin( a );
  1798. m[ 10 ] = cos( a );
  1799. m[ 14 ] = 0;
  1800. m[ 3 ] = 0;
  1801. m[ 7 ] = 0;
  1802. m[ 11 ] = 0;
  1803. m[ 15 ] = 1;
  1804. }
  1805. void MatrixSetupYRotation( matrix_t m, vec_t degrees )
  1806. {
  1807. vec_t a = DEG2RAD( degrees );
  1808. m[ 0 ] = cos( a );
  1809. m[ 4 ] = 0;
  1810. m[ 8 ] = sin( a );
  1811. m[ 12 ] = 0;
  1812. m[ 1 ] = 0;
  1813. m[ 5 ] = 1;
  1814. m[ 9 ] = 0;
  1815. m[ 13 ] = 0;
  1816. m[ 2 ] = -sin( a );
  1817. m[ 6 ] = 0;
  1818. m[ 10 ] = cos( a );
  1819. m[ 14 ] = 0;
  1820. m[ 3 ] = 0;
  1821. m[ 7 ] = 0;
  1822. m[ 11 ] = 0;
  1823. m[ 15 ] = 1;
  1824. }
  1825. void MatrixSetupZRotation( matrix_t m, vec_t degrees )
  1826. {
  1827. vec_t a = DEG2RAD( degrees );
  1828. m[ 0 ] = cos( a );
  1829. m[ 4 ] = -sin( a );
  1830. m[ 8 ] = 0;
  1831. m[ 12 ] = 0;
  1832. m[ 1 ] = sin( a );
  1833. m[ 5 ] = cos( a );
  1834. m[ 9 ] = 0;
  1835. m[ 13 ] = 0;
  1836. m[ 2 ] = 0;
  1837. m[ 6 ] = 0;
  1838. m[ 10 ] = 1;
  1839. m[ 14 ] = 0;
  1840. m[ 3 ] = 0;
  1841. m[ 7 ] = 0;
  1842. m[ 11 ] = 0;
  1843. m[ 15 ] = 1;
  1844. }
  1845. void MatrixSetupTranslation( matrix_t m, vec_t x, vec_t y, vec_t z )
  1846. {
  1847. m[ 0 ] = 1;
  1848. m[ 4 ] = 0;
  1849. m[ 8 ] = 0;
  1850. m[ 12 ] = x;
  1851. m[ 1 ] = 0;
  1852. m[ 5 ] = 1;
  1853. m[ 9 ] = 0;
  1854. m[ 13 ] = y;
  1855. m[ 2 ] = 0;
  1856. m[ 6 ] = 0;
  1857. m[ 10 ] = 1;
  1858. m[ 14 ] = z;
  1859. m[ 3 ] = 0;
  1860. m[ 7 ] = 0;
  1861. m[ 11 ] = 0;
  1862. m[ 15 ] = 1;
  1863. }
  1864. void MatrixSetupScale( matrix_t m, vec_t x, vec_t y, vec_t z )
  1865. {
  1866. m[ 0 ] = x;
  1867. m[ 4 ] = 0;
  1868. m[ 8 ] = 0;
  1869. m[ 12 ] = 0;
  1870. m[ 1 ] = 0;
  1871. m[ 5 ] = y;
  1872. m[ 9 ] = 0;
  1873. m[ 13 ] = 0;
  1874. m[ 2 ] = 0;
  1875. m[ 6 ] = 0;
  1876. m[ 10 ] = z;
  1877. m[ 14 ] = 0;
  1878. m[ 3 ] = 0;
  1879. m[ 7 ] = 0;
  1880. m[ 11 ] = 0;
  1881. m[ 15 ] = 1;
  1882. }
  1883. void MatrixSetupShear( matrix_t m, vec_t x, vec_t y )
  1884. {
  1885. m[ 0 ] = 1;
  1886. m[ 4 ] = x;
  1887. m[ 8 ] = 0;
  1888. m[ 12 ] = 0;
  1889. m[ 1 ] = y;
  1890. m[ 5 ] = 1;
  1891. m[ 9 ] = 0;
  1892. m[ 13 ] = 0;
  1893. m[ 2 ] = 0;
  1894. m[ 6 ] = 0;
  1895. m[ 10 ] = 1;
  1896. m[ 14 ] = 0;
  1897. m[ 3 ] = 0;
  1898. m[ 7 ] = 0;
  1899. m[ 11 ] = 0;
  1900. m[ 15 ] = 1;
  1901. }
  1902. void MatrixMultiply( const matrix_t a, const matrix_t b, matrix_t out )
  1903. {
  1904. #if idx86_sse
  1905. //#error MatrixMultiply
  1906. int i;
  1907. __m128 _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7;
  1908. _t4 = _mm_loadu_ps( &a[ 0 ] );
  1909. _t5 = _mm_loadu_ps( &a[ 4 ] );
  1910. _t6 = _mm_loadu_ps( &a[ 8 ] );
  1911. _t7 = _mm_loadu_ps( &a[ 12 ] );
  1912. for ( i = 0; i < 4; i++ )
  1913. {
  1914. _t0 = _mm_load1_ps( &b[ i * 4 + 0 ] );
  1915. _t0 = _mm_mul_ps( _t4, _t0 );
  1916. _t1 = _mm_load1_ps( &b[ i * 4 + 1 ] );
  1917. _t1 = _mm_mul_ps( _t5, _t1 );
  1918. _t2 = _mm_load1_ps( &b[ i * 4 + 2 ] );
  1919. _t2 = _mm_mul_ps( _t6, _t2 );
  1920. _t3 = _mm_load1_ps( &b[ i * 4 + 3 ] );
  1921. _t3 = _mm_mul_ps( _t7, _t3 );
  1922. _t1 = _mm_add_ps( _t0, _t1 );
  1923. _t2 = _mm_add_ps( _t1, _t2 );
  1924. _t3 = _mm_add_ps( _t2, _t3 );
  1925. _mm_storeu_ps( &out[ i * 4 ], _t3 );
  1926. }
  1927. #else
  1928. out[ 0 ] = b[ 0 ] * a[ 0 ] + b[ 1 ] * a[ 4 ] + b[ 2 ] * a[ 8 ] + b[ 3 ] * a[ 12 ];
  1929. out[ 1 ] = b[ 0 ] * a[ 1 ] + b[ 1 ] * a[ 5 ] + b[ 2 ] * a[ 9 ] + b[ 3 ] * a[ 13 ];
  1930. out[ 2 ] = b[ 0 ] * a[ 2 ] + b[ 1 ] * a[ 6 ] + b[ 2 ] * a[ 10 ] + b[ 3 ] * a[ 14 ];
  1931. out[ 3 ] = b[ 0 ] * a[ 3 ] + b[ 1 ] * a[ 7 ] + b[ 2 ] * a[ 11 ] + b[ 3 ] * a[ 15 ];

Large files files are truncated, but you can click here to view the full file