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