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

View file

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

View file

@ -50,7 +50,6 @@
#include "va.h" #include "va.h"
#include "view.h" #include "view.h"
entity_t r_worldentity; entity_t r_worldentity;
vec3_t modelorg, r_entorigin; vec3_t modelorg, r_entorigin;
@ -118,6 +117,7 @@ cvar_t *gl_playermip;
cvar_t *gl_nocolors; cvar_t *gl_nocolors;
cvar_t *gl_keeptjunctions; cvar_t *gl_keeptjunctions;
cvar_t *gl_particles; cvar_t *gl_particles;
cvar_t *gl_lerp_anim;
cvar_t *r_skyname; cvar_t *r_skyname;
cvar_t *gl_skymultipass; cvar_t *gl_skymultipass;
@ -356,12 +356,12 @@ float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
float *shadedots = r_avertexnormal_dots[0]; float *shadedots = r_avertexnormal_dots[0];
int lastposenum; int lastposenum, lastposenum0;
/* /*
=============
GL_DrawAliasFrame GL_DrawAliasFrame
=============
Standard model drawing
*/ */
static void static void
GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb) 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) { if (count < 0) {
count = -count; count = -count;
glBegin (GL_TRIANGLE_FAN); glBegin (GL_TRIANGLE_FAN);
} else } else {
glBegin (GL_TRIANGLE_STRIP); glBegin (GL_TRIANGLE_STRIP);
}
do { do {
// texture coordinates come from the draw list // texture coordinates come from the draw list
@ -416,11 +417,76 @@ GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb)
glColor3ubv (lighthalf_v); 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 GL_DrawAliasShadow
=============
Standard shadow drawing
*/ */
extern vec3_t lightspot; extern vec3_t lightspot;
@ -442,11 +508,9 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
height = -lheight + 1.0; height = -lheight + 1.0;
while (1) { while ((count = *order++)) {
// get the vertex count and primitive type // get the vertex count and primitive type
count = *order++;
if (!count)
break; // done
if (count < 0) { if (count < 0) {
count = -count; count = -count;
glBegin (GL_TRIANGLE_FAN); glBegin (GL_TRIANGLE_FAN);
@ -459,15 +523,9 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
order += 2; order += 2;
// normals and vertexes come from the frame list // normals and vertexes come from the frame list
point[0] = point[0] = verts->v[0] * paliashdr->mdl.scale[0] + paliashdr->mdl.scale_origin[0];
verts->v[0] * paliashdr->mdl.scale[0] + point[1] = verts->v[1] * paliashdr->mdl.scale[1] + paliashdr->mdl.scale_origin[1];
paliashdr->mdl.scale_origin[0]; point[2] = verts->v[2] * paliashdr->mdl.scale[2] + paliashdr->mdl.scale_origin[2];
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[0] -= shadevector[0] * (point[2] + lheight);
point[1] -= shadevector[1] * (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 R_SetupAliasFrame
=================
*/ */
static void static void
R_SetupAliasFrame (int frame, aliashdr_t *paliashdr, qboolean fb) 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); 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; aliashdr_t *paliashdr;
float an; float an;
int anim; int anim;
qboolean torch = false;
clmodel = currententity->model; clmodel = currententity->model;
@ -567,10 +738,9 @@ R_DrawAliasModel (entity_t *e)
for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) {
if (cl_dlights[lnum].die >= cl.time) { if (cl_dlights[lnum].die >= cl.time) {
VectorSubtract (currententity->origin, VectorSubtract (currententity->origin,
cl_dlights[lnum].origin, dist); cl_dlights[lnum].origin,
add = dist);
(cl_dlights[lnum].radius * cl_dlights[lnum].radius * 8) / add = (cl_dlights[lnum].radius * cl_dlights[lnum].radius * 8) / (DotProduct (dist, dist)); // FIXME Deek
(DotProduct (dist, dist)); // FIXME Deek
if (add > 0) { if (add > 0) {
shadelight += add; shadelight += add;
@ -582,18 +752,19 @@ R_DrawAliasModel (entity_t *e)
shadelight = min (shadelight, 100); shadelight = min (shadelight, 100);
// ZOID: never allow players to go totally black // 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); 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 = if (strnequal (clmodel->name, "progs/flame", 11)) {
r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & torch = true;
(SHADEDOT_QUANT - 1)]; 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; shadelight /= 200.0;
an = e->angles[1] / 180 * M_PI; an = e->angles[1] / 180 * M_PI;
@ -616,11 +787,11 @@ R_DrawAliasModel (entity_t *e)
glPushMatrix (); glPushMatrix ();
R_RotateForEntity (e); R_RotateForEntity (e);
if (!strcmp (clmodel->name, "progs/eyes.mdl")) { if (strequal (clmodel->name, "progs/eyes.mdl")) {
glTranslatef (paliashdr->mdl.scale_origin[0], glTranslatef (paliashdr->mdl.scale_origin[0],
paliashdr->mdl.scale_origin[1], paliashdr->mdl.scale_origin[1],
paliashdr->mdl.scale_origin[2] - (22 + 8)); 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, glScalef (paliashdr->mdl.scale[0] * 2, paliashdr->mdl.scale[1] * 2,
paliashdr->mdl.scale[2] * 2); paliashdr->mdl.scale[2] * 2);
} else { } else {
@ -650,16 +821,22 @@ R_DrawAliasModel (entity_t *e)
if (gl_affinemodels->int_val) if (gl_affinemodels->int_val)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 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); R_SetupAliasFrame (currententity->frame, paliashdr, false);
}
// This block is GL fullbright support for objects... // This block is GL fullbright support for objects...
if (clmodel->hasfullbrights && gl_fb_models->int_val && if (clmodel->hasfullbrights && gl_fb_models->int_val &&
paliashdr->gl_fb_texturenum[currententity->skinnum][anim]) { paliashdr->gl_fb_texturenum[currententity->skinnum][anim]) {
glBindTexture (GL_TEXTURE_2D, glBindTexture (GL_TEXTURE_2D, paliashdr->gl_fb_texturenum[currententity->skinnum][anim]);
paliashdr->gl_fb_texturenum[currententity-> if (gl_lerp_anim->int_val && !torch) {
skinnum][anim]); R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity, true);
} else {
R_SetupAliasFrame (currententity->frame, paliashdr, true); R_SetupAliasFrame (currententity->frame, paliashdr, true);
} }
}
if (gl_affinemodels->int_val) if (gl_affinemodels->int_val)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
@ -667,16 +844,30 @@ R_DrawAliasModel (entity_t *e)
glPopMatrix (); glPopMatrix ();
if (r_shadows->int_val) { 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 (); glPushMatrix ();
R_RotateForEntity (e); R_RotateForEntity (e);
glDisable (GL_TEXTURE_2D); glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.5); glColor4f (0, 0, 0, 0.5);
if (gl_lerp_anim->int_val) {
GL_DrawAliasBlendedShadow (paliashdr, lastposenum0, lastposenum, currententity);
} else {
GL_DrawAliasShadow (paliashdr, lastposenum); GL_DrawAliasShadow (paliashdr, lastposenum);
}
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
glColor3ubv (lighthalf_v); glColor3ubv (lighthalf_v);
glPopMatrix (); glPopMatrix ();
} }
} }
//================================================================================== //==================================================================================

View file

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