pr_edict.c: whitespace

rest: Implement model animation interpolation for alias models. Trying to
implement this has been an annoyance for some time, but IT WORKS NOW. set
gl_lerp_anims to zero to disable.
This commit is contained in:
Jeff Teunissen 2000-12-11 09:59:27 +00:00
parent e886b0566d
commit d8e1f27d4b
6 changed files with 367 additions and 189 deletions

View file

@ -54,8 +54,7 @@ typedef struct
// player_state_t is the information needed by a player entity
// to do move prediction and to generate a drawable entity
typedef struct
{
typedef struct player_state_s {
int messagenum; // all player's won't be updated each frame
double state_time; // not the same as the packet time,
@ -67,6 +66,7 @@ typedef struct
vec3_t velocity;
int weaponframe;
int number;
int modelindex;
int frame;
int skinnum;

View file

@ -79,6 +79,12 @@ typedef struct entity_s
// FIXME: could turn these into a union
int trivial_accept;
struct mnode_s *topnode; // for bmodels, first world node that splits bmodel, or NULL if not split
// Animation interpolation
float frame_start_time;
float frame_interval;
int pose1;
int pose2;
} entity_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!

View file

@ -355,21 +355,14 @@ CL_ParsePacketEntities (qboolean delta)
full = false;
if (oldpacket != -1) {
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) { // we
// can't
// use
// this,
// it
// is
// too
// old
if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP - 1) {
// we can't use this, it is too old
FlushEntityPacket ();
return;
}
cl.validsequence = cls.netchan.incoming_sequence;
oldp = &cl.frames[oldpacket & UPDATE_MASK].packet_entities;
} else { // this is a full update that we can
// start delta compressing from now
} else { // a full update that we can start delta compressing from now
oldp = &dummy;
dummy.num_entities = 0;
cl.validsequence = cls.netchan.incoming_sequence;
@ -489,8 +482,7 @@ CL_LinkPacketEntities (void)
extern int cl_playerindex;
extern int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index;
pack =
&cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].packet_entities;
pack = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].packet_entities;
autorotate = anglemod (100 * cl.time);
@ -502,20 +494,15 @@ CL_LinkPacketEntities (void)
// spawn light flashes, even ones coming from invisible objects
if ((s1->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED))
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1],
s1->origin[2], 200 + (rand () & 31), 0.1, 3);
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand () & 31), 0.1, 3);
else if (s1->effects & EF_BLUE)
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1],
s1->origin[2], 200 + (rand () & 31), 0.1, 1);
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand () & 31), 0.1, 1);
else if (s1->effects & EF_RED)
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1],
s1->origin[2], 200 + (rand () & 31), 0.1, 2);
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand () & 31), 0.1, 2);
else if (s1->effects & EF_BRIGHTLIGHT)
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1],
s1->origin[2] + 16, 400 + (rand () & 31), 0.1, 0);
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2] + 16, 400 + (rand () & 31), 0.1, 0);
else if (s1->effects & EF_DIMLIGHT)
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1],
s1->origin[2], 200 + (rand () & 31), 0.1, 0);
CL_NewDlight (s1->number, s1->origin[0], s1->origin[1], s1->origin[2], 200 + (rand () & 31), 0.1, 0);
// if set to invisible, skip
if (!s1->modelindex)
@ -536,8 +523,7 @@ CL_LinkPacketEntities (void)
if (cl_numvisedicts == MAX_VISEDICTS)
break; // object list is full
ent = &cl_visedicts[cl_numvisedicts];
cl_numvisedicts++;
ent = &cl_visedicts[cl_numvisedicts++];
ent->keynum = s1->number;
ent->model = model = cl.model_precache[s1->modelindex];
@ -552,36 +538,22 @@ CL_LinkPacketEntities (void)
ent->scoreboard = NULL;
}
// LordHavoc: cleaned up Endy's coding style, and fixed Endy's bugs
// Ender: Extend (Colormod) [QSG - Begin]
// N.B: All messy code below is the sole fault of LordHavoc and
// his futile attempts to save bandwidth. :)
//
ent->glowsize =
s1->glowsize <
128 ? s1->glowsize * 8.0 : (s1->glowsize - 256) * 8.0;
// if (s1->glowsize != 0)
// Con_Printf("glowsize: %d\n", s1->glowsize);
ent->glowsize = s1->glowsize < 128 ? s1->glowsize * 8.0 : (s1->glowsize - 256) * 8.0;
ent->glowcolor = s1->glowcolor;
// if (s1->glowcolor != 254)
// Con_Printf("glowcolor: %d\n", s1->glowcolor);
ent->alpha = s1->alpha / 255.0;
// if (s1->alpha != 255)
// Con_Printf("alpha: %d\n", s1->alpha);
ent->scale = s1->scale / 16.0;
// if (s1->scale != 16)
// Con_Printf("scale: %d\n", s1->scale);
if (s1->colormod == 255)
if (s1->colormod == 255) {
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
else {
// Con_Printf("colormod: %d\n", s1->colormod);
} else {
ent->colormod[0] = (float) ((s1->colormod >> 5) & 7) * (1.0 / 7.0);
ent->colormod[1] = (float) ((s1->colormod >> 2) & 7) * (1.0 / 7.0);
ent->colormod[2] = (float) (s1->colormod & 3) * (1.0 / 3.0);
}
//
// Ender: Extend (Colormod) [QSG - End]
// set skin
@ -590,8 +562,7 @@ CL_LinkPacketEntities (void)
// set frame
ent->frame = s1->frame;
// rotate binary objects locally
if (model->flags & EF_ROTATE) {
if (model->flags & EF_ROTATE) { // rotate binary objects locally
ent->angles[0] = 0;
ent->angles[1] = autorotate;
ent->angles[2] = 0;
@ -611,8 +582,7 @@ CL_LinkPacketEntities (void)
// calculate origin
for (i = 0; i < 3; i++)
ent->origin[i] = s2->origin[i] +
f * (s1->origin[i] - s2->origin[i]);
ent->origin[i] = s2->origin[i] + f * (s1->origin[i] - s2->origin[i]);
// add automatic particle trails
if (!model->flags)
@ -621,12 +591,17 @@ CL_LinkPacketEntities (void)
// scan the old entity display list for a matching
for (i = 0; i < cl_oldnumvisedicts; i++) {
if (cl_oldvisedicts[i].keynum == ent->keynum) {
ent->frame_start_time = cl_oldvisedicts[i].frame_start_time;
ent->frame_interval = cl_oldvisedicts[i].frame_interval;
ent->pose1 = cl_oldvisedicts[i].pose1;
ent->pose2 = cl_oldvisedicts[i].pose2;
VectorCopy (cl_oldvisedicts[i].origin, old_origin);
break;
}
}
if (i == cl_oldnumvisedicts)
continue; // not in last message
if (i == cl_oldnumvisedicts) // not in last message
continue;
for (i = 0; i < 3; i++)
if (abs (old_origin[i] - ent->origin[i]) > 128) { // no trail
@ -634,6 +609,7 @@ CL_LinkPacketEntities (void)
VectorCopy (ent->origin, old_origin);
break;
}
if (model->flags & EF_ROCKET) {
R_RocketTrail (old_origin, ent->origin, 0, ent);
dl = CL_AllocDlight (s1->number);
@ -788,6 +764,7 @@ CL_ParsePlayerinfo (void)
state = &cl.frames[parsecountmod].playerstate[num];
state->number = num;
flags = state->flags = MSG_ReadShort ();
state->messagenum = cl.parsecount;
@ -944,7 +921,6 @@ CL_LinkPlayers (void)
if (state->messagenum != cl.parsecount)
continue; // not present this frame
// FIXME: Use a findvar or something for gl_flashblend --KB
// spawn light flashes, even ones coming from invisible objects
if (!gl_flashblend->int_val || j != cl.playernum) {
@ -986,12 +962,23 @@ CL_LinkPlayers (void)
continue;
// grab an entity to fill in
if (cl_numvisedicts == MAX_VISEDICTS)
break; // object list is full
if (cl_numvisedicts == MAX_VISEDICTS) // object list is full
break;
ent = &cl_visedicts[cl_numvisedicts];
cl_numvisedicts++;
ent->keynum = 0;
// scan the old entity display list for a matching player
for (i = 0; i < cl_oldnumvisedicts; i++) {
if (cl_oldvisedicts[i].keynum == state->number) {
ent->frame_start_time = cl_oldvisedicts[i].frame_start_time;
ent->frame_interval = cl_oldvisedicts[i].frame_interval;
ent->pose1 = cl_oldvisedicts[i].pose1;
ent->pose2 = cl_oldvisedicts[i].pose2;
}
}
ent->keynum = 0;
ent->model = cl.model_precache[state->modelindex];
ent->skinnum = state->skinnum;
ent->frame = state->frame;
@ -1019,17 +1006,10 @@ CL_LinkPlayers (void)
// only predict half the move to minimize overruns
msec = 500 * (playertime - state->state_time);
if (msec <= 0
|| (!cl_predict_players->int_val
&& !cl_predict_players2->int_val)) {
if (msec <= 0 || (!cl_predict_players->int_val && !cl_predict_players2->int_val)) {
VectorCopy (state->origin, ent->origin);
//Con_DPrintf ("nopredict\n");
} else {
// predict players movement
if (msec > 255)
msec = 255;
state->command.msec = msec;
//Con_DPrintf ("predict: %i\n", msec);
} else { // predict players movement
state->command.msec = msec = min (msec, 255);
oldphysent = pmove.numphysent;
CL_SetSolidPlayers (j);
@ -1145,9 +1125,7 @@ CL_SetUpPlayerPrediction (qboolean dopred)
// Con_DPrintf ("nopredict\n");
} else {
// predict players movement
if (msec > 255)
msec = 255;
state->command.msec = msec;
state->command.msec = msec = min (msec, 255);
// Con_DPrintf ("predict: %i\n", msec);
CL_PredictUsercmd (state, &exact, &state->command, false);
@ -1221,8 +1199,7 @@ CL_EmitEntities (void)
return;
cl_oldnumvisedicts = cl_numvisedicts;
cl_oldvisedicts =
cl_visedicts_list[(cls.netchan.incoming_sequence - 1) & 1];
cl_oldvisedicts = cl_visedicts_list[(cls.netchan.incoming_sequence - 1) & 1];
cl_visedicts = cl_visedicts_list[cls.netchan.incoming_sequence & 1];
cl_numvisedicts = 0;

View file

@ -50,7 +50,6 @@
#include "va.h"
#include "view.h"
entity_t r_worldentity;
vec3_t modelorg, r_entorigin;
@ -118,6 +117,7 @@ cvar_t *gl_playermip;
cvar_t *gl_nocolors;
cvar_t *gl_keeptjunctions;
cvar_t *gl_particles;
cvar_t *gl_lerp_anim;
cvar_t *r_skyname;
cvar_t *gl_skymultipass;
@ -356,12 +356,12 @@ float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
float *shadedots = r_avertexnormal_dots[0];
int lastposenum;
int lastposenum, lastposenum0;
/*
=============
GL_DrawAliasFrame
=============
Standard model drawing
*/
static void
GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb)
@ -385,8 +385,9 @@ GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb)
if (count < 0) {
count = -count;
glBegin (GL_TRIANGLE_FAN);
} else
} else {
glBegin (GL_TRIANGLE_STRIP);
}
do {
// texture coordinates come from the draw list
@ -416,11 +417,76 @@ GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb)
glColor3ubv (lighthalf_v);
}
/*
GL_DrawAliasBlendedFrame
Interpolated model drawing
*/
void
GL_DrawAliasBlendedFrame (aliashdr_t *paliashdr, int pose1, int pose2, float blend, qboolean fb)
{
float l;
trivertx_t *verts1;
trivertx_t *verts2;
int *order;
int count;
vec3_t d;
lastposenum0 = pose1;
lastposenum = pose2;
verts1 = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata);
verts2 = verts1;
verts1 += pose1 * paliashdr->poseverts;
verts2 += pose2 * paliashdr->poseverts;
order = (int *) ((byte *) paliashdr + paliashdr->commands);
while ((count = *order++)) {
// get the vertex count and primitive type
if (count < 0) {
count = -count;
glBegin (GL_TRIANGLE_FAN);
} else {
glBegin (GL_TRIANGLE_STRIP);
}
do {
// texture coordinates come from the draw list
glTexCoord2f (((float *) order)[0], ((float *) order)[1]);
order += 2;
if (fb) {
glColor4f (1, 1, 1, modelalpha);
} else {
// normals and vertexes come from the frame list
// blend the light intensity from the two frames together
d[0] = shadedots[verts2->lightnormalindex] - shadedots[verts1->lightnormalindex];
l = shadelight * (shadedots[verts1->lightnormalindex] + (blend * d[0]));
glColor4f (shadecolor[0] * l, shadecolor[1] * l, shadecolor[2] * l, modelalpha);
}
VectorSubtract (verts2->v, verts1->v, d);
// blend the vertex positions from each frame together
glVertex3f (verts1->v[0] + (blend * d[0]),
verts1->v[1] + (blend * d[1]),
verts1->v[2] + (blend * d[2]));
verts1++;
verts2++;
} while (--count);
glEnd ();
}
}
/*
=============
GL_DrawAliasShadow
=============
Standard shadow drawing
*/
extern vec3_t lightspot;
@ -442,11 +508,9 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
height = -lheight + 1.0;
while (1) {
while ((count = *order++)) {
// get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0) {
count = -count;
glBegin (GL_TRIANGLE_FAN);
@ -459,15 +523,9 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
order += 2;
// normals and vertexes come from the frame list
point[0] =
verts->v[0] * paliashdr->mdl.scale[0] +
paliashdr->mdl.scale_origin[0];
point[1] =
verts->v[1] * paliashdr->mdl.scale[1] +
paliashdr->mdl.scale_origin[1];
point[2] =
verts->v[2] * paliashdr->mdl.scale[2] +
paliashdr->mdl.scale_origin[2];
point[0] = verts->v[0] * paliashdr->mdl.scale[0] + paliashdr->mdl.scale_origin[0];
point[1] = verts->v[1] * paliashdr->mdl.scale[1] + paliashdr->mdl.scale_origin[1];
point[2] = verts->v[2] * paliashdr->mdl.scale[2] + paliashdr->mdl.scale_origin[2];
point[0] -= shadevector[0] * (point[2] + lheight);
point[1] -= shadevector[1] * (point[2] + lheight);
@ -482,13 +540,75 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
}
}
/*
GL_DrawAliasBlendedShadow
Interpolated shadow drawing
*/
void
GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, entity_t *e)
{
trivertx_t *verts1, *verts2;
vec3_t point1, point2, d;
int *order, count;
float height, lheight, blend;
blend = (realtime - e->frame_start_time) / e->frame_interval;
blend = min (blend, 1);
lheight = e->origin[2] - lightspot[2];
height = -lheight + 1.0;
verts2 = verts1 = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata);
verts1 += pose1 * paliashdr->poseverts;
verts2 += pose2 * paliashdr->poseverts;
order = (int *) ((byte *) paliashdr + paliashdr->commands);
while ((count = *order++)) {
// get the vertex count and primitive type
if (count < 0) {
count = -count;
glBegin (GL_TRIANGLE_FAN);
} else {
glBegin (GL_TRIANGLE_STRIP);
}
do {
order += 2;
point1[0] = verts1->v[0] * paliashdr->mdl.scale[0] + paliashdr->mdl.scale_origin[0];
point1[1] = verts1->v[1] * paliashdr->mdl.scale[1] + paliashdr->mdl.scale_origin[1];
point1[2] = verts1->v[2] * paliashdr->mdl.scale[2] + paliashdr->mdl.scale_origin[2];
point1[0] -= shadevector[0] * (point1[2] + lheight);
point1[1] -= shadevector[1] * (point1[2] + lheight);
point2[0] = verts2->v[0] * paliashdr->mdl.scale[0] + paliashdr->mdl.scale_origin[0];
point2[1] = verts2->v[1] * paliashdr->mdl.scale[1] + paliashdr->mdl.scale_origin[1];
point2[2] = verts2->v[2] * paliashdr->mdl.scale[2] + paliashdr->mdl.scale_origin[2];
point2[0] -= shadevector[0] * (point2[2] + lheight);
point2[1] -= shadevector[1] * (point2[2] + lheight);
VectorSubtract (point2, point1, d);
glVertex3f (point1[0] + (blend * d[0]), point1[1] + (blend * d[1]), height);
verts1++;
verts2++;
} while (--count);
glEnd ();
}
}
/*
=================
R_SetupAliasFrame
=================
*/
static void
R_SetupAliasFrame (int frame, aliashdr_t *paliashdr, qboolean fb)
@ -512,6 +632,56 @@ R_SetupAliasFrame (int frame, aliashdr_t *paliashdr, qboolean fb)
GL_DrawAliasFrame (paliashdr, pose, fb);
}
/*
R_SetupAliasBlendedFrame
*/
void
R_SetupAliasBlendedFrame (int frame, aliashdr_t *paliashdr, entity_t *e, qboolean fb)
{
int pose, numposes;
float blend;
if ((frame >= paliashdr->mdl.numframes) || (frame < 0)) {
Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
frame = 0;
}
pose = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
if (numposes > 1) {
e->frame_interval = paliashdr->frames[frame].interval;
pose += (int) (cl.time / e->frame_interval) % numposes;
} else {
/* One tenth of a second is a good for most Quake animations. If the
nextthink is longer then the animation is usually meant to pause
(e.g. check out the shambler magic animation in shambler.qc). If
its shorter then things will still be smoothed partly, and the
jumps will be less noticable because of the shorter time. So,
this is probably a good assumption. */
e->frame_interval = 0.2;
}
if (e->pose2 != pose) {
e->frame_start_time = realtime;
e->pose1 = e->pose2;
e->pose2 = pose;
blend = 0;
} else {
blend = (realtime - e->frame_start_time) / e->frame_interval;
blend = min (blend, 1);
}
// Sys_Printf ("numposes: %d, pose1: %d, pose2: %d\n", numposes, e->pose1, e->pose2);
// wierd things start happening if blend passes 1
if (cl.paused)
blend = 1;
GL_DrawAliasBlendedFrame (paliashdr, e->pose1, e->pose2, blend, fb);
}
/*
=================
@ -531,6 +701,7 @@ R_DrawAliasModel (entity_t *e)
aliashdr_t *paliashdr;
float an;
int anim;
qboolean torch = false;
clmodel = currententity->model;
@ -567,10 +738,9 @@ R_DrawAliasModel (entity_t *e)
for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
if (cl_dlights[lnum].die >= cl.time) {
VectorSubtract (currententity->origin,
cl_dlights[lnum].origin, dist);
add =
(cl_dlights[lnum].radius * cl_dlights[lnum].radius * 8) /
(DotProduct (dist, dist)); // FIXME Deek
cl_dlights[lnum].origin,
dist);
add = (cl_dlights[lnum].radius * cl_dlights[lnum].radius * 8) / (DotProduct (dist, dist)); // FIXME Deek
if (add > 0) {
shadelight += add;
@ -582,18 +752,19 @@ R_DrawAliasModel (entity_t *e)
shadelight = min (shadelight, 100);
// ZOID: never allow players to go totally black
if (!strcmp (clmodel->name, "progs/player.mdl")) {
if (strequal (clmodel->name, "progs/player.mdl")) {
shadelight = max (shadelight, 8);
} else if (!gl_fb_models->int_val
&& (!strcmp (clmodel->name, "progs/flame.mdl")
|| !strcmp (clmodel->name, "progs/flame2.mdl"))) {
// HACK HACK HACK -- no fullbright colors, so make torches full light
shadelight = 256;
}
shadedots =
r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) &
(SHADEDOT_QUANT - 1)];
if (strnequal (clmodel->name, "progs/flame", 11)) {
torch = true;
if (!gl_fb_models->int_val) { // make torches full brightness anyway
shadelight = 256;
}
}
shadedots = r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
shadelight /= 200.0;
an = e->angles[1] / 180 * M_PI;
@ -616,11 +787,11 @@ R_DrawAliasModel (entity_t *e)
glPushMatrix ();
R_RotateForEntity (e);
if (!strcmp (clmodel->name, "progs/eyes.mdl")) {
if (strequal (clmodel->name, "progs/eyes.mdl")) {
glTranslatef (paliashdr->mdl.scale_origin[0],
paliashdr->mdl.scale_origin[1],
paliashdr->mdl.scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
// double size of eyes, since they are really hard to see in GL
glScalef (paliashdr->mdl.scale[0] * 2, paliashdr->mdl.scale[1] * 2,
paliashdr->mdl.scale[2] * 2);
} else {
@ -650,16 +821,22 @@ R_DrawAliasModel (entity_t *e)
if (gl_affinemodels->int_val)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
if (gl_lerp_anim->int_val && !torch) {
R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity, false);
} else {
R_SetupAliasFrame (currententity->frame, paliashdr, false);
}
// This block is GL fullbright support for objects...
if (clmodel->hasfullbrights && gl_fb_models->int_val &&
paliashdr->gl_fb_texturenum[currententity->skinnum][anim]) {
glBindTexture (GL_TEXTURE_2D,
paliashdr->gl_fb_texturenum[currententity->
skinnum][anim]);
glBindTexture (GL_TEXTURE_2D, paliashdr->gl_fb_texturenum[currententity->skinnum][anim]);
if (gl_lerp_anim->int_val && !torch) {
R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity, true);
} else {
R_SetupAliasFrame (currententity->frame, paliashdr, true);
}
}
if (gl_affinemodels->int_val)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
@ -667,16 +844,30 @@ R_DrawAliasModel (entity_t *e)
glPopMatrix ();
if (r_shadows->int_val) {
// torches, grenades, and lightning bolts do not have shadows
if (torch)
return;
if (strequal (clmodel->name, "progs/grenade.mdl"))
return;
if (strnequal (clmodel->name, "progs/bolt", 10))
return;
glPushMatrix ();
R_RotateForEntity (e);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.5);
if (gl_lerp_anim->int_val) {
GL_DrawAliasBlendedShadow (paliashdr, lastposenum0, lastposenum, currententity);
} else {
GL_DrawAliasShadow (paliashdr, lastposenum);
}
glEnable (GL_TEXTURE_2D);
glColor3ubv (lighthalf_v);
glPopMatrix ();
}
}
//==================================================================================

View file

@ -65,6 +65,7 @@ void R_InitBubble ();
void R_FireColor_f (void);
cvar_t *gl_fires;
extern cvar_t *gl_lerp_anim;
qboolean allowskybox; // allow skyboxes? --KB
/*
@ -252,6 +253,9 @@ R_Init_Cvars (void)
gl_keeptjunctions = Cvar_Get ("gl_keeptjunctions", "1", CVAR_NONE, "None");
gl_lerp_anim = Cvar_Get ("gl_lerp_anim", "1", CVAR_ARCHIVE,
"Toggles model animation interpolation");
r_skyname = Cvar_Get ("r_skyname", "none", CVAR_NONE,
"name of the current skybox");
gl_skymultipass = Cvar_Get ("gl_skymultipass", "1", CVAR_NONE,