?? r_alias.c
字號:
/*
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_alias.c: routines for setting up to draw alias models
/*
** use a real variable to control lerping
*/
#include "r_local.h"
#define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the
// need for inner-loop light clamping
//PGM
extern byte iractive;
//PGM
int r_amodels_drawn;
affinetridesc_t r_affinetridesc;
vec3_t r_plightvec;
vec3_t r_lerped[1024];
vec3_t r_lerp_frontv, r_lerp_backv, r_lerp_move;
int r_ambientlight;
int r_aliasblendcolor;
float r_shadelight;
daliasframe_t *r_thisframe, *r_lastframe;
dmdl_t *s_pmdl;
float aliastransform[3][4];
float aliasworldtransform[3][4];
float aliasoldworldtransform[3][4];
static 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_AliasSetUpLerpData( dmdl_t *pmdl, float backlerp );
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 );
void R_AliasLerpFrames( dmdl_t *paliashdr, float backlerp );
/*
================
R_AliasCheckBBox
================
*/
typedef struct {
int index0;
int index1;
} aedge_t;
static aedge_t aedges[12] = {
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 5}, {1, 4}, {2, 7}, {3, 6}
};
#define BBOX_TRIVIAL_ACCEPT 0
#define BBOX_MUST_CLIP_XY 1
#define BBOX_MUST_CLIP_Z 2
#define BBOX_TRIVIAL_REJECT 8
/*
** R_AliasCheckFrameBBox
**
** Checks a specific alias frame bounding box
*/
unsigned long R_AliasCheckFrameBBox( daliasframe_t *frame, float worldxf[3][4] )
{
unsigned long aggregate_and_clipcode = ~0U,
aggregate_or_clipcode = 0;
int i;
vec3_t mins, maxs;
vec3_t transformed_min, transformed_max;
qboolean zclipped = false, zfullyclipped = true;
float minz = 9999.0F;
/*
** get the exact frame bounding box
*/
for (i=0 ; i<3 ; i++)
{
mins[i] = frame->translate[i];
maxs[i] = mins[i] + frame->scale[i]*255;
}
/*
** transform the min and max values into view space
*/
R_AliasTransformVector( mins, transformed_min, aliastransform );
R_AliasTransformVector( maxs, transformed_max, aliastransform );
if ( transformed_min[2] >= ALIAS_Z_CLIP_PLANE )
zfullyclipped = false;
if ( transformed_max[2] >= ALIAS_Z_CLIP_PLANE )
zfullyclipped = false;
if ( zfullyclipped )
{
return BBOX_TRIVIAL_REJECT;
}
if ( zclipped )
{
return ( BBOX_MUST_CLIP_XY | BBOX_MUST_CLIP_Z );
}
/*
** build a transformed bounding box from the given min and max
*/
for ( i = 0; i < 8; i++ )
{
int j;
vec3_t tmp, transformed;
unsigned long clipcode = 0;
if ( i & 1 )
tmp[0] = mins[0];
else
tmp[0] = maxs[0];
if ( i & 2 )
tmp[1] = mins[1];
else
tmp[1] = maxs[1];
if ( i & 4 )
tmp[2] = mins[2];
else
tmp[2] = maxs[2];
R_AliasTransformVector( tmp, transformed, worldxf );
for ( j = 0; j < 4; j++ )
{
float dp = DotProduct( transformed, view_clipplanes[j].normal );
if ( ( dp - view_clipplanes[j].dist ) < 0.0F )
clipcode |= 1 << j;
}
aggregate_and_clipcode &= clipcode;
aggregate_or_clipcode |= clipcode;
}
if ( aggregate_and_clipcode )
{
return BBOX_TRIVIAL_REJECT;
}
if ( !aggregate_or_clipcode )
{
return BBOX_TRIVIAL_ACCEPT;
}
return BBOX_MUST_CLIP_XY;
}
qboolean R_AliasCheckBBox (void)
{
unsigned long ccodes[2] = { 0, 0 };
ccodes[0] = R_AliasCheckFrameBBox( r_thisframe, aliasworldtransform );
/*
** non-lerping model
*/
if ( currententity->backlerp == 0 )
{
if ( ccodes[0] == BBOX_TRIVIAL_ACCEPT )
return BBOX_TRIVIAL_ACCEPT;
else if ( ccodes[0] & BBOX_TRIVIAL_REJECT )
return BBOX_TRIVIAL_REJECT;
else
return ( ccodes[0] & ~BBOX_TRIVIAL_REJECT );
}
ccodes[1] = R_AliasCheckFrameBBox( r_lastframe, aliasoldworldtransform );
if ( ( ccodes[0] | ccodes[1] ) == BBOX_TRIVIAL_ACCEPT )
return BBOX_TRIVIAL_ACCEPT;
else if ( ( ccodes[0] & ccodes[1] ) & BBOX_TRIVIAL_REJECT )
return BBOX_TRIVIAL_REJECT;
else
return ( ccodes[0] | ccodes[1] ) & ~BBOX_TRIVIAL_REJECT;
}
/*
================
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];
}
/*
================
R_AliasPreparePoints
General clipped case
================
*/
typedef struct
{
int num_points;
dtrivertx_t *last_verts; // verts from the last frame
dtrivertx_t *this_verts; // verts from this frame
finalvert_t *dest_verts; // destination for transformed verts
} aliasbatchedtransformdata_t;
aliasbatchedtransformdata_t aliasbatchedtransformdata;
void R_AliasPreparePoints (void)
{
int i;
dstvert_t *pstverts;
dtriangle_t *ptri;
finalvert_t *pfv[3];
finalvert_t finalverts[MAXALIASVERTS +
((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 3];
finalvert_t *pfinalverts;
//PGM
iractive = (r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE);
// iractive = 0;
// if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
// iractive = 1;
//PGM
// put work vertexes on stack, cache aligned
pfinalverts = (finalvert_t *)
(((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
aliasbatchedtransformdata.num_points = s_pmdl->num_xyz;
aliasbatchedtransformdata.last_verts = r_lastframe->verts;
aliasbatchedtransformdata.this_verts = r_thisframe->verts;
aliasbatchedtransformdata.dest_verts = pfinalverts;
R_AliasTransformFinalVerts( aliasbatchedtransformdata.num_points,
aliasbatchedtransformdata.dest_verts,
aliasbatchedtransformdata.last_verts,
aliasbatchedtransformdata.this_verts );
// clip and draw all triangles
//
pstverts = (dstvert_t *)((byte *)s_pmdl + s_pmdl->ofs_st);
ptri = (dtriangle_t *)((byte *)s_pmdl + s_pmdl->ofs_tris);
if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
{
for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
{
pfv[0] = &pfinalverts[ptri->index_xyz[0]];
pfv[1] = &pfinalverts[ptri->index_xyz[1]];
pfv[2] = &pfinalverts[ptri->index_xyz[2]];
if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
continue; // completely clipped
// insert s/t coordinates
pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
{ // totally unclipped
aliastriangleparms.a = pfv[2];
aliastriangleparms.b = pfv[1];
aliastriangleparms.c = pfv[0];
R_DrawTriangle();
}
else
{
R_AliasClipTriangle (pfv[2], pfv[1], pfv[0]);
}
}
}
else
{
for (i=0 ; i<s_pmdl->num_tris ; i++, ptri++)
{
pfv[0] = &pfinalverts[ptri->index_xyz[0]];
pfv[1] = &pfinalverts[ptri->index_xyz[1]];
pfv[2] = &pfinalverts[ptri->index_xyz[2]];
if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags )
continue; // completely clipped
// insert s/t coordinates
pfv[0]->s = pstverts[ptri->index_st[0]].s << 16;
pfv[0]->t = pstverts[ptri->index_st[0]].t << 16;
pfv[1]->s = pstverts[ptri->index_st[1]].s << 16;
pfv[1]->t = pstverts[ptri->index_st[1]].t << 16;
pfv[2]->s = pstverts[ptri->index_st[2]].s << 16;
pfv[2]->t = pstverts[ptri->index_st[2]].t << 16;
if ( ! (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) )
{ // totally unclipped
aliastriangleparms.a = pfv[0];
aliastriangleparms.b = pfv[1];
aliastriangleparms.c = pfv[2];
R_DrawTriangle();
}
else
{ // partially clipped
R_AliasClipTriangle (pfv[0], pfv[1], pfv[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
//
angles[ROLL] = currententity->angles[ROLL];
angles[PITCH] = currententity->angles[PITCH];
angles[YAW] = 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] = currententity->origin[0]-r_origin[0];
aliasworldtransform[1][3] = currententity->origin[1]-r_origin[1];
aliasworldtransform[2][3] = currententity->origin[2]-r_origin[2];
aliasoldworldtransform[0][3] = currententity->oldorigin[0]-r_origin[0];
aliasoldworldtransform[1][3] = currententity->oldorigin[1]-r_origin[1];
aliasoldworldtransform[2][3] = currententity->oldorigin[2]-r_origin[2];
// FIXME: can do more efficiently than full concatenation
// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -