Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  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.
  8.  
  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.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  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.
  18.  
  19. */
  20. // r_edge.c
  21.  
  22. #include "quakedef.h"
  23. #include "r_local.h"
  24.  
  25. #if 0
  26. // FIXME
  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
  30.  
  31. this breaks spans at every edge, even hidden ones (bad)
  32.  
  33. have a sentinal at both ends?
  34. #endif
  35.  
  36.  
  37. edge_t  *auxedges;
  38. edge_t  *r_edges, *edge_p, *edge_max;
  39.  
  40. surf_t  *surfaces, *surface_p, *surf_max;
  41.  
  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
  45.  
  46. edge_t  *newedges[MAXHEIGHT];
  47. edge_t  *removeedges[MAXHEIGHT];
  48.  
  49. espan_t *span_p, *max_span_p;
  50.  
  51. int             r_currentkey;
  52.  
  53. extern  int     screenwidth;
  54.  
  55. int     current_iv;
  56.  
  57. int     edge_head_u_shift20, edge_tail_u_shift20;
  58.  
  59. static void (*pdrawfunc)(void);
  60.  
  61. edge_t  edge_head;
  62. edge_t  edge_tail;
  63. edge_t  edge_aftertail;
  64. edge_t  edge_sentinel;
  65.  
  66. float   fv;
  67.  
  68. void R_GenerateSpans (void);
  69. void R_GenerateSpansBackward (void);
  70.  
  71. void R_LeadingEdge (edge_t *edge);
  72. void R_LeadingEdgeBackwards (edge_t *edge);
  73. void R_TrailingEdge (surf_t *surf, edge_t *edge);
  74.  
  75.  
  76. //=============================================================================
  77.  
  78.  
  79. /*
  80. ==============
  81. R_DrawCulledPolys
  82. ==============
  83. */
  84. void R_DrawCulledPolys (void)
  85. {
  86.         surf_t                  *s;
  87.         msurface_t              *pface;
  88.  
  89.         currententity = &cl_entities[0];
  90.  
  91.         if (r_worldpolysbacktofront)
  92.         {
  93.                 for (s=surface_p-1 ; s>&surfaces[1] ; s--)
  94.                 {
  95.                         if (!s->spans)
  96.                                 continue;
  97.  
  98.                         if (!(s->flags & SURF_DRAWBACKGROUND))
  99.                         {
  100.                                 pface = (msurface_t *)s->data;
  101.                                 R_RenderPoly (pface, 15);
  102.                         }
  103.                 }
  104.         }
  105.         else
  106.         {
  107.                 for (s = &surfaces[1] ; s<surface_p ; s++)
  108.                 {
  109.                         if (!s->spans)
  110.                                 continue;
  111.  
  112.                         if (!(s->flags & SURF_DRAWBACKGROUND))
  113.                         {
  114.                                 pface = (msurface_t *)s->data;
  115.                                 R_RenderPoly (pface, 15);
  116.                         }
  117.                 }
  118.         }
  119. }
  120.  
  121.  
  122. /*
  123. ==============
  124. R_BeginEdgeFrame
  125. ==============
  126. */
  127. void R_BeginEdgeFrame (void)
  128. {
  129.         int             v;
  130.  
  131.         edge_p = r_edges;
  132.         edge_max = &r_edges[r_numallocatededges];
  133.  
  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;
  138.  
  139. // put the background behind everything in the world
  140.         if (r_draworder.value)
  141.         {
  142.                 pdrawfunc = R_GenerateSpansBackward;
  143.                 surfaces[1].key = 0;
  144.                 r_currentkey = 1;
  145.         }
  146.         else
  147.         {
  148.                 pdrawfunc = R_GenerateSpans;
  149.                 surfaces[1].key = 0x7FFFFFFF;
  150.                 r_currentkey = 0;
  151.         }
  152.  
  153. // FIXME: set with memset
  154.         for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
  155.         {
  156.                 newedges[v] = removeedges[v] = NULL;
  157.         }
  158. }
  159.  
  160.  
  161. #if     !id386
  162.  
  163. /*
  164. ==============
  165. R_InsertNewEdges
  166.  
  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
  170. edge_head.next).
  171. ==============
  172. */
  173. void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
  174. {
  175.         edge_t  *next_edge;
  176.  
  177.         do
  178.         {
  179.                 next_edge = edgestoadd->next;
  180. edgesearch:
  181.                 if (edgelist->u >= edgestoadd->u)
  182.                         goto addedge;
  183.                 edgelist=edgelist->next;
  184.                 if (edgelist->u >= edgestoadd->u)
  185.                         goto addedge;
  186.                 edgelist=edgelist->next;
  187.                 if (edgelist->u >= edgestoadd->u)
  188.                         goto addedge;
  189.                 edgelist=edgelist->next;
  190.                 if (edgelist->u >= edgestoadd->u)
  191.                         goto addedge;
  192.                 edgelist=edgelist->next;
  193.                 goto edgesearch;
  194.  
  195.         // insert edgestoadd before edgelist
  196. addedge:
  197.                 edgestoadd->next = edgelist;
  198.                 edgestoadd->prev = edgelist->prev;
  199.                 edgelist->prev->next = edgestoadd;
  200.                 edgelist->prev = edgestoadd;
  201.         } while ((edgestoadd = next_edge) != NULL);
  202. }
  203.  
  204. #endif  // !id386
  205.        
  206.  
  207. #if     !id386
  208.  
  209. /*
  210. ==============
  211. R_RemoveEdges
  212. ==============
  213. */
  214. void R_RemoveEdges (edge_t *pedge)
  215. {
  216.  
  217.         do
  218.         {
  219.                 pedge->next->prev = pedge->prev;
  220.                 pedge->prev->next = pedge->next;
  221.         } while ((pedge = pedge->nextremove) != NULL);
  222. }
  223.  
  224. #endif  // !id386
  225.  
  226.  
  227. #if     !id386
  228.  
  229. /*
  230. ==============
  231. R_StepActiveU
  232. ==============
  233. */
  234. void R_StepActiveU (edge_t *pedge)
  235. {
  236.         edge_t          *pnext_edge, *pwedge;
  237.  
  238.         while (1)
  239.         {
  240. nextedge:
  241.                 pedge->u += pedge->u_step;
  242.                 if (pedge->u < pedge->prev->u)
  243.                         goto pushback;
  244.                 pedge = pedge->next;
  245.                        
  246.                 pedge->u += pedge->u_step;
  247.                 if (pedge->u < pedge->prev->u)
  248.                         goto pushback;
  249.                 pedge = pedge->next;
  250.                        
  251.                 pedge->u += pedge->u_step;
  252.                 if (pedge->u < pedge->prev->u)
  253.                         goto pushback;
  254.                 pedge = pedge->next;
  255.                        
  256.                 pedge->u += pedge->u_step;
  257.                 if (pedge->u < pedge->prev->u)
  258.                         goto pushback;
  259.                 pedge = pedge->next;
  260.                        
  261.                 goto nextedge;         
  262.                
  263. pushback:
  264.                 if (pedge == &edge_aftertail)
  265.                         return;
  266.                        
  267.         // push it back to keep it sorted              
  268.                 pnext_edge = pedge->next;
  269.  
  270.         // pull the edge out of the edge list
  271.                 pedge->next->prev = pedge->prev;
  272.                 pedge->prev->next = pedge->next;
  273.  
  274.         // find out where the edge goes in the edge list
  275.                 pwedge = pedge->prev->prev;
  276.  
  277.                 while (pwedge->u > pedge->u)
  278.                 {
  279.                         pwedge = pwedge->prev;
  280.                 }
  281.  
  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;
  287.  
  288.                 pedge = pnext_edge;
  289.                 if (pedge == &edge_tail)
  290.                         return;
  291.         }
  292. }
  293.  
  294. #endif  // !id386
  295.  
  296.  
  297. /*
  298. ==============
  299. R_CleanupSpan
  300. ==============
  301. */
  302. void R_CleanupSpan ()
  303. {
  304.         surf_t  *surf;
  305.         int             iu;
  306.         espan_t *span;
  307.  
  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)
  313.         {
  314.                 span = span_p++;
  315.                 span->u = surf->last_u;
  316.                 span->count = iu - span->u;
  317.                 span->v = current_iv;
  318.                 span->pnext = surf->spans;
  319.                 surf->spans = span;
  320.         }
  321.  
  322. // reset spanstate for all surfaces in the surface stack
  323.         do
  324.         {
  325.                 surf->spanstate = 0;
  326.                 surf = surf->next;
  327.         } while (surf != &surfaces[1]);
  328. }
  329.  
  330.  
  331. /*
  332. ==============
  333. R_LeadingEdgeBackwards
  334. ==============
  335. */
  336. void R_LeadingEdgeBackwards (edge_t *edge)
  337. {
  338.         espan_t                 *span;
  339.         surf_t                  *surf, *surf2;
  340.         int                             iu;
  341.  
  342. // it's adding a new surface in, so find the correct place
  343.         surf = &surfaces[edge->surfs[1]];
  344.  
  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
  347. // end edge)
  348.         if (++surf->spanstate == 1)
  349.         {
  350.                 surf2 = surfaces[1].next;
  351.  
  352.                 if (surf->key > surf2->key)
  353.                         goto newtop;
  354.  
  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))
  358.                 {
  359.                 // must be two bmodels in the same leaf; don't care, because they'll
  360.                 // never be farthest anyway
  361.                         goto newtop;
  362.                 }
  363.  
  364. continue_search:
  365.  
  366.                 do
  367.                 {
  368.                         surf2 = surf2->next;
  369.                 } while (surf->key < surf2->key);
  370.  
  371.                 if (surf->key == surf2->key)
  372.                 {
  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;
  377.  
  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
  380.                 }
  381.  
  382.                 goto gotposition;
  383.  
  384. newtop:
  385.         // emit a span (obscures current top)
  386.                 iu = edge->u >> 20;
  387.  
  388.                 if (iu > surf2->last_u)
  389.                 {
  390.                         span = span_p++;
  391.                         span->u = surf2->last_u;
  392.                         span->count = iu - span->u;
  393.                         span->v = current_iv;
  394.                         span->pnext = surf2->spans;
  395.                         surf2->spans = span;
  396.                 }
  397.  
  398.                 // set last_u on the new span
  399.                 surf->last_u = iu;
  400.                                
  401. gotposition:
  402.         // insert before surf2
  403.                 surf->next = surf2;
  404.                 surf->prev = surf2->prev;
  405.                 surf2->prev->next = surf;
  406.                 surf2->prev = surf;
  407.         }
  408. }
  409.  
  410.  
  411. /*
  412. ==============
  413. R_TrailingEdge
  414. ==============
  415. */
  416. void R_TrailingEdge (surf_t *surf, edge_t *edge)
  417. {
  418.         espan_t                 *span;
  419.         int                             iu;
  420.  
  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
  423. // start edge yet)
  424.         if (--surf->spanstate == 0)
  425.         {
  426.                 if (surf->insubmodel)
  427.                         r_bmodelactive--;
  428.  
  429.                 if (surf == surfaces[1].next)
  430.                 {
  431.                 // emit a span (current top going away)
  432.                         iu = edge->u >> 20;
  433.                         if (iu > surf->last_u)
  434.                         {
  435.                                 span = span_p++;
  436.                                 span->u = surf->last_u;
  437.                                 span->count = iu - span->u;
  438.                                 span->v = current_iv;
  439.                                 span->pnext = surf->spans;
  440.                                 surf->spans = span;
  441.                         }
  442.  
  443.                 // set last_u on the surface below
  444.                         surf->next->last_u = iu;
  445.                 }
  446.  
  447.                 surf->prev->next = surf->next;
  448.                 surf->next->prev = surf->prev;
  449.         }
  450. }
  451.  
  452.  
  453. #if     !id386
  454.  
  455. /*
  456. ==============
  457. R_LeadingEdge
  458. ==============
  459. */
  460. void R_LeadingEdge (edge_t *edge)
  461. {
  462.         espan_t                 *span;
  463.         surf_t                  *surf, *surf2;
  464.         int                             iu;
  465.         double                  fu, newzi, testzi, newzitop, newzibottom;
  466.  
  467.         if (edge->surfs[1])
  468.         {
  469.         // it's adding a new surface in, so find the correct place
  470.                 surf = &surfaces[edge->surfs[1]];
  471.  
  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
  474.         // end edge)
  475.                 if (++surf->spanstate == 1)
  476.                 {
  477.                         if (surf->insubmodel)
  478.                                 r_bmodelactive++;
  479.  
  480.                         surf2 = surfaces[1].next;
  481.  
  482.                         if (surf->key < surf2->key)
  483.                                 goto newtop;
  484.  
  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))
  488.                         {
  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 +
  492.                                                 fu*surf->d_zistepu;
  493.                                 newzibottom = newzi * 0.99;
  494.  
  495.                                 testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
  496.                                                 fu*surf2->d_zistepu;
  497.  
  498.                                 if (newzibottom >= testzi)
  499.                                 {
  500.                                         goto newtop;
  501.                                 }
  502.  
  503.                                 newzitop = newzi * 1.01;
  504.                                 if (newzitop >= testzi)
  505.                                 {
  506.                                         if (surf->d_zistepu >= surf2->d_zistepu)
  507.                                         {
  508.                                                 goto newtop;
  509.                                         }
  510.                                 }
  511.                         }
  512.  
  513. continue_search:
  514.  
  515.                         do
  516.                         {
  517.                                 surf2 = surf2->next;
  518.                         } while (surf->key > surf2->key);
  519.  
  520.                         if (surf->key == surf2->key)
  521.                         {
  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;
  526.  
  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 +
  530.                                                 fu*surf->d_zistepu;
  531.                                 newzibottom = newzi * 0.99;
  532.  
  533.                                 testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
  534.                                                 fu*surf2->d_zistepu;
  535.  
  536.                                 if (newzibottom >= testzi)
  537.                                 {
  538.                                         goto gotposition;
  539.                                 }
  540.  
  541.                                 newzitop = newzi * 1.01;
  542.                                 if (newzitop >= testzi)
  543.                                 {
  544.                                         if (surf->d_zistepu >= surf2->d_zistepu)
  545.                                         {
  546.                                                 goto gotposition;
  547.                                         }
  548.                                 }
  549.  
  550.                                 goto continue_search;
  551.                         }
  552.  
  553.                         goto gotposition;
  554.  
  555. newtop:
  556.                 // emit a span (obscures current top)
  557.                         iu = edge->u >> 20;
  558.  
  559.                         if (iu > surf2->last_u)
  560.                         {
  561.                                 span = span_p++;
  562.                                 span->u = surf2->last_u;
  563.                                 span->count = iu - span->u;
  564.                                 span->v = current_iv;
  565.                                 span->pnext = surf2->spans;
  566.                                 surf2->spans = span;
  567.                         }
  568.  
  569.                         // set last_u on the new span
  570.                         surf->last_u = iu;
  571.                                
  572. gotposition:
  573.                 // insert before surf2
  574.                         surf->next = surf2;
  575.                         surf->prev = surf2->prev;
  576.                         surf2->prev->next = surf;
  577.                         surf2->prev = surf;
  578.                 }
  579.         }
  580. }
  581.  
  582.  
  583. /*
  584. ==============
  585. R_GenerateSpans
  586. ==============
  587. */
  588. void R_GenerateSpans (void)
  589. {
  590.         edge_t                  *edge;
  591.         surf_t                  *surf;
  592.  
  593.         r_bmodelactive = 0;
  594.  
  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;
  598.  
  599. // generate spans
  600.         for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
  601.         {                      
  602.                 if (edge->surfs[0])
  603.                 {
  604.                 // it has a left surface, so a surface is going away for this span
  605.                         surf = &surfaces[edge->surfs[0]];
  606.  
  607.                         R_TrailingEdge (surf, edge);
  608.  
  609.                         if (!edge->surfs[1])
  610.                                 continue;
  611.                 }
  612.  
  613.                 R_LeadingEdge (edge);
  614.         }
  615.  
  616.         R_CleanupSpan ();
  617. }
  618.  
  619. #endif  // !id386
  620.  
  621.  
  622. /*
  623. ==============
  624. R_GenerateSpansBackward
  625. ==============
  626. */
  627. void R_GenerateSpansBackward (void)
  628. {
  629.         edge_t                  *edge;
  630.  
  631.         r_bmodelactive = 0;
  632.  
  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;
  636.  
  637. // generate spans
  638.         for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
  639.         {                      
  640.                 if (edge->surfs[0])
  641.                         R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
  642.  
  643.                 if (edge->surfs[1])
  644.                         R_LeadingEdgeBackwards (edge);
  645.         }
  646.  
  647.         R_CleanupSpan ();
  648. }
  649.  
  650.  
  651. /*
  652. ==============
  653. R_ScanEdges
  654.  
  655. Input:
  656. newedges[] array
  657.         this has links to edges, which have links to surfaces
  658.  
  659. Output:
  660. Each surface has a linked list of its visible spans
  661. ==============
  662. */
  663. void R_ScanEdges (void)
  664. {
  665.         int             iv, bottom;
  666.         byte    basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
  667.         espan_t *basespan_p;
  668.         surf_t  *s;
  669.  
  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];
  673.  
  674.         span_p = basespan_p;
  675.  
  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;
  685.        
  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;
  693.        
  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;
  698.  
  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;
  702.  
  703. //     
  704. // process all scan lines
  705. //
  706.         bottom = r_refdef.vrectbottom - 1;
  707.  
  708.         for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
  709.         {
  710.                 current_iv = iv;
  711.                 fv = (float)iv;
  712.  
  713.         // mark that the head (background start) span is pre-included
  714.                 surfaces[1].spanstate = 1;
  715.  
  716.                 if (newedges[iv])
  717.                 {
  718.                         R_InsertNewEdges (newedges[iv], edge_head.next);
  719.                 }
  720.  
  721.                 (*pdrawfunc) ();
  722.  
  723.         // flush the span list if we can't be sure we have enough spans left for
  724.         // the next scan
  725.                 if (span_p >= max_span_p)
  726.                 {
  727.                         VID_UnlockBuffer ();
  728.                         S_ExtraUpdate ();       // don't let sound get messed up if going slow
  729.                         VID_LockBuffer ();
  730.                
  731.                         if (r_drawculledpolys)
  732.                         {
  733.                                 R_DrawCulledPolys ();
  734.                         }
  735.                         else
  736.                         {
  737.                                 D_DrawSurfaces ();
  738.                         }
  739.  
  740.                 // clear the surface span pointers
  741.                         for (s = &surfaces[1] ; s<surface_p ; s++)
  742.                                 s->spans = NULL;
  743.  
  744.                         span_p = basespan_p;
  745.                 }
  746.  
  747.                 if (removeedges[iv])
  748.                         R_RemoveEdges (removeedges[iv]);
  749.  
  750.                 if (edge_head.next != &edge_tail)
  751.                         R_StepActiveU (edge_head.next);
  752.         }
  753.  
  754. // do the last scan (no need to step or sort or remove on the last scan)
  755.  
  756.         current_iv = iv;
  757.         fv = (float)iv;
  758.  
  759. // mark that the head (background start) span is pre-included
  760.         surfaces[1].spanstate = 1;
  761.  
  762.         if (newedges[iv])
  763.                 R_InsertNewEdges (newedges[iv], edge_head.next);
  764.  
  765.         (*pdrawfunc) ();
  766.  
  767. // draw whatever's left in the span list
  768.         if (r_drawculledpolys)
  769.                 R_DrawCulledPolys ();
  770.         else
  771.                 D_DrawSurfaces ();
  772. }
  773.  
  774.  
  775.