2 //**************************************************************************
4 //** r_bsp.c : Heretic 2 : Raven Software, Corp.
11 //**************************************************************************
19 sector_t *frontsector, *backsector;
21 drawseg_t drawsegs[MAXDRAWSEGS], *ds_p;
23 void R_StoreWallRange (int start, int stop);
33 void R_ClearDrawSegs (void)
38 //=============================================================================
42 ===============================================================================
46 = Clips the given range of columns and includes it in the new clip list
47 ===============================================================================
57 cliprange_t solidsegs[MAXSEGS], *newend; // newend is one past the last valid seg
60 void R_ClipSolidWallSegment (int first, int last)
62 cliprange_t *next, *start;
64 // find the first range that touches the range (adjacent pixels are touching)
66 while (start->last < first-1)
69 if (first < start->first)
71 if (last < start->first-1)
72 { // post is entirely visible (above start), so insert a new clippost
73 R_StoreWallRange (first, last);
86 // there is a fragment above *start
87 R_StoreWallRange (first, start->first - 1);
88 start->first = first; // adjust the clip size
91 if (last <= start->last)
92 return; // bottom contained in start
95 while (last >= (next+1)->first-1)
97 // there is a fragment between two posts
98 R_StoreWallRange (next->last + 1, (next+1)->first - 1);
100 if (last <= next->last)
101 { // bottom is contained in next
102 start->last = next->last; // adjust the clip size
107 // there is a fragment after *next
108 R_StoreWallRange (next->last + 1, last);
109 start->last = last; // adjust the clip size
112 // remove start+1 to next from the clip list,
113 // because start now covers their area
116 return; // post just extended past the bottom of one post
118 while (next++ != newend) // remove a post
124 ===============================================================================
126 = R_ClipPassWallSegment
128 = Clips the given range of columns, but does not includes it in the clip list
129 ===============================================================================
132 void R_ClipPassWallSegment (int first, int last)
136 // find the first range that touches the range (adjacent pixels are touching)
138 while (start->last < first-1)
141 if (first < start->first)
143 if (last < start->first-1)
144 { // post is entirely visible (above start)
145 R_StoreWallRange (first, last);
149 // there is a fragment above *start
150 R_StoreWallRange (first, start->first - 1);
153 if (last <= start->last)
154 return; // bottom contained in start
156 while (last >= (start+1)->first-1)
158 // there is a fragment between two posts
159 R_StoreWallRange (start->last + 1, (start+1)->first - 1);
161 if (last <= start->last)
165 // there is a fragment after *next
166 R_StoreWallRange (start->last + 1, last);
179 void R_ClearClipSegs (void)
181 solidsegs[0].first = -0x7fffffff;
182 solidsegs[0].last = -1;
183 solidsegs[1].first = viewwidth;
184 solidsegs[1].last = 0x7fffffff;
185 newend = solidsegs+2;
189 //=============================================================================
192 ======================
196 = Clips the given segment and adds any visible pieces to the line list
198 ======================
201 void R_AddLine (seg_t *line)
204 angle_t angle1, angle2, span, tspan;
207 RD_DrawLineCheck (line);
211 // OPTIMIZE: quickly reject orthogonal back sides
213 angle1 = R_PointToAngle (line->v1->x, line->v1->y);
214 angle2 = R_PointToAngle (line->v2->x, line->v2->y);
217 // clip to view edges
218 // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW)
219 span = angle1 - angle2;
223 rw_angle1 = angle1; // global angle needed by segcalc
227 tspan = angle1 + clipangle;
228 if (tspan > 2*clipangle)
230 tspan -= 2*clipangle;
232 return; // totally off the left edge
235 tspan = clipangle - angle2;
236 if (tspan > 2*clipangle)
238 tspan -= 2*clipangle;
240 return; // totally off the left edge
245 // the seg is in the view range, but not necessarily visible
247 angle1 = (angle1+ANG90)>>ANGLETOFINESHIFT;
248 angle2 = (angle2+ANG90)>>ANGLETOFINESHIFT;
249 x1 = viewangletox[angle1];
250 x2 = viewangletox[angle2];
252 return; // does not cross a pixel
254 backsector = line->backsector;
257 goto clipsolid; // single sided line
259 if (backsector->ceilingheight <= frontsector->floorheight
260 || backsector->floorheight >= frontsector->ceilingheight)
261 goto clipsolid; // closed door
263 if (backsector->ceilingheight != frontsector->ceilingheight
264 || backsector->floorheight != frontsector->floorheight)
265 goto clippass; // window
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
271 && backsector->special == frontsector->special
272 && curline->sidedef->midtexture == 0)
276 R_ClipPassWallSegment (x1, x2-1);
280 R_ClipSolidWallSegment (x1, x2-1);
283 //============================================================================
287 ===============================================================================
291 = Returns true if some part of the bbox might be visible
293 ===============================================================================
296 int checkcoord[12][4] = {
310 boolean R_CheckBBox (fixed_t *bspcoord)
312 int boxx, boxy, boxpos;
313 fixed_t x1, y1, x2, y2;
314 angle_t angle1, angle2, span, tspan;
319 RD_DrawBBox (bspcoord);
322 // find the corners of the box that define the edges from current viewpoint
323 if (viewx <= bspcoord[BOXLEFT])
325 else if (viewx < bspcoord[BOXRIGHT])
330 if (viewy >= bspcoord[BOXTOP])
332 else if (viewy > bspcoord[BOXBOTTOM])
337 boxpos = (boxy<<2)+boxx;
341 x1 = bspcoord[checkcoord[boxpos][0]];
342 y1 = bspcoord[checkcoord[boxpos][1]];
343 x2 = bspcoord[checkcoord[boxpos][2]];
344 y2 = bspcoord[checkcoord[boxpos][3]];
348 // RD_DisplayLine (x1, y1, x2, y2, 0.1);
352 // check clip list for an open space
354 angle1 = R_PointToAngle (x1, y1) - viewangle;
355 angle2 = R_PointToAngle (x2, y2) - viewangle;
357 span = angle1 - angle2;
359 return true; // sitting on a line
360 tspan = angle1 + clipangle;
361 if (tspan > 2*clipangle)
363 tspan -= 2*clipangle;
365 return false; // totally off the left edge
368 tspan = clipangle - angle2;
369 if (tspan > 2*clipangle)
371 tspan -= 2*clipangle;
373 return false; // totally off the left edge
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];
384 return false; // does not cross a pixel
388 while (start->last < sx2)
390 if (sx1 >= start->first && sx2 <= start->last)
391 return false; // the clippost contains the new span
402 = Draw one or more segments
406 void R_Subsector (int num)
415 if (num>=numsubsectors)
416 I_Error ("R_Subsector: ss %i with numss = %i",num, numsubsectors);
420 sub = &subsectors[num];
421 frontsector = sub->sector;
422 count = sub->numlines;
423 line = &segs[sub->firstline];
425 if(frontsector->floorheight < viewz)
427 floorplane = R_FindPlane(frontsector->floorheight,
428 frontsector->floorpic, frontsector->lightlevel,
429 frontsector->special);
436 if(frontsector->ceilingheight > viewz
437 || frontsector->ceilingpic == skyflatnum)
439 ceilingplane = R_FindPlane(frontsector->ceilingheight,
440 frontsector->ceilingpic, frontsector->lightlevel, 0);
447 R_AddSprites(frontsector);
449 { // Render the polyobj in the subsector first
450 polyCount = sub->poly->numsegs;
451 polySeg = sub->poly->segs;
454 R_AddLine(*polySeg++);
466 ===============================================================================
470 ===============================================================================
473 void R_RenderBSPNode (int bspnum)
478 if (bspnum & NF_SUBSECTOR)
483 R_Subsector (bspnum&(~NF_SUBSECTOR));
487 bsp = &nodes[bspnum];
490 RD_DrawNodeLine (bsp);
494 // decide which side the view point is on
496 side = R_PointOnSide (viewx, viewy, bsp);
498 R_RenderBSPNode (bsp->children[side]); // recursively divide front space
500 if (R_CheckBBox (bsp->bbox[side^1])) // possibly divide back space
501 R_RenderBSPNode (bsp->children[side^1]);