2001-08-25 02:47:11 +00:00
|
|
|
/*
|
|
|
|
d_sprite.c
|
|
|
|
|
|
|
|
software top-level rasterization driver module for drawing sprites
|
|
|
|
|
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
#define NH_DEFINE
|
|
|
|
#include "namehack.h"
|
2003-01-15 15:31:36 +00:00
|
|
|
|
2001-08-25 02:47:11 +00:00
|
|
|
#include "QF/render.h"
|
|
|
|
#include "QF/sys.h"
|
|
|
|
|
2001-08-31 19:13:16 +00:00
|
|
|
#include "compat.h"
|
2001-08-25 02:47:11 +00:00
|
|
|
#include "d_local.h"
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "r_internal.h"
|
2012-02-17 07:13:56 +00:00
|
|
|
#include "vid_internal.h"
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
static int sprite_height;
|
|
|
|
static int minindex, maxindex;
|
|
|
|
static sspan_t *sprite_spans;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_D_SpriteDrawSpans (sspan_t *pspan)
|
2001-08-25 02:47:11 +00:00
|
|
|
{
|
2012-02-22 07:32:34 +00:00
|
|
|
switch(sw32_r_pixbytes) {
|
2001-08-25 02:47:11 +00:00
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
int count, spancount, izistep;
|
|
|
|
int izi;
|
|
|
|
byte *pbase;
|
|
|
|
byte *pdest;
|
|
|
|
fixed16_t s, t, snext, tnext, sstep, tstep;
|
|
|
|
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
|
|
|
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
|
|
|
byte btemp;
|
|
|
|
short *pz;
|
|
|
|
|
|
|
|
sstep = 0; // keep compiler happy
|
|
|
|
tstep = 0; // ditto
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
pbase = (byte *) sw32_cacheblock;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz8stepu = sw32_d_sdivzstepu * 8;
|
|
|
|
tdivz8stepu = sw32_d_tdivzstepu * 8;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi8stepu = d_zistepu * 8 * 65536.0f;
|
|
|
|
|
|
|
|
// we count on FP exceptions being turned off to avoid range problems
|
|
|
|
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
|
|
|
|
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
count = pspan->count;
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
goto NextSpan1;
|
|
|
|
|
|
|
|
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
|
|
|
du = (float) pspan->u;
|
|
|
|
dv = (float) pspan->v;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
|
|
|
|
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
// we count on FP exceptions being turned off to avoid range
|
|
|
|
// problems
|
|
|
|
|
|
|
|
izi = (int) (zi * 0x8000);
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
s = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (s > sw32_bbextents)
|
|
|
|
s = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (s < 0)
|
|
|
|
s = 0;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
t = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (t > sw32_bbextentt)
|
|
|
|
t = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (t < 0)
|
|
|
|
t = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
// calculate s and t at the far end of the span
|
|
|
|
if (count >= 8)
|
|
|
|
spancount = 8;
|
|
|
|
else
|
|
|
|
spancount = count;
|
|
|
|
|
|
|
|
count -= spancount;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at far end of
|
|
|
|
// span, calculate s and t steps across span by shifting
|
|
|
|
sdivz += sdivz8stepu;
|
|
|
|
tdivz += tdivz8stepu;
|
|
|
|
zi += zi8stepu;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps from causing overstepping
|
|
|
|
// & running off the texture's edge
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off
|
|
|
|
// error on <0 steps
|
|
|
|
|
|
|
|
sstep = (snext - s) >> 3;
|
|
|
|
tstep = (tnext - t) >> 3;
|
|
|
|
} else {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at last pixel
|
|
|
|
// in span (so can't step off polygon), clamp,
|
|
|
|
// calculate s and t steps across span by division,
|
|
|
|
// biasing steps low so we don't run off the texture
|
|
|
|
spancountminus1 = (float) (spancount - 1);
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz += sw32_d_sdivzstepu * spancountminus1;
|
|
|
|
tdivz += sw32_d_tdivzstepu * spancountminus1;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi += d_zistepu * 65536.0f * spancountminus1;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps from from causing
|
|
|
|
// overstepping & running off the
|
|
|
|
// edge of the texture
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off error on
|
|
|
|
// <0 steps
|
|
|
|
|
|
|
|
if (spancount > 1) {
|
|
|
|
sstep = (snext - s) / (spancount - 1);
|
|
|
|
tstep = (tnext - t) / (spancount - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
|
2001-08-25 02:47:11 +00:00
|
|
|
if (btemp != TRANSPARENT_COLOR) {
|
|
|
|
if (*pz <= (izi >> 16)) {
|
|
|
|
*pz = izi >> 16;
|
|
|
|
*pdest = btemp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
izi += izistep;
|
|
|
|
pdest++;
|
|
|
|
pz++;
|
|
|
|
s += sstep;
|
|
|
|
t += tstep;
|
|
|
|
} while (--spancount > 0);
|
|
|
|
|
|
|
|
s = snext;
|
|
|
|
t = tnext;
|
|
|
|
|
|
|
|
} while (count > 0);
|
|
|
|
|
|
|
|
NextSpan1:
|
|
|
|
pspan++;
|
|
|
|
|
|
|
|
} while (pspan->count != DS_SPAN_LIST_END);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
int count, spancount, izistep;
|
|
|
|
int izi;
|
|
|
|
byte *pbase;
|
|
|
|
short *pdest;
|
|
|
|
fixed16_t s, t, snext, tnext, sstep, tstep;
|
|
|
|
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
|
|
|
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
|
|
|
byte btemp;
|
|
|
|
short *pz;
|
|
|
|
|
|
|
|
sstep = 0; // keep compiler happy
|
|
|
|
tstep = 0; // ditto
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
pbase = (byte *) sw32_cacheblock;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz8stepu = sw32_d_sdivzstepu * 8;
|
|
|
|
tdivz8stepu = sw32_d_tdivzstepu * 8;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi8stepu = d_zistepu * 8 * 65536;
|
|
|
|
|
|
|
|
// we count on FP exceptions being turned off to avoid range problems
|
|
|
|
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
|
|
|
|
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
count = pspan->count;
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
goto NextSpan2;
|
|
|
|
|
|
|
|
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
|
|
|
du = (float) pspan->u;
|
|
|
|
dv = (float) pspan->v;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
|
|
|
|
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
// we count on FP exceptions being turned off to avoid range
|
|
|
|
// problems
|
|
|
|
izi = (int) (zi * 0x8000);
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
s = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (s > sw32_bbextents)
|
|
|
|
s = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (s < 0)
|
|
|
|
s = 0;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
t = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (t > sw32_bbextentt)
|
|
|
|
t = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (t < 0)
|
|
|
|
t = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
// calculate s and t at the far end of the span
|
|
|
|
if (count >= 8)
|
|
|
|
spancount = 8;
|
|
|
|
else
|
|
|
|
spancount = count;
|
|
|
|
|
|
|
|
count -= spancount;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at far end of
|
|
|
|
// span, calculate s and t steps across span by shifting
|
|
|
|
sdivz += sdivz8stepu;
|
|
|
|
tdivz += tdivz8stepu;
|
|
|
|
zi += zi8stepu;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps from causing overstepping
|
|
|
|
// & running off the texture's edge
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off error on
|
|
|
|
// <0 steps
|
|
|
|
|
|
|
|
sstep = (snext - s) >> 3;
|
|
|
|
tstep = (tnext - t) >> 3;
|
|
|
|
} else {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at last pixel in
|
|
|
|
// span (so can't step off polygon), clamp, calculate s
|
|
|
|
// and t steps across span by division, biasing steps
|
|
|
|
// low so we don't run off the texture
|
|
|
|
spancountminus1 = (float) (spancount - 1);
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz += sw32_d_sdivzstepu * spancountminus1;
|
|
|
|
tdivz += sw32_d_tdivzstepu * spancountminus1;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi += d_zistepu * 65536.0f * spancountminus1;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps from from causing
|
|
|
|
// overstepping & running off the
|
|
|
|
// edge of the texture
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off error on
|
|
|
|
// <0 steps
|
|
|
|
|
|
|
|
if (spancount > 1) {
|
|
|
|
sstep = (snext - s) / (spancount - 1);
|
|
|
|
tstep = (tnext - t) / (spancount - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
|
2001-08-25 02:47:11 +00:00
|
|
|
if (btemp != TRANSPARENT_COLOR) {
|
|
|
|
if (*pz <= (izi >> 16)) {
|
|
|
|
*pz = izi >> 16;
|
2012-02-22 07:32:34 +00:00
|
|
|
*pdest = sw32_8to16table[btemp];
|
2001-08-25 02:47:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
izi += izistep;
|
|
|
|
pdest++;
|
|
|
|
pz++;
|
|
|
|
s += sstep;
|
|
|
|
t += tstep;
|
|
|
|
} while (--spancount > 0);
|
|
|
|
|
|
|
|
s = snext;
|
|
|
|
t = tnext;
|
|
|
|
|
|
|
|
} while (count > 0);
|
|
|
|
|
|
|
|
NextSpan2:
|
|
|
|
pspan++;
|
|
|
|
|
|
|
|
} while (pspan->count != DS_SPAN_LIST_END);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
int count, spancount, izistep;
|
|
|
|
int izi;
|
|
|
|
byte *pbase;
|
|
|
|
int *pdest;
|
|
|
|
fixed16_t s, t, snext, tnext, sstep, tstep;
|
|
|
|
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
|
|
|
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
|
|
|
byte btemp;
|
|
|
|
short *pz;
|
|
|
|
|
|
|
|
sstep = 0; // keep compiler happy
|
|
|
|
tstep = 0; // ditto
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
pbase = (byte *) sw32_cacheblock;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz8stepu = sw32_d_sdivzstepu * 8;
|
|
|
|
tdivz8stepu = sw32_d_tdivzstepu * 8;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi8stepu = d_zistepu * 8 * 65536;
|
|
|
|
|
|
|
|
// we count on FP exceptions being turned off to avoid range problems
|
|
|
|
izistep = (int) (d_zistepu * 0x8000 * 0x10000);
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u;
|
|
|
|
pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
count = pspan->count;
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
goto NextSpan4;
|
|
|
|
|
|
|
|
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
|
|
|
|
du = (float) pspan->u;
|
|
|
|
dv = (float) pspan->v;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu;
|
|
|
|
tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
// we count on FP exceptions being turned off to avoid range
|
|
|
|
// problems
|
|
|
|
izi = (int) (zi * 0x8000);
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
s = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (s > sw32_bbextents)
|
|
|
|
s = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (s < 0)
|
|
|
|
s = 0;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
t = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (t > sw32_bbextentt)
|
|
|
|
t = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (t < 0)
|
|
|
|
t = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
// calculate s and t at the far end of the span
|
|
|
|
if (count >= 8)
|
|
|
|
spancount = 8;
|
|
|
|
else
|
|
|
|
spancount = count;
|
|
|
|
|
|
|
|
count -= spancount;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at far end of
|
|
|
|
// span, calculate s and t steps across span by shifting
|
|
|
|
sdivz += sdivz8stepu;
|
|
|
|
tdivz += tdivz8stepu;
|
|
|
|
zi += zi8stepu;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps from causing overstepping
|
|
|
|
// & running off the texture's edge
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off error on
|
|
|
|
// <0 steps
|
|
|
|
|
|
|
|
sstep = (snext - s) >> 3;
|
|
|
|
tstep = (tnext - t) >> 3;
|
|
|
|
} else {
|
|
|
|
// calculate s/z, t/z, zi->fixed s and t at last pixel in
|
|
|
|
// span (so can't step off polygon), clamp, calculate s
|
|
|
|
// and t steps across span by division, biasing steps low
|
|
|
|
// so we don't run off the texture
|
|
|
|
spancountminus1 = (float) (spancount - 1);
|
2012-02-22 07:32:34 +00:00
|
|
|
sdivz += sw32_d_sdivzstepu * spancountminus1;
|
|
|
|
tdivz += sw32_d_tdivzstepu * spancountminus1;
|
2001-08-25 02:47:11 +00:00
|
|
|
zi += d_zistepu * 65536.0f * spancountminus1;
|
2012-02-22 07:32:34 +00:00
|
|
|
z = sw32_d_zitable[(int) zi];
|
|
|
|
snext = (int) (sdivz * z) + sw32_sadjust;
|
|
|
|
if (snext > sw32_bbextents)
|
|
|
|
snext = sw32_bbextents;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (snext < 8)
|
|
|
|
snext = 8; // prevent round-off error on <0
|
|
|
|
// steps fromcausing overstepping
|
|
|
|
// & running off the texture's edge
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
tnext = (int) (tdivz * z) + sw32_tadjust;
|
|
|
|
if (tnext > sw32_bbextentt)
|
|
|
|
tnext = sw32_bbextentt;
|
2001-08-25 02:47:11 +00:00
|
|
|
else if (tnext < 8)
|
|
|
|
tnext = 8; // guard against round-off error on
|
|
|
|
// <0 steps
|
|
|
|
|
|
|
|
if (spancount > 1) {
|
|
|
|
sstep = (snext - s) / (spancount - 1);
|
|
|
|
tstep = (tnext - t) / (spancount - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth];
|
2001-08-25 02:47:11 +00:00
|
|
|
if (btemp != TRANSPARENT_COLOR) {
|
|
|
|
if (*pz <= (izi >> 16)) {
|
|
|
|
*pz = izi >> 16;
|
|
|
|
*pdest = d_8to24table[btemp];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
izi += izistep;
|
|
|
|
pdest++;
|
|
|
|
pz++;
|
|
|
|
s += sstep;
|
|
|
|
t += tstep;
|
|
|
|
} while (--spancount > 0);
|
|
|
|
|
|
|
|
s = snext;
|
|
|
|
t = tnext;
|
|
|
|
|
|
|
|
} while (count > 0);
|
|
|
|
|
|
|
|
NextSpan4:
|
|
|
|
pspan++;
|
|
|
|
|
|
|
|
} while (pspan->count != DS_SPAN_LIST_END);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2002-05-14 06:12:29 +00:00
|
|
|
Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i",
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_r_pixbytes);
|
2001-08-25 02:47:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-08-25 02:47:11 +00:00
|
|
|
D_SpriteScanLeftEdge (void)
|
|
|
|
{
|
|
|
|
int i, v, itop, ibottom, lmaxindex;
|
|
|
|
emitpoint_t *pvert, *pnext;
|
|
|
|
sspan_t *pspan;
|
|
|
|
float du, dv, vtop, vbottom, slope;
|
|
|
|
fixed16_t u, u_step;
|
|
|
|
|
|
|
|
pspan = sprite_spans;
|
|
|
|
i = minindex;
|
|
|
|
if (i == 0)
|
2012-02-22 07:32:34 +00:00
|
|
|
i = sw32_r_spritedesc.nump;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
lmaxindex = maxindex;
|
|
|
|
if (lmaxindex == 0)
|
2012-02-22 07:32:34 +00:00
|
|
|
lmaxindex = sw32_r_spritedesc.nump;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
vtop = ceil (sw32_r_spritedesc.pverts[i].v);
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
pvert = &sw32_r_spritedesc.pverts[i];
|
2001-08-25 02:47:11 +00:00
|
|
|
pnext = pvert - 1;
|
|
|
|
|
|
|
|
vbottom = ceil (pnext->v);
|
|
|
|
|
|
|
|
if (vtop < vbottom) {
|
|
|
|
du = pnext->u - pvert->u;
|
|
|
|
dv = pnext->v - pvert->v;
|
|
|
|
slope = du / dv;
|
|
|
|
u_step = (int) (slope * 0x10000);
|
|
|
|
// adjust u to ceil the integer portion
|
|
|
|
u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
|
|
|
|
(0x10000 - 1);
|
|
|
|
itop = (int) vtop;
|
|
|
|
ibottom = (int) vbottom;
|
|
|
|
|
|
|
|
for (v = itop; v < ibottom; v++) {
|
|
|
|
pspan->u = u >> 16;
|
|
|
|
pspan->v = v;
|
|
|
|
u += u_step;
|
|
|
|
pspan++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vtop = vbottom;
|
|
|
|
|
|
|
|
i--;
|
|
|
|
if (i == 0)
|
2012-02-22 07:32:34 +00:00
|
|
|
i = sw32_r_spritedesc.nump;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
} while (i != lmaxindex);
|
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-08-25 02:47:11 +00:00
|
|
|
D_SpriteScanRightEdge (void)
|
|
|
|
{
|
|
|
|
int i, v, itop, ibottom;
|
|
|
|
emitpoint_t *pvert, *pnext;
|
|
|
|
sspan_t *pspan;
|
|
|
|
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
|
|
|
|
fixed16_t u, u_step;
|
|
|
|
|
|
|
|
pspan = sprite_spans;
|
|
|
|
i = minindex;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
vvert = sw32_r_spritedesc.pverts[i].v;
|
2001-08-25 02:47:11 +00:00
|
|
|
if (vvert < r_refdef.fvrecty_adj)
|
|
|
|
vvert = r_refdef.fvrecty_adj;
|
|
|
|
if (vvert > r_refdef.fvrectbottom_adj)
|
|
|
|
vvert = r_refdef.fvrectbottom_adj;
|
|
|
|
|
|
|
|
vtop = ceil (vvert);
|
|
|
|
|
|
|
|
do {
|
2012-02-22 07:32:34 +00:00
|
|
|
pvert = &sw32_r_spritedesc.pverts[i];
|
2001-08-25 02:47:11 +00:00
|
|
|
pnext = pvert + 1;
|
|
|
|
|
|
|
|
vnext = pnext->v;
|
|
|
|
if (vnext < r_refdef.fvrecty_adj)
|
|
|
|
vnext = r_refdef.fvrecty_adj;
|
|
|
|
if (vnext > r_refdef.fvrectbottom_adj)
|
|
|
|
vnext = r_refdef.fvrectbottom_adj;
|
|
|
|
|
|
|
|
vbottom = ceil (vnext);
|
|
|
|
|
|
|
|
if (vtop < vbottom) {
|
|
|
|
uvert = pvert->u;
|
|
|
|
if (uvert < r_refdef.fvrectx_adj)
|
|
|
|
uvert = r_refdef.fvrectx_adj;
|
|
|
|
if (uvert > r_refdef.fvrectright_adj)
|
|
|
|
uvert = r_refdef.fvrectright_adj;
|
|
|
|
|
|
|
|
unext = pnext->u;
|
|
|
|
if (unext < r_refdef.fvrectx_adj)
|
|
|
|
unext = r_refdef.fvrectx_adj;
|
|
|
|
if (unext > r_refdef.fvrectright_adj)
|
|
|
|
unext = r_refdef.fvrectright_adj;
|
|
|
|
|
|
|
|
du = unext - uvert;
|
|
|
|
dv = vnext - vvert;
|
|
|
|
slope = du / dv;
|
|
|
|
u_step = (int) (slope * 0x10000);
|
|
|
|
// adjust u to ceil the integer portion
|
|
|
|
u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) +
|
|
|
|
(0x10000 - 1);
|
|
|
|
itop = (int) vtop;
|
|
|
|
ibottom = (int) vbottom;
|
|
|
|
|
|
|
|
for (v = itop; v < ibottom; v++) {
|
|
|
|
pspan->count = (u >> 16) - pspan->u;
|
|
|
|
u += u_step;
|
|
|
|
pspan++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vtop = vbottom;
|
|
|
|
vvert = vnext;
|
|
|
|
|
|
|
|
i++;
|
2012-02-22 07:32:34 +00:00
|
|
|
if (i == sw32_r_spritedesc.nump)
|
2001-08-25 02:47:11 +00:00
|
|
|
i = 0;
|
|
|
|
|
|
|
|
} while (i != maxindex);
|
|
|
|
|
2012-05-21 23:23:22 +00:00
|
|
|
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
|
2001-08-25 02:47:11 +00:00
|
|
|
}
|
|
|
|
|
2003-01-06 18:28:13 +00:00
|
|
|
static void
|
2001-08-25 02:47:11 +00:00
|
|
|
D_SpriteCalculateGradients (void)
|
|
|
|
{
|
|
|
|
vec3_t p_normal, p_saxis, p_taxis, p_temp1;
|
|
|
|
float distinv;
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_TransformVector (sw32_r_spritedesc.vpn, p_normal);
|
|
|
|
sw32_TransformVector (sw32_r_spritedesc.vright, p_saxis);
|
|
|
|
sw32_TransformVector (sw32_r_spritedesc.vup, p_taxis);
|
2007-03-10 12:00:59 +00:00
|
|
|
VectorNegate (p_taxis, p_taxis);
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
distinv = 1.0 / (-DotProduct (modelorg, sw32_r_spritedesc.vpn));
|
2001-08-31 19:13:16 +00:00
|
|
|
distinv = min (distinv, 1.0);
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_d_sdivzstepu = p_saxis[0] * sw32_xscaleinv;
|
|
|
|
sw32_d_tdivzstepu = p_taxis[0] * sw32_xscaleinv;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_d_sdivzstepv = -p_saxis[1] * sw32_yscaleinv;
|
|
|
|
sw32_d_tdivzstepv = -p_taxis[1] * sw32_yscaleinv;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
d_zistepu = p_normal[0] * sw32_xscaleinv * distinv;
|
|
|
|
d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_d_sdivzorigin = p_saxis[2] - sw32_xcenter * sw32_d_sdivzstepu -
|
|
|
|
sw32_ycenter * sw32_d_sdivzstepv;
|
|
|
|
sw32_d_tdivzorigin = p_taxis[2] - sw32_xcenter * sw32_d_tdivzstepu -
|
|
|
|
sw32_ycenter * sw32_d_tdivzstepv;
|
|
|
|
d_ziorigin = p_normal[2] * distinv - sw32_xcenter * d_zistepu -
|
|
|
|
sw32_ycenter * d_zistepv;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_TransformVector (modelorg, p_temp1);
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
|
|
|
|
(-(sw32_cachewidth >> 1) << 16);
|
|
|
|
sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
|
2001-08-25 02:47:11 +00:00
|
|
|
(-(sprite_height >> 1) << 16);
|
|
|
|
|
|
|
|
// -1 (-epsilon) so we never wander off the edge of the texture
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_bbextents = (sw32_cachewidth << 16) - 1;
|
|
|
|
sw32_bbextentt = (sprite_height << 16) - 1;
|
2001-08-25 02:47:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_D_DrawSprite (void)
|
2001-08-25 02:47:11 +00:00
|
|
|
{
|
|
|
|
int i, nump;
|
|
|
|
float ymin, ymax;
|
|
|
|
emitpoint_t *pverts;
|
|
|
|
sspan_t spans[MAXHEIGHT + 1];
|
|
|
|
|
|
|
|
sprite_spans = spans;
|
|
|
|
|
|
|
|
// find the top and bottom vertices, and make sure there's at least one
|
|
|
|
// scan to draw
|
|
|
|
ymin = 999999.9;
|
|
|
|
ymax = -999999.9;
|
2012-02-22 07:32:34 +00:00
|
|
|
pverts = sw32_r_spritedesc.pverts;
|
2001-08-25 02:47:11 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
for (i = 0; i < sw32_r_spritedesc.nump; i++) {
|
2001-08-25 02:47:11 +00:00
|
|
|
if (pverts->v < ymin) {
|
|
|
|
ymin = pverts->v;
|
|
|
|
minindex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pverts->v > ymax) {
|
|
|
|
ymax = pverts->v;
|
|
|
|
maxindex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
pverts++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ymin = ceil (ymin);
|
|
|
|
ymax = ceil (ymax);
|
|
|
|
|
|
|
|
if (ymin >= ymax)
|
|
|
|
return; // doesn't cross any scans at all
|
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_cachewidth = sw32_r_spritedesc.pspriteframe->width;
|
|
|
|
sprite_height = sw32_r_spritedesc.pspriteframe->height;
|
|
|
|
sw32_cacheblock = &sw32_r_spritedesc.pspriteframe->pixels[0];
|
2001-08-25 02:47:11 +00:00
|
|
|
|
|
|
|
// copy the first vertex to the last vertex, so we don't have to deal with
|
|
|
|
// wrapping
|
2012-02-22 07:32:34 +00:00
|
|
|
nump = sw32_r_spritedesc.nump;
|
|
|
|
pverts = sw32_r_spritedesc.pverts;
|
2001-08-25 02:47:11 +00:00
|
|
|
pverts[nump] = pverts[0];
|
|
|
|
|
|
|
|
D_SpriteCalculateGradients ();
|
|
|
|
D_SpriteScanLeftEdge ();
|
|
|
|
D_SpriteScanRightEdge ();
|
2012-02-22 07:32:34 +00:00
|
|
|
sw32_D_SpriteDrawSpans (sprite_spans);
|
2001-08-25 02:47:11 +00:00
|
|
|
}
|