GLMatrix.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. /*
  24. ==========================================================================================
  25. OLD MATRIX MATH
  26. ==========================================================================================
  27. */
  28. /*
  29. ======================
  30. R_AxisToModelMatrix
  31. ======================
  32. */
  33. void R_AxisToModelMatrix( const idMat3 &axis, const idVec3 &origin, float modelMatrix[16] ) {
  34. modelMatrix[0 * 4 + 0] = axis[0][0];
  35. modelMatrix[1 * 4 + 0] = axis[1][0];
  36. modelMatrix[2 * 4 + 0] = axis[2][0];
  37. modelMatrix[3 * 4 + 0] = origin[0];
  38. modelMatrix[0 * 4 + 1] = axis[0][1];
  39. modelMatrix[1 * 4 + 1] = axis[1][1];
  40. modelMatrix[2 * 4 + 1] = axis[2][1];
  41. modelMatrix[3 * 4 + 1] = origin[1];
  42. modelMatrix[0 * 4 + 2] = axis[0][2];
  43. modelMatrix[1 * 4 + 2] = axis[1][2];
  44. modelMatrix[2 * 4 + 2] = axis[2][2];
  45. modelMatrix[3 * 4 + 2] = origin[2];
  46. modelMatrix[0 * 4 + 3] = 0.0f;
  47. modelMatrix[1 * 4 + 3] = 0.0f;
  48. modelMatrix[2 * 4 + 3] = 0.0f;
  49. modelMatrix[3 * 4 + 3] = 1.0f;
  50. }
  51. /*
  52. ==========================
  53. R_MatrixMultiply
  54. ==========================
  55. */
  56. void R_MatrixMultiply( const float a[16], const float b[16], float out[16] ) {
  57. #ifdef ID_WIN_X86_SSE2_INTRIN
  58. __m128 a0 = _mm_loadu_ps( a + 0*4 );
  59. __m128 a1 = _mm_loadu_ps( a + 1*4 );
  60. __m128 a2 = _mm_loadu_ps( a + 2*4 );
  61. __m128 a3 = _mm_loadu_ps( a + 3*4 );
  62. __m128 b0 = _mm_loadu_ps( b + 0*4 );
  63. __m128 b1 = _mm_loadu_ps( b + 1*4 );
  64. __m128 b2 = _mm_loadu_ps( b + 2*4 );
  65. __m128 b3 = _mm_loadu_ps( b + 3*4 );
  66. __m128 t0 = _mm_mul_ps( _mm_splat_ps( a0, 0 ), b0 );
  67. __m128 t1 = _mm_mul_ps( _mm_splat_ps( a1, 0 ), b0 );
  68. __m128 t2 = _mm_mul_ps( _mm_splat_ps( a2, 0 ), b0 );
  69. __m128 t3 = _mm_mul_ps( _mm_splat_ps( a3, 0 ), b0 );
  70. t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 1 ), b1 ) );
  71. t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 1 ), b1 ) );
  72. t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 1 ), b1 ) );
  73. t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 1 ), b1 ) );
  74. t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 2 ), b2 ) );
  75. t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 2 ), b2 ) );
  76. t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 2 ), b2 ) );
  77. t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 2 ), b2 ) );
  78. t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 3 ), b3 ) );
  79. t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 3 ), b3 ) );
  80. t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 3 ), b3 ) );
  81. t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 3 ), b3 ) );
  82. _mm_storeu_ps( out + 0*4, t0 );
  83. _mm_storeu_ps( out + 1*4, t1 );
  84. _mm_storeu_ps( out + 2*4, t2 );
  85. _mm_storeu_ps( out + 3*4, t3 );
  86. #else
  87. /*
  88. for ( int i = 0; i < 4; i++ ) {
  89. for ( int j = 0; j < 4; j++ ) {
  90. out[ i * 4 + j ] =
  91. a[ i * 4 + 0 ] * b[ 0 * 4 + j ] +
  92. a[ i * 4 + 1 ] * b[ 1 * 4 + j ] +
  93. a[ i * 4 + 2 ] * b[ 2 * 4 + j ] +
  94. a[ i * 4 + 3 ] * b[ 3 * 4 + j ];
  95. }
  96. }
  97. */
  98. out[0*4+0] = a[0*4+0]*b[0*4+0] + a[0*4+1]*b[1*4+0] + a[0*4+2]*b[2*4+0] + a[0*4+3]*b[3*4+0];
  99. out[0*4+1] = a[0*4+0]*b[0*4+1] + a[0*4+1]*b[1*4+1] + a[0*4+2]*b[2*4+1] + a[0*4+3]*b[3*4+1];
  100. out[0*4+2] = a[0*4+0]*b[0*4+2] + a[0*4+1]*b[1*4+2] + a[0*4+2]*b[2*4+2] + a[0*4+3]*b[3*4+2];
  101. out[0*4+3] = a[0*4+0]*b[0*4+3] + a[0*4+1]*b[1*4+3] + a[0*4+2]*b[2*4+3] + a[0*4+3]*b[3*4+3];
  102. out[1*4+0] = a[1*4+0]*b[0*4+0] + a[1*4+1]*b[1*4+0] + a[1*4+2]*b[2*4+0] + a[1*4+3]*b[3*4+0];
  103. out[1*4+1] = a[1*4+0]*b[0*4+1] + a[1*4+1]*b[1*4+1] + a[1*4+2]*b[2*4+1] + a[1*4+3]*b[3*4+1];
  104. out[1*4+2] = a[1*4+0]*b[0*4+2] + a[1*4+1]*b[1*4+2] + a[1*4+2]*b[2*4+2] + a[1*4+3]*b[3*4+2];
  105. out[1*4+3] = a[1*4+0]*b[0*4+3] + a[1*4+1]*b[1*4+3] + a[1*4+2]*b[2*4+3] + a[1*4+3]*b[3*4+3];
  106. out[2*4+0] = a[2*4+0]*b[0*4+0] + a[2*4+1]*b[1*4+0] + a[2*4+2]*b[2*4+0] + a[2*4+3]*b[3*4+0];
  107. out[2*4+1] = a[2*4+0]*b[0*4+1] + a[2*4+1]*b[1*4+1] + a[2*4+2]*b[2*4+1] + a[2*4+3]*b[3*4+1];
  108. out[2*4+2] = a[2*4+0]*b[0*4+2] + a[2*4+1]*b[1*4+2] + a[2*4+2]*b[2*4+2] + a[2*4+3]*b[3*4+2];
  109. out[2*4+3] = a[2*4+0]*b[0*4+3] + a[2*4+1]*b[1*4+3] + a[2*4+2]*b[2*4+3] + a[2*4+3]*b[3*4+3];
  110. out[3*4+0] = a[3*4+0]*b[0*4+0] + a[3*4+1]*b[1*4+0] + a[3*4+2]*b[2*4+0] + a[3*4+3]*b[3*4+0];
  111. out[3*4+1] = a[3*4+0]*b[0*4+1] + a[3*4+1]*b[1*4+1] + a[3*4+2]*b[2*4+1] + a[3*4+3]*b[3*4+1];
  112. out[3*4+2] = a[3*4+0]*b[0*4+2] + a[3*4+1]*b[1*4+2] + a[3*4+2]*b[2*4+2] + a[3*4+3]*b[3*4+2];
  113. out[3*4+3] = a[3*4+0]*b[0*4+3] + a[3*4+1]*b[1*4+3] + a[3*4+2]*b[2*4+3] + a[3*4+3]*b[3*4+3];
  114. #endif
  115. }
  116. /*
  117. ======================
  118. R_MatrixTranspose
  119. ======================
  120. */
  121. void R_MatrixTranspose( const float in[16], float out[16] ) {
  122. for ( int i = 0; i < 4; i++ ) {
  123. for ( int j = 0; j < 4; j++ ) {
  124. out[i*4+j] = in[j*4+i];
  125. }
  126. }
  127. }
  128. /*
  129. ==========================
  130. R_TransformModelToClip
  131. ==========================
  132. */
  133. void R_TransformModelToClip( const idVec3 &src, const float *modelMatrix, const float *projectionMatrix, idPlane &eye, idPlane &dst ) {
  134. for ( int i = 0; i < 4; i++ ) {
  135. eye[i] = modelMatrix[i + 0 * 4] * src[0] +
  136. modelMatrix[i + 1 * 4] * src[1] +
  137. modelMatrix[i + 2 * 4] * src[2] +
  138. modelMatrix[i + 3 * 4];
  139. }
  140. for ( int i = 0; i < 4; i++ ) {
  141. dst[i] = projectionMatrix[i + 0 * 4] * eye[0] +
  142. projectionMatrix[i + 1 * 4] * eye[1] +
  143. projectionMatrix[i + 2 * 4] * eye[2] +
  144. projectionMatrix[i + 3 * 4] * eye[3];
  145. }
  146. }
  147. /*
  148. ==========================
  149. R_TransformClipToDevice
  150. Clip to normalized device coordinates
  151. ==========================
  152. */
  153. void R_TransformClipToDevice( const idPlane &clip, idVec3 &ndc ) {
  154. const float invW = 1.0f / clip[3];
  155. ndc[0] = clip[0] * invW;
  156. ndc[1] = clip[1] * invW;
  157. ndc[2] = clip[2] * invW; // NOTE: in D3D this is in the range [0,1]
  158. }
  159. /*
  160. ==========================
  161. R_GlobalToNormalizedDeviceCoordinates
  162. -1 to 1 range in x, y, and z
  163. ==========================
  164. */
  165. void R_GlobalToNormalizedDeviceCoordinates( const idVec3 &global, idVec3 &ndc ) {
  166. idPlane view;
  167. idPlane clip;
  168. // _D3XP use tr.primaryView when there is no tr.viewDef
  169. const viewDef_t * viewDef = ( tr.viewDef != NULL ) ? tr.viewDef : tr.primaryView;
  170. for ( int i = 0; i < 4; i ++ ) {
  171. view[i] = viewDef->worldSpace.modelViewMatrix[i + 0 * 4] * global[0] +
  172. viewDef->worldSpace.modelViewMatrix[i + 1 * 4] * global[1] +
  173. viewDef->worldSpace.modelViewMatrix[i + 2 * 4] * global[2] +
  174. viewDef->worldSpace.modelViewMatrix[i + 3 * 4];
  175. }
  176. for ( int i = 0; i < 4; i ++ ) {
  177. clip[i] = viewDef->projectionMatrix[i + 0 * 4] * view[0] +
  178. viewDef->projectionMatrix[i + 1 * 4] * view[1] +
  179. viewDef->projectionMatrix[i + 2 * 4] * view[2] +
  180. viewDef->projectionMatrix[i + 3 * 4] * view[3];
  181. }
  182. const float invW = 1.0f / clip[3];
  183. ndc[0] = clip[0] * invW;
  184. ndc[1] = clip[1] * invW;
  185. ndc[2] = clip[2] * invW; // NOTE: in D3D this is in the range [0,1]
  186. }
  187. /*
  188. ======================
  189. R_LocalPointToGlobal
  190. NOTE: assumes no skewing or scaling transforms
  191. ======================
  192. */
  193. void R_LocalPointToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) {
  194. out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0] + modelMatrix[3 * 4 + 0];
  195. out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1] + modelMatrix[3 * 4 + 1];
  196. out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2] + modelMatrix[3 * 4 + 2];
  197. }
  198. /*
  199. ======================
  200. R_GlobalPointToLocal
  201. NOTE: assumes no skewing or scaling transforms
  202. ======================
  203. */
  204. void R_GlobalPointToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) {
  205. idVec3 temp;
  206. temp[0] = in[0] - modelMatrix[3 * 4 + 0];
  207. temp[1] = in[1] - modelMatrix[3 * 4 + 1];
  208. temp[2] = in[2] - modelMatrix[3 * 4 + 2];
  209. out[0] = temp[0] * modelMatrix[0 * 4 + 0] + temp[1] * modelMatrix[0 * 4 + 1] + temp[2] * modelMatrix[0 * 4 + 2];
  210. out[1] = temp[0] * modelMatrix[1 * 4 + 0] + temp[1] * modelMatrix[1 * 4 + 1] + temp[2] * modelMatrix[1 * 4 + 2];
  211. out[2] = temp[0] * modelMatrix[2 * 4 + 0] + temp[1] * modelMatrix[2 * 4 + 1] + temp[2] * modelMatrix[2 * 4 + 2];
  212. }
  213. /*
  214. ======================
  215. R_LocalVectorToGlobal
  216. NOTE: assumes no skewing or scaling transforms
  217. ======================
  218. */
  219. void R_LocalVectorToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) {
  220. out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0];
  221. out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1];
  222. out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2];
  223. }
  224. /*
  225. ======================
  226. R_GlobalVectorToLocal
  227. NOTE: assumes no skewing or scaling transforms
  228. ======================
  229. */
  230. void R_GlobalVectorToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) {
  231. out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[0 * 4 + 1] + in[2] * modelMatrix[0 * 4 + 2];
  232. out[1] = in[0] * modelMatrix[1 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[1 * 4 + 2];
  233. out[2] = in[0] * modelMatrix[2 * 4 + 0] + in[1] * modelMatrix[2 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 2];
  234. }
  235. /*
  236. ======================
  237. R_GlobalPlaneToLocal
  238. NOTE: assumes no skewing or scaling transforms
  239. ======================
  240. */
  241. void R_GlobalPlaneToLocal( const float modelMatrix[16], const idPlane &in, idPlane &out ) {
  242. out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[0 * 4 + 1] + in[2] * modelMatrix[0 * 4 + 2];
  243. out[1] = in[0] * modelMatrix[1 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[1 * 4 + 2];
  244. out[2] = in[0] * modelMatrix[2 * 4 + 0] + in[1] * modelMatrix[2 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 2];
  245. out[3] = in[0] * modelMatrix[3 * 4 + 0] + in[1] * modelMatrix[3 * 4 + 1] + in[2] * modelMatrix[3 * 4 + 2] + in[3];
  246. }
  247. /*
  248. ======================
  249. R_LocalPlaneToGlobal
  250. NOTE: assumes no skewing or scaling transforms
  251. ======================
  252. */
  253. void R_LocalPlaneToGlobal( const float modelMatrix[16], const idPlane &in, idPlane &out ) {
  254. out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0];
  255. out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1];
  256. out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2];
  257. out[3] = in[3] - modelMatrix[3 * 4 + 0] * out[0] - modelMatrix[3 * 4 + 1] * out[1] - modelMatrix[3 * 4 + 2] * out[2];
  258. }
  259. /*
  260. ==========================================================================================
  261. WORLD/VIEW/PROJECTION MATRIX SETUP
  262. ==========================================================================================
  263. */
  264. /*
  265. ======================
  266. R_SetupViewMatrix
  267. Sets up the world to view matrix for a given viewParm
  268. ======================
  269. */
  270. void R_SetupViewMatrix( viewDef_t *viewDef ) {
  271. static float s_flipMatrix[16] = {
  272. // convert from our coordinate system (looking down X)
  273. // to OpenGL's coordinate system (looking down -Z)
  274. 0, 0, -1, 0,
  275. -1, 0, 0, 0,
  276. 0, 1, 0, 0,
  277. 0, 0, 0, 1
  278. };
  279. viewEntity_t *world = &viewDef->worldSpace;
  280. memset( world, 0, sizeof( *world ) );
  281. // the model matrix is an identity
  282. world->modelMatrix[0*4+0] = 1.0f;
  283. world->modelMatrix[1*4+1] = 1.0f;
  284. world->modelMatrix[2*4+2] = 1.0f;
  285. // transform by the camera placement
  286. const idVec3 & origin = viewDef->renderView.vieworg;
  287. const idMat3 & axis = viewDef->renderView.viewaxis;
  288. float viewerMatrix[16];
  289. viewerMatrix[0*4+0] = axis[0][0];
  290. viewerMatrix[1*4+0] = axis[0][1];
  291. viewerMatrix[2*4+0] = axis[0][2];
  292. viewerMatrix[3*4+0] = - origin[0] * axis[0][0] - origin[1] * axis[0][1] - origin[2] * axis[0][2];
  293. viewerMatrix[0*4+1] = axis[1][0];
  294. viewerMatrix[1*4+1] = axis[1][1];
  295. viewerMatrix[2*4+1] = axis[1][2];
  296. viewerMatrix[3*4+1] = - origin[0] * axis[1][0] - origin[1] * axis[1][1] - origin[2] * axis[1][2];
  297. viewerMatrix[0*4+2] = axis[2][0];
  298. viewerMatrix[1*4+2] = axis[2][1];
  299. viewerMatrix[2*4+2] = axis[2][2];
  300. viewerMatrix[3*4+2] = - origin[0] * axis[2][0] - origin[1] * axis[2][1] - origin[2] * axis[2][2];
  301. viewerMatrix[0*4+3] = 0.0f;
  302. viewerMatrix[1*4+3] = 0.0f;
  303. viewerMatrix[2*4+3] = 0.0f;
  304. viewerMatrix[3*4+3] = 1.0f;
  305. // convert from our coordinate system (looking down X)
  306. // to OpenGL's coordinate system (looking down -Z)
  307. R_MatrixMultiply( viewerMatrix, s_flipMatrix, world->modelViewMatrix );
  308. }
  309. /*
  310. ======================
  311. R_SetupProjectionMatrix
  312. This uses the "infinite far z" trick
  313. ======================
  314. */
  315. idCVar r_centerX( "r_centerX", "0", CVAR_FLOAT, "projection matrix center adjust" );
  316. idCVar r_centerY( "r_centerY", "0", CVAR_FLOAT, "projection matrix center adjust" );
  317. void R_SetupProjectionMatrix( viewDef_t *viewDef ) {
  318. // random jittering is usefull when multiple
  319. // frames are going to be blended together
  320. // for motion blurred anti-aliasing
  321. float jitterx, jittery;
  322. if ( r_jitter.GetBool() ) {
  323. static idRandom random;
  324. jitterx = random.RandomFloat();
  325. jittery = random.RandomFloat();
  326. } else {
  327. jitterx = 0.0f;
  328. jittery = 0.0f;
  329. }
  330. //
  331. // set up projection matrix
  332. //
  333. const float zNear = ( viewDef->renderView.cramZNear ) ? ( r_znear.GetFloat() * 0.25f ) : r_znear.GetFloat();
  334. float ymax = zNear * tan( viewDef->renderView.fov_y * idMath::PI / 360.0f );
  335. float ymin = -ymax;
  336. float xmax = zNear * tan( viewDef->renderView.fov_x * idMath::PI / 360.0f );
  337. float xmin = -xmax;
  338. const float width = xmax - xmin;
  339. const float height = ymax - ymin;
  340. const int viewWidth = viewDef->viewport.x2 - viewDef->viewport.x1 + 1;
  341. const int viewHeight = viewDef->viewport.y2 - viewDef->viewport.y1 + 1;
  342. jitterx = jitterx * width / viewWidth;
  343. jitterx += r_centerX.GetFloat();
  344. jitterx += viewDef->renderView.stereoScreenSeparation;
  345. xmin += jitterx * width;
  346. xmax += jitterx * width;
  347. jittery = jittery * height / viewHeight;
  348. jittery += r_centerY.GetFloat();
  349. ymin += jittery * height;
  350. ymax += jittery * height;
  351. viewDef->projectionMatrix[0*4+0] = 2.0f * zNear / width;
  352. viewDef->projectionMatrix[1*4+0] = 0.0f;
  353. viewDef->projectionMatrix[2*4+0] = ( xmax + xmin ) / width; // normally 0
  354. viewDef->projectionMatrix[3*4+0] = 0.0f;
  355. viewDef->projectionMatrix[0*4+1] = 0.0f;
  356. viewDef->projectionMatrix[1*4+1] = 2.0f * zNear / height;
  357. viewDef->projectionMatrix[2*4+1] = ( ymax + ymin ) / height; // normally 0
  358. viewDef->projectionMatrix[3*4+1] = 0.0f;
  359. // this is the far-plane-at-infinity formulation, and
  360. // crunches the Z range slightly so w=0 vertexes do not
  361. // rasterize right at the wraparound point
  362. viewDef->projectionMatrix[0*4+2] = 0.0f;
  363. viewDef->projectionMatrix[1*4+2] = 0.0f;
  364. viewDef->projectionMatrix[2*4+2] = -0.999f; // adjust value to prevent imprecision issues
  365. viewDef->projectionMatrix[3*4+2] = -2.0f * zNear;
  366. viewDef->projectionMatrix[0*4+3] = 0.0f;
  367. viewDef->projectionMatrix[1*4+3] = 0.0f;
  368. viewDef->projectionMatrix[2*4+3] = -1.0f;
  369. viewDef->projectionMatrix[3*4+3] = 0.0f;
  370. if ( viewDef->renderView.flipProjection ) {
  371. viewDef->projectionMatrix[1*4+1] = -viewDef->projectionMatrix[1*4+1];
  372. viewDef->projectionMatrix[1*4+3] = -viewDef->projectionMatrix[1*4+3];
  373. }
  374. }