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