Add 'ref_soft/' from commit '9045657352c7dfd3622cdf2b69462ca33f4262ee'

git-subtree-dir: ref_soft
git-subtree-mainline: 89ca0dec5e
git-subtree-split: 9045657352
This commit is contained in:
Alibek Omarov 2020-03-29 17:45:00 +03:00
commit 7429a6bc8a
26 changed files with 26107 additions and 0 deletions

1077
ref_soft/adivtab.h Normal file

File diff suppressed because it is too large Load Diff

323
ref_soft/r_aclip.c Normal file
View File

@ -0,0 +1,323 @@
/*
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_aclip.c: clip routines for drawing Alias models directly to the screen
#include "r_local.h"
static finalvert_t fv[2][8];
void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out);
/*
================
R_Alias_clip_z
pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
================
*/
void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) /
(pfv1->xyz[2] - pfv0->xyz[2]);
out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale;
out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale;
out->xyz[2] = ALIAS_Z_CLIP_PLANE;
out->s = pfv0->s + (pfv1->s - pfv0->s) * scale;
out->t = pfv0->t + (pfv1->t - pfv0->t) * scale;
out->l = pfv0->l + (pfv1->l - pfv0->l) * scale;
R_AliasProjectAndClipTestFinalVert (out);
}
#if !id386
void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v )
{
scale = (float)(RI.aliasvrect.x - pfv0->u) /
(pfv1->u - pfv0->u);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f;
}
else
{
scale = (float)(RI.aliasvrect.x - pfv1->u) /
(pfv0->u - pfv1->u);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f;
}
}
void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if ( pfv0->v >= pfv1->v )
{
scale = (float)(RI.aliasvrectright - pfv0->u ) /
(pfv1->u - pfv0->u );
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f;
}
else
{
scale = (float)(RI.aliasvrectright - pfv1->u ) /
(pfv0->u - pfv1->u );
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f;
}
}
void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v)
{
scale = (float)(RI.aliasvrect.y - pfv0->v) /
(pfv1->v - pfv0->v);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f;
}
else
{
scale = (float)(RI.aliasvrect.y - pfv1->v) /
(pfv0->v - pfv1->v);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f;
}
}
void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1,
finalvert_t *out)
{
float scale;
if (pfv0->v >= pfv1->v)
{
scale = (float)(RI.aliasvrectbottom - pfv0->v) /
(pfv1->v - pfv0->v);
out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f;
out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f;
out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f;
out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f;
out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f;
out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f;
}
else
{
scale = (float)(RI.aliasvrectbottom - pfv1->v) /
(pfv0->v - pfv1->v);
out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f;
out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f;
out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f;
out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f;
out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f;
out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f;
}
}
#endif
int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count,
void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) )
{
int i,j,k;
int flags, oldflags;
j = count-1;
k = 0;
for (i=0 ; i<count ; j = i, i++)
{
oldflags = in[j].flags & flag;
flags = in[i].flags & flag;
if (flags && oldflags)
continue;
if (oldflags ^ flags)
{
clip (&in[j], &in[i], &out[k]);
out[k].flags = 0;
if (out[k].u < RI.aliasvrect.x)
out[k].flags |= ALIAS_LEFT_CLIP;
if (out[k].v < RI.aliasvrect.y)
out[k].flags |= ALIAS_TOP_CLIP;
if (out[k].u > RI.aliasvrectright)
out[k].flags |= ALIAS_RIGHT_CLIP;
if (out[k].v > RI.aliasvrectbottom)
out[k].flags |= ALIAS_BOTTOM_CLIP;
k++;
}
if (!flags)
{
out[k] = in[i];
k++;
}
}
return k;
}
/*
================
R_AliasClipTriangle
================
*/
void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2)
{
int i, k, pingpong;
unsigned clipflags;
// copy vertexes and fix seam texture coordinates
fv[0][0] = *index0;
fv[0][1] = *index1;
fv[0][2] = *index2;
// clip
clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags;
if (clipflags & ALIAS_Z_CLIP)
{
k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z);
if (k == 0)
return;
pingpong = 1;
clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags;
}
else
{
pingpong = 0;
k = 3;
}
if (clipflags & ALIAS_LEFT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_RIGHT_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_BOTTOM_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
if (k == 0)
return;
pingpong ^= 1;
}
if (clipflags & ALIAS_TOP_CLIP)
{
k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1],
ALIAS_TOP_CLIP, k, R_Alias_clip_top);
if (k == 0)
return;
pingpong ^= 1;
}
for (i=0 ; i<k ; i++)
{
if (fv[pingpong][i].u < RI.aliasvrect.x)
fv[pingpong][i].u = RI.aliasvrect.x;
else if (fv[pingpong][i].u > RI.aliasvrectright)
fv[pingpong][i].u = RI.aliasvrectright;
if (fv[pingpong][i].v < RI.aliasvrect.y)
fv[pingpong][i].v = RI.aliasvrect.y;
else if (fv[pingpong][i].v > RI.aliasvrectbottom)
fv[pingpong][i].v = RI.aliasvrectbottom;
fv[pingpong][i].flags = 0;
}
// draw triangles
for (i=1 ; i<k-1 ; i++)
{
aliastriangleparms.a = &fv[pingpong][0];
aliastriangleparms.b = &fv[pingpong][i];
aliastriangleparms.c = &fv[pingpong][i+1];
R_DrawTriangle();
}
}

1313
ref_soft/r_beams.c Normal file

File diff suppressed because it is too large Load Diff

965
ref_soft/r_bsp.c Normal file
View File

@ -0,0 +1,965 @@
/*
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;
// 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 1000 // 12K
#define MAX_BMODEL_EDGES 2000 // 24K
static mvertex_t *pbverts;
static bedge_t *pbedges;
static int numbverts, numbedges;
static mvertex_t *pfrontenter, *pfrontexit;
static qboolean makeclippededge;
/*
================
R_ConcatRotations
================
*/
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
}
//===========================================================================
/*
================
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_F * 2 / 360.0f;
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_F * 2 / 360.0f;
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_F*2 / 360.0f;
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 (tr.modelorg);
R_EntityRotate (RI.vforward);
R_EntityRotate (RI.vright);
R_EntityRotate (RI.vup);
R_TransformFrustum ();
}
#if 0
/*
================
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);
}
}
}
}
}
#else
/*
================
R_RecursiveClipBPoly
================
*/
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;
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 == tr.visframecount)
{
if (pn->contents < 0)
{
if (pn->contents != CONTENTS_SOLID)
{
//r_currentbkey = ((mleaf_t *)pn)->cluster;
r_currentbkey = LEAF_KEY (((mleaf_t *)pn));
R_RenderBmodelFace (psideedges[i], psurf);
}
}
else
{
R_RecursiveClipBPoly (psideedges[i], pnode->children[i],
psurf);
}
}
}
}
}
#endif
#if 0
/*
================
R_DrawSolidClippedSubmodelPolygons
================
*/
void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel)
{
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)))
{
// 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;
if (psurf->numedges > 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
R_RecursiveClipBPoly (pbedge, RI.currententity->topnode, psurf);
}
else
{
gEngfuncs.Host_Error ("no edges in bmodel");
}
}
}
}
/*
================
R_DrawSubmodelPolygons
================
*/
void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
{
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 *)RI.currententity->topnode)->cluster;
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (psurf, clipflags);
}
}
}
#else
/*
================
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++)
{
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
{
if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES ))
continue;
if( r_entorigin[2] + pmodel->mins[2] + 1.0f >= psurf->plane->dist )
continue;
}
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (tr.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++)
{
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
{
if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES ))
continue;
if( r_entorigin[2] + pmodel->mins[2] + 1.0f >= psurf->plane->dist )
continue;
}
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (tr.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 = LEAF_KEY(((mleaf_t *)topnode));
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (psurf, clipflags);
}
}
}
#endif
int c_drawnode;
#if XASH_LOW_MEMORY
unsigned short r_leafkeys[MAX_MAP_LEAFS];
#else
int r_leafkeys[MAX_MAP_LEAFS];
#endif
/*
================
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 != tr.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 = qfrustum.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, qfrustum.view_clipplanes[i].normal);
d -= qfrustum.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, qfrustum.view_clipplanes[i].normal);
d -= qfrustum.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 = tr.framecount;
mark++;
} while (--c);
}
// deal with model fragments in this leaf
if (pleaf->efrags)
{
gEngfuncs.R_StoreEfrags(&pleaf->efrags,tr.realframecount);
}
// pleaf->cluster
LEAF_KEY(pleaf) = 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 = tr.modelorg[0] - plane->dist;
break;
case PLANE_Y:
dot = tr.modelorg[1] - plane->dist;
break;
case PLANE_Z:
dot = tr.modelorg[2] - plane->dist;
break;
default:
dot = DotProduct (tr.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 == tr.framecount))
{
R_RenderFace (surf, clipflags);
}
surf++;
} while (--c);
}
else if (dot > BACKFACE_EPSILON)
{
do
{
if (!(surf->flags & SURF_PLANEBACK) &&
(surf->visframe == tr.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 (RI.vieworg, tr.modelorg);
RI.currentmodel = WORLDMODEL;
r_pcurrentvertbase = RI.currentmodel->vertexes;
R_RecursiveWorldNode (RI.currentmodel->nodes, 15);
}

600
ref_soft/r_context.c Normal file
View File

@ -0,0 +1,600 @@
/*
vid_sdl.c - SDL vid component
Copyright (C) 2018 a1batross
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"
ref_api_t gEngfuncs;
ref_globals_t *gpGlobals;
ref_instance_t RI;
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 GAME_EXPORT R_ClearScreen( void )
{
}
static qboolean GAME_EXPORT IsNormalPass( void )
{
return RP_NORMALPASS();
}
static void GAME_EXPORT R_IncrementSpeedsCounter( int type )
{
switch( type )
{
case RS_ACTIVE_TENTS:
r_stats.c_active_tents_count++;
break;
default:
gEngfuncs.Host_Error( "R_IncrementSpeedsCounter: unsupported type %d\n", type );
}
}
static const byte * GAME_EXPORT R_GetTextureOriginalBuffer( unsigned int idx )
{
/*gl_texture_t *glt = R_GetTexture( idx );
if( !glt || !glt->original || !glt->original->buffer )
return NULL;*/
return NULL;
}
/*
=============
CL_FillRGBA
=============
*/
static void GAME_EXPORT CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
{
vid.rendermode = kRenderTransAdd;
_TriColor4ub(r,g,b,a);
Draw_Fill(_x,_y,_w,_h);
}
/*
=============
pfnFillRGBABlend
=============
*/
static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
{
vid.rendermode = kRenderTransAlpha;
_TriColor4ub(r,g,b,a);
Draw_Fill(_x,_y,_w,_h);
}
void Mod_UnloadTextures( model_t *mod );
qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
{
qboolean loaded = true;
if( create )
{
switch( mod->type )
{
case mod_studio:
//Mod_LoadStudioModel( mod, buf, loaded );
break;
case mod_sprite:
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
break;
case mod_alias:
//Mod_LoadAliasModel( mod, buf, &loaded );
break;
case mod_brush:
// Mod_LoadBrushModel( mod, buf, loaded );
break;
default: gEngfuncs.Host_Error( "Mod_LoadModel: unsupported type %d\n", mod->type );
}
}
if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf );
if( !create )
Mod_UnloadTextures( mod );
return loaded;
}
static int GL_RefGetParm( int parm, int arg )
{
image_t *glt;
switch( parm )
{
case PARM_TEX_WIDTH:
glt = R_GetTexture( arg );
return glt->width;
case PARM_TEX_HEIGHT:
glt = R_GetTexture( arg );
return glt->height;
case PARM_TEX_SRC_WIDTH:
glt = R_GetTexture( arg );
return glt->srcWidth;
case PARM_TEX_SRC_HEIGHT:
glt = R_GetTexture( arg );
return glt->srcHeight;
case PARM_TEX_GLFORMAT:
glt = R_GetTexture( arg );
return 0; //glt->format;
case PARM_TEX_ENCODE:
glt = R_GetTexture( arg );
return 0; //glt->encode;
case PARM_TEX_MIPCOUNT:
glt = R_GetTexture( arg );
return glt->numMips;
case PARM_TEX_DEPTH:
glt = R_GetTexture( arg );
return glt->depth;
case PARM_TEX_SKYBOX:
Assert( arg >= 0 && arg < 6 );
return tr.skyboxTextures[arg];
case PARM_TEX_SKYTEXNUM:
return 0; //tr.skytexturenum;
case PARM_TEX_LIGHTMAP:
arg = bound( 0, arg, MAX_LIGHTMAPS - 1 );
return tr.lightmapTextures[arg];
case PARM_WIDESCREEN:
return gpGlobals->wideScreen;
case PARM_FULLSCREEN:
return gpGlobals->fullScreen;
case PARM_SCREEN_WIDTH:
return gpGlobals->width;
case PARM_SCREEN_HEIGHT:
return gpGlobals->height;
case PARM_TEX_TARGET:
glt = R_GetTexture( arg );
return 0; //glt->target;
case PARM_TEX_TEXNUM:
glt = R_GetTexture( arg );
return 0; //glt->texnum;
case PARM_TEX_FLAGS:
glt = R_GetTexture( arg );
return glt->flags;
case PARM_ACTIVE_TMU:
return 0; //glState.activeTMU;
case PARM_LIGHTSTYLEVALUE:
arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 );
return tr.lightstylevalue[arg];
case PARM_MAX_IMAGE_UNITS:
return 0; //GL_MaxTextureUnits();
case PARM_REBUILD_GAMMA:
return 0;
case PARM_SURF_SAMPLESIZE:
if( arg >= 0 && arg < WORLDMODEL->numsurfaces )
return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] );
return LM_SAMPLE_SIZE;
case PARM_GL_CONTEXT_TYPE:
return 0; //glConfig.context;
case PARM_GLES_WRAPPER:
return 0; //glConfig.wrapper;
case PARM_STENCIL_ACTIVE:
return 0; //glState.stencilEnabled;
case PARM_SKY_SPHERE:
return ENGINE_GET_PARM_( parm, arg ) && !tr.fCustomSkybox;
default:
return ENGINE_GET_PARM_( parm, arg );
}
return 0;
}
static void GAME_EXPORT R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
{
image_t *glt = R_GetTexture( texture );
if( xScale ) *xScale = glt->xscale;
if( yScale ) *yScale = glt->yscale;
}
static void GAME_EXPORT R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density )
{
image_t *glt = R_GetTexture( texture );
if( red ) *red = glt->fogParams[0];
if( green ) *green = glt->fogParams[1];
if( blue ) *blue = glt->fogParams[2];
if( density ) *density = glt->fogParams[3];
}
static void GAME_EXPORT R_SetCurrentEntity( cl_entity_t *ent )
{
RI.currententity = ent;
// set model also
if( RI.currententity != NULL )
{
RI.currentmodel = RI.currententity->model;
}
}
static void GAME_EXPORT R_SetCurrentModel( model_t *mod )
{
RI.currentmodel = mod;
}
static float GAME_EXPORT R_GetFrameTime( void )
{
return tr.frametime;
}
static const char * GAME_EXPORT GL_TextureName( unsigned int texnum )
{
return "";//return R_GetTexture( texnum )->name;
}
const byte * GAME_EXPORT GL_TextureData( unsigned int texnum )
{
// rgbdata_t *pic = R_GetTexture( texnum )->original;
//if( pic != NULL )
//return pic->buffer;
return NULL;
}
void Mod_BrushUnloadTextures( model_t *mod )
{
int i;
gEngfuncs.Con_Printf("Unloading world\n");
tr.map_unload = true;
for( i = 0; i < mod->numtextures; i++ )
{
texture_t *tx = mod->textures[i];
if( !tx || tx->gl_texturenum == tr.defaultTexture )
continue; // free slot
GL_FreeTexture( tx->gl_texturenum ); // main texture
GL_FreeTexture( tx->fb_texturenum ); // luma texture
}
}
void Mod_UnloadTextures( model_t *mod )
{
int i, j;
Assert( mod != NULL );
switch( mod->type )
{
case mod_studio:
//Mod_StudioUnloadTextures( mod->cache.data );
break;
case mod_alias:
//Mod_AliasUnloadTextures( mod->cache.data );
break;
case mod_brush:
Mod_BrushUnloadTextures( mod );
break;
case mod_sprite:
Mod_SpriteUnloadTextures( mod->cache.data );
break;
default: gEngfuncs.Host_Error( "Mod_UnloadModel: unsupported type %d\n", mod->type );
}
}
void GAME_EXPORT R_ProcessEntData( qboolean allocate )
{
}
// stubs
void GAME_EXPORT GL_SetTexCoordArrayMode( uint mode )
{
}
void GAME_EXPORT GL_BackendStartFrame( void )
{
}
void GAME_EXPORT GL_BackendEndFrame( void )
{
}
void GAME_EXPORT GL_SetRenderMode(int mode)
{
vid.rendermode = mode;
/// TODO: table shading/blending???
/// maybe, setup block drawing function pointers here
}
void GAME_EXPORT R_ShowTextures( void )
{
// textures undone too
}
void GAME_EXPORT R_ShowTree( void )
{
// do we really need this here???
}
void GAME_EXPORT R_SetupSky(const char *skyboxname)
{
}
qboolean GAME_EXPORT VID_ScreenShot(const char *filename, int shot_type)
{
return false;
}
qboolean GAME_EXPORT VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot)
{
// cubemaps? in my softrender???
return false;
}
void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette)
{
}
void GAME_EXPORT GL_SubdivideSurface(msurface_t *fa)
{
}
void GAME_EXPORT DrawSingleDecal(decal_t *pDecal, msurface_t *fa)
{
}
void GAME_EXPORT GL_SelectTexture(int texture)
{
}
void GAME_EXPORT GL_LoadTexMatrixExt(const float *glmatrix)
{
}
void GAME_EXPORT GL_LoadIdentityTexMatrix( void )
{
}
void GAME_EXPORT GL_CleanUpTextureUnits(int last)
{
}
void GAME_EXPORT GL_TexGen(unsigned int coord, unsigned int mode)
{
}
void GAME_EXPORT GL_TextureTarget(uint target)
{
}
void GAME_EXPORT GL_BuildLightmaps( void )
{
CL_RunLightStyles();
}
void GAME_EXPORT Mod_SetOrthoBounds(const float *mins, const float *maxs)
{
}
qboolean GAME_EXPORT R_SpeedsMessage(char *out, size_t size)
{
return false;
}
byte *GAME_EXPORT Mod_GetCurrentVis( void )
{
return NULL;
}
const char *R_GetConfigName( void )
{
return "ref_soft"; // software specific cvars will go to ref_soft.cfg
}
static void* GAME_EXPORT R_GetProcAddress( const char *name )
{
return gEngfuncs.GL_GetProcAddress( name );
}
ref_interface_t gReffuncs =
{
R_Init,
R_Shutdown,
R_GetConfigName,
R_SetDisplayTransform,
GL_SetupAttributes,
GL_InitExtensions,
GL_ClearExtensions,
R_BeginFrame,
R_RenderScene,
R_EndFrame,
R_PushScene,
R_PopScene,
GL_BackendStartFrame,
GL_BackendEndFrame,
R_ClearScreen,
R_AllowFog,
GL_SetRenderMode,
R_AddEntity,
CL_AddCustomBeam,
R_ProcessEntData,
R_ShowTextures,
R_GetTextureOriginalBuffer,
GL_LoadTextureFromBuffer,
GL_ProcessTexture,
R_SetupSky,
R_Set2DMode,
R_DrawStretchRaw,
R_DrawStretchPic,
R_DrawTileClear,
CL_FillRGBA,
CL_FillRGBABlend,
VID_ScreenShot,
VID_CubemapShot,
R_LightPoint,
R_DecalShoot,
R_DecalRemoveAll,
R_CreateDecalList,
R_ClearAllDecals,
R_StudioEstimateFrame,
R_StudioLerpMovement,
CL_InitStudioAPI,
R_InitSkyClouds,
GL_SubdivideSurface,
CL_RunLightStyles,
R_GetSpriteParms,
R_GetSpriteTexture,
Mod_LoadMapSprite,
Mod_ProcessRenderData,
Mod_StudioLoadTextures,
CL_DrawParticles,
CL_DrawTracers,
CL_DrawBeams,
R_BeamCull,
GL_RefGetParm,
R_GetDetailScaleForTexture,
R_GetExtraParmsForTexture,
R_GetFrameTime,
R_SetCurrentEntity,
R_SetCurrentModel,
GL_FindTexture,
GL_TextureName,
GL_TextureData,
GL_LoadTexture,
GL_CreateTexture,
GL_LoadTextureArray,
GL_CreateTextureArray,
GL_FreeTexture,
DrawSingleDecal,
R_DecalSetupVerts,
R_EntityRemoveDecals,
R_UploadStretchRaw,
GL_Bind,
GL_SelectTexture,
GL_LoadTexMatrixExt,
GL_LoadIdentityTexMatrix,
GL_CleanUpTextureUnits,
GL_TexGen,
GL_TextureTarget,
GL_SetTexCoordArrayMode,
GL_UpdateTexSize,
NULL,
NULL,
CL_DrawParticlesExternal,
R_LightVec,
R_StudioGetTexture,
R_RenderFrame,
Mod_SetOrthoBounds,
R_SpeedsMessage,
Mod_GetCurrentVis,
R_NewMap,
R_ClearScene,
R_GetProcAddress,
TriRenderMode,
TriBegin,
TriEnd,
_TriColor4f,
_TriColor4ub,
TriTexCoord2f,
TriVertex3fv,
TriVertex3f,
TriWorldToScreen,
TriFog,
R_ScreenToWorld,
TriGetMatrix,
TriFogParams,
TriCullFace,
VGUI_DrawInit,
VGUI_DrawShutdown,
VGUI_SetupDrawingText,
VGUI_SetupDrawingRect,
VGUI_SetupDrawingImage,
VGUI_BindTexture,
VGUI_EnableTexture,
VGUI_CreateTexture,
VGUI_UploadTexture,
VGUI_UploadTextureBlock,
VGUI_DrawQuad,
VGUI_GetTextureSizes,
VGUI_GenerateTexture,
};
int EXPORT GAME_EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals )
{
if( version != REF_API_VERSION )
return 0;
// fill in our callbacks
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
gpGlobals = globals;
return REF_API_VERSION;
}
void EXPORT GetRefHumanReadableName( char *out, size_t size )
{
Q_strncpy( out, "Software", size );
}

1298
ref_soft/r_decals.c Normal file

File diff suppressed because it is too large Load Diff

428
ref_soft/r_draw.c Normal file
View File

