From 7d184704e499b001046ef76851ed70d53f93d38a Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 25 Aug 2002 11:12:01 +0000 Subject: [PATCH] monster movement interpolation now works in both protocols (shared code), this bloated the entity persistent struct a bit more unfortunately git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2283 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 52 +++++++++++++++++++-------------------- cl_parse.c | 71 ++++++++++++++++++++++++++++++++++++++---------------- client.h | 12 +++++++++ 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/cl_main.c b/cl_main.c index 21a4df5c..5e287a8f 100644 --- a/cl_main.c +++ b/cl_main.c @@ -349,7 +349,7 @@ static void CL_RelinkNetworkEntities() { entity_t *ent; int i, effects, temp; - float f, d, bobjrotate, bobjoffset, dlightradius, lerp; + float d, bobjrotate, bobjoffset, dlightradius, lerp; vec3_t oldorg, neworg, delta, dlightcolor, v, v2, mins, maxs; bobjrotate = ANGLEMOD(100*cl.time); @@ -375,41 +375,39 @@ static void CL_RelinkNetworkEntities() if (!ent->state_previous.active) { // only one state available - lerp = 1; - VectorCopy (ent->state_current.origin, oldorg); // skip trails - VectorCopy (ent->state_current.origin, neworg); - VectorCopy (ent->state_current.angles, ent->render.angles); + VectorCopy (ent->persistent.neworigin, neworg); + VectorCopy (ent->persistent.newangles, ent->render.angles); + VectorCopy (neworg, oldorg); } else { // if the delta is large, assume a teleport and don't lerp - VectorSubtract(ent->state_current.origin, ent->state_previous.origin, delta); - // LordHavoc: increased tolerance from 100 to 200, and now to 1000 - if ((sv.active && svs.maxclients == 1 && !(ent->state_current.flags & RENDER_STEP)) || cls.timedemo || DotProduct(delta, delta) > 1000*1000 || cl_nolerp.integer) - lerp = 1; - else + VectorSubtract(ent->persistent.neworigin, ent->persistent.oldorigin, delta); + if (ent->persistent.lerpdeltatime > 0) { - f = ent->state_current.time - ent->state_previous.time; - if (f > 0) - lerp = (cl.time - ent->state_previous.time) / f; + lerp = (cl.time - ent->persistent.lerpstarttime) / ent->persistent.lerpdeltatime; + if (lerp < 1) + { + // interpolate the origin and angles + VectorMA(ent->persistent.oldorigin, lerp, delta, neworg); + VectorSubtract(ent->persistent.newangles, ent->persistent.oldangles, delta); + if (delta[0] < -180) delta[0] += 360;else if (delta[0] >= 180) delta[0] -= 360; + if (delta[1] < -180) delta[1] += 360;else if (delta[1] >= 180) delta[1] -= 360; + if (delta[2] < -180) delta[2] += 360;else if (delta[2] >= 180) delta[2] -= 360; + VectorMA(ent->persistent.oldangles, lerp, delta, ent->render.angles); + } else - lerp = 1; - } - if (lerp >= 1) - { - // no interpolation - VectorCopy (ent->state_current.origin, neworg); - VectorCopy (ent->state_current.angles, ent->render.angles); + { + // no interpolation + VectorCopy (ent->persistent.neworigin, neworg); + VectorCopy (ent->persistent.newangles, ent->render.angles); + } } else { - // interpolate the origin and angles - VectorMA(ent->state_previous.origin, lerp, delta, neworg); - VectorSubtract(ent->state_current.angles, ent->state_previous.angles, delta); - if (delta[0] < -180) delta[0] += 360;else if (delta[0] >= 180) delta[0] -= 360; - if (delta[1] < -180) delta[1] += 360;else if (delta[1] >= 180) delta[1] -= 360; - if (delta[2] < -180) delta[2] += 360;else if (delta[2] >= 180) delta[2] -= 360; - VectorMA(ent->state_previous.angles, lerp, delta, ent->render.angles); + // no interpolation + VectorCopy (ent->persistent.neworigin, neworg); + VectorCopy (ent->persistent.newangles, ent->render.angles); } } diff --git a/cl_parse.c b/cl_parse.c index 896ddf0e..b33a23d7 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -502,6 +502,52 @@ void CL_ValidateState(entity_state_t *s) } } +void CL_MoveLerpEntityStates(entity_t *ent) +{ + float odelta[3], adelta[3]; + VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta); + VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta); + if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer) + { + // we definitely shouldn't lerp + ent->persistent.lerpdeltatime = 0; + ent->persistent.lerpstarttime = cl.mtime[1]; + VectorCopy(ent->state_current.origin, ent->persistent.oldorigin); + VectorCopy(ent->state_current.angles, ent->persistent.oldangles); + VectorCopy(ent->state_current.origin, ent->persistent.neworigin); + VectorCopy(ent->state_current.angles, ent->persistent.newangles); + } + else// if (ent->state_current.flags & RENDER_STEP) + { + // monster interpolation + if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01) + { + ent->persistent.lerpdeltatime = cl.time - ent->persistent.lerpstarttime; + ent->persistent.lerpstarttime = cl.mtime[1]; + VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin); + VectorCopy(ent->persistent.newangles, ent->persistent.oldangles); + VectorCopy(ent->state_current.origin, ent->persistent.neworigin); + VectorCopy(ent->state_current.angles, ent->persistent.newangles); + } + } + /* + else + { + // not a monster + ent->persistent.lerpstarttime = cl.mtime[1]; + // no lerp if it's singleplayer + //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP) + // ent->persistent.lerpdeltatime = 0; + //else + ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1]; + VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin); + VectorCopy(ent->persistent.newangles, ent->persistent.oldangles); + VectorCopy(ent->state_current.origin, ent->persistent.neworigin); + VectorCopy(ent->state_current.angles, ent->persistent.newangles); + } + */ +} + /* ================== CL_ParseUpdate @@ -606,28 +652,11 @@ void CL_ParseUpdate (int bits) if (new.active) CL_ValidateState(&new); - if (new.flags & RENDER_STEP) // FIXME: rename this flag? - { - // make time identical for memcmp - new.time = ent->state_current.time; - if (memcmp(&new, &ent->state_current, sizeof(entity_state_t))) - { - // set it back to what it should be - new.time = cl.mtime[0] + 0.1; - // state has changed - ent->state_previous = ent->state_current; - ent->state_current = new; - // assume 10fps animation - //ent->state_previous.time = cl.mtime[0] - 0.1; - } - } - else - { - ent->state_previous = ent->state_current; - ent->state_current = new; - } + ent->state_previous = ent->state_current; + ent->state_current = new; if (ent->state_current.active) { + CL_MoveLerpEntityStates(ent); cl_entities_active[ent->state_current.number] = true; // mark as visible (no kill this frame) entlife[ent->state_current.number] = 2; @@ -647,7 +676,7 @@ void CL_ReadEntityFrame(void) ent = &cl_entities[entityframe.entitydata[i].number]; ent->state_previous = ent->state_current; ent->state_current = entityframe.entitydata[i]; - ent->state_current.time = cl.mtime[0]; + CL_MoveLerpEntityStates(ent); // the entity lives again... entlife[ent->state_current.number] = 2; cl_entities_active[ent->state_current.number] = true; diff --git a/client.h b/client.h index 3faba2f8..c7e61e49 100644 --- a/client.h +++ b/client.h @@ -153,6 +153,18 @@ typedef struct entity_persistent_s // muzzleflash fading float muzzleflash; + // interpolated movement + + // start time of move + float lerpstarttime; + // time difference from start to end of move + float lerpdeltatime; + // the move itself, start and end + float oldorigin[3]; + float oldangles[3]; + float neworigin[3]; + float newangles[3]; + // interpolated animation // lerp resets when model changes -- 2.39.2