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 #if 0 34 static float oldbright; 35 36 if (r_fullbright.value != oldbright) 37 { 38 oldbright = r_fullbright.value; 39 D_FlushCaches (); // so all lighting changes 40 } 41 #endif 42 } 43 44 45 /* 46 ============ 47 Show 48 49 Debugging use 50 ============ 51 */ 52 void Show (void) 53 { 54 vrect_t vr; 55 56 vr.x = vr.y = 0; 57 vr.width = vid.width; 58 vr.height = vid.height; 59 vr.pnext = NULL; 60 VID_Update (&vr); 61 } 62 63 /* 64 ==================== 65 R_TimeRefresh_f 66 67 For program optimization 68 ==================== 69 */ 70 void R_TimeRefresh_f (void) 71 { 72 int i; 73 float start, stop, time; 74 int startangle; 75 vrect_t vr; 76 77 startangle = r_refdef.viewangles[1]; 78 79 start = Sys_DoubleTime (); 80 for (i=0 ; i<128 ; i++) 81 { 82 r_refdef.viewangles[1] = i/128.0*360.0; 83 84 VID_LockBuffer (); 85 86 R_RenderView (); 87 88 VID_UnlockBuffer (); 89 90 vr.x = r_refdef.vrect.x; 91 vr.y = r_refdef.vrect.y; 92 vr.width = r_refdef.vrect.width; 93 vr.height = r_refdef.vrect.height; 94 vr.pnext = NULL; 95 VID_Update (&vr); 96 } 97 stop = Sys_DoubleTime (); 98 time = stop-start; 99 Con_Printf ("%f seconds (%f fps)\n", time, 128/time); 100 101 r_refdef.viewangles[1] = startangle; 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 int color; 117 118 // FIXME: should be disabled on no-buffer adapters, or should be in the driver 119 120 // x += r_refdef.vrect.x; 121 // y += r_refdef.vrect.y; 122 123 dest = vid.buffer + vid.rowbytes*y + x; 124 125 s = r_graphheight.value; 126 127 if (h == 10000) 128 color = 0x6f; // yellow 129 else if (h == 9999) 130 color = 0x4f; // red 131 else if (h == 9998) 132 color = 0xd0; // blue 133 else 134 color = 0xff; // pink 135 136 if (h>s) 137 h = s; 138 139 for (i=0 ; i<h ; i++, dest -= vid.rowbytes*2) 140 { 141 dest[0] = color; 142 // *(dest-vid.rowbytes) = 0x30; 143 } 144 #if 0 145 for ( ; i<s ; i++, dest -= vid.rowbytes*2) 146 { 147 dest[0] = 0x30; 148 *(dest-vid.rowbytes) = 0x30; 149 } 150 #endif 151 } 152 153 /* 154 ============== 155 R_TimeGraph 156 157 Performance monitoring tool 158 ============== 159 */ 160 #define MAX_TIMINGS 100 161 extern float mouse_x, mouse_y; 162 int graphval; 163 void R_TimeGraph (void) 164 { 165 static int timex; 166 int a; 167 float r_time2; 168 static byte r_timings[MAX_TIMINGS]; 169 int x; 170 171 r_time2 = Sys_DoubleTime (); 172 173 a = (r_time2-r_time1)/0.01; 174 //a = fabs(mouse_y * 0.05); 175 //a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight.value; 176 //a = (int)((pmove.velocity[2] + 500)/10); 177 //a = fabs(velocity[0])/20; 178 //a = ((int)fabs(origin[0])/8)%20; 179 //a = (cl.idealpitch + 30)/5; 180 //a = (int)(cl.simangles[YAW] * 64/360) & 63; 181 a = graphval; 182 183 r_timings[timex] = a; 184 a = timex; 185 186 if (r_refdef.vrect.width <= MAX_TIMINGS) 187 x = r_refdef.vrect.width-1; 188 else 189 x = r_refdef.vrect.width - 190 (r_refdef.vrect.width - MAX_TIMINGS)/2; 191 do 192 { 193 R_LineGraph (x, r_refdef.vrect.height-2, r_timings[a]); 194 if (x==0) 195 break; // screen too small to hold entire thing 196 x--; 197 a--; 198 if (a == -1) 199 a = MAX_TIMINGS-1; 200 } while (a != timex); 201 202 timex = (timex+1)%MAX_TIMINGS; 203 } 204 205 /* 206 ============== 207 R_NetGraph 208 ============== 209 */ 210 void R_NetGraph (void) 211 { 212 int a, x, y, y2, w, i; 213 frame_t *frame; 214 int lost; 215 char st[80]; 216 217 if (vid.width - 16 <= NET_TIMINGS) 218 w = vid.width - 16; 219 else 220 w = NET_TIMINGS; 221 222 x = -((vid.width - 320)>>1); 223 y = vid.height - sb_lines - 24 - (int)r_graphheight.value*2 - 2; 224 225 M_DrawTextBox (x, y, (w+7)/8, ((int)r_graphheight.value*2+7)/8 + 1); 226 y2 = y + 8; 227 y = vid.height - sb_lines - 8 - 2; 228 229 x = 8; 230 lost = CL_CalcNet(); 231 for (a=NET_TIMINGS-w ; a<w ; a++) 232 { 233 i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK; 234 R_LineGraph (x+w-1-a, y, packet_latency[i]); 235 } 236 sprintf(st, "%3i%% packet loss", lost); 237 Draw_String(8, y2, st); 238 } 239 240 /* 241 ============== 242 R_ZGraph 243 ============== 244 */ 245 void R_ZGraph (void) 246 { 247 int a, x, w, i; 248 static int height[256]; 249 250 if (r_refdef.vrect.width <= 256) 251 w = r_refdef.vrect.width; 252 else 253 w = 256; 254 255 height[r_framecount&255] = ((int)r_origin[2]) & 31; 256 257 x = 0; 258 for (a=0 ; a<w ; a++) 259 { 260 i = (r_framecount-a) & 255; 261 R_LineGraph (x+w-1-a, r_refdef.vrect.height-2, height[i]); 262 } 263 } 264 265 /* 266 ============= 267 R_PrintTimes 268 ============= 269 */ 270 void R_PrintTimes (void) 271 { 272 float r_time2; 273 float ms; 274 275 r_time2 = Sys_DoubleTime (); 276 277 ms = 1000* (r_time2 - r_time1); 278 279 Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n", 280 ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf); 281 c_surf = 0; 282 } 283 284 285 /* 286 ============= 287 R_PrintDSpeeds 288 ============= 289 */ 290 void R_PrintDSpeeds (void) 291 { 292 float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, dv_time; 293 294 r_time2 = Sys_DoubleTime (); 295 296 dp_time = (dp_time2 - dp_time1) * 1000; 297 rw_time = (rw_time2 - rw_time1) * 1000; 298 db_time = (db_time2 - db_time1) * 1000; 299 se_time = (se_time2 - se_time1) * 1000; 300 de_time = (de_time2 - de_time1) * 1000; 301 dv_time = (dv_time2 - dv_time1) * 1000; 302 ms = (r_time2 - r_time1) * 1000; 303 304 Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n", 305 (int)ms, dp_time, (int)rw_time, db_time, (int)se_time, de_time, 306 dv_time); 307 } 308 309 310 /* 311 ============= 312 R_PrintAliasStats 313 ============= 314 */ 315 void R_PrintAliasStats (void) 316 { 317 Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn); 318 } 319 320 321 void WarpPalette (void) 322 { 323 int i,j; 324 byte newpalette[768]; 325 int basecolor[3]; 326 327 basecolor[0] = 130; 328 basecolor[1] = 80; 329 basecolor[2] = 50; 330 331 // pull the colors halfway to bright brown 332 for (i=0 ; i<256 ; i++) 333 { 334 for (j=0 ; j<3 ; j++) 335 { 336 newpalette[i*3+j] = (host_basepal[i*3+j] + basecolor[j])/2; 337 } 338 } 339 340 VID_ShiftPalette (newpalette); 341 } 342 343 344 /* 345 =================== 346 R_TransformFrustum 347 =================== 348 */ 349 void R_TransformFrustum (void) 350 { 351 int i; 352 vec3_t v, v2; 353 354 for (i=0 ; i<4 ; i++) 355 { 356 v[0] = screenedge[i].normal[2]; 357 v[1] = -screenedge[i].normal[0]; 358 v[2] = screenedge[i].normal[1]; 359 360 v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0]; 361 v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1]; 362 v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2]; 363 364 VectorCopy (v2, view_clipplanes[i].normal); 365 366 view_clipplanes[i].dist = DotProduct (modelorg, v2); 367 } 368 } 369 370 371 #if !id386 372 373 /* 374 ================ 375 TransformVector 376 ================ 377 */ 378 void TransformVector (vec3_t in, vec3_t out) 379 { 380 out[0] = DotProduct(in,vright); 381 out[1] = DotProduct(in,vup); 382 out[2] = DotProduct(in,vpn); 383 } 384 385 #endif 386 387 388 /* 389 ================ 390 R_TransformPlane 391 ================ 392 */ 393 void R_TransformPlane (mplane_t *p, float *normal, float *dist) 394 { 395 float d; 396 397 d = DotProduct (r_origin, p->normal); 398 *dist = p->dist - d; 399 // TODO: when we have rotating entities, this will need to use the view matrix 400 TransformVector (p->normal, normal); 401 } 402 403 404 /* 405 =============== 406 R_SetUpFrustumIndexes 407 =============== 408 */ 409 void R_SetUpFrustumIndexes (void) 410 { 411 int i, j, *pindex; 412 413 pindex = r_frustum_indexes; 414 415 for (i=0 ; i<4 ; i++) 416 { 417 for (j=0 ; j<3 ; j++) 418 { 419 if (view_clipplanes[i].normal[j] < 0) 420 { 421 pindex[j] = j; 422 pindex[j+3] = j+3; 423 } 424 else 425 { 426 pindex[j] = j+3; 427 pindex[j+3] = j; 428 } 429 } 430 431 // FIXME: do just once at start 432 pfrustum_indexes[i] = pindex; 433 pindex += 6; 434 } 435 } 436 437 438 /* 439 =============== 440 R_SetupFrame 441 =============== 442 */ 443 void R_SetupFrame (void) 444 { 445 int edgecount; 446 vrect_t vrect; 447 float w, h; 448 449 // don't allow cheats in multiplayer 450 r_draworder.value = 0; 451 r_fullbright.value = 0; 452 r_ambient.value = 0; 453 r_drawflat.value = 0; 454 455 if (r_numsurfs.value) 456 { 457 if ((surface_p - surfaces) > r_maxsurfsseen) 458 r_maxsurfsseen = surface_p - surfaces; 459 460 Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces, 461 surf_max - surfaces, r_maxsurfsseen); 462 } 463 464 if (r_numedges.value) 465 { 466 edgecount = edge_p - r_edges; 467 468 if (edgecount > r_maxedgesseen) 469 r_maxedgesseen = edgecount; 470 471 Con_Printf ("Used %d of %d edges; %d max\n", edgecount, 472 r_numallocatededges, r_maxedgesseen); 473 } 474 475 r_refdef.ambientlight = r_ambient.value; 476 477 if (r_refdef.ambientlight < 0) 478 r_refdef.ambientlight = 0; 479 480 // if (!sv.active) 481 r_draworder.value = 0; // don't let cheaters look behind walls 482 483 R_CheckVariables (); 484 485 R_AnimateLight (); 486 487 r_framecount++; 488 489 numbtofpolys = 0; 490 491 // debugging 492 #if 0 493 r_refdef.vieworg[0]= 80; 494 r_refdef.vieworg[1]= 64; 495 r_refdef.vieworg[2]= 40; 496 r_refdef.viewangles[0]= 0; 497 r_refdef.viewangles[1]= 46.763641357; 498 r_refdef.viewangles[2]= 0; 499 #endif 500 501 // build the transformation matrix for the given view angles 502 VectorCopy (r_refdef.vieworg, modelorg); 503 VectorCopy (r_refdef.vieworg, r_origin); 504 505 AngleVectors (r_refdef.viewangles, vpn, vright, vup); 506 507 // current viewleaf 508 r_oldviewleaf = r_viewleaf; 509 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); 510 511 r_dowarpold = r_dowarp; 512 r_dowarp = r_waterwarp.value && (r_viewleaf->contents <= CONTENTS_WATER); 513 514 if ((r_dowarp != r_dowarpold) || r_viewchanged) 515 { 516 if (r_dowarp) 517 { 518 if ((vid.width <= vid.maxwarpwidth) && 519 (vid.height <= vid.maxwarpheight)) 520 { 521 vrect.x = 0; 522 vrect.y = 0; 523 vrect.width = vid.width; 524 vrect.height = vid.height; 525 526 R_ViewChanged (&vrect, sb_lines, vid.aspect); 527 } 528 else 529 { 530 w = vid.width; 531 h = vid.height; 532 533 if (w > vid.maxwarpwidth) 534 { 535 h *= (float)vid.maxwarpwidth / w; 536 w = vid.maxwarpwidth; 537 } 538 539 if (h > vid.maxwarpheight) 540 { 541 h = vid.maxwarpheight; 542 w *= (float)vid.maxwarpheight / h; 543 } 544 545 vrect.x = 0; 546 vrect.y = 0; 547 vrect.width = (int)w; 548 vrect.height = (int)h; 549 550 R_ViewChanged (&vrect, 551 (int)((float)sb_lines * (h/(float)vid.height)), 552 vid.aspect * (h / w) * 553 ((float)vid.width / (float)vid.height)); 554 } 555 } 556 else 557 { 558 vrect.x = 0; 559 vrect.y = 0; 560 vrect.width = vid.width; 561 vrect.height = vid.height; 562 563 R_ViewChanged (&vrect, sb_lines, vid.aspect); 564 } 565 566 r_viewchanged = false; 567 } 568 569 // start off with just the four screen edge clip planes 570 R_TransformFrustum (); 571 572 // save base values 573 VectorCopy (vpn, base_vpn); 574 VectorCopy (vright, base_vright); 575 VectorCopy (vup, base_vup); 576 VectorCopy (modelorg, base_modelorg); 577 578 R_SetSkyFrame (); 579 580 R_SetUpFrustumIndexes (); 581 582 r_cache_thrash = false; 583 584 // clear frame counts 585 c_faceclip = 0; 586 d_spanpixcount = 0; 587 r_polycount = 0; 588 r_drawnpolycount = 0; 589 r_wholepolycount = 0; 590 r_amodels_drawn = 0; 591 r_outofsurfaces = 0; 592 r_outofedges = 0; 593 594 D_SetupFrame (); 595 } 596 597