1 /*
2 Copyright (C) 1997-2001 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 "r_local.h"
23
24 #ifndef id386
R_SurfacePatch(void)25 void R_SurfacePatch (void)
26 {
27 }
28
R_EdgeCodeStart(void)29 void R_EdgeCodeStart (void)
30 {
31 }
32
R_EdgeCodeEnd(void)33 void R_EdgeCodeEnd (void)
34 {
35 }
36 #endif
37
38
39 #if 0
40 the complex cases add new polys on most lines, so dont optimize for keeping them the same
41 have multiple free span lists to try to get better coherence?
42 low depth complexity -- 1 to 3 or so
43
44 have a sentinal at both ends?
45 #endif
46
47
48 edge_t *auxedges;
49 edge_t *r_edges, *edge_p, *edge_max;
50
51 surf_t *surfaces, *surface_p, *surf_max;
52
53 // surfaces are generated in back to front order by the bsp, so if a surf
54 // pointer is greater than another one, it should be drawn in front
55 // surfaces[1] is the background, and is used as the active surface stack
56
57 edge_t *newedges[MAXHEIGHT];
58 edge_t *removeedges[MAXHEIGHT];
59
60 espan_t *span_p, *max_span_p;
61
62 int r_currentkey;
63
64 int current_iv;
65
66 int edge_head_u_shift20, edge_tail_u_shift20;
67
68 static void (*pdrawfunc)(void);
69
70 edge_t edge_head;
71 edge_t edge_tail;
72 edge_t edge_aftertail;
73 edge_t edge_sentinel;
74
75 float fv;
76
77 static int miplevel;
78
79 float scale_for_mip;
80 int ubasestep, errorterm, erroradjustup, erroradjustdown;
81
82 // FIXME: should go away
83 extern void R_RotateBmodel (void);
84 extern void R_TransformFrustum (void);
85
86
87
88 void R_GenerateSpans (void);
89 void R_GenerateSpansBackward (void);
90
91 void R_LeadingEdge (edge_t *edge);
92 void R_LeadingEdgeBackwards (edge_t *edge);
93 void R_TrailingEdge (surf_t *surf, edge_t *edge);
94
95
96 /*
97 ===============================================================================
98
99 EDGE SCANNING
100
101 ===============================================================================
102 */
103
104 /*
105 ==============
106 R_BeginEdgeFrame
107 ==============
108 */
R_BeginEdgeFrame(void)109 void R_BeginEdgeFrame (void)
110 {
111 int v;
112
113 edge_p = r_edges;
114 edge_max = &r_edges[r_numallocatededges];
115
116 surface_p = &surfaces[2]; // background is surface 1,
117 // surface 0 is a dummy
118 surfaces[1].spans = NULL; // no background spans yet
119 surfaces[1].flags = SURF_DRAWBACKGROUND;
120
121 // put the background behind everything in the world
122 if (sw_draworder->value)
123 {
124 pdrawfunc = R_GenerateSpansBackward;
125 surfaces[1].key = 0;
126 r_currentkey = 1;
127 }
128 else
129 {
130 pdrawfunc = R_GenerateSpans;
131 surfaces[1].key = 0x7FFfFFFF;
132 r_currentkey = 0;
133 }
134
135 // FIXME: set with memset
136 for (v=r_refdef.vrect.y ; v<r_refdef.vrectbottom ; v++)
137 {
138 newedges[v] = removeedges[v] = NULL;
139 }
140 }
141
142
143 #if !id386
144
145 /*
146 ==============
147 R_InsertNewEdges
148
149 Adds the edges in the linked list edgestoadd, adding them to the edges in the
150 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
151 sentinel at the end (actually, this is the active edge table starting at
152 edge_head.next).
153 ==============
154 */
R_InsertNewEdges(edge_t * edgestoadd,edge_t * edgelist)155 void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist)
156 {
157 edge_t *next_edge;
158
159 do
160 {
161 next_edge = edgestoadd->next;
162 edgesearch:
163 if (edgelist->u >= edgestoadd->u)
164 goto addedge;
165 edgelist=edgelist->next;
166 if (edgelist->u >= edgestoadd->u)
167 goto addedge;
168 edgelist=edgelist->next;
169 if (edgelist->u >= edgestoadd->u)
170 goto addedge;
171 edgelist=edgelist->next;
172 if (edgelist->u >= edgestoadd->u)
173 goto addedge;
174 edgelist=edgelist->next;
175 goto edgesearch;
176
177 // insert edgestoadd before edgelist
178 addedge:
179 edgestoadd->next = edgelist;
180 edgestoadd->prev = edgelist->prev;
181 edgelist->prev->next = edgestoadd;
182 edgelist->prev = edgestoadd;
183 } while ((edgestoadd = next_edge) != NULL);
184 }
185
186 #endif // !id386
187
188
189 #if !id386
190
191 /*
192 ==============
193 R_RemoveEdges
194 ==============
195 */
R_RemoveEdges(edge_t * pedge)196 void R_RemoveEdges (edge_t *pedge)
197 {
198
199 do
200 {
201 pedge->next->prev = pedge->prev;
202 pedge->prev->next = pedge->next;
203 } while ((pedge = pedge->nextremove) != NULL);
204 }
205
206 #endif // !id386
207
208
209 #if !id386
210
211 /*
212 ==============
213 R_StepActiveU
214 ==============
215 */
R_StepActiveU(edge_t * pedge)216 void R_StepActiveU (edge_t *pedge)
217 {
218 edge_t *pnext_edge, *pwedge;
219
220 while (1)
221 {
222 nextedge:
223 pedge->u += pedge->u_step;
224 if (pedge->u < pedge->prev->u)
225 goto pushback;
226 pedge = pedge->next;
227
228 pedge->u += pedge->u_step;
229 if (pedge->u < pedge->prev->u)
230 goto pushback;
231 pedge = pedge->next;
232
233 pedge->u += pedge->u_step;
234 if (pedge->u < pedge->prev->u)
235 goto pushback;
236 pedge = pedge->next;
237
238 pedge->u += pedge->u_step;
239 if (pedge->u < pedge->prev->u)
240 goto pushback;
241 pedge = pedge->next;
242
243 goto nextedge;
244
245 pushback:
246 if (pedge == &edge_aftertail)
247 return;
248
249 // push it back to keep it sorted
250 pnext_edge = pedge->next;
251
252 // pull the edge out of the edge list
253 pedge->next->prev = pedge->prev;
254 pedge->prev->next = pedge->next;
255
256 // find out where the edge goes in the edge list
257 pwedge = pedge->prev->prev;
258
259 while (pwedge->u > pedge->u)
260 {
261 pwedge = pwedge->prev;
262 }
263
264 // put the edge back into the edge list
265 pedge->next = pwedge->next;
266 pedge->prev = pwedge;
267 pedge->next->prev = pedge;
268 pwedge->next = pedge;
269
270 pedge = pnext_edge;
271 if (pedge == &edge_tail)
272 return;
273 }
274 }
275
276 #endif // !id386
277
278
279 /*
280 ==============
281 R_CleanupSpan
282 ==============
283 */
R_CleanupSpan(void)284 void R_CleanupSpan (void)
285 {
286 surf_t *surf;
287 int iu;
288 espan_t *span;
289
290 // now that we've reached the right edge of the screen, we're done with any
291 // unfinished surfaces, so emit a span for whatever's on top
292 surf = surfaces[1].next;
293 iu = edge_tail_u_shift20;
294 if (iu > surf->last_u)
295 {
296 span = span_p++;
297 span->u = surf->last_u;
298 span->count = iu - span->u;
299 span->v = current_iv;
300 span->pnext = surf->spans;
301 surf->spans = span;
302 }
303
304 // reset spanstate for all surfaces in the surface stack
305 do
306 {
307 surf->spanstate = 0;
308 surf = surf->next;
309 } while (surf != &surfaces[1]);
310 }
311
312
313 /*
314 ==============
315 R_LeadingEdgeBackwards
316 ==============
317 */
R_LeadingEdgeBackwards(edge_t * edge)318 void R_LeadingEdgeBackwards (edge_t *edge)
319 {
320 espan_t *span;
321 surf_t *surf, *surf2;
322 int iu;
323
324 // it's adding a new surface in, so find the correct place
325 surf = &surfaces[edge->surfs[1]];
326
327 // don't start a span if this is an inverted span, with the end
328 // edge preceding the start edge (that is, we've already seen the
329 // end edge)
330 if (++surf->spanstate == 1)
331 {
332 surf2 = surfaces[1].next;
333
334 if (surf->key > surf2->key)
335 goto newtop;
336
337 // if it's two surfaces on the same plane, the one that's already
338 // active is in front, so keep going unless it's a bmodel
339 if (surf->insubmodel && (surf->key == surf2->key))
340 {
341 // must be two bmodels in the same leaf; don't care, because they'll
342 // never be farthest anyway
343 goto newtop;
344 }
345
346 continue_search:
347
348 do
349 {
350 surf2 = surf2->next;
351 } while (surf->key < surf2->key);
352
353 if (surf->key == surf2->key)
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)
358 goto continue_search;
359
360 // must be two bmodels in the same leaf; don't care which is really
361 // in front, because they'll never be farthest anyway
362 }
363
364 goto gotposition;
365
366 newtop:
367 // emit a span (obscures current top)
368 iu = edge->u >> 20;
369
370 if (iu > surf2->last_u)
371 {
372 span = span_p++;
373 span->u = surf2->last_u;
374 span->count = iu - span->u;
375 span->v = current_iv;
376 span->pnext = surf2->spans;
377 surf2->spans = span;
378 }
379
380 // set last_u on the new span
381 surf->last_u = iu;
382
383 gotposition:
384 // insert before surf2
385 surf->next = surf2;
386 surf->prev = surf2->prev;
387 surf2->prev->next = surf;
388 surf2->prev = surf;
389 }
390 }
391
392
393 /*
394 ==============
395 R_TrailingEdge
396 ==============
397 */
R_TrailingEdge(surf_t * surf,edge_t * edge)398 void R_TrailingEdge (surf_t *surf, edge_t *edge)
399 {
400 espan_t *span;
401 int iu;
402
403 // don't generate a span if this is an inverted span, with the end
404 // edge preceding the start edge (that is, we haven't seen the
405 // start edge yet)
406 if (--surf->spanstate == 0)
407 {
408 if (surf == surfaces[1].next)
409 {
410 // emit a span (current top going away)
411 iu = edge->u >> 20;
412 if (iu > surf->last_u)
413 {
414 span = span_p++;
415 span->u = surf->last_u;
416 span->count = iu - span->u;
417 span->v = current_iv;
418 span->pnext = surf->spans;
419 surf->spans = span;
420 }
421
422 // set last_u on the surface below
423 surf->next->last_u = iu;
424 }
425
426 surf->prev->next = surf->next;
427 surf->next->prev = surf->prev;
428 }
429 }
430
431
432 #if !id386
433
434 /*
435 ==============
436 R_LeadingEdge
437 ==============
438 */
R_LeadingEdge(edge_t * edge)439 void R_LeadingEdge (edge_t *edge)
440 {
441 espan_t *span;
442 surf_t *surf, *surf2;
443 int iu;
444 float fu, newzi, testzi, newzitop, newzibottom;
445
446 if (edge->surfs[1])
447 {
448 // it's adding a new surface in, so find the correct place
449 surf = &surfaces[edge->surfs[1]];
450
451 // don't start a span if this is an inverted span, with the end
452 // edge preceding the start edge (that is, we've already seen the
453 // end edge)
454 if (++surf->spanstate == 1)
455 {
456 surf2 = surfaces[1].next;
457
458 if (surf->key < surf2->key)
459 goto newtop;
460
461 // if it's two surfaces on the same plane, the one that's already
462 // active is in front, so keep going unless it's a bmodel
463 if (surf->insubmodel && (surf->key == surf2->key))
464 {
465 // must be two bmodels in the same leaf; sort on 1/z
466 fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
467 newzi = surf->d_ziorigin + fv*surf->d_zistepv +
468 fu*surf->d_zistepu;
469 newzibottom = newzi * 0.99;
470
471 testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
472 fu*surf2->d_zistepu;
473
474 if (newzibottom >= testzi)
475 {
476 goto newtop;
477 }
478
479 newzitop = newzi * 1.01;
480 if (newzitop >= testzi)
481 {
482 if (surf->d_zistepu >= surf2->d_zistepu)
483 {
484 goto newtop;
485 }
486 }
487 }
488
489 continue_search:
490
491 do
492 {
493 surf2 = surf2->next;
494 } while (surf->key > surf2->key);
495
496 if (surf->key == surf2->key)
497 {
498 // if it's two surfaces on the same plane, the one that's already
499 // active is in front, so keep going unless it's a bmodel
500 if (!surf->insubmodel)
501 goto continue_search;
502
503 // must be two bmodels in the same leaf; sort on 1/z
504 fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000);
505 newzi = surf->d_ziorigin + fv*surf->d_zistepv +
506 fu*surf->d_zistepu;
507 newzibottom = newzi * 0.99;
508
509 testzi = surf2->d_ziorigin + fv*surf2->d_zistepv +
510 fu*surf2->d_zistepu;
511
512 if (newzibottom >= testzi)
513 {
514 goto gotposition;
515 }
516
517 newzitop = newzi * 1.01;
518 if (newzitop >= testzi)
519 {
520 if (surf->d_zistepu >= surf2->d_zistepu)
521 {
522 goto gotposition;
523 }
524 }
525
526 goto continue_search;
527 }
528
529 goto gotposition;
530
531 newtop:
532 // emit a span (obscures current top)
533 iu = edge->u >> 20;
534
535 if (iu > surf2->last_u)
536 {
537 span = span_p++;
538 span->u = surf2->last_u;
539 span->count = iu - span->u;
540 span->v = current_iv;
541 span->pnext = surf2->spans;
542 surf2->spans = span;
543 }
544
545 // set last_u on the new span
546 surf->last_u = iu;
547
548 gotposition:
549 // insert before surf2
550 surf->next = surf2;
551 surf->prev = surf2->prev;
552 surf2->prev->next = surf;
553 surf2->prev = surf;
554 }
555 }
556 }
557
558
559 /*
560 ==============
561 R_GenerateSpans
562 ==============
563 */
R_GenerateSpans(void)564 void R_GenerateSpans (void)
565 {
566 edge_t *edge;
567 surf_t *surf;
568
569 // clear active surfaces to just the background surface
570 surfaces[1].next = surfaces[1].prev = &surfaces[1];
571 surfaces[1].last_u = edge_head_u_shift20;
572
573 // generate spans
574 for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
575 {
576 if (edge->surfs[0])
577 {
578 // it has a left surface, so a surface is going away for this span
579 surf = &surfaces[edge->surfs[0]];
580
581 R_TrailingEdge (surf, edge);
582
583 if (!edge->surfs[1])
584 continue;
585 }
586
587 R_LeadingEdge (edge);
588 }
589
590 R_CleanupSpan ();
591 }
592
593 #endif // !id386
594
595
596 /*
597 ==============
598 R_GenerateSpansBackward
599 ==============
600 */
R_GenerateSpansBackward(void)601 void R_GenerateSpansBackward (void)
602 {
603 edge_t *edge;
604
605 // clear active surfaces to just the background surface
606 surfaces[1].next = surfaces[1].prev = &surfaces[1];
607 surfaces[1].last_u = edge_head_u_shift20;
608
609 // generate spans
610 for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
611 {
612 if (edge->surfs[0])
613 R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
614
615 if (edge->surfs[1])
616 R_LeadingEdgeBackwards (edge);
617 }
618
619 R_CleanupSpan ();
620 }
621
622
623 /*
624 ==============
625 R_ScanEdges
626
627 Input:
628 newedges[] array
629 this has links to edges, which have links to surfaces
630
631 Output:
632 Each surface has a linked list of its visible spans
633 ==============
634 */
R_ScanEdges(void)635 void R_ScanEdges (void)
636 {
637 int iv, bottom;
638 byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
639 espan_t *basespan_p;
640 surf_t *s;
641
642 basespan_p = (espan_t *)
643 ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
644 max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
645
646 span_p = basespan_p;
647
648 // clear active edges to just the background edges around the whole screen
649 // FIXME: most of this only needs to be set up once
650 edge_head.u = r_refdef.vrect.x << 20;
651 edge_head_u_shift20 = edge_head.u >> 20;
652 edge_head.u_step = 0;
653 edge_head.prev = NULL;
654 edge_head.next = &edge_tail;
655 edge_head.surfs[0] = 0;
656 edge_head.surfs[1] = 1;
657
658 edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
659 edge_tail_u_shift20 = edge_tail.u >> 20;
660 edge_tail.u_step = 0;
661 edge_tail.prev = &edge_head;
662 edge_tail.next = &edge_aftertail;
663 edge_tail.surfs[0] = 1;
664 edge_tail.surfs[1] = 0;
665
666 edge_aftertail.u = -1; // force a move
667 edge_aftertail.u_step = 0;
668 edge_aftertail.next = &edge_sentinel;
669 edge_aftertail.prev = &edge_tail;
670
671 // FIXME: do we need this now that we clamp x in r_draw.c?
672 edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
673 edge_sentinel.prev = &edge_aftertail;
674
675 //
676 // process all scan lines
677 //
678 bottom = r_refdef.vrectbottom - 1;
679
680 for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
681 {
682 current_iv = iv;
683 fv = (float)iv;
684
685 // mark that the head (background start) span is pre-included
686 surfaces[1].spanstate = 1;
687
688 if (newedges[iv])
689 {
690 R_InsertNewEdges (newedges[iv], edge_head.next);
691 }
692
693 (*pdrawfunc) ();
694
695 // flush the span list if we can't be sure we have enough spans left for
696 // the next scan
697 if (span_p > max_span_p)
698 {
699 D_DrawSurfaces ();
700
701 // clear the surface span pointers
702 for (s = &surfaces[1] ; s<surface_p ; s++)
703 s->spans = NULL;
704
705 span_p = basespan_p;
706 }
707
708 if (removeedges[iv])
709 R_RemoveEdges (removeedges[iv]);
710
711 if (edge_head.next != &edge_tail)
712 R_StepActiveU (edge_head.next);
713 }
714
715 // do the last scan (no need to step or sort or remove on the last scan)
716
717 current_iv = iv;
718 fv = (float)iv;
719
720 // mark that the head (background start) span is pre-included
721 surfaces[1].spanstate = 1;
722
723 if (newedges[iv])
724 R_InsertNewEdges (newedges[iv], edge_head.next);
725
726 (*pdrawfunc) ();
727
728 // draw whatever's left in the span list
729 D_DrawSurfaces ();
730 }
731
732
733 /*
734 =========================================================================
735
736 SURFACE FILLING
737
738 =========================================================================
739 */
740
741 msurface_t *pface;
742 surfcache_t *pcurrentcache;
743 vec3_t transformed_modelorg;
744 vec3_t world_transformed_modelorg;
745 vec3_t local_modelorg;
746
747 /*
748 =============
749 D_MipLevelForScale
750 =============
751 */
D_MipLevelForScale(float scale)752 int D_MipLevelForScale (float scale)
753 {
754 int lmiplevel;
755
756 if (scale >= d_scalemip[0] )
757 lmiplevel = 0;
758 else if (scale >= d_scalemip[1] )
759 lmiplevel = 1;
760 else if (scale >= d_scalemip[2] )
761 lmiplevel = 2;
762 else
763 lmiplevel = 3;
764
765 if (lmiplevel < d_minmip)
766 lmiplevel = d_minmip;
767
768 return lmiplevel;
769 }
770
771
772 /*
773 ==============
774 D_FlatFillSurface
775
776 Simple single color fill with no texture mapping
777 ==============
778 */
D_FlatFillSurface(surf_t * surf,int color)779 void D_FlatFillSurface (surf_t *surf, int color)
780 {
781 espan_t *span;
782 byte *pdest;
783 int u, u2;
784
785 for (span=surf->spans ; span ; span=span->pnext)
786 {
787 pdest = (byte *)d_viewbuffer + r_screenwidth*span->v;
788 u = span->u;
789 u2 = span->u + span->count - 1;
790 for ( ; u <= u2 ; u++)
791 pdest[u] = color;
792 }
793 }
794
795
796 /*
797 ==============
798 D_CalcGradients
799 ==============
800 */
D_CalcGradients(msurface_t * pface)801 void D_CalcGradients (msurface_t *pface)
802 {
803 mplane_t *pplane;
804 float mipscale;
805 vec3_t p_temp1;
806 vec3_t p_saxis, p_taxis;
807 float t;
808
809 pplane = pface->plane;
810
811 mipscale = 1.0 / (float)(1 << miplevel);
812
813 TransformVector (pface->texinfo->vecs[0], p_saxis);
814 TransformVector (pface->texinfo->vecs[1], p_taxis);
815
816 t = xscaleinv * mipscale;
817 d_sdivzstepu = p_saxis[0] * t;
818 d_tdivzstepu = p_taxis[0] * t;
819
820 t = yscaleinv * mipscale;
821 d_sdivzstepv = -p_saxis[1] * t;
822 d_tdivzstepv = -p_taxis[1] * t;
823
824 d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
825 ycenter * d_sdivzstepv;
826 d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
827 ycenter * d_tdivzstepv;
828
829 VectorScale (transformed_modelorg, mipscale, p_temp1);
830
831 t = 0x10000*mipscale;
832 sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
833 ((pface->texturemins[0] << 16) >> miplevel)
834 + pface->texinfo->vecs[0][3]*t;
835 tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
836 ((pface->texturemins[1] << 16) >> miplevel)
837 + pface->texinfo->vecs[1][3]*t;
838
839 // PGM - changing flow speed for non-warping textures.
840 if (pface->texinfo->flags & SURF_FLOWING)
841 {
842 if(pface->texinfo->flags & SURF_WARP)
843 sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) ));
844 else
845 sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) ));
846 }
847 // PGM
848
849 //
850 // -1 (-epsilon) so we never wander off the edge of the texture
851 //
852 bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
853 bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
854 }
855
856
857 /*
858 ==============
859 D_BackgroundSurf
860
861 The grey background filler seen when there is a hole in the map
862 ==============
863 */
D_BackgroundSurf(surf_t * s)864 void D_BackgroundSurf (surf_t *s)
865 {
866 // set up a gradient for the background surface that places it
867 // effectively at infinity distance from the viewpoint
868 d_zistepu = 0;
869 d_zistepv = 0;
870 d_ziorigin = -0.9;
871
872 D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
873 D_DrawZSpans (s->spans);
874 }
875
876 /*
877 =================
878 D_TurbulentSurf
879 =================
880 */
D_TurbulentSurf(surf_t * s)881 void D_TurbulentSurf (surf_t *s)
882 {
883 d_zistepu = s->d_zistepu;
884 d_zistepv = s->d_zistepv;
885 d_ziorigin = s->d_ziorigin;
886
887 pface = s->msurf;
888 miplevel = 0;
889 cacheblock = pface->texinfo->image->pixels[0];
890 cachewidth = 64;
891
892 if (s->insubmodel)
893 {
894 // FIXME: we don't want to do all this for every polygon!
895 // TODO: store once at start of frame
896 currententity = s->entity; //FIXME: make this passed in to
897 // R_RotateBmodel ()
898 VectorSubtract (r_origin, currententity->origin,
899 local_modelorg);
900 TransformVector (local_modelorg, transformed_modelorg);
901
902 R_RotateBmodel (); // FIXME: don't mess with the frustum,
903 // make entity passed in
904 }
905
906 D_CalcGradients (pface);
907
908 //============
909 //PGM
910 // textures that aren't warping are just flowing. Use NonTurbulent8 instead
911 if(!(pface->texinfo->flags & SURF_WARP))
912 NonTurbulent8 (s->spans);
913 else
914 Turbulent8 (s->spans);
915 //PGM
916 //============
917
918 D_DrawZSpans (s->spans);
919
920 if (s->insubmodel)
921 {
922 //
923 // restore the old drawing state
924 // FIXME: we don't want to do this every time!
925 // TODO: speed up
926 //
927 currententity = NULL; // &r_worldentity;
928 VectorCopy (world_transformed_modelorg,
929 transformed_modelorg);
930 VectorCopy (base_vpn, vpn);
931 VectorCopy (base_vup, vup);
932 VectorCopy (base_vright, vright);
933 R_TransformFrustum ();
934 }
935 }
936
937 /*
938 ==============
939 D_SkySurf
940 ==============
941 */
D_SkySurf(surf_t * s)942 void D_SkySurf (surf_t *s)
943 {
944 pface = s->msurf;
945 miplevel = 0;
946 if (!pface->texinfo->image)
947 return;
948 cacheblock = pface->texinfo->image->pixels[0];
949 cachewidth = 256;
950
951 d_zistepu = s->d_zistepu;
952 d_zistepv = s->d_zistepv;
953 d_ziorigin = s->d_ziorigin;
954
955 D_CalcGradients (pface);
956
957 D_DrawSpans16 (s->spans);
958
959 // set up a gradient for the background surface that places it
960 // effectively at infinity distance from the viewpoint
961 d_zistepu = 0;
962 d_zistepv = 0;
963 d_ziorigin = -0.9;
964
965 D_DrawZSpans (s->spans);
966 }
967
968 /*
969 ==============
970 D_SolidSurf
971
972 Normal surface cached, texture mapped surface
973 ==============
974 */
D_SolidSurf(surf_t * s)975 void D_SolidSurf (surf_t *s)
976 {
977 d_zistepu = s->d_zistepu;
978 d_zistepv = s->d_zistepv;
979 d_ziorigin = s->d_ziorigin;
980
981 if (s->insubmodel)
982 {
983 // FIXME: we don't want to do all this for every polygon!
984 // TODO: store once at start of frame
985 currententity = s->entity; //FIXME: make this passed in to
986 // R_RotateBmodel ()
987 VectorSubtract (r_origin, currententity->origin, local_modelorg);
988 TransformVector (local_modelorg, transformed_modelorg);
989
990 R_RotateBmodel (); // FIXME: don't mess with the frustum,
991 // make entity passed in
992 }
993 else
994 currententity = &r_worldentity;
995
996 pface = s->msurf;
997 #if 1
998 miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
999 #else
1000 {
1001 float dot;
1002 float normal[3];
1003
1004 if ( s->insubmodel )
1005 {
1006 VectorCopy( pface->plane->normal, normal );
1007 // TransformVector( pface->plane->normal, normal);
1008 dot = DotProduct( normal, vpn );
1009 }
1010 else
1011 {
1012 VectorCopy( pface->plane->normal, normal );
1013 dot = DotProduct( normal, vpn );
1014 }
1015
1016 if ( pface->flags & SURF_PLANEBACK )
1017 dot = -dot;
1018
1019 if ( dot > 0 )
1020 printf( "blah" );
1021
1022 miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
1023 }
1024 #endif
1025
1026 // FIXME: make this passed in to D_CacheSurface
1027 pcurrentcache = D_CacheSurface (pface, miplevel);
1028
1029 cacheblock = (pixel_t *)pcurrentcache->data;
1030 cachewidth = pcurrentcache->width;
1031
1032 D_CalcGradients (pface);
1033
1034 D_DrawSpans16 (s->spans);
1035
1036 D_DrawZSpans (s->spans);
1037
1038 if (s->insubmodel)
1039 {
1040 //
1041 // restore the old drawing state
1042 // FIXME: we don't want to do this every time!
1043 // TODO: speed up
1044 //
1045 VectorCopy (world_transformed_modelorg,
1046 transformed_modelorg);
1047 VectorCopy (base_vpn, vpn);
1048 VectorCopy (base_vup, vup);
1049 VectorCopy (base_vright, vright);
1050 R_TransformFrustum ();
1051 currententity = NULL; //&r_worldentity;
1052 }
1053 }
1054
1055 /*
1056 =============
1057 D_DrawflatSurfaces
1058
1059 To allow developers to see the polygon carving of the world
1060 =============
1061 */
D_DrawflatSurfaces(void)1062 void D_DrawflatSurfaces (void)
1063 {
1064 surf_t *s;
1065
1066 for (s = &surfaces[1] ; s<surface_p ; s++)
1067 {
1068 if (!s->spans)
1069 continue;
1070
1071 d_zistepu = s->d_zistepu;
1072 d_zistepv = s->d_zistepv;
1073 d_ziorigin = s->d_ziorigin;
1074
1075 // make a stable color for each surface by taking the low
1076 // bits of the msurface pointer
1077 D_FlatFillSurface (s, (int)s->msurf & 0xFF);
1078 D_DrawZSpans (s->spans);
1079 }
1080 }
1081
1082 /*
1083 ==============
1084 D_DrawSurfaces
1085
1086 Rasterize all the span lists. Guaranteed zero overdraw.
1087 May be called more than once a frame if the surf list overflows (higher res)
1088 ==============
1089 */
D_DrawSurfaces(void)1090 void D_DrawSurfaces (void)
1091 {
1092 surf_t *s;
1093
1094 // currententity = NULL; //&r_worldentity;
1095 VectorSubtract (r_origin, vec3_origin, modelorg);
1096 TransformVector (modelorg, transformed_modelorg);
1097 VectorCopy (transformed_modelorg, world_transformed_modelorg);
1098
1099 if (!sw_drawflat->value)
1100 {
1101 for (s = &surfaces[1] ; s<surface_p ; s++)
1102 {
1103 if (!s->spans)
1104 continue;
1105
1106 r_drawnpolycount++;
1107
1108 if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) )
1109 D_SolidSurf (s);
1110 else if (s->flags & SURF_DRAWSKYBOX)
1111 D_SkySurf (s);
1112 else if (s->flags & SURF_DRAWBACKGROUND)
1113 D_BackgroundSurf (s);
1114 else if (s->flags & SURF_DRAWTURB)
1115 D_TurbulentSurf (s);
1116 }
1117 }
1118 else
1119 D_DrawflatSurfaces ();
1120
1121 currententity = NULL; //&r_worldentity;
1122 VectorSubtract (r_origin, vec3_origin, modelorg);
1123 R_TransformFrustum ();
1124 }
1125
1126