From: divverent Date: Sat, 12 Nov 2011 11:17:38 +0000 (+0000) Subject: complexanimation now beginning to be suitable for SVQC use X-Git-Tag: xonotic-v0.6.0~163^2~13 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=bfebdee6f90da32974e4305a33ed15c72ad0a5dc;p=xonotic%2Fdarkplaces.git complexanimation now beginning to be suitable for SVQC use - only set E5_COMPLEXANIMATION flag when required to save a LOT of bandwidth - don't also send a legacy frame number when using complex animation to save a bit more - no more support of "anims that start in the future", use a QC think function to handle them - fix wraparound logic for complex animation (if a model animation is shorter than 30 sec, it won't jerk when playing the same anim for over a minute) Bandwidth use per update message: - simple anim: 1 byte - 1 blends: 5 bytes - 2 blends: 11 bytes - 3 blends: 16 bytes - 4 blends: 21 bytes - skeletonobject: 4 + 12*bonecount bytes git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11546 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/protocol.c b/protocol.c index 4f0139b5..d63d0918 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; @@ -2231,50 +2256,54 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi MSG_WriteShort(msg, pose6s[5]); } } - 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) @@ -2414,7 +2443,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 +2457,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 +2471,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 +2485,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); @@ -2599,7 +2628,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; } diff --git a/sv_main.c b/sv_main.c index 21e34361..27befbcf 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1362,6 +1362,7 @@ static qboolean SV_PrepareEntityForSending (prvm_edict_t *ent, entity_state_t *c cs->framegroupblend[2].lerp = PRVM_serveredictfloat(ent, lerpfrac3); cs->framegroupblend[3].lerp = PRVM_serveredictfloat(ent, lerpfrac4); cs->framegroupblend[0].lerp = 1.0f - cs->framegroupblend[1].lerp - cs->framegroupblend[2].lerp - cs->framegroupblend[3].lerp; + cs->frame = 0; // don't need the legacy frame } cs->light[0] = light[0];