GLMatrix.cpp (16693B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition 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 Doom 3 BFG Edition 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 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. 23 24 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. 25 26 =========================================================================== 27 */ 28 29 #pragma hdrstop 30 #include "../idlib/precompiled.h" 31 32 #include "tr_local.h" 33 34 /* 35 ========================================================================================== 36 37 OLD MATRIX MATH 38 39 ========================================================================================== 40 */ 41 42 /* 43 ====================== 44 R_AxisToModelMatrix 45 ====================== 46 */ 47 void R_AxisToModelMatrix( const idMat3 &axis, const idVec3 &origin, float modelMatrix[16] ) { 48 modelMatrix[0 * 4 + 0] = axis[0][0]; 49 modelMatrix[1 * 4 + 0] = axis[1][0]; 50 modelMatrix[2 * 4 + 0] = axis[2][0]; 51 modelMatrix[3 * 4 + 0] = origin[0]; 52 53 modelMatrix[0 * 4 + 1] = axis[0][1]; 54 modelMatrix[1 * 4 + 1] = axis[1][1]; 55 modelMatrix[2 * 4 + 1] = axis[2][1]; 56 modelMatrix[3 * 4 + 1] = origin[1]; 57 58 modelMatrix[0 * 4 + 2] = axis[0][2]; 59 modelMatrix[1 * 4 + 2] = axis[1][2]; 60 modelMatrix[2 * 4 + 2] = axis[2][2]; 61 modelMatrix[3 * 4 + 2] = origin[2]; 62 63 modelMatrix[0 * 4 + 3] = 0.0f; 64 modelMatrix[1 * 4 + 3] = 0.0f; 65 modelMatrix[2 * 4 + 3] = 0.0f; 66 modelMatrix[3 * 4 + 3] = 1.0f; 67 } 68 69 /* 70 ========================== 71 R_MatrixMultiply 72 ========================== 73 */ 74 void R_MatrixMultiply( const float a[16], const float b[16], float out[16] ) { 75 #ifdef ID_WIN_X86_SSE2_INTRIN 76 77 __m128 a0 = _mm_loadu_ps( a + 0*4 ); 78 __m128 a1 = _mm_loadu_ps( a + 1*4 ); 79 __m128 a2 = _mm_loadu_ps( a + 2*4 ); 80 __m128 a3 = _mm_loadu_ps( a + 3*4 ); 81 82 __m128 b0 = _mm_loadu_ps( b + 0*4 ); 83 __m128 b1 = _mm_loadu_ps( b + 1*4 ); 84 __m128 b2 = _mm_loadu_ps( b + 2*4 ); 85 __m128 b3 = _mm_loadu_ps( b + 3*4 ); 86 87 __m128 t0 = _mm_mul_ps( _mm_splat_ps( a0, 0 ), b0 ); 88 __m128 t1 = _mm_mul_ps( _mm_splat_ps( a1, 0 ), b0 ); 89 __m128 t2 = _mm_mul_ps( _mm_splat_ps( a2, 0 ), b0 ); 90 __m128 t3 = _mm_mul_ps( _mm_splat_ps( a3, 0 ), b0 ); 91 92 t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 1 ), b1 ) ); 93 t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 1 ), b1 ) ); 94 t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 1 ), b1 ) ); 95 t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 1 ), b1 ) ); 96 97 t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 2 ), b2 ) ); 98 t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 2 ), b2 ) ); 99 t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 2 ), b2 ) ); 100 t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 2 ), b2 ) ); 101 102 t0 = _mm_add_ps( t0, _mm_mul_ps( _mm_splat_ps( a0, 3 ), b3 ) ); 103 t1 = _mm_add_ps( t1, _mm_mul_ps( _mm_splat_ps( a1, 3 ), b3 ) ); 104 t2 = _mm_add_ps( t2, _mm_mul_ps( _mm_splat_ps( a2, 3 ), b3 ) ); 105 t3 = _mm_add_ps( t3, _mm_mul_ps( _mm_splat_ps( a3, 3 ), b3 ) ); 106 107 _mm_storeu_ps( out + 0*4, t0 ); 108 _mm_storeu_ps( out + 1*4, t1 ); 109 _mm_storeu_ps( out + 2*4, t2 ); 110 _mm_storeu_ps( out + 3*4, t3 ); 111 112 #else 113 114 /* 115 for ( int i = 0; i < 4; i++ ) { 116 for ( int j = 0; j < 4; j++ ) { 117 out[ i * 4 + j ] = 118 a[ i * 4 + 0 ] * b[ 0 * 4 + j ] + 119 a[ i * 4 + 1 ] * b[ 1 * 4 + j ] + 120 a[ i * 4 + 2 ] * b[ 2 * 4 + j ] + 121 a[ i * 4 + 3 ] * b[ 3 * 4 + j ]; 122 } 123 } 124 */ 125 126 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]; 127 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]; 128 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]; 129 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]; 130 131 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]; 132 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]; 133 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]; 134 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]; 135 136 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]; 137 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]; 138 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]; 139 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]; 140 141 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]; 142 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]; 143 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]; 144 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]; 145 146 #endif 147 } 148 149 /* 150 ====================== 151 R_MatrixTranspose 152 ====================== 153 */ 154 void R_MatrixTranspose( const float in[16], float out[16] ) { 155 for ( int i = 0; i < 4; i++ ) { 156 for ( int j = 0; j < 4; j++ ) { 157 out[i*4+j] = in[j*4+i]; 158 } 159 } 160 } 161 162 /* 163 ========================== 164 R_TransformModelToClip 165 ========================== 166 */ 167 void R_TransformModelToClip( const idVec3 &src, const float *modelMatrix, const float *projectionMatrix, idPlane &eye, idPlane &dst ) { 168 for ( int i = 0; i < 4; i++ ) { 169 eye[i] = modelMatrix[i + 0 * 4] * src[0] + 170 modelMatrix[i + 1 * 4] * src[1] + 171 modelMatrix[i + 2 * 4] * src[2] + 172 modelMatrix[i + 3 * 4]; 173 } 174 175 for ( int i = 0; i < 4; i++ ) { 176 dst[i] = projectionMatrix[i + 0 * 4] * eye[0] + 177 projectionMatrix[i + 1 * 4] * eye[1] + 178 projectionMatrix[i + 2 * 4] * eye[2] + 179 projectionMatrix[i + 3 * 4] * eye[3]; 180 } 181 } 182 183 /* 184 ========================== 185 R_TransformClipToDevice 186 187 Clip to normalized device coordinates 188 ========================== 189 */ 190 void R_TransformClipToDevice( const idPlane &clip, idVec3 &ndc ) { 191 const float invW = 1.0f / clip[3]; 192 ndc[0] = clip[0] * invW; 193 ndc[1] = clip[1] * invW; 194 ndc[2] = clip[2] * invW; // NOTE: in D3D this is in the range [0,1] 195 } 196 197 /* 198 ========================== 199 R_GlobalToNormalizedDeviceCoordinates 200 201 -1 to 1 range in x, y, and z 202 ========================== 203 */ 204 void R_GlobalToNormalizedDeviceCoordinates( const idVec3 &global, idVec3 &ndc ) { 205 idPlane view; 206 idPlane clip; 207 208 // _D3XP use tr.primaryView when there is no tr.viewDef 209 const viewDef_t * viewDef = ( tr.viewDef != NULL ) ? tr.viewDef : tr.primaryView; 210 211 for ( int i = 0; i < 4; i ++ ) { 212 view[i] = viewDef->worldSpace.modelViewMatrix[i + 0 * 4] * global[0] + 213 viewDef->worldSpace.modelViewMatrix[i + 1 * 4] * global[1] + 214 viewDef->worldSpace.modelViewMatrix[i + 2 * 4] * global[2] + 215 viewDef->worldSpace.modelViewMatrix[i + 3 * 4]; 216 } 217 218 for ( int i = 0; i < 4; i ++ ) { 219 clip[i] = viewDef->projectionMatrix[i + 0 * 4] * view[0] + 220 viewDef->projectionMatrix[i + 1 * 4] * view[1] + 221 viewDef->projectionMatrix[i + 2 * 4] * view[2] + 222 viewDef->projectionMatrix[i + 3 * 4] * view[3]; 223 } 224 225 const float invW = 1.0f / clip[3]; 226 ndc[0] = clip[0] * invW; 227 ndc[1] = clip[1] * invW; 228 ndc[2] = clip[2] * invW; // NOTE: in D3D this is in the range [0,1] 229 } 230 231 /* 232 ====================== 233 R_LocalPointToGlobal 234 235 NOTE: assumes no skewing or scaling transforms 236 ====================== 237 */ 238 void R_LocalPointToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) { 239 out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0] + modelMatrix[3 * 4 + 0]; 240 out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1] + modelMatrix[3 * 4 + 1]; 241 out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2] + modelMatrix[3 * 4 + 2]; 242 } 243 244 /* 245 ====================== 246 R_GlobalPointToLocal 247 248 NOTE: assumes no skewing or scaling transforms 249 ====================== 250 */ 251 void R_GlobalPointToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) { 252 idVec3 temp; 253 254 temp[0] = in[0] - modelMatrix[3 * 4 + 0]; 255 temp[1] = in[1] - modelMatrix[3 * 4 + 1]; 256 temp[2] = in[2] - modelMatrix[3 * 4 + 2]; 257 258 out[0] = temp[0] * modelMatrix[0 * 4 + 0] + temp[1] * modelMatrix[0 * 4 + 1] + temp[2] * modelMatrix[0 * 4 + 2]; 259 out[1] = temp[0] * modelMatrix[1 * 4 + 0] + temp[1] * modelMatrix[1 * 4 + 1] + temp[2] * modelMatrix[1 * 4 + 2]; 260 out[2] = temp[0] * modelMatrix[2 * 4 + 0] + temp[1] * modelMatrix[2 * 4 + 1] + temp[2] * modelMatrix[2 * 4 + 2]; 261 } 262 263 /* 264 ====================== 265 R_LocalVectorToGlobal 266 267 NOTE: assumes no skewing or scaling transforms 268 ====================== 269 */ 270 void R_LocalVectorToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) { 271 out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0]; 272 out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1]; 273 out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2]; 274 } 275 276 /* 277 ====================== 278 R_GlobalVectorToLocal 279 280 NOTE: assumes no skewing or scaling transforms 281 ====================== 282 */ 283 void R_GlobalVectorToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out ) { 284 out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[0 * 4 + 1] + in[2] * modelMatrix[0 * 4 + 2]; 285 out[1] = in[0] * modelMatrix[1 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[1 * 4 + 2]; 286 out[2] = in[0] * modelMatrix[2 * 4 + 0] + in[1] * modelMatrix[2 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 2]; 287 } 288 289 /* 290 ====================== 291 R_GlobalPlaneToLocal 292 293 NOTE: assumes no skewing or scaling transforms 294 ====================== 295 */ 296 void R_GlobalPlaneToLocal( const float modelMatrix[16], const idPlane &in, idPlane &out ) { 297 out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[0 * 4 + 1] + in[2] * modelMatrix[0 * 4 + 2]; 298 out[1] = in[0] * modelMatrix[1 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[1 * 4 + 2]; 299 out[2] = in[0] * modelMatrix[2 * 4 + 0] + in[1] * modelMatrix[2 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 2]; 300 out[3] = in[0] * modelMatrix[3 * 4 + 0] + in[1] * modelMatrix[3 * 4 + 1] + in[2] * modelMatrix[3 * 4 + 2] + in[3]; 301 } 302 303 /* 304 ====================== 305 R_LocalPlaneToGlobal 306 307 NOTE: assumes no skewing or scaling transforms 308 ====================== 309 */ 310 void R_LocalPlaneToGlobal( const float modelMatrix[16], const idPlane &in, idPlane &out ) { 311 out[0] = in[0] * modelMatrix[0 * 4 + 0] + in[1] * modelMatrix[1 * 4 + 0] + in[2] * modelMatrix[2 * 4 + 0]; 312 out[1] = in[0] * modelMatrix[0 * 4 + 1] + in[1] * modelMatrix[1 * 4 + 1] + in[2] * modelMatrix[2 * 4 + 1]; 313 out[2] = in[0] * modelMatrix[0 * 4 + 2] + in[1] * modelMatrix[1 * 4 + 2] + in[2] * modelMatrix[2 * 4 + 2]; 314 out[3] = in[3] - modelMatrix[3 * 4 + 0] * out[0] - modelMatrix[3 * 4 + 1] * out[1] - modelMatrix[3 * 4 + 2] * out[2]; 315 } 316 317 /* 318 ========================================================================================== 319 320 WORLD/VIEW/PROJECTION MATRIX SETUP 321 322 ========================================================================================== 323 */ 324 325 /* 326 ====================== 327 R_SetupViewMatrix 328 329 Sets up the world to view matrix for a given viewParm 330 ====================== 331 */ 332 void R_SetupViewMatrix( viewDef_t *viewDef ) { 333 static float s_flipMatrix[16] = { 334 // convert from our coordinate system (looking down X) 335 // to OpenGL's coordinate system (looking down -Z) 336 0, 0, -1, 0, 337 -1, 0, 0, 0, 338 0, 1, 0, 0, 339 0, 0, 0, 1 340 }; 341 342 viewEntity_t *world = &viewDef->worldSpace; 343 memset( world, 0, sizeof( *world ) ); 344 345 // the model matrix is an identity 346 world->modelMatrix[0*4+0] = 1.0f; 347 world->modelMatrix[1*4+1] = 1.0f; 348 world->modelMatrix[2*4+2] = 1.0f; 349 350 // transform by the camera placement 351 const idVec3 & origin = viewDef->renderView.vieworg; 352 const idMat3 & axis = viewDef->renderView.viewaxis; 353 354 float viewerMatrix[16]; 355 viewerMatrix[0*4+0] = axis[0][0]; 356 viewerMatrix[1*4+0] = axis[0][1]; 357 viewerMatrix[2*4+0] = axis[0][2]; 358 viewerMatrix[3*4+0] = - origin[0] * axis[0][0] - origin[1] * axis[0][1] - origin[2] * axis[0][2]; 359 360 viewerMatrix[0*4+1] = axis[1][0]; 361 viewerMatrix[1*4+1] = axis[1][1]; 362 viewerMatrix[2*4+1] = axis[1][2]; 363 viewerMatrix[3*4+1] = - origin[0] * axis[1][0] - origin[1] * axis[1][1] - origin[2] * axis[1][2]; 364 365 viewerMatrix[0*4+2] = axis[2][0]; 366 viewerMatrix[1*4+2] = axis[2][1]; 367 viewerMatrix[2*4+2] = axis[2][2]; 368 viewerMatrix[3*4+2] = - origin[0] * axis[2][0] - origin[1] * axis[2][1] - origin[2] * axis[2][2]; 369 370 viewerMatrix[0*4+3] = 0.0f; 371 viewerMatrix[1*4+3] = 0.0f; 372 viewerMatrix[2*4+3] = 0.0f; 373 viewerMatrix[3*4+3] = 1.0f; 374 375 // convert from our coordinate system (looking down X) 376 // to OpenGL's coordinate system (looking down -Z) 377 R_MatrixMultiply( viewerMatrix, s_flipMatrix, world->modelViewMatrix ); 378 } 379 380 /* 381 ====================== 382 R_SetupProjectionMatrix 383 384 This uses the "infinite far z" trick 385 ====================== 386 */ 387 idCVar r_centerX( "r_centerX", "0", CVAR_FLOAT, "projection matrix center adjust" ); 388 idCVar r_centerY( "r_centerY", "0", CVAR_FLOAT, "projection matrix center adjust" ); 389 390 void R_SetupProjectionMatrix( viewDef_t *viewDef ) { 391 // random jittering is usefull when multiple 392 // frames are going to be blended together 393 // for motion blurred anti-aliasing 394 float jitterx, jittery; 395 if ( r_jitter.GetBool() ) { 396 static idRandom random; 397 jitterx = random.RandomFloat(); 398 jittery = random.RandomFloat(); 399 } else { 400 jitterx = 0.0f; 401 jittery = 0.0f; 402 } 403 404 // 405 // set up projection matrix 406 // 407 const float zNear = ( viewDef->renderView.cramZNear ) ? ( r_znear.GetFloat() * 0.25f ) : r_znear.GetFloat(); 408 409 float ymax = zNear * tan( viewDef->renderView.fov_y * idMath::PI / 360.0f ); 410 float ymin = -ymax; 411 412 float xmax = zNear * tan( viewDef->renderView.fov_x * idMath::PI / 360.0f ); 413 float xmin = -xmax; 414 415 const float width = xmax - xmin; 416 const float height = ymax - ymin; 417 418 const int viewWidth = viewDef->viewport.x2 - viewDef->viewport.x1 + 1; 419 const int viewHeight = viewDef->viewport.y2 - viewDef->viewport.y1 + 1; 420 421 jitterx = jitterx * width / viewWidth; 422 jitterx += r_centerX.GetFloat(); 423 jitterx += viewDef->renderView.stereoScreenSeparation; 424 xmin += jitterx * width; 425 xmax += jitterx * width; 426 427 jittery = jittery * height / viewHeight; 428 jittery += r_centerY.GetFloat(); 429 ymin += jittery * height; 430 ymax += jittery * height; 431 432 viewDef->projectionMatrix[0*4+0] = 2.0f * zNear / width; 433 viewDef->projectionMatrix[1*4+0] = 0.0f; 434 viewDef->projectionMatrix[2*4+0] = ( xmax + xmin ) / width; // normally 0 435 viewDef->projectionMatrix[3*4+0] = 0.0f; 436 437 viewDef->projectionMatrix[0*4+1] = 0.0f; 438 viewDef->projectionMatrix[1*4+1] = 2.0f * zNear / height; 439 viewDef->projectionMatrix[2*4+1] = ( ymax + ymin ) / height; // normally 0 440 viewDef->projectionMatrix[3*4+1] = 0.0f; 441 442 // this is the far-plane-at-infinity formulation, and 443 // crunches the Z range slightly so w=0 vertexes do not 444 // rasterize right at the wraparound point 445 viewDef->projectionMatrix[0*4+2] = 0.0f; 446 viewDef->projectionMatrix[1*4+2] = 0.0f; 447 viewDef->projectionMatrix[2*4+2] = -0.999f; // adjust value to prevent imprecision issues 448 viewDef->projectionMatrix[3*4+2] = -2.0f * zNear; 449 450 viewDef->projectionMatrix[0*4+3] = 0.0f; 451 viewDef->projectionMatrix[1*4+3] = 0.0f; 452 viewDef->projectionMatrix[2*4+3] = -1.0f; 453 viewDef->projectionMatrix[3*4+3] = 0.0f; 454 455 if ( viewDef->renderView.flipProjection ) { 456 viewDef->projectionMatrix[1*4+1] = -viewDef->projectionMatrix[1*4+1]; 457 viewDef->projectionMatrix[1*4+3] = -viewDef->projectionMatrix[1*4+3]; 458 } 459 }