@ -0,0 +1,428 @@
/*
gl_draw.c - orthogonal drawing stuff
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"
/*
=============
R_GetImageParms
=============
*/
void R_GetTextureParms( int *w, int *h, int texnum )
{
image_t *glt;
glt = R_GetTexture( texnum );
if( w ) *w = glt->srcWidth;
if( h ) *h = glt->srcHeight;
}
/*
=============
R_GetSpriteParms
same as GetImageParms but used
for sprite models
=============
*/
void GAME_EXPORT R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite )
{
mspriteframe_t *pFrame;
if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ?
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f );
if( frameWidth ) *frameWidth = pFrame->width;
if( frameHeight ) *frameHeight = pFrame->height;
if( numFrames ) *numFrames = pSprite->numframes;
}
int GAME_EXPORT R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame )
{
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data )
return 0;
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum;
}
/*
=============
Draw_StretchPicImplementation
=============
*/
void R_DrawStretchPicImplementation( int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic )
{
pixel_t *source, *dest;
unsigned int v, u, sv;
unsigned int height;
unsigned int f, fstep;
int skip;
qboolean transparent = false;
pixel_t *buffer;
if( x < 0 )
{
s1 += (-x)*(s2-s1) / w;
x = 0;
}
if( x + w > vid.width )
{
s2 -= (x + w - vid.width) * (s2 - s1)/ w ;
w = vid.width - x;
}
if( y + h > vid.height )
{
t2 -= (y + h - vid.height) * (t2 - t1) / h;
h = vid.height - y;
}
if( !pic->pixels[0] || s1 >= s2 || t1 >= t2 )
return;
//gEngfuncs.Con_Printf ("pixels is %p\n", pic->pixels[0] );
height = h;
if (y < 0)
{
skip = -y;
height += y;
y = 0;
}
else
skip = 0;
dest = vid.buffer + y * vid.rowbytes + x;
if( pic->alpha_pixels )
{
buffer = pic->alpha_pixels;
transparent = true;
}
else
buffer = pic->pixels[0];
#pragma omp parallel for schedule(static)
for (v=0 ; v<height ; v++)
{
int alpha1 = vid.alpha;
#ifdef _OPENMP
pixel_t *dest = vid.buffer + (y + v) * vid.rowbytes + x;
#endif
sv = (skip + v)*(t2-t1)/h + t1;
source = buffer + sv*pic->width + s1;
{
f = 0;
fstep = ((s2-s1) << 16)/w;
#if 0
for (u=0 ; u<w ; u+=4)
{
dest[u] = source[f>>16];
f += fstep;
dest[u+1] = source[f>>16];
f += fstep;
dest[u+2] = source[f>>16];
f += fstep;
dest[u+3] = source[f>>16];
f += fstep;
}
#else
for (u=0 ; u<w ; u++)
{
pixel_t src = source[f>>16];
int alpha = alpha1;
f += fstep;
if( transparent )
{
alpha &= src >> ( 16 - 3 );
src = src << 3;
}
if( alpha == 0 )
continue;
if( vid.color != COLOR_WHITE )
src = vid.modmap[(src & 0xff00)|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 3);
if( vid.rendermode == kRenderTransAdd)
{
pixel_t screen = dest[u];
dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0);
}
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) )
{
pixel_t screen = dest[u]; // | 0xff & screen & src ;
dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3);
}
else
dest[u] = src;
}
#endif
}
dest += vid.rowbytes;
}
}
/*
=============
R_DrawStretchPic
=============
*/
void GAME_EXPORT R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
{
image_t *pic = R_GetTexture(texnum);
int width = pic->width, height = pic->height;
// GL_Bind( XASH_TEXTURE0, texnum );
if( s2 > 1.0f || t2 > 1.0f )
return;
if( s1 < 0.0f || t1 < 0.0f )
return;
if( w < 1.0f || h < 1.0f )
return;
R_DrawStretchPicImplementation(x,y,w,h, width * s1, height * t1, width * s2, height * t2, pic);
}
void Draw_Fill (int x, int y, int w, int h)
{
pixel_t *dest;
unsigned int v, u;
unsigned int height;
int skip;
pixel_t src = vid.color;
int alpha = vid.alpha;
if( x < 0 )
x = 0;
if( x + w > vid.width )
w = vid.width - x;
if( w <= 0 )
return;
if( y + h > vid.height )
h = vid.height - y;
if( h <= 0 )
return;
height = h;
if( y < 0 )
{
if( h <= -y )
return;
skip = -y;
height += y;
y = 0;
}
else
skip = 0;
dest = vid.buffer + y * vid.rowbytes + x;
#pragma omp parallel for schedule(static)
for (v=0 ; v<height ; v++)
{
#ifdef _OPENMP
pixel_t *dest = vid.buffer + (y + v) * vid.rowbytes + x;
#endif
{
#if 0
for (u=0 ; u<w ; u+=4)
{
dest[u] = source[f>>16];
f += fstep;
dest[u+1] = source[f>>16];
f += fstep;
dest[u+2] = source[f>>16];
f += fstep;
dest[u+3] = source[f>>16];
f += fstep;
}
#else
for (u=0 ; u<w ; u++)
{
if( alpha == 0 )
continue;
if( vid.rendermode == kRenderTransAdd)
{
pixel_t screen = dest[u];
dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0);
}
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) )
{
pixel_t screen = dest[u]; // | 0xff & screen & src ;
dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3);
}
else
dest[u] = src;
}
#endif
}
dest += vid.rowbytes;
}
}
/*
=============
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void GAME_EXPORT R_DrawTileClear( int texnum, int x, int y, int w, int h )
{
int tw, th, x2, i, j;
image_t *pic;
pixel_t *psrc, *pdest;
GL_SetRenderMode( kRenderNormal );
_TriColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
GL_Bind( XASH_TEXTURE0, texnum );
pic = R_GetTexture( texnum );
tw = pic->width;
th = pic->height;
if (x < 0)
{
w += x;
x = 0;
}
if (y < 0)
{
h += y;
y = 0;
}
if (x + w > vid.width)
w = vid.width - x;
if (y + h > vid.height)
h = vid.height - y;
if (w <= 0 || h <= 0)
return;
x2 = x + w;
pdest = vid.buffer + y*vid.rowbytes;
for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
{
psrc = pic->pixels[0] + tw * ((i+y)&63);
for (j=x ; j<x2 ; j++)
pdest[j] = psrc[j&63];
}
}
/*
=============
R_DrawStretchRaw
=============
*/
void GAME_EXPORT R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty )
{
byte *raw = NULL;
image_t *tex;
raw = (byte *)data;
//pglDisable( GL_BLEND );
//pglDisable( GL_ALPHA_TEST );
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
tex = R_GetTexture( tr.cinTexture );
GL_Bind( XASH_TEXTURE0, tr.cinTexture );
}
/*
=============
R_UploadStretchRaw
=============
*/
void GAME_EXPORT R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data )
{
byte *raw = NULL;
image_t *tex;
raw = (byte *)data;
tex = R_GetTexture( texture );
GL_Bind( GL_KEEP_UNIT, texture );
tex->width = cols;
tex->height = rows;
}
/*
===============
R_Set2DMode
===============
*/
void GAME_EXPORT R_Set2DMode( qboolean enable )
{
vid.color = COLOR_WHITE;
vid.is2d = enable;
vid.alpha = 7;
if( enable )
{
// if( glState.in2DMode )
// return;
#if 0
// set 2D virtual screen size
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
GL_Cull( GL_NONE );
pglDepthMask( GL_FALSE );
pglDisable( GL_DEPTH_TEST );
pglEnable( GL_ALPHA_TEST );
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
#endif
// glState.in2DMode = true;
RI.currententity = NULL;
RI.currentmodel = NULL;
}
else
{
#if 0
pglDepthMask( GL_TRUE );
pglEnable( GL_DEPTH_TEST );
glState.in2DMode = false;
pglMatrixMode( GL_PROJECTION );
GL_LoadMatrix( RI.projectionMatrix );
pglMatrixMode( GL_MODELVIEW );
GL_LoadMatrix( RI.worldviewMatrix );
GL_Cull( GL_FRONT );
#endif
}
}

1311
ref_soft/r_edge.c Normal file

File diff suppressed because it is too large Load Diff

771
ref_soft/r_glblit.c Normal file
View File

