mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
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:
parent
31c13d92a2
commit
cacd2fb895
9 changed files with 355 additions and 239 deletions
|
@ -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 !!!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *
|
||||
|
|
Loading…
Reference in a new issue