1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
6 // Copyright (C) 1993-1996 by id Software, Inc.
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.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
18 // Revision 1.1 2000/02/29 18:21:05 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
23 // BSP traversal, handling of LineSegs for rendering.
25 //-----------------------------------------------------------------------------
46 //#include "r_local.h"
52 sector_t
* frontsector
;
55 FAR drawseg_t drawsegs
[MAXDRAWSEGS
];
69 void R_ClearDrawSegs (void)
78 // Clips the given range of columns
79 // and includes it in the new clip list.
91 // newend is one past the last valid seg
93 FAR cliprange_t solidsegs
[MAXSEGS
];
99 // R_ClipSolidWallSegment
100 // Does handle solid walls,
101 // e.g. single sided LineDefs (middle texture)
102 // that entirely block the view.
105 R_ClipSolidWallSegment
112 // Find the first range that touches the range
113 // (adjacent pixels are touching).
115 while (start
->last
< first
-1)
118 if (first
< start
->first
)
120 if (last
< start
->first
-1)
122 // Post is entirely visible (above start),
123 // so insert a new clippost.
124 R_StoreWallRange (first
, last
);
128 while (next
!= start
)
138 // There is a fragment above *start.
139 R_StoreWallRange (first
, start
->first
- 1);
140 // Now adjust the clip size.
141 start
->first
= first
;
144 // Bottom contained in start?
145 if (last
<= start
->last
)
149 while (last
>= (next
+1)->first
-1)
151 // There is a fragment between two posts.
152 R_StoreWallRange (next
->last
+ 1, (next
+1)->first
- 1);
155 if (last
<= next
->last
)
157 // Bottom is contained in next.
158 // Adjust the clip size.
159 start
->last
= next
->last
;
164 // There is a fragment after *next.
165 R_StoreWallRange (next
->last
+ 1, last
);
166 // Adjust the clip size.
169 // Remove start+1 to next from the clip list,
170 // because start now covers their area.
174 // Post just extended past the bottom of one post.
179 while (next
++ != newend
)
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.
198 R_ClipPassWallSegment
204 // Find the first range that touches the range
205 // (adjacent pixels are touching).
207 while (start
->last
< first
-1)
210 if (first
< start
->first
)
212 if (last
< start
->first
-1)
214 // Post is entirely visible (above start).
215 R_StoreWallRange (first
, last
);
219 // There is a fragment above *start.
220 R_StoreWallRange (first
, start
->first
- 1);
223 // Bottom contained in start?
224 if (last
<= start
->last
)
227 while (last
>= (start
+1)->first
-1)
229 // There is a fragment between two posts.
230 R_StoreWallRange (start
->last
+ 1, (start
+1)->first
- 1);
233 if (last
<= start
->last
)
237 // There is a fragment after *next.
238 R_StoreWallRange (start
->last
+ 1, last
);
246 void R_ClearClipSegs (void)
248 solidsegs
[0].first
= -0x7fffffff;
249 solidsegs
[0].last
= -1;
250 solidsegs
[1].first
= viewwidth
;
251 solidsegs
[1].last
= 0x7fffffff;
252 newend
= solidsegs
+2;
257 // Clips the given segment
258 // and adds any visible pieces to the line list.
260 void R_AddLine (seg_t
* line
)
271 // OPTIMIZE: quickly reject orthogonal back sides.
272 angle1
= R_PointToAngle (line
->v1
->x
, line
->v1
->y
);
273 angle2
= R_PointToAngle (line
->v2
->x
, line
->v2
->y
);
275 // Clip to view edges.
276 // OPTIMIZE: make constant out of 2*clipangle (FIELDOFVIEW).
277 span
= angle1
- angle2
;
279 // Back side? I.e. backface culling?
283 // Global angle needed by segcalc.
288 tspan
= angle1
+ clipangle
;
289 if (tspan
> 2*clipangle
)
291 tspan
-= 2*clipangle
;
293 // Totally off the left edge?
299 tspan
= clipangle
- angle2
;
300 if (tspan
> 2*clipangle
)
302 tspan
-= 2*clipangle
;
304 // Totally off the left edge?
310 // The seg is in the view range,
311 // but not necessarily visible.
312 angle1
= (angle1
+ANG90
)>>ANGLETOFINESHIFT
;
313 angle2
= (angle2
+ANG90
)>>ANGLETOFINESHIFT
;
314 x1
= viewangletox
[angle1
];
315 x2
= viewangletox
[angle2
];
317 // Does not cross a pixel?
321 backsector
= line
->backsector
;
323 // Single sided line?
328 if (backsector
->ceilingheight
<= frontsector
->floorheight
329 || backsector
->floorheight
>= frontsector
->ceilingheight
)
333 if (backsector
->ceilingheight
!= frontsector
->ceilingheight
334 || backsector
->floorheight
!= frontsector
->floorheight
)
337 // Reject empty lines used for triggers
338 // and special events.
339 // Identical floor and ceiling on both sides,
340 // identical light levels on both sides,
341 // and no middle texture.
342 if (backsector
->ceilingpic
== frontsector
->ceilingpic
343 && backsector
->floorpic
== frontsector
->floorpic
344 && backsector
->lightlevel
== frontsector
->lightlevel
345 && curline
->sidedef
->midtexture
== 0)
352 R_ClipPassWallSegment (x1
, x2
-1);
356 R_ClipSolidWallSegment (x1
, x2
-1);
362 // Checks BSP node/subtree bounding box.
364 // if some part of the bbox might be visible.
366 int checkcoord
[12][4] =
382 boolean
R_CheckBBox (fixed_t
* bspcoord
)
403 // Find the corners of the box
404 // that define the edges from current viewpoint.
405 if (viewx
<= bspcoord
[BOXLEFT
])
407 else if (viewx
< bspcoord
[BOXRIGHT
])
412 if (viewy
>= bspcoord
[BOXTOP
])
414 else if (viewy
> bspcoord
[BOXBOTTOM
])
419 boxpos
= (boxy
<<2)+boxx
;
423 x1
= bspcoord
[checkcoord
[boxpos
][0]];
424 y1
= bspcoord
[checkcoord
[boxpos
][1]];
425 x2
= bspcoord
[checkcoord
[boxpos
][2]];
426 y2
= bspcoord
[checkcoord
[boxpos
][3]];
428 // check clip list for an open space
429 angle1
= R_PointToAngle (x1
, y1
) - viewangle
;
430 angle2
= R_PointToAngle (x2
, y2
) - viewangle
;
432 span
= angle1
- angle2
;
434 // Sitting on a line?
438 tspan
= angle1
+ clipangle
;
440 if (tspan
> 2*clipangle
)
442 tspan
-= 2*clipangle
;
444 // Totally off the left edge?
450 tspan
= clipangle
- angle2
;
451 if (tspan
> 2*clipangle
)
453 tspan
-= 2*clipangle
;
455 // Totally off the left edge?
463 // Find the first clippost
464 // that touches the source post
465 // (adjacent pixels are touching).
466 angle1
= (angle1
+ANG90
)>>ANGLETOFINESHIFT
;
467 angle2
= (angle2
+ANG90
)>>ANGLETOFINESHIFT
;
468 sx1
= viewangletox
[angle1
];
469 sx2
= viewangletox
[angle2
];
471 // Does not cross a pixel.
477 while (start
->last
< sx2
)
480 if (sx1
>= start
->first
481 && sx2
<= start
->last
)
483 // The clippost contains the new span.
494 // Determine floor/ceiling planes.
495 // Add sprites of things in sector.
496 // Draw one or more line segments.
498 void R_Subsector (int num
)
505 if (num
>=numsubsectors
)
506 I_Error ("R_Subsector: ss %i with numss = %i",
512 sub
= &subsectors
[num
];
513 frontsector
= sub
->sector
;
514 count
= sub
->numlines
;
515 line
= &segs
[sub
->firstline
];
517 if (frontsector
->floorheight
< viewz
)
519 floorplane
= R_FindPlane (frontsector
->floorheight
,
520 frontsector
->floorpic
,
521 frontsector
->lightlevel
);
526 if (frontsector
->ceilingheight
> viewz
527 || frontsector
->ceilingpic
== skyflatnum
)
529 ceilingplane
= R_FindPlane (frontsector
->ceilingheight
,
530 frontsector
->ceilingpic
,
531 frontsector
->lightlevel
);
536 R_AddSprites (frontsector
);
550 // Renders all subsectors below a given node,
551 // traversing subtree recursively.
552 // Just call with BSP root.
553 void R_RenderBSPNode (int bspnum
)
558 // Found a subsector?
559 if (bspnum
& NF_SUBSECTOR
)
564 R_Subsector (bspnum
&(~NF_SUBSECTOR
));
568 bsp
= &nodes
[bspnum
];
570 // Decide which side the view point is on.
571 side
= R_PointOnSide (viewx
, viewy
, bsp
);
573 // Recursively divide front space.
574 R_RenderBSPNode (bsp
->children
[side
]);
576 // Possibly divide back space.
577 if (R_CheckBBox (bsp
->bbox
[side
^1]))
578 R_RenderBSPNode (bsp
->children
[side
^1]);