@ -0,0 +1,771 @@
#include "r_local.h"
#include "../ref_gl/gl_export.h"
struct swblit_s
{
uint stride;
uint bpp;
uint rmask, gmask, bmask;
void *(*pLockBuffer)( void );
void (*pUnlockBuffer)( void );
qboolean(*pCreateBuffer)( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b );
uint rotate;
} swblit;
qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
{
qboolean ret = true;
if( rotate > 1 )
{
gEngfuncs.Con_Printf("only 0-1 rotation supported\n");
ret = false;
}
else
swblit.rotate = rotate;
if( offset_x || offset_y )
{
// it is possible implement for offset > 0
gEngfuncs.Con_Printf("offset transform not supported\n");
ret = false;
}
if( scale_x != 1.0f || scale_y != 1.0f )
{
// maybe implement 2x2?
gEngfuncs.Con_Printf("scale transform not supported\n");
ret = false;
}
return ret;
}
/*
========================
DebugCallback
For ARB_debug_output
========================
*/
static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLuint severity, GLint length, const GLcharARB *message, GLvoid *userParam )
{
switch( type )
{
case GL_DEBUG_TYPE_ERROR_ARB:
gEngfuncs.Con_Printf( S_OPENGL_ERROR "%s\n", message );
break;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
gEngfuncs.Con_Printf( S_OPENGL_WARN "%s\n", message );
break;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
gEngfuncs.Con_Printf( S_OPENGL_WARN "%s\n", message );
break;
case GL_DEBUG_TYPE_PORTABILITY_ARB:
gEngfuncs.Con_Reportf( S_OPENGL_WARN "%s\n", message );
break;
case GL_DEBUG_TYPE_PERFORMANCE_ARB:
gEngfuncs.Con_Printf( S_OPENGL_NOTE "%s\n", message );
break;
case GL_DEBUG_TYPE_OTHER_ARB:
default:
gEngfuncs.Con_Printf( S_OPENGL_NOTE "%s\n", message );
break;
}
}
static unsigned short *glbuf;
static int tex;
#define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x); \
gEngfuncs.Con_Printf(#x " : %p\n",p##x)
void GAME_EXPORT GL_SetupAttributes( int safegl )
{
#if GLDEBUG
gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" );
gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG );
#endif
// untill we have any blitter in ref api, setup GL
gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_ES );
gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_EGL, 1 );
gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MAJOR_VERSION, 3 );
gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MINOR_VERSION, 0 );
gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 );
gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 );
gEngfuncs.GL_SetAttribute( REF_GL_GREEN_SIZE, 6 );
gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 );
}
void (*pglOrthof)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);
void GL_FUNCTION( glBindBuffer)(GLenum target, GLuint buffer);
void GL_FUNCTION( glBufferData )(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
void GL_FUNCTION( glGenBuffers )(GLsizei n, GLuint *buffers);
void GL_FUNCTION( glDeleteBuffers )(GLsizei n, const GLuint *buffers);
GLvoid* GL_FUNCTION( glMapBuffer )(GLenum target, GLenum access);
GLboolean GL_FUNCTION( glUnmapBuffer )(GLenum target);
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#define GL_FRAMEBUFFER 0x8D40
#define GL_COLOR_ATTACHMENT0 0x8CE0
#define GL_READ_FRAMEBUFFER 0x8CA8
#define GL_DRAW_FRAMEBUFFER 0x8CA9
void GAME_EXPORT GL_InitExtensions( void )
{
LOAD(glBegin);
LOAD(glEnd);
LOAD(glTexCoord2f);
LOAD(glVertex2f);
LOAD(glEnable);
LOAD(glDisable);
LOAD(glTexImage2D);
LOAD(glOrtho);
LOAD(glOrthof);
LOAD(glMatrixMode);
LOAD(glLoadIdentity);
LOAD(glViewport);
LOAD(glBindTexture);
LOAD(glDebugMessageCallbackARB);
LOAD(glDebugMessageControlARB);
LOAD(glGetError);
LOAD(glGenTextures);
LOAD(glTexParameteri);
LOAD(glEnableClientState);
LOAD(glDisableClientState);
LOAD(glVertexPointer);
LOAD(glTexCoordPointer);
LOAD(glDrawElements);
LOAD(glClear);
LOAD(glClearColor);
LOAD(glGetString);
LOAD(glColor4f);
LOAD(glDrawArrays);
LOAD(glBindBuffer);
LOAD(glBufferData);
LOAD(glGenBuffers);
LOAD(glDeleteBuffers);
LOAD(glMapBuffer);
LOAD(glUnmapBuffer);
LOAD(glGenFramebuffers);
LOAD(glBindFramebuffer);
LOAD(glFramebufferTexture2D);
LOAD(glBlitFramebuffer);
LOAD(glGenTextures);
gEngfuncs.Con_Printf("version:%s\n",pglGetString(GL_VERSION));
#if GLDEBUG
if( gpGlobals->developer )
{
gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n");
pglDebugMessageCallbackARB( GL_DebugOutput, NULL );
// force everything to happen in the main thread instead of in a separate driver thread
pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB );
}
// enable all the low priority messages
pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true );
#endif
}
void GAME_EXPORT GL_ClearExtensions( void )
{
}
static void *R_Lock_GL1( void )
{
return glbuf;
}
static void R_Unlock_GL1( void )
{
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf );
//gEngfuncs.Con_Printf("%d\n",pglGetError());
pglBegin( GL_QUADS );
pglTexCoord2f( 0, 0 );
pglVertex2f( 0, 0 );
pglTexCoord2f( 1, 0 );
pglVertex2f( 1, 0 );
pglTexCoord2f( 1, 1 );
pglVertex2f( 1, 1 );
pglTexCoord2f( 0, 1 );
pglVertex2f( 0, 1 );
pglEnd();
gEngfuncs.GL_SwapBuffers();
}
static void R_Unlock_GLES1( void )
{
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf );
pglDrawArrays( GL_TRIANGLE_FAN, 0,4 );
gEngfuncs.GL_SwapBuffers();
}
static qboolean R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
{
pglViewport( 0, 0, width, height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, 1, 1, 0, -99999, 99999 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
pglEnable( GL_TEXTURE_2D );
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
if( glbuf )
Mem_Free(glbuf);
glbuf = Mem_Malloc( r_temppool, width*height*2 );
*stride = width;
*bpp = 2;
*r = MASK(5) << (6 + 5);
*g = MASK(6) << 5;
*b = MASK(5);
return true;
}
static qboolean R_CreateBuffer_GLES1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
{
float data[] = {
// quad verts match texcoords
0, 0,
1, 0,
1, 1,
0, 1,
};
int vbo;
pglViewport( 0, 0, width, height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
// project 0..1 to screen size
pglOrthof( 0, 1, 1, 0, -99999, 99999 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
pglEnable( GL_TEXTURE_2D );
pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
if( vbo )
pglDeleteBuffers( 1,&vbo );
pglGenBuffers( 1,&vbo );
pglBindBuffer( GL_ARRAY_BUFFER_ARB, vbo );
pglBufferData( GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB );
pglEnableClientState( GL_VERTEX_ARRAY );
pglEnableClientState( GL_TEXTURE_COORD_ARRAY );
pglVertexPointer( 2, GL_FLOAT, 8, 0 );
pglTexCoordPointer( 2, GL_FLOAT, 8, 0 );
pglBindBuffer( GL_ARRAY_BUFFER_ARB, 0 ) ;
pglColor4f( 1, 1, 1, 1 );
if( glbuf )
Mem_Free( glbuf );
glbuf = Mem_Malloc( r_temppool, width*height*2 );
*stride = width;
*bpp = 2;
*r = MASK(5) << (6 + 5);
*g = MASK(6) << 5;
*b = MASK(5);
return true;
}
static void *R_Lock_GLES3( void )
{
pglBufferData( GL_PIXEL_UNPACK_BUFFER, vid.width * vid.height * 2, 0, GL_STREAM_DRAW_ARB );
return pglMapBuffer( GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY_ARB );
}
static void R_Unlock_GLES3( void )
{
gEngfuncs.GL_SwapBuffers();
pglUnmapBuffer( GL_PIXEL_UNPACK_BUFFER );
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 );
//pglDrawArrays( GL_TRIANGLE_FAN, 0,4 );
pglBlitFramebuffer( 0, vid.height, vid.width, 0, 0, 0, vid.width, vid.height, GL_COLOR_BUFFER_BIT, GL_NEAREST );
}
static qboolean R_CreateBuffer_GLES3( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
{
float data[] = {
// quad verts match texcoords
0, 0,
1, 0,
1, 1,
0, 1,
};
int vbo, pbo, fbo, to;
// shitty fbo does not work without texture objects :(
pglGenTextures( 1, &to );
pglBindTexture( GL_TEXTURE_2D, to );
pglViewport( 0, 0, width, height );
/*pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
// project 0..1 to screen size
pglOrtho( 0, 1, 1, 0, -99999, 99999 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
pglEnable( GL_TEXTURE_2D );
pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
if( vbo )
pglDeleteBuffers( 1,&vbo );
*/
if( pbo )
pglDeleteBuffers( 1,&pbo );
//pglGenBuffers( 1,&vbo );
pglGenBuffers( 1, &pbo );
//pglBindBuffer( GL_ARRAY_BUFFER_ARB, vbo );
//pglBufferData( GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB );
//pglEnableClientState( GL_VERTEX_ARRAY );
//pglEnableClientState( GL_TEXTURE_COORD_ARRAY );
//pglVertexPointer( 2, GL_FLOAT, 8, 0 );
//pglTexCoordPointer( 2, GL_FLOAT, 8, 0 );
//pglBindBuffer( GL_ARRAY_BUFFER_ARB, 0 );
pglBindBuffer( GL_PIXEL_UNPACK_BUFFER, pbo );
pglBufferData( GL_PIXEL_UNPACK_BUFFER, width * height * 2, 0, GL_STREAM_DRAW_ARB );
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 );
pglGenFramebuffers(1, &fbo);
pglBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
pglFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to, 0);
pglBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//pglColor4f( 1, 1, 1, 1 );
*stride = width;
*bpp = 2;
*r = MASK(5) << (6 + 5);
*g = MASK(6) << 5;
*b = MASK(5);
return true;
}
static int FIRST_BIT( uint mask )
{
uint i;
for( i = 0; !(BIT(i) & mask); i++ );
return i;
}
static int COUNT_BITS( uint mask )
{
uint i;
for( i = 0; mask; mask = mask >> 1 )
i += mask & 1;
return i;
}
void R_BuildScreenMap( void )
{
int i;
uint rshift = FIRST_BIT(swblit.rmask), gshift = FIRST_BIT(swblit.gmask), bshift = FIRST_BIT(swblit.bmask);
uint rbits = COUNT_BITS(swblit.rmask), gbits = COUNT_BITS(swblit.gmask), bbits = COUNT_BITS(swblit.bmask);
uint rmult = BIT(rbits), gmult = BIT(gbits), bmult = BIT(bbits);
uint rdiv = MASK(5), gdiv = MASK(6), bdiv = MASK(5);
gEngfuncs.Con_Printf("Blit table: %d %d %d %d %d %d\n", rmult, gmult, bmult, rdiv, gdiv, bdiv );
#ifdef SEPARATE_BLIT
for( i = 0; i < 256; i++ )
{
unsigned int r,g,b;
// 332 to 565
r = ((i >> (8 - 3) )<< 2 ) & MASK(5);
g = ((i >> (8 - 3 - 3)) << 3) & MASK(6);
b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
vid.screen_major[i] = r << (6 + 5) | (g << 5) | b;
// restore minor GBRGBRGB
r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0);
g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0);
b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0);
vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b;
}
#else
for( i = 0; i < 256; i++ )
{
unsigned int r,g,b , major, j;
// 332 to 565
r = ((i >> (8 - 3) )<< 2 ) & MASK(5);
g = ((i >> (8 - 3 - 3)) << 3) & MASK(6);
b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
//major = r << (6 + 5) | (g << 5) | b;
major = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift;
for( j = 0; j < 256; j++ )
{
uint minor;
// restore minor GBRGBRGB
r = MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0);
g = MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0);
b = MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0);
//vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major;
minor = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift;
if( swblit.bpp == 2 )
vid.screen[(i<<8)|j] = major | minor;
else
vid.screen32[(i<<8)|j] = major | minor;
}
}
#endif
}
#define FOR_EACH_COLOR(x) for( r##x = 0; r##x < BIT(3); r##x++ ) for( g##x = 0; g##x < BIT(3); g##x++ ) for( b##x = 0; b##x < BIT(2); b##x++ )
void R_BuildBlendMaps( void )
{
unsigned int r1, g1, b1;
unsigned int r2, g2, b2;
unsigned int i, j;
FOR_EACH_COLOR(1)FOR_EACH_COLOR(2)
{
unsigned int r, g, b;
unsigned short index1 = r1 << (2 + 3) | g1 << 2 | b1;
unsigned short index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 8;
unsigned int a;
r = r1 + r2;
g = g1 + g2;
b = b1 + b2;
if( r > MASK(3) )
r = MASK(3);
if( g > MASK(3) )
g = MASK(3);
if( b > MASK(2) )
b = MASK(2);
ASSERT(!vid.addmap[index2|index1]);
vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b;
r = r1 * r2 / MASK(3);
g = g1 * g2 / MASK(3);
b = b1 * b2 / MASK(2);
vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b;
#if 0
for( a = 0; a < 8; a++ )
{
r = r1 * (7 - a) / 7 + r2 * a / 7;
g = g1 * (7 - a) / 7 + g2 * a / 7;
b = b1 * (7 - a) / 7 + b2 * a / 7;
//if( b == 1 ) b = 0;
vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b;
}
#endif
}
for( i = 0; i < 8192; i++ )
{
unsigned int r, g, b;
uint color = i << 3;
uint m = color >> 8;
uint j = color & 0xff;
unsigned short index1 = i;
r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5);
g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6);
b1 = ((m >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
r1 |= MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0);
g1 |= MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0);
b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0);
for( j = 0; j < 32; j++)
{
unsigned int index2 = j << 13;
unsigned int major, minor;
r = r1 * j / 32;
g = g1 * j / 32;
b = b1 * j / 32;
major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2)));
// save minor GBRGBRGB
minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0);
vid.colormap[index2|index1] = major << 8 | (minor & 0xFF);
}
}
#if 1
for( i = 0; i < 1024; i++ )
{
unsigned int r, g, b;
uint color = i << 6 | BIT(5) | BIT(4) | BIT(3);
uint m = color >> 8;
uint j = color & 0xff;
unsigned short index1 = i;
r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5);
g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6);
b1 = ((m >> (8 - 3 - 3 - 2)) << 3) & MASK(5);
r1 |= MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0);
g1 |= MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0);
b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0);
FOR_EACH_COLOR(2)
{
unsigned int index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 10;
unsigned int k;
for( k = 0; k < 3; k++ )
{
unsigned int major, minor;
unsigned int a = k + 2;
r = r1 * (7 - a) / 7 + (r2 << 2 | BIT(2)) * a / 7;
g = g1 * (7 - a) / 7 + (g2 << 3 | MASK(2)) * a / 7;
b = b1 * (7 - a) / 7 + (b2 << 3 | MASK(2)) * a / 7;
if( r > MASK(5) )
r = MASK(5);
if( g > MASK(6) )
g = MASK(6);
if( b > MASK(5) )
b = MASK(5);
ASSERT( b < 32 );
major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2)));
// save minor GBRGBRGB
minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0);
minor = minor & ~0x3f;
vid.alphamap[k << 18|index2|index1] = major << 8 | (minor & 0xFF);
}
}
}
#endif
}
void R_AllocScreen( void );
void R_InitBlit( qboolean glblit )
{
R_BuildBlendMaps();
if( glblit )
{
swblit.pLockBuffer = R_Lock_GLES3;
swblit.pUnlockBuffer = R_Unlock_GLES3;
swblit.pCreateBuffer = R_CreateBuffer_GLES3;
}
else
{
swblit.pLockBuffer = gEngfuncs.SW_LockBuffer;
swblit.pUnlockBuffer = gEngfuncs.SW_UnlockBuffer;
swblit.pCreateBuffer = gEngfuncs.SW_CreateBuffer;
}
R_AllocScreen();
}
void R_AllocScreen( void )
{
int w, h;
if( gpGlobals->width < 128 )
gpGlobals->width = 128;
if( gpGlobals->height < 128 )
gpGlobals->height = 128;
R_InitCaches();
if( swblit.rotate )
w = gpGlobals->height, h = gpGlobals->width;
else
h = gpGlobals->height, w = gpGlobals->width;
swblit.pCreateBuffer( w, h, &swblit.stride, &swblit.bpp,
&swblit.rmask, &swblit.gmask, &swblit.bmask);
R_BuildScreenMap();
vid.width = gpGlobals->width;
vid.height = gpGlobals->height;
vid.rowbytes = gpGlobals->width; // rowpixels
if( d_pzbuffer )
free( d_pzbuffer );
d_pzbuffer = malloc( vid.width*vid.height*2 + 64 );
if( vid.buffer )
free( vid.buffer );
vid.buffer = malloc( vid.width * vid.height*sizeof( pixel_t ) );
}
void R_BlitScreen( void )
{
int u, v;
void *buffer = swblit.pLockBuffer();
// gEngfuncs.Con_Printf("blit begin\n");
//memset( vid.buffer, 10, vid.width * vid.height );
if( !buffer || gpGlobals->width != vid.width || gpGlobals->height != vid.height )
{
gEngfuncs.Con_Printf("pre allocscrn\n");
R_AllocScreen();
gEngfuncs.Con_Printf("post allocscrn\n");
return;
}
//return;
//byte *buf = vid.buffer;
//#pragma omp parallel for schedule(static)
//gEngfuncs.Con_Printf("swblit %d %d", swblit.bpp, vid.height );
if( swblit.rotate )
{
if( swblit.bpp == 2 )
{
unsigned short *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint d = swblit.stride - v - 1;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen[vid.buffer[start + u]];
pbuf[d] = s;
d += swblit.stride;
}
}
}
else if( swblit.bpp == 4 )
{
unsigned int *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint d = swblit.stride - v - 1;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen32[vid.buffer[start + u]];
pbuf[d] = s;
d += swblit.stride;
}
}
}
else if( swblit.bpp == 3 )
{
byte *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint d = swblit.stride - v - 1;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen32[vid.buffer[start + u]];
pbuf[(d)*3] = s;
s = s >> 8;
pbuf[(d)*3+1] = s;
s = s >> 8;
pbuf[(d)*3+2] = s;
d += swblit.stride;
}
}
}
}
else
{
if( swblit.bpp == 2 )
{
unsigned short *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint dstart = swblit.stride * v;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen[vid.buffer[start + u]];
pbuf[dstart + u] = s;
}
}
}
else if( swblit.bpp == 4 )
{
unsigned int *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint dstart = swblit.stride * v;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen32[vid.buffer[start + u]];
pbuf[dstart + u] = s;
}
}
}
else if( swblit.bpp == 3 )
{
byte *pbuf = buffer;
for( v = 0; v < vid.height;v++)
{
uint start = vid.rowbytes * v;
uint dstart = swblit.stride * v;
for( u = 0; u < vid.width; u++ )
{
unsigned int s = vid.screen32[vid.buffer[start + u]];
pbuf[(dstart+u)*3] = s;
s = s >> 8;
pbuf[(dstart+u)*3+1] = s;
s = s >> 8;
pbuf[(dstart+u)*3+2] = s;
}
}
}
}
swblit.pUnlockBuffer();
// gEngfuncs.Con_Printf("blit end\n");
}

1414
ref_soft/r_image.c Normal file

File diff suppressed because it is too large Load Diff

501
ref_soft/r_light.c Normal file
View File

@ -0,0 +1,501 @@
/*
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 "xash3d_mathlib.h"
#include "ref_params.h"
//unused, need refactor
unsigned blocklights[10240];
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
==================
CL_RunLightStyles
==================
*/
void GAME_EXPORT 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( !ENGINE_GET_PARM( PARAM_GAMEPAUSED ) && 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.framecount )//tr.dlightframecount )
{
surf->dlightbits = 0;
surf->dlightframe = tr.framecount; //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 * 2.5; // scale;
cv->g += lm->g * scale * 2.5; // scale;
cv->b += lm->b * scale * 2.5; // 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 GAME_EXPORT R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
{
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
//light.r = light.g = light.b = 255;
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 GAME_EXPORT 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 );
}

