PageRenderTime 73ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  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 ];
  1932. out[ 4 ] = b[ 4 ] * a[ 0 ] + b[ 5 ] * a[ 4 ] + b[ 6 ] * a[ 8 ] + b[ 7 ] * a[ 12 ];
  1933. out[ 5 ] = b[ 4 ] * a[ 1 ] + b[ 5 ] * a[ 5 ] + b[ 6 ] * a[ 9 ] + b[ 7 ] * a[ 13 ];
  1934. out[ 6 ] = b[ 4 ] * a[ 2 ] + b[ 5 ] * a[ 6 ] + b[ 6 ] * a[ 10 ] + b[ 7 ] * a[ 14 ];
  1935. out[ 7 ] = b[ 4 ] * a[ 3 ] + b[ 5 ] * a[ 7 ] + b[ 6 ] * a[ 11 ] + b[ 7 ] * a[ 15 ];
  1936. out[ 8 ] = b[ 8 ] * a[ 0 ] + b[ 9 ] * a[ 4 ] + b[ 10 ] * a[ 8 ] + b[ 11 ] * a[ 12 ];
  1937. out[ 9 ] = b[ 8 ] * a[ 1 ] + b[ 9 ] * a[ 5 ] + b[ 10 ] * a[ 9 ] + b[ 11 ] * a[ 13 ];
  1938. out[ 10 ] = b[ 8 ] * a[ 2 ] + b[ 9 ] * a[ 6 ] + b[ 10 ] * a[ 10 ] + b[ 11 ] * a[ 14 ];
  1939. out[ 11 ] = b[ 8 ] * a[ 3 ] + b[ 9 ] * a[ 7 ] + b[ 10 ] * a[ 11 ] + b[ 11 ] * a[ 15 ];
  1940. out[ 12 ] = b[ 12 ] * a[ 0 ] + b[ 13 ] * a[ 4 ] + b[ 14 ] * a[ 8 ] + b[ 15 ] * a[ 12 ];
  1941. out[ 13 ] = b[ 12 ] * a[ 1 ] + b[ 13 ] * a[ 5 ] + b[ 14 ] * a[ 9 ] + b[ 15 ] * a[ 13 ];
  1942. out[ 14 ] = b[ 12 ] * a[ 2 ] + b[ 13 ] * a[ 6 ] + b[ 14 ] * a[ 10 ] + b[ 15 ] * a[ 14 ];
  1943. out[ 15 ] = b[ 12 ] * a[ 3 ] + b[ 13 ] * a[ 7 ] + b[ 14 ] * a[ 11 ] + b[ 15 ] * a[ 15 ];
  1944. #endif
  1945. }
  1946. void MatrixMultiply2( matrix_t m, const matrix_t m2 )
  1947. {
  1948. matrix_t tmp;
  1949. MatrixCopy( m, tmp );
  1950. MatrixMultiply( tmp, m2, m );
  1951. }
  1952. void MatrixMultiplyRotation( matrix_t m, vec_t pitch, vec_t yaw, vec_t roll )
  1953. {
  1954. matrix_t tmp, rot;
  1955. MatrixCopy( m, tmp );
  1956. MatrixFromAngles( rot, pitch, yaw, roll );
  1957. MatrixMultiply( tmp, rot, m );
  1958. }
  1959. void MatrixMultiplyZRotation( matrix_t m, vec_t degrees )
  1960. {
  1961. matrix_t tmp;
  1962. float angle = DEG2RAD( degrees );
  1963. float s = sin( angle );
  1964. float c = cos( angle );
  1965. MatrixCopy( m, tmp );
  1966. m[ 0 ] = tmp[ 0 ] * c + tmp[ 4 ] * s;
  1967. m[ 1 ] = tmp[ 1 ] * c + tmp[ 5 ] * s;
  1968. m[ 2 ] = tmp[ 2 ] * c + tmp[ 6 ] * s;
  1969. m[ 3 ] = tmp[ 3 ] * c + tmp[ 7 ] * s;
  1970. m[ 4 ] = tmp[ 0 ] * -s + tmp[ 4 ] * c;
  1971. m[ 5 ] = tmp[ 1 ] * -s + tmp[ 5 ] * c;
  1972. m[ 6 ] = tmp[ 2 ] * -s + tmp[ 6 ] * c;
  1973. m[ 7 ] = tmp[ 3 ] * -s + tmp[ 7 ] * c;
  1974. }
  1975. void MatrixMultiplyTranslation( matrix_t m, vec_t x, vec_t y, vec_t z )
  1976. {
  1977. m[ 12 ] += m[ 0 ] * x + m[ 4 ] * y + m[ 8 ] * z;
  1978. m[ 13 ] += m[ 1 ] * x + m[ 5 ] * y + m[ 9 ] * z;
  1979. m[ 14 ] += m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z;
  1980. m[ 15 ] += m[ 3 ] * x + m[ 7 ] * y + m[ 11 ] * z;
  1981. }
  1982. void MatrixMultiplyScale( matrix_t m, vec_t x, vec_t y, vec_t z )
  1983. {
  1984. m[ 0 ] *= x;
  1985. m[ 4 ] *= y;
  1986. m[ 8 ] *= z;
  1987. m[ 1 ] *= x;
  1988. m[ 5 ] *= y;
  1989. m[ 9 ] *= z;
  1990. m[ 2 ] *= x;
  1991. m[ 6 ] *= y;
  1992. m[ 10 ] *= z;
  1993. m[ 3 ] *= x;
  1994. m[ 7 ] *= y;
  1995. m[ 11 ] *= z;
  1996. }
  1997. void MatrixMultiplyShear( matrix_t m, vec_t x, vec_t y )
  1998. {
  1999. matrix_t tmp;
  2000. MatrixCopy( m, tmp );
  2001. m[ 0 ] += m[ 4 ] * y;
  2002. m[ 1 ] += m[ 5 ] * y;
  2003. m[ 2 ] += m[ 6 ] * y;
  2004. m[ 3 ] += m[ 7 ] * y;
  2005. m[ 4 ] += tmp[ 0 ] * x;
  2006. m[ 5 ] += tmp[ 1 ] * x;
  2007. m[ 6 ] += tmp[ 2 ] * x;
  2008. m[ 7 ] += tmp[ 3 ] * x;
  2009. }
  2010. void MatrixToAngles( const matrix_t m, vec3_t angles )
  2011. {
  2012. #if 1
  2013. float theta;
  2014. float cp;
  2015. float sp;
  2016. sp = m[ 2 ];
  2017. // cap off our sin value so that we don't get any NANs
  2018. if ( sp > 1.0 )
  2019. {
  2020. sp = 1.0;
  2021. }
  2022. else if ( sp < -1.0 )
  2023. {
  2024. sp = -1.0;
  2025. }
  2026. theta = -asin( sp );
  2027. cp = cos( theta );
  2028. if ( cp > 8192 * FLT_EPSILON )
  2029. {
  2030. angles[ PITCH ] = RAD2DEG( theta );
  2031. angles[ YAW ] = RAD2DEG( atan2( m[ 1 ], m[ 0 ] ) );
  2032. angles[ ROLL ] = RAD2DEG( atan2( m[ 6 ], m[ 10 ] ) );
  2033. }
  2034. else
  2035. {
  2036. angles[ PITCH ] = RAD2DEG( theta );
  2037. angles[ YAW ] = RAD2DEG( -atan2( m[ 4 ], m[ 5 ] ) );
  2038. angles[ ROLL ] = 0;
  2039. }
  2040. #else
  2041. float a;
  2042. float ca;
  2043. a = asin( -m[ 2 ] );
  2044. ca = cos( a );
  2045. if ( fabs( ca ) > 0.005 ) // Gimbal lock?
  2046. {
  2047. angles[ PITCH ] = RAD2DEG( atan2( m[ 6 ] / ca, m[ 10 ] / ca ) );
  2048. angles[ YAW ] = RAD2DEG( a );
  2049. angles[ ROLL ] = RAD2DEG( atan2( m[ 1 ] / ca, m[ 0 ] / ca ) );
  2050. }
  2051. else
  2052. {
  2053. // Gimbal lock has occurred
  2054. angles[ PITCH ] = RAD2DEG( atan2( -m[ 9 ], m[ 5 ] ) );
  2055. angles[ YAW ] = RAD2DEG( a );
  2056. angles[ ROLL ] = 0;
  2057. }
  2058. #endif
  2059. }
  2060. void MatrixFromAngles( matrix_t m, vec_t pitch, vec_t yaw, vec_t roll )
  2061. {
  2062. static float sr, sp, sy, cr, cp, cy;
  2063. // static to help MS compiler fp bugs
  2064. sp = sin( DEG2RAD( pitch ) );
  2065. cp = cos( DEG2RAD( pitch ) );
  2066. sy = sin( DEG2RAD( yaw ) );
  2067. cy = cos( DEG2RAD( yaw ) );
  2068. sr = sin( DEG2RAD( roll ) );
  2069. cr = cos( DEG2RAD( roll ) );
  2070. m[ 0 ] = cp * cy;
  2071. m[ 4 ] = ( sr * sp * cy + cr * -sy );
  2072. m[ 8 ] = ( cr * sp * cy + -sr * -sy );
  2073. m[ 12 ] = 0;
  2074. m[ 1 ] = cp * sy;
  2075. m[ 5 ] = ( sr * sp * sy + cr * cy );
  2076. m[ 9 ] = ( cr * sp * sy + -sr * cy );
  2077. m[ 13 ] = 0;
  2078. m[ 2 ] = -sp;
  2079. m[ 6 ] = sr * cp;
  2080. m[ 10 ] = cr * cp;
  2081. m[ 14 ] = 0;
  2082. m[ 3 ] = 0;
  2083. m[ 7 ] = 0;
  2084. m[ 11 ] = 0;
  2085. m[ 15 ] = 1;
  2086. }
  2087. void MatrixFromVectorsFLU( matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up )
  2088. {
  2089. m[ 0 ] = forward[ 0 ];
  2090. m[ 4 ] = left[ 0 ];
  2091. m[ 8 ] = up[ 0 ];
  2092. m[ 12 ] = 0;
  2093. m[ 1 ] = forward[ 1 ];
  2094. m[ 5 ] = left[ 1 ];
  2095. m[ 9 ] = up[ 1 ];
  2096. m[ 13 ] = 0;
  2097. m[ 2 ] = forward[ 2 ];
  2098. m[ 6 ] = left[ 2 ];
  2099. m[ 10 ] = up[ 2 ];
  2100. m[ 14 ] = 0;
  2101. m[ 3 ] = 0;
  2102. m[ 7 ] = 0;
  2103. m[ 11 ] = 0;
  2104. m[ 15 ] = 1;
  2105. }
  2106. void MatrixFromVectorsFRU( matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up )
  2107. {
  2108. m[ 0 ] = forward[ 0 ];
  2109. m[ 4 ] = -right[ 0 ];
  2110. m[ 8 ] = up[ 0 ];
  2111. m[ 12 ] = 0;
  2112. m[ 1 ] = forward[ 1 ];
  2113. m[ 5 ] = -right[ 1 ];
  2114. m[ 9 ] = up[ 1 ];
  2115. m[ 13 ] = 0;
  2116. m[ 2 ] = forward[ 2 ];
  2117. m[ 6 ] = -right[ 2 ];
  2118. m[ 10 ] = up[ 2 ];
  2119. m[ 14 ] = 0;
  2120. m[ 3 ] = 0;
  2121. m[ 7 ] = 0;
  2122. m[ 11 ] = 0;
  2123. m[ 15 ] = 1;
  2124. }
  2125. void MatrixFromQuat( matrix_t m, const quat_t q )
  2126. {
  2127. #if 1
  2128. /*
  2129. * From Quaternion to Matrix and Back
  2130. * February 27th 2005
  2131. * J.M.P. van Waveren
  2132. *
  2133. * http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
  2134. */
  2135. float x2, y2, z2 /*, w2*/;
  2136. float yy2, xy2;
  2137. float xz2, yz2, zz2;
  2138. float wz2, wy2, wx2, xx2;
  2139. x2 = q[ 0 ] + q[ 0 ];
  2140. y2 = q[ 1 ] + q[ 1 ];
  2141. z2 = q[ 2 ] + q[ 2 ];
  2142. //w2 = q[3] + q[3]; //Is this used for some underlying optimization?
  2143. yy2 = q[ 1 ] * y2;
  2144. xy2 = q[ 0 ] * y2;
  2145. xz2 = q[ 0 ] * z2;
  2146. yz2 = q[ 1 ] * z2;
  2147. zz2 = q[ 2 ] * z2;
  2148. wz2 = q[ 3 ] * z2;
  2149. wy2 = q[ 3 ] * y2;
  2150. wx2 = q[ 3 ] * x2;
  2151. xx2 = q[ 0 ] * x2;
  2152. m[ 0 ] = -yy2 - zz2 + 1.0f;
  2153. m[ 1 ] = xy2 + wz2;
  2154. m[ 2 ] = xz2 - wy2;
  2155. m[ 4 ] = xy2 - wz2;
  2156. m[ 5 ] = -xx2 - zz2 + 1.0f;
  2157. m[ 6 ] = yz2 + wx2;
  2158. m[ 8 ] = xz2 + wy2;
  2159. m[ 9 ] = yz2 - wx2;
  2160. m[ 10 ] = -xx2 - yy2 + 1.0f;
  2161. m[ 3 ] = m[ 7 ] = m[ 11 ] = m[ 12 ] = m[ 13 ] = m[ 14 ] = 0;
  2162. m[ 15 ] = 1;
  2163. #else
  2164. /*
  2165. * http://www.gamedev.net/reference/articles/article1691.asp#Q54
  2166. * Q54. How do I convert a quaternion to a rotation matrix?
  2167. *
  2168. * Assuming that a quaternion has been created in the form:
  2169. *
  2170. * Q = |X Y Z W|
  2171. *
  2172. * Then the quaternion can then be converted into a 4x4 rotation
  2173. * matrix using the following expression (Warning: you might have to
  2174. * transpose this matrix if you (do not) follow the OpenGL order!):
  2175. *
  2176. * ? 2 2 ?
  2177. * ? 1 - (2Y + 2Z ) 2XY - 2ZW 2XZ + 2YW ?
  2178. * ? ?
  2179. * ? 2 2 ?
  2180. * M = ? 2XY + 2ZW 1 - (2X + 2Z ) 2YZ - 2XW ?
  2181. * ? ?
  2182. * ? 2 2 ?
  2183. * ? 2XZ - 2YW 2YZ + 2XW 1 - (2X + 2Y ) ?
  2184. * ? ?
  2185. */
  2186. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
  2187. float xx, xy, xz, xw, yy, yz, yw, zz, zw;
  2188. xx = q[ 0 ] * q[ 0 ];
  2189. xy = q[ 0 ] * q[ 1 ];
  2190. xz = q[ 0 ] * q[ 2 ];
  2191. xw = q[ 0 ] * q[ 3 ];
  2192. yy = q[ 1 ] * q[ 1 ];
  2193. yz = q[ 1 ] * q[ 2 ];
  2194. yw = q[ 1 ] * q[ 3 ];
  2195. zz = q[ 2 ] * q[ 2 ];
  2196. zw = q[ 2 ] * q[ 3 ];
  2197. m[ 0 ] = 1 - 2 * ( yy + zz );
  2198. m[ 1 ] = 2 * ( xy + zw );
  2199. m[ 2 ] = 2 * ( xz - yw );
  2200. m[ 4 ] = 2 * ( xy - zw );
  2201. m[ 5 ] = 1 - 2 * ( xx + zz );
  2202. m[ 6 ] = 2 * ( yz + xw );
  2203. m[ 8 ] = 2 * ( xz + yw );
  2204. m[ 9 ] = 2 * ( yz - xw );
  2205. m[ 10 ] = 1 - 2 * ( xx + yy );
  2206. m[ 3 ] = m[ 7 ] = m[ 11 ] = m[ 12 ] = m[ 13 ] = m[ 14 ] = 0;
  2207. m[ 15 ] = 1;
  2208. #endif
  2209. }
  2210. void MatrixFromPlanes( matrix_t m, const vec4_t left, const vec4_t right, const vec4_t bottom, const vec4_t top, const vec4_t near, const vec4_t far )
  2211. {
  2212. m[ 0 ] = ( right[ 0 ] - left[ 0 ] ) / 2;
  2213. m[ 1 ] = ( top[ 0 ] - bottom[ 0 ] ) / 2;
  2214. m[ 2 ] = ( far[ 0 ] - near[ 0 ] ) / 2;
  2215. m[ 3 ] = right[ 0 ] - ( right[ 0 ] - left[ 0 ] ) / 2;
  2216. m[ 4 ] = ( right[ 1 ] - left[ 1 ] ) / 2;
  2217. m[ 5 ] = ( top[ 1 ] - bottom[ 1 ] ) / 2;
  2218. m[ 6 ] = ( far[ 1 ] - near[ 1 ] ) / 2;
  2219. m[ 7 ] = right[ 1 ] - ( right[ 1 ] - left[ 1 ] ) / 2;
  2220. m[ 8 ] = ( right[ 2 ] - left[ 2 ] ) / 2;
  2221. m[ 9 ] = ( top[ 2 ] - bottom[ 2 ] ) / 2;
  2222. m[ 10 ] = ( far[ 2 ] - near[ 2 ] ) / 2;
  2223. m[ 11 ] = right[ 2 ] - ( right[ 2 ] - left[ 2 ] ) / 2;
  2224. #if 0
  2225. m[ 12 ] = ( right[ 3 ] - left[ 3 ] ) / 2;
  2226. m[ 13 ] = ( top[ 3 ] - bottom[ 3 ] ) / 2;
  2227. m[ 14 ] = ( far[ 3 ] - near[ 3 ] ) / 2;
  2228. m[ 15 ] = right[ 3 ] - ( right[ 3 ] - left[ 3 ] ) / 2;
  2229. #else
  2230. m[ 12 ] = ( -right[ 3 ] - -left[ 3 ] ) / 2;
  2231. m[ 13 ] = ( -top[ 3 ] - -bottom[ 3 ] ) / 2;
  2232. m[ 14 ] = ( -far[ 3 ] - -near[ 3 ] ) / 2;
  2233. m[ 15 ] = -right[ 3 ] - ( -right[ 3 ] - -left[ 3 ] ) / 2;
  2234. #endif
  2235. }
  2236. void MatrixToVectorsFLU( const matrix_t m, vec3_t forward, vec3_t left, vec3_t up )
  2237. {
  2238. if ( forward )
  2239. {
  2240. forward[ 0 ] = m[ 0 ]; // cp*cy;
  2241. forward[ 1 ] = m[ 1 ]; // cp*sy;
  2242. forward[ 2 ] = m[ 2 ]; //-sp;
  2243. }
  2244. if ( left )
  2245. {
  2246. left[ 0 ] = m[ 4 ]; // sr*sp*cy+cr*-sy;
  2247. left[ 1 ] = m[ 5 ]; // sr*sp*sy+cr*cy;
  2248. left[ 2 ] = m[ 6 ]; // sr*cp;
  2249. }
  2250. if ( up )
  2251. {
  2252. up[ 0 ] = m[ 8 ]; // cr*sp*cy+-sr*-sy;
  2253. up[ 1 ] = m[ 9 ]; // cr*sp*sy+-sr*cy;
  2254. up[ 2 ] = m[ 10 ]; // cr*cp;
  2255. }
  2256. }
  2257. void MatrixToVectorsFRU( const matrix_t m, vec3_t forward, vec3_t right, vec3_t up )
  2258. {
  2259. if ( forward )
  2260. {
  2261. forward[ 0 ] = m[ 0 ];
  2262. forward[ 1 ] = m[ 1 ];
  2263. forward[ 2 ] = m[ 2 ];
  2264. }
  2265. if ( right )
  2266. {
  2267. right[ 0 ] = -m[ 4 ];
  2268. right[ 1 ] = -m[ 5 ];
  2269. right[ 2 ] = -m[ 6 ];
  2270. }
  2271. if ( up )
  2272. {
  2273. up[ 0 ] = m[ 8 ];
  2274. up[ 1 ] = m[ 9 ];
  2275. up[ 2 ] = m[ 10 ];
  2276. }
  2277. }
  2278. void MatrixSetupTransformFromVectorsFLU( matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up, const vec3_t origin )
  2279. {
  2280. m[ 0 ] = forward[ 0 ];
  2281. m[ 4 ] = left[ 0 ];
  2282. m[ 8 ] = up[ 0 ];
  2283. m[ 12 ] = origin[ 0 ];
  2284. m[ 1 ] = forward[ 1 ];
  2285. m[ 5 ] = left[ 1 ];
  2286. m[ 9 ] = up[ 1 ];
  2287. m[ 13 ] = origin[ 1 ];
  2288. m[ 2 ] = forward[ 2 ];
  2289. m[ 6 ] = left[ 2 ];
  2290. m[ 10 ] = up[ 2 ];
  2291. m[ 14 ] = origin[ 2 ];
  2292. m[ 3 ] = 0;
  2293. m[ 7 ] = 0;
  2294. m[ 11 ] = 0;
  2295. m[ 15 ] = 1;
  2296. }
  2297. void MatrixSetupTransformFromVectorsFRU( matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up, const vec3_t origin )
  2298. {
  2299. m[ 0 ] = forward[ 0 ];
  2300. m[ 4 ] = -right[ 0 ];
  2301. m[ 8 ] = up[ 0 ];
  2302. m[ 12 ] = origin[ 0 ];
  2303. m[ 1 ] = forward[ 1 ];
  2304. m[ 5 ] = -right[ 1 ];
  2305. m[ 9 ] = up[ 1 ];
  2306. m[ 13 ] = origin[ 1 ];
  2307. m[ 2 ] = forward[ 2 ];
  2308. m[ 6 ] = -right[ 2 ];
  2309. m[ 10 ] = up[ 2 ];
  2310. m[ 14 ] = origin[ 2 ];
  2311. m[ 3 ] = 0;
  2312. m[ 7 ] = 0;
  2313. m[ 11 ] = 0;
  2314. m[ 15 ] = 1;
  2315. }
  2316. void MatrixSetupTransformFromRotation( matrix_t m, const matrix_t rot, const vec3_t origin )
  2317. {
  2318. m[ 0 ] = rot[ 0 ];
  2319. m[ 4 ] = rot[ 4 ];
  2320. m[ 8 ] = rot[ 8 ];
  2321. m[ 12 ] = origin[ 0 ];
  2322. m[ 1 ] = rot[ 1 ];
  2323. m[ 5 ] = rot[ 5 ];
  2324. m[ 9 ] = rot[ 9 ];
  2325. m[ 13 ] = origin[ 1 ];
  2326. m[ 2 ] = rot[ 2 ];
  2327. m[ 6 ] = rot[ 6 ];
  2328. m[ 10 ] = rot[ 10 ];
  2329. m[ 14 ] = origin[ 2 ];
  2330. m[ 3 ] = 0;
  2331. m[ 7 ] = 0;
  2332. m[ 11 ] = 0;
  2333. m[ 15 ] = 1;
  2334. }
  2335. void MatrixSetupTransformFromQuat( matrix_t m, const quat_t quat, const vec3_t origin )
  2336. {
  2337. matrix_t rot;
  2338. MatrixFromQuat( rot, quat );
  2339. m[ 0 ] = rot[ 0 ];
  2340. m[ 4 ] = rot[ 4 ];
  2341. m[ 8 ] = rot[ 8 ];
  2342. m[ 12 ] = origin[ 0 ];
  2343. m[ 1 ] = rot[ 1 ];
  2344. m[ 5 ] = rot[ 5 ];
  2345. m[ 9 ] = rot[ 9 ];
  2346. m[ 13 ] = origin[ 1 ];
  2347. m[ 2 ] = rot[ 2 ];
  2348. m[ 6 ] = rot[ 6 ];
  2349. m[ 10 ] = rot[ 10 ];
  2350. m[ 14 ] = origin[ 2 ];
  2351. m[ 3 ] = 0;
  2352. m[ 7 ] = 0;
  2353. m[ 11 ] = 0;
  2354. m[ 15 ] = 1;
  2355. }
  2356. void MatrixAffineInverse( const matrix_t in, matrix_t out )
  2357. {
  2358. #if 0
  2359. MatrixCopy( in, out );
  2360. MatrixInverse( out );
  2361. #else
  2362. // Tr3B - cleaned up
  2363. out[ 0 ] = in[ 0 ];
  2364. out[ 4 ] = in[ 1 ];
  2365. out[ 8 ] = in[ 2 ];
  2366. out[ 1 ] = in[ 4 ];
  2367. out[ 5 ] = in[ 5 ];
  2368. out[ 9 ] = in[ 6 ];
  2369. out[ 2 ] = in[ 8 ];
  2370. out[ 6 ] = in[ 9 ];
  2371. out[ 10 ] = in[ 10 ];
  2372. out[ 3 ] = 0;
  2373. out[ 7 ] = 0;
  2374. out[ 11 ] = 0;
  2375. out[ 15 ] = 1;
  2376. out[ 12 ] = - ( in[ 12 ] * out[ 0 ] + in[ 13 ] * out[ 4 ] + in[ 14 ] * out[ 8 ] );
  2377. out[ 13 ] = - ( in[ 12 ] * out[ 1 ] + in[ 13 ] * out[ 5 ] + in[ 14 ] * out[ 9 ] );
  2378. out[ 14 ] = - ( in[ 12 ] * out[ 2 ] + in[ 13 ] * out[ 6 ] + in[ 14 ] * out[ 10 ] );
  2379. #endif
  2380. }
  2381. void MatrixTransformNormal( const matrix_t m, const vec3_t in, vec3_t out )
  2382. {
  2383. out[ 0 ] = m[ 0 ] * in[ 0 ] + m[ 4 ] * in[ 1 ] + m[ 8 ] * in[ 2 ];
  2384. out[ 1 ] = m[ 1 ] * in[ 0 ] + m[ 5 ] * in[ 1 ] + m[ 9 ] * in[ 2 ];
  2385. out[ 2 ] = m[ 2 ] * in[ 0 ] + m[ 6 ] * in[ 1 ] + m[ 10 ] * in[ 2 ];
  2386. }
  2387. void MatrixTransformNormal2( const matrix_t m, vec3_t inout )
  2388. {
  2389. vec3_t tmp;
  2390. tmp[ 0 ] = m[ 0 ] * inout[ 0 ] + m[ 4 ] * inout[ 1 ] + m[ 8 ] * inout[ 2 ];
  2391. tmp[ 1 ] = m[ 1 ] * inout[ 0 ] + m[ 5 ] * inout[ 1 ] + m[ 9 ] * inout[ 2 ];
  2392. tmp[ 2 ] = m[ 2 ] * inout[ 0 ] + m[ 6 ] * inout[ 1 ] + m[ 10 ] * inout[ 2 ];
  2393. VectorCopy( tmp, inout );
  2394. }
  2395. void MatrixTransformPoint( const matrix_t m, const vec3_t in, vec3_t out )
  2396. {
  2397. out[ 0 ] = m[ 0 ] * in[ 0 ] + m[ 4 ] * in[ 1 ] + m[ 8 ] * in[ 2 ] + m[ 12 ];
  2398. out[ 1 ] = m[ 1 ] * in[ 0 ] + m[ 5 ] * in[ 1 ] + m[ 9 ] * in[ 2 ] + m[ 13 ];
  2399. out[ 2 ] = m[ 2 ] * in[ 0 ] + m[ 6 ] * in[ 1 ] + m[ 10 ] * in[ 2 ] + m[ 14 ];
  2400. }
  2401. void MatrixTransformPoint2( const matrix_t m, vec3_t inout )
  2402. {
  2403. vec3_t tmp;
  2404. tmp[ 0 ] = m[ 0 ] * inout[ 0 ] + m[ 4 ] * inout[ 1 ] + m[ 8 ] * inout[ 2 ] + m[ 12 ];
  2405. tmp[ 1 ] = m[ 1 ] * inout[ 0 ] + m[ 5 ] * inout[ 1 ] + m[ 9 ] * inout[ 2 ] + m[ 13 ];
  2406. tmp[ 2 ] = m[ 2 ] * inout[ 0 ] + m[ 6 ] * inout[ 1 ] + m[ 10 ] * inout[ 2 ] + m[ 14 ];
  2407. VectorCopy( tmp, inout );
  2408. }
  2409. void MatrixTransform4( const matrix_t m, const vec4_t in, vec4_t out )
  2410. {
  2411. out[ 0 ] = m[ 0 ] * in[ 0 ] + m[ 4 ] * in[ 1 ] + m[ 8 ] * in[ 2 ] + m[ 12 ] * in[ 3 ];
  2412. out[ 1 ] = m[ 1 ] * in[ 0 ] + m[ 5 ] * in[ 1 ] + m[ 9 ] * in[ 2 ] + m[ 13 ] * in[ 3 ];
  2413. out[ 2 ] = m[ 2 ] * in[ 0 ] + m[ 6 ] * in[ 1 ] + m[ 10 ] * in[ 2 ] + m[ 14 ] * in[ 3 ];
  2414. out[ 3 ] = m[ 3 ] * in[ 0 ] + m[ 7 ] * in[ 1 ] + m[ 11 ] * in[ 2 ] + m[ 15 ] * in[ 3 ];
  2415. }
  2416. void MatrixTransformPlane( const matrix_t m, const vec4_t in, vec4_t out )
  2417. {
  2418. vec3_t translation;
  2419. vec3_t planePos;
  2420. // rotate the plane normal
  2421. MatrixTransformNormal( m, in, out );
  2422. // add new position to current plane position
  2423. VectorSet( translation, m[ 12 ], m[ 13 ], m[ 14 ] );
  2424. VectorMA( translation, in[ 3 ], out, planePos );
  2425. out[ 3 ] = DotProduct( out, planePos );
  2426. }
  2427. void MatrixTransformPlane2( const matrix_t m, vec4_t inout )
  2428. {
  2429. vec4_t tmp;
  2430. MatrixTransformPlane( m, inout, tmp );
  2431. Vector4Copy( tmp, inout );
  2432. }
  2433. /*
  2434. * replacement for glFrustum
  2435. * see glspec30.pdf chapter 2.12 Coordinate Transformations
  2436. */
  2437. void MatrixPerspectiveProjection( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2438. {
  2439. m[ 0 ] = ( 2 * near ) / ( right - left );
  2440. m[ 4 ] = 0;
  2441. m[ 8 ] = ( right + left ) / ( right - left );
  2442. m[ 12 ] = 0;
  2443. m[ 1 ] = 0;
  2444. m[ 5 ] = ( 2 * near ) / ( top - bottom );
  2445. m[ 9 ] = ( top + bottom ) / ( top - bottom );
  2446. m[ 13 ] = 0;
  2447. m[ 2 ] = 0;
  2448. m[ 6 ] = 0;
  2449. m[ 10 ] = - ( far + near ) / ( far - near );
  2450. m[ 14 ] = - ( 2 * far * near ) / ( far - near );
  2451. m[ 3 ] = 0;
  2452. m[ 7 ] = 0;
  2453. m[ 11 ] = -1;
  2454. m[ 15 ] = 0;
  2455. }
  2456. /*
  2457. * same as D3DXMatrixPerspectiveOffCenterLH
  2458. *
  2459. * http://msdn.microsoft.com/en-us/library/bb205353(VS.85).aspx
  2460. */
  2461. void MatrixPerspectiveProjectionLH( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2462. {
  2463. m[ 0 ] = ( 2 * near ) / ( right - left );
  2464. m[ 4 ] = 0;
  2465. m[ 8 ] = ( left + right ) / ( left - right );
  2466. m[ 12 ] = 0;
  2467. m[ 1 ] = 0;
  2468. m[ 5 ] = ( 2 * near ) / ( top - bottom );
  2469. m[ 9 ] = ( top + bottom ) / ( bottom - top );
  2470. m[ 13 ] = 0;
  2471. m[ 2 ] = 0;
  2472. m[ 6 ] = 0;
  2473. m[ 10 ] = far / ( far - near );
  2474. m[ 14 ] = ( near * far ) / ( near - far );
  2475. m[ 3 ] = 0;
  2476. m[ 7 ] = 0;
  2477. m[ 11 ] = 1;
  2478. m[ 15 ] = 0;
  2479. }
  2480. /*
  2481. * same as D3DXMatrixPerspectiveOffCenterRH
  2482. *
  2483. * http://msdn.microsoft.com/en-us/library/bb205354(VS.85).aspx
  2484. */
  2485. void MatrixPerspectiveProjectionRH( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2486. {
  2487. m[ 0 ] = ( 2 * near ) / ( right - left );
  2488. m[ 4 ] = 0;
  2489. m[ 8 ] = ( left + right ) / ( right - left );
  2490. m[ 12 ] = 0;
  2491. m[ 1 ] = 0;
  2492. m[ 5 ] = ( 2 * near ) / ( top - bottom );
  2493. m[ 9 ] = ( top + bottom ) / ( top - bottom );
  2494. m[ 13 ] = 0;
  2495. m[ 2 ] = 0;
  2496. m[ 6 ] = 0;
  2497. m[ 10 ] = far / ( near - far );
  2498. m[ 14 ] = ( near * far ) / ( near - far );
  2499. m[ 3 ] = 0;
  2500. m[ 7 ] = 0;
  2501. m[ 11 ] = -1;
  2502. m[ 15 ] = 0;
  2503. }
  2504. /*
  2505. * same as D3DXMatrixPerspectiveFovLH
  2506. *
  2507. * http://msdn.microsoft.com/en-us/library/bb205350(VS.85).aspx
  2508. */
  2509. void MatrixPerspectiveProjectionFovYAspectLH( matrix_t m, vec_t fov, vec_t aspect, vec_t near, vec_t far )
  2510. {
  2511. vec_t width, height;
  2512. width = tanf( DEG2RAD( fov * 0.5f ) );
  2513. height = width / aspect;
  2514. m[ 0 ] = 1 / width;
  2515. m[ 4 ] = 0;
  2516. m[ 8 ] = 0;
  2517. m[ 12 ] = 0;
  2518. m[ 1 ] = 0;
  2519. m[ 5 ] = 1 / height;
  2520. m[ 9 ] = 0;
  2521. m[ 13 ] = 0;
  2522. m[ 2 ] = 0;
  2523. m[ 6 ] = 0;
  2524. m[ 10 ] = far / ( far - near );
  2525. m[ 14 ] = - ( near * far ) / ( far - near );
  2526. m[ 3 ] = 0;
  2527. m[ 7 ] = 0;
  2528. m[ 11 ] = 1;
  2529. m[ 15 ] = 0;
  2530. }
  2531. void MatrixPerspectiveProjectionFovXYLH( matrix_t m, vec_t fovX, vec_t fovY, vec_t near, vec_t far )
  2532. {
  2533. vec_t width, height;
  2534. width = tanf( DEG2RAD( fovX * 0.5f ) );
  2535. height = tanf( DEG2RAD( fovY * 0.5f ) );
  2536. m[ 0 ] = 1 / width;
  2537. m[ 4 ] = 0;
  2538. m[ 8 ] = 0;
  2539. m[ 12 ] = 0;
  2540. m[ 1 ] = 0;
  2541. m[ 5 ] = 1 / height;
  2542. m[ 9 ] = 0;
  2543. m[ 13 ] = 0;
  2544. m[ 2 ] = 0;
  2545. m[ 6 ] = 0;
  2546. m[ 10 ] = far / ( far - near );
  2547. m[ 14 ] = - ( near * far ) / ( far - near );
  2548. m[ 3 ] = 0;
  2549. m[ 7 ] = 0;
  2550. m[ 11 ] = 1;
  2551. m[ 15 ] = 0;
  2552. }
  2553. void MatrixPerspectiveProjectionFovXYRH( matrix_t m, vec_t fovX, vec_t fovY, vec_t near, vec_t far )
  2554. {
  2555. vec_t width, height;
  2556. width = tanf( DEG2RAD( fovX * 0.5f ) );
  2557. height = tanf( DEG2RAD( fovY * 0.5f ) );
  2558. m[ 0 ] = 1 / width;
  2559. m[ 4 ] = 0;
  2560. m[ 8 ] = 0;
  2561. m[ 12 ] = 0;
  2562. m[ 1 ] = 0;
  2563. m[ 5 ] = 1 / height;
  2564. m[ 9 ] = 0;
  2565. m[ 13 ] = 0;
  2566. m[ 2 ] = 0;
  2567. m[ 6 ] = 0;
  2568. m[ 10 ] = far / ( near - far );
  2569. m[ 14 ] = ( near * far ) / ( near - far );
  2570. m[ 3 ] = 0;
  2571. m[ 7 ] = 0;
  2572. m[ 11 ] = -1;
  2573. m[ 15 ] = 0;
  2574. }
  2575. // Tr3B: far plane at infinity, see RobustShadowVolumes.pdf by Nvidia
  2576. void MatrixPerspectiveProjectionFovXYInfiniteRH( matrix_t m, vec_t fovX, vec_t fovY, vec_t near )
  2577. {
  2578. vec_t width, height;
  2579. width = tanf( DEG2RAD( fovX * 0.5f ) );
  2580. height = tanf( DEG2RAD( fovY * 0.5f ) );
  2581. m[ 0 ] = 1 / width;
  2582. m[ 4 ] = 0;
  2583. m[ 8 ] = 0;
  2584. m[ 12 ] = 0;
  2585. m[ 1 ] = 0;
  2586. m[ 5 ] = 1 / height;
  2587. m[ 9 ] = 0;
  2588. m[ 13 ] = 0;
  2589. m[ 2 ] = 0;
  2590. m[ 6 ] = 0;
  2591. m[ 10 ] = -1;
  2592. m[ 14 ] = -2 * near;
  2593. m[ 3 ] = 0;
  2594. m[ 7 ] = 0;
  2595. m[ 11 ] = -1;
  2596. m[ 15 ] = 0;
  2597. }
  2598. /*
  2599. * replacement for glOrtho
  2600. * see glspec30.pdf chapter 2.12 Coordinate Transformations
  2601. */
  2602. void MatrixOrthogonalProjection( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2603. {
  2604. m[ 0 ] = 2 / ( right - left );
  2605. m[ 4 ] = 0;
  2606. m[ 8 ] = 0;
  2607. m[ 12 ] = - ( right + left ) / ( right - left );
  2608. m[ 1 ] = 0;
  2609. m[ 5 ] = 2 / ( top - bottom );
  2610. m[ 9 ] = 0;
  2611. m[ 13 ] = - ( top + bottom ) / ( top - bottom );
  2612. m[ 2 ] = 0;
  2613. m[ 6 ] = 0;
  2614. m[ 10 ] = -2 / ( far - near );
  2615. m[ 14 ] = - ( far + near ) / ( far - near );
  2616. m[ 3 ] = 0;
  2617. m[ 7 ] = 0;
  2618. m[ 11 ] = 0;
  2619. m[ 15 ] = 1;
  2620. }
  2621. /*
  2622. * same as D3DXMatrixOrthoOffCenterLH
  2623. *
  2624. * http://msdn.microsoft.com/en-us/library/bb205347(VS.85).aspx
  2625. */
  2626. void MatrixOrthogonalProjectionLH( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2627. {
  2628. m[ 0 ] = 2 / ( right - left );
  2629. m[ 4 ] = 0;
  2630. m[ 8 ] = 0;
  2631. m[ 12 ] = ( left + right ) / ( left - right );
  2632. m[ 1 ] = 0;
  2633. m[ 5 ] = 2 / ( top - bottom );
  2634. m[ 9 ] = 0;
  2635. m[ 13 ] = ( top + bottom ) / ( bottom - top );
  2636. m[ 2 ] = 0;
  2637. m[ 6 ] = 0;
  2638. m[ 10 ] = 1 / ( far - near );
  2639. m[ 14 ] = near / ( near - far );
  2640. m[ 3 ] = 0;
  2641. m[ 7 ] = 0;
  2642. m[ 11 ] = 0;
  2643. m[ 15 ] = 1;
  2644. }
  2645. /*
  2646. * same as D3DXMatrixOrthoOffCenterRH
  2647. *
  2648. * http://msdn.microsoft.com/en-us/library/bb205348(VS.85).aspx
  2649. */
  2650. void MatrixOrthogonalProjectionRH( matrix_t m, vec_t left, vec_t right, vec_t bottom, vec_t top, vec_t near, vec_t far )
  2651. {
  2652. m[ 0 ] = 2 / ( right - left );
  2653. m[ 4 ] = 0;
  2654. m[ 8 ] = 0;
  2655. m[ 12 ] = ( left + right ) / ( left - right );
  2656. m[ 1 ] = 0;
  2657. m[ 5 ] = 2 / ( top - bottom );
  2658. m[ 9 ] = 0;
  2659. m[ 13 ] = ( top + bottom ) / ( bottom - top );
  2660. m[ 2 ] = 0;
  2661. m[ 6 ] = 0;
  2662. m[ 10 ] = 1 / ( near - far );
  2663. m[ 14 ] = near / ( near - far );
  2664. m[ 3 ] = 0;
  2665. m[ 7 ] = 0;
  2666. m[ 11 ] = 0;
  2667. m[ 15 ] = 1;
  2668. }
  2669. /*
  2670. * same as D3DXMatrixReflect
  2671. *
  2672. * http://msdn.microsoft.com/en-us/library/bb205356%28v=VS.85%29.aspx
  2673. */
  2674. void MatrixPlaneReflection( matrix_t m, const vec4_t plane )
  2675. {
  2676. vec4_t P;
  2677. Vector4Copy( plane, P );
  2678. PlaneNormalize( P );
  2679. /*
  2680. * -2 * P.a * P.a + 1 -2 * P.b * P.a -2 * P.c * P.a 0
  2681. * -2 * P.a * P.b -2 * P.b * P.b + 1 -2 * P.c * P.b 0
  2682. * -2 * P.a * P.c -2 * P.b * P.c -2 * P.c * P.c + 1 0
  2683. * -2 * P.a * P.d -2 * P.b * P.d -2 * P.c * P.d 1
  2684. */
  2685. // Quake uses a different plane equation
  2686. m[ 0 ] = -2 * P[ 0 ] * P[ 0 ] + 1;
  2687. m[ 4 ] = -2 * P[ 0 ] * P[ 1 ];
  2688. m[ 8 ] = -2 * P[ 0 ] * P[ 2 ];
  2689. m[ 12 ] = 2 * P[ 0 ] * P[ 3 ];
  2690. m[ 1 ] = -2 * P[ 1 ] * P[ 0 ];
  2691. m[ 5 ] = -2 * P[ 1 ] * P[ 1 ] + 1;
  2692. m[ 9 ] = -2 * P[ 1 ] * P[ 2 ];
  2693. m[ 13 ] = 2 * P[ 1 ] * P[ 3 ];
  2694. m[ 2 ] = -2 * P[ 2 ] * P[ 0 ];
  2695. m[ 6 ] = -2 * P[ 2 ] * P[ 1 ];
  2696. m[ 10 ] = -2 * P[ 2 ] * P[ 2 ] + 1;
  2697. m[ 14 ] = 2 * P[ 2 ] * P[ 3 ];
  2698. m[ 3 ] = 0;
  2699. m[ 7 ] = 0;
  2700. m[ 11 ] = 0;
  2701. m[ 15 ] = 1;
  2702. #if 0
  2703. matrix_t m2;
  2704. MatrixCopy( m, m2 );
  2705. MatrixTranspose( m2, m );
  2706. #endif
  2707. }
  2708. void MatrixLookAtLH( matrix_t m, const vec3_t eye, const vec3_t dir, const vec3_t up )
  2709. {
  2710. vec3_t dirN;
  2711. vec3_t upN;
  2712. vec3_t sideN;
  2713. #if 1
  2714. CrossProduct( up, dir, sideN );
  2715. VectorNormalize( sideN );
  2716. CrossProduct( dir, sideN, upN );
  2717. VectorNormalize( upN );
  2718. #else
  2719. CrossProduct( dir, up, sideN );
  2720. VectorNormalize( sideN );
  2721. CrossProduct( sideN, dir, upN );
  2722. VectorNormalize( upN );
  2723. #endif
  2724. VectorNormalize2( dir, dirN );
  2725. m[ 0 ] = sideN[ 0 ];
  2726. m[ 4 ] = sideN[ 1 ];
  2727. m[ 8 ] = sideN[ 2 ];
  2728. m[ 12 ] = -DotProduct( sideN, eye );
  2729. m[ 1 ] = upN[ 0 ];
  2730. m[ 5 ] = upN[ 1 ];
  2731. m[ 9 ] = upN[ 2 ];
  2732. m[ 13 ] = -DotProduct( upN, eye );
  2733. m[ 2 ] = dirN[ 0 ];
  2734. m[ 6 ] = dirN[ 1 ];
  2735. m[ 10 ] = dirN[ 2 ];
  2736. m[ 14 ] = -DotProduct( dirN, eye );
  2737. m[ 3 ] = 0;
  2738. m[ 7 ] = 0;
  2739. m[ 11 ] = 0;
  2740. m[ 15 ] = 1;
  2741. }
  2742. void MatrixLookAtRH( matrix_t m, const vec3_t eye, const vec3_t dir, const vec3_t up )
  2743. {
  2744. vec3_t dirN;
  2745. vec3_t upN;
  2746. vec3_t sideN;
  2747. CrossProduct( dir, up, sideN );
  2748. VectorNormalize( sideN );
  2749. CrossProduct( sideN, dir, upN );
  2750. VectorNormalize( upN );
  2751. VectorNormalize2( dir, dirN );
  2752. m[ 0 ] = sideN[ 0 ];
  2753. m[ 4 ] = sideN[ 1 ];
  2754. m[ 8 ] = sideN[ 2 ];
  2755. m[ 12 ] = -DotProduct( sideN, eye );
  2756. m[ 1 ] = upN[ 0 ];
  2757. m[ 5 ] = upN[ 1 ];
  2758. m[ 9 ] = upN[ 2 ];
  2759. m[ 13 ] = -DotProduct( upN, eye );
  2760. m[ 2 ] = -dirN[ 0 ];
  2761. m[ 6 ] = -dirN[ 1 ];
  2762. m[ 10 ] = -dirN[ 2 ];
  2763. m[ 14 ] = DotProduct( dirN, eye );
  2764. m[ 3 ] = 0;
  2765. m[ 7 ] = 0;
  2766. m[ 11 ] = 0;
  2767. m[ 15 ] = 1;
  2768. }
  2769. void MatrixScaleTranslateToUnitCube( matrix_t m, const vec3_t mins, const vec3_t maxs )
  2770. {
  2771. m[ 0 ] = 2 / ( maxs[ 0 ] - mins[ 0 ] );
  2772. m[ 4 ] = 0;
  2773. m[ 8 ] = 0;
  2774. m[ 12 ] = - ( maxs[ 0 ] + mins[ 0 ] ) / ( maxs[ 0 ] - mins[ 0 ] );
  2775. m[ 1 ] = 0;
  2776. m[ 5 ] = 2 / ( maxs[ 1 ] - mins[ 1 ] );
  2777. m[ 9 ] = 0;
  2778. m[ 13 ] = - ( maxs[ 1 ] + mins[ 1 ] ) / ( maxs[ 1 ] - mins[ 1 ] );
  2779. m[ 2 ] = 0;
  2780. m[ 6 ] = 0;
  2781. m[ 10 ] = 2 / ( maxs[ 2 ] - mins[ 2 ] );
  2782. m[ 14 ] = - ( maxs[ 2 ] + mins[ 2 ] ) / ( maxs[ 2 ] - mins[ 2 ] );
  2783. m[ 3 ] = 0;
  2784. m[ 7 ] = 0;
  2785. m[ 11 ] = 0;
  2786. m[ 15 ] = 1;
  2787. }
  2788. void MatrixCrop( matrix_t m, const vec3_t mins, const vec3_t maxs )
  2789. {
  2790. float scaleX, scaleY, scaleZ;
  2791. float offsetX, offsetY, offsetZ;
  2792. scaleX = 2.0f / ( maxs[ 0 ] - mins[ 0 ] );
  2793. scaleY = 2.0f / ( maxs[ 1 ] - mins[ 1 ] );
  2794. offsetX = -0.5f * ( maxs[ 0 ] + mins[ 0 ] ) * scaleX;
  2795. offsetY = -0.5f * ( maxs[ 1 ] + mins[ 1 ] ) * scaleY;
  2796. scaleZ = 1.0f / ( maxs[ 2 ] - mins[ 2 ] );
  2797. offsetZ = -mins[ 2 ] * scaleZ;
  2798. m[ 0 ] = scaleX;
  2799. m[ 4 ] = 0;
  2800. m[ 8 ] = 0;
  2801. m[ 12 ] = offsetX;
  2802. m[ 1 ] = 0;
  2803. m[ 5 ] = scaleY;
  2804. m[ 9 ] = 0;
  2805. m[ 13 ] = offsetY;
  2806. m[ 2 ] = 0;
  2807. m[ 6 ] = 0;
  2808. m[ 10 ] = scaleZ;
  2809. m[ 14 ] = offsetZ;
  2810. m[ 3 ] = 0;
  2811. m[ 7 ] = 0;
  2812. m[ 11 ] = 0;
  2813. m[ 15 ] = 1;
  2814. }
  2815. //=============================================
  2816. // RB: XreaL quaternion math functions
  2817. // *INDENT-ON*
  2818. vec_t QuatNormalize( quat_t q )
  2819. {
  2820. float length, ilength;
  2821. length = DotProduct4( q, q );
  2822. if ( length )
  2823. {
  2824. ilength = Q_rsqrt( length );
  2825. length *= ilength;
  2826. q[ 0 ] *= ilength;
  2827. q[ 1 ] *= ilength;
  2828. q[ 2 ] *= ilength;
  2829. q[ 3 ] *= ilength;
  2830. }
  2831. return length;
  2832. }
  2833. void QuatFromAngles( quat_t q, vec_t pitch, vec_t yaw, vec_t roll )
  2834. {
  2835. #if 1
  2836. matrix_t tmp;
  2837. MatrixFromAngles( tmp, pitch, yaw, roll );
  2838. QuatFromMatrix( q, tmp );
  2839. #else
  2840. static float sr, sp, sy, cr, cp, cy;
  2841. // static to help MS compiler fp bugs
  2842. sp = sin( DEG2RAD( pitch ) );
  2843. cp = cos( DEG2RAD( pitch ) );
  2844. sy = sin( DEG2RAD( yaw ) );
  2845. cy = cos( DEG2RAD( yaw ) );
  2846. sr = sin( DEG2RAD( roll ) );
  2847. cr = cos( DEG2RAD( roll ) );
  2848. q[ 0 ] = sr * cp * cy - cr * sp * sy; // x
  2849. q[ 1 ] = cr * sp * cy + sr * cp * sy; // y
  2850. q[ 2 ] = cr * cp * sy - sr * sp * cy; // z
  2851. q[ 3 ] = cr * cp * cy + sr * sp * sy; // w
  2852. #endif
  2853. }
  2854. void QuatFromMatrix( quat_t q, const matrix_t m )
  2855. {
  2856. #if 1
  2857. /*
  2858. * From Quaternion to Matrix and Back
  2859. * February 27th 2005
  2860. * J.M.P. van Waveren
  2861. *
  2862. * http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
  2863. */
  2864. float t, s;
  2865. if ( m[ 0 ] + m[ 5 ] + m[ 10 ] > 0.0f )
  2866. {
  2867. t = m[ 0 ] + m[ 5 ] + m[ 10 ] + 1.0f;
  2868. s = ( 1.0f / sqrtf( t ) ) * 0.5f;
  2869. q[ 3 ] = s * t;
  2870. q[ 2 ] = ( m[ 1 ] - m[ 4 ] ) * s;
  2871. q[ 1 ] = ( m[ 8 ] - m[ 2 ] ) * s;
  2872. q[ 0 ] = ( m[ 6 ] - m[ 9 ] ) * s;
  2873. }
  2874. else if ( m[ 0 ] > m[ 5 ] && m[ 0 ] > m[ 10 ] )
  2875. {
  2876. t = m[ 0 ] - m[ 5 ] - m[ 10 ] + 1.0f;
  2877. s = ( 1.0f / sqrtf( t ) ) * 0.5f;
  2878. q[ 0 ] = s * t;
  2879. q[ 1 ] = ( m[ 1 ] + m[ 4 ] ) * s;
  2880. q[ 2 ] = ( m[ 8 ] + m[ 2 ] ) * s;
  2881. q[ 3 ] = ( m[ 6 ] - m[ 9 ] ) * s;
  2882. }
  2883. else if ( m[ 5 ] > m[ 10 ] )
  2884. {
  2885. t = -m[ 0 ] + m[ 5 ] - m[ 10 ] + 1.0f;
  2886. s = ( 1.0f / sqrtf( t ) ) * 0.5f;
  2887. q[ 1 ] = s * t;
  2888. q[ 0 ] = ( m[ 1 ] + m[ 4 ] ) * s;
  2889. q[ 3 ] = ( m[ 8 ] - m[ 2 ] ) * s;
  2890. q[ 2 ] = ( m[ 6 ] + m[ 9 ] ) * s;
  2891. }
  2892. else
  2893. {
  2894. t = -m[ 0 ] - m[ 5 ] + m[ 10 ] + 1.0f;
  2895. s = ( 1.0f / sqrtf( t ) ) * 0.5f;
  2896. q[ 2 ] = s * t;
  2897. q[ 3 ] = ( m[ 1 ] - m[ 4 ] ) * s;
  2898. q[ 0 ] = ( m[ 8 ] + m[ 2 ] ) * s;
  2899. q[ 1 ] = ( m[ 6 ] + m[ 9 ] ) * s;
  2900. }
  2901. #else
  2902. float trace;
  2903. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
  2904. trace = 1.0f + m[ 0 ] + m[ 5 ] + m[ 10 ];
  2905. if ( trace > 0.0f )
  2906. {
  2907. vec_t s = 0.5f / sqrt( trace );
  2908. q[ 0 ] = ( m[ 6 ] - m[ 9 ] ) * s;
  2909. q[ 1 ] = ( m[ 8 ] - m[ 2 ] ) * s;
  2910. q[ 2 ] = ( m[ 1 ] - m[ 4 ] ) * s;
  2911. q[ 3 ] = 0.25f / s;
  2912. }
  2913. else
  2914. {
  2915. if ( m[ 0 ] > m[ 5 ] && m[ 0 ] > m[ 10 ] )
  2916. {
  2917. // column 0
  2918. float s = sqrt( 1.0f + m[ 0 ] - m[ 5 ] - m[ 10 ] ) * 2.0f;
  2919. q[ 0 ] = 0.25f * s;
  2920. q[ 1 ] = ( m[ 4 ] + m[ 1 ] ) / s;
  2921. q[ 2 ] = ( m[ 8 ] + m[ 2 ] ) / s;
  2922. q[ 3 ] = ( m[ 9 ] - m[ 6 ] ) / s;
  2923. }
  2924. else if ( m[ 5 ] > m[ 10 ] )
  2925. {
  2926. // column 1
  2927. float s = sqrt( 1.0f + m[ 5 ] - m[ 0 ] - m[ 10 ] ) * 2.0f;
  2928. q[ 0 ] = ( m[ 4 ] + m[ 1 ] ) / s;
  2929. q[ 1 ] = 0.25f * s;
  2930. q[ 2 ] = ( m[ 9 ] + m[ 6 ] ) / s;
  2931. q[ 3 ] = ( m[ 8 ] - m[ 2 ] ) / s;
  2932. }
  2933. else
  2934. {
  2935. // column 2
  2936. float s = sqrt( 1.0f + m[ 10 ] - m[ 0 ] - m[ 5 ] ) * 2.0f;
  2937. q[ 0 ] = ( m[ 8 ] + m[ 2 ] ) / s;
  2938. q[ 1 ] = ( m[ 9 ] + m[ 6 ] ) / s;
  2939. q[ 2 ] = 0.25f * s;
  2940. q[ 3 ] = ( m[ 4 ] - m[ 1 ] ) / s;
  2941. }
  2942. }
  2943. QuatNormalize( q );
  2944. #endif
  2945. }
  2946. void QuatToVectorsFLU( const quat_t q, vec3_t forward, vec3_t left, vec3_t up )
  2947. {
  2948. matrix_t tmp;
  2949. MatrixFromQuat( tmp, q );
  2950. MatrixToVectorsFRU( tmp, forward, left, up );
  2951. }
  2952. void QuatToVectorsFRU( const quat_t q, vec3_t forward, vec3_t right, vec3_t up )
  2953. {
  2954. matrix_t tmp;
  2955. MatrixFromQuat( tmp, q );
  2956. MatrixToVectorsFRU( tmp, forward, right, up );
  2957. }
  2958. void QuatToAxis( const quat_t q, vec3_t axis[ 3 ] )
  2959. {
  2960. matrix_t tmp;
  2961. MatrixFromQuat( tmp, q );
  2962. MatrixToVectorsFLU( tmp, axis[ 0 ], axis[ 1 ], axis[ 2 ] );
  2963. }
  2964. void QuatToAngles( const quat_t q, vec3_t angles )
  2965. {
  2966. quat_t q2;
  2967. q2[ 0 ] = q[ 0 ] * q[ 0 ];
  2968. q2[ 1 ] = q[ 1 ] * q[ 1 ];
  2969. q2[ 2 ] = q[ 2 ] * q[ 2 ];
  2970. q2[ 3 ] = q[ 3 ] * q[ 3 ];
  2971. angles[ PITCH ] = RAD2DEG( asin( -2 * ( q[ 2 ] * q[ 0 ] - q[ 3 ] * q[ 1 ] ) ) );
  2972. angles[ YAW ] = RAD2DEG( atan2( 2 * ( q[ 2 ] * q[ 3 ] + q[ 0 ] * q[ 1 ] ), ( q2[ 2 ] - q2[ 3 ] - q2[ 0 ] + q2[ 1 ] ) ) );
  2973. angles[ ROLL ] = RAD2DEG( atan2( 2 * ( q[ 3 ] * q[ 0 ] + q[ 2 ] * q[ 1 ] ), ( -q2[ 2 ] - q2[ 3 ] + q2[ 0 ] + q2[ 1 ] ) ) );
  2974. }
  2975. void QuatMultiply0( quat_t qa, const quat_t qb )
  2976. {
  2977. quat_t tmp;
  2978. QuatCopy( qa, tmp );
  2979. QuatMultiply1( tmp, qb, qa );
  2980. }
  2981. void QuatMultiply1( const quat_t qa, const quat_t qb, quat_t qc )
  2982. {
  2983. /*
  2984. * from matrix and quaternion faq
  2985. * x = w1x2 + x1w2 + y1z2 - z1y2
  2986. * y = w1y2 + y1w2 + z1x2 - x1z2
  2987. * z = w1z2 + z1w2 + x1y2 - y1x2
  2988. *
  2989. * w = w1w2 - x1x2 - y1y2 - z1z2
  2990. */
  2991. qc[ 0 ] = qa[ 3 ] * qb[ 0 ] + qa[ 0 ] * qb[ 3 ] + qa[ 1 ] * qb[ 2 ] - qa[ 2 ] * qb[ 1 ];
  2992. qc[ 1 ] = qa[ 3 ] * qb[ 1 ] + qa[ 1 ] * qb[ 3 ] + qa[ 2 ] * qb[ 0 ] - qa[ 0 ] * qb[ 2 ];
  2993. qc[ 2 ] = qa[ 3 ] * qb[ 2 ] + qa[ 2 ] * qb[ 3 ] + qa[ 0 ] * qb[ 1 ] - qa[ 1 ] * qb[ 0 ];
  2994. qc[ 3 ] = qa[ 3 ] * qb[ 3 ] - qa[ 0 ] * qb[ 0 ] - qa[ 1 ] * qb[ 1 ] - qa[ 2 ] * qb[ 2 ];
  2995. }
  2996. void QuatMultiply2( const quat_t qa, const quat_t qb, quat_t qc )
  2997. {
  2998. qc[ 0 ] = qa[ 3 ] * qb[ 0 ] + qa[ 0 ] * qb[ 3 ] + qa[ 1 ] * qb[ 2 ] + qa[ 2 ] * qb[ 1 ];
  2999. qc[ 1 ] = qa[ 3 ] * qb[ 1 ] - qa[ 1 ] * qb[ 3 ] - qa[ 2 ] * qb[ 0 ] + qa[ 0 ] * qb[ 2 ];
  3000. qc[ 2 ] = qa[ 3 ] * qb[ 2 ] - qa[ 2 ] * qb[ 3 ] - qa[ 0 ] * qb[ 1 ] + qa[ 1 ] * qb[ 0 ];
  3001. qc[ 3 ] = qa[ 3 ] * qb[ 3 ] - qa[ 0 ] * qb[ 0 ] - qa[ 1 ] * qb[ 1 ] + qa[ 2 ] * qb[ 2 ];
  3002. }
  3003. void QuatMultiply3( const quat_t qa, const quat_t qb, quat_t qc )
  3004. {
  3005. qc[ 0 ] = qa[ 3 ] * qb[ 0 ] + qa[ 0 ] * qb[ 3 ] + qa[ 1 ] * qb[ 2 ] + qa[ 2 ] * qb[ 1 ];
  3006. qc[ 1 ] = -qa[ 3 ] * qb[ 1 ] + qa[ 1 ] * qb[ 3 ] - qa[ 2 ] * qb[ 0 ] + qa[ 0 ] * qb[ 2 ];
  3007. qc[ 2 ] = -qa[ 3 ] * qb[ 2 ] + qa[ 2 ] * qb[ 3 ] - qa[ 0 ] * qb[ 1 ] + qa[ 1 ] * qb[ 0 ];
  3008. qc[ 3 ] = -qa[ 3 ] * qb[ 3 ] + qa[ 0 ] * qb[ 0 ] - qa[ 1 ] * qb[ 1 ] + qa[ 2 ] * qb[ 2 ];
  3009. }
  3010. void QuatMultiply4( const quat_t qa, const quat_t qb, quat_t qc )
  3011. {
  3012. qc[ 0 ] = qa[ 3 ] * qb[ 0 ] - qa[ 0 ] * qb[ 3 ] - qa[ 1 ] * qb[ 2 ] - qa[ 2 ] * qb[ 1 ];
  3013. qc[ 1 ] = -qa[ 3 ] * qb[ 1 ] - qa[ 1 ] * qb[ 3 ] + qa[ 2 ] * qb[ 0 ] - qa[ 0 ] * qb[ 2 ];
  3014. qc[ 2 ] = -qa[ 3 ] * qb[ 2 ] - qa[ 2 ] * qb[ 3 ] + qa[ 0 ] * qb[ 1 ] - qa[ 1 ] * qb[ 0 ];
  3015. qc[ 3 ] = -qa[ 3 ] * qb[ 3 ] - qa[ 0 ] * qb[ 0 ] + qa[ 1 ] * qb[ 1 ] - qa[ 2 ] * qb[ 2 ];
  3016. }
  3017. void QuatSlerp( const quat_t from, const quat_t to, float frac, quat_t out )
  3018. {
  3019. #if 0
  3020. quat_t to1;
  3021. float omega, cosom, sinom, scale0, scale1;
  3022. cosom = from[ 0 ] * to[ 0 ] + from[ 1 ] * to[ 1 ] + from[ 2 ] * to[ 2 ] + from[ 3 ] * to[ 3 ];
  3023. if ( cosom < 0.0 )
  3024. {
  3025. cosom = -cosom;
  3026. QuatCopy( to, to1 );
  3027. QuatAntipodal( to1 );
  3028. }
  3029. else
  3030. {
  3031. QuatCopy( to, to1 );
  3032. }
  3033. if ( ( 1.0 - cosom ) > 0 )
  3034. {
  3035. omega = acos( cosom );
  3036. sinom = sin( omega );
  3037. scale0 = sin( ( 1.0 - frac ) * omega ) / sinom;
  3038. scale1 = sin( frac * omega ) / sinom;
  3039. }
  3040. else
  3041. {
  3042. scale0 = 1.0 - frac;
  3043. scale1 = frac;
  3044. }
  3045. out[ 0 ] = scale0 * from[ 0 ] + scale1 * to1[ 0 ];
  3046. out[ 1 ] = scale0 * from[ 1 ] + scale1 * to1[ 1 ];
  3047. out[ 2 ] = scale0 * from[ 2 ] + scale1 * to1[ 2 ];
  3048. out[ 3 ] = scale0 * from[ 3 ] + scale1 * to1[ 3 ];
  3049. #else
  3050. /*
  3051. * Slerping Clock Cycles
  3052. * February 27th 2005
  3053. * J.M.P. van Waveren
  3054. *
  3055. * http://www.intel.com/cd/ids/developer/asmo-na/eng/293747.htm
  3056. */
  3057. float cosom, absCosom, sinom, sinSqr, omega, scale0, scale1;
  3058. if ( frac <= 0.0f )
  3059. {
  3060. QuatCopy( from, out );
  3061. return;
  3062. }
  3063. if ( frac >= 1.0f )
  3064. {
  3065. QuatCopy( to, out );
  3066. return;
  3067. }
  3068. if ( QuatCompare( from, to ) )
  3069. {
  3070. QuatCopy( from, out );
  3071. return;
  3072. }
  3073. cosom = from[ 0 ] * to[ 0 ] + from[ 1 ] * to[ 1 ] + from[ 2 ] * to[ 2 ] + from[ 3 ] * to[ 3 ];
  3074. absCosom = fabs( cosom );
  3075. if ( ( 1.0f - absCosom ) > 1e-6f )
  3076. {
  3077. sinSqr = 1.0f - absCosom * absCosom;
  3078. sinom = 1.0f / sqrt( sinSqr );
  3079. omega = atan2( sinSqr * sinom, absCosom );
  3080. scale0 = sin( ( 1.0f - frac ) * omega ) * sinom;
  3081. scale1 = sin( frac * omega ) * sinom;
  3082. }
  3083. else
  3084. {
  3085. scale0 = 1.0f - frac;
  3086. scale1 = frac;
  3087. }
  3088. scale1 = ( cosom >= 0.0f ) ? scale1 : -scale1;
  3089. out[ 0 ] = scale0 * from[ 0 ] + scale1 * to[ 0 ];
  3090. out[ 1 ] = scale0 * from[ 1 ] + scale1 * to[ 1 ];
  3091. out[ 2 ] = scale0 * from[ 2 ] + scale1 * to[ 2 ];
  3092. out[ 3 ] = scale0 * from[ 3 ] + scale1 * to[ 3 ];
  3093. #endif
  3094. }
  3095. void QuatTransformVector( const quat_t q, const vec3_t in, vec3_t out )
  3096. {
  3097. #if 0
  3098. matrix_t m;
  3099. MatrixFromQuat( m, q );
  3100. MatrixTransformNormal( m, in, out );
  3101. #else
  3102. vec3_t tmp, tmp2;
  3103. CrossProduct( q, in, tmp );
  3104. VectorScale( tmp, 2.0f, tmp );
  3105. CrossProduct( q, tmp, tmp2 );
  3106. VectorMA( in, q[3], tmp, out );
  3107. VectorAdd( out, tmp2, out );
  3108. #endif
  3109. }
  3110. void QuatTransformVectorInverse( const quat_t q, const vec3_t in, vec3_t out )
  3111. {
  3112. vec3_t tmp, tmp2;
  3113. // The inverse rotation is obtained by negating the vector
  3114. // component of q, but that is mathematically the same as
  3115. // swapping the arguments of the cross product.
  3116. CrossProduct( in, q, tmp );
  3117. VectorScale( tmp, 2.0f, tmp );
  3118. CrossProduct( tmp, q, tmp2 );
  3119. VectorMA( in, q[3], tmp, out );
  3120. VectorAdd( out, tmp2, out );
  3121. }
  3122. #if !idx86_sse
  3123. // create an identity transform
  3124. void TransInit( transform_t *t )
  3125. {
  3126. QuatClear( t->rot );
  3127. VectorClear( t->trans );
  3128. t->scale = 1.0f;
  3129. }
  3130. // copy a transform
  3131. void TransCopy( const transform_t *in, transform_t *out )
  3132. {
  3133. Com_Memcpy( out, in, sizeof( transform_t ) );
  3134. }
  3135. // apply a transform to a point
  3136. void TransformPoint( const transform_t *t, const vec3_t in, vec3_t out )
  3137. {
  3138. QuatTransformVector( t->rot, in, out );
  3139. VectorScale( out, t->scale, out );
  3140. VectorAdd( out, t->trans, out );
  3141. }
  3142. // apply the inverse of a transform to a point
  3143. void TransformPointInverse( const transform_t *t, const vec3_t in, vec3_t out )
  3144. {
  3145. VectorSubtract( in, t->trans, out );
  3146. VectorScale( out, 1.0f / t->scale, out );
  3147. QuatTransformVectorInverse( t->rot, out, out );
  3148. }
  3149. // apply a transform to a normal vector (ignore scale and translation)
  3150. void TransformNormalVector( const transform_t *t, const vec3_t in, vec3_t out )
  3151. {
  3152. QuatTransformVector( t->rot, in, out );
  3153. }
  3154. // apply the inverse of a transform to a normal vector (ignore scale
  3155. // and translation)
  3156. void TransformNormalVectorInverse( const transform_t *t, const vec3_t in,
  3157. vec3_t out )
  3158. {
  3159. QuatTransformVectorInverse( t->rot, in, out );
  3160. }
  3161. // initialize a transform with a pure rotation
  3162. void TransInitRotationQuat( const quat_t quat, transform_t *t )
  3163. {
  3164. QuatCopy( quat, t->rot );
  3165. VectorClear( t->trans );
  3166. t->scale = 1.0f;
  3167. }
  3168. void TransInitRotation( const vec3_t axis, float angle, transform_t *t )
  3169. {
  3170. float sa = sin( 0.5f * angle );
  3171. float ca = cos( 0.5f * angle );
  3172. quat_t q;
  3173. VectorScale( axis, sa, q );
  3174. q[3] = ca;
  3175. TransInitRotationQuat( q, t );
  3176. }
  3177. // initialize a transform with a pure translation
  3178. void TransInitTranslation( const vec3_t vec, transform_t *t )
  3179. {
  3180. QuatClear( t->rot );
  3181. VectorCopy( vec, t->trans );
  3182. t->scale = 1.0f;
  3183. }
  3184. // initialize a transform with a pure scale
  3185. void TransInitScale( float factor, transform_t *t )
  3186. {
  3187. QuatClear( t->rot );
  3188. VectorClear( t->trans );
  3189. t->scale = factor;
  3190. }
  3191. // add a rotation to the start of an existing transform
  3192. void TransInsRotationQuat( const quat_t quat, transform_t *t )
  3193. {
  3194. QuatMultiply0( t->rot, quat );
  3195. }
  3196. void TransInsRotation( const vec3_t axis, float angle, transform_t *t )
  3197. {
  3198. float sa = sin( 0.5f * angle );
  3199. float ca = cos( 0.5f * angle );
  3200. quat_t q;
  3201. VectorScale( axis, sa, q );
  3202. q[3] = ca;
  3203. TransInsRotationQuat( q, t );
  3204. }
  3205. // add a rotation to the end of an existing transform
  3206. void TransAddRotationQuat( const quat_t quat, transform_t *t )
  3207. {
  3208. quat_t tmp;
  3209. QuatTransformVector( quat, t->trans, t->trans );
  3210. QuatCopy( quat, tmp );
  3211. QuatMultiply0( tmp, t->rot );
  3212. QuatCopy( tmp, t->rot );
  3213. }
  3214. void TransAddRotation( const vec3_t axis, float angle, transform_t *t )
  3215. {
  3216. float sa = sin( 0.5f * angle );
  3217. float ca = cos( 0.5f * angle );
  3218. quat_t q;
  3219. VectorScale( axis, sa, q );
  3220. q[3] = ca;
  3221. TransAddRotationQuat( q, t );
  3222. }
  3223. // add a scale to the start of an existing transform
  3224. void TransInsScale( float factor, transform_t *t )
  3225. {
  3226. t->scale *= factor;
  3227. }
  3228. // add a scale to the end of an existing transform
  3229. void TransAddScale( float factor, transform_t *t )
  3230. {
  3231. VectorScale( t->trans, factor, t->trans );
  3232. t->scale *= factor;
  3233. }
  3234. // add a translation at the start of an existing transformation
  3235. void TransInsTranslation( const vec3_t vec, transform_t *t )
  3236. {
  3237. vec3_t tmp;
  3238. TransformPoint( t, vec, tmp );
  3239. VectorAdd( t->trans, tmp, t->trans );
  3240. }
  3241. // add a translation at the end of an existing transformation
  3242. void TransAddTranslation( const vec3_t vec, transform_t *t )
  3243. {
  3244. VectorAdd( t->trans, vec, t->trans );
  3245. }
  3246. // combine transform a and transform b into transform c
  3247. void TransCombine( const transform_t *a, const transform_t *b,
  3248. transform_t *out )
  3249. {
  3250. TransCopy( a, out );
  3251. TransAddRotationQuat( b->rot, out );
  3252. TransAddScale( b->scale, out );
  3253. TransAddTranslation( b->trans, out );
  3254. }
  3255. // compute the inverse transform
  3256. void TransInverse( const transform_t *in, transform_t *out )
  3257. {
  3258. quat_t inverse;
  3259. static transform_t tmp; // static for proper alignment in QVMs
  3260. TransInit( &tmp );
  3261. VectorNegate( in->trans, tmp.trans );
  3262. TransAddScale( 1.0f / in->scale, &tmp );
  3263. QuatCopy( in->rot, inverse );
  3264. QuatInverse( inverse );
  3265. TransAddRotationQuat( inverse, &tmp );
  3266. TransCopy( &tmp, out );
  3267. }
  3268. // lerp between transforms
  3269. void TransStartLerp( transform_t *t )
  3270. {
  3271. QuatZero( t->rot );
  3272. VectorClear( t->trans );
  3273. t->scale = 0.0f;
  3274. }
  3275. void TransAddWeight( float weight, const transform_t *a, transform_t *out )
  3276. {
  3277. if ( DotProduct4( out->rot, a->rot ) < 0 )
  3278. {
  3279. QuatMA( out->rot, -weight, a->rot, out->rot );
  3280. }
  3281. else
  3282. {
  3283. QuatMA( out->rot, weight, a->rot, out->rot );
  3284. }
  3285. VectorMA( out->trans, weight, a->trans, out->trans );
  3286. out->scale += a->scale * weight;
  3287. }
  3288. void TransEndLerp( transform_t *t )
  3289. {
  3290. QuatNormalize( t->rot );
  3291. }
  3292. #endif