|
|
1.1.1.3 root 1: // Emacs style mode select -*- C++ -*-
2: //-----------------------------------------------------------------------------
3: //
4: // $Id:$
5: //
6: // Copyright (C) 1993-1996 by id Software, Inc.
7: //
1.1.1.5 ! root 8: // This source is available for distribution and/or modification
! 9: // only under the terms of the DOOM Source Code License as
! 10: // published by id Software. All rights reserved.
1.1.1.3 root 11: //
1.1.1.5 ! root 12: // The source is distributed in the hope that it will be useful,
1.1.1.3 root 13: // but WITHOUT ANY WARRANTY; without even the implied warranty of
1.1.1.5 ! root 14: // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
! 15: // for more details.
1.1.1.3 root 16: //
17: // $Log:$
18: //
19: // DESCRIPTION:
20: // BSP traversal, handling of LineSegs for rendering.
21: //
22: //-----------------------------------------------------------------------------
1.1 root 23:
24:
1.1.1.3 root 25: static const char
26: rcsid[] = "$Id: r_bsp.c,v 1.4 1997/02/03 22:45:12 b1 Exp $";
1.1 root 27:
28:
1.1.1.3 root 29: #include "doomdef.h"
1.1 root 30:
1.1.1.3 root 31: #include "m_bbox.h"
1.1 root 32:
1.1.1.3 root 33: #include "i_system.h"
1.1 root 34:
1.1.1.3 root 35: #include "r_main.h"
36: #include "r_plane.h"
37: #include "r_things.h"
1.1 root 38:
1.1.1.3 root 39: // State.
40: #include "doomstat.h"
41: #include "r_state.h"
1.1 root 42:
1.1.1.3 root 43: //#include "r_local.h"
1.1.1.5 ! root 44: char MsgText[256];
! 45: void WriteDebug(char *);
1.1 root 46:
47:
1.1.1.3 root 48: seg_t* curline;
49: side_t* sidedef;
50: line_t* linedef;
51: sector_t* frontsector;
52: sector_t* backsector;
1.1.1.2 root 53:
1.1.1.3 root 54: drawseg_t drawsegs[MAXDRAWSEGS];
55: drawseg_t* ds_p;
1.1.1.2 root 56:
57:
1.1.1.3 root 58: void
59: R_StoreWallRange
60: ( int start,
61: int stop );
1.1.1.2 root 62:
63:
1.1 root 64:
65:
1.1.1.3 root 66: //
67: // R_ClearDrawSegs
68: //
69: void R_ClearDrawSegs (void)
1.1 root 70: {
1.1.1.3 root 71: ds_p = drawsegs;
72: }
1.1 root 73:
74:
1.1.1.2 root 75:
1.1.1.3 root 76: //
77: // ClipWallSegment
78: // Clips the given range of columns
79: // and includes it in the new clip list.
80: //
81: typedef struct
82: {
83: int first;
84: int last;
85:
86: } cliprange_t;
1.1.1.2 root 87:
88:
1.1.1.3 root 89: #define MAXSEGS 32
1.1.1.2 root 90:
1.1.1.3 root 91: // newend is one past the last valid seg
92: cliprange_t* newend;
93: cliprange_t solidsegs[MAXSEGS];
1.1 root 94:
95:
96:
97:
1.1.1.3 root 98: //
99: // R_ClipSolidWallSegment
100: // Does handle solid walls,
101: // e.g. single sided LineDefs (middle texture)
102: // that entirely block the view.
103: //
104: void
105: R_ClipSolidWallSegment
106: ( int first,
107: int last )
1.1 root 108: {
1.1.1.3 root 109: cliprange_t* next;
110: cliprange_t* start;
1.1 root 111:
1.1.1.3 root 112: // Find the first range that touches the range
113: // (adjacent pixels are touching).
114: start = solidsegs;
115: while (start->last < first-1)
116: start++;
117:
118: if (first < start->first)
119: {
120: if (last < start->first-1)
121: {
122: // Post is entirely visible (above start),
123: // so insert a new clippost.
124: R_StoreWallRange (first, last);
125: next = newend;
126: newend++;
127:
128: while (next != start)
129: {
130: *next = *(next-1);
131: next--;
132: }
133: next->first = first;
134: next->last = last;
135: return;
136: }
137:
138: // There is a fragment above *start.
139: R_StoreWallRange (first, start->first - 1);
140: // Now adjust the clip size.
141: start->first = first;
142: }
143:
144: // Bottom contained in start?
145: if (last <= start->last)
146: return;
147:
148: next = start;
149: while (last >= (next+1)->first-1)
150: {
151: // There is a fragment between two posts.
152: R_StoreWallRange (next->last + 1, (next+1)->first - 1);
153: next++;
154:
155: if (last <= next->last)
156: {
157: // Bottom is contained in next.
158: // Adjust the clip size.
159: start->last = next->last;
160: goto crunch;
161: }
162: }
163:
164: // There is a fragment after *next.
165: R_StoreWallRange (next->last + 1, last);
166: // Adjust the clip size.
167: start->last = last;
168:
169: // Remove start+1 to next from the clip list,
170: // because start now covers their area.
171: crunch:
172: if (next == start)
173: {
174: // Post just extended past the bottom of one post.
175: return;
176: }
177:
1.1 root 178:
1.1.1.3 root 179: while (next++ != newend)
180: {
181: // Remove a post.
182: *++start = *next;
183: }
1.1.1.2 root 184:
1.1.1.3 root 185: newend = start+1;
186: }
1.1 root 187:
188:
189:
190: //
1.1.1.3 root 191: // R_ClipPassWallSegment
192: // Clips the given range of columns,
193: // but does not includes it in the clip list.
194: // Does handle windows,
195: // e.g. LineDefs with upper and lower texture.
196: //
1.1.1.5 ! root 197: void R_ClipPassWallSegment( int first, int last )
! 198: {
1.1.1.3 root 199: cliprange_t* start;
200:
201: // Find the first range that touches the range
202: // (adjacent pixels are touching).
203: start = solidsegs;
204: while (start->last < first-1)
1.1.1.5 ! root 205: start++;
1.1.1.3 root 206:
207: if (first < start->first)
1.1.1.5 ! root 208: {
! 209: if (last < start->first-1)
! 210: {
! 211: // Post is entirely visible (above start).
! 212: R_StoreWallRange (first, last);
! 213: return;
! 214: }
1.1.1.3 root 215:
1.1.1.5 ! root 216: // There is a fragment above *start.
! 217: R_StoreWallRange (first, start->first - 1);
! 218: }
1.1.1.3 root 219:
220: // Bottom contained in start?
221: if (last <= start->last)
1.1.1.5 ! root 222: return;
1.1.1.3 root 223:
224: while (last >= (start+1)->first-1)
1.1.1.5 ! root 225: {
! 226: // There is a fragment between two posts.
! 227: R_StoreWallRange (start->last + 1, (start+1)->first - 1);
! 228: start++;
! 229:
! 230: if (last <= start->last)
! 231: return;
! 232: }
1.1.1.3 root 233:
234: // There is a fragment after *next.
235: R_StoreWallRange (start->last + 1, last);
236: }
1.1 root 237:
1.1.1.2 root 238:
1.1 root 239:
240: //
1.1.1.3 root 241: // R_ClearClipSegs
1.1 root 242: //
1.1.1.3 root 243: void R_ClearClipSegs (void)
244: {
1.1.1.5 ! root 245: solidsegs[0].first = -(0x7fffffff);
1.1.1.3 root 246: solidsegs[0].last = -1;
247: solidsegs[1].first = viewwidth;
248: solidsegs[1].last = 0x7fffffff;
249: newend = solidsegs+2;
250: }
1.1 root 251:
1.1.1.3 root 252: //
253: // R_AddLine
254: // Clips the given segment
255: // and adds any visible pieces to the line list.
256: //
257: void R_AddLine (seg_t* line)
1.1.1.5 ! root 258: {
1.1.1.3 root 259: int x1;
260: int x2;
261: angle_t angle1;
262: angle_t angle2;
263: angle_t span;
264: angle_t tspan;
265:
266: curline = line;
267:
268: // OPTIMIZE: quickly reject orthogonal back sides.
269: angle1 = R_PointToAngle (line->v1->x, line->v1->y);
270: angle2 = R_PointToAngle (line->v2->x, line->v2->y);
271:
272: // Clip to view edges.
273: // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).
274: span = angle1 - angle2;
275:
276: // Back side? I.e. backface culling?
277: if (span >= ANG180)
1.1.1.5 ! root 278: {
! 279: //WriteDebug("Back face culled...\n");
! 280: return;
! 281: }
1.1.1.3 root 282:
283: // Global angle needed by segcalc.
284: rw_angle1 = angle1;
285: angle1 -= viewangle;
286: angle2 -= viewangle;
287:
288: tspan = angle1 + clipangle;
289: if (tspan > 2*clipangle)
1.1.1.5 ! root 290: {
! 291: tspan -= 2*clipangle;
1.1.1.3 root 292:
1.1.1.5 ! root 293: // Totally off the left edge?
! 294: if (tspan >= span)
! 295: {
! 296: //WriteDebug("Off the left edge...\n");
! 297: return;
! 298: }
1.1.1.3 root 299:
1.1.1.5 ! root 300: angle1 = clipangle;
! 301: }
1.1.1.3 root 302: tspan = clipangle - angle2;
303: if (tspan > 2*clipangle)
1.1.1.5 ! root 304: {
! 305: tspan -= 2*clipangle;
1.1.1.3 root 306:
1.1.1.5 ! root 307: // Totally off the left edge?
! 308: if (tspan >= span)
! 309: {
! 310: //WriteDebug("Off the left edge...\n");
! 311: return;
! 312: }
! 313: angle2 = (clipangle * -1);
! 314: }
1.1.1.3 root 315:
316: // The seg is in the view range,
317: // but not necessarily visible.
318: angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
319: angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
320: x1 = viewangletox[angle1];
321: x2 = viewangletox[angle2];
322:
323: // Does not cross a pixel?
324: if (x1 == x2)
1.1.1.5 ! root 325: {
! 326: //WriteDebug("No pixel spanned...\n");
! 327: return;
! 328: }
1.1.1.3 root 329:
330: backsector = line->backsector;
331:
332: // Single sided line?
333: if (!backsector)
1.1.1.5 ! root 334: {
! 335: //WriteDebug("Wall...\n");
! 336: goto clipsolid;
! 337: }
1.1.1.2 root 338:
1.1.1.3 root 339: // Closed door.
1.1.1.5 ! root 340: if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight)
! 341: {
! 342: //WriteDebug("Closed door...\n");
! 343: goto clipsolid;
! 344: }
1.1.1.2 root 345:
1.1.1.3 root 346: // Window.
1.1.1.5 ! root 347: if (backsector->ceilingheight != frontsector->ceilingheight || backsector->floorheight != frontsector->floorheight)
! 348: {
! 349: //WriteDebug("Window (portal)...\n");
! 350: goto clippass;
! 351: }
1.1.1.3 root 352:
1.1.1.5 ! root 353: // Reject empty lines used for triggers and special events.
1.1.1.3 root 354: // Identical floor and ceiling on both sides,
355: // identical light levels on both sides,
356: // and no middle texture.
1.1.1.5 ! root 357: if (backsector->ceilingpic == frontsector->ceilingpic && backsector->floorpic == frontsector->floorpic &&
! 358: backsector->lightlevel == frontsector->lightlevel && curline->sidedef->midtexture == 0)
! 359: {
! 360: //WriteDebug("Trip line...\n");
! 361: return;
! 362: }
1.1.1.3 root 363:
1.1.1.5 ! root 364: clippass:
! 365: R_ClipPassWallSegment (x1, x2-1);
! 366: return;
1.1.1.3 root 367:
1.1.1.5 ! root 368: clipsolid:
! 369: R_ClipSolidWallSegment (x1, x2-1);
! 370: return;
! 371: }
1.1 root 372:
373:
1.1.1.3 root 374: //
375: // R_CheckBBox
376: // Checks BSP node/subtree bounding box.
377: // Returns true
378: // if some part of the bbox might be visible.
379: //
380: int checkcoord[12][4] =
1.1 root 381: {
1.1.1.3 root 382: {3,0,2,1},
383: {3,0,2,0},
384: {3,1,2,0},
385: {0},
386: {2,0,2,1},
387: {0,0,0,0},
388: {3,1,3,0},
389: {0},
390: {2,0,3,1},
391: {2,1,3,1},
392: {2,1,3,0}
393: };
1.1.1.2 root 394:
1.1 root 395:
1.1.1.3 root 396: boolean R_CheckBBox (fixed_t* bspcoord)
397: {
398: int boxx;
399: int boxy;
400: int boxpos;
401:
402: fixed_t x1;
403: fixed_t y1;
404: fixed_t x2;
405: fixed_t y2;
406:
407: angle_t angle1;
408: angle_t angle2;
409: angle_t span;
410: angle_t tspan;
411:
412: cliprange_t* start;
413:
414: int sx1;
415: int sx2;
416:
417: // Find the corners of the box
418: // that define the edges from current viewpoint.
419: if (viewx <= bspcoord[BOXLEFT])
420: boxx = 0;
421: else if (viewx < bspcoord[BOXRIGHT])
422: boxx = 1;
423: else
424: boxx = 2;
425:
426: if (viewy >= bspcoord[BOXTOP])
427: boxy = 0;
428: else if (viewy > bspcoord[BOXBOTTOM])
429: boxy = 1;
430: else
431: boxy = 2;
432:
433: boxpos = (boxy<<2)+boxx;
434: if (boxpos == 5)
435: return true;
436:
437: x1 = bspcoord[checkcoord[boxpos][0]];
438: y1 = bspcoord[checkcoord[boxpos][1]];
439: x2 = bspcoord[checkcoord[boxpos][2]];
440: y2 = bspcoord[checkcoord[boxpos][3]];
441:
442: // check clip list for an open space
443: angle1 = R_PointToAngle (x1, y1) - viewangle;
444: angle2 = R_PointToAngle (x2, y2) - viewangle;
445:
446: span = angle1 - angle2;
1.1.1.2 root 447:
1.1.1.3 root 448: // Sitting on a line?
449: if (span >= ANG180)
450: return true;
451:
452: tspan = angle1 + clipangle;
1.1.1.2 root 453:
1.1.1.3 root 454: if (tspan > 2*clipangle)
455: {
456: tspan -= 2*clipangle;
457:
458: // Totally off the left edge?
459: if (tspan >= span)
460: return false;
461:
462: angle1 = clipangle;
463: }
464: tspan = clipangle - angle2;
465: if (tspan > 2*clipangle)
466: {
467: tspan -= 2*clipangle;
468:
469: // Totally off the left edge?
470: if (tspan >= span)
471: return false;
472:
1.1.1.5 ! root 473: angle2 = (clipangle * -1);
1.1.1.3 root 474: }
475:
476:
477: // Find the first clippost
478: // that touches the source post
479: // (adjacent pixels are touching).
480: angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
481: angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
482: sx1 = viewangletox[angle1];
483: sx2 = viewangletox[angle2];
484:
485: // Does not cross a pixel.
486: if (sx1 == sx2)
487: return false;
488: sx2--;
489:
490: start = solidsegs;
491: while (start->last < sx2)
492: start++;
493:
494: if (sx1 >= start->first
495: && sx2 <= start->last)
496: {
497: // The clippost contains the new span.
498: return false;
499: }
1.1.1.2 root 500:
1.1.1.3 root 501: return true;
502: }
1.1 root 503:
504:
1.1.1.2 root 505:
1.1 root 506: //
1.1.1.3 root 507: // R_Subsector
508: // Determine floor/ceiling planes.
509: // Add sprites of things in sector.
510: // Draw one or more line segments.
1.1.1.2 root 511: //
1.1 root 512: void R_Subsector (int num)
513: {
1.1.1.3 root 514: int count;
515: seg_t* line;
516: subsector_t* sub;
517:
1.1 root 518: #ifdef RANGECHECK
1.1.1.5 ! root 519: if (num >= numsubsectors)
! 520: I_Error ("R_Subsector: ss %i with numss = %i", num, numsubsectors);
1.1 root 521: #endif
522:
1.1.1.3 root 523: sscount++;
524: sub = &subsectors[num];
525: frontsector = sub->sector;
526: count = sub->numlines;
527: line = &segs[sub->firstline];
528:
529: if (frontsector->floorheight < viewz)
1.1.1.5 ! root 530: {
! 531: floorplane = R_FindPlane (frontsector->floorheight, frontsector->floorpic, frontsector->lightlevel);
! 532: }
1.1.1.3 root 533: else
1.1.1.5 ! root 534: floorplane = NULL;
! 535:
! 536: if (frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum)
! 537: {
! 538: ceilingplane = R_FindPlane (frontsector->ceilingheight, frontsector->ceilingpic, frontsector->lightlevel);
! 539: }
1.1.1.3 root 540: else
1.1.1.5 ! root 541: ceilingplane = NULL;
1.1.1.3 root 542:
543: R_AddSprites (frontsector);
544:
545: while (count--)
1.1.1.5 ! root 546: {
! 547: R_AddLine (line);
! 548: line++;
! 549: }
! 550: }
1.1 root 551:
552:
553:
1.1.1.2 root 554:
1.1 root 555: //
1.1.1.3 root 556: // RenderBSPNode
557: // Renders all subsectors below a given node,
558: // traversing subtree recursively.
559: // Just call with BSP root.
560: void R_RenderBSPNode (int bspnum)
1.1.1.5 ! root 561: {
1.1.1.3 root 562: node_t* bsp;
563: int side;
1.1.1.2 root 564:
1.1.1.3 root 565: // Found a subsector?
566: if (bspnum & NF_SUBSECTOR)
1.1.1.5 ! root 567: {
! 568: if (bspnum == -1)
! 569: R_Subsector (0);
! 570: else
! 571: R_Subsector (bspnum&(~NF_SUBSECTOR));
! 572: return;
! 573: }
1.1.1.3 root 574:
575: bsp = &nodes[bspnum];
576:
577: // Decide which side the view point is on.
1.1.1.5 ! root 578: side = R_PointOnSide(viewx, viewy, bsp);
1.1.1.3 root 579:
580: // Recursively divide front space.
581: R_RenderBSPNode (bsp->children[side]);
582:
583: // Possibly divide back space.
584: if (R_CheckBBox (bsp->bbox[side^1]))
585: R_RenderBSPNode (bsp->children[side^1]);
1.1 root 586: }
587:
588:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.