r_main.c
1 // 2 // Copyright(C) 1993-1996 Id Software, Inc. 3 // Copyright(C) 2005-2014 Simon Howard 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program 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 // 15 // DESCRIPTION: 16 // Rendering main loop and setup functions, 17 // utility functions (BSP, geometry, trigonometry). 18 // See tables.c, too. 19 // 20 21 22 23 24 25 #include <stdlib.h> 26 #include <math.h> 27 28 29 #include "doomdef.h" 30 #include "d_loop.h" 31 32 #include "m_bbox.h" 33 #include "m_menu.h" 34 35 #include "r_local.h" 36 #include "r_sky.h" 37 38 39 40 41 42 // Fineangles in the SCREENWIDTH wide window. 43 #define FIELDOFVIEW 2048 44 45 46 47 int viewangleoffset; 48 49 // increment every time a check is made 50 int validcount = 1; 51 52 53 lighttable_t* fixedcolormap; 54 extern lighttable_t** walllights; 55 56 int centerx; 57 int centery; 58 59 fixed_t centerxfrac; 60 fixed_t centeryfrac; 61 fixed_t projection; 62 63 // just for profiling purposes 64 int framecount; 65 66 int sscount; 67 int linecount; 68 int loopcount; 69 70 fixed_t viewx; 71 fixed_t viewy; 72 fixed_t viewz; 73 74 angle_t viewangle; 75 76 fixed_t viewcos; 77 fixed_t viewsin; 78 79 player_t* viewplayer; 80 81 // 0 = high, 1 = low 82 int detailshift; 83 84 // 85 // precalculated math tables 86 // 87 angle_t clipangle; 88 89 // The viewangletox[viewangle + FINEANGLES/4] lookup 90 // maps the visible view angles to screen X coordinates, 91 // flattening the arc to a flat projection plane. 92 // There will be many angles mapped to the same X. 93 int * viewangletox = NULL; 94 95 // The xtoviewangleangle[] table maps a screen pixel 96 // to the lowest viewangle that maps back to x ranges 97 // from clipangle to -clipangle. 98 angle_t * xtoviewangle = NULL; 99 100 101 lighttable_t* scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; 102 lighttable_t* scalelightfixed[MAXLIGHTSCALE]; 103 lighttable_t* zlight[LIGHTLEVELS][MAXLIGHTZ]; 104 105 // bumped light from gun blasts 106 int extralight; 107 108 109 110 void (*colfunc) (void); 111 void (*basecolfunc) (void); 112 void (*fuzzcolfunc) (void); 113 void (*transcolfunc) (void); 114 void (*spanfunc) (void); 115 116 117 118 // 119 // R_AddPointToBox 120 // Expand a given bbox 121 // so that it encloses a given point. 122 // 123 void 124 R_AddPointToBox 125 ( int x, 126 int y, 127 fixed_t* box ) 128 { 129 if (x< box[BOXLEFT]) 130 box[BOXLEFT] = x; 131 if (x> box[BOXRIGHT]) 132 box[BOXRIGHT] = x; 133 if (y< box[BOXBOTTOM]) 134 box[BOXBOTTOM] = y; 135 if (y> box[BOXTOP]) 136 box[BOXTOP] = y; 137 } 138 139 140 // 141 // R_PointOnSide 142 // Traverse BSP (sub) tree, 143 // check point against partition plane. 144 // Returns side 0 (front) or 1 (back). 145 // 146 int 147 R_PointOnSide 148 ( fixed_t x, 149 fixed_t y, 150 node_t* node ) 151 { 152 fixed_t dx; 153 fixed_t dy; 154 fixed_t left; 155 fixed_t right; 156 157 if (!node->dx) 158 { 159 if (x <= node->x) 160 return node->dy > 0; 161 162 return node->dy < 0; 163 } 164 if (!node->dy) 165 { 166 if (y <= node->y) 167 return node->dx < 0; 168 169 return node->dx > 0; 170 } 171 172 dx = (x - node->x); 173 dy = (y - node->y); 174 175 // Try to quickly decide by looking at sign bits. 176 if ( (node->dy ^ node->dx ^ dx ^ dy)&0x80000000 ) 177 { 178 if ( (node->dy ^ dx) & 0x80000000 ) 179 { 180 // (left is negative) 181 return 1; 182 } 183 return 0; 184 } 185 186 left = FixedMul ( node->dy>>FRACBITS , dx ); 187 right = FixedMul ( dy , node->dx>>FRACBITS ); 188 189 if (right < left) 190 { 191 // front side 192 return 0; 193 } 194 // back side 195 return 1; 196 } 197 198 199 int 200 R_PointOnSegSide 201 ( fixed_t x, 202 fixed_t y, 203 seg_t* line ) 204 { 205 fixed_t lx; 206 fixed_t ly; 207 fixed_t ldx; 208 fixed_t ldy; 209 fixed_t dx; 210 fixed_t dy; 211 fixed_t left; 212 fixed_t right; 213 214 lx = line->v1->x; 215 ly = line->v1->y; 216 217 ldx = line->v2->x - lx; 218 ldy = line->v2->y - ly; 219 220 if (!ldx) 221 { 222 if (x <= lx) 223 return ldy > 0; 224 225 return ldy < 0; 226 } 227 if (!ldy) 228 { 229 if (y <= ly) 230 return ldx < 0; 231 232 return ldx > 0; 233 } 234 235 dx = (x - lx); 236 dy = (y - ly); 237 238 // Try to quickly decide by looking at sign bits. 239 if ( (ldy ^ ldx ^ dx ^ dy)&0x80000000 ) 240 { 241 if ( (ldy ^ dx) & 0x80000000 ) 242 { 243 // (left is negative) 244 return 1; 245 } 246 return 0; 247 } 248 249 left = FixedMul ( ldy>>FRACBITS , dx ); 250 right = FixedMul ( dy , ldx>>FRACBITS ); 251 252 if (right < left) 253 { 254 // front side 255 return 0; 256 } 257 // back side 258 return 1; 259 } 260 261 262 // 263 // R_PointToAngle 264 // To get a global angle from cartesian coordinates, 265 // the coordinates are flipped until they are in 266 // the first octant of the coordinate system, then 267 // the y (<=x) is scaled and divided by x to get a 268 // tangent (slope) value which is looked up in the 269 // tantoangle[] table. 270 271 // 272 273 274 275 276 angle_t 277 R_PointToAngle 278 ( fixed_t x, 279 fixed_t y ) 280 { 281 x -= viewx; 282 y -= viewy; 283 284 if ( (!x) && (!y) ) 285 return 0; 286 287 if (x>= 0) 288 { 289 // x >=0 290 if (y>= 0) 291 { 292 // y>= 0 293 294 if (x>y) 295 { 296 // octant 0 297 return tantoangle[ SlopeDiv(y,x)]; 298 } 299 else 300 { 301 // octant 1 302 return ANG90-1-tantoangle[ SlopeDiv(x,y)]; 303 } 304 } 305 else 306 { 307 // y<0 308 y = -y; 309 310 if (x>y) 311 { 312 // octant 8 313 return -tantoangle[SlopeDiv(y,x)]; 314 } 315 else 316 { 317 // octant 7 318 return ANG270+tantoangle[ SlopeDiv(x,y)]; 319 } 320 } 321 } 322 else 323 { 324 // x<0 325 x = -x; 326 327 if (y>= 0) 328 { 329 // y>= 0 330 if (x>y) 331 { 332 // octant 3 333 return ANG180-1-tantoangle[ SlopeDiv(y,x)]; 334 } 335 else 336 { 337 // octant 2 338 return ANG90+ tantoangle[ SlopeDiv(x,y)]; 339 } 340 } 341 else 342 { 343 // y<0 344 y = -y; 345 346 if (x>y) 347 { 348 // octant 4 349 return ANG180+tantoangle[ SlopeDiv(y,x)]; 350 } 351 else 352 { 353 // octant 5 354 return ANG270-1-tantoangle[ SlopeDiv(x,y)]; 355 } 356 } 357 } 358 return 0; 359 } 360 361 362 angle_t 363 R_PointToAngle2 364 ( fixed_t x1, 365 fixed_t y1, 366 fixed_t x2, 367 fixed_t y2 ) 368 { 369 viewx = x1; 370 viewy = y1; 371 372 return R_PointToAngle (x2, y2); 373 } 374 375 376 fixed_t 377 R_PointToDist 378 ( fixed_t x, 379 fixed_t y ) 380 { 381 int angle; 382 fixed_t dx; 383 fixed_t dy; 384 fixed_t temp; 385 fixed_t dist; 386 fixed_t frac; 387 388 dx = abs(x - viewx); 389 dy = abs(y - viewy); 390 391 if (dy>dx) 392 { 393 temp = dx; 394 dx = dy; 395 dy = temp; 396 } 397 398 // Fix crashes in udm1.wad 399 400 if (dx != 0) 401 { 402 frac = FixedDiv(dy, dx); 403 } 404 else 405 { 406 frac = 0; 407 } 408 409 angle = (tantoangle[frac>>DBITS]+ANG90) >> ANGLETOFINESHIFT; 410 411 // use as cosine 412 dist = FixedDiv (dx, finesine[angle] ); 413 414 return dist; 415 } 416 417 418 419 420 // 421 // R_InitPointToAngle 422 // 423 void R_InitPointToAngle (void) 424 { 425 // UNUSED - now getting from tables.c 426 #if 0 427 int i; 428 long t; 429 float f; 430 // 431 // slope (tangent) to angle lookup 432 // 433 for (i=0 ; i<=SLOPERANGE ; i++) 434 { 435 f = atan( (float)i/SLOPERANGE )/(3.141592657*2); 436 t = 0xffffffff*f; 437 tantoangle[i] = t; 438 } 439 #endif 440 } 441 442 443 // 444 // R_ScaleFromGlobalAngle 445 // Returns the texture mapping scale 446 // for the current line (horizontal span) 447 // at the given angle. 448 // rw_distance must be calculated first. 449 // 450 fixed_t R_ScaleFromGlobalAngle (angle_t visangle) 451 { 452 fixed_t scale; 453 angle_t anglea; 454 angle_t angleb; 455 int sinea; 456 int sineb; 457 fixed_t num; 458 int den; 459 460 // UNUSED 461 #if 0 462 { 463 fixed_t dist; 464 fixed_t z; 465 fixed_t sinv; 466 fixed_t cosv; 467 468 sinv = finesine[(visangle-rw_normalangle)>>ANGLETOFINESHIFT]; 469 dist = FixedDiv (rw_distance, sinv); 470 cosv = finecosine[(viewangle-visangle)>>ANGLETOFINESHIFT]; 471 z = abs(FixedMul (dist, cosv)); 472 scale = FixedDiv(projection, z); 473 return scale; 474 } 475 #endif 476 477 anglea = ANG90 + (visangle-viewangle); 478 angleb = ANG90 + (visangle-rw_normalangle); 479 480 // both sines are allways positive 481 sinea = finesine[anglea>>ANGLETOFINESHIFT]; 482 sineb = finesine[angleb>>ANGLETOFINESHIFT]; 483 num = FixedMul(projection,sineb)<<detailshift; 484 den = FixedMul(rw_distance,sinea); 485 486 if (den > num>>16) 487 { 488 scale = FixedDiv (num, den); 489 490 if (scale > 64*FRACUNIT) 491 scale = 64*FRACUNIT; 492 else if (scale < 256) 493 scale = 256; 494 } 495 else 496 scale = 64*FRACUNIT; 497 498 return scale; 499 } 500 501 502 503 // 504 // R_InitTables 505 // 506 void R_InitTables (void) 507 { 508 509 510 // UNUSED: now getting from tables.c 511 #if 0 512 int i; 513 float a; 514 float fv; 515 int t; 516 517 // viewangle tangent table 518 for (i=0 ; i<FINEANGLES/2 ; i++) 519 { 520 a = (i-FINEANGLES/4+0.5)*PI*2/FINEANGLES; 521 fv = FRACUNIT*tan (a); 522 t = fv; 523 finetangent[i] = t; 524 } 525 526 // finesine table 527 for (i=0 ; i<5*FINEANGLES/4 ; i++) 528 { 529 // OPTIMIZE: mirror... 530 a = (i+0.5)*PI*2/FINEANGLES; 531 t = FRACUNIT*sin (a); 532 finesine[i] = t; 533 } 534 #endif 535 536 } 537 538 539 540 // 541 // R_InitTextureMapping 542 // 543 void R_InitTextureMapping (void) 544 { 545 int i; 546 int x; 547 int t; 548 fixed_t focallength; 549 550 if (xtoviewangle == NULL) xtoviewangle = emu_Malloc(sizeof(angle_t)*(SCREENWIDTH+1)); 551 if (viewangletox == NULL) viewangletox = emu_Malloc(sizeof(int)*(FINEANGLES/2)); 552 553 // Use tangent table to generate viewangletox: 554 // viewangletox will give the next greatest x 555 // after the view angle. 556 // 557 // Calc focallength 558 // so FIELDOFVIEW angles covers SCREENWIDTH. 559 focallength = FixedDiv (centerxfrac, 560 finetangent[FINEANGLES/4+FIELDOFVIEW/2] ); 561 562 for (i=0 ; i<FINEANGLES/2 ; i++) 563 { 564 if (finetangent[i] > FRACUNIT*2) 565 t = -1; 566 else if (finetangent[i] < -FRACUNIT*2) 567 t = viewwidth+1; 568 else 569 { 570 t = FixedMul (finetangent[i], focallength); 571 t = (centerxfrac - t+FRACUNIT-1)>>FRACBITS; 572 573 if (t < -1) 574 t = -1; 575 else if (t>viewwidth+1) 576 t = viewwidth+1; 577 } 578 viewangletox[i] = t; 579 } 580 581 // Scan viewangletox[] to generate xtoviewangle[]: 582 // xtoviewangle will give the smallest view angle 583 // that maps to x. 584 for (x=0;x<=viewwidth;x++) 585 { 586 i = 0; 587 while (viewangletox[i]>x) 588 i++; 589 xtoviewangle[x] = (i<<ANGLETOFINESHIFT)-ANG90; 590 } 591 592 // Take out the fencepost cases from viewangletox. 593 for (i=0 ; i<FINEANGLES/2 ; i++) 594 { 595 t = FixedMul (finetangent[i], focallength); 596 t = centerx - t; 597 598 if (viewangletox[i] == -1) 599 viewangletox[i] = 0; 600 else if (viewangletox[i] == viewwidth+1) 601 viewangletox[i] = viewwidth; 602 } 603 604 clipangle = xtoviewangle[0]; 605 } 606 607 608 609 // 610 // R_InitLightTables 611 // Only inits the zlight table, 612 // because the scalelight table changes with view size. 613 // 614 #define DISTMAP 2 615 616 void R_InitLightTables (void) 617 { 618 int i; 619 int j; 620 int level; 621 int startmap; 622 int scale; 623 624 // Calculate the light levels to use 625 // for each level / distance combination. 626 for (i=0 ; i< LIGHTLEVELS ; i++) 627 { 628 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; 629 for (j=0 ; j<MAXLIGHTZ ; j++) 630 { 631 scale = FixedDiv ((SCREENWIDTH/2*FRACUNIT), (j+1)<<LIGHTZSHIFT); 632 scale >>= LIGHTSCALESHIFT; 633 level = startmap - scale/DISTMAP; 634 635 if (level < 0) 636 level = 0; 637 638 if (level >= NUMCOLORMAPS) 639 level = NUMCOLORMAPS-1; 640 641 zlight[i][j] = colormaps + level*256; 642 } 643 } 644 } 645 646 647 648 // 649 // R_SetViewSize 650 // Do not really change anything here, 651 // because it might be in the middle of a refresh. 652 // The change will take effect next refresh. 653 // 654 boolean setsizeneeded; 655 int setblocks; 656 int setdetail; 657 658 659 void 660 R_SetViewSize 661 ( int blocks, 662 int detail ) 663 { 664 setsizeneeded = true; 665 setblocks = blocks; 666 setdetail = detail; 667 } 668 669 670 // 671 // R_ExecuteSetViewSize 672 // 673 void R_ExecuteSetViewSize (void) 674 { 675 fixed_t cosadj; 676 fixed_t dy; 677 int i; 678 int j; 679 int level; 680 int startmap; 681 682 setsizeneeded = false; 683 684 if (setblocks == 11) 685 { 686 scaledviewwidth = SCREENWIDTH; 687 viewheight = SCREENHEIGHT; 688 } 689 else 690 { 691 scaledviewwidth = setblocks*32; 692 viewheight = (setblocks*168/10)&~7; 693 } 694 695 detailshift = setdetail; 696 viewwidth = scaledviewwidth>>detailshift; 697 698 centery = viewheight/2; 699 centerx = viewwidth/2; 700 centerxfrac = centerx<<FRACBITS; 701 centeryfrac = centery<<FRACBITS; 702 projection = centerxfrac; 703 704 if (!detailshift) 705 { 706 colfunc = basecolfunc = R_DrawColumn; 707 fuzzcolfunc = R_DrawFuzzColumn; 708 transcolfunc = R_DrawTranslatedColumn; 709 spanfunc = R_DrawSpan; 710 } 711 else 712 { 713 colfunc = basecolfunc = R_DrawColumnLow; 714 fuzzcolfunc = R_DrawFuzzColumnLow; 715 transcolfunc = R_DrawTranslatedColumnLow; 716 spanfunc = R_DrawSpanLow; 717 } 718 719 R_InitBuffer (scaledviewwidth, viewheight); 720 721 R_InitTextureMapping (); 722 723 // psprite scales 724 pspritescale = FRACUNIT*viewwidth/SCREENWIDTH; 725 pspriteiscale = FRACUNIT*SCREENWIDTH/viewwidth; 726 727 // thing clipping 728 for (i=0 ; i<viewwidth ; i++) 729 screenheightarray[i] = viewheight; 730 731 // planes 732 for (i=0 ; i<viewheight ; i++) 733 { 734 dy = ((i-viewheight/2)<<FRACBITS)+FRACUNIT/2; 735 dy = abs(dy); 736 yslope[i] = FixedDiv ( (viewwidth<<detailshift)/2*FRACUNIT, dy); 737 } 738 739 for (i=0 ; i<viewwidth ; i++) 740 { 741 cosadj = abs(finecosine[xtoviewangle[i]>>ANGLETOFINESHIFT]); 742 distscale[i] = FixedDiv (FRACUNIT,cosadj); 743 } 744 745 // Calculate the light levels to use 746 // for each level / scale combination. 747 for (i=0 ; i< LIGHTLEVELS ; i++) 748 { 749 startmap = ((LIGHTLEVELS-1-i)*2)*NUMCOLORMAPS/LIGHTLEVELS; 750 for (j=0 ; j<MAXLIGHTSCALE ; j++) 751 { 752 level = startmap - j*SCREENWIDTH/(viewwidth<<detailshift)/DISTMAP; 753 754 if (level < 0) 755 level = 0; 756 757 if (level >= NUMCOLORMAPS) 758 level = NUMCOLORMAPS-1; 759 760 scalelight[i][j] = colormaps + level*256; 761 } 762 } 763 } 764 765 766 767 // 768 // R_Init 769 // 770 771 772 773 void R_Init (void) 774 { 775 R_InitData (); 776 printf ("."); 777 R_InitPointToAngle (); 778 printf ("."); 779 R_InitTables (); 780 // viewwidth / viewheight / detailLevel are set by the defaults 781 printf ("."); 782 783 R_SetViewSize (screenblocks, detailLevel); 784 R_InitPlanes (); 785 printf ("."); 786 R_InitLightTables (); 787 printf ("."); 788 R_InitSkyMap (); 789 R_InitTranslationTables (); 790 printf ("."); 791 792 framecount = 0; 793 } 794 795 796 // 797 // R_PointInSubsector 798 // 799 subsector_t* 800 R_PointInSubsector 801 ( fixed_t x, 802 fixed_t y ) 803 { 804 node_t* node; 805 int side; 806 int nodenum; 807 808 // single subsector is a special case 809 if (!numnodes) 810 return subsectors; 811 812 nodenum = numnodes-1; 813 814 while (! (nodenum & NF_SUBSECTOR) ) 815 { 816 node = &nodes[nodenum]; 817 side = R_PointOnSide (x, y, node); 818 nodenum = node->children[side]; 819 } 820 821 return &subsectors[nodenum & ~NF_SUBSECTOR]; 822 } 823 824 825 826 // 827 // R_SetupFrame 828 // 829 void R_SetupFrame (player_t* player) 830 { 831 int i; 832 833 viewplayer = player; 834 viewx = player->mo->x; 835 viewy = player->mo->y; 836 viewangle = player->mo->angle + viewangleoffset; 837 extralight = player->extralight; 838 839 viewz = player->viewz; 840 841 viewsin = finesine[viewangle>>ANGLETOFINESHIFT]; 842 viewcos = finecosine[viewangle>>ANGLETOFINESHIFT]; 843 844 sscount = 0; 845 846 if (player->fixedcolormap) 847 { 848 fixedcolormap = 849 colormaps 850 + player->fixedcolormap*256*sizeof(lighttable_t); 851 852 walllights = scalelightfixed; 853 854 for (i=0 ; i<MAXLIGHTSCALE ; i++) 855 scalelightfixed[i] = fixedcolormap; 856 } 857 else 858 fixedcolormap = 0; 859 860 framecount++; 861 validcount++; 862 } 863 864 865 866 // 867 // R_RenderView 868 // 869 void R_RenderPlayerView (player_t* player) 870 { 871 R_SetupFrame (player); 872 873 // Clear buffers. 874 R_ClearClipSegs (); 875 R_ClearDrawSegs (); 876 R_ClearPlanes (); 877 R_ClearSprites (); 878 879 // check for new console commands. 880 NetUpdate (); 881 882 // The head node is the last node output. 883 R_RenderBSPNode (numnodes-1); 884 885 // Check for new console commands. 886 NetUpdate (); 887 888 R_DrawPlanes (); 889 890 // Check for new console commands. 891 NetUpdate (); 892 893 R_DrawMasked (); 894 895 // Check for new console commands. 896 NetUpdate (); 897 }