Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 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 |
||
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 |
||
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 |
||
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 |
||
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 |