FiztQuake's lerping system.

Seems to be mostly working. I get some funny results for zombies, but that
might be moving and turning at the same time causing issues.
This commit is contained in:
Bill Currie 2010-11-26 09:22:04 +09:00
parent 31c13d92a2
commit cacd2fb895
9 changed files with 355 additions and 239 deletions

View file

@ -66,8 +66,14 @@ extern lightstyle_t r_lightstyle[MAX_LIGHTSTYLES];
#define TOP_RANGE 16 // soldier uniform colors
#define BOTTOM_RANGE 96
typedef struct entity_s
{
#define LERP_MOVESTEP (1<<0) //this is a MOVETYPE_STEP entity, enable movement lerp
#define LERP_RESETANIM (1<<1) //disable anim lerping until next anim frame
#define LERP_RESETANIM2 (1<<2) //set this and previous flag to disable anim lerping for two anim frames
#define LERP_RESETMOVE (1<<3) //disable movement lerping until next origin/angles change
#define LERP_FINISH (1<<4) //use lerpfinish time from server update instead of assuming interval of 0.1
typedef struct entity_s {
vec3_t origin;
vec3_t old_origin;
vec3_t angles;
@ -94,10 +100,18 @@ typedef struct entity_s
// splits bmodel, or NULL if not split
// Animation interpolation
float frame_start_time;
float frame_interval;
int pose1;
int pose2;
// FIXME separate struct?
byte lerpflags;
float lerpstart;
float lerptime;
float lerpfinish;
short previouspose;
short currentpose;
float movelerpstart;
vec3_t previousorigin;
vec3_t currentorigin;
vec3_t previousangles; //FIXME quaternion?
vec3_t currentangles;
} entity_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!

View file

@ -101,6 +101,16 @@ static byte cs_data[8 * 8 * 4] = {
0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
//From FitzQuake
255,255,255,255,255,255,255,255,
255,255,255, 8, 9,255,255,255,
255,255,255, 6, 8, 2,255,255,
255, 6, 8, 8, 6, 8, 8,255,
255,255, 2, 8, 8, 2, 2, 2,
255,255,255, 7, 8, 2,255,255,
255,255,255,255, 2, 2,255,255,
255,255,255,255,255,255,255,255,
};
typedef struct {
@ -568,10 +578,60 @@ crosshair_3 (int x, int y)
qfglColor3ubv (color_white);
}
static void
crosshair_4 (int x, int y)
{
unsigned char *pColor;
pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val];
qfglColor4ubv (pColor);
qfglBindTexture (GL_TEXTURE_2D, cs_texture);
qfglBegin (GL_QUADS);
qfglTexCoord2f (0, 0.5);
qfglVertex2f (x - 7, y - 7);
qfglTexCoord2f (0.5, 0.5);
qfglVertex2f (x + 9, y - 7);
qfglTexCoord2f (0.5, 1);
qfglVertex2f (x + 9, y + 9);
qfglTexCoord2f (0, 1);
qfglVertex2f (x - 7, y + 9);
qfglEnd ();
qfglColor3ubv (color_white);
}
static void
crosshair_5 (int x, int y) //FIXME don't use until the data is filled in
{
unsigned char *pColor;
pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val];
qfglColor4ubv (pColor);
qfglBindTexture (GL_TEXTURE_2D, cs_texture);
qfglBegin (GL_QUADS);
qfglTexCoord2f (0.5, 0.5);
qfglVertex2f (x - 7, y - 7);
qfglTexCoord2f (1, 0.5);
qfglVertex2f (x + 9, y - 7);
qfglTexCoord2f (1, 1);
qfglVertex2f (x + 9, y + 9);
qfglTexCoord2f (0.5, 1);
qfglVertex2f (x - 7, y + 9);
qfglEnd ();
qfglColor3ubv (color_white);
}
static void (*crosshair_func[]) (int x, int y) = {
crosshair_1,
crosshair_2,
crosshair_3,
crosshair_4,
crosshair_5,
};
VISIBLE void

