X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=protocol.c;h=db2de2f08ec155ba4bce8a5ed7aa4af8c2a102ab;hb=4774b89a8a498bbe6875a22c48f921068e51f349;hp=4f0139b502453f07d3407d205059e4ed8d531d3d;hpb=cfee52a1ec9db338098789cae89ae5cf1f7a6fbf;p=xonotic%2Fdarkplaces.git diff --git a/protocol.c b/protocol.c index 4f0139b5..db2de2f0 100644 --- a/protocol.c +++ b/protocol.c @@ -2062,6 +2062,31 @@ static int EntityState5_Priority(entityframe5_database_t *d, int stateindex) return bound(1, priority, ENTITYFRAME5_PRIORITYLEVELS - 1); } +static double anim_reducetime(double t, double frameduration, double maxtime) +{ + if(t < 0) // clamp to non-negative + return 0; + if(t <= maxtime) // time can be represented normally + return t; + if(frameduration == 0) // don't like dividing by zero + return t; + if(maxtime <= 2 * frameduration) // if two frames don't fit, we better not do this + return t; + t -= frameduration * ceil((t - maxtime) / frameduration); + // now maxtime - frameduration < t <= maxtime + return t; +} + +// see VM_SV_frameduration +static double anim_frameduration(dp_model_t *model, int framenum) +{ + if (!model || !model->animscenes || framenum < 0 || framenum >= model->numframes) + return 0; + if(model->animscenes[framenum].framerate) + return model->animscenes[framenum].framecount / model->animscenes[framenum].framerate; + return 0; +} + void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg) { prvm_prog_t *prog = SVVM_prog; @@ -2216,65 +2241,70 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi { int numbones = s->skeletonobject.model->num_bones; int bonenum; - short pose6s[6]; + short pose7s[7]; MSG_WriteByte(msg, 4); MSG_WriteShort(msg, s->modelindex); MSG_WriteByte(msg, numbones); for (bonenum = 0;bonenum < numbones;bonenum++) { - Matrix4x4_ToBonePose6s(s->skeletonobject.relativetransforms + bonenum, 64, pose6s); - MSG_WriteShort(msg, pose6s[0]); - MSG_WriteShort(msg, pose6s[1]); - MSG_WriteShort(msg, pose6s[2]); - MSG_WriteShort(msg, pose6s[3]); - MSG_WriteShort(msg, pose6s[4]); - MSG_WriteShort(msg, pose6s[5]); + Matrix4x4_ToBonePose7s(s->skeletonobject.relativetransforms + bonenum, 64, pose7s); + MSG_WriteShort(msg, pose7s[0]); + MSG_WriteShort(msg, pose7s[1]); + MSG_WriteShort(msg, pose7s[2]); + MSG_WriteShort(msg, pose7s[3]); + MSG_WriteShort(msg, pose7s[4]); + MSG_WriteShort(msg, pose7s[5]); + MSG_WriteShort(msg, pose7s[6]); } } - else if (s->framegroupblend[3].lerp > 0) - { - MSG_WriteByte(msg, 3); - MSG_WriteShort(msg, s->framegroupblend[0].frame); - MSG_WriteShort(msg, s->framegroupblend[1].frame); - MSG_WriteShort(msg, s->framegroupblend[2].frame); - MSG_WriteShort(msg, s->framegroupblend[3].frame); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[3].start) * 1000.0)); - MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f); - } - else if (s->framegroupblend[2].lerp > 0) - { - MSG_WriteByte(msg, 2); - MSG_WriteShort(msg, s->framegroupblend[0].frame); - MSG_WriteShort(msg, s->framegroupblend[1].frame); - MSG_WriteShort(msg, s->framegroupblend[2].frame); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[2].start) * 1000.0)); - MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f); - } - else if (s->framegroupblend[1].lerp > 0) - { - MSG_WriteByte(msg, 1); - MSG_WriteShort(msg, s->framegroupblend[0].frame); - MSG_WriteShort(msg, s->framegroupblend[1].frame); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0)); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[1].start) * 1000.0)); - MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); - MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); - } else { - MSG_WriteByte(msg, 0); - MSG_WriteShort(msg, s->framegroupblend[0].frame); - MSG_WriteShort(msg, (int)((sv.time - s->framegroupblend[0].start) * 1000.0)); + dp_model_t *model = SV_GetModelByIndex(s->modelindex); + if (s->framegroupblend[3].lerp > 0) + { + MSG_WriteByte(msg, 3); + MSG_WriteShort(msg, s->framegroupblend[0].frame); + MSG_WriteShort(msg, s->framegroupblend[1].frame); + MSG_WriteShort(msg, s->framegroupblend[2].frame); + MSG_WriteShort(msg, s->framegroupblend[3].frame); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[3].start, anim_frameduration(model, s->framegroupblend[3].frame), 65.535) * 1000.0)); + MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[3].lerp * 255.0f); + } + else if (s->framegroupblend[2].lerp > 0) + { + MSG_WriteByte(msg, 2); + MSG_WriteShort(msg, s->framegroupblend[0].frame); + MSG_WriteShort(msg, s->framegroupblend[1].frame); + MSG_WriteShort(msg, s->framegroupblend[2].frame); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[2].start, anim_frameduration(model, s->framegroupblend[2].frame), 65.535) * 1000.0)); + MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[2].lerp * 255.0f); + } + else if (s->framegroupblend[1].lerp > 0) + { + MSG_WriteByte(msg, 1); + MSG_WriteShort(msg, s->framegroupblend[0].frame); + MSG_WriteShort(msg, s->framegroupblend[1].frame); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0)); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[1].start, anim_frameduration(model, s->framegroupblend[1].frame), 65.535) * 1000.0)); + MSG_WriteByte(msg, s->framegroupblend[0].lerp * 255.0f); + MSG_WriteByte(msg, s->framegroupblend[1].lerp * 255.0f); + } + else + { + MSG_WriteByte(msg, 0); + MSG_WriteShort(msg, s->framegroupblend[0].frame); + MSG_WriteShort(msg, (int)(anim_reducetime(sv.time - s->framegroupblend[0].start, anim_frameduration(model, s->framegroupblend[0].frame), 65.535) * 1000.0)); + } } } if (bits & E5_TRAILEFFECTNUM) @@ -2287,6 +2317,8 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi static void EntityState5_ReadUpdate(entity_state_t *s, int number) { int bits; + int startoffset = cl_message.readcount; + int bytes = 0; bits = MSG_ReadByte(&cl_message); if (bits & E5_EXTEND1) { @@ -2405,7 +2437,7 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) int type; int bonenum; int numbones; - short pose6s[6]; + short pose7s[7]; type = MSG_ReadByte(&cl_message); switch(type) { @@ -2414,7 +2446,7 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) s->framegroupblend[1].frame = 0; s->framegroupblend[2].frame = 0; s->framegroupblend[3].frame = 0; - s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); s->framegroupblend[1].start = 0; s->framegroupblend[2].start = 0; s->framegroupblend[3].start = 0; @@ -2428,8 +2460,8 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) s->framegroupblend[1].frame = MSG_ReadShort(&cl_message); s->framegroupblend[2].frame = 0; s->framegroupblend[3].frame = 0; - s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); s->framegroupblend[2].start = 0; s->framegroupblend[3].start = 0; s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); @@ -2442,9 +2474,9 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) s->framegroupblend[1].frame = MSG_ReadShort(&cl_message); s->framegroupblend[2].frame = MSG_ReadShort(&cl_message); s->framegroupblend[3].frame = 0; - s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); s->framegroupblend[3].start = 0; s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); @@ -2456,10 +2488,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) s->framegroupblend[1].frame = MSG_ReadShort(&cl_message); s->framegroupblend[2].frame = MSG_ReadShort(&cl_message); s->framegroupblend[3].frame = MSG_ReadShort(&cl_message); - s->framegroupblend[0].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[1].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[2].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); - s->framegroupblend[3].start = cl.time - (short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[0].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[1].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[2].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); + s->framegroupblend[3].start = cl.time - (unsigned short)MSG_ReadShort(&cl_message) * (1.0f / 1000.0f); s->framegroupblend[0].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); s->framegroupblend[1].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); s->framegroupblend[2].lerp = MSG_ReadByte(&cl_message) * (1.0f / 255.0f); @@ -2483,13 +2515,14 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) } for (bonenum = 0;bonenum < numbones;bonenum++) { - pose6s[0] = (short)MSG_ReadShort(&cl_message); - pose6s[1] = (short)MSG_ReadShort(&cl_message); - pose6s[2] = (short)MSG_ReadShort(&cl_message); - pose6s[3] = (short)MSG_ReadShort(&cl_message); - pose6s[4] = (short)MSG_ReadShort(&cl_message); - pose6s[5] = (short)MSG_ReadShort(&cl_message); - Matrix4x4_FromBonePose6s(skeleton->relativetransforms + bonenum, 1.0f / 64.0f, pose6s); + pose7s[0] = (short)MSG_ReadShort(&cl_message); + pose7s[1] = (short)MSG_ReadShort(&cl_message); + pose7s[2] = (short)MSG_ReadShort(&cl_message); + pose7s[3] = (short)MSG_ReadShort(&cl_message); + pose7s[4] = (short)MSG_ReadShort(&cl_message); + pose7s[5] = (short)MSG_ReadShort(&cl_message); + pose7s[6] = (short)MSG_ReadShort(&cl_message); + Matrix4x4_FromBonePose7s(skeleton->relativetransforms + bonenum, 1.0f / 64.0f, pose7s); } s->skeletonobject = *skeleton; break; @@ -2502,9 +2535,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) s->traileffectnum = (unsigned short) MSG_ReadShort(&cl_message); + bytes = cl_message.readcount - startoffset; if (developer_networkentities.integer >= 2) { - Con_Printf("ReadFields e%i", number); + Con_Printf("ReadFields e%i (%i bytes)", number, bytes); if (bits & E5_ORIGIN) Con_Printf(" E5_ORIGIN %f %f %f", s->origin[0], s->origin[1], s->origin[2]); @@ -2557,6 +2591,10 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) Con_Printf(" E5_COLORMOD %f:%f:%f", s->colormod[0] / 32.0f, s->colormod[1] / 32.0f, s->colormod[2] / 32.0f); if (bits & E5_GLOWMOD) Con_Printf(" E5_GLOWMOD %f:%f:%f", s->glowmod[0] / 32.0f, s->glowmod[1] / 32.0f, s->glowmod[2] / 32.0f); + if (bits & E5_COMPLEXANIMATION) + Con_Printf(" E5_COMPLEXANIMATION"); + if (bits & E5_TRAILEFFECTNUM) + Con_Printf(" E5_TRAILEFFECTNUM %i", s->traileffectnum); Con_Print("\n"); } } @@ -2599,7 +2637,25 @@ static int EntityState5_DeltaBits(const entity_state_t *o, const entity_state_t if (o->glowmod[0] != n->glowmod[0] || o->glowmod[1] != n->glowmod[1] || o->glowmod[2] != n->glowmod[2]) bits |= E5_GLOWMOD; if (n->flags & RENDER_COMPLEXANIMATION) - bits |= E5_COMPLEXANIMATION; + { + if ((o->skeletonobject.model && o->skeletonobject.relativetransforms) != (n->skeletonobject.model && n->skeletonobject.relativetransforms)) + { + bits |= E5_COMPLEXANIMATION; + } + else if (o->skeletonobject.model && o->skeletonobject.relativetransforms) + { + if(o->modelindex != n->modelindex) + bits |= E5_COMPLEXANIMATION; + else if(o->skeletonobject.model->num_bones != n->skeletonobject.model->num_bones) + bits |= E5_COMPLEXANIMATION; + else if(memcmp(o->skeletonobject.relativetransforms, n->skeletonobject.relativetransforms, o->skeletonobject.model->num_bones * sizeof(*o->skeletonobject.relativetransforms))) + bits |= E5_COMPLEXANIMATION; + } + else if (memcmp(o->framegroupblend, n->framegroupblend, sizeof(o->framegroupblend))) + { + bits |= E5_COMPLEXANIMATION; + } + } if (o->traileffectnum != n->traileffectnum) bits |= E5_TRAILEFFECTNUM; } @@ -3209,7 +3265,6 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK; newsnap = d->snapshot + newsnapindex; memset(newsnap, 0, sizeof(*newsnap)); - oldsnapindex = -1; oldsnap = NULL; if (delta) {