ngunix/renderer/d_sprite.c

1548 lines
39 KiB
C

/*
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 the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// d_sprite.c: software top-level rasterization driver module for drawing
// spritesy
#include "globaldef.h"
#include "d_local.h"
static int sprite_height;
static int minindex, maxindex;
static sspan_t *sprite_spans;
extern particle_t *currentparticle;
extern flare_t *currentflare;
extern byte additiveshade[16384];
#if !id386
// yeah,we sitll have the asm codes still used in there :)
#endif
extern byte *host_colormap_nofb;
extern byte gelmap[256];
extern pixel_t addTable[256][256]; // Additive Blending
extern pixel_t mulTable[256][256]; // Color Mod!
extern pixel_t transTable[256][256];
//extern pixel_t alphaTable[256][256];
extern cvar_t *r_filter;
extern byte menumap[256][16]; // haha hack
// =!=!=!=!=!=!=!=
// ASMME (or extern the blending mode stuff to a new function)
// =!=!=!=!=!=!=!=
float alfer;
float scaalx;
float scaaly;
int flared; // draw through edges
int flarespan; // the span we need to know before we determine
int pacolor;
float lensreflection = 1; // hack
//#define DITHERALPHATEST
/*
=====================
D_SpriteDrawSpans_C
=====================
*/
void D_SpriteDrawSpans_C (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *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;
int forg;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin+ dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin+ dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
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;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
}
}
if (foguse){ forg = (float)z / 1024; if (forg > 32762) forg = 32762; } // leilei - fog
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
if (foguse)
btemp = host_fogmap[btemp + (forg >> fogrange & 0xFF00)];
if (btemp != 255)
{
*pdest = btemp;
*pz = izi >> 16;
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
extern cvar_t *temp2;
extern cvar_t *temp3;
void D_SpriteDrawSpans_Blend_C (sspan_t *pspan, int blendmode)
{
int count, spancount, izistep;
int izi;
byte *pbase, *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;
int addlpha, dalpha;
int forg;
#ifdef DITHERALPHATEST
int ehh, heh; // leilei - dithered alpha fade
#endif
dalpha = 8192 * (alfer * -1) + 16384;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
#ifdef DITHERALPHATEST
ehh = 256;
#endif
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin+ dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin+ dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
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;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
sstep = (snext - s) >> 3;
tstep = (tnext - t) >> 3;
#ifdef DITHERALPHATEST
ehh = 256;
#endif
}
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);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < 8)
tnext = 8; // guard against round-off error on <0 steps
#ifdef DITHERALPHATEST
ehh = -256;
#endif
if (spancount > 1)
{
sstep = (snext - s) / (spancount - 1);
tstep = (tnext - t) / (spancount - 1);
}
}
if (foguse){ forg = (float)z / 1024; if (forg > 32762) forg = 32762; } // leilei - fog
do
{
btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
#ifdef DITHERALPHATEST
ehh *= -1;
addlpha = dalpha + ehh;
if (addlpha < 0)
addlpha = 0; // don't overgo it
#else
addlpha = dalpha;
#endif
// -------------------------------------------------
// Big FAT BLENDING ROUTINES Begin
// -------------------------------------------------
if (btemp != 255)
{
if (blendmode == 3)
btemp = pacolor;
if (flared){
btemp = mulTable[btemp][pacolor];
// btemp = menumap[btemp][3];
if (reflectpass) {
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
*pz = izi >> 16;
}
else{
if (alfer < 1)
*pdest = addTable[*pdest][host_colormap[btemp + (addlpha & 0xFF00)]];
else
*pdest = addTable[btemp][*pdest];
*pz = izi >> 16;
}
}
else if (*pz <= (izi >> 16))
{
//*pdest = btemp;
if (blendmode == 1){
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
}
// Variable Alpha Blend
else if (blendmode == 10){
btemp = btemp;
if (addlpha > 10900){
// off.
}
else if (addlpha > 10000){
*pdest = transTable[btemp][*pdest];
}
else if (addlpha > 8700){
*pdest = transTable[*pdest][btemp];
}
else
*pdest = btemp;
}
else if (blendmode == 8){
btemp = mulTable[btemp][pacolor];
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
}
else if (blendmode == 4){
*pdest = menumap[*pdest][btemp];
}
else if (blendmode == 6){
if (foguse)
*pdest = host_fogmap[mulTable[btemp][*pdest] + (forg >> fogrange & 0xFF00)];
else
*pdest = mulTable[btemp][*pdest];
}
else
{
*pdest = btemp;
*pz = izi >> 16;
}
}
// -------------------------------------------------
// Big FAT BLENDING ROUTINES End
// -------------------------------------------------
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
extern int kernel[2][2][2];
void D_SpriteDrawSpans_C_Filter (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *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;
int addlpha;
int forg;
addlpha = 8192 * (alfer * -1) + 16384;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin+ dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin+ dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
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;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
}
}
if (foguse){ forg = (float)z / 1024; if (forg > 32762) forg = 32762; } // leilei - fog
do
{
int idiths = s;
int iditht = t;
int X = (pspan->u + spancount) & 1;
int Y = (pspan->v)&1;
//Using the kernel
idiths += kernel[X][Y][0];
iditht += kernel[X][Y][1];
idiths = idiths >> 16;
idiths = idiths ? idiths -1 : idiths;
iditht = iditht >> 16;
iditht = iditht ? iditht -1 : iditht;
btemp = *(pbase + + idiths + iditht * cachewidth);
if (*pz <= (izi >> 16))
if (btemp != 255)
{
if (foguse)
*pdest = host_fogmap[btemp + (forg >> fogrange & 0xFF00)];
else
*pdest = btemp;
*pz = izi >> 16;
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
void D_SpriteDrawSpans_Blend_C_Filter (sspan_t *pspan, int blendmode)
{
int count, spancount, izistep;
int izi;
byte *pbase, *pdest;
fixed16_t s, t, snext, tnext, sstep, tstep;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivz8stepu, tdivz8stepu, zi8stepu;
byte btemp;
byte ctemp;
short *pz;
int forg;
int addlpha;
addlpha = 8192 * (alfer * -1) + 16384;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin+ dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin+ dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
else if (t < 0)
t = 0;
if (foguse){ forg = (float)z / 1024; if (forg > 32762) forg = 32762; } // leilei - fog
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;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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
{
int idiths = s;
int iditht = t;
int X = (pspan->u + spancount) & 1;
int Y = (pspan->v)&1;
//Using the kernel
idiths += kernel[X][Y][0];
iditht += kernel[X][Y][1];
idiths = idiths >> 16;
idiths = idiths ? idiths -1 : idiths;
iditht = iditht >> 16;
iditht = iditht ? iditht -1 : iditht;
btemp = *(pbase + + idiths + iditht * cachewidth);
// btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
// -------------------------------------------------
// Big FAT BLENDING ROUTINES Begin
// -------------------------------------------------
if (btemp != 255)
{
if (blendmode == 3)
btemp = pacolor;
if (flared){
btemp = mulTable[btemp][pacolor];
//*btemp = menumap[*btemp][color];
if (reflectpass) {
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
*pz = izi >> 16;
}
else{
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
*pz = izi >> 16;
}
}
else if (*pz <= (izi >> 16))
{
//*pdest = btemp;
if (blendmode == 1){
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
}
// Variable Alpha Blend
else if (blendmode == 10){
btemp = btemp;
if (addlpha > 10900){
// off.
}
else if (addlpha > 10000){
*pdest = transTable[btemp][*pdest];
}
else if (addlpha > 8700){
*pdest = transTable[*pdest][btemp];
}
else
*pdest = btemp;
}
else if (blendmode == 8){
btemp = mulTable[btemp][pacolor];
if (alfer < 1)
*pdest = addTable[host_colormap[btemp + (addlpha & 0xFF00)]][*pdest];
else
*pdest = addTable[btemp][*pdest];
}
else if (blendmode == 4){
*pdest = menumap[*pdest][btemp];
}
else if (blendmode == 6){
if (foguse)
*pdest = host_fogmap[mulTable[btemp][*pdest] + (forg >> fogrange & 0xFF00)];
else
*pdest = mulTable[btemp][*pdest];
}
else
{
*pdest = btemp;
*pz = izi >> 16;
}
}
// -------------------------------------------------
// Big FAT BLENDING ROUTINES End
// -------------------------------------------------
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
void D_SpriteDrawSpans_Censor (sspan_t *pspan)
{
int count, spancount, izistep;
int izi;
byte *pbase, *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;
int forg;
int censwidth = 8;
sstep = 0; // keep compiler happy
tstep = 0; // ditto
pbase = cacheblock;
sdivz8stepu = d_sdivzstepu * 8;
tdivz8stepu = d_tdivzstepu * 8;
zi8stepu = d_zistepu * 8;
// we count on FP exceptions being turned off to avoid range problems
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
do
{
pdest = (byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u;
pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin+ dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin+ dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
izi = (int)(zi * 0x8000 * 0x10000);
s = (int)(sdivz * z) + sadjust;
if (s > bbextents)
s = bbextents;
else if (s < 0)
s = 0;
t = (int)(tdivz * z) + tadjust;
if (t > bbextentt)
t = bbextentt;
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;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
if (snext > bbextents)
snext = bbextents;
else if (snext < 8)
snext = 8; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
tnext = (int)(tdivz * z) + tadjust;
if (tnext > bbextentt)
tnext = bbextentt;
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
{
btemp = (pdest[spancount]);
if (btemp != 255)
{
*pdest = btemp;
*pz = izi >> 16;
}
izi += izistep;
pdest++;
pz++;
s += sstep;
t += tstep;
} while (--spancount > 0);
s = snext;
t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
/*
=====================
D_SpriteScanLeftEdge
=====================
*/
void 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)
i = r_spritedesc.nump;
lmaxindex = maxindex;
if (lmaxindex == 0)
lmaxindex = r_spritedesc.nump;
vtop = ceil (r_spritedesc.pverts[i].v);
do
{
pvert = &r_spritedesc.pverts[i];
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)
i = r_spritedesc.nump;
} while (i != lmaxindex);
}
/*
=====================
D_SpriteScanRightEdge
=====================
*/
void 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;
vvert = r_spritedesc.pverts[i].v;
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
{
pvert = &r_spritedesc.pverts[i];
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++;
if (i == r_spritedesc.nump)
i = 0;
} while (i != maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
extern cvar_t *temp2;
extern cvar_t *temp3;
/*
=====================
D_SpriteCalculateGradients
=====================
*/
void D_SpriteCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis, p_temp1, p_temp2;
float distinv;
float scel, scely;
int xcanter, ycanter;
TransformVector (r_spritedesc.vpn, p_normal);
TransformVector (r_spritedesc.vright, p_saxis);
TransformVector (r_spritedesc.vup, p_taxis);
VectorInverse (p_taxis);
distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn));
//lensreflection = -2;
// lame
xcanter = vid.width - xcenter;
ycanter = vid.height - ycenter;
//if (currentparticle){
scel = scaalx;
scely = scaaly;
//scel = currententity->scale;
if (scaalx > 665)
scel = scaalx -= 665; // leilei - flare hack
// if (reflectpass)
// scely *= 4; // leilei - try to make the water flares long
// Manoel Kasimier - QC Scale - begin
p_saxis[0] /= scel;
p_saxis[1] /= scel;
p_saxis[2] /= scel;
p_taxis[0] /= scely;
p_taxis[1] /= scely;
p_taxis[2] /= scely;
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu -
ycenter * d_zistepv;
//d_sdivzorigin *= lensreflection;
TransformVector (modelorg, p_temp1);
// leilei - lens flare reflections (if it even works :/ )
//p_temp1[0] *= lensreflection;
//p_temp1[1] *= lensreflection;
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
(-(cachewidth >> 1) << 16);
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
(-(sprite_height >> 1) << 16);
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (cachewidth << 16) - 1;
bbextentt = (sprite_height << 16) - 1;
}
extern cvar_t *temp2;
/*
=====================
D_DrawSprite
=====================
*/
void D_DrawSprite (int isthisaparticle)
{
int i, nump;
float ymin, ymax;
int isfading;
int bypass;
emitpoint_t *pverts;
sspan_t spans[MAXHEIGHT+1];
sprite_spans = spans;
if (!isthisaparticle){
// scaalx = currententity->scale;
// scaaly = currententity->scale;
scaalx = 1; // no qc scale yet
scaaly = 1; // no qc scale yet
}
else if (isthisaparticle == 2) // it's a flare
{
scaalx = currentflare->scale;
scaaly = currentflare->scaley;
}
else // ok it is a particle
{
scaalx = currentparticle->scale;
scaaly = currentparticle->scaley;
if (currentparticle->alphavel)
isfading = 1;
else
isfading = 0;
}
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = 999999.9;
ymax = -999999.9;
pverts = r_spritedesc.pverts;
for (i=0 ; i<r_spritedesc.nump ; i++)
{
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
cachewidth = r_spritedesc.pspriteframe->width;
sprite_height = r_spritedesc.pspriteframe->height;
cacheblock = (byte *)&r_spritedesc.pspriteframe->pixels[0];
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_spritedesc.nump;
pverts = r_spritedesc.pverts;
pverts[nump] = pverts[0];
/*
if(currentparticle->sprtype == 15){ flared = 1; currentparticle->sprtype = 5; lensreflection = -3.5;}
else if(currentparticle->sprtype == 16){ flared = 1; currentparticle->sprtype = 5; lensreflection = -2;}
else if(currentparticle->sprtype == 17){ flared = 1; currentparticle->sprtype = 5; lensreflection = -1.5;}
else if(currentparticle->sprtype == 18){ flared = 1; currentparticle->sprtype = 5; lensreflection = -1.1;}
else if(currentparticle->sprtype == 19){ flared = 1; currentparticle->sprtype = 5; lensreflection = -0.7;}
else if(currentparticle->sprtype == 20){ flared = 1; currentparticle->sprtype = 5; lensreflection = -0.3;}
else if(currentparticle->sprtype == 21){ flared = 1; currentparticle->sprtype = 5; lensreflection = 1.2;}
else if(currentparticle->sprtype == 22){ flared = 1; currentparticle->sprtype = 5; lensreflection = 1.7;}
else if(currentparticle->sprtype == 23){ flared = 1; currentparticle->sprtype = 5; lensreflection = 2;}
else
*/
lensreflection = 3;
//if (flared)
// currentflare->lensreflection = lensreflection;
D_SpriteCalculateGradients ();
// :(
D_SpriteScanLeftEdge ();
D_SpriteScanRightEdge ();
if (isthisaparticle){
if (isthisaparticle == 2){
alfer = currentflare->alpha;
pacolor = currentflare->color;
}
else if (isthisaparticle){
alfer = currentparticle->alpha;
pacolor = currentparticle->color;
}
if (flared && alfer < 0.08f)
return; // try not to draw totally faded flares.
if (alfer < 0.01f && !isfading)
alfer = 1;
if (alfer < 0.005f && isfading)
return;
if (isthisaparticle == 2){
if (r_filter->value)
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 5);
else
D_SpriteDrawSpans_Blend_C (sprite_spans, 5);
return;
}
// only do one type for flares
if (r_filter->value){
if (currentparticle->blend == 1) // additeev
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 1);
else if (currentparticle->blend == 4) // gelmapped
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 4);
else if (currentparticle->blend == 5) // additive glow flare
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 5);
else if (currentparticle->blend == 6) // multiplicatev
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 6);
else if (currentparticle->blend == 8) // additive bt colorable like flare
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 8);
else if (currentparticle->blend == 9) // alpha bt colorable like flare
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 9);
else if (currentparticle->blend == 10) // alpha
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 10);
else if (currentparticle->blend == 3) // particle color only
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 3);
else if (alfer < 1)
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 2);
else
D_SpriteDrawSpans_C_Filter (sprite_spans);
}
else
{
if (currentparticle->blend == 1)
D_SpriteDrawSpans_Blend_C (sprite_spans, 1);
else if (currentparticle->blend == 4) // gelmapped
D_SpriteDrawSpans_Blend_C (sprite_spans, 4);
else if (currentparticle->blend == 3)
D_SpriteDrawSpans_Blend_C (sprite_spans, 3);
else if (currentparticle->blend == 5)
D_SpriteDrawSpans_Blend_C (sprite_spans, 5);
else if (currentparticle->blend == 6)
D_SpriteDrawSpans_Blend_C (sprite_spans, 6);
else if (currentparticle->blend == 8) // additive bt colorable like flare
D_SpriteDrawSpans_Blend_C (sprite_spans, 8);
else if (currentparticle->blend == 9) // alpha bt colorable like flare
D_SpriteDrawSpans_Blend_C (sprite_spans, 9);
else if (currentparticle->blend == 10) // alpha
D_SpriteDrawSpans_Blend_C (sprite_spans, 10);
else if (alfer < 1)
D_SpriteDrawSpans_Blend_C (sprite_spans, 2);
else
#if !id386
D_SpriteDrawSpans_C (sprite_spans);
#else
D_SpriteDrawSpans (sprite_spans);
#endif
}
//return;
}
else
{
flared = 0; // no it is not a flare. also these frys are not ok.
alfer = currententity->alpha;
if (alfer < 0.01f)
alfer = 1;
else
alfer = 0;
if (r_filter->value){
if (currententity->effects & EF_ADDITIVE)
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 1);
else if (alfer < 1)
D_SpriteDrawSpans_Blend_C_Filter (sprite_spans, 1);
else
D_SpriteDrawSpans_C_Filter (sprite_spans);
}
else
{
if (currententity->effects & EF_ADDITIVE)
D_SpriteDrawSpans_Blend_C (sprite_spans, 1);
else if (alfer < 1)
D_SpriteDrawSpans_Blend_C (sprite_spans, 1);
else
#if !id386
D_SpriteDrawSpans_C (sprite_spans);
#else
D_SpriteDrawSpans (sprite_spans);
#endif
}
}
}