View file

@ -76,6 +76,14 @@ typedef struct {
int count;
} vert_order_t;
typedef struct {
short pose1;
short pose2;
float blend;
vec3_t origin;
vec3_t angles;
} lerpdata_t;
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "anorms.h"
};
@ -246,28 +254,102 @@ GL_DrawAliasShadow (aliashdr_t *paliashdr, vert_order_t *vo)
}
}
static inline vert_order_t *
GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
static inline void
gl_calc_blend16 (byte *posedata, lerpdata_t *lerpdata, vert_order_t *vo,
int count)
{
float interval;
int count, numposes, pose, i;
trivertx16_t *verts;
vert_order_t *vo;
blended_vert_t *vo_v;
trivertx16_t *verts;
trivertx16_t *verts1, *verts2;
int i;
if ((frame >= paliashdr->mdl.numframes) || (frame < 0)) {
if (developer->int_val)
Sys_MaskPrintf (SYS_DEV,
"R_AliasSetupFrame: no such frame %d %s\n", frame,
currententity->model->name);
frame = 0;
verts = (trivertx16_t *) posedata;
if (lerpdata->blend == 0.0) {
verts = verts + lerpdata->pose1 * count;
} else if (lerpdata->blend == 1.0) {
verts = verts + lerpdata->pose2 * count;
} else {
verts1 = verts + lerpdata->pose1 * count;
verts2 = verts + lerpdata->pose2 * count;
for (i = 0, vo_v = vo->verts; i < count;
i++, vo_v++, verts1++, verts2++) {
float *n1, *n2;
VectorBlend (verts1->v, verts2->v, lerpdata->blend, vo_v->vert);
n1 = r_avertexnormals[verts1->lightnormalindex];
n2 = r_avertexnormals[verts2->lightnormalindex];
VectorBlend (n1, n2, lerpdata->blend, vo_v->normal);
if (VectorIsZero (vo_v->normal)) {
if (lerpdata->blend < 0.5) {
VectorCopy (n1, vo_v->normal);
} else {
VectorCopy (n2, vo_v->normal);
}
}
}
return;
}
pose = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata);
for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts++) {
VectorCopy (verts->v, vo_v->vert);
VectorCopy (r_avertexnormals[verts->lightnormalindex], vo_v->normal);
}
}
static inline void
gl_calc_blend8 (byte *posedata, lerpdata_t *lerpdata, vert_order_t *vo,
int count)
{
blended_vert_t *vo_v;
trivertx_t *verts;
trivertx_t *verts1, *verts2;
int i;
verts = (trivertx_t *) posedata;
if (lerpdata->blend == 0.0) {
verts = verts + lerpdata->pose1 * count;
} else if (lerpdata->blend == 1.0) {
verts = verts + lerpdata->pose2 * count;
} else {
verts1 = verts + lerpdata->pose1 * count;
verts2 = verts + lerpdata->pose2 * count;
for (i = 0, vo_v = vo->verts; i < count;
i++, vo_v++, verts1++, verts2++) {
float *n1, *n2;
VectorBlend (verts1->v, verts2->v, lerpdata->blend, vo_v->vert);
n1 = r_avertexnormals[verts1->lightnormalindex];
n2 = r_avertexnormals[verts2->lightnormalindex];
VectorBlend (n1, n2, lerpdata->blend, vo_v->normal);
if (VectorIsZero (vo_v->normal)) {
if (lerpdata->blend < 0.5) {
VectorCopy (n1, vo_v->normal);
} else {
VectorCopy (n2, vo_v->normal);
}
}
}
return;
}
for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts++) {
VectorCopy (verts->v, vo_v->vert);
VectorCopy (r_avertexnormals[verts->lightnormalindex], vo_v->normal);
}
}
static inline vert_order_t *
GL_GetAliasFrameVerts (aliashdr_t *paliashdr, lerpdata_t *lerpdata)
{
int count;
vert_order_t *vo;
byte *posedata;
posedata = (byte *) paliashdr + paliashdr->posedata;
count = paliashdr->poseverts;
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t *) &vo[1];
@ -278,186 +360,12 @@ GL_GetAliasFrameVerts16 (int frame, aliashdr_t *paliashdr, entity_t *e)
vo->tex_coord = NULL;
}
vo->count = count;
if (numposes > 1) {
interval = paliashdr->frames[frame].interval;
pose += (int) (r_realtime / interval) % numposes;
} else {
/*
One tenth of a second is 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.
*/
interval = 0.1;
}
if (gl_lerp_anim->int_val) {
trivertx16_t *verts1, *verts2;
float blend;
if (paliashdr->mdl.ident == HEADER_MDL16)
gl_calc_blend16 (posedata, lerpdata, vo, count);
else
gl_calc_blend8 (posedata, lerpdata, vo, count);
e->frame_interval = interval;
if (e->pose2 != pose) {
e->frame_start_time = r_realtime;
if (e->pose2 == -1) {
e->pose1 = pose;
} else {
e->pose1 = e->pose2;
}
e->pose2 = pose;
blend = 0.0;
} else if (r_paused) {
blend = 1.0;
} else {
blend = (r_realtime - e->frame_start_time) / e->frame_interval;
blend = min (blend, 1.0);
}
if (blend == 0.0) {
verts = verts + e->pose1 * count;
} else if (blend == 1.0) {
verts = verts + e->pose2 * count;
} else {
verts1 = verts + e->pose1 * count;
verts2 = verts + e->pose2 * count;
for (i = 0, vo_v = vo->verts; i < count;
i++, vo_v++, verts1++, verts2++) {
float *n1, *n2;
VectorBlend (verts1->v, verts2->v, blend, vo_v->vert);
n1 = r_avertexnormals[verts1->lightnormalindex];
n2 = r_avertexnormals[verts2->lightnormalindex];
VectorBlend (n1, n2, blend, vo_v->normal);
if (VectorIsZero (vo_v->normal)) {
if (blend < 0.5) {
VectorCopy (n1, vo_v->normal);
} else {
VectorCopy (n2, vo_v->normal);
}
}
}
return vo;
}
} else {
verts += pose * count;
}
for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts++) {
VectorCopy (verts->v, vo_v->vert);
VectorCopy (r_avertexnormals[verts->lightnormalindex], vo_v->normal);
}
return vo;
}
static inline vert_order_t *
GL_GetAliasFrameVerts (int frame, aliashdr_t *paliashdr, entity_t *e)
{
float interval;
int count, numposes, pose, i;
trivertx_t *verts;
vert_order_t *vo;
blended_vert_t *vo_v;
if ((frame >= paliashdr->mdl.numframes) || (frame < 0)) {
if (developer->int_val)
Sys_MaskPrintf (SYS_DEV,
"R_AliasSetupFrame: no such frame %d %s\n", frame,
currententity->model->name);
frame = 0;
}
pose = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
verts = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata);
count = paliashdr->poseverts;
vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->verts = (blended_vert_t *) &vo[1];
if (paliashdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) paliashdr + paliashdr->tex_coord);
} else {
vo->tex_coord = NULL;
}
vo->count = count;
if (numposes > 1) {
interval = paliashdr->frames[frame].interval;
pose += (int) (r_realtime / interval) % numposes;
} else {
/*
One tenth of a second is 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.
*/
interval = 0.1;
}
if (gl_lerp_anim->int_val) {
trivertx_t *verts1, *verts2;
float blend;
e->frame_interval = interval;
if (e->pose2 != pose) {
e->frame_start_time = r_realtime;
if (e->pose2 == -1) {
e->pose1 = pose;
} else {
e->pose1 = e->pose2;
}
e->pose2 = pose;
blend = 0.0;
} else if (r_paused) {
blend = 1.0;
} else {
blend = (r_realtime - e->frame_start_time) / e->frame_interval;
blend = min (blend, 1.0);
}
if (blend == 0.0) {
verts = verts + e->pose1 * count;
} else if (blend == 1.0) {
verts = verts + e->pose2 * count;
} else {
verts1 = verts + e->pose1 * count;
verts2 = verts + e->pose2 * count;
for (i = 0, vo_v = vo->verts; i < count;
i++, vo_v++, verts1++, verts2++) {
float *n1, *n2;
VectorBlend (verts1->v, verts2->v, blend, vo_v->vert);
n1 = r_avertexnormals[verts1->lightnormalindex];
n2 = r_avertexnormals[verts2->lightnormalindex];
VectorBlend (n1, n2, blend, vo_v->normal);
if (VectorIsZero (vo_v->normal)) {
if (blend < 0.5) {
VectorCopy (n1, vo_v->normal);
} else {
VectorCopy (n2, vo_v->normal);
}
}
}
return vo;
}
} else {
verts += pose * count;
}
for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts++) {
VectorCopy (verts->v, vo_v->vert);
VectorCopy (r_avertexnormals[verts->lightnormalindex], vo_v->normal);
}
return vo;
}
@ -468,7 +376,7 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr)
maliasskingroup_t *paliasskingroup;
if ((skinnum >= ahdr->mdl.numskins) || (skinnum < 0)) {
Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n",
Sys_MaskPrintf (SYS_DEV, "R_AliasGetSkindesc: no such skin # %d\n",
skinnum);
skinnum = 0;
}
@ -502,6 +410,118 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr)
return pskindesc;
}
static void
r_alais_setup_lerp (aliashdr_t *paliashdr, entity_t *e, lerpdata_t *lerpdata)
{
int frame = e->frame;
int posenum, numposes;
if ((frame >= paliashdr->mdl.numframes) || (frame < 0)) {
Sys_MaskPrintf (SYS_DEV, "r_alais_setup_lerp: no such frame %d %s\n",
frame, currententity->model->name);
frame = 0;
}
posenum = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
if (numposes > 1) {
e->lerptime = paliashdr->frames[frame].interval;
posenum += (int) (r_realtime / e->lerptime) % numposes;
} else {
e->lerptime = 0.1;
}
if (e->lerpflags & LERP_RESETANIM) {
//kill any lerp in progress
e->lerpstart = 0;
e->previouspose = posenum;
e->currentpose = posenum;
e->lerpflags &= ~LERP_RESETANIM;
} else if (e->currentpose != posenum) {
// pose changed, start new lerp
if (e->lerpflags & LERP_RESETANIM2) {
//defer lerping one more time
e->lerpstart = 0;
e->previouspose = posenum;
e->currentpose = posenum;
e->lerpflags &= ~LERP_RESETANIM2;
} else {
e->lerpstart = r_realtime;
e->previouspose = e->currentpose;
e->currentpose = posenum;
}
}
if (gl_lerp_anim->int_val
/*&& !(e->model->flags & MOD_NOLERP && gl_lerp_anim->int_val != 2)*/) {
float interval = e->lerpfinish - e->lerpstart;
float time = r_realtime - e->lerpstart;
if (e->lerpflags & LERP_FINISH && numposes == 1)
lerpdata->blend = bound (0, (time) / (interval), 1);
else
lerpdata->blend = bound (0, (time) / e->lerptime, 1);
lerpdata->pose1 = e->previouspose;
lerpdata->pose2 = e->currentpose;
} else {
lerpdata->blend = 1;
lerpdata->pose1 = posenum;
lerpdata->pose2 = posenum;
}
}
static void
r_alias_lerp_transform (entity_t *e, lerpdata_t *lerpdata)
{
float blend;
vec3_t d;
int i;
if (e->lerpflags & LERP_RESETMOVE) {
// kill any lerps in progress
e->movelerpstart = 0;
VectorCopy (e->origin, e->previousorigin);
VectorCopy (e->origin, e->currentorigin);
VectorCopy (e->angles, e->previousangles);
VectorCopy (e->angles, e->currentangles);
e->lerpflags &= ~LERP_RESETMOVE;
} else if (!VectorCompare (e->origin, e->currentorigin)
|| !VectorCompare (e->angles, e->currentangles)) {
// origin/angles changed, start new lerp
e->movelerpstart = r_realtime;
VectorCopy (e->currentorigin, e->previousorigin);
VectorCopy (e->origin, e->currentorigin);
VectorCopy (e->currentangles, e->previousangles);
VectorCopy (e->angles, e->currentangles);
}
if (gl_lerp_anim->int_val /* && e != &cl.viewent */
&& e->lerpflags & LERP_MOVESTEP) {
float interval = e->lerpfinish - e->lerpstart;
float time = r_realtime - e->movelerpstart;
if (e->lerpflags & LERP_FINISH)
blend = bound (0, (time) / (interval), 1);
else
blend = bound (0, (time) / 0.1, 1);
VectorBlend (e->previousorigin, e->currentorigin, blend,
lerpdata->origin);
//FIXME use quaternions?
VectorSubtract (e->currentangles, e->previousangles, d);
for (i = 0; i < 3; i++) {
if (d[i] > 180)
d[i] -= 360;
if (d[i] < -180)
d[i] += 360;
}
VectorMultAdd (e->previousangles, blend, d, lerpdata->angles);
} else {
//don't lerp
VectorCopy (e->origin, lerpdata->origin);
VectorCopy (e->angles, lerpdata->angles);
}
}
void
R_DrawAliasModel (entity_t *e)
{
@ -519,14 +539,21 @@ R_DrawAliasModel (entity_t *e)
model_t *model;
vec3_t dist, scale;
vert_order_t *vo;
lerpdata_t lerpdata;
paliashdr = Cache_Get (&e->model->cache);
r_alais_setup_lerp (paliashdr, e, &lerpdata);
r_alias_lerp_transform (e, &lerpdata);
model = e->model;
radius = model->radius;
if (e->scale != 1.0)
radius *= e->scale;
if (R_CullSphere (e->origin, radius))
if (R_CullSphere (e->origin, radius)) {
Cache_Release (&e->model->cache);
return;
}
VectorSubtract (r_origin, e->origin, modelorg);
@ -645,7 +672,6 @@ R_DrawAliasModel (entity_t *e)
}
// locate the proper data
paliashdr = Cache_Get (&e->model->cache);
c_alias_polys += paliashdr->mdl.numtris;
// if the model has a colorised/external skin, use it, otherwise use
@ -668,11 +694,10 @@ R_DrawAliasModel (entity_t *e)
if (paliashdr->mdl.ident == HEADER_MDL16) {
VectorScale (paliashdr->mdl.scale, e->scale / 256.0, scale);
vo = GL_GetAliasFrameVerts16 (e->frame, paliashdr, e);
} else {
VectorScale (paliashdr->mdl.scale, e->scale, scale);
vo = GL_GetAliasFrameVerts (e->frame, paliashdr, e);
}
vo = GL_GetAliasFrameVerts (paliashdr, &lerpdata);
// setup the transform
qfglPushMatrix ();

