|
|
1.1 root 1: 1.1.1.2 ! root 2: //************************************************************************** ! 3: //** ! 4: //** r_plane.c : Heretic 2 : Raven Software, Corp. ! 5: //** ! 6: //** $RCSfile: r_plane.c,v $ ! 7: //** $Revision: 1.5 $ ! 8: //** $Date: 95/07/13 15:17:12 $ ! 9: //** $Author: cjr $ ! 10: //** ! 11: //************************************************************************** 1.1 root 12: 1.1.1.2 ! root 13: // HEADER FILES ------------------------------------------------------------ 1.1 root 14: 1.1.1.2 ! root 15: #include "h2def.h" ! 16: #include "r_local.h" 1.1 root 17: 1.1.1.2 ! root 18: // MACROS ------------------------------------------------------------------ 1.1 root 19: 1.1.1.2 ! root 20: // TYPES ------------------------------------------------------------------- 1.1 root 21: 1.1.1.2 ! root 22: // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- 1.1 root 23: 1.1.1.2 ! root 24: // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- ! 25: ! 26: // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- ! 27: ! 28: // EXTERNAL DATA DECLARATIONS ---------------------------------------------- ! 29: ! 30: extern fixed_t Sky1ScrollDelta; ! 31: extern fixed_t Sky2ScrollDelta; ! 32: ! 33: // PUBLIC DATA DEFINITIONS ------------------------------------------------- ! 34: ! 35: int Sky1Texture; ! 36: int Sky2Texture; ! 37: fixed_t Sky1ColumnOffset; ! 38: fixed_t Sky2ColumnOffset; ! 39: int skyflatnum; ! 40: int skytexturemid; ! 41: fixed_t skyiscale; ! 42: boolean DoubleSky; ! 43: planefunction_t floorfunc, ceilingfunc; ! 44: ! 45: // Opening ! 46: visplane_t visplanes[MAXVISPLANES], *lastvisplane; ! 47: visplane_t *floorplane, *ceilingplane; ! 48: short openings[MAXOPENINGS], *lastopening; ! 49: ! 50: // Clip values are the solid pixel bounding the range. ! 51: // floorclip start out SCREENHEIGHT 1.1 root 52: // ceilingclip starts out -1 1.1.1.2 ! root 53: short floorclip[SCREENWIDTH]; ! 54: short ceilingclip[SCREENWIDTH]; 1.1 root 55: 1.1.1.2 ! root 56: // spanstart holds the start of a plane span, initialized to 0 ! 57: int spanstart[SCREENHEIGHT]; ! 58: int spanstop[SCREENHEIGHT]; 1.1 root 59: 1.1.1.2 ! root 60: // Texture mapping ! 61: lighttable_t **planezlight; ! 62: fixed_t planeheight; ! 63: fixed_t yslope[SCREENHEIGHT]; ! 64: fixed_t distscale[SCREENWIDTH]; ! 65: fixed_t basexscale, baseyscale; ! 66: fixed_t cachedheight[SCREENHEIGHT]; ! 67: fixed_t cacheddistance[SCREENHEIGHT]; ! 68: fixed_t cachedxstep[SCREENHEIGHT]; ! 69: fixed_t cachedystep[SCREENHEIGHT]; ! 70: ! 71: // PRIVATE DATA DEFINITIONS ------------------------------------------------ 1.1 root 72: 1.1.1.2 ! root 73: // CODE -------------------------------------------------------------------- 1.1 root 74: 1.1.1.2 ! root 75: //========================================================================== ! 76: // ! 77: // R_InitSky ! 78: // ! 79: // Called at level load. ! 80: // ! 81: //========================================================================== 1.1 root 82: 1.1.1.2 ! root 83: void R_InitSky(int map) ! 84: { ! 85: Sky1Texture = P_GetMapSky1Texture(map); ! 86: Sky2Texture = P_GetMapSky2Texture(map); ! 87: Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map); ! 88: Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map); ! 89: Sky1ColumnOffset = 0; ! 90: Sky2ColumnOffset = 0; ! 91: DoubleSky = P_GetMapDoubleSky(map); ! 92: } 1.1 root 93: 1.1.1.2 ! root 94: //========================================================================== ! 95: // ! 96: // R_InitSkyMap ! 97: // ! 98: // Called whenever the view size changes. ! 99: // ! 100: //========================================================================== 1.1 root 101: 1.1.1.2 ! root 102: void R_InitSkyMap(void) 1.1 root 103: { 1.1.1.2 ! root 104: skyflatnum = R_FlatNumForName("F_SKY"); 1.1 root 105: skytexturemid = 200*FRACUNIT; 106: skyiscale = FRACUNIT; 107: } 108: 1.1.1.2 ! root 109: //========================================================================== ! 110: // ! 111: // R_InitPlanes ! 112: // ! 113: // Called at game startup. ! 114: // ! 115: //========================================================================== 1.1 root 116: 1.1.1.2 ! root 117: void R_InitPlanes(void) 1.1 root 118: { 119: } 120: 1.1.1.2 ! root 121: //========================================================================== ! 122: // ! 123: // R_MapPlane ! 124: // ! 125: // Globals used: planeheight, ds_source, basexscale, baseyscale, ! 126: // viewx, viewy. ! 127: // ! 128: //========================================================================== 1.1 root 129: 1.1.1.2 ! root 130: void R_MapPlane(int y, int x1, int x2) 1.1 root 131: { 1.1.1.2 ! root 132: angle_t angle; ! 133: fixed_t distance, length; ! 134: unsigned index; ! 135: 1.1 root 136: #ifdef RANGECHECK 1.1.1.2 ! root 137: if(x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned)y > viewheight) ! 138: { ! 139: I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); ! 140: } 1.1 root 141: #endif 142: 1.1.1.2 ! root 143: if(planeheight != cachedheight[y]) 1.1 root 144: { 145: cachedheight[y] = planeheight; 1.1.1.2 ! root 146: distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]); ! 147: ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale); ! 148: ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale); 1.1 root 149: } 150: else 151: { 152: distance = cacheddistance[y]; 153: ds_xstep = cachedxstep[y]; 154: ds_ystep = cachedystep[y]; 155: } 156: 1.1.1.2 ! root 157: length = FixedMul(distance, distscale[x1]); ! 158: angle = (viewangle+xtoviewangle[x1])>>ANGLETOFINESHIFT; ! 159: ds_xfrac = viewx+FixedMul(finecosine[angle], length); ! 160: ds_yfrac = -viewy-FixedMul(finesine[angle], length); 1.1 root 161: 1.1.1.2 ! root 162: if(fixedcolormap) ! 163: { 1.1 root 164: ds_colormap = fixedcolormap; 1.1.1.2 ! root 165: } 1.1 root 166: else 167: { 168: index = distance >> LIGHTZSHIFT; 1.1.1.2 ! root 169: if(index >= MAXLIGHTZ ) ! 170: { 1.1 root 171: index = MAXLIGHTZ-1; 1.1.1.2 ! root 172: } 1.1 root 173: ds_colormap = planezlight[index]; 174: } 1.1.1.2 ! root 175: 1.1 root 176: ds_y = y; 177: ds_x1 = x1; 178: ds_x2 = x2; 179: 1.1.1.2 ! root 180: spanfunc(); // High or low detail ! 181: } 1.1 root 182: 1.1.1.2 ! root 183: //========================================================================== ! 184: // ! 185: // R_ClearPlanes ! 186: // ! 187: // Called at the beginning of each frame. ! 188: // ! 189: //========================================================================== 1.1 root 190: 1.1.1.2 ! root 191: void R_ClearPlanes(void) 1.1 root 192: { 1.1.1.2 ! root 193: int i; ! 194: angle_t angle; ! 195: ! 196: // Opening / clipping determination ! 197: for(i = 0; i < viewwidth; i++) 1.1 root 198: { 199: floorclip[i] = viewheight; 200: ceilingclip[i] = -1; 201: } 202: 203: lastvisplane = visplanes; 204: lastopening = openings; 205: 1.1.1.2 ! root 206: // Texture calculation ! 207: memset(cachedheight, 0, sizeof(cachedheight)); ! 208: angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; // left to right mapping ! 209: // Scale will be unit scale at SCREENWIDTH/2 distance ! 210: basexscale = FixedDiv(finecosine[angle], centerxfrac); ! 211: baseyscale = -FixedDiv(finesine[angle], centerxfrac); ! 212: } 1.1 root 213: 1.1.1.2 ! root 214: //========================================================================== ! 215: // ! 216: // R_FindPlane ! 217: // ! 218: //========================================================================== 1.1 root 219: 220: visplane_t *R_FindPlane(fixed_t height, int picnum, 221: int lightlevel, int special) 222: { 223: visplane_t *check; 224: 1.1.1.2 ! root 225: if(special < 150) ! 226: { // Don't let low specials affect search ! 227: special = 0; ! 228: } ! 229: 1.1 root 230: if(picnum == skyflatnum) 1.1.1.2 ! root 231: { // All skies map together 1.1 root 232: height = 0; 233: lightlevel = 0; 234: } 235: 236: for(check = visplanes; check < lastvisplane; check++) 237: { 238: if(height == check->height 239: && picnum == check->picnum 240: && lightlevel == check->lightlevel 241: && special == check->special) 242: break; 243: } 244: 245: if(check < lastvisplane) 246: { 247: return(check); 248: } 249: 250: if(lastvisplane-visplanes == MAXVISPLANES) 251: { 252: I_Error("R_FindPlane: no more visplanes"); 253: } 254: 255: lastvisplane++; 256: check->height = height; 257: check->picnum = picnum; 258: check->lightlevel = lightlevel; 259: check->special = special; 260: check->minx = SCREENWIDTH; 261: check->maxx = -1; 1.1.1.2 ! root 262: memset(check->top, 0xff, sizeof(check->top)); 1.1 root 263: return(check); 264: } 265: 1.1.1.2 ! root 266: //========================================================================== ! 267: // ! 268: // R_CheckPlane ! 269: // ! 270: //========================================================================== 1.1 root 271: 1.1.1.2 ! root 272: visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) 1.1 root 273: { 1.1.1.2 ! root 274: int intrl, intrh; ! 275: int unionl, unionh; ! 276: int x; ! 277: ! 278: if(start < pl->minx) 1.1 root 279: { 280: intrl = pl->minx; 281: unionl = start; 282: } 283: else 284: { 285: unionl = pl->minx; 286: intrl = start; 287: } 1.1.1.2 ! root 288: if(stop > pl->maxx) 1.1 root 289: { 290: intrh = pl->maxx; 291: unionh = stop; 292: } 293: else 294: { 295: unionh = pl->maxx; 296: intrh = stop; 297: } 298: 1.1.1.2 ! root 299: for(x = intrl; x <= intrh; x++) ! 300: { ! 301: if(pl->top[x] != 0xff) ! 302: { 1.1 root 303: break; 1.1.1.2 ! root 304: } ! 305: } 1.1 root 306: 1.1.1.2 ! root 307: if(x > intrh) 1.1 root 308: { 309: pl->minx = unionl; 310: pl->maxx = unionh; 1.1.1.2 ! root 311: return pl; // use the same visplane 1.1 root 312: } 313: 1.1.1.2 ! root 314: // Make a new visplane 1.1 root 315: lastvisplane->height = pl->height; 316: lastvisplane->picnum = pl->picnum; 317: lastvisplane->lightlevel = pl->lightlevel; 318: lastvisplane->special = pl->special; 319: pl = lastvisplane++; 320: pl->minx = start; 321: pl->maxx = stop; 1.1.1.2 ! root 322: memset(pl->top, 0xff, sizeof(pl->top)); ! 323: 1.1 root 324: return pl; 325: } 326: 1.1.1.2 ! root 327: //========================================================================== ! 328: // ! 329: // R_MakeSpans ! 330: // ! 331: //========================================================================== 1.1 root 332: 1.1.1.2 ! root 333: void R_MakeSpans(int x, int t1, int b1, int t2, int b2) 1.1 root 334: { 1.1.1.2 ! root 335: while(t1 < t2 && t1 <= b1) 1.1 root 336: { 1.1.1.2 ! root 337: R_MapPlane(t1, spanstart[t1], x-1); 1.1 root 338: t1++; 339: } 1.1.1.2 ! root 340: while(b1 > b2 && b1 >= t1) 1.1 root 341: { 1.1.1.2 ! root 342: R_MapPlane(b1, spanstart[b1], x-1); 1.1 root 343: b1--; 344: } 1.1.1.2 ! root 345: while(t2 < t1 && t2 <= b2) 1.1 root 346: { 347: spanstart[t2] = x; 348: t2++; 349: } 1.1.1.2 ! root 350: while(b2 > b1 && b2 >= t2) 1.1 root 351: { 352: spanstart[b2] = x; 353: b2--; 354: } 355: } 356: 1.1.1.2 ! root 357: //========================================================================== ! 358: // ! 359: // R_DrawPlanes ! 360: // ! 361: //========================================================================== 1.1 root 362: 1.1.1.2 ! root 363: #define SKYTEXTUREMIDSHIFTED 200 1.1 root 364: 1.1.1.2 ! root 365: void R_DrawPlanes(void) 1.1 root 366: { 1.1.1.2 ! root 367: visplane_t *pl; ! 368: int light; ! 369: int x, stop; ! 370: int angle; 1.1 root 371: byte *tempSource; 1.1.1.2 ! root 372: byte *source; ! 373: byte *source2; 1.1 root 374: byte *dest; 375: int count; 1.1.1.2 ! root 376: int offset; ! 377: int skyTexture; ! 378: int offset2; ! 379: int skyTexture2; ! 380: int scrollOffset; ! 381: ! 382: extern byte *ylookup[MAXHEIGHT]; ! 383: extern int columnofs[MAXWIDTH]; 1.1 root 384: 385: #ifdef RANGECHECK 1.1.1.2 ! root 386: if(ds_p-drawsegs > MAXDRAWSEGS) ! 387: { ! 388: I_Error("R_DrawPlanes: drawsegs overflow (%i)", ds_p-drawsegs); ! 389: } ! 390: if(lastvisplane-visplanes > MAXVISPLANES) ! 391: { ! 392: I_Error("R_DrawPlanes: visplane overflow (%i)", ! 393: lastvisplane-visplanes); ! 394: } ! 395: if(lastopening-openings > MAXOPENINGS) ! 396: { ! 397: I_Error("R_DrawPlanes: opening overflow (%i)", ! 398: lastopening-openings); ! 399: } 1.1 root 400: #endif 401: 1.1.1.2 ! root 402: for(pl = visplanes; pl < lastvisplane; pl++) 1.1 root 403: { 1.1.1.2 ! root 404: if(pl->minx > pl->maxx) 1.1 root 405: { 1.1.1.2 ! root 406: continue; ! 407: } ! 408: if(pl->picnum == skyflatnum) ! 409: { // Sky flat ! 410: if(DoubleSky) ! 411: { // Render 2 layers, sky 1 in front ! 412: offset = Sky1ColumnOffset>>16; ! 413: skyTexture = texturetranslation[Sky1Texture]; ! 414: offset2 = Sky2ColumnOffset>>16; ! 415: skyTexture2 = texturetranslation[Sky2Texture]; ! 416: for(x = pl->minx; x <= pl->maxx; x++) 1.1 root 417: { 1.1.1.2 ! root 418: dc_yl = pl->top[x]; ! 419: dc_yh = pl->bottom[x]; ! 420: if(dc_yl <= dc_yh) 1.1 root 421: { 1.1.1.2 ! root 422: count = dc_yh-dc_yl; ! 423: if(count < 0) ! 424: { ! 425: return; ! 426: } ! 427: angle = (viewangle+xtoviewangle[x]) ! 428: >>ANGLETOSKYSHIFT; ! 429: source = R_GetColumn(skyTexture, angle+offset) ! 430: +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); ! 431: source2 = R_GetColumn(skyTexture2, angle+offset2) ! 432: +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); ! 433: dest = ylookup[dc_yl]+columnofs[x]; ! 434: do ! 435: { ! 436: if(*source) ! 437: { ! 438: *dest = *source++; ! 439: source2++; ! 440: } ! 441: else ! 442: { ! 443: *dest = *source2++; ! 444: source++; ! 445: } ! 446: dest += SCREENWIDTH; ! 447: } while(count--); ! 448: } 1.1 root 449: } 1.1.1.2 ! root 450: continue; // Next visplane ! 451: } ! 452: else ! 453: { // Render single layer ! 454: if(pl->special == 200) ! 455: { // Use sky 2 ! 456: offset = Sky2ColumnOffset>>16; ! 457: skyTexture = texturetranslation[Sky2Texture]; ! 458: } ! 459: else ! 460: { // Use sky 1 ! 461: offset = Sky1ColumnOffset>>16; ! 462: skyTexture = texturetranslation[Sky1Texture]; ! 463: } ! 464: for(x = pl->minx; x <= pl->maxx; x++) ! 465: { ! 466: dc_yl = pl->top[x]; ! 467: dc_yh = pl->bottom[x]; ! 468: if(dc_yl <= dc_yh) ! 469: { ! 470: count = dc_yh-dc_yl; ! 471: if(count < 0) ! 472: { ! 473: return; ! 474: } ! 475: angle = (viewangle+xtoviewangle[x]) ! 476: >>ANGLETOSKYSHIFT; ! 477: source = R_GetColumn(skyTexture, angle+offset) ! 478: +SKYTEXTUREMIDSHIFTED+(dc_yl-centery); ! 479: dest = ylookup[dc_yl]+columnofs[x]; ! 480: do ! 481: { ! 482: *dest = *source++; ! 483: dest += SCREENWIDTH; ! 484: } while(count--); ! 485: } ! 486: } ! 487: continue; // Next visplane 1.1 root 488: } 489: } 1.1.1.2 ! root 490: // Regular flat ! 491: tempSource = W_CacheLumpNum(firstflat+ 1.1 root 492: flattranslation[pl->picnum], PU_STATIC); 1.1.1.2 ! root 493: scrollOffset = leveltime>>1&63; 1.1 root 494: switch(pl->special) 1.1.1.2 ! root 495: { // Handle scrolling flats ! 496: case 201: case 202: case 203: // Scroll_North_xxx ! 497: ds_source = tempSource+((scrollOffset ! 498: <<(pl->special-201)&63)<<6); 1.1 root 499: break; 1.1.1.2 ! root 500: case 204: case 205: case 206: // Scroll_East_xxx ! 501: ds_source = tempSource+((63-scrollOffset) ! 502: <<(pl->special-204)&63); 1.1 root 503: break; 1.1.1.2 ! root 504: case 207: case 208: case 209: // Scroll_South_xxx ! 505: ds_source = tempSource+(((63-scrollOffset) ! 506: <<(pl->special-207)&63)<<6); 1.1 root 507: break; 1.1.1.2 ! root 508: case 210: case 211: case 212: // Scroll_West_xxx ! 509: ds_source = tempSource+(scrollOffset ! 510: <<(pl->special-210)&63); 1.1 root 511: break; 1.1.1.2 ! root 512: case 213: case 214: case 215: // Scroll_NorthWest_xxx ! 513: ds_source = tempSource+(scrollOffset ! 514: <<(pl->special-213)&63)+((scrollOffset ! 515: <<(pl->special-213)&63)<<6); ! 516: break; ! 517: case 216: case 217: case 218: // Scroll_NorthEast_xxx ! 518: ds_source = tempSource+((63-scrollOffset) ! 519: <<(pl->special-216)&63)+((scrollOffset ! 520: <<(pl->special-216)&63)<<6); ! 521: break; ! 522: case 219: case 220: case 221: // Scroll_SouthEast_xxx ! 523: ds_source = tempSource+((63-scrollOffset) ! 524: <<(pl->special-219)&63)+(((63-scrollOffset) ! 525: <<(pl->special-219)&63)<<6); ! 526: break; ! 527: case 222: case 223: case 224: // Scroll_SouthWest_xxx ! 528: ds_source = tempSource+(scrollOffset ! 529: <<(pl->special-222)&63)+(((63-scrollOffset) ! 530: <<(pl->special-222)&63)<<6); 1.1 root 531: break; 532: default: 533: ds_source = tempSource; 1.1.1.2 ! root 534: break; 1.1 root 535: } 536: planeheight = abs(pl->height-viewz); 537: light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight; 1.1.1.2 ! root 538: if(light >= LIGHTLEVELS) ! 539: { 1.1 root 540: light = LIGHTLEVELS-1; 1.1.1.2 ! root 541: } ! 542: if(light < 0) ! 543: { 1.1 root 544: light = 0; 1.1.1.2 ! root 545: } 1.1 root 546: planezlight = zlight[light]; 547: 548: pl->top[pl->maxx+1] = 0xff; 549: pl->top[pl->minx-1] = 0xff; 1.1.1.2 ! root 550: ! 551: stop = pl->maxx+1; ! 552: for(x = pl->minx; x <= stop; x++) ! 553: { ! 554: R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], ! 555: pl->top[x], pl->bottom[x]); ! 556: } ! 557: Z_ChangeTag(tempSource, PU_CACHE); 1.1 root 558: } 559: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.