2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 the
complex cases add
new polys on most lines
, so dont optimize
for keeping them the same
28 have multiple free span lists to
try to get better coherence
?
29 low depth complexity
-- 1 to
3 or so
31 this breaks spans at every edge
, even hidden
ones (bad
)
33 have a sentinal at both ends
?
38 edge_t
*r_edges
, *edge_p
, *edge_max
;
40 surf_t
*surfaces
, *surface_p
, *surf_max
;
42 // surfaces are generated in back to front order by the bsp, so if a surf
43 // pointer is greater than another one, it should be drawn in front
44 // surfaces[1] is the background, and is used as the active surface stack
46 edge_t
*newedges
[MAXHEIGHT
];
47 edge_t
*removeedges
[MAXHEIGHT
];
49 espan_t
*span_p
, *max_span_p
;
53 extern int screenwidth
;
57 int edge_head_u_shift20
, edge_tail_u_shift20
;
59 static void (*pdrawfunc
)(void);
63 edge_t edge_aftertail
;
68 void R_GenerateSpans (void);
69 void R_GenerateSpansBackward (void);
71 void R_LeadingEdge (edge_t
*edge
);
72 void R_LeadingEdgeBackwards (edge_t
*edge
);
73 void R_TrailingEdge (surf_t
*surf
, edge_t
*edge
);
76 //=============================================================================
84 void R_DrawCulledPolys (void)
89 currententity
= &cl_entities
[0];
91 if (r_worldpolysbacktofront
)
93 for (s
=surface_p
-1 ; s
>&surfaces
[1] ; s
--)
98 if (!(s
->flags
& SURF_DRAWBACKGROUND
))
100 pface
= (msurface_t
*)s
->data
;
101 R_RenderPoly (pface
, 15);
107 for (s
= &surfaces
[1] ; s
<surface_p
; s
++)
112 if (!(s
->flags
& SURF_DRAWBACKGROUND
))
114 pface
= (msurface_t
*)s
->data
;
115 R_RenderPoly (pface
, 15);
127 void R_BeginEdgeFrame (void)
132 edge_max
= &r_edges
[r_numallocatededges
];
134 surface_p
= &surfaces
[2]; // background is surface 1,
135 // surface 0 is a dummy
136 surfaces
[1].spans
= NULL
; // no background spans yet
137 surfaces
[1].flags
= SURF_DRAWBACKGROUND
;
139 // put the background behind everything in the world
140 if (r_draworder
.value
)
142 pdrawfunc
= R_GenerateSpansBackward
;
148 pdrawfunc
= R_GenerateSpans
;
149 surfaces
[1].key
= 0x7FFFFFFF;
153 // FIXME: set with memset
154 for (v
=r_refdef
.vrect
.y
; v
<r_refdef
.vrectbottom
; v
++)
156 newedges
[v
] = removeedges
[v
] = NULL
;
167 Adds the edges in the linked list edgestoadd, adding them to the edges in the
168 linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a
169 sentinel at the end (actually, this is the active edge table starting at
173 void R_InsertNewEdges (edge_t
*edgestoadd
, edge_t
*edgelist
)
179 next_edge
= edgestoadd
->next
;
181 if (edgelist
->u
>= edgestoadd
->u
)
183 edgelist
=edgelist
->next
;
184 if (edgelist
->u
>= edgestoadd
->u
)
186 edgelist
=edgelist
->next
;
187 if (edgelist
->u
>= edgestoadd
->u
)
189 edgelist
=edgelist
->next
;
190 if (edgelist
->u
>= edgestoadd
->u
)
192 edgelist
=edgelist
->next
;
195 // insert edgestoadd before edgelist
197 edgestoadd
->next
= edgelist
;
198 edgestoadd
->prev
= edgelist
->prev
;
199 edgelist
->prev
->next
= edgestoadd
;
200 edgelist
->prev
= edgestoadd
;
201 } while ((edgestoadd
= next_edge
) != NULL
);
214 void R_RemoveEdges (edge_t
*pedge
)
219 pedge
->next
->prev
= pedge
->prev
;
220 pedge
->prev
->next
= pedge
->next
;
221 } while ((pedge
= pedge
->nextremove
) != NULL
);
234 void R_StepActiveU (edge_t
*pedge
)
236 edge_t
*pnext_edge
, *pwedge
;
241 pedge
->u
+= pedge
->u_step
;
242 if (pedge
->u
< pedge
->prev
->u
)
246 pedge
->u
+= pedge
->u_step
;
247 if (pedge
->u
< pedge
->prev
->u
)
251 pedge
->u
+= pedge
->u_step
;
252 if (pedge
->u
< pedge
->prev
->u
)
256 pedge
->u
+= pedge
->u_step
;
257 if (pedge
->u
< pedge
->prev
->u
)
264 if (pedge
== &edge_aftertail
)
267 // push it back to keep it sorted
268 pnext_edge
= pedge
->next
;
270 // pull the edge out of the edge list
271 pedge
->next
->prev
= pedge
->prev
;
272 pedge
->prev
->next
= pedge
->next
;
274 // find out where the edge goes in the edge list
275 pwedge
= pedge
->prev
->prev
;
277 while (pwedge
->u
> pedge
->u
)
279 pwedge
= pwedge
->prev
;
282 // put the edge back into the edge list
283 pedge
->next
= pwedge
->next
;
284 pedge
->prev
= pwedge
;
285 pedge
->next
->prev
= pedge
;
286 pwedge
->next
= pedge
;
289 if (pedge
== &edge_tail
)
302 void R_CleanupSpan ()
308 // now that we've reached the right edge of the screen, we're done with any
309 // unfinished surfaces, so emit a span for whatever's on top
310 surf
= surfaces
[1].next
;
311 iu
= edge_tail_u_shift20
;
312 if (iu
> surf
->last_u
)
315 span
->u
= surf
->last_u
;
316 span
->count
= iu
- span
->u
;
317 span
->v
= current_iv
;
318 span
->pnext
= surf
->spans
;
322 // reset spanstate for all surfaces in the surface stack
327 } while (surf
!= &surfaces
[1]);
333 R_LeadingEdgeBackwards
336 void R_LeadingEdgeBackwards (edge_t
*edge
)
339 surf_t
*surf
, *surf2
;
342 // it's adding a new surface in, so find the correct place
343 surf
= &surfaces
[edge
->surfs
[1]];
345 // don't start a span if this is an inverted span, with the end
346 // edge preceding the start edge (that is, we've already seen the
348 if (++surf
->spanstate
== 1)
350 surf2
= surfaces
[1].next
;
352 if (surf
->key
> surf2
->key
)
355 // if it's two surfaces on the same plane, the one that's already
356 // active is in front, so keep going unless it's a bmodel
357 if (surf
->insubmodel
&& (surf
->key
== surf2
->key
))
359 // must be two bmodels in the same leaf; don't care, because they'll
360 // never be farthest anyway
369 } while (surf
->key
< surf2
->key
);
371 if (surf
->key
== surf2
->key
)
373 // if it's two surfaces on the same plane, the one that's already
374 // active is in front, so keep going unless it's a bmodel
375 if (!surf
->insubmodel
)
376 goto continue_search
;
378 // must be two bmodels in the same leaf; don't care which is really
379 // in front, because they'll never be farthest anyway
385 // emit a span (obscures current top)
388 if (iu
> surf2
->last_u
)
391 span
->u
= surf2
->last_u
;
392 span
->count
= iu
- span
->u
;
393 span
->v
= current_iv
;
394 span
->pnext
= surf2
->spans
;
398 // set last_u on the new span
402 // insert before surf2
404 surf
->prev
= surf2
->prev
;
405 surf2
->prev
->next
= surf
;
416 void R_TrailingEdge (surf_t
*surf
, edge_t
*edge
)
421 // don't generate a span if this is an inverted span, with the end
422 // edge preceding the start edge (that is, we haven't seen the
424 if (--surf
->spanstate
== 0)
426 if (surf
->insubmodel
)
429 if (surf
== surfaces
[1].next
)
431 // emit a span (current top going away)
433 if (iu
> surf
->last_u
)
436 span
->u
= surf
->last_u
;
437 span
->count
= iu
- span
->u
;
438 span
->v
= current_iv
;
439 span
->pnext
= surf
->spans
;
443 // set last_u on the surface below
444 surf
->next
->last_u
= iu
;
447 surf
->prev
->next
= surf
->next
;
448 surf
->next
->prev
= surf
->prev
;
460 void R_LeadingEdge (edge_t
*edge
)
463 surf_t
*surf
, *surf2
;
465 float fu
, newzi
, testzi
, newzitop
, newzibottom
;
469 // it's adding a new surface in, so find the correct place
470 surf
= &surfaces
[edge
->surfs
[1]];
472 // don't start a span if this is an inverted span, with the end
473 // edge preceding the start edge (that is, we've already seen the
475 if (++surf
->spanstate
== 1)
477 if (surf
->insubmodel
)
480 surf2
= surfaces
[1].next
;
482 if (surf
->key
< surf2
->key
)
485 // if it's two surfaces on the same plane, the one that's already
486 // active is in front, so keep going unless it's a bmodel
487 if (surf
->insubmodel
&& (surf
->key
== surf2
->key
))
489 // must be two bmodels in the same leaf; sort on 1/z
490 fu
= (float)(edge
->u
- 0xFFFFF) * (1.0 / 0x100000);
491 newzi
= surf
->d_ziorigin
+ fv
*surf
->d_zistepv
+
493 newzibottom
= newzi
* 0.99;
495 testzi
= surf2
->d_ziorigin
+ fv
*surf2
->d_zistepv
+
498 if (newzibottom
>= testzi
)
503 newzitop
= newzi
* 1.01;
504 if (newzitop
>= testzi
)
506 if (surf
->d_zistepu
>= surf2
->d_zistepu
)
518 } while (surf
->key
> surf2
->key
);
520 if (surf
->key
== surf2
->key
)
522 // if it's two surfaces on the same plane, the one that's already
523 // active is in front, so keep going unless it's a bmodel
524 if (!surf
->insubmodel
)
525 goto continue_search
;
527 // must be two bmodels in the same leaf; sort on 1/z
528 fu
= (float)(edge
->u
- 0xFFFFF) * (1.0 / 0x100000);
529 newzi
= surf
->d_ziorigin
+ fv
*surf
->d_zistepv
+
531 newzibottom
= newzi
* 0.99;
533 testzi
= surf2
->d_ziorigin
+ fv
*surf2
->d_zistepv
+
536 if (newzibottom
>= testzi
)
541 newzitop
= newzi
* 1.01;
542 if (newzitop
>= testzi
)
544 if (surf
->d_zistepu
>= surf2
->d_zistepu
)
550 goto continue_search
;
556 // emit a span (obscures current top)
559 if (iu
> surf2
->last_u
)
562 span
->u
= surf2
->last_u
;
563 span
->count
= iu
- span
->u
;
564 span
->v
= current_iv
;
565 span
->pnext
= surf2
->spans
;
569 // set last_u on the new span
573 // insert before surf2
575 surf
->prev
= surf2
->prev
;
576 surf2
->prev
->next
= surf
;
588 void R_GenerateSpans (void)
595 // clear active surfaces to just the background surface
596 surfaces
[1].next
= surfaces
[1].prev
= &surfaces
[1];
597 surfaces
[1].last_u
= edge_head_u_shift20
;
600 for (edge
=edge_head
.next
; edge
!= &edge_tail
; edge
=edge
->next
)
604 // it has a left surface, so a surface is going away for this span
605 surf
= &surfaces
[edge
->surfs
[0]];
607 R_TrailingEdge (surf
, edge
);
613 R_LeadingEdge (edge
);
624 R_GenerateSpansBackward
627 void R_GenerateSpansBackward (void)
633 // clear active surfaces to just the background surface
634 surfaces
[1].next
= surfaces
[1].prev
= &surfaces
[1];
635 surfaces
[1].last_u
= edge_head_u_shift20
;
638 for (edge
=edge_head
.next
; edge
!= &edge_tail
; edge
=edge
->next
)
641 R_TrailingEdge (&surfaces
[edge
->surfs
[0]], edge
);
644 R_LeadingEdgeBackwards (edge
);
657 this has links to edges, which have links to surfaces
660 Each surface has a linked list of its visible spans
663 void R_ScanEdges (void)
666 byte basespans
[MAXSPANS
*sizeof(espan_t
)+CACHE_SIZE
];
670 basespan_p
= (espan_t
*)
671 ((long)(basespans
+ CACHE_SIZE
- 1) & ~(CACHE_SIZE
- 1));
672 max_span_p
= &basespan_p
[MAXSPANS
- r_refdef
.vrect
.width
];
676 // clear active edges to just the background edges around the whole screen
677 // FIXME: most of this only needs to be set up once
678 edge_head
.u
= r_refdef
.vrect
.x
<< 20;
679 edge_head_u_shift20
= edge_head
.u
>> 20;
680 edge_head
.u_step
= 0;
681 edge_head
.prev
= NULL
;
682 edge_head
.next
= &edge_tail
;
683 edge_head
.surfs
[0] = 0;
684 edge_head
.surfs
[1] = 1;
686 edge_tail
.u
= (r_refdef
.vrectright
<< 20) + 0xFFFFF;
687 edge_tail_u_shift20
= edge_tail
.u
>> 20;
688 edge_tail
.u_step
= 0;
689 edge_tail
.prev
= &edge_head
;
690 edge_tail
.next
= &edge_aftertail
;
691 edge_tail
.surfs
[0] = 1;
692 edge_tail
.surfs
[1] = 0;
694 edge_aftertail
.u
= -1; // force a move
695 edge_aftertail
.u_step
= 0;
696 edge_aftertail
.next
= &edge_sentinel
;
697 edge_aftertail
.prev
= &edge_tail
;
699 // FIXME: do we need this now that we clamp x in r_draw.c?
700 edge_sentinel
.u
= 2000 << 24; // make sure nothing sorts past this
701 edge_sentinel
.prev
= &edge_aftertail
;
704 // process all scan lines
706 bottom
= r_refdef
.vrectbottom
- 1;
708 for (iv
=r_refdef
.vrect
.y
; iv
<bottom
; iv
++)
713 // mark that the head (background start) span is pre-included
714 surfaces
[1].spanstate
= 1;
718 R_InsertNewEdges (newedges
[iv
], edge_head
.next
);
723 // flush the span list if we can't be sure we have enough spans left for
725 if (span_p
>= max_span_p
)
728 S_ExtraUpdate (); // don't let sound get messed up if going slow
731 if (r_drawculledpolys
)
733 R_DrawCulledPolys ();
740 // clear the surface span pointers
741 for (s
= &surfaces
[1] ; s
<surface_p
; s
++)
748 R_RemoveEdges (removeedges
[iv
]);
750 if (edge_head
.next
!= &edge_tail
)
751 R_StepActiveU (edge_head
.next
);
754 // do the last scan (no need to step or sort or remove on the last scan)
759 // mark that the head (background start) span is pre-included
760 surfaces
[1].spanstate
= 1;
763 R_InsertNewEdges (newedges
[iv
], edge_head
.next
);
767 // draw whatever's left in the span list
768 if (r_drawculledpolys
)
769 R_DrawCulledPolys ();