View file

@ -234,10 +234,6 @@ typedef struct entity_state_s
byte colormap;
byte skin;
byte alpha;
byte scale;
byte glow_size;
byte glow_color;
byte colormod;
} entity_state_t;
#endif // __protocol_h

View file

@ -530,7 +530,9 @@ CL_RelinkEntities (void)
// if the object wasn't included in the last packet, remove it
if (state->msgtime != cl.mtime[0]) {
ent->model = NULL;
ent->pose1 = ent->pose2 = -1;
//johnfitz -- next time this entity slot is reused, the lerp will
//need to be reset
ent->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM;
if (ent->efrag)
R_RemoveEfrags (ent); // just became empty
continue;
@ -541,6 +543,8 @@ CL_RelinkEntities (void)
if (state->forcelink) {
// The entity was not updated in the last message so move to the
// final spot
VectorCopy (state->msg_origins[0], ent->origin);
VectorCopy (state->msg_angles[0], ent->angles);
if (i != cl.viewentity || chase_active->int_val) {
if (ent->efrag)
R_RemoveEfrags (ent);
@ -556,10 +560,13 @@ CL_RelinkEntities (void)
// assume a teleportation, not a motion
VectorCopy (state->msg_origins[0], ent->origin);
VectorCopy (state->msg_angles[0], ent->angles);
ent->pose1 = ent->pose2 = -1;
ent->lerpflags |= LERP_RESETMOVE;
} else {
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
// interpolate the origin and angles
// FIXME r_lerpmove.value &&
if (ent->lerpflags & LERP_MOVESTEP)
f = 1;
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
for (j = 0; j < 3; j++) {
d = state->msg_angles[0][j] - state->msg_angles[1][j];
if (d > 180)
@ -604,6 +611,14 @@ CL_RelinkEntities (void)
dl->color[2] = 0.05;
dl->color[3] = 0.7;
}
#if 0 //FIXME how much do we want this?
//johnfitz -- assume muzzle flash accompanied by muzzle flare,
//which looks bad when lerped
if (ent == &cl_entities[cl.viewentity])
cl.viewent.lerpflags |= LERP_RESETANIM | LERP_RESETANIM2;
else
ent->lerpflags |= LERP_RESETANIM | LERP_RESETANIM2;
#endif
}
CL_NewDlight (i, ent->origin, state->effects);
if (VectorDistance_fast (state->msg_origins[1], ent->origin)

View file

@ -137,6 +137,8 @@ CL_EntityNum (int num)
cl_baselines[cl.num_entities].ent =
&cl_entities[cl.num_entities];
cl_entities[cl.num_entities].colormap = vid.colormap8;
cl_entities[cl.num_entities].lerpflags |= (LERP_RESETMOVE
| LERP_RESETANIM);
cl.num_entities++;
}
}
@ -450,6 +452,13 @@ CL_ParseUpdate (int bits)
else
forcelink = false;
if (state->msgtime + 0.2 < cl.mtime[0]) {
//more than 0.2 seconds since the last message (most entities think
//every 0.1 sec)
//if we missed a think, we'd be lerping from the wrong frame
ent->lerpflags |= LERP_RESETANIM;
}
if (forcelink) { // FIXME: do this right (ie, protocol support)
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] =
ent->colormod[3] = 1.0;
@ -532,8 +541,12 @@ CL_ParseUpdate (int bits)
else
state->msg_angles[0][2] = state->baseline.angles[2];
if (bits & U_STEP) //FIXME lerping (see fitzquake)
if (bits & U_STEP) {
ent->lerpflags |= LERP_MOVESTEP;
forcelink = true;
} else {
ent->lerpflags &= ~LERP_MOVESTEP;
}
if (cl.protocol == PROTOCOL_FITZQUAKE) {
if (bits & U_ALPHA)
@ -545,14 +558,14 @@ CL_ParseUpdate (int bits)
if (bits & U_MODEL2)
modnum |= MSG_ReadByte(net_message) << 8;
if (bits & U_LERPFINISH) {
MSG_ReadByte (net_message); //FIXME ignored for now. see fitzquake
float finish_time = MSG_ReadByte (net_message);
ent->lerpfinish = state->msgtime + finish_time / 255;
ent->lerpflags |= LERP_FINISH;
} else {
ent->lerpflags &= ~LERP_FINISH;
}
} else {
state->alpha = state->baseline.alpha;
state->scale = state->baseline.scale;
state->glow_size = state->baseline.glow_size;
state->glow_color = state->baseline.glow_color;
state->colormod = state->baseline.colormod;
}
model = cl.model_precache[modnum];
@ -573,6 +586,8 @@ CL_ParseUpdate (int bits)
if (ent->skin)
CL_NewTranslation (num - 1, ent->skin);
}
//johnfitz -- don't lerp animation across model changes
ent->lerpflags |= LERP_RESETANIM;
}
if (forcelink) { // didn't have an update last message
@ -611,11 +626,7 @@ CL_ParseBaseline (cl_entity_state_t *state, int version)
if (bits & B_ALPHA)
state->baseline.alpha = MSG_ReadByte (net_message);
else
state->baseline.alpha = 255;//FIXME alpha
state->baseline.scale = 16;
state->baseline.glow_size = 0;
state->baseline.glow_color = 254;
state->baseline.colormod = 255;
state->baseline.alpha = ENTALPHA_DEFAULT;
}
/*
@ -699,6 +710,9 @@ CL_ParseClientdata (void)
if (cl.stats[STAT_WEAPON] != i) {
cl.stats[STAT_WEAPON] = i;
Sbar_Changed ();
//johnfitz -- lerping
if (cl.viewent.model != cl.model_precache[cl.stats[STAT_WEAPON]])
cl.viewent.lerpflags |= LERP_RESETANIM;
}
i = MSG_ReadShort (net_message);
@ -774,26 +788,18 @@ CL_ParseStatic (int version)
CL_ParseBaseline (&state, version);
// copy it to the current state
VectorCopy (state.baseline.origin, ent->origin);
VectorCopy (state.baseline.angles, ent->angles);
//FIXME alpha & lerp
ent->model = cl.model_precache[state.baseline.modelindex];
ent->lerpflags |= LERP_RESETANIM;
ent->frame = state.baseline.frame;
ent->colormap = vid.colormap8;
ent->skinnum = state.baseline.skin;
if (state.baseline.colormod == 255) {
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1.0;
} else {
ent->colormod[0] = ((float) ((state.baseline.colormod >> 5) & 7)) *
(1.0 / 7.0);
ent->colormod[1] = ((float) ((state.baseline.colormod >> 2) & 7)) *
(1.0 / 7.0);
ent->colormod[2] = ((float) (state.baseline.colormod & 3)) *
(1.0 / 3.0);
}
VectorSet (1.0, 1.0, 1.0, ent->colormod);
ent->colormod[3] = ENTALPHA_DECODE (state.baseline.alpha);
ent->scale = state.baseline.scale / 16.0;
ent->scale = 1.0;
VectorCopy (state.baseline.origin, ent->origin);
VectorCopy (state.baseline.angles, ent->angles);
R_AddEfrags (ent);
}

View file

@ -137,7 +137,7 @@ CL_Init_Entity (entity_t *ent)
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] =
ent->colormod[3] = 1.0;
ent->scale = 1.0;
ent->pose1 = ent->pose2 = -1;
ent->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM;
}
static tent_t *

View file

@ -510,7 +510,7 @@ CL_LinkPacketEntities (void)
(*ent)->frame = s1->frame;
if ((*ent)->visframe != r_framecount - 1) {
(*ent)->pose1 = (*ent)->pose2 = -1;
(*ent)->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM;
// No trail if new this frame
VectorCopy (s1->origin, (*ent)->origin);

View file

@ -141,7 +141,7 @@ CL_Init_Entity (entity_t *ent)
ent->colormod[0] = ent->colormod[1] = ent->colormod[2] =
ent->colormod[3] = 1.0;
ent->scale = 1.0;
ent->pose1 = ent->pose2 = -1;
ent->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM;
}
static tent_t *