mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-12-23 17:25:24 +01:00
ref_soft: Copy world renderer from zq/q2, does not render anything now
This commit is contained in:
parent
ce27aad67b
commit
2b521ee201
626
r_bsp.c
Normal file
626
r_bsp.c
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 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_bsp.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
//
|
||||
// current entity info
|
||||
//
|
||||
qboolean insubmodel;
|
||||
vec3_t modelorg; // modelorg is the viewpoint reletive to
|
||||
// the currently rendering entity
|
||||
vec3_t r_entorigin; // the currently rendering entity in world
|
||||
// coordinates
|
||||
|
||||
float entity_rotation[3][3];
|
||||
|
||||
int r_currentbkey;
|
||||
|
||||
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
|
||||
|
||||
#define MAX_BMODEL_VERTS 500 // 6K
|
||||
#define MAX_BMODEL_EDGES 1000 // 12K
|
||||
|
||||
static mvertex_t *pbverts;
|
||||
static bedge_t *pbedges;
|
||||
static int numbverts, numbedges;
|
||||
|
||||
static mvertex_t *pfrontenter, *pfrontexit;
|
||||
|
||||
static qboolean makeclippededge;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
R_EntityRotate
|
||||
================
|
||||
*/
|
||||
void R_EntityRotate (vec3_t vec)
|
||||
{
|
||||
vec3_t tvec;
|
||||
|
||||
VectorCopy (vec, tvec);
|
||||
vec[0] = DotProduct (entity_rotation[0], tvec);
|
||||
vec[1] = DotProduct (entity_rotation[1], tvec);
|
||||
vec[2] = DotProduct (entity_rotation[2], tvec);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RotateBmodel
|
||||
================
|
||||
*/
|
||||
void R_RotateBmodel (void)
|
||||
{
|
||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
||||
|
||||
// TODO: should use a look-up table
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
// TODO: share work with R_SetUpAliasTransform
|
||||
|
||||
// yaw
|
||||
angle = RI.currententity->angles[YAW];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp1[0][0] = c;
|
||||
temp1[0][1] = s;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = -s;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = 0;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = 0;
|
||||
temp1[2][2] = 1;
|
||||
|
||||
|
||||
// pitch
|
||||
angle = RI.currententity->angles[PITCH];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp2[0][0] = c;
|
||||
temp2[0][1] = 0;
|
||||
temp2[0][2] = -s;
|
||||
temp2[1][0] = 0;
|
||||
temp2[1][1] = 1;
|
||||
temp2[1][2] = 0;
|
||||
temp2[2][0] = s;
|
||||
temp2[2][1] = 0;
|
||||
temp2[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp2, temp1, temp3);
|
||||
|
||||
// roll
|
||||
angle = RI.currententity->angles[ROLL];
|
||||
angle = angle * M_PI*2 / 360;
|
||||
s = sin(angle);
|
||||
c = cos(angle);
|
||||
|
||||
temp1[0][0] = 1;
|
||||
temp1[0][1] = 0;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = 0;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = s;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = -s;
|
||||
temp1[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp1, temp3, entity_rotation);
|
||||
|
||||
//
|
||||
// rotate modelorg and the transformation matrix
|
||||
//
|
||||
R_EntityRotate (modelorg);
|
||||
R_EntityRotate (vpn);
|
||||
R_EntityRotate (vright);
|
||||
R_EntityRotate (vup);
|
||||
|
||||
R_TransformFrustum ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_RecursiveClipBPoly
|
||||
|
||||
Clip a bmodel poly down the world bsp tree
|
||||
================
|
||||
*/
|
||||
void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf)
|
||||
{
|
||||
bedge_t *psideedges[2], *pnextedge, *ptedge;
|
||||
int i, side, lastside;
|
||||
float dist, frac, lastdist;
|
||||
mplane_t *splitplane, tplane;
|
||||
mvertex_t *pvert, *plastvert, *ptvert;
|
||||
mnode_t *pn;
|
||||
int area;
|
||||
|
||||
psideedges[0] = psideedges[1] = NULL;
|
||||
|
||||
makeclippededge = false;
|
||||
|
||||
// transform the BSP plane into model space
|
||||
// FIXME: cache these?
|
||||
splitplane = pnode->plane;
|
||||
tplane.dist = splitplane->dist -
|
||||
DotProduct(r_entorigin, splitplane->normal);
|
||||
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
|
||||
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
|
||||
tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal);
|
||||
|
||||
// clip edges to BSP plane
|
||||
for ( ; pedges ; pedges = pnextedge)
|
||||
{
|
||||
pnextedge = pedges->pnext;
|
||||
|
||||
// set the status for the last point as the previous point
|
||||
// FIXME: cache this stuff somehow?
|
||||
plastvert = pedges->v[0];
|
||||
lastdist = DotProduct (plastvert->position, tplane.normal) -
|
||||
tplane.dist;
|
||||
|
||||
if (lastdist > 0)
|
||||
lastside = 0;
|
||||
else
|
||||
lastside = 1;
|
||||
|
||||
pvert = pedges->v[1];
|
||||
|
||||
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
|
||||
|
||||
if (dist > 0)
|
||||
side = 0;
|
||||
else
|
||||
side = 1;
|
||||
|
||||
if (side != lastside)
|
||||
{
|
||||
// clipped
|
||||
if (numbverts >= MAX_BMODEL_VERTS)
|
||||
return;
|
||||
|
||||
// generate the clipped vertex
|
||||
frac = lastdist / (lastdist - dist);
|
||||
ptvert = &pbverts[numbverts++];
|
||||
ptvert->position[0] = plastvert->position[0] +
|
||||
frac * (pvert->position[0] -
|
||||
plastvert->position[0]);
|
||||
ptvert->position[1] = plastvert->position[1] +
|
||||
frac * (pvert->position[1] -
|
||||
plastvert->position[1]);
|
||||
ptvert->position[2] = plastvert->position[2] +
|
||||
frac * (pvert->position[2] -
|
||||
plastvert->position[2]);
|
||||
|
||||
// split into two edges, one on each side, and remember entering
|
||||
// and exiting points
|
||||
// FIXME: share the clip edge by having a winding direction flag?
|
||||
if (numbedges >= (MAX_BMODEL_EDGES - 1))
|
||||
{
|
||||
gEngfuncs.Con_Printf ("Out of edges for bmodel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptedge = &pbedges[numbedges];
|
||||
ptedge->pnext = psideedges[lastside];
|
||||
psideedges[lastside] = ptedge;
|
||||
ptedge->v[0] = plastvert;
|
||||
ptedge->v[1] = ptvert;
|
||||
|
||||
ptedge = &pbedges[numbedges + 1];
|
||||
ptedge->pnext = psideedges[side];
|
||||
psideedges[side] = ptedge;
|
||||
ptedge->v[0] = ptvert;
|
||||
ptedge->v[1] = pvert;
|
||||
|
||||
numbedges += 2;
|
||||
|
||||
if (side == 0)
|
||||
{
|
||||
// entering for front, exiting for back
|
||||
pfrontenter = ptvert;
|
||||
makeclippededge = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pfrontexit = ptvert;
|
||||
makeclippededge = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add the edge to the appropriate side
|
||||
pedges->pnext = psideedges[side];
|
||||
psideedges[side] = pedges;
|
||||
}
|
||||
}
|
||||
|
||||
// if anything was clipped, reconstitute and add the edges along the clip
|
||||
// plane to both sides (but in opposite directions)
|
||||
if (makeclippededge)
|
||||
{
|
||||
if (numbedges >= (MAX_BMODEL_EDGES - 2))
|
||||
{
|
||||
gEngfuncs.Con_Printf ("Out of edges for bmodel\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptedge = &pbedges[numbedges];
|
||||
ptedge->pnext = psideedges[0];
|
||||
psideedges[0] = ptedge;
|
||||
ptedge->v[0] = pfrontexit;
|
||||
ptedge->v[1] = pfrontenter;
|
||||
|
||||
ptedge = &pbedges[numbedges + 1];
|
||||
ptedge->pnext = psideedges[1];
|
||||
psideedges[1] = ptedge;
|
||||
ptedge->v[0] = pfrontenter;
|
||||
ptedge->v[1] = pfrontexit;
|
||||
|
||||
numbedges += 2;
|
||||
}
|
||||
// draw or recurse further
|
||||
for (i=0 ; i<2 ; i++)
|
||||
{
|
||||
if (psideedges[i])
|
||||
{
|
||||
// draw if we've reached a non-solid leaf, done if all that's left is a
|
||||
// solid leaf, and continue down the tree if it's not a leaf
|
||||
pn = pnode->children[i];
|
||||
|
||||
// we're done with this branch if the node or leaf isn't in the PVS
|
||||
if (pn->visframe == r_visframecount)
|
||||
{
|
||||
if (pn->contents < 0)
|
||||
{
|
||||
if (pn->contents != CONTENTS_SOLID)
|
||||
{
|
||||
r_currentbkey = ((mleaf_t *)pn)->cluster;
|
||||
R_RenderBmodelFace (psideedges[i], psurf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
|
||||
psurf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSolidClippedSubmodelPolygons
|
||||
|
||||
Bmodel crosses multiple leafs
|
||||
================
|
||||
*/
|
||||
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode)
|
||||
{
|
||||
int i, j, lindex;
|
||||
vec_t dot;
|
||||
msurface_t *psurf;
|
||||
int numsurfaces;
|
||||
mplane_t *pplane;
|
||||
mvertex_t bverts[MAX_BMODEL_VERTS];
|
||||
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
|
||||
medge_t *pedge, *pedges;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
|
||||
numsurfaces = pmodel->nummodelsurfaces;
|
||||
pedges = pmodel->edges;
|
||||
|
||||
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)))
|
||||
continue;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
// copy the edges to bedges, flipping if necessary so always
|
||||
// clockwise winding
|
||||
// FIXME: if edges and vertices get caches, these assignments must move
|
||||
// outside the loop, and overflow checking must be done here
|
||||
pbverts = bverts;
|
||||
pbedges = bedges;
|
||||
numbverts = numbedges = 0;
|
||||
pbedge = &bedges[numbedges];
|
||||
numbedges += psurf->numedges;
|
||||
|
||||
for (j=0 ; j<psurf->numedges ; j++)
|
||||
{
|
||||
lindex = pmodel->surfedges[psurf->firstedge+j];
|
||||
|
||||
if (lindex > 0)
|
||||
{
|
||||
pedge = &pedges[lindex];
|
||||
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]];
|
||||
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
lindex = -lindex;
|
||||
pedge = &pedges[lindex];
|
||||
pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]];
|
||||
pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]];
|
||||
}
|
||||
|
||||
pbedge[j].pnext = &pbedge[j+1];
|
||||
}
|
||||
|
||||
pbedge[j-1].pnext = NULL; // mark end of edges
|
||||
|
||||
//if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) )
|
||||
R_RecursiveClipBPoly (pbedge, topnode, psurf);
|
||||
//else
|
||||
// R_RenderBmodelFace( pbedge, psurf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_DrawSubmodelPolygons
|
||||
|
||||
All in one leaf
|
||||
================
|
||||
*/
|
||||
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode)
|
||||
{
|
||||
int i;
|
||||
vec_t dot;
|
||||
msurface_t *psurf;
|
||||
int numsurfaces;
|
||||
mplane_t *pplane;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
|
||||
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)))
|
||||
{
|
||||
r_currentkey = ((mleaf_t *)topnode)->cluster;
|
||||
|
||||
// FIXME: use bounding-box-based frustum clipping info?
|
||||
R_RenderFace (psurf, clipflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int c_drawnode;
|
||||
|
||||
/*
|
||||
================
|
||||
R_RecursiveWorldNode
|
||||
================
|
||||
*/
|
||||
void R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
int i, c, side, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
mplane_t *plane;
|
||||
msurface_t *surf, **mark;
|
||||
mleaf_t *pleaf;
|
||||
double d, dot;
|
||||
|
||||
if (node->contents == CONTENTS_SOLID)
|
||||
return; // solid
|
||||
|
||||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
// cull the clipping planes if not trivial accept
|
||||
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
|
||||
// twice as fast in ASM
|
||||
if (clipflags)
|
||||
{
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
if (! (clipflags & (1<<i)) )
|
||||
continue; // don't need to clip against it
|
||||
|
||||
// generate accept and reject points
|
||||
// FIXME: do with fast look-ups or integer tests based on the sign bit
|
||||
// of the floating point values
|
||||
|
||||
pindex = pfrustum_indexes[i];
|
||||
|
||||
rejectpt[0] = (float)node->minmaxs[pindex[0]];
|
||||
rejectpt[1] = (float)node->minmaxs[pindex[1]];
|
||||
rejectpt[2] = (float)node->minmaxs[pindex[2]];
|
||||
|
||||
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d <= 0)
|
||||
return;
|
||||
|
||||
acceptpt[0] = (float)node->minmaxs[pindex[3+0]];
|
||||
acceptpt[1] = (float)node->minmaxs[pindex[3+1]];
|
||||
acceptpt[2] = (float)node->minmaxs[pindex[3+2]];
|
||||
|
||||
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d >= 0)
|
||||
clipflags &= ~(1<<i); // node is entirely on screen
|
||||
}
|
||||
}
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if (node->contents < 0)
|
||||
{
|
||||
pleaf = (mleaf_t *)node;
|
||||
|
||||
mark = pleaf->firstmarksurface;
|
||||
c = pleaf->nummarksurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
do
|
||||
{
|
||||
(*mark)->visframe = r_framecount;
|
||||
mark++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
// deal with model fragments in this leaf
|
||||
if (pleaf->efrags)
|
||||
{
|
||||
gEngfuncs.R_StoreEfrags(&pleaf->efrags,tr.realframecount);
|
||||
}
|
||||
|
||||
pleaf->cluster = r_currentkey;
|
||||
r_currentkey++; // all bmodels in a leaf share the same key
|
||||
}
|
||||
else
|
||||
{
|
||||
// node is just a decision point, so go down the apropriate sides
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = node->plane;
|
||||
|
||||
switch (plane->type)
|
||||
{
|
||||
case PLANE_X:
|
||||
dot = modelorg[0] - plane->dist;
|
||||
break;
|
||||
case PLANE_Y:
|
||||
dot = modelorg[1] - plane->dist;
|
||||
break;
|
||||
case PLANE_Z:
|
||||
dot = modelorg[2] - plane->dist;
|
||||
break;
|
||||
default:
|
||||
dot = DotProduct (modelorg, plane->normal) - plane->dist;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dot >= 0)
|
||||
side = 0;
|
||||
else
|
||||
side = 1;
|
||||
|
||||
// recurse down the children, front side first
|
||||
R_RecursiveWorldNode (node->children[side], clipflags);
|
||||
|
||||
// draw stuff
|
||||
c = node->numsurfaces;
|
||||
|
||||
if (c)
|
||||
{
|
||||
surf = WORLDMODEL->surfaces + node->firstsurface;
|
||||
|
||||
if (dot < -BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
else if (dot > BACKFACE_EPSILON)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!(surf->flags & SURF_PLANEBACK) &&
|
||||
(surf->visframe == r_framecount))
|
||||
{
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
|
||||
surf++;
|
||||
} while (--c);
|
||||
}
|
||||
|
||||
// all surfaces on the same node share the same sequence number
|
||||
r_currentkey++;
|
||||
}
|
||||
|
||||
// recurse down the back side
|
||||
R_RecursiveWorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_RenderWorld
|
||||
================
|
||||
*/
|
||||
void R_RenderWorld (void)
|
||||
{
|
||||
|
||||
//if (!r_drawworld->value)
|
||||
// return;
|
||||
if ( !RI.drawWorld )
|
||||
return;
|
||||
|
||||
c_drawnode=0;
|
||||
|
||||
// auto cycle the world frame for texture animation
|
||||
RI.currententity = gEngfuncs.GetEntityByIndex(0);
|
||||
//RI.currententity->frame = (int)(gpGlobals->time*2);
|
||||
|
||||
VectorCopy (r_origin, modelorg);
|
||||
RI.currentmodel = WORLDMODEL;
|
||||
r_pcurrentvertbase = RI.currentmodel->vertexes;
|
||||
|
||||
R_RecursiveWorldNode (RI.currentmodel->nodes, 15);
|
||||
}
|
||||
|
||||
|
105
r_context.c
105
r_context.c
@ -22,6 +22,10 @@ gl_globals_t tr;
|
||||
ref_speeds_t r_stats;
|
||||
byte *r_temppool;
|
||||
cvar_t *gl_emboss_scale;
|
||||
cvar_t *r_drawentities;
|
||||
cvar_t *r_norefresh;
|
||||
cvar_t *vid_gamma;
|
||||
cvar_t *vid_brightness;
|
||||
viddef_t vid;
|
||||
static void R_ClearScreen( void )
|
||||
{
|
||||
@ -319,7 +323,7 @@ void GL_SetTexCoordArrayMode()
|
||||
{
|
||||
|
||||
}
|
||||
void R_InitBlit();
|
||||
|
||||
void GL_OnContextCreated()
|
||||
{
|
||||
R_InitBlit();
|
||||
@ -333,30 +337,6 @@ void GL_InitExtensions()
|
||||
void GL_ClearExtensions()
|
||||
{
|
||||
|
||||
}
|
||||
void R_BeginFrame(qboolean clearScene)
|
||||
{
|
||||
}
|
||||
|
||||
void R_RenderScene()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_EndFrame()
|
||||
{
|
||||
// blit pixels with GL until engine supports REF_SOFT context
|
||||
R_BlitScreen();
|
||||
}
|
||||
|
||||
void R_PushScene()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_PopScene()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_BackendStartFrame()
|
||||
@ -369,10 +349,6 @@ void GL_BackendEndFrame()
|
||||
|
||||
}
|
||||
|
||||
void R_AllowFog(qboolean allowed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_SetRenderMode(int mode)
|
||||
{
|
||||
@ -381,12 +357,6 @@ void GL_SetRenderMode(int mode)
|
||||
/// maybe, setup block drawing function pointers here
|
||||
}
|
||||
|
||||
qboolean R_AddEntity(struct cl_entity_s *pRefEntity, int entityType)
|
||||
{
|
||||
// no entities support until we draw world...
|
||||
return false;
|
||||
}
|
||||
|
||||
void CL_AddCustomBeam(cl_entity_t *pEnvBeam)
|
||||
{
|
||||
// same for beams
|
||||
@ -417,12 +387,6 @@ qboolean VID_CubemapShot(const char *base, uint size, const float *vieworg, qboo
|
||||
// cubemaps? in my softrender???
|
||||
}
|
||||
|
||||
colorVec R_LightPoint(const vec3_t p0)
|
||||
{
|
||||
colorVec c = {0};
|
||||
return c;
|
||||
}
|
||||
|
||||
void R_DecalShoot(int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale)
|
||||
{
|
||||
|
||||
@ -468,11 +432,6 @@ void GL_SubdivideSurface(msurface_t *fa)
|
||||
|
||||
}
|
||||
|
||||
void CL_RunLightStyles()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Mod_LoadMapSprite(model_t *mod, const void *buffer, size_t size, qboolean *loaded)
|
||||
{
|
||||
|
||||
@ -558,17 +517,6 @@ struct mstudiotex_s *R_StudioGetTexture(cl_entity_t *e)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
colorVec R_LightVec(const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec)
|
||||
{
|
||||
colorVec v = {0};
|
||||
return v;
|
||||
}
|
||||
|
||||
int R_RenderFrame(const struct ref_viewpass_s *vp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GL_BuildLightmaps()
|
||||
{
|
||||
|
||||
@ -589,16 +537,6 @@ byte *Mod_GetCurrentVis()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void R_ClearScene()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_NewMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_ScreenToWorld(const vec3_t screen, vec3_t point)
|
||||
{
|
||||
|
||||
@ -617,39 +555,6 @@ void GL_SetupAttributes( int safegl )
|
||||
gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
qboolean R_Init()
|
||||
{
|
||||
gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" );
|
||||
// create the window and set up the context
|
||||
r_temppool = Mem_AllocPool( "ref_sw zone" );
|
||||
|
||||
vid.width = 1920;
|
||||
vid.height = 1080;
|
||||
vid.rowbytes = 1920; // rowpixels
|
||||
|
||||
vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) );
|
||||
if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context
|
||||
{
|
||||
gEngfuncs.R_Free_Video();
|
||||
|
||||
gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
R_InitImages();
|
||||
return true;
|
||||
}
|
||||
|
||||
void R_Shutdown()
|
||||
{
|
||||
R_ShutdownImages();
|
||||
gEngfuncs.R_Free_Video();
|
||||
}
|
||||
|
||||
ref_interface_t gReffuncs =
|
||||
{
|
||||
R_Init,
|
||||
|
8
r_draw.c
8
r_draw.c
@ -151,7 +151,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1,
|
||||
}
|
||||
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) )
|
||||
{
|
||||
pixel_t screen = dest[u];
|
||||
pixel_t screen = dest[u]; // | 0xff & screen & src ;
|
||||
dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3);
|
||||
|
||||
}
|
||||
@ -181,6 +181,12 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f
|
||||
R_DrawStretchPicImplementation(x,y,w,h, pic->width * s1, pic->height * t1, pic->width * s2, pic->height * t2, pic);
|
||||
}
|
||||
|
||||
void Draw_Fill (int x, int y, int w, int h, int c)
|
||||
{
|
||||
// todo: color
|
||||
R_DrawStretchPicImplementation(x,y,w,h, 0, 0, 12, 1, tr.whiteTexture );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_TileClear
|
||||
|
@ -218,5 +218,5 @@ void R_BlitScreen()
|
||||
pglEnd();
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
gEngfuncs.GL_SwapBuffers();
|
||||
memset( vid.buffer, 0, vid.width * vid.height * 2 );
|
||||
// memset( vid.buffer, 0, vid.width * vid.height * 2 );
|
||||
}
|
||||
|
499
r_light.c
Normal file
499
r_light.c
Normal file
@ -0,0 +1,499 @@
|
||||
/*
|
||||
gl_rlight.c - dynamic and static lights
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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 3 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.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "pm_local.h"
|
||||
#include "studio.h"
|
||||
#include "mathlib.h"
|
||||
#include "ref_params.h"
|
||||
|
||||
//unused, need refactor
|
||||
unsigned blocklights[1024];
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
==================
|
||||
CL_RunLightStyles
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_RunLightStyles( void )
|
||||
{
|
||||
int i, k, flight, clight;
|
||||
float l, lerpfrac, backlerp;
|
||||
float frametime = (gpGlobals->time - gpGlobals->oldtime);
|
||||
float scale;
|
||||
lightstyle_t *ls;
|
||||
|
||||
if( !WORLDMODEL ) return;
|
||||
|
||||
scale = 1; //r_lighting_modulate->value;
|
||||
|
||||
// light animations
|
||||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
|
||||
{
|
||||
ls = gEngfuncs.GetLightStyle( i );
|
||||
if( !WORLDMODEL->lightdata )
|
||||
{
|
||||
tr.lightstylevalue[i] = 256 * 256;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !gEngfuncs.CL_GetRenderParm( PARAM_GAMEPAUSED, 0 ) && frametime <= 0.1f )
|
||||
ls->time += frametime; // evaluate local time
|
||||
|
||||
flight = (int)Q_floor( ls->time * 10 );
|
||||
clight = (int)Q_ceil( ls->time * 10 );
|
||||
lerpfrac = ( ls->time * 10 ) - flight;
|
||||
backlerp = 1.0f - lerpfrac;
|
||||
|
||||
if( !ls->length )
|
||||
{
|
||||
tr.lightstylevalue[i] = 256 * scale;
|
||||
continue;
|
||||
}
|
||||
else if( ls->length == 1 )
|
||||
{
|
||||
// single length style so don't bother interpolating
|
||||
tr.lightstylevalue[i] = ls->map[0] * 22 * scale;
|
||||
continue;
|
||||
}
|
||||
else if( !ls->interp ) // || !CVAR_TO_BOOL( cl_lightstyle_lerping ))
|
||||
{
|
||||
tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
// interpolate animating light
|
||||
// frame just gone
|
||||
k = ls->map[flight % ls->length];
|
||||
l = (float)( k * 22.0f ) * backlerp;
|
||||
|
||||
// upcoming frame
|
||||
k = ls->map[clight % ls->length];
|
||||
l += (float)( k * 22.0f ) * lerpfrac;
|
||||
|
||||
tr.lightstylevalue[i] = (int)l * scale;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
||||
{
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
|
||||
if( !node || node->contents < 0 )
|
||||
return;
|
||||
|
||||
dist = PlaneDiff( light->origin, node->plane );
|
||||
|
||||
if( dist > light->radius )
|
||||
{
|
||||
R_MarkLights( light, bit, node->children[0] );
|
||||
return;
|
||||
}
|
||||
if( dist < -light->radius )
|
||||
{
|
||||
R_MarkLights( light, bit, node->children[1] );
|
||||
return;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
surf = RI.currentmodel->surfaces + node->firstsurface;
|
||||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||
continue; // no intersection
|
||||
|
||||
if( surf->dlightframe != tr.dlightframecount )
|
||||
{
|
||||
surf->dlightbits = 0;
|
||||
surf->dlightframe = tr.dlightframecount;
|
||||
}
|
||||
surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights( light, bit, node->children[0] );
|
||||
R_MarkLights( light, bit, node->children[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void R_PushDlights( void )
|
||||
{
|
||||
dlight_t *l;
|
||||
int i;
|
||||
|
||||
tr.dlightframecount = tr.framecount;
|
||||
|
||||
RI.currententity = gEngfuncs.GetEntityByIndex( 0 );
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
l = gEngfuncs.GetDynamicLight( i );
|
||||
|
||||
if( l->die < gpGlobals->time || !l->radius )
|
||||
continue;
|
||||
|
||||
//if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||
//continue;
|
||||
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CountDlights
|
||||
=============
|
||||
*/
|
||||
int R_CountDlights( void )
|
||||
{
|
||||
dlight_t *l;
|
||||
int i, numDlights = 0;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
l = gEngfuncs.GetDynamicLight( i );
|
||||
|
||||
if( l->die < gpGlobals->time || !l->radius )
|
||||
continue;
|
||||
|
||||
numDlights++;
|
||||
}
|
||||
|
||||
return numDlights;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CountSurfaceDlights
|
||||
=============
|
||||
*/
|
||||
int R_CountSurfaceDlights( msurface_t *surf )
|
||||
{
|
||||
int i, numDlights = 0;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
if(!( surf->dlightbits & BIT( i )))
|
||||
continue; // not lit by this light
|
||||
|
||||
numDlights++;
|
||||
}
|
||||
|
||||
return numDlights;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
AMBIENT LIGHTING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
static vec3_t g_trace_lightspot;
|
||||
static vec3_t g_trace_lightvec;
|
||||
static float g_trace_fraction;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
float front, back, frac, midf;
|
||||
int i, map, side, size;
|
||||
float ds, dt, s, t;
|
||||
int sample_size;
|
||||
color24 *lm, *dm;
|
||||
mextrasurf_t *info;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
matrix3x4 tbn;
|
||||
vec3_t mid;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node || node->contents < 0 )
|
||||
{
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate mid point
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( end, node->plane );
|
||||
|
||||
side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
VectorLerp( start, frac, end, mid );
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
|
||||
// co down front side
|
||||
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0 ) == side )
|
||||
{
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
return false; // didn't hit anything
|
||||
}
|
||||
|
||||
// check for impact on this node
|
||||
surf = model->surfaces + node->firstsurface;
|
||||
VectorCopy( mid, g_trace_lightspot );
|
||||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
int smax, tmax;
|
||||
|
||||
tex = surf->texinfo;
|
||||
info = surf->info;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3];
|
||||
t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3];
|
||||
|
||||
if( s < info->lightmapmins[0] || t < info->lightmapmins[1] )
|
||||
continue;
|
||||
|
||||
ds = s - info->lightmapmins[0];
|
||||
dt = t - info->lightmapmins[1];
|
||||
|
||||
if ( ds > info->lightextents[0] || dt > info->lightextents[1] )
|
||||
continue;
|
||||
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
smax = (info->lightextents[0] / sample_size) + 1;
|
||||
tmax = (info->lightextents[1] / sample_size) + 1;
|
||||
ds /= sample_size;
|
||||
dt /= sample_size;
|
||||
|
||||
lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
g_trace_fraction = midf;
|
||||
size = smax * tmax;
|
||||
dm = NULL;
|
||||
|
||||
if( surf->info->deluxemap )
|
||||
{
|
||||
vec3_t faceNormal;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
VectorNegate( surf->plane->normal, faceNormal );
|
||||
else VectorCopy( surf->plane->normal, faceNormal );
|
||||
|
||||
// compute face TBN
|
||||
#if 1
|
||||
Vector4Set( tbn[0], surf->info->lmvecs[0][0], surf->info->lmvecs[0][1], surf->info->lmvecs[0][2], 0.0f );
|
||||
Vector4Set( tbn[1], -surf->info->lmvecs[1][0], -surf->info->lmvecs[1][1], -surf->info->lmvecs[1][2], 0.0f );
|
||||
Vector4Set( tbn[2], faceNormal[0], faceNormal[1], faceNormal[2], 0.0f );
|
||||
#else
|
||||
Vector4Set( tbn[0], surf->info->lmvecs[0][0], -surf->info->lmvecs[1][0], faceNormal[0], 0.0f );
|
||||
Vector4Set( tbn[1], surf->info->lmvecs[0][1], -surf->info->lmvecs[1][1], faceNormal[1], 0.0f );
|
||||
Vector4Set( tbn[2], surf->info->lmvecs[0][2], -surf->info->lmvecs[1][2], faceNormal[2], 0.0f );
|
||||
#endif
|
||||
VectorNormalize( tbn[0] );
|
||||
VectorNormalize( tbn[1] );
|
||||
VectorNormalize( tbn[2] );
|
||||
dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
}
|
||||
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
uint scale = tr.lightstylevalue[surf->styles[map]];
|
||||
|
||||
if( tr.ignore_lightgamma )
|
||||
{
|
||||
cv->r += lm->r * scale;
|
||||
cv->g += lm->g * scale;
|
||||
cv->b += lm->b * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale;
|
||||
cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale;
|
||||
cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale;
|
||||
}
|
||||
lm += size; // skip to next lightmap
|
||||
|
||||
if( dm != NULL )
|
||||
{
|
||||
vec3_t srcNormal, lightNormal;
|
||||
float f = (1.0f / 128.0f);
|
||||
|
||||
VectorSet( srcNormal, ((float)dm->r - 128.0f) * f, ((float)dm->g - 128.0f) * f, ((float)dm->b - 128.0f) * f );
|
||||
Matrix3x4_VectorIRotate( tbn, srcNormal, lightNormal ); // turn to world space
|
||||
VectorScale( lightNormal, (float)scale * -1.0f, lightNormal ); // turn direction from light
|
||||
VectorAdd( g_trace_lightvec, lightNormal, g_trace_lightvec );
|
||||
dm += size; // skip to next deluxmap
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
float last_fraction;
|
||||
int i, maxEnts = 1;
|
||||
colorVec light, cv;
|
||||
|
||||
if( lspot ) VectorClear( lspot );
|
||||
if( lvec ) VectorClear( lvec );
|
||||
|
||||
if( WORLDMODEL && WORLDMODEL->lightdata )
|
||||
{
|
||||
light.r = light.g = light.b = light.a = 0;
|
||||
last_fraction = 1.0f;
|
||||
|
||||
// get light from bmodels too
|
||||
//if( CVAR_TO_BOOL( r_lighting_extended ))
|
||||
maxEnts = MAX_PHYSENTS;
|
||||
|
||||
// check all the bsp-models
|
||||
for( i = 0; i < maxEnts; i++ )
|
||||
{
|
||||
physent_t *pe = gEngfuncs.EV_GetPhysent( i );
|
||||
vec3_t offset, start_l, end_l;
|
||||
mnode_t *pnodes;
|
||||
matrix4x4 matrix;
|
||||
|
||||
if( !pe )
|
||||
break;
|
||||
|
||||
if( !pe->model || pe->model->type != mod_brush )
|
||||
continue; // skip non-bsp models
|
||||
|
||||
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( !VectorIsNull( pe->angles ))
|
||||
{
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||
}
|
||||
|
||||
VectorClear( g_trace_lightspot );
|
||||
VectorClear( g_trace_lightvec );
|
||||
g_trace_fraction = 1.0f;
|
||||
|
||||
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
|
||||
continue; // didn't hit anything
|
||||
|
||||
if( g_trace_fraction < last_fraction )
|
||||
{
|
||||
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
|
||||
if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
|
||||
light.r = Q_min(( cv.r >> 7 ), 255 );
|
||||
light.g = Q_min(( cv.g >> 7 ), 255 );
|
||||
light.b = Q_min(( cv.b >> 7 ), 255 );
|
||||
last_fraction = g_trace_fraction;
|
||||
|
||||
if(( light.r + light.g + light.b ) != 0 )
|
||||
break; // we get light now
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
light.r = light.g = light.b = 255;
|
||||
light.a = 0;
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
|
||||
|
||||
if( lspot != NULL && lvec != NULL ) // CVAR_TO_BOOL( r_lighting_extended ) &&
|
||||
{
|
||||
// trying to get light from ceiling (but ignore gradient analyze)
|
||||
if(( light.r + light.g + light.b ) == 0 )
|
||||
return R_LightVecInternal( end, start, lspot, lvec );
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightPoint
|
||||
|
||||
light from floor
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightPoint( const vec3_t p0 )
|
||||
{
|
||||
vec3_t p1;
|
||||
|
||||
VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f );
|
||||
|
||||
return R_LightVec( p0, p1, NULL, NULL );
|
||||
}
|
516
r_local.h
516
r_local.h
@ -32,6 +32,10 @@ GNU General Public License for more details.
|
||||
#include "pm_movevars.h"
|
||||
//#include "cvar.h"
|
||||
typedef struct mip_s mip_t;
|
||||
|
||||
typedef int fixed8_t;
|
||||
typedef int fixed16_t;
|
||||
|
||||
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
||||
|
||||
#define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
@ -426,7 +430,7 @@ void R_InitDlightTexture( void );
|
||||
void R_TextureList_f( void );
|
||||
void R_InitImages( void );
|
||||
void R_ShutdownImages( void );
|
||||
#if 0
|
||||
#if 1
|
||||
//
|
||||
// gl_rlight.c
|
||||
//
|
||||
@ -439,7 +443,7 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec
|
||||
int R_CountSurfaceDlights( msurface_t *surf );
|
||||
colorVec R_LightPoint( const vec3_t p0 );
|
||||
int R_CountDlights( void );
|
||||
|
||||
#endif
|
||||
//
|
||||
// gl_rmain.c
|
||||
//
|
||||
@ -457,7 +461,7 @@ void R_FindViewLeaf( void );
|
||||
void R_PushScene( void );
|
||||
void R_PopScene( void );
|
||||
void R_DrawFog( void );
|
||||
|
||||
#if 0
|
||||
//
|
||||
// gl_rmath.c
|
||||
//
|
||||
@ -610,8 +614,8 @@ void Mod_SpriteUnloadTextures( void *data );
|
||||
void Mod_UnloadAliasModel( struct model_s *mod );
|
||||
void Mod_AliasUnloadTextures( void *data );
|
||||
void GL_SetRenderMode( int mode );
|
||||
void R_RunViewmodelEvents( void );
|
||||
void R_DrawViewModel( void );
|
||||
//void R_RunViewmodelEvents( void );
|
||||
//void R_DrawViewModel( void );
|
||||
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||
@ -654,9 +658,20 @@ void TriFogParams( float flDensity, int iFogSkybox );
|
||||
void TriCullFace( TRICULLSTYLE mode );
|
||||
|
||||
|
||||
//
|
||||
// r_blitscreen.c
|
||||
//
|
||||
void R_BlitScreen();
|
||||
void R_InitBlit();
|
||||
|
||||
|
||||
extern ref_api_t gEngfuncs;
|
||||
extern ref_globals_t *gpGlobals;
|
||||
extern cvar_t *gl_emboss_scale;
|
||||
extern cvar_t *r_drawentities;
|
||||
extern cvar_t *vid_brightness;
|
||||
extern cvar_t *vid_gamma;
|
||||
extern cvar_t *r_norefresh;
|
||||
#if 0
|
||||
//
|
||||
// renderer cvars
|
||||
@ -682,7 +697,6 @@ extern cvar_t *gl_stencilbits;
|
||||
|
||||
extern cvar_t *r_speeds;
|
||||
extern cvar_t *r_fullbright;
|
||||
extern cvar_t *r_norefresh;
|
||||
extern cvar_t *r_showtree; // build graph of visible hull
|
||||
extern cvar_t *r_lighting_extended;
|
||||
extern cvar_t *r_lighting_modulate;
|
||||
@ -715,6 +729,496 @@ extern cvar_t *traceralpha;
|
||||
extern cvar_t *cl_lightstyle_lerping;
|
||||
extern cvar_t *r_showhull;
|
||||
#endif
|
||||
// softrender defs
|
||||
|
||||
#define CACHE_SIZE 32
|
||||
|
||||
/*
|
||||
====================================================
|
||||
CONSTANTS
|
||||
====================================================
|
||||
*/
|
||||
|
||||
#define VID_CBITS 6
|
||||
#define VID_GRADES (1 << VID_CBITS)
|
||||
|
||||
|
||||
// r_shared.h: general refresh-related stuff shared between the refresh and the
|
||||
// driver
|
||||
|
||||
|
||||
#define MAXVERTS 64 // 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 1200
|
||||
#define MAXWIDTH 1600
|
||||
|
||||
#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
|
||||
// be farther away than anything in
|
||||
// the scene
|
||||
|
||||
|
||||
// d_iface.h: interface header file for rasterization driver modules
|
||||
|
||||
#define WARP_WIDTH 320
|
||||
#define WARP_HEIGHT 240
|
||||
|
||||
#define MAX_LBM_HEIGHT 480
|
||||
|
||||
|
||||
#define PARTICLE_Z_CLIP 8.0
|
||||
|
||||
// !!! must be kept the same as in quakeasm.h !!!
|
||||
#define TRANSPARENT_COLOR 0xFF
|
||||
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define TURB_TEX_SIZE 64 // base turbulent texture size
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
#define CYCLE 128 // turbulent cycle size
|
||||
|
||||
#define SCANBUFFERPAD 0x1000
|
||||
|
||||
#define DS_SPAN_LIST_END -128
|
||||
|
||||
#define NUMSTACKEDGES 2000
|
||||
#define MINEDGES NUMSTACKEDGES
|
||||
#define NUMSTACKSURFACES 1000
|
||||
#define MINSURFACES NUMSTACKSURFACES
|
||||
#define MAXSPANS 3000
|
||||
|
||||
// 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
|
||||
#define ALIAS_XY_CLIP_MASK 0x000F
|
||||
|
||||
#define SURFCACHE_SIZE_AT_320X240 1024*768
|
||||
|
||||
#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox ()
|
||||
// if bbox is trivially rejected
|
||||
|
||||
#define XCENTERING (1.0 / 2.0)
|
||||
#define YCENTERING (1.0 / 2.0)
|
||||
|
||||
#define CLIP_EPSILON 0.001
|
||||
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
#define NEAR_CLIP 0.01
|
||||
|
||||
|
||||
#define MAXALIASVERTS 2000 // TODO: tune this
|
||||
#define ALIAS_Z_CLIP_PLANE 4
|
||||
|
||||
// turbulence stuff
|
||||
|
||||
#define AMP 8*0x10000
|
||||
#define AMP2 3
|
||||
#define SPEED 20
|
||||
|
||||
|
||||
/*
|
||||
====================================================
|
||||
TYPES
|
||||
====================================================
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
float s, t;
|
||||
float zi;
|
||||
} emitpoint_t;
|
||||
|
||||
/*
|
||||
** if you change this structure be sure to change the #defines
|
||||
** listed after it!
|
||||
*/
|
||||
#define SMALL_FINALVERT 0
|
||||
|
||||
#if SMALL_FINALVERT
|
||||
|
||||
typedef struct finalvert_s {
|
||||
short u, v, s, t;
|
||||
int l;
|
||||
int zi;
|
||||
int flags;
|
||||
float xyz[3]; // eye space
|
||||
} finalvert_t;
|
||||
|
||||
#define FINALVERT_V0 0
|
||||
#define FINALVERT_V1 2
|
||||
#define FINALVERT_V2 4
|
||||
#define FINALVERT_V3 6
|
||||
#define FINALVERT_V4 8
|
||||
#define FINALVERT_V5 12
|
||||
#define FINALVERT_FLAGS 16
|
||||
#define FINALVERT_X 20
|
||||
#define FINALVERT_Y 24
|
||||
#define FINALVERT_Z 28
|
||||
#define FINALVERT_SIZE 32
|
||||
|
||||
#else
|
||||
|
||||
typedef struct finalvert_s {
|
||||
int u, v, s, t;
|
||||
int l;
|
||||
int zi;
|
||||
int flags;
|
||||
float xyz[3]; // eye space
|
||||
} finalvert_t;
|
||||
|
||||
#define FINALVERT_V0 0
|
||||
#define FINALVERT_V1 4
|
||||
#define FINALVERT_V2 8
|
||||
#define FINALVERT_V3 12
|
||||
#define FINALVERT_V4 16
|
||||
#define FINALVERT_V5 20
|
||||
#define FINALVERT_FLAGS 24
|
||||
#define FINALVERT_X 28
|
||||
#define FINALVERT_Y 32
|
||||
#define FINALVERT_Z 36
|
||||
#define FINALVERT_SIZE 40
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short s;
|
||||
short t;
|
||||
} dstvert_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short index_xyz[3];
|
||||
short index_st[3];
|
||||
} dtriangle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte v[3]; // scaled byte to fit in frame mins/maxs
|
||||
byte lightnormalindex;
|
||||
} dtrivertx_t;
|
||||
|
||||
#define DTRIVERTX_V0 0
|
||||
#define DTRIVERTX_V1 1
|
||||
#define DTRIVERTX_V2 2
|
||||
#define DTRIVERTX_LNI 3
|
||||
#define DTRIVERTX_SIZE 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *pskin;
|
||||
int pskindesc;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
dtriangle_t *ptriangles;
|
||||
finalvert_t *pfinalverts;
|
||||
int numtriangles;
|
||||
int drawtype;
|
||||
int seamfixupX16;
|
||||
qboolean do_vis_thresh;
|
||||
int vis_thresh;
|
||||
} affinetridesc_t;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte *surfdat; // destination for generated surface
|
||||
int rowbytes; // destination logical width in bytes
|
||||
msurface_t *surf; // description for surface to generate
|
||||
fixed8_t lightadj[MAXLIGHTMAPS];
|
||||
// adjust for lightmap levels for dynamic lighting
|
||||
image_t *image;
|
||||
int surfmip; // mipmapped ratio of surface texels / world pixels
|
||||
int surfwidth; // in mipmapped texels
|
||||
int surfheight; // in mipmapped texels
|
||||
} drawsurf_t;
|
||||
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
int ambientlight;
|
||||
int shadelight;
|
||||
float *plightvec;
|
||||
} alight_t;
|
||||
|
||||
#endif
|
||||
|
||||
// clipped bmodel edges
|
||||
|
||||
typedef struct bedge_s
|
||||
{
|
||||
mvertex_t *v[2];
|
||||
struct bedge_s *pnext;
|
||||
} bedge_t;
|
||||
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct clipplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
struct clipplane_s *next;
|
||||
byte leftedge;
|
||||
byte rightedge;
|
||||
byte reserved[2];
|
||||
} clipplane_t;
|
||||
|
||||
|
||||
typedef struct surfcache_s
|
||||
{
|
||||
struct surfcache_s *next;
|
||||
struct surfcache_s **owner; // NULL is an empty chunk of memory
|
||||
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
|
||||
int dlight;
|
||||
int size; // including header
|
||||
unsigned width;
|
||||
unsigned height; // DEBUG only needed for debug
|
||||
float mipscale;
|
||||
image_t *image;
|
||||
byte data[4]; // width*height elements
|
||||
} surfcache_t;
|
||||
|
||||
// !!! 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;
|
||||
|
||||
// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C)
|
||||
typedef struct
|
||||
{
|
||||
int nump;
|
||||
emitpoint_t *pverts;
|
||||
byte *pixels; // image
|
||||
int pixel_width; // image width
|
||||
int pixel_height; // image height
|
||||
vec3_t vup, vright, vpn; // in worldspace, for plane eq
|
||||
float dist;
|
||||
float s_offset, t_offset;
|
||||
float viewer_position[3];
|
||||
void (*drawspanlet)( void );
|
||||
int stipple_parity;
|
||||
} polydesc_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
|
||||
msurface_t *msurf;
|
||||
cl_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;
|
||||
|
||||
// !!! 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;
|
||||
|
||||
|
||||
/*
|
||||
====================================================
|
||||
VARS
|
||||
====================================================
|
||||
*/
|
||||
|
||||
extern int d_spanpixcount;
|
||||
extern int r_framecount; // sequence # of current frame since Quake
|
||||
// started
|
||||
extern float r_aliasuvscale; // scale-up factor for screen u and v
|
||||
// on Alias vertices passed to driver
|
||||
extern qboolean r_dowarp;
|
||||
|
||||
extern affinetridesc_t r_affinetridesc;
|
||||
|
||||
extern vec3_t r_pright, r_pup, r_ppn;
|
||||
|
||||
void D_DrawSurfaces (void);
|
||||
void R_DrawParticle( void );
|
||||
void D_ViewChanged (void);
|
||||
void D_WarpScreen (void);
|
||||
void R_PolysetUpdateTables (void);
|
||||
|
||||
extern void *acolormap; // FIXME: should go away
|
||||
|
||||
//=======================================================================//
|
||||
|
||||
// callbacks to Quake
|
||||
|
||||
extern drawsurf_t r_drawsurf;
|
||||
|
||||
void R_DrawSurface (void);
|
||||
|
||||
extern int c_surf;
|
||||
|
||||
extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT];
|
||||
|
||||
|
||||
|
||||
|
||||
extern float scale_for_mip;
|
||||
|
||||
extern qboolean d_roverwrapped;
|
||||
extern surfcache_t *sc_rover;
|
||||
extern surfcache_t *d_initial_rover;
|
||||
|
||||
extern float d_sdivzstepu, d_tdivzstepu, d_zistepu;
|
||||
extern float d_sdivzstepv, d_tdivzstepv, d_zistepv;
|
||||
extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin;
|
||||
|
||||
extern fixed16_t sadjust, tadjust;
|
||||
extern fixed16_t bbextents, bbextentt;
|
||||
|
||||
|
||||
void D_DrawSpans16 (espan_t *pspans);
|
||||
void D_DrawZSpans (espan_t *pspans);
|
||||
void Turbulent8 (espan_t *pspan);
|
||||
void NonTurbulent8 (espan_t *pspan); //PGM
|
||||
|
||||
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel);
|
||||
|
||||
extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
extern int d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
extern pixel_t *d_viewbuffer;
|
||||
extern short *d_pzbuffer;
|
||||
extern unsigned int d_zrowbytes, d_zwidth;
|
||||
extern short *zspantable[MAXHEIGHT];
|
||||
extern int d_scantable[MAXHEIGHT];
|
||||
|
||||
extern int d_minmip;
|
||||
extern float d_scalemip[3];
|
||||
|
||||
//===================================================================
|
||||
|
||||
extern int cachewidth;
|
||||
extern pixel_t *cacheblock;
|
||||
extern int r_screenwidth;
|
||||
|
||||
extern int r_drawnpolycount;
|
||||
|
||||
extern int sintable[1280];
|
||||
extern int intsintable[1280];
|
||||
extern int blanktable[1280]; // PGM
|
||||
|
||||
extern vec3_t vup, base_vup;
|
||||
extern vec3_t vpn, base_vpn;
|
||||
extern vec3_t vright, base_vright;
|
||||
|
||||
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 float xcenter, ycenter;
|
||||
extern float xscale, yscale;
|
||||
extern float xscaleinv, yscaleinv;
|
||||
extern float xscaleshrink, yscaleshrink;
|
||||
|
||||
|
||||
extern edge_t *auxedges;
|
||||
extern int r_numallocatededges;
|
||||
extern edge_t *r_edges, *edge_p, *edge_max;
|
||||
|
||||
extern edge_t *newedges[MAXHEIGHT];
|
||||
extern edge_t *removeedges[MAXHEIGHT];
|
||||
|
||||
// FIXME: make stack vars when debugging done
|
||||
extern edge_t edge_head;
|
||||
extern edge_t edge_tail;
|
||||
extern edge_t edge_aftertail;
|
||||
|
||||
|
||||
extern int r_frustum_indexes[4*6];
|
||||
extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs;
|
||||
extern qboolean r_surfsonstack;
|
||||
|
||||
extern mleaf_t *r_viewleaf;
|
||||
extern int r_viewcluster, r_oldviewcluster;
|
||||
|
||||
extern int r_clipflags;
|
||||
extern int r_dlightframecount;
|
||||
extern qboolean r_fov_greater_than_90;
|
||||
|
||||
|
||||
extern cvar_t *sw_aliasstats;
|
||||
extern cvar_t *sw_clearcolor;
|
||||
extern cvar_t *sw_drawflat;
|
||||
extern cvar_t *sw_draworder;
|
||||
extern cvar_t *sw_maxedges;
|
||||
extern cvar_t *sw_maxsurfs;
|
||||
extern cvar_t *sw_mipcap;
|
||||
extern cvar_t *sw_mipscale;
|
||||
extern cvar_t *sw_mode;
|
||||
extern cvar_t *sw_reportsurfout;
|
||||
extern cvar_t *sw_reportedgeout;
|
||||
extern cvar_t *sw_stipplealpha;
|
||||
extern cvar_t *sw_surfcacheoverride;
|
||||
extern cvar_t *sw_waterwarp;
|
||||
|
||||
extern vec3_t modelorg;
|
||||
extern vec3_t r_origin;
|
||||
extern mplane_t screenedge[4];
|
||||
|
||||
|
||||
extern clipplane_t view_clipplanes[4];
|
||||
extern int *pfrustum_indexes[4];
|
||||
|
||||
extern vec3_t vup, base_vup;
|
||||
extern vec3_t vpn, base_vpn;
|
||||
extern vec3_t vright, base_vright;
|
||||
|
||||
extern cvar_t *r_fullbright;
|
||||
|
||||
#define CACHESPOT(surf) ((surfcache_t**)surf->info->reserved)
|
||||
extern int r_visframecount;
|
||||
extern mvertex_t *r_pcurrentvertbase;
|
||||
extern int r_maxvalidedgeoffset;
|
||||
extern int r_currentkey;
|
||||
extern int r_currentbkey;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// engine callbacks
|
||||
//
|
||||
|
421
r_misc.c
Normal file
421
r_misc.c
Normal file
@ -0,0 +1,421 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 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_misc.c
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
#define NUM_MIPS 4
|
||||
|
||||
cvar_t *sw_mipcap;
|
||||
cvar_t *sw_mipscale;
|
||||
|
||||
surfcache_t *d_initial_rover;
|
||||
qboolean d_roverwrapped;
|
||||
int d_minmip;
|
||||
float d_scalemip[NUM_MIPS-1];
|
||||
|
||||
static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8};
|
||||
|
||||
extern int d_aflatcolor;
|
||||
|
||||
int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle;
|
||||
|
||||
int d_pix_min, d_pix_max, d_pix_shift;
|
||||
|
||||
int d_scantable[MAXHEIGHT];
|
||||
short *zspantable[MAXHEIGHT];
|
||||
|
||||
/*
|
||||
================
|
||||
D_Patch
|
||||
================
|
||||
*/
|
||||
void D_Patch (void)
|
||||
{
|
||||
#if id386
|
||||
extern void D_Aff8Patch( void );
|
||||
static qboolean protectset8 = false;
|
||||
extern void D_PolysetAff8Start( void );
|
||||
|
||||
if (!protectset8)
|
||||
{
|
||||
Sys_MakeCodeWriteable ((int)D_PolysetAff8Start,
|
||||
(int)D_Aff8Patch - (int)D_PolysetAff8Start);
|
||||
Sys_MakeCodeWriteable ((long)R_Surf8Start,
|
||||
(long)R_Surf8End - (long)R_Surf8Start);
|
||||
protectset8 = true;
|
||||
}
|
||||
colormap = vid.colormap;
|
||||
|
||||
R_Surf8Patch ();
|
||||
D_Aff8Patch();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
================
|
||||
D_ViewChanged
|
||||
================
|
||||
*/
|
||||
unsigned char *alias_colormap;
|
||||
|
||||
void D_ViewChanged (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
scale_for_mip = xscale;
|
||||
if (yscale > xscale)
|
||||
scale_for_mip = yscale;
|
||||
|
||||
d_zrowbytes = vid.width * 2;
|
||||
d_zwidth = vid.width;
|
||||
|
||||
d_pix_min = gpGlobals->width / 320;
|
||||
if (d_pix_min < 1)
|
||||
d_pix_min = 1;
|
||||
|
||||
d_pix_max = (int)((float)gpGlobals->height / (320.0 / 4.0) + 0.5);
|
||||
d_pix_shift = 8 - (int)((float)gpGlobals->height / 320.0 + 0.5);
|
||||
if (d_pix_max < 1)
|
||||
d_pix_max = 1;
|
||||
|
||||
d_vrectx = 0;//r_refdef.vrect.x;
|
||||
d_vrecty = 0;//r_refdef.vrect.y;
|
||||
d_vrectright_particle = gpGlobals->width - d_pix_max;
|
||||
d_vrectbottom_particle =
|
||||
gpGlobals->height - d_pix_max;
|
||||
|
||||
for (i=0 ; i<vid.height; i++)
|
||||
{
|
||||
d_scantable[i] = i*r_screenwidth;
|
||||
zspantable[i] = d_pzbuffer + i*d_zwidth;
|
||||
}
|
||||
|
||||
/*
|
||||
** clear Z-buffer and color-buffers if we're doing the gallery
|
||||
*/
|
||||
if ( !RI.drawWorld )
|
||||
{
|
||||
memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) );
|
||||
// newrefdef
|
||||
Draw_Fill( 0, 0, gpGlobals->width, gpGlobals->height,( int ) sw_clearcolor->value & 0xff );
|
||||
}
|
||||
|
||||
alias_colormap = vid.colormap;
|
||||
|
||||
D_Patch ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
R_TransformFrustum
|
||||
===================
|
||||
*/
|
||||
void R_TransformFrustum (void)
|
||||
{
|
||||
int i;
|
||||
vec3_t v, v2;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
v[0] = screenedge[i].normal[2];
|
||||
v[1] = -screenedge[i].normal[0];
|
||||
v[2] = screenedge[i].normal[1];
|
||||
|
||||
v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0];
|
||||
v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1];
|
||||
v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2];
|
||||
|
||||
VectorCopy (v2, view_clipplanes[i].normal);
|
||||
|
||||
view_clipplanes[i].dist = DotProduct (modelorg, v2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
TransformVector
|
||||
================
|
||||
*/
|
||||
void TransformVector (vec3_t in, vec3_t out)
|
||||
{
|
||||
out[0] = DotProduct(in,vright);
|
||||
out[1] = DotProduct(in,vup);
|
||||
out[2] = DotProduct(in,vpn);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_TransformPlane
|
||||
================
|
||||
*/
|
||||
void R_TransformPlane (mplane_t *p, float *normal, float *dist)
|
||||
{
|
||||
float d;
|
||||
|
||||
d = DotProduct (RI.vieworg, p->normal);
|
||||
*dist = p->dist - d;
|
||||
// TODO: when we have rotating entities, this will need to use the view matrix
|
||||
TransformVector (p->normal, normal);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetUpFrustumIndexes
|
||||
===============
|
||||
*/
|
||||
void R_SetUpFrustumIndexes (void)
|
||||
{
|
||||
int i, j, *pindex;
|
||||
|
||||
pindex = r_frustum_indexes;
|
||||
|
||||
for (i=0 ; i<4 ; i++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
if (view_clipplanes[i].normal[j] < 0)
|
||||
{
|
||||
pindex[j] = j;
|
||||
pindex[j+3] = j+3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pindex[j] = j+3;
|
||||
pindex[j+3] = j;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: do just once at start
|
||||
pfrustum_indexes[i] = pindex;
|
||||
pindex += 6;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ViewChanged
|
||||
|
||||
Called every time the vid structure or r_refdef changes.
|
||||
Guaranteed to be called before the first refresh
|
||||
===============
|
||||
*/
|
||||
void R_ViewChanged (vrect_t *vr)
|
||||
{
|
||||
int i;
|
||||
#if 0
|
||||
r_refdef.vrect = *vr;
|
||||
|
||||
r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);;
|
||||
verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI);
|
||||
|
||||
r_refdef.fvrectx = (float)r_refdef.vrect.x;
|
||||
r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5;
|
||||
r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1;
|
||||
r_refdef.fvrecty = (float)r_refdef.vrect.y;
|
||||
r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5;
|
||||
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
|
||||
r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1;
|
||||
r_refdef.fvrectright = (float)r_refdef.vrectright;
|
||||
r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5;
|
||||
r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99;
|
||||
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
|
||||
r_refdef.fvrectbottom = (float)r_refdef.vrectbottom;
|
||||
r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5;
|
||||
|
||||
r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale);
|
||||
r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale);
|
||||
r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
|
||||
r_refdef.aliasvrect.width;
|
||||
r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
|
||||
r_refdef.aliasvrect.height;
|
||||
|
||||
xOrigin = r_refdef.xOrigin;
|
||||
yOrigin = r_refdef.yOrigin;
|
||||
|
||||
// values for perspective projection
|
||||
// if math were exact, the values would range from 0.5 to to range+0.5
|
||||
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
|
||||
// the polygon rasterization will never render in the first row or column
|
||||
// but will definately render in the [range] row and column, so adjust the
|
||||
// buffer origin to get an exact edge to edge fill
|
||||
xcenter = ((float)r_refdef.vrect.width * XCENTERING) +
|
||||
r_refdef.vrect.x - 0.5;
|
||||
aliasxcenter = xcenter * r_aliasuvscale;
|
||||
ycenter = ((float)r_refdef.vrect.height * YCENTERING) +
|
||||
r_refdef.vrect.y - 0.5;
|
||||
aliasycenter = ycenter * r_aliasuvscale;
|
||||
|
||||
xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
|
||||
aliasxscale = xscale * r_aliasuvscale;
|
||||
xscaleinv = 1.0 / xscale;
|
||||
|
||||
yscale = xscale;
|
||||
aliasyscale = yscale * r_aliasuvscale;
|
||||
yscaleinv = 1.0 / yscale;
|
||||
xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView;
|
||||
yscaleshrink = xscaleshrink;
|
||||
|
||||
// left side clip
|
||||
screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView);
|
||||
screenedge[0].normal[1] = 0;
|
||||
screenedge[0].normal[2] = 1;
|
||||
screenedge[0].type = PLANE_ANYZ;
|
||||
|
||||
// right side clip
|
||||
screenedge[1].normal[0] =
|
||||
1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView);
|
||||
screenedge[1].normal[1] = 0;
|
||||
screenedge[1].normal[2] = 1;
|
||||
screenedge[1].type = PLANE_ANYZ;
|
||||
|
||||
// top side clip
|
||||
screenedge[2].normal[0] = 0;
|
||||
screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView);
|
||||
screenedge[2].normal[2] = 1;
|
||||
screenedge[2].type = PLANE_ANYZ;
|
||||
|
||||
// bottom side clip
|
||||
screenedge[3].normal[0] = 0;
|
||||
screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView);
|
||||
screenedge[3].normal[2] = 1;
|
||||
screenedge[3].type = PLANE_ANYZ;
|
||||
#endif
|
||||
for (i=0 ; i<4 ; i++)
|
||||
VectorNormalize (screenedge[i].normal);
|
||||
|
||||
D_ViewChanged ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetupFrame
|
||||
===============
|
||||
*/
|
||||
void R_SetupFrameQ (void)
|
||||
{
|
||||
int i;
|
||||
vrect_t vrect;
|
||||
|
||||
if (r_fullbright->flags & FCVAR_CHANGED)
|
||||
{
|
||||
r_fullbright->flags &= ~FCVAR_CHANGED;
|
||||
D_FlushCaches (); // so all lighting changes
|
||||
}
|
||||
|
||||
r_framecount++;
|
||||
|
||||
|
||||
// build the transformation matrix for the given view angles
|
||||
VectorCopy (RI.vieworg, modelorg);
|
||||
VectorCopy (RI.vieworg, r_origin);
|
||||
|
||||
AngleVectors (RI.viewangles, vpn, vright, vup);
|
||||
|
||||
// current viewleaf
|
||||
if ( RI.drawWorld )
|
||||
{
|
||||
r_viewleaf = gEngfuncs.Mod_PointInLeaf (r_origin, WORLDMODEL->nodes);
|
||||
r_viewcluster = r_viewleaf->cluster;
|
||||
}
|
||||
|
||||
// if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
|
||||
// r_dowarp = true;
|
||||
// else
|
||||
r_dowarp = false;
|
||||
|
||||
if (r_dowarp)
|
||||
{ // warp into off screen buffer
|
||||
vrect.x = 0;
|
||||
vrect.y = 0;
|
||||
//vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH;
|
||||
//vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT;
|
||||
|
||||
d_viewbuffer = r_warpbuffer;
|
||||
r_screenwidth = WARP_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
vrect.x = 0;//r_newrefdef.x;
|
||||
vrect.y = 0;//r_newrefdef.y;
|
||||
vrect.width = gpGlobals->width;
|
||||
vrect.height = gpGlobals->height;
|
||||
|
||||
d_viewbuffer = (void *)vid.buffer;
|
||||
r_screenwidth = vid.rowbytes;
|
||||
}
|
||||
|
||||
R_ViewChanged (&vrect);
|
||||
|
||||
// start off with just the four screen edge clip planes
|
||||
R_TransformFrustum ();
|
||||
R_SetUpFrustumIndexes ();
|
||||
|
||||
// save base values
|
||||
VectorCopy (vpn, base_vpn);
|
||||
VectorCopy (vright, base_vright);
|
||||
VectorCopy (vup, base_vup);
|
||||
|
||||
// clear frame counts
|
||||
/* c_faceclip = 0;
|
||||
d_spanpixcount = 0;
|
||||
r_polycount = 0;
|
||||
r_drawnpolycount = 0;
|
||||
r_wholepolycount = 0;
|
||||
r_amodels_drawn = 0;
|
||||
r_outofsurfaces = 0;
|
||||
r_outofedges = 0;*/
|
||||
|
||||
// d_setup
|
||||
d_roverwrapped = false;
|
||||
d_initial_rover = sc_rover;
|
||||
|
||||
d_minmip = sw_mipcap->value;
|
||||
if (d_minmip > 3)
|
||||
d_minmip = 3;
|
||||
else if (d_minmip < 0)
|
||||
d_minmip = 0;
|
||||
|
||||
for (i=0 ; i<(NUM_MIPS-1) ; i++)
|
||||
d_scalemip[i] = basemip[i] * sw_mipscale->value;
|
||||
|
||||
//d_aflatcolor = 0;
|
||||
}
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
================
|
||||
R_SurfacePatch
|
||||
================
|
||||
*/
|
||||
/*void R_SurfacePatch (void)
|
||||
{
|
||||
// we only patch code on Intel
|
||||
}
|
||||
*/
|
||||
#endif // !id386
|
852
r_rast.c
Normal file
852
r_rast.c
Normal file
@ -0,0 +1,852 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 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_rast.c
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "r_local.h"
|
||||
|
||||
#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
|
||||
|
||||
|
||||
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];
|
||||
int blanktable[1280]; // PGM
|
||||
|
||||
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;
|
||||
int r_skyframe;
|
||||
|
||||
msurface_t *r_skyfaces;
|
||||
mplane_t r_skyplanes[6];
|
||||
mtexinfo_t r_skytexinfo[6];
|
||||
mvertex_t *r_skyverts;
|
||||
medge_t *r_skyedges;
|
||||
int *r_skysurfedges;
|
||||
|
||||
// I just copied this data from a box map...
|
||||
int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128};
|
||||
|
||||
int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11,
|
||||
12,-3,-11,-8, -12,-10,-5,-4};
|
||||
int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4};
|
||||
|
||||
int box_faces[6] = {0,0,2,2,2,0};
|
||||
|
||||
vec3_t box_vecs[6][2] = {
|
||||
{ {0,-1,0}, {-1,0,0} },
|
||||
{ {0,1,0}, {0,0,-1} },
|
||||
{ {0,-1,0}, {1,0,0} },
|
||||
{ {1,0,0}, {0,0,-1} },
|
||||
{ {0,-1,0}, {0,0,-1} },
|
||||
{ {-1,0,0}, {0,0,-1} }
|
||||
};
|
||||
|
||||
float box_verts[8][3] = {
|
||||
{-1,-1,-1},
|
||||
{-1,1,-1},
|
||||
{1,1,-1},
|
||||
{1,-1,-1},
|
||||
{-1,-1,1},
|
||||
{-1,1,1},
|
||||
{1,-1,1},
|
||||
{1,1,1}
|
||||
};
|
||||
|
||||
// down, west, up, north, east, south
|
||||
// {"rt", "bk", "lf", "ft", "up", "dn"};
|
||||
#if 0
|
||||
/*
|
||||
================
|
||||
R_InitSkyBox
|
||||
|
||||
================
|
||||
*/
|
||||
void R_InitSkyBox (void)
|
||||
{
|
||||
int i;
|
||||
extern model_t *loadmodel;
|
||||
|
||||
r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces;
|
||||
loadmodel->numsurfaces += 6;
|
||||
r_skyverts = loadmodel->vertexes + loadmodel->numvertexes;
|
||||
loadmodel->numvertexes += 8;
|
||||
r_skyedges = loadmodel->edges + loadmodel->numedges;
|
||||
loadmodel->numedges += 12;
|
||||
r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges;
|
||||
loadmodel->numsurfedges += 24;
|
||||
if (loadmodel->numsurfaces > MAX_MAP_FACES
|
||||
|| loadmodel->numvertexes > MAX_MAP_VERTS
|
||||
|| loadmodel->numedges > MAX_MAP_EDGES)
|
||||
ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow");
|
||||
|
||||
memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces));
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
r_skyplanes[i].normal[skybox_planes[i*2]] = 1;
|
||||
r_skyplanes[i].dist = skybox_planes[i*2+1];
|
||||
|
||||
VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]);
|
||||
VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]);
|
||||
|
||||
r_skyfaces[i].plane = &r_skyplanes[i];
|
||||
r_skyfaces[i].numedges = 4;
|
||||
r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX;
|
||||
r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4;
|
||||
r_skyfaces[i].texinfo = &r_skytexinfo[i];
|
||||
r_skyfaces[i].texturemins[0] = -128;
|
||||
r_skyfaces[i].texturemins[1] = -128;
|
||||
r_skyfaces[i].extents[0] = 256;
|
||||
r_skyfaces[i].extents[1] = 256;
|
||||
}
|
||||
|
||||
for (i=0 ; i<24 ; i++)
|
||||
if (box_surfedges[i] > 0)
|
||||
r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i];
|
||||
else
|
||||
r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]);
|
||||
|
||||
for(i=0 ; i<12 ; i++)
|
||||
{
|
||||
r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0];
|
||||
r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1];
|
||||
r_skyedges[i].cachededgeoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_EmitSkyBox
|
||||
================
|
||||
*/
|
||||
void R_EmitSkyBox (void)
|
||||
{
|
||||
int i, j;
|
||||
int oldkey;
|
||||
|
||||
if (insubmodel)
|
||||
return; // submodels should never have skies
|
||||
if (r_skyframe == r_framecount)
|
||||
return; // already set this frame
|
||||
|
||||
r_skyframe = r_framecount;
|
||||
|
||||
// set the eight fake vertexes
|
||||
for (i=0 ; i<8 ; i++)
|
||||
for (j=0 ; j<3 ; j++)
|
||||
r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128;
|
||||
|
||||
// set the six fake planes
|
||||
for (i=0 ; i<6 ; i++)
|
||||
if (skybox_planes[i*2+1] > 0)
|
||||
r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128;
|
||||
else
|
||||
r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128;
|
||||
|
||||
// fix texture offseets
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]);
|
||||
r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]);
|
||||
}
|
||||
|
||||
// emit the six faces
|
||||
oldkey = r_currentkey;
|
||||
r_currentkey = 0x7ffffff0;
|
||||
for (i=0 ; i<6 ; i++)
|
||||
{
|
||||
R_RenderFace (r_skyfaces + i, 15);
|
||||
}
|
||||
r_currentkey = oldkey; // bsp sorting order
|
||||
}
|
||||
|
||||
#endif
|
||||
#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 < 0)
|
||||
u0 = 0;
|
||||
if (u0 > gpGlobals->width)
|
||||
u0 = gpGlobals->width;
|
||||
|
||||
scale = yscale * lzi0;
|
||||
v0 = (ycenter - scale*transformed[1]);
|
||||
if (v0 < 0)
|
||||
v0 = 0;
|
||||
if (v0 > gpGlobals->height)
|
||||
v0 = gpGlobals->height;
|
||||
|
||||
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 < 0)
|
||||
r_u1 = 0;
|
||||
if (r_u1 > gpGlobals->width)
|
||||
r_u1 = gpGlobals->width;
|
||||
|
||||
scale = yscale * r_lzi1;
|
||||
r_v1 = (ycenter - scale*transformed[1]);
|
||||
if (r_v1 < 0)
|
||||
r_v1 = 0;
|
||||
if (r_v1 > gpGlobals->height)
|
||||
r_v1 = gpGlobals->height;
|
||||
|
||||
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;
|
||||
|
||||
// translucent surfaces are not drawn by the edge renderer
|
||||
/* if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
|
||||
{
|
||||
fa->nextalphasurface = r_alpha_surfaces;
|
||||
r_alpha_surfaces = fa;
|
||||
return;
|
||||
}*/
|
||||
|
||||
// sky surfaces encountered in the world will cause the
|
||||
// environment box surfaces to be emited
|
||||
/* if ( fa->texinfo->flags & SURF_SKY )
|
||||
{
|
||||
R_EmitSkyBox ();
|
||||
return;
|
||||
}*/
|
||||
|
||||
// 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 = RI.currentmodel->edges;
|
||||
r_lastvertvalid = false;
|
||||
|
||||
for (i=0 ; i<fa->numedges ; i++)
|
||||
{
|
||||
lindex = RI.currentmodel->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->msurf = fa;
|
||||
surface_p->nearzi = r_nearzi;
|
||||
surface_p->flags = fa->flags;
|
||||
//surface_p->insubmodel = insubmodel;
|
||||
surface_p->spanstate = 0;
|
||||
surface_p->entity = RI.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;
|
||||
|
||||
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;
|
||||
|
||||
/*if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
|
||||
{
|
||||
psurf->nextalphasurface = r_alpha_surfaces;
|
||||
r_alpha_surfaces = psurf;
|
||||
return;
|
||||
}*/
|
||||
|
||||
// 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->msurf = psurf;
|
||||
surface_p->nearzi = r_nearzi;
|
||||
surface_p->flags = psurf->flags;
|
||||
surface_p->insubmodel = true;
|
||||
surface_p->spanstate = 0;
|
||||
surface_p->entity = RI.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;
|
||||
|
||||
surface_p++;
|
||||
}
|
||||
|
593
r_scan.c
Normal file
593
r_scan.c
Normal file
@ -0,0 +1,593 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 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 "r_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)
|
||||
{
|
||||
#if 0
|
||||
int w, h;
|
||||
int u,v, u2, v2;
|
||||
byte *dest;
|
||||
int *turb;
|
||||
int *col;
|
||||
byte **row;
|
||||
|
||||
static int cached_width, cached_height;
|
||||
static byte *rowptr[1200+AMP2*2];
|
||||
static int column[1600+AMP2*2];
|
||||
|
||||
//
|
||||
// these are constant over resolutions, and can be saved
|
||||
//
|
||||
w = r_newrefdef.width;
|
||||
h = r_newrefdef.height;
|
||||
if (w != cached_width || h != cached_height)
|
||||
{
|
||||
cached_width = w;
|
||||
cached_height = h;
|
||||
for (v=0 ; v<h+AMP2*2 ; v++)
|
||||
{
|
||||
v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
|
||||
rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
|
||||
}
|
||||
|
||||
for (u=0 ; u<w+AMP2*2 ; u++)
|
||||
{
|
||||
u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
|
||||
column[u] = u2;
|
||||
}
|
||||
}
|
||||
|
||||
turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
|
||||
dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
|
||||
|
||||
for (v=0 ; v<h ; v++, dest += vid.rowbytes)
|
||||
{
|
||||
col = &column[turb[v]];
|
||||
row = &rowptr[v];
|
||||
for (u=0 ; u<w ; 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]];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#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)(gpGlobals->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 +
|
||||
(r_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);
|
||||
}
|
||||
|
||||
//====================
|
||||
//PGM
|
||||
/*
|
||||
=============
|
||||
NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
|
||||
but the turbulence is automatically 0.
|
||||
=============
|
||||
*/
|
||||
void NonTurbulent8 (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)(r_newrefdef.time*SPEED)&(CYCLE-1));
|
||||
r_turb_turb = blanktable;
|
||||
|
||||
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 +
|
||||
(r_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);
|
||||
}
|
||||
//PGM
|
||||
//====================
|
||||
|
||||
|
||||
#if !id386
|
||||
|
||||
/*
|
||||
=============
|
||||
D_DrawSpans16
|
||||
|
||||
FIXME: actually make this subdivide by 16 instead of 8!!!
|
||||
=============
|
||||
*/
|
||||
void D_DrawSpans16 (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 +
|
||||
(r_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;
|
||||
float 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
|
||||
|
753
r_surf.c
Normal file
753
r_surf.c
Normal file
@ -0,0 +1,753 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 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 "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
|
||||
};
|
||||
|
||||
void R_BuildLightMap (void);
|
||||
extern unsigned blocklights[1024]; // allow some very large lightmaps
|
||||
|
||||
float surfscale;
|
||||
qboolean r_cache_thrash; // set if surface cache is thrashing
|
||||
|
||||
int sc_size;
|
||||
surfcache_t *sc_rover, *sc_base;
|
||||
|
||||
static int rtable[MOD_FRAMES][MOD_FRAMES];
|
||||
|
||||
void R_InitRandomTable( void )
|
||||
{
|
||||
int tu, tv;
|
||||
|
||||
// make random predictable
|
||||
gEngfuncs.COM_SetRandomSeed( 255 );
|
||||
|
||||
for( tu = 0; tu < MOD_FRAMES; tu++ )
|
||||
{
|
||||
for( tv = 0; tv < MOD_FRAMES; tv++ )
|
||||
{
|
||||
rtable[tu][tv] = gEngfuncs.COM_RandomLong( 0, 0x7FFF );
|
||||
}
|
||||
}
|
||||
|
||||
gEngfuncs.COM_SetRandomSeed( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TextureAnim
|
||||
|
||||
Returns the proper texture for a given time and base texture, do not process random tiling
|
||||
===============
|
||||
*/
|
||||
texture_t *R_TextureAnim( texture_t *b )
|
||||
{
|
||||
texture_t *base = b;
|
||||
int count, reletive;
|
||||
|
||||
if( RI.currententity->curstate.frame )
|
||||
{
|
||||
if( base->alternate_anims )
|
||||
base = base->alternate_anims;
|
||||
}
|
||||
|
||||
if( !base->anim_total )
|
||||
return base;
|
||||
if( base->name[0] == '-' )
|
||||
{
|
||||
return b; // already tiled
|
||||
}
|
||||
else
|
||||
{
|
||||
int speed;
|
||||
|
||||
// Quake1 textures uses 10 frames per second
|
||||
if( FBitSet( R_GetTexture( base->gl_texturenum )->flags, TF_QUAKEPAL ))
|
||||
speed = 10;
|
||||
else speed = 20;
|
||||
|
||||
reletive = (int)(gpGlobals->time * speed) % base->anim_total;
|
||||
}
|
||||
|
||||
|
||||
count = 0;
|
||||
|
||||
while( base->anim_min > reletive || base->anim_max <= reletive )
|
||||
{
|
||||
base = base->anim_next;
|
||||
|
||||
if( !base || ++count > MOD_FRAMES )
|
||||
return b;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TextureAnimation
|
||||
|
||||
Returns the proper texture for a given time and surface
|
||||
===============
|
||||
*/
|
||||
texture_t *R_TextureAnimation( msurface_t *s )
|
||||
{
|
||||
texture_t *base = s->texinfo->texture;
|
||||
int count, reletive;
|
||||
|
||||
if( RI.currententity && RI.currententity->curstate.frame )
|
||||
{
|
||||
if( base->alternate_anims )
|
||||
base = base->alternate_anims;
|
||||
}
|
||||
|
||||
if( !base->anim_total )
|
||||
return base;
|
||||
|
||||
if( base->name[0] == '-' )
|
||||
{
|
||||
int tx = (int)((s->texturemins[0] + (base->width << 16)) / base->width) % MOD_FRAMES;
|
||||
int ty = (int)((s->texturemins[1] + (base->height << 16)) / base->height) % MOD_FRAMES;
|
||||
|
||||
reletive = rtable[tx][ty] % base->anim_total;
|
||||
}
|
||||
else
|
||||
{
|
||||
int speed;
|
||||
|
||||
// Quake1 textures uses 10 frames per second
|
||||
if( FBitSet( R_GetTexture( base->gl_texturenum )->flags, TF_QUAKEPAL ))
|
||||
speed = 10;
|
||||
else speed = 20;
|
||||
|
||||
reletive = (int)(gpGlobals->time * speed) % base->anim_total;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
while( base->anim_min > reletive || base->anim_max <= reletive )
|
||||
{
|
||||
base = base->anim_next;
|
||||
|
||||
if( !base || ++count > MOD_FRAMES )
|
||||
return s->texinfo->texture;
|
||||
}
|
||||
|
||||
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);
|
||||
image_t *mt;
|
||||
|
||||
surfrowbytes = r_drawsurf.rowbytes;
|
||||
|
||||
mt = r_drawsurf.image;
|
||||
|
||||
r_source = mt->pixels[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;
|
||||
|
||||
//==============================
|
||||
|
||||
pblockdrawer = surfmiptable[r_drawsurf.surfmip];
|
||||
// TODO: only needs to be set when there is a display settings change
|
||||
horzblockstep = blocksize;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_InitCaches
|
||||
|
||||
================
|
||||
*/
|
||||
void R_InitCaches (void)
|
||||
{
|
||||
int size;
|
||||
int pix;
|
||||
|
||||
// calculate size to allocate
|
||||
if (sw_surfcacheoverride->value)
|
||||
{
|
||||
size = sw_surfcacheoverride->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = SURFCACHE_SIZE_AT_320X240;
|
||||
|
||||
pix = vid.width*vid.height;
|
||||
if (pix > 64000)
|
||||
size += (pix-64000)*3;
|
||||
}
|
||||
|
||||
// round up to page size
|
||||
size = (size + 8191) & ~8191;
|
||||
|
||||
gEngfuncs.Con_Printf ("%ik surface cache\n", size/1024);
|
||||
|
||||
sc_size = size;
|
||||
sc_base = (surfcache_t *)malloc(size);
|
||||
sc_rover = sc_base;
|
||||
|
||||
sc_base->next = NULL;
|
||||
sc_base->owner = NULL;
|
||||
sc_base->size = sc_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
D_FlushCaches
|
||||
==================
|
||||
*/
|
||||
void D_FlushCaches (void)
|
||||
{
|
||||
surfcache_t *c;
|
||||
|
||||
if (!sc_base)
|
||||
return;
|
||||
|
||||
for (c = sc_base ; c ; c = c->next)
|
||||
{
|
||||
if (c->owner)
|
||||
*c->owner = NULL;
|
||||
}
|
||||
|
||||
sc_rover = sc_base;
|
||||
sc_base->next = NULL;
|
||||
sc_base->owner = NULL;
|
||||
sc_base->size = sc_size;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
D_SCAlloc
|
||||
=================
|
||||
*/
|
||||
surfcache_t *D_SCAlloc (int width, int size)
|
||||
{
|
||||
surfcache_t *new;
|
||||
qboolean wrapped_this_time;
|
||||
|
||||
if ((width < 0) || (width > 256))
|
||||
gEngfuncs.Host_Error ("D_SCAlloc: bad cache width %d\n", width);
|
||||
|
||||
if ((size <= 0) || (size > 0x10000))
|
||||
gEngfuncs.Host_Error ("D_SCAlloc: bad cache size %d\n", size);
|
||||
|
||||
size = (int)&((surfcache_t *)0)->data[size];
|
||||
size = (size + 3) & ~3;
|
||||
if (size > sc_size)
|
||||
gEngfuncs.Host_Error ("D_SCAlloc: %i > cache size of %i",size, sc_size);
|
||||
|
||||
// if there is not size bytes after the rover, reset to the start
|
||||
wrapped_this_time = false;
|
||||
|
||||
if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
|
||||
{
|
||||
if (sc_rover)
|
||||
{
|
||||
wrapped_this_time = true;
|
||||
}
|
||||
sc_rover = sc_base;
|
||||
}
|
||||
|
||||
// colect and free surfcache_t blocks until the rover block is large enough
|
||||
new = sc_rover;
|
||||
if (sc_rover->owner)
|
||||
*sc_rover->owner = NULL;
|
||||
|
||||
while (new->size < size)
|
||||
{
|
||||
// free another
|
||||
sc_rover = sc_rover->next;
|
||||
if (!sc_rover)
|
||||
gEngfuncs.Host_Error ("D_SCAlloc: hit the end of memory");
|
||||
if (sc_rover->owner)
|
||||
*sc_rover->owner = NULL;
|
||||
|
||||
new->size += sc_rover->size;
|
||||
new->next = sc_rover->next;
|
||||
}
|
||||
|
||||
// create a fragment out of any leftovers
|
||||
if (new->size - size > 256)
|
||||
{
|
||||
sc_rover = (surfcache_t *)( (byte *)new + size);
|
||||
sc_rover->size = new->size - size;
|
||||
sc_rover->next = new->next;
|
||||
sc_rover->width = 0;
|
||||
sc_rover->owner = NULL;
|
||||
new->next = sc_rover;
|
||||
new->size = size;
|
||||
}
|
||||
else
|
||||
sc_rover = new->next;
|
||||
|
||||
new->width = width;
|
||||
// DEBUG
|
||||
if (width > 0)
|
||||
new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
|
||||
|
||||
new->owner = NULL; // should be set properly after return
|
||||
|
||||
if (d_roverwrapped)
|
||||
{
|
||||
if (wrapped_this_time || (sc_rover >= d_initial_rover))
|
||||
r_cache_thrash = true;
|
||||
}
|
||||
else if (wrapped_this_time)
|
||||
{
|
||||
d_roverwrapped = true;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
D_SCDump
|
||||
=================
|
||||
*/
|
||||
void D_SCDump (void)
|
||||
{
|
||||
surfcache_t *test;
|
||||
|
||||
for (test = sc_base ; test ; test = test->next)
|
||||
{
|
||||
if (test == sc_rover)
|
||||
gEngfuncs.Con_Printf ("ROVER:\n");
|
||||
gEngfuncs.Con_Printf ("%p : %i bytes %i width\n",test, test->size, test->width);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// if the num is not a power of 2, assume it will not repeat
|
||||
|
||||
int MaskForNum (int num)
|
||||
{
|
||||
if (num==128)
|
||||
return 127;
|
||||
if (num==64)
|
||||
return 63;
|
||||
if (num==32)
|
||||
return 31;
|
||||
if (num==16)
|
||||
return 15;
|
||||
return 255;
|
||||
}
|
||||
|
||||
int D_log2 (int num)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
|
||||
while (num>>=1)
|
||||
c++;
|
||||
return c;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
D_CacheSurface
|
||||
================
|
||||
*/
|
||||
surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
|
||||
{
|
||||
surfcache_t *cache;
|
||||
|
||||
//
|
||||
// if the surface is animating or flashing, flush the cache
|
||||
//
|
||||
r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface->texinfo->texture->gl_texturenum));
|
||||
|
||||
/// todo: port this
|
||||
//r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128;
|
||||
//r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128;
|
||||
//r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128;
|
||||
//r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128;
|
||||
|
||||
//
|
||||
// see if the cache holds apropriate data
|
||||
//
|
||||
cache = CACHESPOT(surface)[miplevel];
|
||||
|
||||
|
||||
if (cache && !cache->dlight && surface->dlightframe != r_framecount
|
||||
&& cache->image == r_drawsurf.image
|
||||
&& cache->lightadj[0] == r_drawsurf.lightadj[0]
|
||||
&& cache->lightadj[1] == r_drawsurf.lightadj[1]
|
||||
&& cache->lightadj[2] == r_drawsurf.lightadj[2]
|
||||
&& cache->lightadj[3] == r_drawsurf.lightadj[3] )
|
||||
return cache;
|
||||
|
||||
//
|
||||
// determine shape of surface
|
||||
//
|
||||
surfscale = 1.0 / (1<<miplevel);
|
||||
r_drawsurf.surfmip = miplevel;
|
||||
r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
|
||||
r_drawsurf.rowbytes = r_drawsurf.surfwidth;
|
||||
r_drawsurf.surfheight = surface->extents[1] >> miplevel;
|
||||
|
||||
//
|
||||
// allocate memory if needed
|
||||
//
|
||||
if (!cache) // if a texture just animated, don't reallocate it
|
||||
{
|
||||
cache = D_SCAlloc (r_drawsurf.surfwidth,
|
||||
r_drawsurf.surfwidth * r_drawsurf.surfheight);
|
||||
CACHESPOT(surface)[miplevel] = cache;
|
||||
cache->owner = &CACHESPOT(surface)[miplevel];
|
||||
cache->mipscale = surfscale;
|
||||
}
|
||||
|
||||
if (surface->dlightframe == r_framecount)
|
||||
cache->dlight = 1;
|
||||
else
|
||||
cache->dlight = 0;
|
||||
|
||||
r_drawsurf.surfdat = (pixel_t *)cache->data;
|
||||
|
||||
cache->image = r_drawsurf.image;
|
||||
cache->lightadj[0] = r_drawsurf.lightadj[0];
|
||||
cache->lightadj[1] = r_drawsurf.lightadj[1];
|
||||
cache->lightadj[2] = r_drawsurf.lightadj[2];
|
||||
cache->lightadj[3] = r_drawsurf.lightadj[3];
|
||||
|
||||
//
|
||||
// draw and light the surface texture
|
||||
//
|
||||
r_drawsurf.surf = surface;
|
||||
|
||||
c_surf++;
|
||||
|
||||
// calculate the lightings
|
||||
//R_BuildLightMap ();
|
||||
|
||||
// rasterize the surface into the cache
|
||||
R_DrawSurface ();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user