1327
ref_soft/r_local.h Normal file

File diff suppressed because it is too large Load Diff

2135
ref_soft/r_main.c Normal file

File diff suppressed because it is too large Load Diff

267
ref_soft/r_math.c Normal file
View File

@ -0,0 +1,267 @@
/*
gl_rmath.c - renderer mathlib
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 "xash3d_mathlib.h"
/*
========================================================================
Matrix4x4 operations (private to renderer)
========================================================================
*/
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
}
/*
================
Matrix4x4_CreateProjection
NOTE: produce quake style world orientation
================
*/
void Matrix4x4_CreateProjection( matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar )
{
out[0][0] = ( 2.0f * zNear ) / ( xMax - xMin );
out[1][1] = ( 2.0f * zNear ) / ( yMax - yMin );
out[2][2] = -( zFar + zNear ) / ( zFar - zNear );
out[3][3] = out[0][1] = out[1][0] = out[3][0] = out[0][3] = out[3][1] = out[1][3] = 0.0f;
out[2][0] = 0.0f;
out[2][1] = 0.0f;
out[0][2] = ( xMax + xMin ) / ( xMax - xMin );
out[1][2] = ( yMax + yMin ) / ( yMax - yMin );
out[3][2] = -1.0f;
out[2][3] = -( 2.0f * zFar * zNear ) / ( zFar - zNear );
}
void Matrix4x4_CreateOrtho( matrix4x4 out, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar )
{
out[0][0] = 2.0f / (xRight - xLeft);
out[1][1] = 2.0f / (yTop - yBottom);
out[2][2] = -2.0f / (zFar - zNear);
out[3][3] = 1.0f;
out[0][1] = out[0][2] = out[1][0] = out[1][2] = out[3][0] = out[3][1] = out[3][2] = 0.0f;
out[2][0] = 0.0f;
out[2][1] = 0.0f;
out[0][3] = -(xRight + xLeft) / (xRight - xLeft);
out[1][3] = -(yTop + yBottom) / (yTop - yBottom);
out[2][3] = -(zFar + zNear) / (zFar - zNear);
}
/*
================
Matrix4x4_CreateModelview
NOTE: produce quake style world orientation
================
*/
void Matrix4x4_CreateModelview( matrix4x4 out )
{
out[0][0] = out[1][1] = out[2][2] = 0.0f;
out[3][0] = out[0][3] = 0.0f;
out[3][1] = out[1][3] = 0.0f;
out[3][2] = out[2][3] = 0.0f;
out[3][3] = 1.0f;
out[1][0] = out[0][2] = out[2][1] = 0.0f;
out[2][0] = out[0][1] = -1.0f;
out[1][2] = 1.0f;
}
void Matrix4x4_ToArrayFloatGL( const matrix4x4 in, float out[16] )
{
out[ 0] = in[0][0];
out[ 1] = in[1][0];
out[ 2] = in[2][0];
out[ 3] = in[3][0];
out[ 4] = in[0][1];
out[ 5] = in[1][1];
out[ 6] = in[2][1];
out[ 7] = in[3][1];
out[ 8] = in[0][2];
out[ 9] = in[1][2];
out[10] = in[2][2];
out[11] = in[3][2];
out[12] = in[0][3];
out[13] = in[1][3];
out[14] = in[2][3];
out[15] = in[3][3];
}
void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] )
{
out[0][0] = in[0];
out[1][0] = in[1];
out[2][0] = in[2];
out[3][0] = in[3];
out[0][1] = in[4];
out[1][1] = in[5];
out[2][1] = in[6];
out[3][1] = in[7];
out[0][2] = in[8];
out[1][2] = in[9];
out[2][2] = in[10];
out[3][2] = in[11];
out[0][3] = in[12];
out[1][3] = in[13];
out[2][3] = in[14];
out[3][3] = in[15];
}
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
{
out[0][0] = 1.0f;
out[0][1] = 0.0f;
out[0][2] = 0.0f;
out[0][3] = x;
out[1][0] = 0.0f;
out[1][1] = 1.0f;
out[1][2] = 0.0f;
out[1][3] = y;
out[2][0] = 0.0f;
out[2][1] = 0.0f;
out[2][2] = 1.0f;
out[2][3] = z;
out[3][0] = 0.0f;
out[3][1] = 0.0f;
out[3][2] = 0.0f;
out[3][3] = 1.0f;
}
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z )
{
float len, c, s;
len = x * x + y * y + z * z;
if( len != 0.0f ) len = 1.0f / sqrt( len );
x *= len;
y *= len;
z *= len;
angle *= (-M_PI_F / 180.0f);
SinCos( angle, &s, &c );
out[0][0]=x * x + c * (1 - x * x);
out[0][1]=x * y * (1 - c) + z * s;
out[0][2]=z * x * (1 - c) - y * s;
out[0][3]=0.0f;
out[1][0]=x * y * (1 - c) - z * s;
out[1][1]=y * y + c * (1 - y * y);
out[1][2]=y * z * (1 - c) + x * s;
out[1][3]=0.0f;
out[2][0]=z * x * (1 - c) + y * s;
out[2][1]=y * z * (1 - c) - x * s;
out[2][2]=z * z + c * (1 - z * z);
out[2][3]=0.0f;
out[3][0]=0.0f;
out[3][1]=0.0f;
out[3][2]=0.0f;
out[3][3]=1.0f;
}
void Matrix4x4_CreateScale( matrix4x4 out, float x )
{
out[0][0] = x;
out[0][1] = 0.0f;
out[0][2] = 0.0f;
out[0][3] = 0.0f;
out[1][0] = 0.0f;
out[1][1] = x;
out[1][2] = 0.0f;
out[1][3] = 0.0f;
out[2][0] = 0.0f;
out[2][1] = 0.0f;
out[2][2] = x;
out[2][3] = 0.0f;
out[3][0] = 0.0f;
out[3][1] = 0.0f;
out[3][2] = 0.0f;
out[3][3] = 1.0f;
}
void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z )
{
out[0][0] = x;
out[0][1] = 0.0f;
out[0][2] = 0.0f;
out[0][3] = 0.0f;
out[1][0] = 0.0f;
out[1][1] = y;
out[1][2] = 0.0f;
out[1][3] = 0.0f;
out[2][0] = 0.0f;
out[2][1] = 0.0f;
out[2][2] = z;
out[2][3] = 0.0f;
out[3][0] = 0.0f;
out[3][1] = 0.0f;
out[3][2] = 0.0f;
out[3][3] = 1.0f;
}
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z )
{
matrix4x4 base, temp;
Matrix4x4_Copy( base, out );
Matrix4x4_CreateTranslate( temp, x, y, z );
Matrix4x4_Concat( out, base, temp );
}
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z )
{
matrix4x4 base, temp;
Matrix4x4_Copy( base, out );
Matrix4x4_CreateRotate( temp, angle, x, y, z );
Matrix4x4_Concat( out, base, temp );
}
void Matrix4x4_ConcatScale( matrix4x4 out, float x )
{
matrix4x4 base, temp;
Matrix4x4_Copy( base, out );
Matrix4x4_CreateScale( temp, x );
Matrix4x4_Concat( out, base, temp );
}
void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z )
{
matrix4x4 base, temp;
Matrix4x4_Copy( base, out );
Matrix4x4_CreateScale3( temp, x, y, z );
Matrix4x4_Concat( out, base, temp );
}

405
ref_soft/r_misc.c Normal file
View File

@ -0,0 +1,405 @@
/*
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};
//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];
struct qfrustum_s qfrustum;
/*
================
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
================
*/
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 = RI.vrect.x;
//d_vrecty = RI.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] ) );
}
D_Patch ();
}
/*
===================
R_TransformFrustum
===================
*/
void R_TransformFrustum (void)
{
int i;
vec3_t v, v2;
for (i=0 ; i<4 ; i++)
{
v[0] = qfrustum.screenedge[i].normal[2];
v[1] = -qfrustum.screenedge[i].normal[0];
v[2] = qfrustum.screenedge[i].normal[1];
v2[0] = v[1]*RI.vright[0] + v[2]*RI.vup[0] + v[0]*RI.vforward[0];
v2[1] = v[1]*RI.vright[1] + v[2]*RI.vup[1] + v[0]*RI.vforward[1];
v2[2] = v[1]*RI.vright[2] + v[2]*RI.vup[2] + v[0]*RI.vforward[2];
VectorCopy (v2, qfrustum.view_clipplanes[i].normal);
qfrustum.view_clipplanes[i].dist = DotProduct (tr.modelorg, v2);
}
}
/*
================
TransformVector
================
*/
void TransformVector (vec3_t in, vec3_t out)
{
out[0] = DotProduct(in,RI.vright);
out[1] = DotProduct(in,RI.vup);
out[2] = DotProduct(in,RI.vforward);
}
/*
================
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 = qfrustum.frustum_indexes;
for (i=0 ; i<4 ; i++)
{
for (j=0 ; j<3 ; j++)
{
if (qfrustum.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
qfrustum.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;
float verticalFieldOfView, horizontalFieldOfView, xOrigin, yOrigin;
RI.vrect = *vr;
horizontalFieldOfView = 2*tan((float)RI.fov_x/360.0f * M_PI_F);
verticalFieldOfView = 2*tan((float)RI.fov_y/360.0f * M_PI_F);
RI.fvrectx = (float)RI.vrect.x;
RI.fvrectx_adj = (float)RI.vrect.x - 0.5f;
RI.vrect_x_adj_shift20 = (RI.vrect.x<<20) + (1<<19) - 1;
RI.fvrecty = (float)RI.vrect.y;
RI.fvrecty_adj = (float)RI.vrect.y - 0.5f;
RI.vrectright = RI.vrect.x + RI.vrect.width;
RI.vrectright_adj_shift20 = (RI.vrectright<<20) + (1<<19) - 1;
RI.fvrectright = (float)RI.vrectright;
RI.fvrectright_adj = (float)RI.vrectright - 0.5f;
RI.vrectrightedge = (float)RI.vrectright - 0.99f;
RI.vrectbottom = RI.vrect.y + RI.vrect.height;
RI.fvrectbottom = (float)RI.vrectbottom;
RI.fvrectbottom_adj = (float)RI.vrectbottom - 0.5f;
RI.aliasvrect.x = (int)(RI.vrect.x * r_aliasuvscale);
RI.aliasvrect.y = (int)(RI.vrect.y * r_aliasuvscale);
RI.aliasvrect.width = (int)(RI.vrect.width * r_aliasuvscale);
RI.aliasvrect.height = (int)(RI.vrect.height * r_aliasuvscale);
RI.aliasvrectright = RI.aliasvrect.x +
RI.aliasvrect.width;
RI.aliasvrectbottom = RI.aliasvrect.y +
RI.aliasvrect.height;
xOrigin = XCENTERING;
yOrigin = YCENTERING;
#define PLANE_ANYZ 5
// 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)RI.vrect.width * XCENTERING) +
RI.vrect.x - 0.5f;
aliasxcenter = xcenter * r_aliasuvscale;
ycenter = ((float)RI.vrect.height * YCENTERING) +
RI.vrect.y - 0.5f;
aliasycenter = ycenter * r_aliasuvscale;
xscale = RI.vrect.width / horizontalFieldOfView;
aliasxscale = xscale * r_aliasuvscale;
xscaleinv = 1.0f / xscale;
yscale = xscale;
aliasyscale = yscale * r_aliasuvscale;
yscaleinv = 1.0f / yscale;
//xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView;
//yscaleshrink = xscaleshrink;
// left side clip
qfrustum.screenedge[0].normal[0] = -1.0f / (xOrigin*horizontalFieldOfView);
qfrustum.screenedge[0].normal[1] = 0;
qfrustum.screenedge[0].normal[2] = 1;
qfrustum.screenedge[0].type = PLANE_ANYZ;
// right side clip
qfrustum.screenedge[1].normal[0] =
1.0f / ((1.0f-xOrigin)*horizontalFieldOfView);
qfrustum.screenedge[1].normal[1] = 0;
qfrustum.screenedge[1].normal[2] = 1;
qfrustum.screenedge[1].type = PLANE_ANYZ;
// top side clip
qfrustum.screenedge[2].normal[0] = 0;
qfrustum.screenedge[2].normal[1] = -1.0f / (yOrigin*verticalFieldOfView);
qfrustum.screenedge[2].normal[2] = 1;
qfrustum.screenedge[2].type = PLANE_ANYZ;
// bottom side clip
qfrustum.screenedge[3].normal[0] = 0;
qfrustum.screenedge[3].normal[1] = 1.0f / ((1.0f-yOrigin)*verticalFieldOfView);
qfrustum.screenedge[3].normal[2] = 1;
qfrustum.screenedge[3].type = PLANE_ANYZ;
for (i=0 ; i<4 ; i++)
VectorNormalize (qfrustum.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
}
//tr.framecount++;
// build the transformation matrix for the given view angles
VectorCopy (RI.vieworg, tr.modelorg);
//AngleVectors (RI.viewangles, RI.vforward, RI.vright, RI.vup);
// current viewleaf
if ( RI.drawWorld )
{
RI.viewleaf = gEngfuncs.Mod_PointInLeaf (RI.vieworg, WORLDMODEL->nodes);
r_viewcluster = RI.viewleaf->cluster;
}
// if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) )
// r_dowarp = true;
// else
/*vrect.x = 0;//r_newrefdef.x;
vrect.y = 0;//r_newrefdef.y;
vrect.width = gpGlobals->width;
vrect.height = gpGlobals->height;*/
vrect.x = RI.viewport[0];
vrect.y = RI.viewport[1];
vrect.width = RI.viewport[2];
vrect.height = RI.viewport[3];
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 (RI.vforward, RI.base_vpn);
VectorCopy (RI.vright, RI.base_vright);
VectorCopy (RI.vup, RI.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

308
ref_soft/r_part.c Normal file
View File

@ -0,0 +1,308 @@
/*
cl_part.c - particles and tracers
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 "r_efx.h"
#include "event_flags.h"
#include "entity_types.h"
#include "triangleapi.h"
#include "pm_local.h"
#include "cl_tent.h"
#include "studio.h"
static float gTracerSize[11] = { 1.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
static color24 gTracerColors[] =
{
{ 255, 255, 255 }, // White
{ 255, 0, 0 }, // Red
{ 0, 255, 0 }, // Green
{ 0, 0, 255 }, // Blue
{ 0, 0, 0 }, // Tracer default, filled in from cvars, etc.
{ 255, 167, 17 }, // Yellow-orange sparks
{ 255, 130, 90 }, // Yellowish streaks (garg)
{ 55, 60, 144 }, // Blue egon streak
{ 255, 130, 90 }, // More Yellowish streaks (garg)
{ 255, 140, 90 }, // More Yellowish streaks (garg)
{ 200, 130, 90 }, // More red streaks (garg)
{ 255, 120, 70 }, // Darker red streaks (garg)
};
/*
================
CL_DrawParticles
update particle color, position, free expired and draw it
================
*/
void GAME_EXPORT CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize )
{
particle_t *p;
vec3_t right, up;
color24 *pColor;
int alpha;
float size;
if( !cl_active_particles )
return; // nothing to draw?
//pglEnable( GL_BLEND );
//pglDisable( GL_ALPHA_TEST );
//pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
GL_SetRenderMode( kRenderTransAdd );
GL_Bind( XASH_TEXTURE0, tr.particleTexture );
//pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
//pglDepthMask( GL_FALSE );
for( p = cl_active_particles; p; p = p->next )
{
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
{
size = partsize; // get initial size of particle
// scale up to keep particles from disappearing
size += (p->org[0] - RI.vieworg[0]) * RI.cull_vforward[0];
size += (p->org[1] - RI.vieworg[1]) * RI.cull_vforward[1];
size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2];
if( size < 20.0f ) size = partsize;
else size = partsize + size * 0.002f;
// scale the axes by radius
VectorScale( RI.cull_vright, size, right );
VectorScale( RI.cull_vup, size, up );
p->color = bound( 0, p->color, 255 );
pColor = gEngfuncs.CL_GetPaletteColor( p->color );
alpha = 255 * (p->die - gpGlobals->time) * 16.0f;
if( alpha > 255 || p->type == pt_static )
alpha = 255;
//TriColor4ub( gEngfuncs.LightToTexGamma( pColor->r ),
// gEngfuncs.LightToTexGamma( pColor->g ),
// gEngfuncs.LightToTexGamma( pColor->b ), alpha );
//TriBrightness( alpha / 255.0f );
_TriColor4f(1.0f*alpha/255/255*pColor->r,1.0f*alpha/255/255*pColor->g,1.0f*alpha/255/255* pColor->b,1.0f );
TriBegin( TRI_QUADS );
TriTexCoord2f( 0.0f, 1.0f );
TriVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] );
TriTexCoord2f( 0.0f, 0.0f );
TriVertex3f( p->org[0] + right[0] + up[0], p->org[1] + right[1] + up[1], p->org[2] + right[2] + up[2] );
TriTexCoord2f( 1.0f, 0.0f );
TriVertex3f( p->org[0] + right[0] - up[0], p->org[1] + right[1] - up[1], p->org[2] + right[2] - up[2] );
TriTexCoord2f( 1.0f, 1.0f );
TriVertex3f( p->org[0] - right[0] - up[0], p->org[1] - right[1] - up[1], p->org[2] - right[2] - up[2] );
TriEnd();
r_stats.c_particle_count++;
}
gEngfuncs.CL_ThinkParticle( frametime, p );
}
TriEnd();
//pglDepthMask( GL_TRUE );
}
/*
================
CL_CullTracer
check tracer bbox
================
*/
static qboolean CL_CullTracer( particle_t *p, const vec3_t start, const vec3_t end )
{
vec3_t mins, maxs;
int i;
return false;
/*
// compute the bounding box
for( i = 0; i < 3; i++ )
{
if( start[i] < end[i] )
{
mins[i] = start[i];
maxs[i] = end[i];
}
else
{
mins[i] = end[i];
maxs[i] = start[i];
}
// don't let it be zero sized
if( mins[i] == maxs[i] )
{
maxs[i] += gTracerSize[p->type] * 2.0f;
}
}
// check bbox
return R_CullBox( mins, maxs );*/
}
/*
================
CL_DrawTracers
update tracer color, position, free expired and draw it
================
*/
void GAME_EXPORT CL_DrawTracers( double frametime, particle_t *cl_active_tracers )
{
float scale, atten, gravity;
vec3_t screenLast, screen;
vec3_t start, end, delta;
particle_t *p;
// update tracer color if this is changed
if( FBitSet( tracerred->flags|tracergreen->flags|tracerblue->flags|traceralpha->flags, FCVAR_CHANGED ))
{
color24 *customColors = &gTracerColors[4];
customColors->r = (byte)(tracerred->value * traceralpha->value * 255);
customColors->g = (byte)(tracergreen->value * traceralpha->value * 255);
customColors->b = (byte)(tracerblue->value * traceralpha->value * 255);
ClearBits( tracerred->flags, FCVAR_CHANGED );
ClearBits( tracergreen->flags, FCVAR_CHANGED );
ClearBits( tracerblue->flags, FCVAR_CHANGED );
ClearBits( traceralpha->flags, FCVAR_CHANGED );
}
if( !cl_active_tracers )
return; // nothing to draw?
GL_SetRenderMode( kRenderTransAdd );
if( !TriSpriteTexture( gEngfuncs.GetDefaultSprite( REF_DOT_SPRITE ), 0 ))
return;
//pglEnable( GL_BLEND );
//pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
//pglDisable( GL_ALPHA_TEST );
//pglDepthMask( GL_FALSE );
gravity = frametime * MOVEVARS->gravity;
scale = 1.0 - (frametime * 0.9);
if( scale < 0.0f ) scale = 0.0f;
for( p = cl_active_tracers; p; p = p->next )
{
atten = (p->die - gpGlobals->time);
if( atten > 0.1f ) atten = 0.1f;
VectorScale( p->vel, ( p->ramp * atten ), delta );
VectorAdd( p->org, delta, end );
VectorCopy( p->org, start );
if( !CL_CullTracer( p, start, end ))
{
vec3_t verts[4], tmp2;
vec3_t tmp, normal;
color24 *pColor;
short alpha = p->packedColor;
// Transform point into screen space
TriWorldToScreen( start, screen );
TriWorldToScreen( end, screenLast );
// build world-space normal to screen-space direction vector
VectorSubtract( screen, screenLast, tmp );
// we don't need Z, we're in screen space
tmp[2] = 0;
VectorNormalize( tmp );
// build point along noraml line (normal is -y, x)
VectorScale( RI.cull_vup, tmp[0] * gTracerSize[p->type], normal );
VectorScale( RI.cull_vright, -tmp[1] * gTracerSize[p->type], tmp2 );
VectorSubtract( normal, tmp2, normal );
// compute four vertexes
VectorSubtract( start, normal, verts[0] );
VectorAdd( start, normal, verts[1] );
VectorAdd( verts[0], delta, verts[2] );
VectorAdd( verts[1], delta, verts[3] );
if( p->color > sizeof( gTracerColors ) / sizeof( color24 ) )
{
gEngfuncs.Con_Printf( S_ERROR "UserTracer with color > %d\n", sizeof( gTracerColors ) / sizeof( color24 ));
p->color = 0;
}
pColor = &gTracerColors[p->color];
//TriColor4ub( pColor->r, pColor->g, pColor->b, p->packedColor );
_TriColor4f(1.0f*alpha/255/255*pColor->r,1.0f*alpha/255/255*pColor->g,1.0f*alpha/255/255* pColor->b,1.0f );
TriBegin( TRI_QUADS );
TriTexCoord2f( 0.0f, 0.8f );
TriVertex3fv( verts[2] );
TriTexCoord2f( 1.0f, 0.8f );
TriVertex3fv( verts[3] );
TriTexCoord2f( 1.0f, 0.0f );
TriVertex3fv( verts[1] );
TriTexCoord2f( 0.0f, 0.0f );
TriVertex3fv( verts[0] );
TriEnd();
}
// evaluate position
VectorMA( p->org, frametime, p->vel, p->org );
if( p->type == pt_grav )
{
p->vel[0] *= scale;
p->vel[1] *= scale;
p->vel[2] -= gravity;
p->packedColor = 255 * (p->die - gpGlobals->time) * 2;
if( p->packedColor > 255 ) p->packedColor = 255;
}
else if( p->type == pt_slowgrav )
{
p->vel[2] = gravity * 0.05;
}
}
//pglDepthMask( GL_TRUE );
}
/*
===============
CL_DrawParticlesExternal
allow to draw effects from custom renderer
===============
*/
void GAME_EXPORT CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime )
{
ref_instance_t oldRI = RI;
memcpy( &oldRI, &RI, sizeof( ref_instance_t ));
R_SetupRefParams( rvp );
R_SetupFrustum();
// R_SetupGL( false ); // don't touch GL-states
// setup PVS for frame
memcpy( RI.visbytes, tr.visbytes, gpGlobals->visbytes );
tr.frametime = frametime;
gEngfuncs.CL_DrawEFX( frametime, trans_pass );
// restore internal state
memcpy( &RI, &oldRI, sizeof( ref_instance_t ));
}

2009
ref_soft/r_polyse.c Normal file

File diff suppressed because it is too large Load Diff

870
ref_soft/r_rast.c Normal file
View File

@ -0,0 +1,870 @@
/*
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 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, tr.modelorg, local);
TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
lzi0 = 1.0f / transformed[2];
// FIXME: build x/yscale into transform?
scale = xscale * lzi0;
u0 = (xcenter + scale*transformed[0]);
if (u0 < RI.fvrectx_adj)
u0 = RI.fvrectx_adj;
if (u0 > RI.fvrectright_adj)
u0 = RI.fvrectright_adj;
scale = yscale * lzi0;
v0 = (ycenter - scale*transformed[1]);
if (v0 < RI.fvrecty_adj)
v0 = RI.fvrecty_adj;
if (v0 > RI.fvrectbottom_adj)
v0 = RI.fvrectbottom_adj;
ceilv0 = (int) ceil(v0);
}
world = &pv1->position[0];
// transform and project
VectorSubtract (world, tr.modelorg, local);
TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
r_lzi1 = 1.0f / transformed[2];
scale = xscale * r_lzi1;
r_u1 = (xcenter + scale*transformed[0]);
if (r_u1 < RI.fvrectx_adj)
r_u1 = RI.fvrectx_adj;
if (r_u1 > RI.fvrectright_adj)
r_u1 = RI.fvrectright_adj;
scale = yscale * r_lzi1;
r_v1 = (ycenter - scale*transformed[1]);
if (r_v1 < RI.fvrecty_adj)
r_v1 = RI.fvrecty_adj;
if (r_v1 > RI.fvrectbottom_adj)
r_v1 = RI.fvrectbottom_adj;
if (r_lzi1 > lzi0)
lzi0 = r_lzi1;
if (lzi0 > r_nearzi) // for mipmap finding
r_nearzi = lzi0;
// for right edges, all we want is the effect on 1/z
if (r_nearzionly)
return;
r_emitted = 1;
r_ceilv1 = (int) ceil(r_v1);
// create the edge
if (ceilv0 == r_ceilv1 || ceilv0 < 0 )
{
// we cache unclipped horizontal edges as fully clipped
if (cacheoffset != 0x7FFFFFFF)
{
cacheoffset = FULLY_CLIPPED_CACHED |
(tr.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;
if( v < 0 || v > MAXHEIGHT )
{
gEngfuncs.Con_Printf( S_ERROR "trailing edge overflow : %d\n", v );
return;
}
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;
if( v < 0 || v > MAXHEIGHT )
{
gEngfuncs.Con_Printf( S_ERROR "leading edge overflow : %d\n", v );
return;
}
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?
/*int r = (gpGlobals->width<<20) + (1<<19) - 1;
int x = (1<<20) + (1<<19) - 1;
if (edge->u < x)
edge->u = x;
if (edge->u > r)
edge->u = r;*/
if (edge->u < RI.vrect_x_adj_shift20)
edge->u = RI.vrect_x_adj_shift20;
if (edge->u > RI.vrectright_adj_shift20)
edge->u = RI.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 |
(tr.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->flags & (SURF_DRAWTURB|SURF_TRANSPARENT))
{
//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->flags & SURF_DRAWSKY )
{
//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)
{
qfrustum.view_clipplanes[i].next = pclip;
pclip = &qfrustum.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) ==
tr.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) ==
tr.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, qfrustum.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.0f / (pplane->dist - DotProduct (tr.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)
{
qfrustum.view_clipplanes[i].next = pclip;
pclip = &qfrustum.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, qfrustum.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.0f / (pplane->dist - DotProduct (tr.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++;
}

1420
ref_soft/r_scan.c Normal file

File diff suppressed because it is too large Load Diff

1090
ref_soft/r_sprite.c Normal file

File diff suppressed because it is too large Load Diff

3771
ref_soft/r_studio.c Normal file

File diff suppressed because it is too large Load Diff

1431
ref_soft/r_surf.c Normal file

File diff suppressed because it is too large Load Diff

294
ref_soft/r_trialias.c Normal file
View File

@ -0,0 +1,294 @@
#include "r_local.h"
// not really draw alias models here, but use this to draw triangles
affinetridesc_t r_affinetridesc;
int r_aliasblendcolor;
float aliastransform[3][4];
float aliasworldtransform[3][4];
float aliasoldworldtransform[3][4];
float s_ziscale;
static vec3_t s_alias_forward, s_alias_right, s_alias_up;
#define NUMVERTEXNORMALS 162
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
void R_AliasSetUpTransform (void);
void R_AliasTransformVector (vec3_t in, vec3_t out, float m[3][4] );
void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv);
void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv );
/*
================
R_AliasCheckBBox
================
*/
#define BBOX_TRIVIAL_ACCEPT 0
#define BBOX_MUST_CLIP_XY 1
#define BBOX_MUST_CLIP_Z 2
#define BBOX_TRIVIAL_REJECT 8
/*
================
R_AliasTransformVector
================
*/
void R_AliasTransformVector(vec3_t in, vec3_t out, float xf[3][4] )
{
out[0] = DotProduct(in, xf[0]) + xf[0][3];
out[1] = DotProduct(in, xf[1]) + xf[1][3];
out[2] = DotProduct(in, xf[2]) + xf[2][3];
}
void VectorInverse (vec3_t v)
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
/*
================
R_SetUpWorldTransform
================
*/
void R_SetUpWorldTransform (void)
{
int i;
static float viewmatrix[3][4];
vec3_t angles;
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: should use a look-up table
// TODO: could cache lazily, stored in the entity
//
s_ziscale = (float)0x8000 * (float)0x10000;
angles[ROLL] = 0;
angles[PITCH] = 0;
angles[YAW] = 0;
AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up );
// TODO: can do this with simple matrix rearrangement
memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) );
memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) );
for (i=0 ; i<3 ; i++)
{
aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i];
aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i];
aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i];
}
aliasworldtransform[0][3] = -RI.vieworg[0];
aliasworldtransform[1][3] = -RI.vieworg[1];
aliasworldtransform[2][3] = -RI.vieworg[2];
//aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0];
//aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1];
//aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]-r_origin[2];
// FIXME: can do more efficiently than full concatenation
// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) );
// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
// TODO: should be global, set when vright, etc., set
VectorCopy (RI.vright, viewmatrix[0]);
VectorCopy (RI.vup, viewmatrix[1]);
VectorInverse (viewmatrix[1]);
//VectorScale(viewmatrix[1], -1, viewmatrix[1]);
VectorCopy (RI.vforward, viewmatrix[2]);
viewmatrix[0][3] = 0;
viewmatrix[1][3] = 0;
viewmatrix[2][3] = 0;
// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) );
//R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform);
Matrix3x4_ConcatTransforms(aliastransform, viewmatrix, aliasworldtransform );
aliasworldtransform[0][3] = 0;
aliasworldtransform[1][3] = 0;
aliasworldtransform[2][3] = 0;
//aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0];
//aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1];
//aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2];
}
/*
================
R_AliasSetUpTransform
================
*/
void R_AliasSetUpTransform (void)
{
int i;
static float viewmatrix[3][4];
vec3_t angles;
// TODO: should really be stored with the entity instead of being reconstructed
// TODO: should use a look-up table
// TODO: could cache lazily, stored in the entity
//
s_ziscale = (float)0x8000 * (float)0x10000;
angles[ROLL] = RI.currententity->angles[ROLL];
angles[PITCH] = RI.currententity->angles[PITCH];
angles[YAW] = RI.currententity->angles[YAW];
AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up );
// TODO: can do this with simple matrix rearrangement
memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) );
memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) );
for (i=0 ; i<3 ; i++)
{
aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i];
aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i];
aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i];
}
aliasworldtransform[0][3] = RI.currententity->origin[0]-RI.vieworg[0];
aliasworldtransform[1][3] = RI.currententity->origin[1]-RI.vieworg[1];
aliasworldtransform[2][3] = RI.currententity->origin[2]-RI.vieworg[2];
//aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0];
//aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1];
//aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]-r_origin[2];
// FIXME: can do more efficiently than full concatenation
// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) );
// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
// TODO: should be global, set when vright, etc., set
VectorCopy (RI.vright, viewmatrix[0]);
VectorCopy (RI.vup, viewmatrix[1]);
VectorInverse (viewmatrix[1]);
//VectorScale(viewmatrix[1], -1, viewmatrix[1]);
VectorCopy (RI.vforward, viewmatrix[2]);
viewmatrix[0][3] = 0;
viewmatrix[1][3] = 0;
viewmatrix[2][3] = 0;
// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) );
//R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform);
Matrix3x4_ConcatTransforms(aliastransform, viewmatrix, aliasworldtransform );
aliasworldtransform[0][3] = RI.currententity->origin[0];
aliasworldtransform[1][3] = RI.currententity->origin[1];
aliasworldtransform[2][3] = RI.currententity->origin[2];
//aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0];
//aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1];
//aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2];
}
/*
================
R_AliasProjectAndClipTestFinalVert
================
*/
void R_AliasProjectAndClipTestFinalVert( finalvert_t *fv )
{
float zi;
float x, y, z;
// project points
x = fv->xyz[0];
y = fv->xyz[1];
z = fv->xyz[2];
zi = 1.0f / z;
fv->zi = zi * s_ziscale;
fv->u = (x * aliasxscale * zi) + aliasxcenter;
fv->v = (y * aliasyscale * zi) + aliasycenter;
if (fv->u < RI.aliasvrect.x)
fv->flags |= ALIAS_LEFT_CLIP;
if (fv->v < RI.aliasvrect.y)
fv->flags |= ALIAS_TOP_CLIP;
if (fv->u > RI.aliasvrectright)
fv->flags |= ALIAS_RIGHT_CLIP;
if (fv->v > RI.aliasvrectbottom)
fv->flags |= ALIAS_BOTTOM_CLIP;
}
void R_AliasWorldToScreen( const float *v, float *out )
{
out[0] = DotProduct(v, aliastransform[0]) + aliastransform[0][3];
out[1] = DotProduct(v, aliastransform[1]) + aliastransform[1][3];
out[2] = DotProduct(v, aliastransform[2]) + aliastransform[2][3];
}
void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t )
{
vec3_t v = {x, y, z};
fv->xyz[0] = DotProduct(v, aliastransform[0]) + aliastransform[0][3];
fv->xyz[1] = DotProduct(v, aliastransform[1]) + aliastransform[1][3];
fv->xyz[2] = DotProduct(v, aliastransform[2]) + aliastransform[2][3];
fv->flags = 0;
fv->l = light;
if ( fv->xyz[2] < ALIAS_Z_CLIP_PLANE )
{
fv->flags |= ALIAS_Z_CLIP;
}
else
{
R_AliasProjectAndClipTestFinalVert( fv );
}
fv->s = s << 16;
fv->t = t << 16;
}
void R_RenderTriangle( finalvert_t *fv1, finalvert_t *fv2, finalvert_t *fv3 )
{
if ( fv1->flags & fv2->flags & fv3->flags )
return ; // completely clipped
if ( ! (fv1->flags | fv2->flags | fv3->flags) )
{ // totally unclipped
aliastriangleparms.a = fv1;
aliastriangleparms.b = fv2;
aliastriangleparms.c = fv3;
R_DrawTriangle();
}
else
{ // partially clipped
R_AliasClipTriangle (fv1, fv2, fv3);
}
}

505
ref_soft/r_triapi.c Normal file
View File

