mirror of
https://git.code.sf.net/p/quake/quakeforge-old
synced 2024-11-22 11:51:17 +00:00
Another merge from BigM
This commit is contained in:
parent
244297cedc
commit
740177b2c0
8 changed files with 0 additions and 2169 deletions
|
@ -1,446 +0,0 @@
|
||||||
/*
|
|
||||||
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_scan.c
|
|
||||||
//
|
|
||||||
// Portable C scan-level rasterization code, all pixel depths.
|
|
||||||
|
|
||||||
#include "quakedef.h"
|
|
||||||
#include "r_local.h"
|
|
||||||
#include "d_local.h"
|
|
||||||
|
|
||||||
unsigned char *r_turb_pbase, *r_turb_pdest;
|
|
||||||
fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
|
|
||||||
int *r_turb_turb;
|
|
||||||
int r_turb_spancount;
|
|
||||||
|
|
||||||
void D_DrawTurbulent8Span (void);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
D_WarpScreen
|
|
||||||
|
|
||||||
// this performs a slight compression of the screen at the same time as
|
|
||||||
// the sine warp, to keep the edges from wrapping
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void D_WarpScreen (void)
|
|
||||||
{
|
|
||||||
int w, h;
|
|
||||||
int u,v;
|
|
||||||
byte *dest;
|
|
||||||
int *turb;
|
|
||||||
int *col;
|
|
||||||
byte **row;
|
|
||||||
byte *rowptr[1024];
|
|
||||||
int column[1280];
|
|
||||||
float wratio, hratio;
|
|
||||||
|
|
||||||
w = r_refdef.vrect.width;
|
|
||||||
h = r_refdef.vrect.height;
|
|
||||||
|
|
||||||
wratio = w / (float)scr_vrect.width;
|
|
||||||
hratio = h / (float)scr_vrect.height;
|
|
||||||
|
|
||||||
for (v=0 ; v<scr_vrect.height+AMP2*2 ; v++)
|
|
||||||
{
|
|
||||||
rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
|
|
||||||
(screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u=0 ; u<scr_vrect.width+AMP2*2 ; u++)
|
|
||||||
{
|
|
||||||
column[u] = r_refdef.vrect.x +
|
|
||||||
(int)((float)u * wratio * w / (w + AMP2 * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
turb = intsintable + ((int)(cl.time*SPEED)&(CYCLE-1));
|
|
||||||
dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
|
|
||||||
|
|
||||||
for (v=0 ; v<scr_vrect.height ; v++, dest += vid.rowbytes)
|
|
||||||
{
|
|
||||||
col = &column[turb[v]];
|
|
||||||
row = &rowptr[v];
|
|
||||||
for (u=0 ; u<scr_vrect.width ; u+=4)
|
|
||||||
{
|
|
||||||
dest[u+0] = row[turb[u+0]][col[u+0]];
|
|
||||||
dest[u+1] = row[turb[u+1]][col[u+1]];
|
|
||||||
dest[u+2] = row[turb[u+2]][col[u+2]];
|
|
||||||
dest[u+3] = row[turb[u+3]][col[u+3]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
D_DrawTurbulent8Span
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void D_DrawTurbulent8Span (void)
|
|
||||||
{
|
|
||||||
int sturb, tturb;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
|
|
||||||
tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
|
|
||||||
*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
|
|
||||||
r_turb_s += r_turb_sstep;
|
|
||||||
r_turb_t += r_turb_tstep;
|
|
||||||
} while (--r_turb_spancount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
Turbulent8
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void Turbulent8 (espan_t *pspan)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
fixed16_t snext, tnext;
|
|
||||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
|
||||||
float sdivz16stepu, tdivz16stepu, zi16stepu;
|
|
||||||
|
|
||||||
r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
|
|
||||||
|
|
||||||
r_turb_sstep = 0; // keep compiler happy
|
|
||||||
r_turb_tstep = 0; // ditto
|
|
||||||
|
|
||||||
r_turb_pbase = (unsigned char *)cacheblock;
|
|
||||||
|
|
||||||
sdivz16stepu = d_sdivzstepu * 16;
|
|
||||||
tdivz16stepu = d_tdivzstepu * 16;
|
|
||||||
zi16stepu = d_zistepu * 16;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
|
|
||||||
(screenwidth * pspan->v) + pspan->u);
|
|
||||||
|
|
||||||
count = pspan->count;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
r_turb_s = (int)(sdivz * z) + sadjust;
|
|
||||||
if (r_turb_s > bbextents)
|
|
||||||
r_turb_s = bbextents;
|
|
||||||
else if (r_turb_s < 0)
|
|
||||||
r_turb_s = 0;
|
|
||||||
|
|
||||||
r_turb_t = (int)(tdivz * z) + tadjust;
|
|
||||||
if (r_turb_t > bbextentt)
|
|
||||||
r_turb_t = bbextentt;
|
|
||||||
else if (r_turb_t < 0)
|
|
||||||
r_turb_t = 0;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// calculate s and t at the far end of the span
|
|
||||||
if (count >= 16)
|
|
||||||
r_turb_spancount = 16;
|
|
||||||
else
|
|
||||||
r_turb_spancount = count;
|
|
||||||
|
|
||||||
count -= r_turb_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 += sdivz16stepu;
|
|
||||||
tdivz += tdivz16stepu;
|
|
||||||
zi += zi16stepu;
|
|
||||||
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
|
|
||||||
|
|
||||||
snext = (int)(sdivz * z) + sadjust;
|
|
||||||
if (snext > bbextents)
|
|
||||||
snext = bbextents;
|
|
||||||
else if (snext < 16)
|
|
||||||
snext = 16; // 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 < 16)
|
|
||||||
tnext = 16; // guard against round-off error on <0 steps
|
|
||||||
|
|
||||||
r_turb_sstep = (snext - r_turb_s) >> 4;
|
|
||||||
r_turb_tstep = (tnext - r_turb_t) >> 4;
|
|
||||||
}
|
|
||||||
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)(r_turb_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 < 16)
|
|
||||||
snext = 16; // 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 < 16)
|
|
||||||
tnext = 16; // guard against round-off error on <0 steps
|
|
||||||
|
|
||||||
if (r_turb_spancount > 1)
|
|
||||||
{
|
|
||||||
r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
|
|
||||||
r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r_turb_s = r_turb_s & ((CYCLE<<16)-1);
|
|
||||||
r_turb_t = r_turb_t & ((CYCLE<<16)-1);
|
|
||||||
|
|
||||||
D_DrawTurbulent8Span ();
|
|
||||||
|
|
||||||
r_turb_s = snext;
|
|
||||||
r_turb_t = tnext;
|
|
||||||
|
|
||||||
} while (count > 0);
|
|
||||||
|
|
||||||
} while ((pspan = pspan->pnext) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
D_DrawSpans8
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void D_DrawSpans8 (espan_t *pspan)
|
|
||||||
{
|
|
||||||
int count, spancount;
|
|
||||||
unsigned char *pbase, *pdest;
|
|
||||||
fixed16_t s, t, snext, tnext, sstep, tstep;
|
|
||||||
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
|
|
||||||
float sdivz8stepu, tdivz8stepu, zi8stepu;
|
|
||||||
|
|
||||||
sstep = 0; // keep compiler happy
|
|
||||||
tstep = 0; // ditto
|
|
||||||
|
|
||||||
pbase = (unsigned char *)cacheblock;
|
|
||||||
|
|
||||||
sdivz8stepu = d_sdivzstepu * 8;
|
|
||||||
tdivz8stepu = d_tdivzstepu * 8;
|
|
||||||
zi8stepu = d_zistepu * 8;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pdest = (unsigned char *)((byte *)d_viewbuffer +
|
|
||||||
(screenwidth * pspan->v) + pspan->u);
|
|
||||||
|
|
||||||
count = pspan->count;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
|
|
||||||
s += sstep;
|
|
||||||
t += tstep;
|
|
||||||
} while (--spancount > 0);
|
|
||||||
|
|
||||||
s = snext;
|
|
||||||
t = tnext;
|
|
||||||
|
|
||||||
} while (count > 0);
|
|
||||||
|
|
||||||
} while ((pspan = pspan->pnext) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
=============
|
|
||||||
D_DrawZSpans
|
|
||||||
=============
|
|
||||||
*/
|
|
||||||
void D_DrawZSpans (espan_t *pspan)
|
|
||||||
{
|
|
||||||
int count, doublecount, izistep;
|
|
||||||
int izi;
|
|
||||||
short *pdest;
|
|
||||||
unsigned ltemp;
|
|
||||||
double zi;
|
|
||||||
float du, dv;
|
|
||||||
|
|
||||||
// FIXME: check for clamping/range problems
|
|
||||||
// we count on FP exceptions being turned off to avoid range problems
|
|
||||||
izistep = (int)(d_zistepu * 0x8000 * 0x10000);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
|
|
||||||
|
|
||||||
count = pspan->count;
|
|
||||||
|
|
||||||
// calculate the initial 1/z
|
|
||||||
du = (float)pspan->u;
|
|
||||||
dv = (float)pspan->v;
|
|
||||||
|
|
||||||
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
|
|
||||||
// we count on FP exceptions being turned off to avoid range problems
|
|
||||||
izi = (int)(zi * 0x8000 * 0x10000);
|
|
||||||
|
|
||||||
if ((long)pdest & 0x02)
|
|
||||||
{
|
|
||||||
*pdest++ = (short)(izi >> 16);
|
|
||||||
izi += izistep;
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((doublecount = count >> 1) > 0)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ltemp = izi >> 16;
|
|
||||||
izi += izistep;
|
|
||||||
ltemp |= izi & 0xFFFF0000;
|
|
||||||
izi += izistep;
|
|
||||||
*(int *)pdest = ltemp;
|
|
||||||
pdest += 2;
|
|
||||||
} while (--doublecount > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count & 1)
|
|
||||||
*pdest = (short)(izi >> 16);
|
|
||||||
|
|
||||||
} while ((pspan = pspan->pnext) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,908 +0,0 @@
|
||||||
/*
|
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// r_draw.c
|
|
||||||
|
|
||||||
#include "quakedef.h"
|
|
||||||
#include "r_local.h"
|
|
||||||
#include "d_local.h" // FIXME: shouldn't need to include this
|
|
||||||
|
|
||||||
#define MAXLEFTCLIPEDGES 100
|
|
||||||
|
|
||||||
// !!! if these are changed, they must be changed in asm_draw.h too !!!
|
|
||||||
#define FULLY_CLIPPED_CACHED 0x80000000
|
|
||||||
#define FRAMECOUNT_MASK 0x7FFFFFFF
|
|
||||||
|
|
||||||
unsigned int cacheoffset;
|
|
||||||
|
|
||||||
int c_faceclip; // number of faces clipped
|
|
||||||
|
|
||||||
zpointdesc_t r_zpointdesc;
|
|
||||||
|
|
||||||
polydesc_t r_polydesc;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
clipplane_t *entity_clipplanes;
|
|
||||||
clipplane_t view_clipplanes[4];
|
|
||||||
clipplane_t world_clipplanes[16];
|
|
||||||
|
|
||||||
medge_t *r_pedge;
|
|
||||||
|
|
||||||
qboolean r_leftclipped, r_rightclipped;
|
|
||||||
static qboolean makeleftedge, makerightedge;
|
|
||||||
qboolean r_nearzionly;
|
|
||||||
|
|
||||||
int sintable[1280];
|
|
||||||
int intsintable[1280];
|
|
||||||
|
|
||||||
mvertex_t r_leftenter, r_leftexit;
|
|
||||||
mvertex_t r_rightenter, r_rightexit;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
float u,v;
|
|
||||||
int ceilv;
|
|
||||||
} evert_t;
|
|
||||||
|
|
||||||
int r_emitted;
|
|
||||||
float r_nearzi;
|
|
||||||
float r_u1, r_v1, r_lzi1;
|
|
||||||
int r_ceilv1;
|
|
||||||
|
|
||||||
qboolean r_lastvertvalid;
|
|
||||||
|
|
||||||
|
|
||||||
#if !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_EmitEdge
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
|
|
||||||
{
|
|
||||||
edge_t *edge, *pcheck;
|
|
||||||
int u_check;
|
|
||||||
float u, u_step;
|
|
||||||
vec3_t local, transformed;
|
|
||||||
float *world;
|
|
||||||
int v, v2, ceilv0;
|
|
||||||
float scale, lzi0, u0, v0;
|
|
||||||
int side;
|
|
||||||
|
|
||||||
if (r_lastvertvalid)
|
|
||||||
{
|
|
||||||
u0 = r_u1;
|
|
||||||
v0 = r_v1;
|
|
||||||
lzi0 = r_lzi1;
|
|
||||||
ceilv0 = r_ceilv1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
world = &pv0->position[0];
|
|
||||||
|
|
||||||
// transform and project
|
|
||||||
VectorSubtract (world, modelorg, local);
|
|
||||||
TransformVector (local, transformed);
|
|
||||||
|
|
||||||
if (transformed[2] < NEAR_CLIP)
|
|
||||||
transformed[2] = NEAR_CLIP;
|
|
||||||
|
|
||||||
lzi0 = 1.0 / transformed[2];
|
|
||||||
|
|
||||||
// FIXME: build x/yscale into transform?
|
|
||||||
scale = xscale * lzi0;
|
|
||||||
u0 = (xcenter + scale*transformed[0]);
|
|
||||||
if (u0 < r_refdef.fvrectx_adj)
|
|
||||||
u0 = r_refdef.fvrectx_adj;
|
|
||||||
if (u0 > r_refdef.fvrectright_adj)
|
|
||||||
u0 = r_refdef.fvrectright_adj;
|
|
||||||
|
|
||||||
scale = yscale * lzi0;
|
|
||||||
v0 = (ycenter - scale*transformed[1]);
|
|
||||||
if (v0 < r_refdef.fvrecty_adj)
|
|
||||||
v0 = r_refdef.fvrecty_adj;
|
|
||||||
if (v0 > r_refdef.fvrectbottom_adj)
|
|
||||||
v0 = r_refdef.fvrectbottom_adj;
|
|
||||||
|
|
||||||
ceilv0 = (int) ceil(v0);
|
|
||||||
}
|
|
||||||
|
|
||||||
world = &pv1->position[0];
|
|
||||||
|
|
||||||
// transform and project
|
|
||||||
VectorSubtract (world, modelorg, local);
|
|
||||||
TransformVector (local, transformed);
|
|
||||||
|
|
||||||
if (transformed[2] < NEAR_CLIP)
|
|
||||||
transformed[2] = NEAR_CLIP;
|
|
||||||
|
|
||||||
r_lzi1 = 1.0 / transformed[2];
|
|
||||||
|
|
||||||
scale = xscale * r_lzi1;
|
|
||||||
r_u1 = (xcenter + scale*transformed[0]);
|
|
||||||
if (r_u1 < r_refdef.fvrectx_adj)
|
|
||||||
r_u1 = r_refdef.fvrectx_adj;
|
|
||||||
if (r_u1 > r_refdef.fvrectright_adj)
|
|
||||||
r_u1 = r_refdef.fvrectright_adj;
|
|
||||||
|
|
||||||
scale = yscale * r_lzi1;
|
|
||||||
r_v1 = (ycenter - scale*transformed[1]);
|
|
||||||
if (r_v1 < r_refdef.fvrecty_adj)
|
|
||||||
r_v1 = r_refdef.fvrecty_adj;
|
|
||||||
if (r_v1 > r_refdef.fvrectbottom_adj)
|
|
||||||
r_v1 = r_refdef.fvrectbottom_adj;
|
|
||||||
|
|
||||||
if (r_lzi1 > lzi0)
|
|
||||||
lzi0 = r_lzi1;
|
|
||||||
|
|
||||||
if (lzi0 > r_nearzi) // for mipmap finding
|
|
||||||
r_nearzi = lzi0;
|
|
||||||
|
|
||||||
// for right edges, all we want is the effect on 1/z
|
|
||||||
if (r_nearzionly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
r_emitted = 1;
|
|
||||||
|
|
||||||
r_ceilv1 = (int) ceil(r_v1);
|
|
||||||
|
|
||||||
|
|
||||||
// create the edge
|
|
||||||
if (ceilv0 == r_ceilv1)
|
|
||||||
{
|
|
||||||
// we cache unclipped horizontal edges as fully clipped
|
|
||||||
if (cacheoffset != 0x7FFFFFFF)
|
|
||||||
{
|
|
||||||
cacheoffset = FULLY_CLIPPED_CACHED |
|
|
||||||
(r_framecount & FRAMECOUNT_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return; // horizontal edge
|
|
||||||
}
|
|
||||||
|
|
||||||
side = ceilv0 > r_ceilv1;
|
|
||||||
|
|
||||||
edge = edge_p++;
|
|
||||||
|
|
||||||
edge->owner = r_pedge;
|
|
||||||
|
|
||||||
edge->nearzi = lzi0;
|
|
||||||
|
|
||||||
if (side == 0)
|
|
||||||
{
|
|
||||||
// trailing edge (go from p1 to p2)
|
|
||||||
v = ceilv0;
|
|
||||||
v2 = r_ceilv1 - 1;
|
|
||||||
|
|
||||||
edge->surfs[0] = surface_p - surfaces;
|
|
||||||
edge->surfs[1] = 0;
|
|
||||||
|
|
||||||
u_step = ((r_u1 - u0) / (r_v1 - v0));
|
|
||||||
u = u0 + ((float)v - v0) * u_step;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// leading edge (go from p2 to p1)
|
|
||||||
v2 = ceilv0 - 1;
|
|
||||||
v = r_ceilv1;
|
|
||||||
|
|
||||||
edge->surfs[0] = 0;
|
|
||||||
edge->surfs[1] = surface_p - surfaces;
|
|
||||||
|
|
||||||
u_step = ((u0 - r_u1) / (v0 - r_v1));
|
|
||||||
u = r_u1 + ((float)v - r_v1) * u_step;
|
|
||||||
}
|
|
||||||
|
|
||||||
edge->u_step = u_step*0x100000;
|
|
||||||
edge->u = u*0x100000 + 0xFFFFF;
|
|
||||||
|
|
||||||
// we need to do this to avoid stepping off the edges if a very nearly
|
|
||||||
// horizontal edge is less than epsilon above a scan, and numeric error causes
|
|
||||||
// it to incorrectly extend to the scan, and the extension of the line goes off
|
|
||||||
// the edge of the screen
|
|
||||||
// FIXME: is this actually needed?
|
|
||||||
if (edge->u < r_refdef.vrect_x_adj_shift20)
|
|
||||||
edge->u = r_refdef.vrect_x_adj_shift20;
|
|
||||||
if (edge->u > r_refdef.vrectright_adj_shift20)
|
|
||||||
edge->u = r_refdef.vrectright_adj_shift20;
|
|
||||||
|
|
||||||
//
|
|
||||||
// sort the edge in normally
|
|
||||||
//
|
|
||||||
u_check = edge->u;
|
|
||||||
if (edge->surfs[0])
|
|
||||||
u_check++; // sort trailers after leaders
|
|
||||||
|
|
||||||
if (!newedges[v] || newedges[v]->u >= u_check)
|
|
||||||
{
|
|
||||||
edge->next = newedges[v];
|
|
||||||
newedges[v] = edge;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pcheck = newedges[v];
|
|
||||||
while (pcheck->next && pcheck->next->u < u_check)
|
|
||||||
pcheck = pcheck->next;
|
|
||||||
edge->next = pcheck->next;
|
|
||||||
pcheck->next = edge;
|
|
||||||
}
|
|
||||||
|
|
||||||
edge->nextremove = removeedges[v2];
|
|
||||||
removeedges[v2] = edge;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_ClipEdge
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
|
|
||||||
{
|
|
||||||
float d0, d1, f;
|
|
||||||
mvertex_t clipvert;
|
|
||||||
|
|
||||||
if (clip)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
|
|
||||||
d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
|
|
||||||
|
|
||||||
if (d0 >= 0)
|
|
||||||
{
|
|
||||||
// point 0 is unclipped
|
|
||||||
if (d1 >= 0)
|
|
||||||
{
|
|
||||||
// both points are unclipped
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only point 1 is clipped
|
|
||||||
|
|
||||||
// we don't cache clipped edges
|
|
||||||
cacheoffset = 0x7FFFFFFF;
|
|
||||||
|
|
||||||
f = d0 / (d0 - d1);
|
|
||||||
clipvert.position[0] = pv0->position[0] +
|
|
||||||
f * (pv1->position[0] - pv0->position[0]);
|
|
||||||
clipvert.position[1] = pv0->position[1] +
|
|
||||||
f * (pv1->position[1] - pv0->position[1]);
|
|
||||||
clipvert.position[2] = pv0->position[2] +
|
|
||||||
f * (pv1->position[2] - pv0->position[2]);
|
|
||||||
|
|
||||||
if (clip->leftedge)
|
|
||||||
{
|
|
||||||
r_leftclipped = true;
|
|
||||||
r_leftexit = clipvert;
|
|
||||||
}
|
|
||||||
else if (clip->rightedge)
|
|
||||||
{
|
|
||||||
r_rightclipped = true;
|
|
||||||
r_rightexit = clipvert;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_ClipEdge (pv0, &clipvert, clip->next);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// point 0 is clipped
|
|
||||||
if (d1 < 0)
|
|
||||||
{
|
|
||||||
// both points are clipped
|
|
||||||
// we do cache fully clipped edges
|
|
||||||
if (!r_leftclipped)
|
|
||||||
cacheoffset = FULLY_CLIPPED_CACHED |
|
|
||||||
(r_framecount & FRAMECOUNT_MASK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only point 0 is clipped
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
|
|
||||||
// we don't cache partially clipped edges
|
|
||||||
cacheoffset = 0x7FFFFFFF;
|
|
||||||
|
|
||||||
f = d0 / (d0 - d1);
|
|
||||||
clipvert.position[0] = pv0->position[0] +
|
|
||||||
f * (pv1->position[0] - pv0->position[0]);
|
|
||||||
clipvert.position[1] = pv0->position[1] +
|
|
||||||
f * (pv1->position[1] - pv0->position[1]);
|
|
||||||
clipvert.position[2] = pv0->position[2] +
|
|
||||||
f * (pv1->position[2] - pv0->position[2]);
|
|
||||||
|
|
||||||
if (clip->leftedge)
|
|
||||||
{
|
|
||||||
r_leftclipped = true;
|
|
||||||
r_leftenter = clipvert;
|
|
||||||
}
|
|
||||||
else if (clip->rightedge)
|
|
||||||
{
|
|
||||||
r_rightclipped = true;
|
|
||||||
r_rightenter = clipvert;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_ClipEdge (&clipvert, pv1, clip->next);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while ((clip = clip->next) != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the edge
|
|
||||||
R_EmitEdge (pv0, pv1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !id386
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_EmitCachedEdge
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_EmitCachedEdge (void)
|
|
||||||
{
|
|
||||||
edge_t *pedge_t;
|
|
||||||
|
|
||||||
pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
|
|
||||||
|
|
||||||
if (!pedge_t->surfs[0])
|
|
||||||
pedge_t->surfs[0] = surface_p - surfaces;
|
|
||||||
else
|
|
||||||
pedge_t->surfs[1] = surface_p - surfaces;
|
|
||||||
|
|
||||||
if (pedge_t->nearzi > r_nearzi) // for mipmap finding
|
|
||||||
r_nearzi = pedge_t->nearzi;
|
|
||||||
|
|
||||||
r_emitted = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_RenderFace
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_RenderFace (msurface_t *fa, int clipflags)
|
|
||||||
{
|
|
||||||
int i, lindex;
|
|
||||||
unsigned mask;
|
|
||||||
mplane_t *pplane;
|
|
||||||
float distinv;
|
|
||||||
vec3_t p_normal;
|
|
||||||
medge_t *pedges, tedge;
|
|
||||||
clipplane_t *pclip;
|
|
||||||
|
|
||||||
// skip out if no more surfs
|
|
||||||
if ((surface_p) >= surf_max)
|
|
||||||
{
|
|
||||||
r_outofsurfaces++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ditto if not enough edges left, or switch to auxedges if possible
|
|
||||||
if ((edge_p + fa->numedges + 4) >= edge_max)
|
|
||||||
{
|
|
||||||
r_outofedges += fa->numedges;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
c_faceclip++;
|
|
||||||
|
|
||||||
// set up clip planes
|
|
||||||
pclip = NULL;
|
|
||||||
|
|
||||||
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
|
|
||||||
{
|
|
||||||
if (clipflags & mask)
|
|
||||||
{
|
|
||||||
view_clipplanes[i].next = pclip;
|
|
||||||
pclip = &view_clipplanes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// push the edges through
|
|
||||||
r_emitted = 0;
|
|
||||||
r_nearzi = 0;
|
|
||||||
r_nearzionly = false;
|
|
||||||
makeleftedge = makerightedge = false;
|
|
||||||
pedges = currententity->model->edges;
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
|
|
||||||
for (i=0 ; i<fa->numedges ; i++)
|
|
||||||
{
|
|
||||||
lindex = currententity->model->surfedges[fa->firstedge + i];
|
|
||||||
|
|
||||||
if (lindex > 0)
|
|
||||||
{
|
|
||||||
r_pedge = &pedges[lindex];
|
|
||||||
|
|
||||||
// if the edge is cached, we can just reuse the edge
|
|
||||||
if (!insubmodel)
|
|
||||||
{
|
|
||||||
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
|
|
||||||
{
|
|
||||||
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
|
|
||||||
r_framecount)
|
|
||||||
{
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
|
|
||||||
r_pedge->cachededgeoffset) &&
|
|
||||||
(((edge_t *)((unsigned long)r_edges +
|
|
||||||
r_pedge->cachededgeoffset))->owner == r_pedge))
|
|
||||||
{
|
|
||||||
R_EmitCachedEdge ();
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assume it's cacheable
|
|
||||||
cacheoffset = (byte *)edge_p - (byte *)r_edges;
|
|
||||||
r_leftclipped = r_rightclipped = false;
|
|
||||||
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
|
|
||||||
&r_pcurrentvertbase[r_pedge->v[1]],
|
|
||||||
pclip);
|
|
||||||
r_pedge->cachededgeoffset = cacheoffset;
|
|
||||||
|
|
||||||
if (r_leftclipped)
|
|
||||||
makeleftedge = true;
|
|
||||||
if (r_rightclipped)
|
|
||||||
makerightedge = true;
|
|
||||||
r_lastvertvalid = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lindex = -lindex;
|
|
||||||
r_pedge = &pedges[lindex];
|
|
||||||
// if the edge is cached, we can just reuse the edge
|
|
||||||
if (!insubmodel)
|
|
||||||
{
|
|
||||||
if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
|
|
||||||
{
|
|
||||||
if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
|
|
||||||
r_framecount)
|
|
||||||
{
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// it's cached if the cached edge is valid and is owned
|
|
||||||
// by this medge_t
|
|
||||||
if ((((unsigned long)edge_p - (unsigned long)r_edges) >
|
|
||||||
r_pedge->cachededgeoffset) &&
|
|
||||||
(((edge_t *)((unsigned long)r_edges +
|
|
||||||
r_pedge->cachededgeoffset))->owner == r_pedge))
|
|
||||||
{
|
|
||||||
R_EmitCachedEdge ();
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assume it's cacheable
|
|
||||||
cacheoffset = (byte *)edge_p - (byte *)r_edges;
|
|
||||||
r_leftclipped = r_rightclipped = false;
|
|
||||||
R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
|
|
||||||
&r_pcurrentvertbase[r_pedge->v[0]],
|
|
||||||
pclip);
|
|
||||||
r_pedge->cachededgeoffset = cacheoffset;
|
|
||||||
|
|
||||||
if (r_leftclipped)
|
|
||||||
makeleftedge = true;
|
|
||||||
if (r_rightclipped)
|
|
||||||
makerightedge = true;
|
|
||||||
r_lastvertvalid = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there was a clip off the left edge, add that edge too
|
|
||||||
// FIXME: faster to do in screen space?
|
|
||||||
// FIXME: share clipped edges?
|
|
||||||
if (makeleftedge)
|
|
||||||
{
|
|
||||||
r_pedge = &tedge;
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there was a clip off the right edge, get the right r_nearzi
|
|
||||||
if (makerightedge)
|
|
||||||
{
|
|
||||||
r_pedge = &tedge;
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
r_nearzionly = true;
|
|
||||||
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no edges made it out, return without posting the surface
|
|
||||||
if (!r_emitted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
r_polycount++;
|
|
||||||
|
|
||||||
surface_p->data = (void *)fa;
|
|
||||||
surface_p->nearzi = r_nearzi;
|
|
||||||
surface_p->flags = fa->flags;
|
|
||||||
surface_p->insubmodel = insubmodel;
|
|
||||||
surface_p->spanstate = 0;
|
|
||||||
surface_p->entity = currententity;
|
|
||||||
surface_p->key = r_currentkey++;
|
|
||||||
surface_p->spans = NULL;
|
|
||||||
|
|
||||||
pplane = fa->plane;
|
|
||||||
// FIXME: cache this?
|
|
||||||
TransformVector (pplane->normal, p_normal);
|
|
||||||
// FIXME: cache this?
|
|
||||||
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
|
|
||||||
|
|
||||||
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
|
|
||||||
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
|
|
||||||
surface_p->d_ziorigin = p_normal[2] * distinv -
|
|
||||||
xcenter * surface_p->d_zistepu -
|
|
||||||
ycenter * surface_p->d_zistepv;
|
|
||||||
|
|
||||||
//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
|
|
||||||
surface_p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_RenderBmodelFace
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
unsigned mask;
|
|
||||||
mplane_t *pplane;
|
|
||||||
float distinv;
|
|
||||||
vec3_t p_normal;
|
|
||||||
medge_t tedge;
|
|
||||||
clipplane_t *pclip;
|
|
||||||
|
|
||||||
// skip out if no more surfs
|
|
||||||
if (surface_p >= surf_max)
|
|
||||||
{
|
|
||||||
r_outofsurfaces++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ditto if not enough edges left, or switch to auxedges if possible
|
|
||||||
if ((edge_p + psurf->numedges + 4) >= edge_max)
|
|
||||||
{
|
|
||||||
r_outofedges += psurf->numedges;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
c_faceclip++;
|
|
||||||
|
|
||||||
// this is a dummy to give the caching mechanism someplace to write to
|
|
||||||
r_pedge = &tedge;
|
|
||||||
|
|
||||||
// set up clip planes
|
|
||||||
pclip = NULL;
|
|
||||||
|
|
||||||
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
|
|
||||||
{
|
|
||||||
if (r_clipflags & mask)
|
|
||||||
{
|
|
||||||
view_clipplanes[i].next = pclip;
|
|
||||||
pclip = &view_clipplanes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// push the edges through
|
|
||||||
r_emitted = 0;
|
|
||||||
r_nearzi = 0;
|
|
||||||
r_nearzionly = false;
|
|
||||||
makeleftedge = makerightedge = false;
|
|
||||||
// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
|
|
||||||
// can be used?
|
|
||||||
r_lastvertvalid = false;
|
|
||||||
|
|
||||||
for ( ; pedges ; pedges = pedges->pnext)
|
|
||||||
{
|
|
||||||
r_leftclipped = r_rightclipped = false;
|
|
||||||
R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
|
|
||||||
|
|
||||||
if (r_leftclipped)
|
|
||||||
makeleftedge = true;
|
|
||||||
if (r_rightclipped)
|
|
||||||
makerightedge = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there was a clip off the left edge, add that edge too
|
|
||||||
// FIXME: faster to do in screen space?
|
|
||||||
// FIXME: share clipped edges?
|
|
||||||
if (makeleftedge)
|
|
||||||
{
|
|
||||||
r_pedge = &tedge;
|
|
||||||
R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there was a clip off the right edge, get the right r_nearzi
|
|
||||||
if (makerightedge)
|
|
||||||
{
|
|
||||||
r_pedge = &tedge;
|
|
||||||
r_nearzionly = true;
|
|
||||||
R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no edges made it out, return without posting the surface
|
|
||||||
if (!r_emitted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
r_polycount++;
|
|
||||||
|
|
||||||
surface_p->data = (void *)psurf;
|
|
||||||
surface_p->nearzi = r_nearzi;
|
|
||||||
surface_p->flags = psurf->flags;
|
|
||||||
surface_p->insubmodel = true;
|
|
||||||
surface_p->spanstate = 0;
|
|
||||||
surface_p->entity = currententity;
|
|
||||||
surface_p->key = r_currentbkey;
|
|
||||||
surface_p->spans = NULL;
|
|
||||||
|
|
||||||
pplane = psurf->plane;
|
|
||||||
// FIXME: cache this?
|
|
||||||
TransformVector (pplane->normal, p_normal);
|
|
||||||
// FIXME: cache this?
|
|
||||||
distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
|
|
||||||
|
|
||||||
surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
|
|
||||||
surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
|
|
||||||
surface_p->d_ziorigin = p_normal[2] * distinv -
|
|
||||||
xcenter * surface_p->d_zistepu -
|
|
||||||
ycenter * surface_p->d_zistepv;
|
|
||||||
|
|
||||||
//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg);
|
|
||||||
surface_p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_RenderPoly
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_RenderPoly (msurface_t *fa, int clipflags)
|
|
||||||
{
|
|
||||||
int i, lindex, lnumverts, s_axis, t_axis;
|
|
||||||
float dist, lastdist, lzi, scale, u, v, frac;
|
|
||||||
unsigned mask;
|
|
||||||
vec3_t local, transformed;
|
|
||||||
clipplane_t *pclip;
|
|
||||||
medge_t *pedges;
|
|
||||||
mplane_t *pplane;
|
|
||||||
mvertex_t verts[2][100]; //FIXME: do real number
|
|
||||||
polyvert_t pverts[100]; //FIXME: do real number, safely
|
|
||||||
int vertpage, newverts, newpage, lastvert;
|
|
||||||
qboolean visible;
|
|
||||||
|
|
||||||
// FIXME: clean this up and make it faster
|
|
||||||
// FIXME: guard against running out of vertices
|
|
||||||
|
|
||||||
s_axis = t_axis = 0; // keep compiler happy
|
|
||||||
|
|
||||||
// set up clip planes
|
|
||||||
pclip = NULL;
|
|
||||||
|
|
||||||
for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
|
|
||||||
{
|
|
||||||
if (clipflags & mask)
|
|
||||||
{
|
|
||||||
view_clipplanes[i].next = pclip;
|
|
||||||
pclip = &view_clipplanes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reconstruct the polygon
|
|
||||||
// FIXME: these should be precalculated and loaded off disk
|
|
||||||
pedges = currententity->model->edges;
|
|
||||||
lnumverts = fa->numedges;
|
|
||||||
vertpage = 0;
|
|
||||||
|
|
||||||
for (i=0 ; i<lnumverts ; i++)
|
|
||||||
{
|
|
||||||
lindex = currententity->model->surfedges[fa->firstedge + i];
|
|
||||||
|
|
||||||
if (lindex > 0)
|
|
||||||
{
|
|
||||||
r_pedge = &pedges[lindex];
|
|
||||||
verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r_pedge = &pedges[-lindex];
|
|
||||||
verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clip the polygon, done if not visible
|
|
||||||
while (pclip)
|
|
||||||
{
|
|
||||||
lastvert = lnumverts - 1;
|
|
||||||
lastdist = DotProduct (verts[vertpage][lastvert].position,
|
|
||||||
pclip->normal) - pclip->dist;
|
|
||||||
|
|
||||||
visible = false;
|
|
||||||
newverts = 0;
|
|
||||||
newpage = vertpage ^ 1;
|
|
||||||
|
|
||||||
for (i=0 ; i<lnumverts ; i++)
|
|
||||||
{
|
|
||||||
dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
|
|
||||||
pclip->dist;
|
|
||||||
|
|
||||||
if ((lastdist > 0) != (dist > 0))
|
|
||||||
{
|
|
||||||
frac = dist / (dist - lastdist);
|
|
||||||
verts[newpage][newverts].position[0] =
|
|
||||||
verts[vertpage][i].position[0] +
|
|
||||||
((verts[vertpage][lastvert].position[0] -
|
|
||||||
verts[vertpage][i].position[0]) * frac);
|
|
||||||
verts[newpage][newverts].position[1] =
|
|
||||||
verts[vertpage][i].position[1] +
|
|
||||||
((verts[vertpage][lastvert].position[1] -
|
|
||||||
verts[vertpage][i].position[1]) * frac);
|
|
||||||
verts[newpage][newverts].position[2] =
|
|
||||||
verts[vertpage][i].position[2] +
|
|
||||||
((verts[vertpage][lastvert].position[2] -
|
|
||||||
verts[vertpage][i].position[2]) * frac);
|
|
||||||
newverts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dist >= 0)
|
|
||||||
{
|
|
||||||
verts[newpage][newverts] = verts[vertpage][i];
|
|
||||||
newverts++;
|
|
||||||
visible = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastvert = i;
|
|
||||||
lastdist = dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!visible || (newverts < 3))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lnumverts = newverts;
|
|
||||||
vertpage ^= 1;
|
|
||||||
pclip = pclip->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transform and project, remembering the z values at the vertices and
|
|
||||||
// r_nearzi, and extract the s and t coordinates at the vertices
|
|
||||||
pplane = fa->plane;
|
|
||||||
switch (pplane->type)
|
|
||||||
{
|
|
||||||
case PLANE_X:
|
|
||||||
case PLANE_ANYX:
|
|
||||||
s_axis = 1;
|
|
||||||
t_axis = 2;
|
|
||||||
break;
|
|
||||||
case PLANE_Y:
|
|
||||||
case PLANE_ANYY:
|
|
||||||
s_axis = 0;
|
|
||||||
t_axis = 2;
|
|
||||||
break;
|
|
||||||
case PLANE_Z:
|
|
||||||
case PLANE_ANYZ:
|
|
||||||
s_axis = 0;
|
|
||||||
t_axis = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_nearzi = 0;
|
|
||||||
|
|
||||||
for (i=0 ; i<lnumverts ; i++)
|
|
||||||
{
|
|
||||||
// transform and project
|
|
||||||
VectorSubtract (verts[vertpage][i].position, modelorg, local);
|
|
||||||
TransformVector (local, transformed);
|
|
||||||
|
|
||||||
if (transformed[2] < NEAR_CLIP)
|
|
||||||
transformed[2] = NEAR_CLIP;
|
|
||||||
|
|
||||||
lzi = 1.0 / transformed[2];
|
|
||||||
|
|
||||||
if (lzi > r_nearzi) // for mipmap finding
|
|
||||||
r_nearzi = lzi;
|
|
||||||
|
|
||||||
// FIXME: build x/yscale into transform?
|
|
||||||
scale = xscale * lzi;
|
|
||||||
u = (xcenter + scale*transformed[0]);
|
|
||||||
if (u < r_refdef.fvrectx_adj)
|
|
||||||
u = r_refdef.fvrectx_adj;
|
|
||||||
if (u > r_refdef.fvrectright_adj)
|
|
||||||
u = r_refdef.fvrectright_adj;
|
|
||||||
|
|
||||||
scale = yscale * lzi;
|
|
||||||
v = (ycenter - scale*transformed[1]);
|
|
||||||
if (v < r_refdef.fvrecty_adj)
|
|
||||||
v = r_refdef.fvrecty_adj;
|
|
||||||
if (v > r_refdef.fvrectbottom_adj)
|
|
||||||
v = r_refdef.fvrectbottom_adj;
|
|
||||||
|
|
||||||
pverts[i].u = u;
|
|
||||||
pverts[i].v = v;
|
|
||||||
pverts[i].zi = lzi;
|
|
||||||
pverts[i].s = verts[vertpage][i].position[s_axis];
|
|
||||||
pverts[i].t = verts[vertpage][i].position[t_axis];
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z
|
|
||||||
// for each vertex
|
|
||||||
r_polydesc.numverts = lnumverts;
|
|
||||||
r_polydesc.nearzi = r_nearzi;
|
|
||||||
r_polydesc.pcurrentface = fa;
|
|
||||||
r_polydesc.pverts = pverts;
|
|
||||||
|
|
||||||
// draw the polygon
|
|
||||||
D_DrawPoly ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_ZDrawSubmodelPolys
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_ZDrawSubmodelPolys (model_t *pmodel)
|
|
||||||
{
|
|
||||||
int i, numsurfaces;
|
|
||||||
msurface_t *psurf;
|
|
||||||
float dot;
|
|
||||||
mplane_t *pplane;
|
|
||||||
|
|
||||||
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
|
|
||||||
numsurfaces = pmodel->nummodelsurfaces;
|
|
||||||
|
|
||||||
for (i=0 ; i<numsurfaces ; i++, psurf++)
|
|
||||||
{
|
|
||||||
// find which side of the node we are on
|
|
||||||
pplane = psurf->plane;
|
|
||||||
|
|
||||||
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
|
|
||||||
|
|
||||||
// draw the polygon
|
|
||||||
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
|
||||||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
|
|
||||||
{
|
|
||||||
// FIXME: use bounding-box-based frustum clipping info?
|
|
||||||
R_RenderPoly (psurf, 15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,661 +0,0 @@
|
||||||
/*
|
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
// r_surf.c: surface-related refresh code
|
|
||||||
|
|
||||||
#include "quakedef.h"
|
|
||||||
#include "r_local.h"
|
|
||||||
|
|
||||||
drawsurf_t r_drawsurf;
|
|
||||||
|
|
||||||
int lightleft, sourcesstep, blocksize, sourcetstep;
|
|
||||||
int lightdelta, lightdeltastep;
|
|
||||||
int lightright, lightleftstep, lightrightstep, blockdivshift;
|
|
||||||
unsigned blockdivmask;
|
|
||||||
void *prowdestbase;
|
|
||||||
unsigned char *pbasesource;
|
|
||||||
int surfrowbytes; // used by ASM files
|
|
||||||
unsigned *r_lightptr;
|
|
||||||
int r_stepback;
|
|
||||||
int r_lightwidth;
|
|
||||||
int r_numhblocks, r_numvblocks;
|
|
||||||
unsigned char *r_source, *r_sourcemax;
|
|
||||||
|
|
||||||
void R_DrawSurfaceBlock8_mip0 (void);
|
|
||||||
void R_DrawSurfaceBlock8_mip1 (void);
|
|
||||||
void R_DrawSurfaceBlock8_mip2 (void);
|
|
||||||
void R_DrawSurfaceBlock8_mip3 (void);
|
|
||||||
|
|
||||||
static void (*surfmiptable[4])(void) = {
|
|
||||||
R_DrawSurfaceBlock8_mip0,
|
|
||||||
R_DrawSurfaceBlock8_mip1,
|
|
||||||
R_DrawSurfaceBlock8_mip2,
|
|
||||||
R_DrawSurfaceBlock8_mip3
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned blocklights[18*18];
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_AddDynamicLights
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void R_AddDynamicLights (void)
|
|
||||||
{
|
|
||||||
msurface_t *surf;
|
|
||||||
int lnum;
|
|
||||||
int sd, td;
|
|
||||||
float dist, rad, minlight;
|
|
||||||
vec3_t impact, local;
|
|
||||||
int s, t;
|
|
||||||
int i;
|
|
||||||
int smax, tmax;
|
|
||||||
mtexinfo_t *tex;
|
|
||||||
|
|
||||||
surf = r_drawsurf.surf;
|
|
||||||
smax = (surf->extents[0]>>4)+1;
|
|
||||||
tmax = (surf->extents[1]>>4)+1;
|
|
||||||
tex = surf->texinfo;
|
|
||||||
|
|
||||||
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
|
|
||||||
{
|
|
||||||
if ( !(surf->dlightbits & (1<<lnum) ) )
|
|
||||||
continue; // not lit by this light
|
|
||||||
|
|
||||||
rad = cl_dlights[lnum].radius;
|
|
||||||
dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
|
|
||||||
surf->plane->dist;
|
|
||||||
rad -= fabs(dist);
|
|
||||||
minlight = cl_dlights[lnum].minlight;
|
|
||||||
if (rad < minlight)
|
|
||||||
continue;
|
|
||||||
minlight = rad - minlight;
|
|
||||||
|
|
||||||
for (i=0 ; i<3 ; i++)
|
|
||||||
{
|
|
||||||
impact[i] = cl_dlights[lnum].origin[i] -
|
|
||||||
surf->plane->normal[i]*dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
|
|
||||||
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
|
|
||||||
|
|
||||||
local[0] -= surf->texturemins[0];
|
|
||||||
local[1] -= surf->texturemins[1];
|
|
||||||
|
|
||||||
for (t = 0 ; t<tmax ; t++)
|
|
||||||
{
|
|
||||||
td = local[1] - t*16;
|
|
||||||
if (td < 0)
|
|
||||||
td = -td;
|
|
||||||
for (s=0 ; s<smax ; s++)
|
|
||||||
{
|
|
||||||
sd = local[0] - s*16;
|
|
||||||
if (sd < 0)
|
|
||||||
sd = -sd;
|
|
||||||
if (sd > td)
|
|
||||||
dist = sd + (td>>1);
|
|
||||||
else
|
|
||||||
dist = td + (sd>>1);
|
|
||||||
if (dist < minlight)
|
|
||||||
blocklights[t*smax + s] += (rad - dist)*256;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_BuildLightMap
|
|
||||||
|
|
||||||
Combine and scale multiple lightmaps into the 8.8 format in blocklights
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void R_BuildLightMap (void)
|
|
||||||
{
|
|
||||||
int smax, tmax;
|
|
||||||
int t;
|
|
||||||
int i, size;
|
|
||||||
byte *lightmap;
|
|
||||||
unsigned scale;
|
|
||||||
int maps;
|
|
||||||
msurface_t *surf;
|
|
||||||
|
|
||||||
surf = r_drawsurf.surf;
|
|
||||||
|
|
||||||
smax = (surf->extents[0]>>4)+1;
|
|
||||||
tmax = (surf->extents[1]>>4)+1;
|
|
||||||
size = smax*tmax;
|
|
||||||
lightmap = surf->samples;
|
|
||||||
|
|
||||||
if (/* r_fullbright.value || */ !cl.worldmodel->lightdata)
|
|
||||||
{
|
|
||||||
for (i=0 ; i<size ; i++)
|
|
||||||
blocklights[i] = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear to ambient
|
|
||||||
for (i=0 ; i<size ; i++)
|
|
||||||
blocklights[i] = r_refdef.ambientlight<<8;
|
|
||||||
|
|
||||||
|
|
||||||
// add all the lightmaps
|
|
||||||
if (lightmap)
|
|
||||||
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
|
|
||||||
maps++)
|
|
||||||
{
|
|
||||||
scale = r_drawsurf.lightadj[maps]; // 8.8 fraction
|
|
||||||
for (i=0 ; i<size ; i++)
|
|
||||||
blocklights[i] += lightmap[i] * scale;
|
|
||||||
lightmap += size; // skip to next lightmap
|
|
||||||
}
|
|
||||||
|
|
||||||
// add all the dynamic lights
|
|
||||||
if (surf->dlightframe == r_framecount)
|
|
||||||
R_AddDynamicLights ();
|
|
||||||
|
|
||||||
// bound, invert, and shift
|
|
||||||
for (i=0 ; i<size ; i++)
|
|
||||||
{
|
|
||||||
t = (255*256 - (int)blocklights[i]) >> (8 - VID_CBITS);
|
|
||||||
|
|
||||||
if (t < (1 << 6))
|
|
||||||
t = (1 << 6);
|
|
||||||
|
|
||||||
blocklights[i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_TextureAnimation
|
|
||||||
|
|
||||||
Returns the proper texture for a given time and base texture
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
texture_t *R_TextureAnimation (texture_t *base)
|
|
||||||
{
|
|
||||||
int reletive;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (currententity->frame)
|
|
||||||
{
|
|
||||||
if (base->alternate_anims)
|
|
||||||
base = base->alternate_anims;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!base->anim_total)
|
|
||||||
return base;
|
|
||||||
|
|
||||||
reletive = (int)(cl.time*10) % base->anim_total;
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
while (base->anim_min > reletive || base->anim_max <= reletive)
|
|
||||||
{
|
|
||||||
base = base->anim_next;
|
|
||||||
if (!base)
|
|
||||||
Sys_Error ("R_TextureAnimation: broken cycle");
|
|
||||||
if (++count > 100)
|
|
||||||
Sys_Error ("R_TextureAnimation: infinite cycle");
|
|
||||||
}
|
|
||||||
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
===============
|
|
||||||
R_DrawSurface
|
|
||||||
===============
|
|
||||||
*/
|
|
||||||
void R_DrawSurface (void)
|
|
||||||
{
|
|
||||||
unsigned char *basetptr;
|
|
||||||
int smax, tmax, twidth;
|
|
||||||
int u;
|
|
||||||
int soffset, basetoffset, texwidth;
|
|
||||||
int horzblockstep;
|
|
||||||
unsigned char *pcolumndest;
|
|
||||||
void (*pblockdrawer)(void);
|
|
||||||
texture_t *mt;
|
|
||||||
|
|
||||||
// calculate the lightings
|
|
||||||
R_BuildLightMap ();
|
|
||||||
|
|
||||||
surfrowbytes = r_drawsurf.rowbytes;
|
|
||||||
|
|
||||||
mt = r_drawsurf.texture;
|
|
||||||
|
|
||||||
r_source = (byte *)mt + mt->offsets[r_drawsurf.surfmip];
|
|
||||||
|
|
||||||
// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
|
|
||||||
// from a source range of 0 - 255
|
|
||||||
|
|
||||||
texwidth = mt->width >> r_drawsurf.surfmip;
|
|
||||||
|
|
||||||
blocksize = 16 >> r_drawsurf.surfmip;
|
|
||||||
blockdivshift = 4 - r_drawsurf.surfmip;
|
|
||||||
blockdivmask = (1 << blockdivshift) - 1;
|
|
||||||
|
|
||||||
r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1;
|
|
||||||
|
|
||||||
r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
|
|
||||||
r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
|
|
||||||
|
|
||||||
//==============================
|
|
||||||
|
|
||||||
if (r_pixbytes == 1)
|
|
||||||
{
|
|
||||||
pblockdrawer = surfmiptable[r_drawsurf.surfmip];
|
|
||||||
// TODO: only needs to be set when there is a display settings change
|
|
||||||
horzblockstep = blocksize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pblockdrawer = R_DrawSurfaceBlock16;
|
|
||||||
// TODO: only needs to be set when there is a display settings change
|
|
||||||
horzblockstep = blocksize << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
smax = mt->width >> r_drawsurf.surfmip;
|
|
||||||
twidth = texwidth;
|
|
||||||
tmax = mt->height >> r_drawsurf.surfmip;
|
|
||||||
sourcetstep = texwidth;
|
|
||||||
r_stepback = tmax * twidth;
|
|
||||||
|
|
||||||
r_sourcemax = r_source + (tmax * smax);
|
|
||||||
|
|
||||||
soffset = r_drawsurf.surf->texturemins[0];
|
|
||||||
basetoffset = r_drawsurf.surf->texturemins[1];
|
|
||||||
|
|
||||||
// << 16 components are to guarantee positive values for %
|
|
||||||
soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
|
|
||||||
basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip)
|
|
||||||
+ (tmax << 16)) % tmax) * twidth)];
|
|
||||||
|
|
||||||
pcolumndest = r_drawsurf.surfdat;
|
|
||||||
|
|
||||||
for (u=0 ; u<r_numhblocks; u++)
|
|
||||||
{
|
|
||||||
r_lightptr = blocklights + u;
|
|
||||||
|
|
||||||
prowdestbase = pcolumndest;
|
|
||||||
|
|
||||||
pbasesource = basetptr + soffset;
|
|
||||||
|
|
||||||
(*pblockdrawer)();
|
|
||||||
|
|
||||||
soffset = soffset + blocksize;
|
|
||||||
if (soffset >= smax)
|
|
||||||
soffset = 0;
|
|
||||||
|
|
||||||
pcolumndest += horzblockstep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
#if !id386
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawSurfaceBlock8_mip0
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawSurfaceBlock8_mip0 (void)
|
|
||||||
{
|
|
||||||
int v, i, b, lightstep, lighttemp, light;
|
|
||||||
unsigned char pix, *psource, *prowdest;
|
|
||||||
|
|
||||||
psource = pbasesource;
|
|
||||||
prowdest = prowdestbase;
|
|
||||||
|
|
||||||
for (v=0 ; v<r_numvblocks ; v++)
|
|
||||||
{
|
|
||||||
// FIXME: make these locals?
|
|
||||||
// FIXME: use delta rather than both right and left, like ASM?
|
|
||||||
lightleft = r_lightptr[0];
|
|
||||||
lightright = r_lightptr[1];
|
|
||||||
r_lightptr += r_lightwidth;
|
|
||||||
lightleftstep = (r_lightptr[0] - lightleft) >> 4;
|
|
||||||
lightrightstep = (r_lightptr[1] - lightright) >> 4;
|
|
||||||
|
|
||||||
for (i=0 ; i<16 ; i++)
|
|
||||||
{
|
|
||||||
lighttemp = lightleft - lightright;
|
|
||||||
lightstep = lighttemp >> 4;
|
|
||||||
|
|
||||||
light = lightright;
|
|
||||||
|
|
||||||
for (b=15; b>=0; b--)
|
|
||||||
{
|
|
||||||
pix = psource[b];
|
|
||||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
|
||||||
[(light & 0xFF00) + pix];
|
|
||||||
light += lightstep;
|
|
||||||
}
|
|
||||||
|
|
||||||
psource += sourcetstep;
|
|
||||||
lightright += lightrightstep;
|
|
||||||
lightleft += lightleftstep;
|
|
||||||
prowdest += surfrowbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psource >= r_sourcemax)
|
|
||||||
psource -= r_stepback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawSurfaceBlock8_mip1
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawSurfaceBlock8_mip1 (void)
|
|
||||||
{
|
|
||||||
int v, i, b, lightstep, lighttemp, light;
|
|
||||||
unsigned char pix, *psource, *prowdest;
|
|
||||||
|
|
||||||
psource = pbasesource;
|
|
||||||
prowdest = prowdestbase;
|
|
||||||
|
|
||||||
for (v=0 ; v<r_numvblocks ; v++)
|
|
||||||
{
|
|
||||||
// FIXME: make these locals?
|
|
||||||
// FIXME: use delta rather than both right and left, like ASM?
|
|
||||||
lightleft = r_lightptr[0];
|
|
||||||
lightright = r_lightptr[1];
|
|
||||||
r_lightptr += r_lightwidth;
|
|
||||||
lightleftstep = (r_lightptr[0] - lightleft) >> 3;
|
|
||||||
lightrightstep = (r_lightptr[1] - lightright) >> 3;
|
|
||||||
|
|
||||||
for (i=0 ; i<8 ; i++)
|
|
||||||
{
|
|
||||||
lighttemp = lightleft - lightright;
|
|
||||||
lightstep = lighttemp >> 3;
|
|
||||||
|
|
||||||
light = lightright;
|
|
||||||
|
|
||||||
for (b=7; b>=0; b--)
|
|
||||||
{
|
|
||||||
pix = psource[b];
|
|
||||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
|
||||||
[(light & 0xFF00) + pix];
|
|
||||||
light += lightstep;
|
|
||||||
}
|
|
||||||
|
|
||||||
psource += sourcetstep;
|
|
||||||
lightright += lightrightstep;
|
|
||||||
lightleft += lightleftstep;
|
|
||||||
prowdest += surfrowbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psource >= r_sourcemax)
|
|
||||||
psource -= r_stepback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawSurfaceBlock8_mip2
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawSurfaceBlock8_mip2 (void)
|
|
||||||
{
|
|
||||||
int v, i, b, lightstep, lighttemp, light;
|
|
||||||
unsigned char pix, *psource, *prowdest;
|
|
||||||
|
|
||||||
psource = pbasesource;
|
|
||||||
prowdest = prowdestbase;
|
|
||||||
|
|
||||||
for (v=0 ; v<r_numvblocks ; v++)
|
|
||||||
{
|
|
||||||
// FIXME: make these locals?
|
|
||||||
// FIXME: use delta rather than both right and left, like ASM?
|
|
||||||
lightleft = r_lightptr[0];
|
|
||||||
lightright = r_lightptr[1];
|
|
||||||
r_lightptr += r_lightwidth;
|
|
||||||
lightleftstep = (r_lightptr[0] - lightleft) >> 2;
|
|
||||||
lightrightstep = (r_lightptr[1] - lightright) >> 2;
|
|
||||||
|
|
||||||
for (i=0 ; i<4 ; i++)
|
|
||||||
{
|
|
||||||
lighttemp = lightleft - lightright;
|
|
||||||
lightstep = lighttemp >> 2;
|
|
||||||
|
|
||||||
light = lightright;
|
|
||||||
|
|
||||||
for (b=3; b>=0; b--)
|
|
||||||
{
|
|
||||||
pix = psource[b];
|
|
||||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
|
||||||
[(light & 0xFF00) + pix];
|
|
||||||
light += lightstep;
|
|
||||||
}
|
|
||||||
|
|
||||||
psource += sourcetstep;
|
|
||||||
lightright += lightrightstep;
|
|
||||||
lightleft += lightleftstep;
|
|
||||||
prowdest += surfrowbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psource >= r_sourcemax)
|
|
||||||
psource -= r_stepback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawSurfaceBlock8_mip3
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawSurfaceBlock8_mip3 (void)
|
|
||||||
{
|
|
||||||
int v, i, b, lightstep, lighttemp, light;
|
|
||||||
unsigned char pix, *psource, *prowdest;
|
|
||||||
|
|
||||||
psource = pbasesource;
|
|
||||||
prowdest = prowdestbase;
|
|
||||||
|
|
||||||
for (v=0 ; v<r_numvblocks ; v++)
|
|
||||||
{
|
|
||||||
// FIXME: make these locals?
|
|
||||||
// FIXME: use delta rather than both right and left, like ASM?
|
|
||||||
lightleft = r_lightptr[0];
|
|
||||||
lightright = r_lightptr[1];
|
|
||||||
r_lightptr += r_lightwidth;
|
|
||||||
lightleftstep = (r_lightptr[0] - lightleft) >> 1;
|
|
||||||
lightrightstep = (r_lightptr[1] - lightright) >> 1;
|
|
||||||
|
|
||||||
for (i=0 ; i<2 ; i++)
|
|
||||||
{
|
|
||||||
lighttemp = lightleft - lightright;
|
|
||||||
lightstep = lighttemp >> 1;
|
|
||||||
|
|
||||||
light = lightright;
|
|
||||||
|
|
||||||
for (b=1; b>=0; b--)
|
|
||||||
{
|
|
||||||
pix = psource[b];
|
|
||||||
prowdest[b] = ((unsigned char *)vid.colormap)
|
|
||||||
[(light & 0xFF00) + pix];
|
|
||||||
light += lightstep;
|
|
||||||
}
|
|
||||||
|
|
||||||
psource += sourcetstep;
|
|
||||||
lightright += lightrightstep;
|
|
||||||
lightleft += lightleftstep;
|
|
||||||
prowdest += surfrowbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psource >= r_sourcemax)
|
|
||||||
psource -= r_stepback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_DrawSurfaceBlock16
|
|
||||||
|
|
||||||
FIXME: make this work
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_DrawSurfaceBlock16 (void)
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
unsigned char *psource;
|
|
||||||
int lighttemp, lightstep, light;
|
|
||||||
unsigned short *prowdest;
|
|
||||||
|
|
||||||
prowdest = (unsigned short *)prowdestbase;
|
|
||||||
|
|
||||||
for (k=0 ; k<blocksize ; k++)
|
|
||||||
{
|
|
||||||
unsigned short *pdest;
|
|
||||||
unsigned char pix;
|
|
||||||
int b;
|
|
||||||
|
|
||||||
psource = pbasesource;
|
|
||||||
lighttemp = lightright - lightleft;
|
|
||||||
lightstep = lighttemp >> blockdivshift;
|
|
||||||
|
|
||||||
light = lightleft;
|
|
||||||
pdest = prowdest;
|
|
||||||
|
|
||||||
for (b=0; b<blocksize; b++)
|
|
||||||
{
|
|
||||||
pix = *psource;
|
|
||||||
*pdest = vid.colormap16[(light & 0xFF00) + pix];
|
|
||||||
psource += sourcesstep;
|
|
||||||
pdest++;
|
|
||||||
light += lightstep;
|
|
||||||
}
|
|
||||||
|
|
||||||
pbasesource += sourcetstep;
|
|
||||||
lightright += lightrightstep;
|
|
||||||
lightleft += lightleftstep;
|
|
||||||
prowdest = (unsigned short *)((long)prowdest + surfrowbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
prowdestbase = prowdest;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_GenTurbTile
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_GenTurbTile (pixel_t *pbasetex, void *pdest)
|
|
||||||
{
|
|
||||||
int *turb;
|
|
||||||
int i, j, s, t;
|
|
||||||
byte *pd;
|
|
||||||
|
|
||||||
turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
|
|
||||||
pd = (byte *)pdest;
|
|
||||||
|
|
||||||
for (i=0 ; i<TILE_SIZE ; i++)
|
|
||||||
{
|
|
||||||
for (j=0 ; j<TILE_SIZE ; j++)
|
|
||||||
{
|
|
||||||
s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
|
|
||||||
t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
|
|
||||||
*pd++ = *(pbasetex + (t<<6) + s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_GenTurbTile16
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_GenTurbTile16 (pixel_t *pbasetex, void *pdest)
|
|
||||||
{
|
|
||||||
int *turb;
|
|
||||||
int i, j, s, t;
|
|
||||||
unsigned short *pd;
|
|
||||||
|
|
||||||
turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
|
|
||||||
pd = (unsigned short *)pdest;
|
|
||||||
|
|
||||||
for (i=0 ; i<TILE_SIZE ; i++)
|
|
||||||
{
|
|
||||||
for (j=0 ; j<TILE_SIZE ; j++)
|
|
||||||
{
|
|
||||||
s = (((j << 16) + turb[i & (CYCLE-1)]) >> 16) & 63;
|
|
||||||
t = (((i << 16) + turb[j & (CYCLE-1)]) >> 16) & 63;
|
|
||||||
*pd++ = d_8to16table[*(pbasetex + (t<<6) + s)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
R_GenTile
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
void R_GenTile (msurface_t *psurf, void *pdest)
|
|
||||||
{
|
|
||||||
if (psurf->flags & SURF_DRAWTURB)
|
|
||||||
{
|
|
||||||
if (r_pixbytes == 1)
|
|
||||||
{
|
|
||||||
R_GenTurbTile ((pixel_t *)
|
|
||||||
((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_GenTurbTile16 ((pixel_t *)
|
|
||||||
((byte *)psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (psurf->flags & SURF_DRAWSKY)
|
|
||||||
{
|
|
||||||
if (r_pixbytes == 1)
|
|
||||||
{
|
|
||||||
R_GenSkyTile (pdest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_GenSkyTile16 (pdest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Sys_Error ("Unknown tile type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
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.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef GLQUAKE
|
|
||||||
// r_shared.h: general refresh-related stuff shared between the refresh and the
|
|
||||||
// driver
|
|
||||||
|
|
||||||
// FIXME: clean up and move into d_iface.h
|
|
||||||
|
|
||||||
#ifndef _R_SHARED_H_
|
|
||||||
#define _R_SHARED_H_
|
|
||||||
|
|
||||||
#define MAXVERTS 16 // max points in a surface polygon
|
|
||||||
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
|
|
||||||
// polygon (while processing)
|
|
||||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
|
||||||
#define MAXHEIGHT 1024
|
|
||||||
#define MAXWIDTH 1280
|
|
||||||
|
|
||||||
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
|
|
||||||
// be farther away than anything in
|
|
||||||
// the scene
|
|
||||||
|
|
||||||
//===================================================================
|
|
||||||
|
|
||||||
extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
|
|
||||||
|
|
||||||
extern int cachewidth;
|
|
||||||
extern pixel_t *cacheblock;
|
|
||||||
extern int screenwidth;
|
|
||||||
|
|
||||||
extern float pixelAspect;
|
|
||||||
|
|
||||||
extern int r_drawnpolycount;
|
|
||||||
|
|
||||||
extern cvar_t r_clearcolor;
|
|
||||||
|
|
||||||
extern int sintable[1280];
|
|
||||||
extern int intsintable[1280];
|
|
||||||
|
|
||||||
extern vec3_t vup, base_vup;
|
|
||||||
extern vec3_t vpn, base_vpn;
|
|
||||||
extern vec3_t vright, base_vright;
|
|
||||||
extern entity_t *currententity;
|
|
||||||
|
|
||||||
#define NUMSTACKEDGES 2000
|
|
||||||
#define MINEDGES NUMSTACKEDGES
|
|
||||||
#define NUMSTACKSURFACES 1000
|
|
||||||
#define MINSURFACES NUMSTACKSURFACES
|
|
||||||
#define MAXSPANS 3000
|
|
||||||
|
|
||||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
|
||||||
typedef struct espan_s
|
|
||||||
{
|
|
||||||
int u, v, count;
|
|
||||||
struct espan_s *pnext;
|
|
||||||
} espan_t;
|
|
||||||
|
|
||||||
// FIXME: compress, make a union if that will help
|
|
||||||
// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte
|
|
||||||
typedef struct surf_s
|
|
||||||
{
|
|
||||||
struct surf_s *next; // active surface stack in r_edge.c
|
|
||||||
struct surf_s *prev; // used in r_edge.c for active surf stack
|
|
||||||
struct espan_s *spans; // pointer to linked list of spans to draw
|
|
||||||
int key; // sorting key (BSP order)
|
|
||||||
int last_u; // set during tracing
|
|
||||||
int spanstate; // 0 = not in span
|
|
||||||
// 1 = in span
|
|
||||||
// -1 = in inverted span (end before
|
|
||||||
// start)
|
|
||||||
int flags; // currentface flags
|
|
||||||
void *data; // associated data like msurface_t
|
|
||||||
entity_t *entity;
|
|
||||||
float nearzi; // nearest 1/z on surface, for mipmapping
|
|
||||||
qboolean insubmodel;
|
|
||||||
float d_ziorigin, d_zistepu, d_zistepv;
|
|
||||||
|
|
||||||
int pad[2]; // to 64 bytes
|
|
||||||
} surf_t;
|
|
||||||
|
|
||||||
extern surf_t *surfaces, *surface_p, *surf_max;
|
|
||||||
|
|
||||||
// surfaces are generated in back to front order by the bsp, so if a surf
|
|
||||||
// pointer is greater than another one, it should be drawn in front
|
|
||||||
// surfaces[1] is the background, and is used as the active surface stack.
|
|
||||||
// surfaces[0] is a dummy, because index 0 is used to indicate no surface
|
|
||||||
// attached to an edge_t
|
|
||||||
|
|
||||||
//===================================================================
|
|
||||||
|
|
||||||
extern vec3_t sxformaxis[4]; // s axis transformed into viewspace
|
|
||||||
extern vec3_t txformaxis[4]; // t axis transformed into viewspac
|
|
||||||
|
|
||||||
extern vec3_t modelorg, base_modelorg;
|
|
||||||
|
|
||||||
extern float xcenter, ycenter;
|
|
||||||
extern float xscale, yscale;
|
|
||||||
extern float xscaleinv, yscaleinv;
|
|
||||||
extern float xscaleshrink, yscaleshrink;
|
|
||||||
|
|
||||||
extern int d_lightstylevalue[256]; // 8.8 frac of base light value
|
|
||||||
|
|
||||||
extern void TransformVector (vec3_t in, vec3_t out);
|
|
||||||
extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
|
|
||||||
fixed8_t endvertu, fixed8_t endvertv);
|
|
||||||
|
|
||||||
extern int r_skymade;
|
|
||||||
extern void R_MakeSky (void);
|
|
||||||
|
|
||||||
extern int ubasestep, errorterm, erroradjustup, erroradjustdown;
|
|
||||||
|
|
||||||
// flags in finalvert_t.flags
|
|
||||||
#define ALIAS_LEFT_CLIP 0x0001
|
|
||||||
#define ALIAS_TOP_CLIP 0x0002
|
|
||||||
#define ALIAS_RIGHT_CLIP 0x0004
|
|
||||||
#define ALIAS_BOTTOM_CLIP 0x0008
|
|
||||||
#define ALIAS_Z_CLIP 0x0010
|
|
||||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
|
||||||
#define ALIAS_ONSEAM 0x0020 // also defined in modelgen.h;
|
|
||||||
// must be kept in sync
|
|
||||||
#define ALIAS_XY_CLIP_MASK 0x000F
|
|
||||||
|
|
||||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
|
||||||
typedef struct edge_s
|
|
||||||
{
|
|
||||||
fixed16_t u;
|
|
||||||
fixed16_t u_step;
|
|
||||||
struct edge_s *prev, *next;
|
|
||||||
unsigned short surfs[2];
|
|
||||||
struct edge_s *nextremove;
|
|
||||||
float nearzi;
|
|
||||||
medge_t *owner;
|
|
||||||
} edge_t;
|
|
||||||
|
|
||||||
#endif // _R_SHARED_H_
|
|
||||||
|
|
||||||
#endif // GLQUAKE
|
|
Loading…
Reference in a new issue