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