@ -0,0 +1,505 @@
/*
gl_triapi.c - TriAPI draw methods
Copyright (C) 2011 Uncle Mike
Copyright (C) 2019 a1batross
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 "const.h"
static struct
{
int renderMode; // override kRenderMode from TriAPI
vec4_t triRGBA;
} ds;
finalvert_t triv[3];
int vertcount, n;
int mode;
short s,t;
uint light;
/*
===============================================================
TRIAPI IMPLEMENTATION
===============================================================
*/
/*
=============
TriRenderMode
set rendermode
=============
*/
void GAME_EXPORT TriRenderMode( int mode )
{
ds.renderMode = vid.rendermode = mode;
#if 0
switch( mode )
{
case kRenderNormal:
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglDisable( GL_BLEND );
pglDepthMask( GL_TRUE );
break;
case kRenderTransAlpha:
pglEnable( GL_BLEND );
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
pglDepthMask( GL_FALSE );
break;
case kRenderTransColor:
case kRenderTransTexture:
pglEnable( GL_BLEND );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
break;
case kRenderGlow:
case kRenderTransAdd:
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
pglEnable( GL_BLEND );
pglDepthMask( GL_FALSE );
break;
}
#endif
}
/*
=============
TriBegin
begin triangle sequence
=============
*/
void GAME_EXPORT TriBegin( int mode1 )
{
#if 0
switch( mode )
{
case TRI_POINTS:
mode = GL_POINTS;
break;
case TRI_TRIANGLES:
mode = GL_TRIANGLES;
break;
case TRI_TRIANGLE_FAN:
mode = GL_TRIANGLE_FAN;
break;
case TRI_QUADS:
mode = GL_QUADS;
break;
case TRI_LINES:
mode = GL_LINES;
break;
case TRI_TRIANGLE_STRIP:
mode = GL_TRIANGLE_STRIP;
break;
case TRI_QUAD_STRIP:
mode = GL_QUAD_STRIP;
break;
case TRI_POLYGON:
default:
mode = GL_POLYGON;
break;
}
pglBegin( mode );
#endif
if( mode1 == TRI_QUADS )
mode1 = TRI_TRIANGLE_FAN;
mode = mode1;
vertcount = n = vertcount = 0;
}
/*
=============
TriEnd
draw triangle sequence
=============
*/
void GAME_EXPORT TriEnd( void )
{
//if( vertcount == 3 )
//pglEnd( );
}
/*
=============
_TriColor4f
=============
*/
void GAME_EXPORT _TriColor4f( float rr, float gg, float bb, float aa )
{
//pglColor4f( r, g, b, a );
unsigned short r,g,b;
unsigned int major, minor;
if( vid.rendermode == kRenderTransAdd || vid.rendermode == kRenderGlow )
rr *= aa, gg *= aa, bb *= aa;
//gEngfuncs.Con_Printf("%d\n", vid.alpha);
light = (rr + gg + bb) * 31 / 3;
if( light > 31 )
light = 31;
if( !vid.is2d && vid.rendermode == kRenderNormal )
return;
vid.alpha = aa * 7;
if( vid.alpha > 7 )
vid.alpha = 7;
if( rr == 1 && gg == 1 && bb == 1 )
{
vid.color = COLOR_WHITE;
return;
}
r = rr * 31, g = gg * 63, b = bb * 31;
if( r > 31 )
r = 31;
if( g > 63 )
g = 63;
if( b > 31 )
b = 31;
major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2)));
// save minor GBRGBRGB
minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0);
vid.color = major << 8 | (minor & 0xFF);
}
/*
=============
TriColor4ub
=============
*/
void TriColor4ub( byte r, byte g, byte b, byte a )
{
ds.triRGBA[0] = r * (1.0f / 255.0f);
ds.triRGBA[1] = g * (1.0f / 255.0f);
ds.triRGBA[2] = b * (1.0f / 255.0f);
ds.triRGBA[3] = a * (1.0f / 255.0f);
_TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f );
}
/*
=============
TriColor4ub
=============
*/
void GAME_EXPORT _TriColor4ub( byte r, byte g, byte b, byte a )
{
_TriColor4f( r * (1.0f / 255.0f),
g * (1.0f / 255.0f),
b * (1.0f / 255.0f),
a * (1.0f / 255.0f));
}
/*
=================
TriColor4f
=================
*/
void TriColor4f( float r, float g, float b, float a )
{
//if( a < 0.5 )
// a = 1;
if( ds.renderMode == kRenderTransAlpha )
TriColor4ub( r * 255.0f, g * 255.0f, b * 255.0f, a * 255.0f );
else _TriColor4f( r * a, g * a, b * a, 1.0 );
ds.triRGBA[0] = r;
ds.triRGBA[1] = g;
ds.triRGBA[2] = b;
ds.triRGBA[3] = a;
}
/*
=============
TriTexCoord2f
=============
*/
void GAME_EXPORT TriTexCoord2f( volatile float u, volatile float v )
{
volatile double u1 = 0, v1 = 0;
u = fmodf(u, 10);
v = fmodf(v, 10);
if( u < 1000 && u > -1000 )
u1 = u;
if( v < 1000 && v > -1000 )
v1 = v;
while( u1 < 0 )
u1 = u1 + 1;
while( v1 < 0 )
v1 = v1 + 1;
while( u1 > 1 )
u1 = u1 - 1;
while( v1 > 1 )
v1 = v1 - 1;
s = r_affinetridesc.skinwidth * bound(0.01,u1,0.99);
t = r_affinetridesc.skinheight * bound(0.01,v1,0.99);
}
/*
=============
TriVertex3fv
=============
*/
void GAME_EXPORT TriVertex3fv( const float *v )
{
//pglVertex3fv( v );
TriVertex3f( v[0], v[1], v[2] );
}
/*
=============
TriVertex3f
=============
*/
void GAME_EXPORT TriVertex3f( float x, float y, float z )
{
if( mode == TRI_TRIANGLES )
{
R_SetupFinalVert( &triv[vertcount], x, y, z, light << 8,s,t);
vertcount++;
if( vertcount == 3 )
{
R_RenderTriangle( &triv[0], &triv[1], &triv[2] );
//R_RenderTriangle( &triv[2], &triv[1], &triv[0] );
vertcount = 0;
}
}
if( mode == TRI_TRIANGLE_FAN )
{
R_SetupFinalVert( &triv[vertcount], x, y, z, light << 8,s,t);
vertcount++;
if( vertcount >= 3 )
{
R_RenderTriangle( &triv[0], &triv[1], &triv[2] );
//R_RenderTriangle( &triv[2], &triv[1], &triv[0] );
triv[1] = triv[2];
vertcount = 2;
}
}
if( mode == TRI_TRIANGLE_STRIP )
{
R_SetupFinalVert( &triv[n], x, y, z, light << 8,s,t);
n++;
vertcount++;
if( n == 3 )
n = 0;
if (vertcount >= 3)
{
if( vertcount & 1 )
R_RenderTriangle( &triv[0], &triv[1], &triv[2] );
else
R_RenderTriangle( &triv[2], &triv[1], &triv[0] );
}
}
#if 0
if( mode == TRI_TRIANGLE_STRIP )
{
R_SetupFinalVert( &triv[vertcount], x, y, z, 0,s,t);
vertcount++;
if( vertcount == 3 )
{
R_RenderTriangle( triv );
finalvert_t fv = triv[0];
triv[0] = triv[2];
triv[2] = fv;
R_RenderTriangle( triv );
fv = triv[0];
triv[0] = triv[2];
triv[2] = fv;
triv[0] = triv[1];
triv[1] = triv[2];
vertcount = 2;
}
}
#endif
}
/*
=============
TriWorldToScreen
convert world coordinates (x,y,z) into screen (x, y)
=============
*/
int GAME_EXPORT TriWorldToScreen( const float *world, float *screen )
{
int retval;
retval = R_WorldToScreen( world, screen );
screen[0] = 0.5f * screen[0] * (float)RI.viewport[2];
screen[1] = -0.5f * screen[1] * (float)RI.viewport[3];
screen[0] += 0.5f * (float)RI.viewport[2];
screen[1] += 0.5f * (float)RI.viewport[3];
return retval;
}
/*
=============
TriSpriteTexture
bind current texture
=============
*/
int TriSpriteTexture( model_t *pSpriteModel, int frame )
{
int gl_texturenum;
if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) == 0 )
return 0;
if( gl_texturenum <= 0 || gl_texturenum > MAX_TEXTURES )
gl_texturenum = tr.defaultTexture;
GL_Bind( XASH_TEXTURE0, gl_texturenum );
return 1;
}
/*
=============
TriFog
enables global fog on the level
=============
*/
void GAME_EXPORT TriFog( float flFogColor[3], float flStart, float flEnd, int bOn )
{
#if 0
// overrided by internal fog
if( RI.fogEnabled ) return;
RI.fogCustom = bOn;
// check for invalid parms
if( flEnd <= flStart )
{
RI.fogCustom = false;
pglDisable( GL_FOG );
return;
}
if( RI.fogCustom )
pglEnable( GL_FOG );
else pglDisable( GL_FOG );
// copy fog params
RI.fogColor[0] = flFogColor[0] / 255.0f;
RI.fogColor[1] = flFogColor[1] / 255.0f;
RI.fogColor[2] = flFogColor[2] / 255.0f;
RI.fogStart = flStart;
RI.fogColor[3] = 1.0f;
RI.fogDensity = 0.0f;
RI.fogSkybox = true;
RI.fogEnd = flEnd;
pglFogi( GL_FOG_MODE, GL_LINEAR );
pglFogfv( GL_FOG_COLOR, RI.fogColor );
pglFogf( GL_FOG_START, RI.fogStart );
pglFogf( GL_FOG_END, RI.fogEnd );
pglHint( GL_FOG_HINT, GL_NICEST );
#endif
}
/*
=============
TriGetMatrix
very strange export
=============
*/
void GAME_EXPORT TriGetMatrix( const int pname, float *matrix )
{
//pglGetFloatv( pname, matrix );
}
/*
=============
TriForParams
=============
*/
void GAME_EXPORT TriFogParams( float flDensity, int iFogSkybox )
{
//RI.fogDensity = flDensity;
//RI.fogSkybox = iFogSkybox;
}
/*
=============
TriCullFace
=============
*/
void GAME_EXPORT TriCullFace( TRICULLSTYLE mode )
{
#if 0
int glMode;
switch( mode )
{
case TRI_FRONT:
glMode = GL_FRONT;
break;
default:
glMode = GL_NONE;
break;
}
GL_Cull( mode );
#endif
}
/*
=============
TriBrightness
=============
*/
void TriBrightness( float brightness )
{
float r, g, b;
//if( brightness < 0.5 )
// brightness = 1; //0.5;
//ds.triRGBA[3] = 1;
r = ds.triRGBA[0] * ds.triRGBA[3] * brightness;
g = ds.triRGBA[1] * ds.triRGBA[3] * brightness;
b = ds.triRGBA[2] * ds.triRGBA[3] * brightness;
_TriColor4f( r, g, b, 1.0f );
}

225
ref_soft/r_vgui.c Normal file
View File

@ -0,0 +1,225 @@
/*
gl_vgui.c - OpenGL vgui draw methods
Copyright (C) 2011 Uncle Mike
Copyright (C) 2019 a1batross
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"
#define VGUI_MAX_TEXTURES ( MAX_TEXTURES / 2 ) // a half of total textures count
static int g_textures[VGUI_MAX_TEXTURES];
static int g_textureId = 0;
static int g_iBoundTexture;
/*
================
VGUI_DrawInit
Startup VGUI backend
================
*/
void GAME_EXPORT VGUI_DrawInit( void )
{
memset( g_textures, 0, sizeof( g_textures ));
g_textureId = g_iBoundTexture = 0;
}
/*
================
VGUI_DrawShutdown
Release all textures
================
*/
void GAME_EXPORT VGUI_DrawShutdown( void )
{
int i;
for( i = 1; i < g_textureId; i++ )
{
GL_FreeTexture( g_textures[i] );
}
}
/*
================
VGUI_GenerateTexture
generate unique texture number
================
*/
int GAME_EXPORT VGUI_GenerateTexture( void )
{
if( ++g_textureId >= VGUI_MAX_TEXTURES )
gEngfuncs.Host_Error( "VGUI_GenerateTexture: VGUI_MAX_TEXTURES limit exceeded\n" );
return g_textureId;
}
/*
================
VGUI_UploadTexture
Upload texture into video memory
================
*/
void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
{
rgbdata_t r_image;
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
gEngfuncs.Con_DPrintf( S_ERROR "VGUI_UploadTexture: bad texture %i. Ignored\n", id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
memset( &r_image, 0, sizeof( r_image ));
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = r_image.width * r_image.height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = (byte *)buffer;
g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
}
/*
================
VGUI_CreateTexture
Create empty rgba texture and upload them into video memory
================
*/
void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
{
rgbdata_t r_image;
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
gEngfuncs.Con_Reportf( S_ERROR "VGUI_CreateTexture: bad texture %i. Ignored\n", id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
memset( &r_image, 0, sizeof( r_image ));
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = r_image.width * r_image.height * 4;
r_image.flags = IMAGE_HAS_ALPHA;
r_image.buffer = NULL;
g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE|TF_NEAREST );
g_iBoundTexture = id;
}
void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == tr.whiteTexture )
{
gEngfuncs.Con_Reportf( S_ERROR "VGUI_UploadTextureBlock: bad texture %i. Ignored\n", id );
return;
}
//pglTexSubImage2D( GL_TEXTURE_2D, 0, drawX, drawY, blockWidth, blockHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba );
g_iBoundTexture = id;
}
void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor )
{
}
void GAME_EXPORT VGUI_SetupDrawingText( int *pColor )
{
}
void GAME_EXPORT VGUI_SetupDrawingImage( int *pColor )
{
}
void GAME_EXPORT VGUI_BindTexture( int id )
{
if( id > 0 && id < VGUI_MAX_TEXTURES && g_textures[id] )
{
GL_Bind( XASH_TEXTURE0, g_textures[id] );
g_iBoundTexture = id;
}
else
{
// NOTE: same as bogus index 2700 in GoldSrc
id = g_iBoundTexture = 1;
GL_Bind( XASH_TEXTURE0, g_textures[id] );
}
}
/*
================
VGUI_GetTextureSizes
returns wide and tall for currently binded texture
================
*/
void GAME_EXPORT VGUI_GetTextureSizes( int *width, int *height )
{
image_t *glt;
int texnum;
if( g_iBoundTexture )
texnum = g_textures[g_iBoundTexture];
else texnum = tr.defaultTexture;
glt = R_GetTexture( texnum );
if( width ) *width = glt->srcWidth;
if( height ) *height = glt->srcHeight;
}
/*
================
VGUI_EnableTexture
disable texturemode for fill rectangle
================
*/
void GAME_EXPORT VGUI_EnableTexture( qboolean enable )
{
}
/*
================
VGUI_DrawQuad
generic method to fill rectangle
================
*/
void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
{
int width, height;
float xscale, yscale;
gEngfuncs.CL_GetScreenInfo( &width, &height );
xscale = gpGlobals->width / (float)width;
yscale = gpGlobals->height / (float)height;
ASSERT( ul != NULL && lr != NULL );
}

49
ref_soft/wscript Normal file
View File

@ -0,0 +1,49 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
from waflib import Logs
import os
top = '.'
def options(opt):
# stub
return
def configure(conf):
# check for dedicated server build
if conf.options.DEDICATED:
return
if conf.options.SUPPORT_BSP2_FORMAT:
conf.env.append_unique('DEFINES', 'SUPPORT_BSP2_FORMAT')
conf.env.append_unique('DEFINES', 'REF_DLL')
def build(bld):
if bld.env.DEDICATED:
return
libs = [ 'public', 'M' ]
source = bld.path.ant_glob(['*.c'])
includes = ['.',
'../engine',
'../engine/common',
'../engine/server',
'../engine/client',
'../public',
'../common',
'../pm_shared' ]
bld.shlib(
source = source,
target = 'ref_soft',
features = 'c',
includes = includes,
use = libs,
install_path = bld.env.LIBDIR,
subsystem = bld.env.MSVC_SUBSYSTEM
)