1 /*
2 	d_sprite.c
3 
4 	software top-level rasterization driver module for drawing sprites
5 
6 	Copyright (C) 1996-1997  Id Software, Inc.
7 
8 	This program is free software; you can redistribute it and/or
9 	modify it under the terms of the GNU General Public License
10 	as published by the Free Software Foundation; either version 2
11 	of the License, or (at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 	See the GNU General Public License for more details.
18 
19 	You should have received a copy of the GNU General Public License
20 	along with this program; if not, write to:
21 
22 		Free Software Foundation, Inc.
23 		59 Temple Place - Suite 330
24 		Boston, MA  02111-1307, USA
25 
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #define NH_DEFINE
32 #include "namehack.h"
33 
34 #include "QF/render.h"
35 #include "QF/sys.h"
36 
37 #include "compat.h"
38 #include "d_local.h"
39 #include "r_internal.h"
40 #include "vid_internal.h"
41 
42 static int  sprite_height;
43 static int  minindex, maxindex;
44 static sspan_t *sprite_spans;
45 
46 
47 
48 void
sw32_D_SpriteDrawSpans(sspan_t * pspan)49 sw32_D_SpriteDrawSpans (sspan_t *pspan)
50 {
51 	switch(sw32_r_pixbytes) {
52 	case 1:
53 	{
54 		int         count, spancount, izistep;
55 		int         izi;
56 		byte       *pbase;
57 		byte       *pdest;
58 		fixed16_t   s, t, snext, tnext, sstep, tstep;
59 		float       sdivz, tdivz, zi, z, du, dv, spancountminus1;
60 		float       sdivz8stepu, tdivz8stepu, zi8stepu;
61 		byte        btemp;
62 		short      *pz;
63 
64 		sstep = 0;							// keep compiler happy
65 		tstep = 0;							// ditto
66 
67 		pbase = (byte *) sw32_cacheblock;
68 
69 		sdivz8stepu = sw32_d_sdivzstepu * 8;
70 		tdivz8stepu = sw32_d_tdivzstepu * 8;
71 		zi8stepu = d_zistepu * 8 * 65536.0f;
72 
73 		// we count on FP exceptions being turned off to avoid range problems
74 		izistep = (int) (d_zistepu * 0x8000 * 0x10000);
75 
76 		do {
77 			pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
78 			pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
79 
80 			count = pspan->count;
81 
82 			if (count <= 0)
83 				goto NextSpan1;
84 
85 			// calculate the initial s/z, t/z, 1/z, s, and t and clamp
86 			du = (float) pspan->u;
87 			dv = (float) pspan->v;
88 
89 			sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
90 			tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
91 			zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
92 			z = sw32_d_zitable[(int) zi];
93 			// we count on FP exceptions being turned off to avoid range
94 			// problems
95 
96 			izi = (int) (zi * 0x8000);
97 
98 			s = (int) (sdivz * z) + sw32_sadjust;
99 			if (s > sw32_bbextents)
100 				s = sw32_bbextents;
101 			else if (s < 0)
102 				s = 0;
103 
104 			t = (int) (tdivz * z) + sw32_tadjust;
105 			if (t > sw32_bbextentt)
106 				t = sw32_bbextentt;
107 			else if (t < 0)
108 				t = 0;
109 
110 			do {
111 				// calculate s and t at the far end of the span
112 				if (count >= 8)
113 					spancount = 8;
114 				else
115 					spancount = count;
116 
117 				count -= spancount;
118 
119 				if (count) {
120 					// calculate s/z, t/z, zi->fixed s and t at far end of
121 					// span, calculate s and t steps across span by shifting
122 					sdivz += sdivz8stepu;
123 					tdivz += tdivz8stepu;
124 					zi += zi8stepu;
125 					z = sw32_d_zitable[(int) zi];
126 
127 					snext = (int) (sdivz * z) + sw32_sadjust;
128 					if (snext > sw32_bbextents)
129 						snext = sw32_bbextents;
130 					else if (snext < 8)
131 						snext = 8;			// prevent round-off error on <0
132 											// steps from causing overstepping
133 											// & running off the texture's edge
134 
135 					tnext = (int) (tdivz * z) + sw32_tadjust;
136 						if (tnext > sw32_bbextentt)
137 							tnext = sw32_bbextentt;
138 						else if (tnext < 8)
139 							tnext = 8;			// guard against round-off
140 												// error on <0 steps
141 
142 						sstep = (snext - s) >> 3;
143 						tstep = (tnext - t) >> 3;
144 				} else {
145 					// calculate s/z, t/z, zi->fixed s and t at last pixel
146 					// in span (so can't step off polygon), clamp,
147 					// calculate s and t steps across span by division,
148 					// biasing steps low so we don't run off the texture
149 					spancountminus1 = (float) (spancount - 1);
150 					sdivz += sw32_d_sdivzstepu * spancountminus1;
151 					tdivz += sw32_d_tdivzstepu * spancountminus1;
152 					zi += d_zistepu * 65536.0f * spancountminus1;
153 					z = sw32_d_zitable[(int) zi];
154 					snext = (int) (sdivz * z) + sw32_sadjust;
155 					if (snext > sw32_bbextents)
156 						snext = sw32_bbextents;
157 					else if (snext < 8)
158 						snext = 8;			// prevent round-off error on <0
159 											// steps from from causing
160 											// overstepping & running off the
161 											// edge of the texture
162 
163 					tnext = (int) (tdivz * z) + sw32_tadjust;
164 					if (tnext > sw32_bbextentt)
165 						tnext = sw32_bbextentt;
166 					else if (tnext < 8)
167 						tnext = 8;			// guard against round-off error on
168 											// <0 steps
169 
170 					if (spancount > 1) {
171 						sstep = (snext - s) / (spancount - 1);
172 						tstep = (tnext - t) / (spancount - 1);
173 					}
174 				}
175 
176 				do {
177 					btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
178 					if (btemp != TRANSPARENT_COLOR) {
179 						if (*pz <= (izi >> 16)) {
180 							*pz = izi >> 16;
181 							*pdest = btemp;
182 						}
183 					}
184 
185 					izi += izistep;
186 					pdest++;
187 					pz++;
188 					s += sstep;
189 					t += tstep;
190 				} while (--spancount > 0);
191 
192 				s = snext;
193 				t = tnext;
194 
195 			} while (count > 0);
196 
197 NextSpan1:
198 			pspan++;
199 
200 		} while (pspan->count != DS_SPAN_LIST_END);
201 	}
202 	break;
203 
204 	case 2:
205 	{
206 		int         count, spancount, izistep;
207 		int         izi;
208 		byte       *pbase;
209 		short      *pdest;
210 		fixed16_t   s, t, snext, tnext, sstep, tstep;
211 		float       sdivz, tdivz, zi, z, du, dv, spancountminus1;
212 		float       sdivz8stepu, tdivz8stepu, zi8stepu;
213 		byte        btemp;
214 		short      *pz;
215 
216 		sstep = 0;							// keep compiler happy
217 		tstep = 0;							// ditto
218 
219 		pbase = (byte *) sw32_cacheblock;
220 
221 		sdivz8stepu = sw32_d_sdivzstepu * 8;
222 		tdivz8stepu = sw32_d_tdivzstepu * 8;
223 		zi8stepu = d_zistepu * 8 * 65536;
224 
225 		// we count on FP exceptions being turned off to avoid range problems
226 		izistep = (int) (d_zistepu * 0x8000 * 0x10000);
227 
228 		do {
229 			pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
230 			pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
231 
232 			count = pspan->count;
233 
234 			if (count <= 0)
235 				goto NextSpan2;
236 
237 			// calculate the initial s/z, t/z, 1/z, s, and t and clamp
238 			du = (float) pspan->u;
239 			dv = (float) pspan->v;
240 
241 			sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
242 			tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
243 			zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
244 			z = sw32_d_zitable[(int) zi];
245 			// we count on FP exceptions being turned off to avoid range
246 			// problems
247 			izi = (int) (zi * 0x8000);
248 
249 			s = (int) (sdivz * z) + sw32_sadjust;
250 			if (s > sw32_bbextents)
251 				s = sw32_bbextents;
252 			else if (s < 0)
253 				s = 0;
254 
255 			t = (int) (tdivz * z) + sw32_tadjust;
256 			if (t > sw32_bbextentt)
257 				t = sw32_bbextentt;
258 			else if (t < 0)
259 				t = 0;
260 
261 			do {
262 				// calculate s and t at the far end of the span
263 				if (count >= 8)
264 					spancount = 8;
265 				else
266 					spancount = count;
267 
268 				count -= spancount;
269 
270 				if (count) {
271 					// calculate s/z, t/z, zi->fixed s and t at far end of
272 					// span, calculate s and t steps across span by shifting
273 					sdivz += sdivz8stepu;
274 					tdivz += tdivz8stepu;
275 					zi += zi8stepu;
276 					z = sw32_d_zitable[(int) zi];
277 
278 					snext = (int) (sdivz * z) + sw32_sadjust;
279 					if (snext > sw32_bbextents)
280 						snext = sw32_bbextents;
281 					else if (snext < 8)
282 						snext = 8;			// prevent round-off error on <0
283 											// steps from causing overstepping
284 											// & running off the texture's edge
285 
286 					tnext = (int) (tdivz * z) + sw32_tadjust;
287 					if (tnext > sw32_bbextentt)
288 						tnext = sw32_bbextentt;
289 					else if (tnext < 8)
290 						tnext = 8;			// guard against round-off error on
291 											// <0 steps
292 
293 					sstep = (snext - s) >> 3;
294 					tstep = (tnext - t) >> 3;
295 				} else {
296 					// calculate s/z, t/z, zi->fixed s and t at last pixel in
297 					// span (so can't step off polygon), clamp, calculate s
298 					// and t steps across span by division, biasing steps
299 					// low so we don't run off the texture
300 					spancountminus1 = (float) (spancount - 1);
301 					sdivz += sw32_d_sdivzstepu * spancountminus1;
302 					tdivz += sw32_d_tdivzstepu * spancountminus1;
303 					zi += d_zistepu * 65536.0f * spancountminus1;
304 					z = sw32_d_zitable[(int) zi];
305 					snext = (int) (sdivz * z) + sw32_sadjust;
306 					if (snext > sw32_bbextents)
307 						snext = sw32_bbextents;
308 					else if (snext < 8)
309 						snext = 8;			// prevent round-off error on <0
310 											// steps from from causing
311 											// overstepping & running off the
312 											// edge of the texture
313 
314 					tnext = (int) (tdivz * z) + sw32_tadjust;
315 					if (tnext > sw32_bbextentt)
316 						tnext = sw32_bbextentt;
317 					else if (tnext < 8)
318 						tnext = 8;			// guard against round-off error on
319 											// <0 steps
320 
321 					if (spancount > 1) {
322 						sstep = (snext - s) / (spancount - 1);
323 						tstep = (tnext - t) / (spancount - 1);
324 					}
325 				}
326 
327 				do {
328 					btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
329 					if (btemp != TRANSPARENT_COLOR) {
330 						if (*pz <= (izi >> 16)) {
331 							*pz = izi >> 16;
332 							*pdest = sw32_8to16table[btemp];
333 						}
334 					}
335 
336 					izi += izistep;
337 					pdest++;
338 					pz++;
339 					s += sstep;
340 					t += tstep;
341 				} while (--spancount > 0);
342 
343 				s = snext;
344 				t = tnext;
345 
346 			} while (count > 0);
347 
348 NextSpan2:
349 			pspan++;
350 
351 		} while (pspan->count != DS_SPAN_LIST_END);
352 	}
353 	break;
354 
355 	case 4:
356 	{
357 		int         count, spancount, izistep;
358 		int         izi;
359 		byte       *pbase;
360 		int        *pdest;
361 		fixed16_t   s, t, snext, tnext, sstep, tstep;
362 		float       sdivz, tdivz, zi, z, du, dv, spancountminus1;
363 		float       sdivz8stepu, tdivz8stepu, zi8stepu;
364 		byte        btemp;
365 		short      *pz;
366 
367 		sstep = 0;							// keep compiler happy
368 		tstep = 0;							// ditto
369 
370 		pbase = (byte *) sw32_cacheblock;
371 
372 		sdivz8stepu = sw32_d_sdivzstepu * 8;
373 		tdivz8stepu = sw32_d_tdivzstepu * 8;
374 		zi8stepu = d_zistepu * 8 * 65536;
375 
376 		// we count on FP exceptions being turned off to avoid range problems
377 		izistep = (int) (d_zistepu * 0x8000 * 0x10000);
378 
379 		do {
380 			pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
381 			pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
382 
383 			count = pspan->count;
384 
385 			if (count <= 0)
386 				goto NextSpan4;
387 
388 			// calculate the initial s/z, t/z, 1/z, s, and t and clamp
389 			du = (float) pspan->u;
390 			dv = (float) pspan->v;
391 
392 			sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
393 			tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
394 			zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
395 			z = sw32_d_zitable[(int) zi];
396 			// we count on FP exceptions being turned off to avoid range
397 			// problems
398 			izi = (int) (zi * 0x8000);
399 
400 			s = (int) (sdivz * z) + sw32_sadjust;
401 			if (s > sw32_bbextents)
402 				s = sw32_bbextents;
403 			else if (s < 0)
404 				s = 0;
405 
406 			t = (int) (tdivz * z) + sw32_tadjust;
407 			if (t > sw32_bbextentt)
408 				t = sw32_bbextentt;
409 			else if (t < 0)
410 				t = 0;
411 
412 			do {
413 				// calculate s and t at the far end of the span
414 				if (count >= 8)
415 					spancount = 8;
416 				else
417 					spancount = count;
418 
419 				count -= spancount;
420 
421 				if (count) {
422 					// calculate s/z, t/z, zi->fixed s and t at far end of
423 					// span, calculate s and t steps across span by shifting
424 					sdivz += sdivz8stepu;
425 					tdivz += tdivz8stepu;
426 					zi += zi8stepu;
427 					z = sw32_d_zitable[(int) zi];
428 
429 					snext = (int) (sdivz * z) + sw32_sadjust;
430 					if (snext > sw32_bbextents)
431 						snext = sw32_bbextents;
432 					else if (snext < 8)
433 						snext = 8;			// prevent round-off error on <0
434 											// steps from causing overstepping
435 											// & running off the texture's edge
436 
437 					tnext = (int) (tdivz * z) + sw32_tadjust;
438 					if (tnext > sw32_bbextentt)
439 						tnext = sw32_bbextentt;
440 					else if (tnext < 8)
441 						tnext = 8;			// guard against round-off error on
442 											// <0 steps
443 
444 					sstep = (snext - s) >> 3;
445 					tstep = (tnext - t) >> 3;
446 				} else {
447 					// calculate s/z, t/z, zi->fixed s and t at last pixel in
448 					// span (so can't step off polygon), clamp, calculate s
449 					// and t steps across span by division, biasing steps low
450 					// so we don't run off the texture
451 					spancountminus1 = (float) (spancount - 1);
452 					sdivz += sw32_d_sdivzstepu * spancountminus1;
453 					tdivz += sw32_d_tdivzstepu * spancountminus1;
454 					zi += d_zistepu * 65536.0f * spancountminus1;
455 					z = sw32_d_zitable[(int) zi];
456 					snext = (int) (sdivz * z) + sw32_sadjust;
457 					if (snext > sw32_bbextents)
458 						snext = sw32_bbextents;
459 					else if (snext < 8)
460 						snext = 8;			// prevent round-off error on <0
461 											// steps fromcausing overstepping
462 											// & running off the texture's edge
463 
464 					tnext = (int) (tdivz * z) + sw32_tadjust;
465 					if (tnext > sw32_bbextentt)
466 						tnext = sw32_bbextentt;
467 					else if (tnext < 8)
468 						tnext = 8;			// guard against round-off error on
469 											// <0 steps
470 
471 					if (spancount > 1) {
472 						sstep = (snext - s) / (spancount - 1);
473 						tstep = (tnext - t) / (spancount - 1);
474 					}
475 				}
476 
477 				do {
478 					btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
479 					if (btemp != TRANSPARENT_COLOR) {
480 						if (*pz <= (izi >> 16)) {
481 							*pz = izi >> 16;
482 							*pdest = d_8to24table[btemp];
483 						}
484 					}
485 
486 					izi += izistep;
487 					pdest++;
488 					pz++;
489 					s += sstep;
490 					t += tstep;
491 				} while (--spancount > 0);
492 
493 				s = snext;
494 				t = tnext;
495 
496 			} while (count > 0);
497 
498 NextSpan4:
499 			pspan++;
500 
501 		} while (pspan->count != DS_SPAN_LIST_END);
502 	}
503 	break;
504 
505 	default:
506 		Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i",
507 				  sw32_r_pixbytes);
508 	}
509 }
510 
511 static void
D_SpriteScanLeftEdge(void)512 D_SpriteScanLeftEdge (void)
513 {
514 	int         i, v, itop, ibottom, lmaxindex;
515 	emitpoint_t *pvert, *pnext;
516 	sspan_t    *pspan;
517 	float       du, dv, vtop, vbottom, slope;
518 	fixed16_t   u, u_step;
519 
520 	pspan = sprite_spans;
521 	i = minindex;
522 	if (i == 0)
523 		i = sw32_r_spritedesc.nump;
524 
525 	lmaxindex = maxindex;
526 	if (lmaxindex == 0)
527 		lmaxindex = sw32_r_spritedesc.nump;
528 
529 	vtop = ceil (sw32_r_spritedesc.pverts[i].v);
530 
531 	do {
532 		pvert = &sw32_r_spritedesc.pverts[i];
533 		pnext = pvert - 1;
534 
535 		vbottom = ceil (pnext->v);
536 
537 		if (vtop < vbottom) {
538 			du = pnext->u - pvert->u;
539 			dv = pnext->v - pvert->v;
540 			slope = du / dv;
541 			u_step = (int) (slope * 0x10000);
542 			// adjust u to ceil the integer portion
543 			u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
544 				(0x10000 - 1);
545 			itop = (int) vtop;
546 			ibottom = (int) vbottom;
547 
548 			for (v = itop; v < ibottom; v++) {
549 				pspan->u = u >> 16;
550 				pspan->v = v;
551 				u += u_step;
552 				pspan++;
553 			}
554 		}
555 
556 		vtop = vbottom;
557 
558 		i--;
559 		if (i == 0)
560 			i = sw32_r_spritedesc.nump;
561 
562 	} while (i != lmaxindex);
563 }
564 
565 static void
D_SpriteScanRightEdge(void)566 D_SpriteScanRightEdge (void)
567 {
568 	int         i, v, itop, ibottom;
569 	emitpoint_t *pvert, *pnext;
570 	sspan_t    *pspan;
571 	float       du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
572 	fixed16_t   u, u_step;
573 
574 	pspan = sprite_spans;
575 	i = minindex;
576 
577 	vvert = sw32_r_spritedesc.pverts[i].v;
578 	if (vvert < r_refdef.fvrecty_adj)
579 		vvert = r_refdef.fvrecty_adj;
580 	if (vvert > r_refdef.fvrectbottom_adj)
581 		vvert = r_refdef.fvrectbottom_adj;
582 
583 	vtop = ceil (vvert);
584 
585 	do {
586 		pvert = &sw32_r_spritedesc.pverts[i];
587 		pnext = pvert + 1;
588 
589 		vnext = pnext->v;
590 		if (vnext < r_refdef.fvrecty_adj)
591 			vnext = r_refdef.fvrecty_adj;
592 		if (vnext > r_refdef.fvrectbottom_adj)
593 			vnext = r_refdef.fvrectbottom_adj;
594 
595 		vbottom = ceil (vnext);
596 
597 		if (vtop < vbottom) {
598 			uvert = pvert->u;
599 			if (uvert < r_refdef.fvrectx_adj)
600 				uvert = r_refdef.fvrectx_adj;
601 			if (uvert > r_refdef.fvrectright_adj)
602 				uvert = r_refdef.fvrectright_adj;
603 
604 			unext = pnext->u;
605 			if (unext < r_refdef.fvrectx_adj)
606 				unext = r_refdef.fvrectx_adj;
607 			if (unext > r_refdef.fvrectright_adj)
608 				unext = r_refdef.fvrectright_adj;
609 
610 			du = unext - uvert;
611 			dv = vnext - vvert;
612 			slope = du / dv;
613 			u_step = (int) (slope * 0x10000);
614 			// adjust u to ceil the integer portion
615 			u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) +
616 				(0x10000 - 1);
617 			itop = (int) vtop;
618 			ibottom = (int) vbottom;
619 
620 			for (v = itop; v < ibottom; v++) {
621 				pspan->count = (u >> 16) - pspan->u;
622 				u += u_step;
623 				pspan++;
624 			}
625 		}
626 
627 		vtop = vbottom;
628 		vvert = vnext;
629 
630 		i++;
631 		if (i == sw32_r_spritedesc.nump)
632 			i = 0;
633 
634 	} while (i != maxindex);
635 
636 	pspan->count = DS_SPAN_LIST_END;	// mark the end of the span list
637 }
638 
639 static void
D_SpriteCalculateGradients(void)640 D_SpriteCalculateGradients (void)
641 {
642 	vec3_t      p_normal, p_saxis, p_taxis, p_temp1;
643 	float       distinv;
644 
645 	sw32_TransformVector (sw32_r_spritedesc.vpn, p_normal);
646 	sw32_TransformVector (sw32_r_spritedesc.vright, p_saxis);
647 	sw32_TransformVector (sw32_r_spritedesc.vup, p_taxis);
648 	VectorNegate (p_taxis, p_taxis);
649 
650 	distinv = 1.0 / (-DotProduct (modelorg, sw32_r_spritedesc.vpn));
651 	distinv = min (distinv, 1.0);
652 
653 	sw32_d_sdivzstepu = p_saxis[0] * sw32_xscaleinv;
654 	sw32_d_tdivzstepu = p_taxis[0] * sw32_xscaleinv;
655 
656 	sw32_d_sdivzstepv = -p_saxis[1] * sw32_yscaleinv;
657 	sw32_d_tdivzstepv = -p_taxis[1] * sw32_yscaleinv;
658 
659 	d_zistepu = p_normal[0] * sw32_xscaleinv * distinv;
660 	d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv;
661 
662 	sw32_d_sdivzorigin = p_saxis[2] - sw32_xcenter * sw32_d_sdivzstepu -
663 		sw32_ycenter * sw32_d_sdivzstepv;
664 	sw32_d_tdivzorigin = p_taxis[2] - sw32_xcenter * sw32_d_tdivzstepu -
665 		sw32_ycenter * sw32_d_tdivzstepv;
666 	d_ziorigin = p_normal[2] * distinv - sw32_xcenter * d_zistepu -
667 		sw32_ycenter * d_zistepv;
668 
669 	sw32_TransformVector (modelorg, p_temp1);
670 
671 	sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
672 		(-(sw32_cachewidth >> 1) << 16);
673 	sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
674 		(-(sprite_height >> 1) << 16);
675 
676 	// -1 (-epsilon) so we never wander off the edge of the texture
677 	sw32_bbextents = (sw32_cachewidth << 16) - 1;
678 	sw32_bbextentt = (sprite_height << 16) - 1;
679 }
680 
681 void
sw32_D_DrawSprite(void)682 sw32_D_DrawSprite (void)
683 {
684 	int         i, nump;
685 	float       ymin, ymax;
686 	emitpoint_t *pverts;
687 	sspan_t     spans[MAXHEIGHT + 1];
688 
689 	sprite_spans = spans;
690 
691 	// find the top and bottom vertices, and make sure there's at least one
692 	// scan to draw
693 	ymin = 999999.9;
694 	ymax = -999999.9;
695 	pverts = sw32_r_spritedesc.pverts;
696 
697 	for (i = 0; i < sw32_r_spritedesc.nump; i++) {
698 		if (pverts->v < ymin) {
699 			ymin = pverts->v;
700 			minindex = i;
701 		}
702 
703 		if (pverts->v > ymax) {
704 			ymax = pverts->v;
705 			maxindex = i;
706 		}
707 
708 		pverts++;
709 	}
710 
711 	ymin = ceil (ymin);
712 	ymax = ceil (ymax);
713 
714 	if (ymin >= ymax)
715 		return;							// doesn't cross any scans at all
716 
717 	sw32_cachewidth = sw32_r_spritedesc.pspriteframe->width;
718 	sprite_height = sw32_r_spritedesc.pspriteframe->height;
719 	sw32_cacheblock = &sw32_r_spritedesc.pspriteframe->pixels[0];
720 
721 	// copy the first vertex to the last vertex, so we don't have to deal with
722 	// wrapping
723 	nump = sw32_r_spritedesc.nump;
724 	pverts = sw32_r_spritedesc.pverts;
725 	pverts[nump] = pverts[0];
726 
727 	D_SpriteCalculateGradients ();
728 	D_SpriteScanLeftEdge ();
729 	D_SpriteScanRightEdge ();
730 	sw32_D_SpriteDrawSpans (sprite_spans);
731 }
732