]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
experimental animation blending
authorRudolf Polzer <divverent@xonotic.org>
Tue, 4 Dec 2012 16:27:36 +0000 (17:27 +0100)
committerRudolf Polzer <divverent@xonotic.org>
Tue, 4 Dec 2012 16:27:36 +0000 (17:27 +0100)
(set _animblend 1 to test it)

qcsrc/client/autocvars.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/player_skeleton.qc [new file with mode: 0644]
qcsrc/client/player_skeleton.qh [new file with mode: 0644]
qcsrc/client/progs.src

index 0d4513f92b802a351f83883eecd5ed8e430d1d2f..85829e809abbcd018076b5dcb7f9ab3b06434d59 100644 (file)
@@ -402,3 +402,4 @@ string autocvar__cl_playermodel;
 float autocvar_cl_precacheplayermodels;
 float autocvar_cl_deathglow;
 float autocvar_developer_csqcentities;
+float autocvar__animblend;
index 7caa36c560faa95578ea78da2a6f475dc78e1129..d850ef3d3770881bbaebb7d9c1483b0b25e05bd2 100644 (file)
@@ -588,7 +588,7 @@ void CSQCModel_Hook_PreDraw(float isplayer)
                else
                {
                        // we know that frame3 and frame4 fields, used by InterpolateAnimation, are left alone - but that is all we know!
-                       float doblend = FALSE;
+                       float doblend = autocvar__animblend;
                        float flg = 0;
                        if(self == csqcplayer)
                        {
@@ -630,12 +630,14 @@ void CSQCModel_Hook_PreDraw(float isplayer)
                        CSQCModel_InterpolateAnimation_2To4_Do();
                        if(doblend)
                        {
-                               // build a skeletonobject
+                               skeleton_from_frames(self);
                        }
                        else
                        {
-                               // remove skeletonobject if any
-                               // all is done
+                               free_skeleton_from_frames(self);
+                               // just in case, clear these
+                               self.lerpfrac3 = 0;
+                               self.lerpfrac4 = 0;
                        }
                }
        }
diff --git a/qcsrc/client/player_skeleton.qc b/qcsrc/client/player_skeleton.qc
new file mode 100644 (file)
index 0000000..25ab266
--- /dev/null
@@ -0,0 +1,90 @@
+.float skeleton_modelindex;
+#define BONETYPE_LOWER 0
+#define BONETYPE_UPPER 1
+#define MAX_BONES 128
+.float skeleton_bonetype[MAX_BONES];
+.float skeleton_aimbone;
+.float skeleton_numbones;
+
+void skeleton_identifybones(entity e)
+{
+       float s = e.skeletonindex;
+       float n = (e.skeleton_numbones = skel_get_numbones(s));
+       e.skeleton_aimbone = 0;
+       float i;
+       for(i = 1; i <= n; ++i)
+       {
+               float t = BONETYPE_LOWER;
+               float p = skel_get_boneparent(s, i);
+               if(p > 0)
+                       t = e.(skeleton_bonetype[p-1]);
+               string nm = skel_get_bonename(s, i);
+               if(nm == "spine2")
+                       t = BONETYPE_UPPER;
+               if(nm == "upperarm_R")
+                       e.skeleton_aimbone = i;
+               e.(skeleton_bonetype[i-1]) = t;
+       }
+}
+
+void free_skeleton_from_frames(entity e)
+{
+       if(e.skeletonindex)
+       {
+               skel_delete(e.skeletonindex);
+               e.skeletonindex = 0;
+       }
+}
+
+void skeleton_from_frames(entity e)
+{
+       float m = e.modelindex;
+       if(m != e.skeleton_modelindex)
+       {
+               if(e.skeletonindex)
+               {
+                       skel_delete(e.skeletonindex);
+                       e.skeletonindex = 0;
+               }
+               m = (e.skeleton_modelindex = e.modelindex);
+               if(m)
+               {
+                       e.skeletonindex = skel_create(m);
+                       skeleton_identifybones(e);
+               }
+       }
+       float s = e.skeletonindex;
+       if(!s)
+               return;
+       float bone;
+       float n = e.skeleton_numbones;
+       float savelerpfrac = e.lerpfrac;
+       float savelerpfrac3 = e.lerpfrac3;
+       float savelerpfrac4 = e.lerpfrac4;
+       for(bone = 0; bone < n; )
+       {
+               float firstbone = bone;
+               float bonetype = e.skeleton_bonetype[bone];
+               for(++bone; (bone < n) && (e.skeleton_bonetype[bone] == bonetype); ++bone)
+                       ;
+               float lastbone = bone - 1;
+               if(bonetype == BONETYPE_LOWER)
+               {
+                       // only show frames 1+3
+                       e.lerpfrac = 0;
+                       e.lerpfrac3 = savelerpfrac3 * 2;
+                       e.lerpfrac4 = 0;
+               }
+               else
+               {
+                       // only show frames 2+4
+                       e.lerpfrac = savelerpfrac * 2;
+                       e.lerpfrac3 = 0;
+                       e.lerpfrac4 = savelerpfrac4 * 2;
+               }
+               skel_build(s, e, m, 0, firstbone + 1, bone);
+       }
+       e.lerpfrac = savelerpfrac;
+       e.lerpfrac3 = savelerpfrac;
+       e.lerpfrac4 = savelerpfrac;
+}
diff --git a/qcsrc/client/player_skeleton.qh b/qcsrc/client/player_skeleton.qh
new file mode 100644 (file)
index 0000000..292cfca
--- /dev/null
@@ -0,0 +1,2 @@
+void free_skeleton_from_frames(entity e);
+void skeleton_from_frames(entity e);
index 8c98a07b709031647c733cf06539fcaa5e8e94ac..9d968f1fe7d86e1ceeecf09b135c6dcc1e23d4f7 100644 (file)
@@ -50,6 +50,7 @@ vehicles/vehicles.qh
 ../csqcmodellib/cl_model.qh
 ../csqcmodellib/cl_player.qh
 projectile.qh
+player_skeleton.qh
 
 sortlist.qc
 miscfunctions.qc
@@ -112,6 +113,7 @@ command/cl_cmd.qc
 ../warpzonelib/client.qc
 tturrets.qc
 
+player_skeleton.qc
 ../common/animdecide.qc
 
 ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail