mirror of
https://github.com/YGGverse/xash3d-fwgs.git
synced 2025-03-13 06:21:08 +00:00
Add 'ref_soft/' from commit '9045657352c7dfd3622cdf2b69462ca33f4262ee'
git-subtree-dir: ref_soft git-subtree-mainline: 89ca0dec5e6914fb6540f1cd6ecc465913a47952 git-subtree-split: 9045657352c7dfd3622cdf2b69462ca33f4262ee
This commit is contained in:
commit
7429a6bc8a
1077
ref_soft/adivtab.h
Normal file
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
323
ref_soft/r_aclip.c
Normal 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
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
965
ref_soft/r_bsp.c
Normal 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
600
ref_soft/r_context.c
Normal 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
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
428
ref_soft/r_draw.c
Normal 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
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
771
ref_soft/r_glblit.c
Normal 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
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
501
ref_soft/r_light.c
Normal 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
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
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
267
ref_soft/r_math.c
Normal 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
405
ref_soft/r_misc.c
Normal 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
308
ref_soft/r_part.c
Normal 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
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
870
ref_soft/r_rast.c
Normal 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
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
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
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
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
294
ref_soft/r_trialias.c
Normal 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
505
ref_soft/r_triapi.c
Normal 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
225
ref_soft/r_vgui.c
Normal 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
49
ref_soft/wscript
Normal 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
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user