{
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);
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);
}
}
}
}
+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
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;
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;
// 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