9 sector_t *frontsector, *backsector;
11 drawseg_t drawsegs[MAXDRAWSEGS], *ds_p;
13 void R_StoreWallRange (int start, int stop);
23 void R_ClearDrawSegs (void)
28 //=============================================================================
32 ===============================================================================
36 = Clips the given range of columns and includes it in the new clip list
37 ===============================================================================
47 cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg
50 void R_ClipSolidWallSegment (int first, int last)
52 cliprange_t *next, *start;
54 // find the first range that touches the range (adjacent pixels are touching)
56 while (start->last < first-1)
59 if (first < start->first)
61 if (last < start->first-1)
62 { // post is entirely visible (above start), so insert a new clippost
63 R_StoreWallRange (first, last);
76 // there is a fragment above *start
77 R_StoreWallRange (first, start->first - 1);
78 start->first = first; // adjust the clip size
81 if (last <= start->last)
82 return; // bottom contained in start
85 while (last >= (next+1)->first-1)
87 // there is a fragment between two posts
88 R_StoreWallRange (next->last + 1, (next+1)->first - 1);
90 if (last <= next->last)
91 { // bottom is contained in next
92 start->last = next->last; // adjust the clip size
97 // there is a fragment after *next
98 R_StoreWallRange (next->last + 1, last);
99 start->last = last; // adjust the clip size
102 // remove start+1 to next from the clip list,
103 // because start now covers their area
106 return; // post just extended past the bottom of one post
108 while (next++ != newend) // remove a post
114 ===============================================================================
116 = R_ClipPassWallSegment
118 = Clips the given range of columns, but does not includes it in the clip list
119 ===============================================================================
122 void R_ClipPassWallSegment (int first, int last)
126 // find the first range that touches the range (adjacent pixels are touching)
128 while (start->last < first-1)
131 if (first < start->first)
133 if (last < start->first-1)
134 { // post is entirely visible (above start)
135 R_StoreWallRange (first, last);
139 // there is a fragment above *start
140 R_StoreWallRange (first, start->first - 1);
143 if (last <= start->last)
144 return; // bottom contained in start
146 while (last >= (start+1)->first-1)
148 // there is a fragment between two posts
149 R_StoreWallRange (start->last + 1, (start+1)->first - 1);
151 if (last <= start->last)
155 // there is a fragment after *next
156 R_StoreWallRange (start->last + 1, last);
169 void R_ClearClipSegs (void)
171 solidsegs[0].first = -0x7fffffff;
172 solidsegs[0].last = -1;
173 solidsegs[1].first = viewwidth;
174 solidsegs[1].last = 0x7fffffff;
175 newend = solidsegs+2;
179 //=============================================================================
182 ======================
186 = Clips the given segment and adds any visible pieces to the line list
188 ======================
191 void R_AddLine (seg_t *line)
194 angle_t angle1, angle2, span, tspan;
197 RD_DrawLineCheck (line);
201 // OPTIMIZE: quickly reject orthogonal back sides
203 angle1 = R_PointToAngle (line->v1->x, line->v1->y);
204 angle2 = R_PointToAngle (line->v2->x, line->v2->y);
207 // clip to view edges
208 // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW)
209 span = angle1 - angle2;
213 rw_angle1 = angle1; // global angle needed by segcalc
217 tspan = angle1 + clipangle;
218 if (tspan > 2*clipangle)
220 tspan -= 2*clipangle;
222 return; // totally off the left edge
225 tspan = clipangle - angle2;
226 if (tspan > 2*clipangle)
228 tspan -= 2*clipangle;
230 return; // totally off the left edge
235 // the seg is in the view range, but not necessarily visible
237 angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
238 angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
239 x1 = viewangletox[angle1];
240 x2 = viewangletox[angle2];
242 return; // does not cross a pixel
244 backsector = line->backsector;
247 goto clipsolid; // single sided line
249 if (backsector->ceilingheight <= frontsector->floorheight
250 || backsector->floorheight >= frontsector->ceilingheight)
251 goto clipsolid; // closed door
253 if (backsector->ceilingheight != frontsector->ceilingheight
254 || backsector->floorheight != frontsector->floorheight)
255 goto clippass; // window
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)
265 R_ClipPassWallSegment (x1, x2-1);
269 R_ClipSolidWallSegment (x1, x2-1);
272 //============================================================================
276 ===============================================================================
280 = Returns true if some part of the bbox might be visible
282 ===============================================================================
285 int checkcoord[12][4] = {
299 boolean R_CheckBBox (fixed_t *bspcoord)
301 int boxx, boxy, boxpos;
302 fixed_t x1, y1, x2, y2;
303 angle_t angle1, angle2, span, tspan;
308 RD_DrawBBox (bspcoord);
311 // find the corners of the box that define the edges from current viewpoint
312 if (viewx <= bspcoord[BOXLEFT])
314 else if (viewx < bspcoord[BOXRIGHT])
319 if (viewy >= bspcoord[BOXTOP])
321 else if (viewy > bspcoord[BOXBOTTOM])
326 boxpos = (boxy<<2)+boxx;
330 x1 = bspcoord[checkcoord[boxpos][0]];
331 y1 = bspcoord[checkcoord[boxpos][1]];
332 x2 = bspcoord[checkcoord[boxpos][2]];
333 y2 = bspcoord[checkcoord[boxpos][3]];
337 // RD_DisplayLine (x1, y1, x2, y2, 0.1);
341 // check clip list for an open space
343 angle1 = R_PointToAngle (x1, y1) - viewangle;
344 angle2 = R_PointToAngle (x2, y2) - viewangle;
346 span = angle1 - angle2;
348 return true; // sitting on a line
349 tspan = angle1 + clipangle;
350 if (tspan > 2*clipangle)
352 tspan -= 2*clipangle;
354 return false; // totally off the left edge
357 tspan = clipangle - angle2;
358 if (tspan > 2*clipangle)
360 tspan -= 2*clipangle;
362 return false; // totally off the left edge
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];
373 return false; // does not cross a pixel
377 while (start->last < sx2)
379 if (sx1 >= start->first && sx2 <= start->last)
380 return false; // the clippost contains the new span
391 = Draw one or more segments
395 void R_Subsector (int num)
402 if (num>=numsubsectors)
403 I_Error ("R_Subsector: ss %i with numss = %i",num, numsubsectors);
407 sub = &subsectors[num];
408 frontsector = sub->sector;
409 count = sub->numlines;
410 line = &segs[sub->firstline];
412 if (frontsector->floorheight < viewz)
413 floorplane = R_FindPlane (frontsector->floorheight,
414 frontsector->floorpic, frontsector->lightlevel,
415 frontsector->special);
418 if (frontsector->ceilingheight > viewz
419 || frontsector->ceilingpic == skyflatnum)
420 ceilingplane = R_FindPlane (frontsector->ceilingheight,
421 frontsector->ceilingpic, frontsector->lightlevel, 0);
425 R_AddSprites (frontsector);
436 ===============================================================================
440 ===============================================================================
443 void R_RenderBSPNode (int bspnum)
448 if (bspnum & NF_SUBSECTOR)
453 R_Subsector (bspnum&(~NF_SUBSECTOR));
457 bsp = &nodes[bspnum];
460 RD_DrawNodeLine (bsp);
464 // decide which side the view point is on
466 side = R_PointOnSide (viewx, viewy, bsp);
468 R_RenderBSPNode (bsp->children[side]); // recursively divide front space
470 if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
471 R_RenderBSPNode (bsp->children[side^1]);