diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_edge.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/r_edge.c | 775 |
1 files changed, 775 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_edge.c b/apps/plugins/sdl/progs/quake/r_edge.c new file mode 100644 index 0000000000..1fff765a3a --- /dev/null +++ b/apps/plugins/sdl/progs/quake/r_edge.c | |||
@@ -0,0 +1,775 @@ | |||
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 | // made static | ||
72 | //void R_LeadingEdge (edge_t *edge); | ||
73 | //void R_LeadingEdgeBackwards (edge_t *edge); | ||
74 | //void R_TrailingEdge (surf_t *surf, edge_t *edge); | ||
75 | |||
76 | |||
77 | //============================================================================= | ||
78 | |||
79 | |||
80 | /* | ||
81 | ============== | ||
82 | R_DrawCulledPolys | ||
83 | ============== | ||
84 | */ | ||
85 | static inline void R_DrawCulledPolys (void) | ||
86 | { | ||
87 | surf_t *s; | ||
88 | msurface_t *pface; | ||
89 | |||
90 | currententity = &cl_entities[0]; | ||
91 | |||
92 | if (r_worldpolysbacktofront) | ||
93 | { | ||
94 | for (s=surface_p-1 ; s>&surfaces[1] ; s--) | ||
95 | { | ||
96 | if (!s->spans) | ||
97 | continue; | ||
98 | |||
99 | if (!(s->flags & SURF_DRAWBACKGROUND)) | ||
100 | { | ||
101 | pface = (msurface_t *)s->data; | ||
102 | R_RenderPoly (pface, 15); | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | for (s = &surfaces[1] ; s<surface_p ; s++) | ||
109 | { | ||
110 | if (!s->spans) | ||
111 | continue; | ||
112 | |||
113 | if (!(s->flags & SURF_DRAWBACKGROUND)) | ||
114 | { | ||
115 | pface = (msurface_t *)s->data; | ||
116 | R_RenderPoly (pface, 15); | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | |||
123 | /* | ||
124 | ============== | ||
125 | R_BeginEdgeFrame | ||
126 | ============== | ||
127 | */ | ||
128 | void R_BeginEdgeFrame (void) | ||
129 | { | ||
130 | int v; | ||
131 | |||
132 | edge_p = r_edges; | ||
133 | edge_max = &r_edges[r_numallocatededges]; | ||
134 | |||
135 | surface_p = &surfaces[2]; // background is surface 1, | ||
136 | // surface 0 is a dummy | ||
137 | surfaces[1].spans = NULL; // no background spans yet | ||
138 | surfaces[1].flags = SURF_DRAWBACKGROUND; | ||
139 | |||
140 | // put the background behind everything in the world | ||
141 | if (r_draworder.value) | ||
142 | { | ||
143 | pdrawfunc = R_GenerateSpansBackward; | ||
144 | surfaces[1].key = 0; | ||
145 | r_currentkey = 1; | ||
146 | } | ||
147 | else | ||
148 | { | ||
149 | pdrawfunc = R_GenerateSpans; | ||
150 | surfaces[1].key = 0x7FFFFFFF; | ||
151 | r_currentkey = 0; | ||
152 | } | ||
153 | |||
154 | // FIXME: set with memset | ||
155 | for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++) | ||
156 | { | ||
157 | newedges[v] = removeedges[v] = NULL; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | |||
162 | #if !id386 | ||
163 | |||
164 | /* | ||
165 | ============== | ||
166 | R_InsertNewEdges | ||
167 | |||
168 | Adds the edges in the linked list edgestoadd, adding them to the edges in the | ||
169 | 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 | ||
170 | sentinel at the end (actually, this is the active edge table starting at | ||
171 | edge_head.next). | ||
172 | ============== | ||
173 | */ | ||
174 | void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) | ||
175 | { | ||
176 | edge_t *next_edge; | ||
177 | |||
178 | do | ||
179 | { | ||
180 | next_edge = edgestoadd->next; | ||
181 | edgesearch: | ||
182 | if (edgelist->u >= edgestoadd->u) | ||
183 | goto addedge; | ||
184 | edgelist=edgelist->next; | ||
185 | if (edgelist->u >= edgestoadd->u) | ||
186 | goto addedge; | ||
187 | edgelist=edgelist->next; | ||
188 | if (edgelist->u >= edgestoadd->u) | ||
189 | goto addedge; | ||
190 | edgelist=edgelist->next; | ||
191 | if (edgelist->u >= edgestoadd->u) | ||
192 | goto addedge; | ||
193 | edgelist=edgelist->next; | ||
194 | goto edgesearch; | ||
195 | |||
196 | // insert edgestoadd before edgelist | ||
197 | addedge: | ||
198 | edgestoadd->next = edgelist; | ||
199 | edgestoadd->prev = edgelist->prev; | ||
200 | edgelist->prev->next = edgestoadd; | ||
201 | edgelist->prev = edgestoadd; | ||
202 | } while ((edgestoadd = next_edge) != NULL); | ||
203 | } | ||
204 | |||
205 | #endif // !id386 | ||
206 | |||
207 | |||
208 | #if !id386 | ||
209 | |||
210 | /* | ||
211 | ============== | ||
212 | R_RemoveEdges | ||
213 | ============== | ||
214 | */ | ||
215 | void R_RemoveEdges (edge_t *pedge) | ||
216 | { | ||
217 | |||
218 | do | ||
219 | { | ||
220 | pedge->next->prev = pedge->prev; | ||
221 | pedge->prev->next = pedge->next; | ||
222 | } while ((pedge = pedge->nextremove) != NULL); | ||
223 | } | ||
224 | |||
225 | #endif // !id386 | ||
226 | |||
227 | |||
228 | #if !id386 | ||
229 | |||
230 | /* | ||
231 | ============== | ||
232 | R_StepActiveU | ||
233 | ============== | ||
234 | */ | ||
235 | void R_StepActiveU (edge_t *pedge) | ||
236 | { | ||
237 | edge_t *pnext_edge, *pwedge; | ||
238 | |||
239 | while (1) | ||
240 | { | ||
241 | nextedge: | ||
242 | pedge->u += pedge->u_step; | ||
243 | if (pedge->u < pedge->prev->u) | ||
244 | goto pushback; | ||
245 | pedge = pedge->next; | ||
246 | |||
247 | pedge->u += pedge->u_step; | ||
248 | if (pedge->u < pedge->prev->u) | ||
249 | goto pushback; | ||
250 | pedge = pedge->next; | ||
251 | |||
252 | pedge->u += pedge->u_step; | ||
253 | if (pedge->u < pedge->prev->u) | ||
254 | goto pushback; | ||
255 | pedge = pedge->next; | ||
256 | |||
257 | pedge->u += pedge->u_step; | ||
258 | if (pedge->u < pedge->prev->u) | ||
259 | goto pushback; | ||
260 | pedge = pedge->next; | ||
261 | |||
262 | goto nextedge; | ||
263 | |||
264 | pushback: | ||
265 | if (pedge == &edge_aftertail) | ||
266 | return; | ||
267 | |||
268 | // push it back to keep it sorted | ||
269 | pnext_edge = pedge->next; | ||
270 | |||
271 | // pull the edge out of the edge list | ||
272 | pedge->next->prev = pedge->prev; | ||
273 | pedge->prev->next = pedge->next; | ||
274 | |||
275 | // find out where the edge goes in the edge list | ||
276 | pwedge = pedge->prev->prev; | ||
277 | |||
278 | while (pwedge->u > pedge->u) | ||
279 | { | ||
280 | pwedge = pwedge->prev; | ||
281 | } | ||
282 | |||
283 | // put the edge back into the edge list | ||
284 | pedge->next = pwedge->next; | ||
285 | pedge->prev = pwedge; | ||
286 | pedge->next->prev = pedge; | ||
287 | pwedge->next = pedge; | ||
288 | |||
289 | pedge = pnext_edge; | ||
290 | if (pedge == &edge_tail) | ||
291 | return; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | #endif // !id386 | ||
296 | |||
297 | |||
298 | /* | ||
299 | ============== | ||
300 | R_CleanupSpan | ||
301 | ============== | ||
302 | */ | ||
303 | void R_CleanupSpan () | ||
304 | { | ||
305 | surf_t *surf; | ||
306 | int iu; | ||
307 | espan_t *span; | ||
308 | |||
309 | // now that we've reached the right edge of the screen, we're done with any | ||
310 | // unfinished surfaces, so emit a span for whatever's on top | ||
311 | surf = surfaces[1].next; | ||
312 | iu = edge_tail_u_shift20; | ||
313 | if (iu > surf->last_u) | ||
314 | { | ||
315 | span = span_p++; | ||
316 | span->u = surf->last_u; | ||
317 | span->count = iu - span->u; | ||
318 | span->v = current_iv; | ||
319 | span->pnext = surf->spans; | ||
320 | surf->spans = span; | ||
321 | } | ||
322 | |||
323 | // reset spanstate for all surfaces in the surface stack | ||
324 | do | ||
325 | { | ||
326 | surf->spanstate = 0; | ||
327 | surf = surf->next; | ||
328 | } while (surf != &surfaces[1]); | ||
329 | } | ||
330 | |||
331 | |||
332 | /* | ||
333 | ============== | ||
334 | R_LeadingEdgeBackwards | ||
335 | ============== | ||
336 | */ | ||
337 | static inline void R_LeadingEdgeBackwards (edge_t *edge) | ||
338 | { | ||
339 | espan_t *span; | ||
340 | surf_t *surf, *surf2; | ||
341 | int iu; | ||
342 | |||
343 | // it's adding a new surface in, so find the correct place | ||
344 | surf = &surfaces[edge->surfs[1]]; | ||
345 | |||
346 | // don't start a span if this is an inverted span, with the end | ||
347 | // edge preceding the start edge (that is, we've already seen the | ||
348 | // end edge) | ||
349 | if (++surf->spanstate == 1) | ||
350 | { | ||
351 | surf2 = surfaces[1].next; | ||
352 | |||
353 | if (surf->key > surf2->key) | ||
354 | goto newtop; | ||
355 | |||
356 | // if it's two surfaces on the same plane, the one that's already | ||
357 | // active is in front, so keep going unless it's a bmodel | ||
358 | if (surf->insubmodel && (surf->key == surf2->key)) | ||
359 | { | ||
360 | // must be two bmodels in the same leaf; don't care, because they'll | ||
361 | // never be farthest anyway | ||
362 | goto newtop; | ||
363 | } | ||
364 | |||
365 | continue_search: | ||
366 | |||
367 | do | ||
368 | { | ||
369 | surf2 = surf2->next; | ||
370 | } while (surf->key < surf2->key); | ||
371 | |||
372 | if (surf->key == surf2->key) | ||
373 | { | ||
374 | // if it's two surfaces on the same plane, the one that's already | ||
375 | // active is in front, so keep going unless it's a bmodel | ||
376 | if (!surf->insubmodel) | ||
377 | goto continue_search; | ||
378 | |||
379 | // must be two bmodels in the same leaf; don't care which is really | ||
380 | // in front, because they'll never be farthest anyway | ||
381 | } | ||
382 | |||
383 | goto gotposition; | ||
384 | |||
385 | newtop: | ||
386 | // emit a span (obscures current top) | ||
387 | iu = edge->u >> 20; | ||
388 | |||
389 | if (iu > surf2->last_u) | ||
390 | { | ||
391 | span = span_p++; | ||
392 | span->u = surf2->last_u; | ||
393 | span->count = iu - span->u; | ||
394 | span->v = current_iv; | ||
395 | span->pnext = surf2->spans; | ||
396 | surf2->spans = span; | ||
397 | } | ||
398 | |||
399 | // set last_u on the new span | ||
400 | surf->last_u = iu; | ||
401 | |||
402 | gotposition: | ||
403 | // insert before surf2 | ||
404 | surf->next = surf2; | ||
405 | surf->prev = surf2->prev; | ||
406 | surf2->prev->next = surf; | ||
407 | surf2->prev = surf; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | |||
412 | /* | ||
413 | ============== | ||
414 | R_TrailingEdge | ||
415 | ============== | ||
416 | */ | ||
417 | static inline void R_TrailingEdge (surf_t *surf, edge_t *edge) | ||
418 | { | ||
419 | espan_t *span; | ||
420 | int iu; | ||
421 | |||
422 | // don't generate a span if this is an inverted span, with the end | ||
423 | // edge preceding the start edge (that is, we haven't seen the | ||
424 | // start edge yet) | ||
425 | if (--surf->spanstate == 0) | ||
426 | { | ||
427 | if (surf->insubmodel) | ||
428 | r_bmodelactive--; | ||
429 | |||
430 | if (surf == surfaces[1].next) | ||
431 | { | ||
432 | // emit a span (current top going away) | ||
433 | iu = edge->u >> 20; | ||
434 | if (iu > surf->last_u) | ||
435 | { | ||
436 | span = span_p++; | ||
437 | span->u = surf->last_u; | ||
438 | span->count = iu - span->u; | ||
439 | span->v = current_iv; | ||
440 | span->pnext = surf->spans; | ||
441 | surf->spans = span; | ||
442 | } | ||
443 | |||
444 | // set last_u on the surface below | ||
445 | surf->next->last_u = iu; | ||
446 | } | ||
447 | |||
448 | surf->prev->next = surf->next; | ||
449 | surf->next->prev = surf->prev; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | |||
454 | #if !id386 | ||
455 | |||
456 | /* | ||
457 | ============== | ||
458 | R_LeadingEdge | ||
459 | ============== | ||
460 | */ | ||
461 | static inline void R_LeadingEdge (edge_t *edge) | ||
462 | { | ||
463 | espan_t *span; | ||
464 | surf_t *surf, *surf2; | ||
465 | int iu; | ||
466 | double fu, newzi, testzi, newzitop, newzibottom; | ||
467 | |||
468 | if (edge->surfs[1]) | ||
469 | { | ||
470 | // it's adding a new surface in, so find the correct place | ||
471 | surf = &surfaces[edge->surfs[1]]; | ||
472 | |||
473 | // don't start a span if this is an inverted span, with the end | ||
474 | // edge preceding the start edge (that is, we've already seen the | ||
475 | // end edge) | ||
476 | if (++surf->spanstate == 1) | ||
477 | { | ||
478 | if (surf->insubmodel) | ||
479 | r_bmodelactive++; | ||
480 | |||
481 | surf2 = surfaces[1].next; | ||
482 | |||
483 | if (surf->key < surf2->key) | ||
484 | goto newtop; | ||
485 | |||
486 | // if it's two surfaces on the same plane, the one that's already | ||
487 | // active is in front, so keep going unless it's a bmodel | ||
488 | if (surf->insubmodel && (surf->key == surf2->key)) | ||
489 | { | ||
490 | // must be two bmodels in the same leaf; sort on 1/z | ||
491 | fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); | ||
492 | newzi = surf->d_ziorigin + fv*surf->d_zistepv + | ||
493 | fu*surf->d_zistepu; | ||
494 | newzibottom = newzi * 0.99; | ||
495 | |||
496 | testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + | ||
497 | fu*surf2->d_zistepu; | ||
498 | |||
499 | if (newzibottom >= testzi) | ||
500 | { | ||
501 | goto newtop; | ||
502 | } | ||
503 | |||
504 | newzitop = newzi * 1.01; | ||
505 | if (newzitop >= testzi) | ||
506 | { | ||
507 | if (surf->d_zistepu >= surf2->d_zistepu) | ||
508 | { | ||
509 | goto newtop; | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | |||
514 | continue_search: | ||
515 | |||
516 | do | ||
517 | { | ||
518 | surf2 = surf2->next; | ||
519 | } while (surf->key > surf2->key); | ||
520 | |||
521 | if (surf->key == surf2->key) | ||
522 | { | ||
523 | // if it's two surfaces on the same plane, the one that's already | ||
524 | // active is in front, so keep going unless it's a bmodel | ||
525 | if (!surf->insubmodel) | ||
526 | goto continue_search; | ||
527 | |||
528 | // must be two bmodels in the same leaf; sort on 1/z | ||
529 | fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); | ||
530 | newzi = surf->d_ziorigin + fv*surf->d_zistepv + | ||
531 | fu*surf->d_zistepu; | ||
532 | newzibottom = newzi * 0.99; | ||
533 | |||
534 | testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + | ||
535 | fu*surf2->d_zistepu; | ||
536 | |||
537 | if (newzibottom >= testzi) | ||
538 | { | ||
539 | goto gotposition; | ||
540 | } | ||
541 | |||
542 | newzitop = newzi * 1.01; | ||
543 | if (newzitop >= testzi) | ||
544 | { | ||
545 | if (surf->d_zistepu >= surf2->d_zistepu) | ||
546 | { | ||
547 | goto gotposition; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | goto continue_search; | ||
552 | } | ||
553 | |||
554 | goto gotposition; | ||
555 | |||
556 | newtop: | ||
557 | // emit a span (obscures current top) | ||
558 | iu = edge->u >> 20; | ||
559 | |||
560 | if (iu > surf2->last_u) | ||
561 | { | ||
562 | span = span_p++; | ||
563 | span->u = surf2->last_u; | ||
564 | span->count = iu - span->u; | ||
565 | span->v = current_iv; | ||
566 | span->pnext = surf2->spans; | ||
567 | surf2->spans = span; | ||
568 | } | ||
569 | |||
570 | // set last_u on the new span | ||
571 | surf->last_u = iu; | ||
572 | |||
573 | gotposition: | ||
574 | // insert before surf2 | ||
575 | surf->next = surf2; | ||
576 | surf->prev = surf2->prev; | ||
577 | surf2->prev->next = surf; | ||
578 | surf2->prev = surf; | ||
579 | } | ||
580 | } | ||
581 | } | ||
582 | |||
583 | |||
584 | /* | ||
585 | ============== | ||
586 | R_GenerateSpans | ||
587 | ============== | ||
588 | */ | ||
589 | void R_GenerateSpans (void) | ||
590 | { | ||
591 | edge_t *edge; | ||
592 | surf_t *surf; | ||
593 | |||
594 | r_bmodelactive = 0; | ||
595 | |||
596 | // clear active surfaces to just the background surface | ||
597 | surfaces[1].next = surfaces[1].prev = &surfaces[1]; | ||
598 | surfaces[1].last_u = edge_head_u_shift20; | ||
599 | |||
600 | // generate spans | ||
601 | for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) | ||
602 | { | ||
603 | if (edge->surfs[0]) | ||
604 | { | ||
605 | // it has a left surface, so a surface is going away for this span | ||
606 | surf = &surfaces[edge->surfs[0]]; | ||
607 | |||
608 | R_TrailingEdge (surf, edge); | ||
609 | |||
610 | if (!edge->surfs[1]) | ||
611 | continue; | ||
612 | } | ||
613 | |||
614 | R_LeadingEdge (edge); | ||
615 | } | ||
616 | |||
617 | R_CleanupSpan (); | ||
618 | } | ||
619 | |||
620 | #endif // !id386 | ||
621 | |||
622 | |||
623 | /* | ||
624 | ============== | ||
625 | R_GenerateSpansBackward | ||
626 | ============== | ||
627 | */ | ||
628 | void R_GenerateSpansBackward (void) | ||
629 | { | ||
630 | edge_t *edge; | ||
631 | |||
632 | r_bmodelactive = 0; | ||
633 | |||
634 | // clear active surfaces to just the background surface | ||
635 | surfaces[1].next = surfaces[1].prev = &surfaces[1]; | ||
636 | surfaces[1].last_u = edge_head_u_shift20; | ||
637 | |||
638 | // generate spans | ||
639 | for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) | ||
640 | { | ||
641 | if (edge->surfs[0]) | ||
642 | R_TrailingEdge (&surfaces[edge->surfs[0]], edge); | ||
643 | |||
644 | if (edge->surfs[1]) | ||
645 | R_LeadingEdgeBackwards (edge); | ||
646 | } | ||
647 | |||
648 | R_CleanupSpan (); | ||
649 | } | ||
650 | |||
651 | |||
652 | /* | ||
653 | ============== | ||
654 | R_ScanEdges | ||
655 | |||
656 | Input: | ||
657 | newedges[] array | ||
658 | this has links to edges, which have links to surfaces | ||
659 | |||
660 | Output: | ||
661 | Each surface has a linked list of its visible spans | ||
662 | ============== | ||
663 | */ | ||
664 | void R_ScanEdges (void) | ||
665 | { | ||
666 | int iv, bottom; | ||
667 | byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE]; | ||
668 | espan_t *basespan_p; | ||
669 | surf_t *s; | ||
670 | |||
671 | basespan_p = (espan_t *) | ||
672 | ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); | ||
673 | max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; | ||
674 | |||
675 | span_p = basespan_p; | ||
676 | |||
677 | // clear active edges to just the background edges around the whole screen | ||
678 | // FIXME: most of this only needs to be set up once | ||
679 | edge_head.u = r_refdef.vrect.x << 20; | ||
680 | edge_head_u_shift20 = edge_head.u >> 20; | ||
681 | edge_head.u_step = 0; | ||
682 | edge_head.prev = NULL; | ||
683 | edge_head.next = &edge_tail; | ||
684 | edge_head.surfs[0] = 0; | ||
685 | edge_head.surfs[1] = 1; | ||
686 | |||
687 | edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; | ||
688 | edge_tail_u_shift20 = edge_tail.u >> 20; | ||
689 | edge_tail.u_step = 0; | ||
690 | edge_tail.prev = &edge_head; | ||
691 | edge_tail.next = &edge_aftertail; | ||
692 | edge_tail.surfs[0] = 1; | ||
693 | edge_tail.surfs[1] = 0; | ||
694 | |||
695 | edge_aftertail.u = -1; // force a move | ||
696 | edge_aftertail.u_step = 0; | ||
697 | edge_aftertail.next = &edge_sentinel; | ||
698 | edge_aftertail.prev = &edge_tail; | ||
699 | |||
700 | // FIXME: do we need this now that we clamp x in r_draw.c? | ||
701 | edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this | ||
702 | edge_sentinel.prev = &edge_aftertail; | ||
703 | |||
704 | // | ||
705 | // process all scan lines | ||
706 | // | ||
707 | bottom = r_refdef.vrectbottom - 1; | ||
708 | |||
709 | for (iv=r_refdef.vrect.y ; iv<bottom ; iv++) | ||
710 | { | ||
711 | current_iv = iv; | ||
712 | fv = (float)iv; | ||
713 | |||
714 | // mark that the head (background start) span is pre-included | ||
715 | surfaces[1].spanstate = 1; | ||
716 | |||
717 | if (newedges[iv]) | ||
718 | { | ||
719 | R_InsertNewEdges (newedges[iv], edge_head.next); | ||
720 | } | ||
721 | |||
722 | (*pdrawfunc) (); | ||
723 | |||
724 | // flush the span list if we can't be sure we have enough spans left for | ||
725 | // the next scan | ||
726 | if (span_p >= max_span_p) | ||
727 | { | ||
728 | VID_UnlockBuffer (); | ||
729 | S_ExtraUpdate (); // don't let sound get messed up if going slow | ||
730 | VID_LockBuffer (); | ||
731 | |||
732 | if (r_drawculledpolys) | ||
733 | { | ||
734 | R_DrawCulledPolys (); | ||
735 | } | ||
736 | else | ||
737 | { | ||
738 | D_DrawSurfaces (); | ||
739 | } | ||
740 | |||
741 | // clear the surface span pointers | ||
742 | for (s = &surfaces[1] ; s<surface_p ; s++) | ||
743 | s->spans = NULL; | ||
744 | |||
745 | span_p = basespan_p; | ||
746 | } | ||
747 | |||
748 | if (removeedges[iv]) | ||
749 | R_RemoveEdges (removeedges[iv]); | ||
750 | |||
751 | if (edge_head.next != &edge_tail) | ||
752 | R_StepActiveU (edge_head.next); | ||
753 | } | ||
754 | |||
755 | // do the last scan (no need to step or sort or remove on the last scan) | ||
756 | |||
757 | current_iv = iv; | ||
758 | fv = (float)iv; | ||
759 | |||
760 | // mark that the head (background start) span is pre-included | ||
761 | surfaces[1].spanstate = 1; | ||
762 | |||
763 | if (newedges[iv]) | ||
764 | R_InsertNewEdges (newedges[iv], edge_head.next); | ||
765 | |||
766 | (*pdrawfunc) (); | ||
767 | |||
768 | // draw whatever's left in the span list | ||
769 | if (r_drawculledpolys) | ||
770 | R_DrawCulledPolys (); | ||
771 | else | ||
772 | D_DrawSurfaces (); | ||
773 | } | ||
774 | |||
775 | |||