OSDN Git Service

Rewrite animation engine
authorRobin Cornelius <robin.cornelius@gmail.com>
Sun, 18 Mar 2012 17:39:24 +0000 (17:39 +0000)
committerRobin Cornelius <robin.cornelius@gmail.com>
Sun, 18 Mar 2012 17:39:24 +0000 (17:39 +0000)
git-svn-id: https://radegast.googlecode.com/svn/trunk@1229 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/GUI/Rendering/RenderAvatar.cs

index d436533..f207edd 100644 (file)
@@ -898,6 +898,7 @@ namespace Radegast.Rendering
         public bool mNeedsUpdate = false;
         public bool mNeedsMeshRebuild = true;
 
+
         public struct binBVHJointState
         {
             public float currenttime_rot;
@@ -909,7 +910,9 @@ namespace Radegast.Rendering
             public int nextkeyframe_pos;
 
             public int loopinframe;
-            public int loopoutframe;
+            public int loopoutframe;\r
+\r
+            public bool finished;
         }
 
 
@@ -1015,7 +1018,7 @@ namespace Radegast.Rendering
         {
             Bone b;
             if (mBones.TryGetValue(bonename, out b))
-            {
+            {\r
                 return (b.getTotalOffset());
             }
             else
@@ -1079,7 +1082,11 @@ namespace Radegast.Rendering
                 state.currenttime_pos = 0;
 
                 state.loopinframe = 0;
-                state.loopoutframe = joint.rotationkeys.Length - 1;
+                state.loopoutframe = joint.rotationkeys.Length - 1;\r
+\r
+                state.finished = false;
+
+               
 
                 if (b.Loop == true)
                 {
@@ -1110,9 +1117,208 @@ namespace Radegast.Rendering
             {
                 av.glavatar.skel.mAnimations.Add(b);
             }
+        }\r
+\r
+        public void animate(float lastframetime)\r
+        {\r
+          \r
+            lock (mAnimations)\r
+            {\r
+                foreach (BinBVHAnimationReader b in mAnimations)\r
+                {\r
+                    if (b == null)\r
+                        continue;\r
+\r
+                    int jpos = 0;\r
+                    foreach (binBVHJoint joint in b.joints)\r
+                    {\r
+                        //warning struct copy non reference\r
+                        binBVHJointState state = (binBVHJointState)b.joints[jpos].Tag;\r
+\r
+                        int prio = 0;\r
+                        //Quick hack to stack animations in the correct order\r
+                        //TODO we need to do this per joint as they all have their own priorities as well ;-(\r
+                        if (mPriority.TryGetValue(joint.Name, out prio))\r
+                        {\r
+                            if (prio > (b.Priority + joint.Priority))\r
+                                continue;\r
+                        }\r
+\r
+                        mPriority[joint.Name] = b.Priority+joint.Priority;\r
+\r
+                        if (state.finished == true)\r
+                            continue;\r
+\r
+                        Vector3 poslerp = Vector3.Zero;\r
+                        Quaternion rotlerp = Quaternion.Identity;\r
+\r
+                        // Position\r
+\r
+                        if ( b.joints[jpos].positionkeys.Length >= 2 && joint.Name == "mPelvis")\r
+                        {\r
+\r
+                            //Console.WriteLine("Animate time " + state.currenttime_pos.ToString());\r
+\r
+                            state.currenttime_pos += lastframetime;\r
+\r
+                            float currentime = state.currenttime_pos;\r
+                            bool overrun = false;\r
+\r
+                            if (state.currenttime_pos > b.OutPoint)\r
+                            {\r
+                                //overrun state\r
+                                int itterations = (int)(state.currenttime_pos / b.OutPoint) + 1;\r
+                                state.currenttime_pos = currentime = (b.OutPoint - b.InPoint) - (((b.OutPoint - b.InPoint) * itterations) - state.currenttime_pos);\r
+                                overrun = true;\r
+                            }\r
+\r
+                            binBVHJointKey pos_next = b.joints[jpos].positionkeys[state.nextkeyframe_pos];\r
+                            binBVHJointKey pos_last = b.joints[jpos].positionkeys[state.lastkeyframe_pos];\r
+\r
+                            // if the current time > than next key frame time we move keyframes\r
+                            if (currentime >= pos_next.time || overrun)\r
+                            {\r
+\r
+                                //Console.WriteLine("bump");\r
+                                state.lastkeyframe_pos++;\r
+                                state.nextkeyframe_pos++;\r
+\r
+                                if (b.Loop)\r
+                                {\r
+                                    if (state.nextkeyframe_pos > state.loopoutframe)\r
+                                        state.nextkeyframe_pos = state.loopinframe;\r
+\r
+                                    if (state.lastkeyframe_pos > state.loopoutframe)\r
+                                        state.lastkeyframe_pos = state.loopinframe;\r
+\r
+\r
+                                    if (state.nextkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                        state.nextkeyframe_pos = state.loopinframe;\r
+\r
+                                    if (state.lastkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                        state.lastkeyframe_pos = state.loopinframe;\r
+\r
+                                }\r
+                                else\r
+                                {\r
+                                    if(state.nextkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                        state.nextkeyframe_pos = b.joints[jpos].positionkeys.Length-1;\r
+\r
+                                    if (state.lastkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                    {\r
+                                        state.lastkeyframe_pos = b.joints[jpos].positionkeys.Length - 1;\r
+                                        state.finished = true;\r
+                                        //animation over\r
+                                    }\r
+                                }\r
+                            }\r
+\r
+                            if (pos_next.time == pos_last.time)\r
+                            {\r
+                                state.finished = true;\r
+                            }\r
+\r
+                            // update the pointers incase they have been moved\r
+                            pos_next = b.joints[jpos].positionkeys[state.nextkeyframe_pos];\r
+                            pos_last = b.joints[jpos].positionkeys[state.lastkeyframe_pos];\r
+\r
+                            float delta = state.currenttime_pos - pos_last.time / (pos_next.time - pos_last.time);\r
+\r
+                            delta = Utils.Clamp(delta, 0f, 1f);\r
+\r
+                            poslerp = Vector3.Lerp(pos_last.key_element, pos_next.key_element, delta);\r
+\r
+                            //Console.WriteLine(string.Format("Time {0} {1} {2} {3} {4}", state.currenttime_pos, delta, poslerp.ToString(), state.lastkeyframe_pos, state.nextkeyframe_pos));\r
+\r
+                        }\r
+\r
+                        // end of position\r
+\r
+                        //rotation\r
+                        \r
+                        if ( b.joints[jpos].rotationkeys.Length >= 2)\r
+                        {\r
+\r
+                            state.currenttime_rot += lastframetime;\r
+\r
+                            float currentime = state.currenttime_rot;\r
+                            bool overrun = false;\r
+\r
+                            if (state.currenttime_rot > b.OutPoint)\r
+                            {\r
+                                //overrun state\r
+                                int itterations = (int)(state.currenttime_rot / b.OutPoint) + 1;\r
+                                state.currenttime_rot = currentime = (b.OutPoint - b.InPoint) - (((b.OutPoint - b.InPoint) * itterations) - state.currenttime_rot);\r
+                                overrun = true;\r
+                            }\r
+\r
+                            binBVHJointKey rot_next = b.joints[jpos].rotationkeys[state.nextkeyframe_rot];\r
+                            binBVHJointKey rot_last = b.joints[jpos].rotationkeys[state.lastkeyframe_rot];\r
+\r
+                            // if the current time > than next key frame time we move keyframes\r
+                            if (currentime >= rot_next.time || overrun)\r
+                            {\r
+\r
+                                state.lastkeyframe_rot++;\r
+                                state.nextkeyframe_rot++;\r
+\r
+                                if (b.Loop)\r
+                                {\r
+                                    if (state.nextkeyframe_rot > state.loopoutframe)\r
+                                        state.nextkeyframe_rot = state.loopinframe;\r
+\r
+                                    if (state.lastkeyframe_rot > state.loopoutframe)\r
+                                        state.lastkeyframe_rot = state.loopinframe;\r
+\r
+                                }\r
+                                else\r
+                                {\r
+                                    if (state.nextkeyframe_rot >= b.joints[jpos].rotationkeys.Length)\r
+                                        state.nextkeyframe_rot = b.joints[jpos].rotationkeys.Length - 1;\r
+\r
+                                    if (state.lastkeyframe_rot >= b.joints[jpos].rotationkeys.Length)\r
+                                    {\r
+                                        state.lastkeyframe_rot = b.joints[jpos].rotationkeys.Length - 1;\r
+                                        state.finished = true;\r
+                                        //animation over\r
+                                    }\r
+                                }\r
+                            }\r
+\r
+                            if (rot_next.time == rot_last.time)\r
+                            {\r
+                                state.finished = true;\r
+                            }\r
+\r
+                            // update the pointers incase they have been moved\r
+                            rot_next = b.joints[jpos].rotationkeys[state.nextkeyframe_rot];\r
+                            rot_last = b.joints[jpos].rotationkeys[state.lastkeyframe_rot];\r
+\r
+                            float delta = state.currenttime_rot - rot_last.time / (rot_next.time - rot_last.time);\r
+                            delta = Utils.Clamp(delta, 0f, 1f);\r
+\r
+                            Vector3 rotlerpv = Vector3.Lerp(rot_last.key_element, rot_next.key_element, delta);\r
+                            rotlerp = new Quaternion(rotlerpv.X, rotlerpv.Y, rotlerpv.Z);\r
+                          \r
+                        }\r
+                        \r
+\r
+                        //end of rotation\r
+\r
+                        deformbone(joint.Name, poslerp, rotlerp);\r
+                        mNeedsMeshRebuild = true;\r
+\r
+                        //warning struct copy non reference\r
+                        b.joints[jpos].Tag = state;\r
+\r
+                        jpos++;\r
+                    }\r
+                }\r
+            }\r
+\r
         }
 
-        public void animate(float lastframetime)
+        public void animateold(float lastframetime)
         {
           
             try
@@ -1155,7 +1361,7 @@ namespace Radegast.Rendering
 
                                 Vector3 poslerp = Vector3.Zero;\r
 \r
-                                //if (joint.Name == "mPelvis")\r
+                                if ( joint.Name == "mPelvis")\r
                                 {\r
 \r
                                     if (b.joints[jpos].positionkeys.Length > 2)\r
@@ -1211,7 +1417,7 @@ namespace Radegast.Rendering
                                         if (state.currenttime_pos != ((pos.time - b.joints[jpos].positionkeys[0].time)))\r
                                         {\r
 \r
-                                            float delta = (pos2.time - pos.time) / ((state.currenttime_pos) - (pos.time - b.joints[jpos].positionkeys[0].time));\r
+                                            float delta = (pos2.time - pos.time) / ((state.currenttime_pos) - (pos.time - b.joints[jpos].positionkeys[0].time)) ;\r
 \r
                                             if (delta < 0)\r
                                                 delta = 0;\r
@@ -1292,7 +1498,7 @@ namespace Radegast.Rendering
 
                                 b.joints[jpos].Tag = (object)state;
 
-                                deformbone(joint.Name, poslerp, new Quaternion(rotlerp.X, rotlerp.Y, rotlerp.Z));\r
+                                deformbone(joint.Name, poslerp*40, new Quaternion(rotlerp.X, rotlerp.Y, rotlerp.Z));\r
                               
 
                                 jpos++;
@@ -1314,8 +1520,8 @@ namespace Radegast.Rendering
 
     public class Bone
     {
-        public string name;
-        public Vector3 pos;
+        public string name;\r
+        private Vector3 pos;
         public Quaternion rot;
         public Vector3 scale;
         public Vector3 piviot;
@@ -1327,7 +1533,9 @@ namespace Radegast.Rendering
         public Vector3 orig_scale;
         public Vector3 orig_piviot;
 
-        Matrix4 mDeformMatrix = Matrix4.Identity;
+        Matrix4 mDeformMatrix = Matrix4.Identity;\r
+\r
+        public Vector3 animation_offset;
 
         public Bone parent;
 
@@ -1433,13 +1641,18 @@ namespace Radegast.Rendering
 
         }
 
-        public void deformbone(Vector3 pos, Quaternion rot)
+        public void deformbone(Vector3 dpos, Quaternion rot)
         {
             //float[] deform = Math3D.CreateSRTMatrix(scale, rot, this.orig_pos);
             //mDeformMatrix = new Matrix4(deform[0], deform[1], deform[2], deform[3], deform[4], deform[5], deform[6], deform[7], deform[8], deform[9], deform[10], deform[11], deform[12], deform[13], deform[14], deform[15]);\r
 \r
-            this.offset_pos += pos;
-            //this.pos = Bone.mBones[name].offset_pos + pos;
+            //this.offset_pos += pos;\r
+            //this.pos = pos;\r
+           // this.offset_pos = pos;\r
+\r
+            animation_offset = dpos;
+
+            //this.pos = Bone.mBones[name].offset_pos + dpos;
             this.rot = Bone.mBones[name].orig_rot * rot;
 
             markdirty();
@@ -1447,7 +1660,6 @@ namespace Radegast.Rendering
 
         public void scalebone(Vector3 scale)
         {
-         //  this.scale = Bone.mBones[name].orig_scale * scale;
             this.scale *= scale;
             markdirty();
         }
@@ -1486,8 +1698,8 @@ namespace Radegast.Rendering
             if (parent != null)
             {
                 Quaternion totalrot = getParentRot(); // we don't want this joints rotation included
-                Vector3 parento = parent.getOffset();
-                mTotalPos = parento + pos * parent.scale * totalrot;
+                Vector3 parento = parent.getOffset();\r
+                mTotalPos =  parento + pos * parent.scale * totalrot;
                 Vector3 orig = getOrigOffset();
                 mDeltaPos = mTotalPos - orig;
 
@@ -1499,8 +1711,8 @@ namespace Radegast.Rendering
             {
                 Vector3 orig = getOrigOffset();
                 //mTotalPos = (pos * scale)+offset_pos;
-                //mTotalPos = (pos) + offset_pos;
-                mTotalPos = pos;
+                //mTotalPos = (pos) + offset_pos;\r
+                mTotalPos = animation_offset + pos;
                 mDeltaPos = mTotalPos - orig;
                 posdirty = false;
                 return mTotalPos;