WIP on interpolation flags rewrite, breaks network interpolation though

This commit is contained in:
UnknownShadow200 2022-10-29 20:05:35 +11:00
parent ceaf0658fc
commit 72694b5bdf
8 changed files with 144 additions and 87 deletions

View File

@ -84,7 +84,7 @@ static void PerspectiveCamera_UpdateMouseRotation(double delta) {
return;
}
update.flags = LU_INCLUDES_YAW | LU_INCLUDES_PITCH;
update.flags = LU_HAS_YAW | LU_HAS_PITCH;
update.yaw = e->next.yaw + rot.X;
update.pitch = e->next.pitch + rot.Y;
update.pitch = Math_ClampAngle(update.pitch);

View File

@ -631,7 +631,7 @@ static void TeleportCommand_Execute(const cc_string* args, int argsCount) {
return;
}
update.flags = LU_INCLUDES_POS;
update.flags = LU_HAS_POS;
update.pos = v;
e->VTABLE->SetLocation(e, &update);
}

View File

@ -508,7 +508,7 @@ void Entity_LerpAngles(struct Entity* e, float t) {
e->Pitch = Math_LerpAngle(prev->pitch, next->pitch, t);
e->Yaw = Math_LerpAngle(prev->yaw, next->yaw, t);
e->RotX = Math_LerpAngle(prev->rotX, next->rotX, t);
e->RotY = Math_LerpAngle(prev->rotY, next->rotY, t);
e->RotY = Math_LerpAngle(prev->rotY, next->rotY, t);
e->RotZ = Math_LerpAngle(prev->rotZ, next->rotZ, t);
}
@ -997,7 +997,7 @@ static void LocalPlayer_DoRespawn(void) {
/* it's obvious to the player that they are being respawned */
spawn.Y += 2.0f/16.0f;
update.flags = LU_INCLUDES_POS | LU_INCLUDES_YAW | LU_INCLUDES_PITCH;
update.flags = LU_HAS_POS | LU_HAS_YAW | LU_HAS_PITCH;
update.pos = spawn;
update.yaw = p->SpawnYaw;
update.pitch = p->SpawnPitch;
@ -1107,7 +1107,7 @@ void LocalPlayer_MoveToSpawn(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
struct LocationUpdate update;
update.flags = LU_INCLUDES_POS | LU_INCLUDES_YAW | LU_INCLUDES_PITCH;
update.flags = LU_HAS_POS | LU_HAS_YAW | LU_HAS_PITCH;
update.pos = p->Spawn;
update.yaw = p->SpawnYaw;
update.pitch = p->SpawnPitch;

View File

@ -32,20 +32,26 @@ extern const char* const ShadowMode_Names[SHADOW_MODE_COUNT];
enum EntityType { ENTITY_TYPE_NONE, ENTITY_TYPE_PLAYER };
/* Which fields are included/valid in a LocationUpdate */
#define LU_INCLUDES_POS 0x01
#define LU_INCLUDES_PITCH 0x02
#define LU_INCLUDES_YAW 0x04
#define LU_INCLUDES_ROTX 0x08
#define LU_INCLUDES_ROTZ 0x10
#define LU_HAS_POS 0x01
#define LU_HAS_PITCH 0x02
#define LU_HAS_YAW 0x04
#define LU_HAS_ROTX 0x08
#define LU_HAS_ROTZ 0x10
/* If set, then new position is calculated by adding current position to update->pos */
/* If not set, then new position is just update->pos */
#define LU_FLAG_RELATIVEPOS 0x20
/* TODO fill this in when implemented */
#define LU_FLAG_X 0x40
/* If set, then linearly interpolates between current and new state */
/* If not set, then current state is immediately updated to new state */
#define LU_FLAG_INTERPOLATE 0x80
/* How to move the entity when position field is included */
#define LU_POS_MODEMASK 0x60
/* Entity is instantly teleported to update->pos */
#define LU_POS_ABSOLUTE_INSTANT 0x00
/* Entity is smoothly moved to update->pos */
#define LU_POS_ABSOLUTE_SMOOTH 0x20
/* Entity is smoothly moved to current position + update->pos */
#define LU_POS_RELATIVE_SMOOTH 0x40
/* Entity is offset/shifted by update->pos */
#define LU_POS_RELATIVE_SHIFT 0x60
/* If set, then linearly interpolates between current and new angles */
/* If not set, then current angles are immediately updated to new angles */
#define LU_ORI_INTERPOLATE 0x80
/* Represents a location update for an entity. Can be a relative position, full position, and/or an orientation update. */
struct LocationUpdate {

View File

@ -313,61 +313,94 @@ static void InterpComp_AdvanceRotY(struct InterpComp* interp, struct Entity* e)
/*########################################################################################################################*
*----------------------------------------------NetworkInterpolationComponent----------------------------------------------*
*#########################################################################################################################*/
#define NetInterpState_Copy(dst, src) \
(dst).pos = (src)->Pos;\
#define NetInterpAngles_Copy(dst, src) \
(dst).pitch = (src)->Pitch;\
(dst).yaw = (src)->Yaw;\
(dst).rotX = (src)->RotX;\
(dst).rotZ = (src)->RotZ;
static void NetInterpComp_RemoveOldestState(struct NetInterpComp* interp) {
static void NetInterpComp_RemoveOldestPosition(struct NetInterpComp* interp) {
int i;
for (i = 0; i < Array_Elems(interp->States); i++) {
interp->States[i] = interp->States[i + 1];
interp->PositionsCount--;
for (i = 0; i < interp->PositionsCount; i++) {
interp->Positions[i] = interp->Positions[i + 1];
}
interp->StatesCount--;
}
static void NetInterpComp_AddState(struct NetInterpComp* interp, struct NetInterpState state) {
if (interp->StatesCount == Array_Elems(interp->States)) {
NetInterpComp_RemoveOldestState(interp);
static void NetInterpComp_AddPosition(struct NetInterpComp* interp, Vec3 pos) {
if (interp->PositionsCount == Array_Elems(interp->Positions)) {
NetInterpComp_RemoveOldestPosition(interp);
}
interp->States[interp->StatesCount] = state; interp->StatesCount++;
interp->Positions[interp->PositionsCount++] = pos;
}
static void NetInterpComp_SetPosition(struct NetInterpComp* interp, struct LocationUpdate* update, struct Entity* e, int mode) {
Vec3 lastPos = interp->CurPos;
Vec3* curPos = &interp->CurPos;
Vec3 midPos;
if (mode == LU_POS_ABSOLUTE_INSTANT || mode == LU_POS_ABSOLUTE_SMOOTH) {
*curPos = update->pos;
} else {
Vec3_AddBy(curPos, &update->pos);
}
if (mode == LU_POS_ABSOLUTE_INSTANT) {
e->prev.pos = *curPos;
e->next.pos = *curPos;
interp->PositionsCount = 0;
} else {
/* Smoother interpolation by also adding midpoint */
Vec3_Lerp(&midPos, &lastPos, curPos, 0.5f);
NetInterpComp_AddPosition(interp, midPos);
NetInterpComp_AddPosition(interp, *curPos);
}
}
static void NetInterpComp_RemoveOldestAngles(struct NetInterpComp* interp) {
int i;
interp->AnglesCount--;
for (i = 0; i < interp->AnglesCount; i++) {
interp->Angles[i] = interp->Angles[i + 1];
}
}
static void NetInterpComp_AddAngles(struct NetInterpComp* interp, struct NetInterpAngles angles) {
if (interp->AnglesCount == Array_Elems(interp->Angles)) {
NetInterpComp_RemoveOldestAngles(interp);
}
interp->Angles[interp->AnglesCount++] = angles;
}
void NetInterpComp_SetLocation(struct NetInterpComp* interp, struct LocationUpdate* update, struct Entity* e) {
struct NetInterpState last = interp->Cur;
struct NetInterpState* cur = &interp->Cur;
struct NetInterpState mid;
struct NetInterpAngles last = interp->CurAngles;
struct NetInterpAngles* cur = &interp->CurAngles;
struct NetInterpAngles mid;
cc_uint8 flags = update->flags;
cc_bool interpolate = flags & LU_FLAG_INTERPOLATE;
cc_bool interpolate = flags & LU_ORI_INTERPOLATE;
if (flags & LU_INCLUDES_POS) {
if (flags & LU_FLAG_RELATIVEPOS) {
Vec3_AddBy(&cur->Pos, &update->pos);
} else {
cur->Pos = update->pos;
}
if (flags & LU_HAS_POS) {
NetInterpComp_SetPosition(interp, update, e, flags & LU_POS_MODEMASK);
}
if (flags & LU_INCLUDES_ROTX) cur->RotX = Math_ClampAngle(update->rotX);
if (flags & LU_INCLUDES_ROTZ) cur->RotZ = Math_ClampAngle(update->rotZ);
if (flags & LU_INCLUDES_PITCH) cur->Pitch = Math_ClampAngle(update->pitch);
if (flags & LU_INCLUDES_YAW) cur->Yaw = Math_ClampAngle(update->yaw);
if (flags & LU_HAS_ROTX) cur->RotX = Math_ClampAngle(update->rotX);
if (flags & LU_HAS_ROTZ) cur->RotZ = Math_ClampAngle(update->rotZ);
if (flags & LU_HAS_PITCH) cur->Pitch = Math_ClampAngle(update->pitch);
if (flags & LU_HAS_YAW) cur->Yaw = Math_ClampAngle(update->yaw);
if (!interpolate) {
NetInterpState_Copy(e->prev, cur); e->prev.rotY = cur->Yaw;
NetInterpState_Copy(e->next, cur); e->next.rotY = cur->Yaw;
interp->RotYCount = 0; interp->StatesCount = 0;
NetInterpAngles_Copy(e->prev, cur); e->prev.rotY = cur->Yaw;
NetInterpAngles_Copy(e->next, cur); e->next.rotY = cur->Yaw;
interp->RotYCount = 0; interp->AnglesCount = 0;
} else {
/* Smoother interpolation by also adding midpoint. */
Vec3_Lerp(&mid.Pos, &last.Pos, &cur->Pos, 0.5f);
/* Smoother interpolation by also adding midpoint */
mid.RotX = Math_LerpAngle(last.RotX, cur->RotX, 0.5f);
mid.RotZ = Math_LerpAngle(last.RotZ, cur->RotZ, 0.5f);
mid.Pitch = Math_LerpAngle(last.Pitch, cur->Pitch, 0.5f);
mid.Yaw = Math_LerpAngle(last.Yaw, cur->Yaw, 0.5f);
NetInterpComp_AddState(interp, mid);
NetInterpComp_AddState(interp, *cur);
NetInterpComp_AddAngles(interp, mid);
NetInterpComp_AddAngles(interp, *cur);
/* Body rotation lags behind head a tiny bit */
InterpComp_AddRotY((struct InterpComp*)interp, Math_LerpAngle(last.Yaw, cur->Yaw, 0.33333333f));
@ -380,9 +413,13 @@ void NetInterpComp_AdvanceState(struct NetInterpComp* interp, struct Entity* e)
e->prev = e->next;
e->Position = e->prev.pos;
if (interp->StatesCount > 0) {
NetInterpState_Copy(e->next, &interp->States[0]);
NetInterpComp_RemoveOldestState(interp);
if (interp->PositionsCount) {
e->next.pos = interp->Positions[0];
NetInterpComp_RemoveOldestPosition(interp);
}
if (interp->AnglesCount) {
NetInterpAngles_Copy(e->next, &interp->Angles[0]);
NetInterpComp_RemoveOldestAngles(interp);
}
InterpComp_AdvanceRotY((struct InterpComp*)interp, e);
}
@ -391,6 +428,28 @@ void NetInterpComp_AdvanceState(struct NetInterpComp* interp, struct Entity* e)
/*########################################################################################################################*
*-----------------------------------------------LocalInterpolationComponent-----------------------------------------------*
*#########################################################################################################################*/
static void LocalInterpComp_SetPosition(struct LocationUpdate* update, int mode) {
struct Entity* e = &LocalPlayer_Instance.Base;
float yOffset;
if (mode == LU_POS_ABSOLUTE_INSTANT || mode == LU_POS_ABSOLUTE_SMOOTH) {
e->next.pos = update->pos;
} else if (mode == LU_POS_RELATIVE_SMOOTH) {
Vec3_AddBy(&e->next.pos, &update->pos);
} else if (mode == LU_POS_RELATIVE_SHIFT) {
Vec3_AddBy(&e->prev.pos, &update->pos);
Vec3_AddBy(&e->next.pos, &update->pos);
}
/* If server sets Y position exactly on ground, push up a tiny bit */
yOffset = e->next.pos.Y - Math_Floor(e->next.pos.Y);
if (yOffset < ENTITY_ADJUSTMENT) e->next.pos.Y += ENTITY_ADJUSTMENT;
if (mode == LU_POS_ABSOLUTE_INSTANT) {
e->prev.pos = e->next.pos; e->Position = e->next.pos;
}
}
static void LocalInterpComp_Angle(float* prev, float* next, float value, cc_bool interpolate) {
value = Math_ClampAngle(value);
*next = value;
@ -402,33 +461,22 @@ void LocalInterpComp_SetLocation(struct InterpComp* interp, struct LocationUpdat
struct EntityLocation* prev = &e->prev;
struct EntityLocation* next = &e->next;
cc_uint8 flags = update->flags;
cc_bool interpolate = flags & LU_FLAG_INTERPOLATE;
cc_bool interpolate = flags & LU_ORI_INTERPOLATE;
float yOffset;
if (flags & LU_INCLUDES_POS) {
if (flags & LU_FLAG_RELATIVEPOS) {
Vec3_AddBy(&next->pos, &update->pos);
} else {
next->pos = update->pos;
}
/* If server sets Y position exactly on ground, push up a tiny bit */
yOffset = next->pos.Y - Math_Floor(next->pos.Y);
if (yOffset < ENTITY_ADJUSTMENT) next->pos.Y += ENTITY_ADJUSTMENT;
if (!interpolate) { prev->pos = next->pos; e->Position = next->pos; }
if (flags & LU_HAS_POS) {
LocalInterpComp_SetPosition(update, flags & LU_POS_MODEMASK);
}
if (flags & LU_INCLUDES_PITCH) {
if (flags & LU_HAS_PITCH) {
LocalInterpComp_Angle(&prev->pitch, &next->pitch, update->pitch, interpolate);
}
if (flags & LU_INCLUDES_ROTX) {
if (flags & LU_HAS_ROTX) {
LocalInterpComp_Angle(&prev->rotX, &next->rotX, update->rotX, interpolate);
}
if (flags & LU_INCLUDES_ROTZ) {
if (flags & LU_HAS_ROTZ) {
LocalInterpComp_Angle(&prev->rotZ, &next->rotZ, update->rotZ, interpolate);
}
if (flags & LU_INCLUDES_YAW) {
if (flags & LU_HAS_YAW) {
LocalInterpComp_Angle(&prev->yaw, &next->yaw, update->yaw, interpolate);
if (!interpolate) {

View File

@ -84,16 +84,17 @@ struct InterpComp { InterpComp_Layout };
void LocalInterpComp_SetLocation(struct InterpComp* interp, struct LocationUpdate* update);
void LocalInterpComp_AdvanceState(struct InterpComp* interp, struct Entity* e);
/* Represents a network position and orientation state */
struct NetInterpState { Vec3 Pos; float Pitch, Yaw, RotX, RotZ; };
/* Represents a network orientation state */
struct NetInterpAngles { float Pitch, Yaw, RotX, RotZ; };
/* Entity component that performs interpolation for network players */
struct NetInterpComp {
InterpComp_Layout
/* Last known position and orientation sent by the server */
struct NetInterpState Cur;
int StatesCount;
struct NetInterpState States[10];
Vec3 CurPos; struct NetInterpAngles CurAngles;
/* Interpolated position and orientation state */
int PositionsCount, AnglesCount;
Vec3 Positions[10]; struct NetInterpAngles Angles[10];
};
void NetInterpComp_SetLocation(struct NetInterpComp* interp, struct LocationUpdate* update, struct Entity* e);

View File

@ -652,7 +652,7 @@ static cc_bool PushbackPlace(struct AABB* blockBB) {
return false;
}
update.flags = LU_INCLUDES_POS;
update.flags = LU_HAS_POS | LU_POS_ABSOLUTE_INSTANT;
update.pos = pos;
p->VTABLE->SetLocation(p, &update);
return true;
@ -711,7 +711,7 @@ static cc_bool CheckIsFree(BlockID block) {
/* Push player upwards when they are jumping and trying to place a block underneath them */
nextPos.Y = pos.Y + Blocks.MaxBB[block].Y + ENTITY_ADJUSTMENT;
update.flags = LU_INCLUDES_POS;
update.flags = LU_HAS_POS | LU_POS_ABSOLUTE_INSTANT;
update.pos = nextPos;
p->VTABLE->SetLocation(p, &update);
return true;

View File

@ -151,7 +151,8 @@ static void AddEntity(cc_uint8* data, EntityID id, const cc_string* name, const
Entity_SetName(e, name);
if (!readPosition) return;
Classic_ReadAbsoluteLocation(data, id, 0);
Classic_ReadAbsoluteLocation(data, id,
LU_HAS_POS | LU_HAS_YAW | LU_HAS_PITCH | LU_POS_ABSOLUTE_INSTANT);
if (id != ENTITIES_SELF_ID) return;
p->Spawn = p->Base.Position;
@ -600,14 +601,15 @@ static void Classic_AddEntity(cc_uint8* data) {
static void Classic_EntityTeleport(cc_uint8* data) {
EntityID id = *data++;
Classic_ReadAbsoluteLocation(data, id, LU_FLAG_INTERPOLATE);
Classic_ReadAbsoluteLocation(data, id,
LU_HAS_POS | LU_HAS_YAW | LU_HAS_PITCH | LU_ORI_INTERPOLATE);
}
static void Classic_RelPosAndOrientationUpdate(cc_uint8* data) {
struct LocationUpdate update;
EntityID id = data[0];
update.flags = LU_INCLUDES_POS | LU_INCLUDES_YAW | LU_INCLUDES_PITCH | LU_FLAG_RELATIVEPOS | LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_POS | LU_HAS_YAW | LU_HAS_PITCH | LU_POS_RELATIVE_SMOOTH | LU_ORI_INTERPOLATE;
update.pos.X = (cc_int8)data[1] / 32.0f;
update.pos.Y = (cc_int8)data[2] / 32.0f;
update.pos.Z = (cc_int8)data[3] / 32.0f;
@ -620,7 +622,7 @@ static void Classic_RelPositionUpdate(cc_uint8* data) {
struct LocationUpdate update;
EntityID id = data[0];
update.flags = LU_INCLUDES_POS | LU_FLAG_RELATIVEPOS | LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_POS | LU_POS_RELATIVE_SMOOTH | LU_ORI_INTERPOLATE;
update.pos.X = (cc_int8)data[1] / 32.0f;
update.pos.Y = (cc_int8)data[2] / 32.0f;
update.pos.Z = (cc_int8)data[3] / 32.0f;
@ -631,7 +633,7 @@ static void Classic_OrientationUpdate(cc_uint8* data) {
struct LocationUpdate update;
EntityID id = data[0];
update.flags = LU_INCLUDES_YAW | LU_INCLUDES_PITCH| LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_YAW | LU_HAS_PITCH | LU_ORI_INTERPOLATE;
update.yaw = Math_Packed2Deg(data[1]);
update.pitch = Math_Packed2Deg(data[2]);
UpdateLocation(id, &update);
@ -701,7 +703,7 @@ static void Classic_ReadAbsoluteLocation(cc_uint8* data, EntityID id, cc_uint8 f
/* so to simplify things, just always add 22 to Y*/
if (id == ENTITIES_SELF_ID) y += 22;
update.flags = LU_INCLUDES_POS | LU_INCLUDES_PITCH | LU_INCLUDES_YAW | flags;
update.flags = flags;
update.pos.X = x/32.0f;
update.pos.Y = y/32.0f;
update.pos.Z = z/32.0f;
@ -1281,13 +1283,13 @@ static void CPE_SetEntityProperty(cc_uint8* data) {
switch (type) {
case 0:
update.flags = LU_INCLUDES_ROTX | LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_ROTX | LU_ORI_INTERPOLATE;
update.rotX = (float)value; break;
case 1:
update.flags = LU_INCLUDES_YAW | LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_YAW | LU_ORI_INTERPOLATE;
update.yaw = (float)value; break;
case 2:
update.flags = LU_INCLUDES_ROTZ | LU_FLAG_INTERPOLATE;
update.flags = LU_HAS_ROTZ | LU_ORI_INTERPOLATE;
update.rotZ = (float)value; break;
case 3: