mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 15:31:39 +00:00
Add alternative model lerping mode for proper compat with csqc/menuqc.
This commit is contained in:
parent
e63dae5f49
commit
e39c88a58b
3 changed files with 129 additions and 62 deletions
|
@ -5787,10 +5787,10 @@ static void PF_m_addentity(void)
|
|||
eval_t *origin = GetEdictFieldValue(ed, ED_FindFieldOffset("origin"));
|
||||
eval_t *angles = GetEdictFieldValue(ed, ED_FindFieldOffset("angles"));
|
||||
eval_t *frame = GetEdictFieldValue(ed, ED_FindFieldOffset("frame"));
|
||||
// eval_t *frame2 = GetEdictFieldValue(ed, ED_FindFieldOffset("frame2"));
|
||||
// eval_t *lerpfrac = GetEdictFieldValue(ed, ED_FindFieldOffset("lerpfrac"));
|
||||
// eval_t *frame1time = GetEdictFieldValue(ed, ED_FindFieldOffset("frame1time"));
|
||||
// eval_t *frame2time = GetEdictFieldValue(ed, ED_FindFieldOffset("frame2time"));
|
||||
eval_t *frame2 = GetEdictFieldValue(ed, ED_FindFieldOffset("frame2"));
|
||||
eval_t *lerpfrac = GetEdictFieldValue(ed, ED_FindFieldOffset("lerpfrac"));
|
||||
eval_t *frame1time = GetEdictFieldValue(ed, ED_FindFieldOffset("frame1time"));
|
||||
eval_t *frame2time = GetEdictFieldValue(ed, ED_FindFieldOffset("frame2time"));
|
||||
eval_t *skin = GetEdictFieldValue(ed, ED_FindFieldOffset("skin"));
|
||||
eval_t *alpha = GetEdictFieldValue(ed, ED_FindFieldOffset("alpha"));
|
||||
|
||||
|
@ -5799,12 +5799,16 @@ static void PF_m_addentity(void)
|
|||
if (angles)
|
||||
VectorCopy(angles->vector, e->angles);
|
||||
e->model = model;
|
||||
e->frame = frame?frame->_float:0;
|
||||
e->skinnum = skin?skin->_float:0;
|
||||
e->alpha = alpha?ENTALPHA_ENCODE(alpha->_float):ENTALPHA_DEFAULT;
|
||||
|
||||
//can't exactly use currentpose/previous pose, as we don't know them.
|
||||
e->lerpflags = LERP_RESETANIM|LERP_RESETMOVE;
|
||||
e->lerpflags = LERP_EXPLICIT|LERP_RESETANIM|LERP_RESETMOVE;
|
||||
e->frame = frame?frame->_float:0;
|
||||
e->lerp.snap.frame2 = frame2?frame2->_float:0;
|
||||
e->lerp.snap.lerpfrac = lerpfrac?lerpfrac->_float:0;
|
||||
e->lerp.snap.time[0] = frame1time?frame1time->_float:0;
|
||||
e->lerp.snap.time[1] = frame2time?frame2time->_float:0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6376,8 +6380,8 @@ static struct
|
|||
|
||||
{"callfunction", PF_callfunction, PF_callfunction, 605,PF_callfunction, 605, D("void(.../*, string funcname*/)", "Invokes the named function. The function name is always passed as the last parameter and must always be present. The others are passed to the named function as-is")},
|
||||
{"isfunction", PF_isfunction, PF_isfunction, 607,PF_isfunction, 607, D("float(string s)", "Returns true if the named function exists and can be called with the callfunction builtin.")},
|
||||
{"getresolution", PF_NoSSQC, PF_NoCSQC, 608,PF_cl_getresolution, 608, D("vector(float mode, float forfullscreen)", "Returns available/common video modes.")},
|
||||
{"gethostcachevalue", PF_NoSSQC, PF_gethostcachevalue, 511,PF_gethostcachevalue, 611, D("float(float type)", "Returns number of servers known")},
|
||||
{"getresolution", PF_NoSSQC, PF_cl_getresolution, 608,PF_cl_getresolution, 608, D("vector(float mode, float forfullscreen)", "Returns available/common video modes.")},
|
||||
{"gethostcachevalue", PF_NoSSQC, PF_gethostcachevalue, 611,PF_gethostcachevalue, 611, D("float(float type)", "Returns number of servers known")},
|
||||
{"gethostcachestring", PF_NoSSQC, PF_gethostcachestring, 612,PF_gethostcachestring, 612, D("string(float type, float hostnr)", "Retrieves some specific type of info about the specified server.")},
|
||||
{"parseentitydata", PF_parseentitydata, NULL/*field hacks*/, 613,NULL, 613, D("float(entity e, string s, optional float offset)", "Reads a single entity's fields into an already-spawned entity. s should contain field pairs like in a saved game: {\"foo1\" \"bar\" \"foo2\" \"5\"}. Returns <=0 on failure, otherwise returns the offset in the string that was read to.")},
|
||||
{"resethostcachemasks", PF_NoSSQC, PF_resethostcachemasks, 615,PF_resethostcachemasks, 615, D("void()", "Resets server listing filters.")},
|
||||
|
@ -6558,6 +6562,8 @@ static void PF_checkbuiltin (void)
|
|||
{ //but it will be defined if its actually executed.
|
||||
if (extensionbuiltins[i].desc && !strncmp(extensionbuiltins[i].desc, "stub.", 5))
|
||||
G_FLOAT(OFS_RETURN) = false; //pretend it won't work if it probably won't be useful
|
||||
else if (!extensionbuiltins[i].menufunc)
|
||||
G_FLOAT(OFS_RETURN) = false; //works, but not in this module
|
||||
else
|
||||
G_FLOAT(OFS_RETURN) = true;
|
||||
break;
|
||||
|
@ -6572,6 +6578,9 @@ static void PF_checkbuiltin (void)
|
|||
{ //but it will be defined if its actually executed.
|
||||
if (extensionbuiltins[i].desc && !strncmp(extensionbuiltins[i].desc, "stub.", 5))
|
||||
G_FLOAT(OFS_RETURN) = false; //pretend it won't work if it probably won't be useful
|
||||
else if ((qcvm == &cl.qcvm && !extensionbuiltins[i].ssqcfunc)
|
||||
|| (qcvm == &sv.qcvm && !extensionbuiltins[i].csqcfunc))
|
||||
G_FLOAT(OFS_RETURN) = false; //works, but not in this module
|
||||
else
|
||||
G_FLOAT(OFS_RETURN) = true;
|
||||
break;
|
||||
|
|
|
@ -730,9 +730,9 @@ void GL_DrawAliasFrame (aliashdr_t *paliashdr, lerpdata_t lerpdata)
|
|||
R_SetupAliasFrame -- johnfitz -- rewritten to support lerping
|
||||
=================
|
||||
*/
|
||||
void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
|
||||
void R_SetupAliasFrame (aliashdr_t *paliashdr, entity_t *e, lerpdata_t *lerpdata)
|
||||
{
|
||||
entity_t *e = currententity;
|
||||
int frame = e->frame;
|
||||
int posenum, numposes;
|
||||
|
||||
if ((frame >= paliashdr->numframes) || (frame < 0))
|
||||
|
@ -741,6 +741,50 @@ void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
|
|||
frame = 0;
|
||||
}
|
||||
|
||||
if (e->lerpflags & LERP_EXPLICIT)
|
||||
{
|
||||
int frame2 = e->lerp.snap.frame2;
|
||||
float frac = e->lerp.snap.lerpfrac;
|
||||
float time = cl.time;
|
||||
|
||||
if ((frame2 >= paliashdr->numframes) || (frame2 < 0))
|
||||
frame2 = 0;
|
||||
|
||||
if (paliashdr->frames[(frac > 0.5)?frame2:frame].numposes > 1)
|
||||
{ //our stronger sequence is a framegroup, but we can only do two-way blends.
|
||||
if (frac > 0.5)
|
||||
{
|
||||
frame = frame2;
|
||||
time = e->lerp.snap.time[1];
|
||||
}
|
||||
else
|
||||
time = e->lerp.snap.time[0];
|
||||
|
||||
if (time < 0)
|
||||
time = 0; //just in case...
|
||||
frac = (time / paliashdr->frames[frame].interval);
|
||||
posenum = (int)frac;
|
||||
lerpdata->blend = (frac - posenum);
|
||||
|
||||
posenum += paliashdr->frames[frame].firstpose;
|
||||
numposes = paliashdr->frames[frame].numposes;
|
||||
|
||||
lerpdata->pose1 = (posenum)%numposes;
|
||||
lerpdata->pose2 = (posenum+1)%numposes;
|
||||
}
|
||||
else
|
||||
{
|
||||
lerpdata->blend = frac;
|
||||
|
||||
lerpdata->pose1 = paliashdr->frames[frame].firstpose;
|
||||
lerpdata->pose1 += (unsigned int)(e->lerp.snap.time[0]/paliashdr->frames[frame].interval) % paliashdr->frames[frame].numposes;
|
||||
|
||||
lerpdata->pose2 = paliashdr->frames[frame2].firstpose;
|
||||
lerpdata->pose2 += (unsigned int)(e->lerp.snap.time[1]/paliashdr->frames[frame2].interval) % paliashdr->frames[frame].numposes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
posenum = paliashdr->frames[frame].firstpose;
|
||||
numposes = paliashdr->frames[frame].numposes;
|
||||
|
||||
|
@ -749,33 +793,33 @@ void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
|
|||
float time = cl.time + e->syncbase; //Spike: Readded syncbase
|
||||
if (time < 0)
|
||||
time = 0; //just in case...
|
||||
e->lerptime = paliashdr->frames[frame].interval; //FIXME: no per-frame intervals
|
||||
posenum += (int)(time / e->lerptime) % numposes;
|
||||
e->lerp.state.lerptime = paliashdr->frames[frame].interval; //FIXME: no per-frame intervals
|
||||
posenum += (int)(time / e->lerp.state.lerptime) % numposes;
|
||||
}
|
||||
else
|
||||
e->lerptime = 0.1;
|
||||
e->lerp.state.lerptime = 0.1;
|
||||
|
||||
if (e->lerpflags & LERP_RESETANIM) //kill any lerp in progress
|
||||
{
|
||||
e->lerpstart = 0;
|
||||
e->previouspose = posenum;
|
||||
e->currentpose = posenum;
|
||||
e->lerp.state.lerpstart = 0;
|
||||
e->lerp.state.previouspose = posenum;
|
||||
e->lerp.state.currentpose = posenum;
|
||||
e->lerpflags -= LERP_RESETANIM;
|
||||
}
|
||||
else if (e->currentpose != posenum) // pose changed, start new lerp
|
||||
else if (e->lerp.state.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->lerp.state.lerpstart = 0;
|
||||
e->lerp.state.previouspose = posenum;
|
||||
e->lerp.state.currentpose = posenum;
|
||||
e->lerpflags -= LERP_RESETANIM2;
|
||||
}
|
||||
else
|
||||
{
|
||||
e->lerpstart = cl.time;
|
||||
e->previouspose = e->currentpose;
|
||||
e->currentpose = posenum;
|
||||
e->lerp.state.lerpstart = cl.time;
|
||||
e->lerp.state.previouspose = e->lerp.state.currentpose;
|
||||
e->lerp.state.currentpose = posenum;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -783,11 +827,11 @@ void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
|
|||
if (r_lerpmodels.value && !(e->model->flags & MOD_NOLERP && r_lerpmodels.value != 2))
|
||||
{
|
||||
if (e->lerpflags & LERP_FINISH && numposes == 1)
|
||||
lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / (e->lerpfinish - e->lerpstart), 1);
|
||||
lerpdata->blend = CLAMP (0, (cl.time - e->lerp.state.lerpstart) / (e->lerpfinish - e->lerp.state.lerpstart), 1);
|
||||
else
|
||||
lerpdata->blend = CLAMP (0, (cl.time - e->lerpstart) / e->lerptime, 1);
|
||||
lerpdata->pose1 = e->previouspose;
|
||||
lerpdata->pose2 = e->currentpose;
|
||||
lerpdata->blend = CLAMP (0, (cl.time - e->lerp.state.lerpstart) / e->lerp.state.lerptime, 1);
|
||||
lerpdata->pose1 = e->lerp.state.previouspose;
|
||||
lerpdata->pose2 = e->lerp.state.currentpose;
|
||||
}
|
||||
else //don't lerp
|
||||
{
|
||||
|
@ -795,7 +839,7 @@ void R_SetupAliasFrame (aliashdr_t *paliashdr, int frame, lerpdata_t *lerpdata)
|
|||
lerpdata->pose1 = posenum;
|
||||
lerpdata->pose2 = posenum;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (paliashdr->numboneposes)
|
||||
{
|
||||
|
@ -1002,7 +1046,7 @@ void R_DrawAliasModel (entity_t *e)
|
|||
// setup pose/lerp data -- do it first so we don't miss updates due to culling
|
||||
//
|
||||
paliashdr = (aliashdr_t *)Mod_Extradata (e->model);
|
||||
R_SetupAliasFrame (paliashdr, e->frame, &lerpdata);
|
||||
R_SetupAliasFrame (paliashdr, e, &lerpdata);
|
||||
R_SetupEntityTransform (e, &lerpdata);
|
||||
|
||||
glsl = &r_alias_glsl[(paliashdr->poseverttype==PV_IQM)?ALIAS_GLSL_SKELETAL:ALIAS_GLSL_BASIC];
|
||||
|
@ -1328,7 +1372,7 @@ void GL_DrawAliasShadow (entity_t *e)
|
|||
if (entalpha == 0) return;
|
||||
|
||||
paliashdr = (aliashdr_t *)Mod_Extradata (e->model);
|
||||
R_SetupAliasFrame (paliashdr, e->frame, &lerpdata);
|
||||
R_SetupAliasFrame (paliashdr, e, &lerpdata);
|
||||
R_SetupEntityTransform (e, &lerpdata);
|
||||
R_LightPoint (e->origin);
|
||||
lheight = currententity->origin[2] - lightspot[2];
|
||||
|
@ -1375,7 +1419,7 @@ void R_DrawAliasModel_ShowTris (entity_t *e)
|
|||
return;
|
||||
|
||||
paliashdr = (aliashdr_t *)Mod_Extradata (e->model);
|
||||
R_SetupAliasFrame (paliashdr, e->frame, &lerpdata);
|
||||
R_SetupAliasFrame (paliashdr, e, &lerpdata);
|
||||
R_SetupEntityTransform (e, &lerpdata);
|
||||
|
||||
glPushMatrix ();
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef struct efrag_s
|
|||
#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
|
||||
#define LERP_EXPLICIT (1<<5) //for csqc, using explicit frame1/2+frac+times
|
||||
//johnfitz
|
||||
|
||||
typedef struct entity_s
|
||||
|
@ -82,11 +83,24 @@ typedef struct entity_s
|
|||
byte eflags; //spike -- mostly a mirror of netstate, but handles tag inheritance (eww!)
|
||||
byte alpha; //johnfitz -- alpha
|
||||
byte lerpflags; //johnfitz -- lerping
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{ //read-only lerp data for csqc...
|
||||
int frame2;
|
||||
float lerpfrac;
|
||||
float time[2];
|
||||
} snap;
|
||||
struct
|
||||
{ //updated by the model rendering code.
|
||||
float lerpstart; //johnfitz -- animation lerping
|
||||
float lerptime; //johnfitz -- animation lerping
|
||||
float lerpfinish; //johnfitz -- lerping -- server sent us a more accurate interval, use it instead of 0.1
|
||||
short previouspose; //johnfitz -- animation lerping
|
||||
short currentpose; //johnfitz -- animation lerping
|
||||
} state;
|
||||
} lerp;
|
||||
float lerpfinish; //johnfitz -- lerping -- server sent us a more accurate interval, use it instead of 0.1
|
||||
// short futurepose; //johnfitz -- animation lerping
|
||||
float movelerpstart; //johnfitz -- transform lerping
|
||||
vec3_t previousorigin; //johnfitz -- transform lerping
|
||||
|
|
Loading…
Reference in a new issue