|
|
1.1 root 1: 1.1.1.2 ! root 2: //************************************************************************** ! 3: //** ! 4: //** r_bsp.c : Heretic 2 : Raven Software, Corp. ! 5: //** ! 6: //** $RCSfile: r_bsp.c,v $ ! 7: //** $Revision: 1.2 $ ! 8: //** $Date: 95/07/13 15:17:10 $ ! 9: //** $Author: cjr $ ! 10: //** ! 11: //************************************************************************** ! 12: ! 13: #include "h2def.h" ! 14: #include "r_local.h" ! 15: ! 16: seg_t *curline; ! 17: side_t *sidedef; ! 18: line_t *linedef; ! 19: sector_t *frontsector, *backsector; 1.1 root 20: 1.1.1.2 ! root 21: drawseg_t drawsegs[MAXDRAWSEGS], *ds_p; 1.1 root 22: 23: void R_StoreWallRange (int start, int stop); 24: 25: /* 26: ==================== 27: = 28: = R_ClearDrawSegs 29: = 30: ==================== 31: */ 32: 33: void R_ClearDrawSegs (void) 34: { 35: ds_p = drawsegs; 36: } 37: 38: //============================================================================= 39: 40: 41: /* 42: =============================================================================== 43: = 44: = ClipWallSegment 45: = 46: = Clips the given range of columns and includes it in the new clip list 47: =============================================================================== 48: */ 49: 1.1.1.2 ! root 50: typedef struct 1.1 root 51: { 1.1.1.2 ! root 52: int first, last; 1.1 root 53: } cliprange_t; 54: 1.1.1.2 ! root 55: #define MAXSEGS 32 1.1 root 56: 1.1.1.2 ! root 57: cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg 1.1 root 58: 59: 60: void R_ClipSolidWallSegment (int first, int last) 61: { 1.1.1.2 ! root 62: cliprange_t *next, *start; 1.1 root 63: 64: // find the first range that touches the range (adjacent pixels are touching) 65: start = solidsegs; 66: while (start->last < first-1) 67: start++; 68: 69: if (first < start->first) 70: { 71: if (last < start->first-1) 1.1.1.2 ! root 72: { // post is entirely visible (above start), so insert a new clippost 1.1 root 73: R_StoreWallRange (first, last); 74: next = newend; 75: newend++; 76: while (next != start) 77: { 78: *next = *(next-1); 79: next--; 80: } 81: next->first = first; 82: next->last = last; 83: return; 84: } 1.1.1.2 ! root 85: 1.1 root 86: // there is a fragment above *start 87: R_StoreWallRange (first, start->first - 1); 1.1.1.2 ! root 88: start->first = first; // adjust the clip size 1.1 root 89: } 1.1.1.2 ! root 90: 1.1 root 91: if (last <= start->last) 1.1.1.2 ! root 92: return; // bottom contained in start ! 93: 1.1 root 94: next = start; 95: while (last >= (next+1)->first-1) 96: { 97: // there is a fragment between two posts 98: R_StoreWallRange (next->last + 1, (next+1)->first - 1); 99: next++; 100: if (last <= next->last) 1.1.1.2 ! root 101: { // bottom is contained in next ! 102: start->last = next->last; // adjust the clip size 1.1 root 103: goto crunch; 104: } 105: } 1.1.1.2 ! root 106: 1.1 root 107: // there is a fragment after *next 108: R_StoreWallRange (next->last + 1, last); 1.1.1.2 ! root 109: start->last = last; // adjust the clip size ! 110: ! 111: 1.1 root 112: // remove start+1 to next from the clip list, 113: // because start now covers their area 114: crunch: 115: if (next == start) 1.1.1.2 ! root 116: return; // post just extended past the bottom of one post 1.1 root 117: 1.1.1.2 ! root 118: while (next++ != newend) // remove a post 1.1 root 119: *++start = *next; 120: newend = start+1; 121: } 122: 123: /* 124: =============================================================================== 125: = 126: = R_ClipPassWallSegment 127: = 128: = Clips the given range of columns, but does not includes it in the clip list 129: =============================================================================== 130: */ 131: 132: void R_ClipPassWallSegment (int first, int last) 133: { 1.1.1.2 ! root 134: cliprange_t *start; 1.1 root 135: 136: // find the first range that touches the range (adjacent pixels are touching) 137: start = solidsegs; 138: while (start->last < first-1) 139: start++; 140: 141: if (first < start->first) 142: { 143: if (last < start->first-1) 1.1.1.2 ! root 144: { // post is entirely visible (above start) 1.1 root 145: R_StoreWallRange (first, last); 146: return; 147: } 1.1.1.2 ! root 148: 1.1 root 149: // there is a fragment above *start 150: R_StoreWallRange (first, start->first - 1); 151: } 1.1.1.2 ! root 152: 1.1 root 153: if (last <= start->last) 1.1.1.2 ! root 154: return; // bottom contained in start ! 155: 1.1 root 156: while (last >= (start+1)->first-1) 157: { 158: // there is a fragment between two posts 159: R_StoreWallRange (start->last + 1, (start+1)->first - 1); 160: start++; 161: if (last <= start->last) 162: return; 163: } 1.1.1.2 ! root 164: 1.1 root 165: // there is a fragment after *next 166: R_StoreWallRange (start->last + 1, last); 167: } 168: 169: 170: 171: /* 172: ==================== 173: = 174: = R_ClearClipSegs 175: = 176: ==================== 177: */ 178: 179: void R_ClearClipSegs (void) 180: { 181: solidsegs[0].first = -0x7fffffff; 182: solidsegs[0].last = -1; 183: solidsegs[1].first = viewwidth; 184: solidsegs[1].last = 0x7fffffff; 185: newend = solidsegs+2; 186: } 187: 188: 189: //============================================================================= 190: 191: /* 192: ====================== 193: = 194: = R_AddLine 195: = 196: = Clips the given segment and adds any visible pieces to the line list 197: = 198: ====================== 199: */ 200: 201: void R_AddLine (seg_t *line) 202: { 1.1.1.2 ! root 203: int x1, x2; ! 204: angle_t angle1, angle2, span, tspan; ! 205: 1.1 root 206: #ifdef __NeXT__ 207: RD_DrawLineCheck (line); 1.1.1.2 ! root 208: #endif 1.1 root 209: curline = line; 210: 211: // OPTIMIZE: quickly reject orthogonal back sides 212: 213: angle1 = R_PointToAngle (line->v1->x, line->v1->y); 214: angle2 = R_PointToAngle (line->v2->x, line->v2->y); 215: 216: // 217: // clip to view edges 218: // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW) 219: span = angle1 - angle2; 220: if (span >= ANG180) 1.1.1.2 ! root 221: return; // back side 1.1 root 222: 1.1.1.2 ! root 223: rw_angle1 = angle1; // global angle needed by segcalc 1.1 root 224: angle1 -= viewangle; 225: angle2 -= viewangle; 1.1.1.2 ! root 226: 1.1 root 227: tspan = angle1 + clipangle; 228: if (tspan > 2*clipangle) 229: { 230: tspan -= 2*clipangle; 231: if (tspan >= span) 1.1.1.2 ! root 232: return; // totally off the left edge 1.1 root 233: angle1 = clipangle; 234: } 235: tspan = clipangle - angle2; 236: if (tspan > 2*clipangle) 237: { 238: tspan -= 2*clipangle; 239: if (tspan >= span) 1.1.1.2 ! root 240: return; // totally off the left edge 1.1 root 241: angle2 = -clipangle; 242: } 243: 244: // 245: // the seg is in the view range, but not necessarily visible 246: // 247: angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; 248: angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; 249: x1 = viewangletox[angle1]; 250: x2 = viewangletox[angle2]; 251: if (x1 == x2) 1.1.1.2 ! root 252: return; // does not cross a pixel ! 253: 1.1 root 254: backsector = line->backsector; 255: 256: if (!backsector) 1.1.1.2 ! root 257: goto clipsolid; // single sided line ! 258: 1.1 root 259: if (backsector->ceilingheight <= frontsector->floorheight 260: || backsector->floorheight >= frontsector->ceilingheight) 1.1.1.2 ! root 261: goto clipsolid; // closed door ! 262: 1.1 root 263: if (backsector->ceilingheight != frontsector->ceilingheight 264: || backsector->floorheight != frontsector->floorheight) 1.1.1.2 ! root 265: goto clippass; // window ! 266: 1.1 root 267: // reject empty lines used for triggers and special events 268: if (backsector->ceilingpic == frontsector->ceilingpic 269: && backsector->floorpic == frontsector->floorpic 270: && backsector->lightlevel == frontsector->lightlevel 1.1.1.2 ! root 271: && backsector->special == frontsector->special 1.1 root 272: && curline->sidedef->midtexture == 0) 1.1.1.2 ! root 273: return; ! 274: 1.1 root 275: clippass: 1.1.1.2 ! root 276: R_ClipPassWallSegment (x1, x2-1); 1.1 root 277: return; 1.1.1.2 ! root 278: 1.1 root 279: clipsolid: 280: R_ClipSolidWallSegment (x1, x2-1); 281: } 282: 283: //============================================================================ 284: 285: 286: /* 287: =============================================================================== 288: = 289: = R_CheckBBox 290: = 291: = Returns true if some part of the bbox might be visible 292: = 293: =============================================================================== 294: */ 295: 1.1.1.2 ! root 296: int checkcoord[12][4] = { 1.1 root 297: {3,0, 2,1}, 298: {3,0, 2,0}, 299: {3,1, 2,0}, 300: {0}, 301: {2,0, 2,1}, 302: {0,0,0,0}, 303: {3,1, 3,0}, 304: {0}, 305: {2,0, 3,1}, 306: {2,1, 3,1}, 307: {2,1, 3,0} }; 308: 309: 310: boolean R_CheckBBox (fixed_t *bspcoord) 311: { 1.1.1.2 ! root 312: int boxx, boxy, boxpos; ! 313: fixed_t x1, y1, x2, y2; ! 314: angle_t angle1, angle2, span, tspan; ! 315: cliprange_t *start; ! 316: int sx1, sx2; ! 317: 1.1 root 318: #ifdef __NeXT__ 319: RD_DrawBBox (bspcoord); 320: #endif 321: 322: // find the corners of the box that define the edges from current viewpoint 323: if (viewx <= bspcoord[BOXLEFT]) 324: boxx = 0; 325: else if (viewx < bspcoord[BOXRIGHT]) 326: boxx = 1; 327: else 328: boxx = 2; 1.1.1.2 ! root 329: 1.1 root 330: if (viewy >= bspcoord[BOXTOP]) 331: boxy = 0; 332: else if (viewy > bspcoord[BOXBOTTOM]) 333: boxy = 1; 334: else 335: boxy = 2; 1.1.1.2 ! root 336: 1.1 root 337: boxpos = (boxy<<2)+boxx; 338: if (boxpos == 5) 339: return true; 1.1.1.2 ! root 340: 1.1 root 341: x1 = bspcoord[checkcoord[boxpos][0]]; 342: y1 = bspcoord[checkcoord[boxpos][1]]; 343: x2 = bspcoord[checkcoord[boxpos][2]]; 344: y2 = bspcoord[checkcoord[boxpos][3]]; 345: 346: 347: #ifdef __NeXT__ 1.1.1.2 ! root 348: // RD_DisplayLine (x1, y1, x2, y2, 0.1); 1.1 root 349: #endif 1.1.1.2 ! root 350: 1.1 root 351: // 352: // check clip list for an open space 1.1.1.2 ! root 353: // 1.1 root 354: angle1 = R_PointToAngle (x1, y1) - viewangle; 355: angle2 = R_PointToAngle (x2, y2) - viewangle; 1.1.1.2 ! root 356: 1.1 root 357: span = angle1 - angle2; 358: if (span >= ANG180) 1.1.1.2 ! root 359: return true; // sitting on a line 1.1 root 360: tspan = angle1 + clipangle; 361: if (tspan > 2*clipangle) 362: { 363: tspan -= 2*clipangle; 364: if (tspan >= span) 1.1.1.2 ! root 365: return false; // totally off the left edge 1.1 root 366: angle1 = clipangle; 367: } 368: tspan = clipangle - angle2; 369: if (tspan > 2*clipangle) 370: { 371: tspan -= 2*clipangle; 372: if (tspan >= span) 1.1.1.2 ! root 373: return false; // totally off the left edge 1.1 root 374: angle2 = -clipangle; 375: } 376: 377: 378: // find the first clippost that touches the source post (adjacent pixels are touching) 379: angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT; 380: angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT; 381: sx1 = viewangletox[angle1]; 382: sx2 = viewangletox[angle2]; 383: if (sx1 == sx2) 1.1.1.2 ! root 384: return false; // does not cross a pixel 1.1 root 385: sx2--; 1.1.1.2 ! root 386: 1.1 root 387: start = solidsegs; 388: while (start->last < sx2) 389: start++; 390: if (sx1 >= start->first && sx2 <= start->last) 1.1.1.2 ! root 391: return false; // the clippost contains the new span 1.1 root 392: 393: return true; 394: } 395: 396: 397: /* 398: ================ 399: = 400: = R_Subsector 401: = 402: = Draw one or more segments 403: ================ 404: */ 405: 406: void R_Subsector (int num) 407: { 1.1.1.2 ! root 408: int count; ! 409: seg_t *line; ! 410: subsector_t *sub; ! 411: int polyCount; ! 412: seg_t **polySeg; ! 413: 1.1 root 414: #ifdef RANGECHECK 415: if (num>=numsubsectors) 416: I_Error ("R_Subsector: ss %i with numss = %i",num, numsubsectors); 417: #endif 418: 419: sscount++; 420: sub = &subsectors[num]; 421: frontsector = sub->sector; 422: count = sub->numlines; 423: line = &segs[sub->firstline]; 424: 1.1.1.2 ! root 425: if(frontsector->floorheight < viewz) ! 426: { ! 427: floorplane = R_FindPlane(frontsector->floorheight, ! 428: frontsector->floorpic, frontsector->lightlevel, ! 429: frontsector->special); ! 430: } 1.1 root 431: else 1.1.1.2 ! root 432: { 1.1 root 433: floorplane = NULL; 1.1.1.2 ! root 434: } ! 435: ! 436: if(frontsector->ceilingheight > viewz ! 437: || frontsector->ceilingpic == skyflatnum) ! 438: { ! 439: ceilingplane = R_FindPlane(frontsector->ceilingheight, ! 440: frontsector->ceilingpic, frontsector->lightlevel, 0); ! 441: } 1.1 root 442: else 1.1.1.2 ! root 443: { 1.1 root 444: ceilingplane = NULL; 1.1.1.2 ! root 445: } 1.1 root 446: 1.1.1.2 ! root 447: R_AddSprites(frontsector); ! 448: if(sub->poly) ! 449: { // Render the polyobj in the subsector first ! 450: polyCount = sub->poly->numsegs; ! 451: polySeg = sub->poly->segs; ! 452: while(polyCount--) ! 453: { ! 454: R_AddLine(*polySeg++); ! 455: } ! 456: } 1.1 root 457: while (count--) 458: { 459: R_AddLine (line); 460: line++; 461: } 462: } 463: 464: 465: /* 466: =============================================================================== 467: = 468: = RenderBSPNode 469: = 470: =============================================================================== 471: */ 472: 473: void R_RenderBSPNode (int bspnum) 474: { 1.1.1.2 ! root 475: node_t *bsp; ! 476: int side; 1.1 root 477: 478: if (bspnum & NF_SUBSECTOR) 479: { 1.1.1.2 ! root 480: if (bspnum == -1) 1.1 root 481: R_Subsector (0); 482: else 483: R_Subsector (bspnum&(~NF_SUBSECTOR)); 484: return; 485: } 1.1.1.2 ! root 486: 1.1 root 487: bsp = &nodes[bspnum]; 1.1.1.2 ! root 488: 1.1 root 489: #ifdef __NeXT__ 490: RD_DrawNodeLine (bsp); 491: #endif 1.1.1.2 ! root 492: 1.1 root 493: // 494: // decide which side the view point is on 495: // 496: side = R_PointOnSide (viewx, viewy, bsp); 497: 498: R_RenderBSPNode (bsp->children[side]); // recursively divide front space 1.1.1.2 ! root 499: ! 500: if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space 1.1 root 501: R_RenderBSPNode (bsp->children[side^1]); 502: } 503: 504:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.