1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // r_misc.c 21 22 #include "quakedef.h" 23 #include "r_local.h" 24 25 26 /* 27 =============== 28 R_CheckVariables 29 =============== 30 */ 31 void R_CheckVariables (void) 32 { 33 static float oldbright; 34 35 if (r_fullbright.value != oldbright) 36 { 37 oldbright = r_fullbright.value; 38 D_FlushCaches (); // so all lighting changes 39 } 40 } 41 42 43 /* 44 ============ 45 Show 46 47 Debugging use 48 ============ 49 */ 50 void Show (void) 51 { 52 vrect_t vr; 53 54 vr.x = vr.y = 0; 55 vr.width = vid.width; 56 vr.height = vid.height; 57 vr.pnext = NULL; 58 VID_Update (&vr); 59 } 60 61 62 /* 63 ==================== 64 R_TimeRefresh_f 65 66 For program optimization 67 ==================== 68 */ 69 void R_TimeRefresh_f (void) 70 { 71 int i; 72 float start, stop, time; 73 int startangle; 74 vrect_t vr; 75 76 startangle = r_refdef.viewangles[1]; 77 78 start = Sys_FloatTime (); 79 for (i=0 ; i<128 ; i++) 80 { 81 r_refdef.viewangles[1] = i/128.0*360.0; 82 83 VID_LockBuffer (); 84 85 R_RenderView (); 86 87 VID_UnlockBuffer (); 88 89 vr.x = r_refdef.vrect.x; 90 vr.y = r_refdef.vrect.y; 91 vr.width = r_refdef.vrect.width; 92 vr.height = r_refdef.vrect.height; 93 vr.pnext = NULL; 94 VID_Update (&vr); 95 } 96 stop = Sys_FloatTime (); 97 time = stop-start; 98 Con_Printf ("%f seconds (%f fps)\n", time, 128/time); 99 100 r_refdef.viewangles[1] = startangle; 101 } 102 103 104 /* 105 ================ 106 R_LineGraph 107 108 Only called by R_DisplayTime 109 ================ 110 */ 111 void R_LineGraph (int x, int y, int h) 112 { 113 int i; 114 byte *dest; 115 int s; 116 117 // FIXME: should be disabled on no-buffer adapters, or should be in the driver 118 119 x += r_refdef.vrect.x; 120 y += r_refdef.vrect.y; 121 122 dest = vid.buffer + vid.rowbytes*y + x; 123 124 s = r_graphheight.value; 125 126 if (h>s) 127 h = s; 128 129 for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2) 130 { 131 dest[0] = 0xff; 132 *(dest-vid.rowbytes) = 0x30; 133 } 134 for ( ; i<s ; i++, dest -= vid.rowbytes*2) 135 { 136 dest[0] = 0x30; 137 *(dest-vid.rowbytes) = 0x30; 138 } 139 } 140 141 /* 142 ============== 143 R_TimeGraph 144 145 Performance monitoring tool 146 ============== 147 */ 148 #define MAX_TIMINGS 100 149 extern float mouse_x, mouse_y; 150 void R_TimeGraph (void) 151 { 152 static int timex; 153 int a; 154 float r_time2; 155 static byte r_timings[MAX_TIMINGS]; 156 int x; 157 158 r_time2 = Sys_FloatTime (); 159 160 a = (r_time2-r_time1)/0.01; 161 //a = fabs(mouse_y * 0.05); 162 //a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value; 163 //a = fabs(velocity[0])/20; 164 //a = ((int)fabs(origin[0])/8)%20; 165 //a = (cl.idealpitch + 30)/5; 166 r_timings[timex] = a; 167 a = timex; 168 169 if (r_refdef.vrect.width <= MAX_TIMINGS) 170 x = r_refdef.vrect.width-1; 171 else 172 x = r_refdef.vrect.width - 173 (r_refdef.vrect.width - MAX_TIMINGS)/2; 174 do 175 { 176 R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]); 177 if (x==0) 178 break; // screen too small to hold entire thing 179 x--; 180 a--; 181 if (a == -1) 182 a = MAX_TIMINGS-1; 183 } while (a != timex); 184 185 timex = (timex+1)%MAX_TIMINGS; 186 } 187 188 189 /* 190 ============= 191 R_PrintTimes 192 ============= 193 */ 194 void R_PrintTimes (void) 195 { 196 float r_time2; 197 float ms; 198 199 r_time2 = Sys_FloatTime (); 200 201 ms = 1000* (r_time2 - r_time1); 202 203 Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n", 204 ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf); 205 c_surf = 0; 206 } 207 208 209 /* 210 ============= 211 R_PrintDSpeeds 212 ============= 213 */ 214 void R_PrintDSpeeds (void) 215 { 216 float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time; 217 218 r_time2 = Sys_FloatTime (); 219 220 dp_time = (dp_time2 - dp_time1) * 1000; 221 rw_time = (rw_time2 - rw_time1) * 1000; 222 db_time = (db_time2 - db_time1) * 1000; 223 se_time = (se_time2 - se_time1) * 1000; 224 de_time = (de_time2 - de_time1) * 1000; 225 dv_time = (dv_time2 - dv_time1) * 1000; 226 ms = (r_time2 - r_time1) * 1000; 227 228 Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n", 229 (int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time, 230 dv_time); 231 } 232 233 234 /* 235 ============= 236 R_PrintAliasStats 237 ============= 238 */ 239 void R_PrintAliasStats (void) 240 { 241 Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn); 242 } 243 244 245 void WarpPalette (void) 246 { 247 int i,j; 248 byte newpalette[768]; 249 int basecolor[3]; 250 251 basecolor[0] = 130; 252 basecolor[1] = 80; 253 basecolor[2] = 50; 254 255 // pull the colors halfway to bright brown 256 for (i=0 ; i<256 ; i++) 257 { 258 for (j=0 ; j<3 ; j++) 259 { 260 newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2; 261 } 262 } 263 264 VID_ShiftPalette (newpalette); 265 } 266 267 268 /* 269 =================== 270 R_TransformFrustum 271 =================== 272 */ 273 void R_TransformFrustum (void) 274 { 275 int i; 276 vec3_t v, v2; 277 278 for (i=0 ; i<4 ; i++) 279 { 280 v[0] = screenedge[i].normal[2]; 281 v[1] = -screenedge[i].normal[0]; 282 v[2] = screenedge[i].normal[1]; 283 284 v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0]; 285 v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1]; 286 v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2]; 287 288 VectorCopy (v2, view_clipplanes[i].normal); 289 290 view_clipplanes[i].dist = DotProduct (modelorg, v2); 291 } 292 } 293 294 295 #if !id386 296 297 /* 298 ================ 299 TransformVector 300 ================ 301 */ 302 void TransformVector (vec3_t in, vec3_t out) 303 { 304 out[0] = DotProduct(in,vright); 305 out[1] = DotProduct(in,vup); 306 out[2] = DotProduct(in,vpn); 307 } 308 309 #endif 310 311 312 /* 313 ================ 314 R_TransformPlane 315 ================ 316 */ 317 void R_TransformPlane (mplane_t *p, float *normal, float *dist) 318 { 319 float d; 320 321 d = DotProduct (r_origin, p->normal); 322 *dist = p->dist - d; 323 // TODO: when we have rotating entities, this will need to use the view matrix 324 TransformVector (p->normal, normal); 325 } 326 327 328 /* 329 =============== 330 R_SetUpFrustumIndexes 331 =============== 332 */ 333 void R_SetUpFrustumIndexes (void) 334 { 335 int i, j, *pindex; 336 337 pindex = r_frustum_indexes; 338 339 for (i=0 ; i<4 ; i++) 340 { 341 for (j=0 ; j<3 ; j++) 342 { 343 if (view_clipplanes[i].normal[j] < 0) 344 { 345 pindex[j] = j; 346 pindex[j+3] = j+3; 347 } 348 else 349 { 350 pindex[j] = j+3; 351 pindex[j+3] = j; 352 } 353 } 354 355 // FIXME: do just once at start 356 pfrustum_indexes[i] = pindex; 357 pindex += 6; 358 } 359 } 360 361 362 /* 363 =============== 364 R_SetupFrame 365 =============== 366 */ 367 void R_SetupFrame (void) 368 { 369 int edgecount; 370 vrect_t vrect; 371 float w, h; 372 373 // don't allow cheats in multiplayer 374 if (cl.maxclients > 1) 375 { 376 Cvar_Set ("r_draworder", "0"); 377 Cvar_Set ("r_fullbright", "0"); 378 Cvar_Set ("r_ambient", "0"); 379 Cvar_Set ("r_drawflat", "0"); 380 } 381 382 if (r_numsurfs.value) 383 { 384 if ((surface_p - surfaces) > r_maxsurfsseen) 385 r_maxsurfsseen = surface_p - surfaces; 386 387 Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces, 388 surf_max - surfaces, r_maxsurfsseen); 389 } 390 391 if (r_numedges.value) 392 { 393 edgecount = edge_p - r_edges; 394 395 if (edgecount > r_maxedgesseen) 396 r_maxedgesseen = edgecount; 397 398 Con_Printf ("Used %d of %d edges; %d max\n", edgecount, 399 r_numallocatededges, r_maxedgesseen); 400 } 401 402 r_refdef.ambientlight = r_ambient.value; 403 404 if (r_refdef.ambientlight < 0) 405 r_refdef.ambientlight = 0; 406 407 if (!sv.active) 408 r_draworder.value = 0; // don't let cheaters look behind walls 409 410 R_CheckVariables (); 411 412 R_AnimateLight (); 413 414 r_framecount++; 415 416 numbtofpolys = 0; 417 418 // debugging 419 #if 0 420 r_refdef.vieworg[0]= 80; 421 r_refdef.vieworg[1]= 64; 422 r_refdef.vieworg[2]= 40; 423 r_refdef.viewangles[0]= 0; 424 r_refdef.viewangles[1]= 46.763641357; 425 r_refdef.viewangles[2]= 0; 426 #endif 427 428 // build the transformation matrix for the given view angles 429 VectorCopy (r_refdef.vieworg, modelorg); 430 VectorCopy (r_refdef.vieworg, r_origin); 431 432 AngleVectors (r_refdef.viewangles, vpn, vright, vup); 433 434 // current viewleaf 435 r_oldviewleaf = r_viewleaf; 436 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); 437 438 r_dowarpold = r_dowarp; 439 r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER); 440 441 if ((r_dowarp != r_dowarpold) || r_viewchanged || lcd_x.value) 442 { 443 if (r_dowarp) 444 { 445 if ((vid.width <= vid.maxwarpwidth) && 446 (vid.height <= vid.maxwarpheight)) 447 { 448 vrect.x = 0; 449 vrect.y = 0; 450 vrect.width = vid.width; 451 vrect.height = vid.height; 452 453 R_ViewChanged (&vrect, sb_lines, vid.aspect); 454 } 455 else 456 { 457 w = vid.width; 458 h = vid.height; 459 460 if (w > vid.maxwarpwidth) 461 { 462 h *= (float)vid.maxwarpwidth / w; 463 w = vid.maxwarpwidth; 464 } 465 466 if (h > vid.maxwarpheight) 467 { 468 h = vid.maxwarpheight; 469 w *= (float)vid.maxwarpheight / h; 470 } 471 472 vrect.x = 0; 473 vrect.y = 0; 474 vrect.width = (int)w; 475 vrect.height = (int)h; 476 477 R_ViewChanged (&vrect, 478 (int)((float)sb_lines * (h/(float)vid.height)), 479 vid.aspect * (h / w) * 480 ((float)vid.width / (float)vid.height)); 481 } 482 } 483 else 484 { 485 vrect.x = 0; 486 vrect.y = 0; 487 vrect.width = vid.width; 488 vrect.height = vid.height; 489 490 R_ViewChanged (&vrect, sb_lines, vid.aspect); 491 } 492 493 r_viewchanged = false; 494 } 495 496 // start off with just the four screen edge clip planes 497 R_TransformFrustum (); 498 499 // save base values 500 VectorCopy (vpn, base_vpn); 501 VectorCopy (vright, base_vright); 502 VectorCopy (vup, base_vup); 503 VectorCopy (modelorg, base_modelorg); 504 505 R_SetSkyFrame (); 506 507 R_SetUpFrustumIndexes (); 508 509 r_cache_thrash = false; 510 511 // clear frame counts 512 c_faceclip = 0; 513 d_spanpixcount = 0; 514 r_polycount = 0; 515 r_drawnpolycount = 0; 516 r_wholepolycount = 0; 517 r_amodels_drawn = 0; 518 r_outofsurfaces = 0; 519 r_outofedges = 0; 520 521 D_SetupFrame (); 522 } 523 524