OSDN Git Service

Connect up avatar animations so that they work with the skinning and skeleton system
authorRobin Cornelius <robin.cornelius@gmail.com>
Wed, 27 Jul 2011 20:24:26 +0000 (20:24 +0000)
committerRobin Cornelius <robin.cornelius@gmail.com>
Wed, 27 Jul 2011 20:24:26 +0000 (20:24 +0000)
git-svn-id: https://radegast.googlecode.com/svn/trunk@1013 f7a694da-4d33-11de-9ad6-1127a62b9fcd

Radegast/GUI/Rendering/Rendering.cs
Radegast/GUI/Rendering/RenderingHelpers.cs

index 140dd1f..f2acde6 100644 (file)
@@ -406,11 +406,19 @@ namespace Radegast.Rendering
                 {\r
                     foreach (Animation anim in e.Animations)\r
                     {\r
-                        if (av.glavatar.skel.addplayinganimation(anim))\r
+                        UUID tid = UUID.Random();\r
+                        skeleton.mAnimationTransactions.Add(tid, av);\r
+\r
+                        BinBVHAnimationReader bvh;\r
+                        if(skeleton.mAnimationCache.TryGetValue(anim.AnimationID,out bvh))\r
                         {\r
-                            Logger.Log("Requesting new animation asset " + anim.AnimationID.ToString(), Helpers.LogLevel.Info);\r
-                            Client.Assets.RequestAsset(anim.AnimationID, AssetType.Animation, false, animRecievedCallback);\r
+                            skeleton.addanimation(null, tid, bvh);\r
+                            break;\r
                         }\r
+\r
+                        Logger.Log("Requesting new animation asset " + anim.AnimationID.ToString(), Helpers.LogLevel.Info);\r
+                       \r
+                        Client.Assets.RequestAsset(anim.AnimationID, AssetType.Animation, false,SourceType.Asset,tid, animRecievedCallback);  \r
                     }\r
                     break;\r
                 }\r
@@ -420,8 +428,8 @@ namespace Radegast.Rendering
         void animRecievedCallback(AssetDownload transfer, Asset asset)\r
         {\r
             if (transfer.Success)\r
-            {\r
-                skeleton.addanimation(asset);\r
+            {        \r
+                skeleton.addanimation(asset,transfer.ID, null);\r
             }\r
         }\r
 \r
@@ -1200,7 +1208,7 @@ namespace Radegast.Rendering
 \r
                     attachment_point apoint = GLAvatar.attachment_points[attachment_index];\r
                     Vector3 point = parentav.glavatar.skel.getOffset(apoint.joint) + apoint.position;\r
-                    Quaternion qrot = parentav.glavatar.skel.getRotation(apoint.joint) * apoint.rotation;\r
+                    Quaternion qrot = apoint.rotation * parentav.glavatar.skel.getRotation(apoint.joint);\r
 \r
                     pos = parentPos + point * parentRot + prim.InterpolatedPosition * (parentRot * qrot);\r
                     rot = qrot * parentRot * prim.InterpolatedRotation;\r
@@ -1411,7 +1419,7 @@ namespace Radegast.Rendering
 \r
                     // Prim roation and position\r
                     Vector3 pos = av.avatar.Position;\r
-                    pos.X += 1;\r
+                    pos.X += 1;               \r
 \r
                     GL.MultMatrix(Math3D.CreateSRTMatrix(new Vector3(1, 1, 1), av.avatar.Rotation, pos));\r
 \r
@@ -1518,6 +1526,8 @@ namespace Radegast.Rendering
                         av.glavatar.skel.mNeedsMeshRebuild = false;\r
                     }\r
 \r
+                    av.glavatar.skel.animate(lastFrameTime);\r
+\r
                     avatarNr++;\r
 \r
                     if (av.glavatar._meshes.Count > 0)\r
index 1e16733..bafc7d8 100644 (file)
@@ -1424,7 +1424,10 @@ namespace Radegast.Rendering
                     if (jointname == "")\r
                     {\r
                         //Don't yet handle this, its a split joint to two children\r
-                        continue;\r
+                        ba = av.skel.mBones[jointname2];\r
+                        bb = null;\r
+\r
+                        //continue;\r
                     }\r
                     else\r
                     {\r
@@ -1738,11 +1741,17 @@ namespace Radegast.Rendering
             if (VisualParamEx.allParams.TryGetValue(param, out vpx))\r
             {\r
 \r
-                Logger.Log(string.Format("Applying visual parameter {0} id {1} value {2}", vpx.Name, vpx.ParamID, weight), Helpers.LogLevel.Info);\r
+                //Logger.Log(string.Format("Applying visual parameter {0} id {1} value {2}", vpx.Name, vpx.ParamID, weight), Helpers.LogLevel.Info);\r
 \r
                 //weight = weight * 2.0f;\r
                 //weight=weight-1.0f;\r
 \r
+                if (weight < 0)\r
+                    weight = 0;\r
+\r
+                if (weight > 1.0)\r
+                    weight = 1;\r
+\r
                 float value = vpx.MinValue + ((vpx.MaxValue - vpx.MinValue) * weight);\r
 \r
                 if (vpx.pType == VisualParamEx.ParamType.TYPE_MORPH)\r
@@ -1941,8 +1950,11 @@ namespace Radegast.Rendering
         public static Dictionary<int, string> mLowerMeshMapping = new Dictionary<int, string>();\r
         public static Dictionary<int, string> mHeadMeshMapping = new Dictionary<int, string>();\r
 \r
-        public static Dictionary<UUID, BinBVHAnimationReader> mKnownAnimations = new Dictionary<UUID, BinBVHAnimationReader>();\r
-        public Dictionary<UUID, Animation> animlist = new Dictionary<UUID, Animation>();\r
+        public BinBVHAnimationReader[] mPlayingAnimations = new BinBVHAnimationReader[6];\r
+\r
+        public static Dictionary<UUID, RenderAvatar> mAnimationTransactions = new Dictionary<UUID, RenderAvatar>();\r
+\r
+        public static Dictionary<UUID, BinBVHAnimationReader> mAnimationCache = new Dictionary<UUID, BinBVHAnimationReader>();\r
 \r
         public bool mNeedsUpdate = false;\r
         public bool mNeedsMeshRebuild = false;\r
@@ -1950,9 +1962,23 @@ namespace Radegast.Rendering
         public Bone mLeftEye = null;\r
         public Bone mRightEye = null;\r
 \r
+        public struct binBVHJointState\r
+        {\r
+            public float currenttime_rot;\r
+            public int lastkeyframe_rot;\r
+            public int nextkeyframe_rot;\r
+\r
+            public float currenttime_pos;\r
+            public int lastkeyframe_pos;\r
+            public int nextkeyframe_pos;\r
+        }\r
+\r
+\r
         public skeleton()\r
         {\r
 \r
+            \r
+\r
             mBones = new Dictionary<string, Bone>();\r
 \r
             foreach (Bone src in Bone.mBones.Values)\r
@@ -2050,62 +2076,187 @@ namespace Radegast.Rendering
 \r
         // Add animations to the global decoded list\r
         // TODO garbage collect unused animations somehow\r
-        public static void addanimation(OpenMetaverse.Assets.Asset asset)\r
+        public static void addanimation(OpenMetaverse.Assets.Asset asset,UUID tid, BinBVHAnimationReader b)\r
         {\r
-            BinBVHAnimationReader b = new BinBVHAnimationReader(asset.AssetData);\r
-            if (!mKnownAnimations.ContainsKey(asset.AssetID))\r
+            RenderAvatar av;\r
+            mAnimationTransactions.TryGetValue(tid, out av);\r
+            if (av == null)\r
+                return;\r
+\r
+            mAnimationTransactions.Remove(tid);\r
+\r
+            if (asset != null)\r
             {\r
+                b = new BinBVHAnimationReader(asset.AssetData);\r
+                mAnimationCache[asset.AssetID] = b;\r
                 Logger.Log("Adding new decoded animaton known animations " + asset.AssetID.ToString(), Helpers.LogLevel.Info);\r
-                mKnownAnimations.Add(asset.AssetID, b);\r
             }\r
-        }\r
+            \r
+            int pos=0;\r
+            foreach (binBVHJoint joint in b.joints)\r
+            {\r
+                binBVHJointState state;\r
 \r
-        public bool addplayinganimation(Animation anim)\r
-        {\r
+                state.lastkeyframe_rot = 0;\r
+                state.nextkeyframe_rot = 1;\r
 \r
-            if (!animlist.ContainsKey(anim.AnimationID))\r
-            {\r
-                Logger.Log("Adding new playing animaton " + anim.AnimationID.ToString(), Helpers.LogLevel.Info);\r
-                animlist.Add(anim.AnimationID, anim);\r
-            }\r
+                state.lastkeyframe_pos = 0;\r
+                state.nextkeyframe_pos = 1;\r
 \r
-            mNeedsUpdate = true;\r
+                state.currenttime_rot = 0;\r
+                state.currenttime_pos = 0;\r
 \r
-            if (skeleton.mKnownAnimations.ContainsKey(anim.AnimationID))\r
-            {\r
-                return false;\r
+                b.joints[pos].Tag = state;\r
+                pos++;\r
             }\r
 \r
-            return true;\r
-\r
+            if (b.Priority >= 0 && b.Priority <= 5)\r
+                av.glavatar.skel.mPlayingAnimations[b.Priority] = b;\r
         }\r
 \r
-        public void firstkeyframe()\r
+        public void animate(float lastframetime)\r
         {\r
-            if (mNeedsUpdate == false)\r
-                return;\r
 \r
-            foreach (Animation anim in this.animlist.Values) // TODO priority sort\r
-            {\r
-                BinBVHAnimationReader b;\r
-                if (skeleton.mKnownAnimations.TryGetValue(anim.AnimationID, out b))\r
+                foreach (BinBVHAnimationReader b in mPlayingAnimations) // TODO priority sort\r
                 {\r
-                    foreach (binBVHJoint joint in b.joints)\r
-                    {\r
-                        //actually get the last for a pose the last frame is probably the static one once\r
-                        //we have reached position\r
-                        binBVHJointKey rot = joint.rotationkeys[joint.rotationkeys.Length - 1];\r
+                    if (b == null)\r
+                        continue;\r
 \r
-                        Vector3 pos = new Vector3(0, 0, 0);\r
-                        //binBVHJointKey pos = joint.positionkeys[0];\r
+                        int jpos = 0;\r
+                        foreach (binBVHJoint joint in b.joints)\r
+                        {\r
 \r
-                        deformbone(joint.Name, new Vector3(0, 0, 0), pos, new Quaternion(rot.key_element.X, rot.key_element.Y, rot.key_element.Z));\r
 \r
-                    }\r
+                            binBVHJointState state = (binBVHJointState) b.joints[jpos].Tag;\r
 \r
-                    mNeedsMeshRebuild = true;\r
-                }\r
-            }\r
+                            state.currenttime_rot += lastframetime;\r
+                            state.currenttime_pos += lastframetime;\r
+\r
+                            //fudge\r
+                            if (b.joints[jpos].rotationkeys.Length == 1)\r
+                            {\r
+                                state.nextkeyframe_rot = 0;\r
+                            }\r
+\r
+                            Vector3 poslerp = Vector3.Zero;\r
+\r
+                            if (b.joints[jpos].positionkeys.Length > 2)\r
+                            {\r
+                                binBVHJointKey pos2 = b.joints[jpos].positionkeys[state.nextkeyframe_pos];\r
+\r
+\r
+                                if (state.currenttime_pos > pos2.time)\r
+                                {\r
+                                    state.lastkeyframe_pos++;\r
+                                    state.nextkeyframe_pos++;\r
+\r
+                                    if (state.nextkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                    {\r
+                                        if (b.Loop == true)\r
+                                        {\r
+                                            state.nextkeyframe_pos = 0;\r
+                                            state.currenttime_pos = 0;\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            state.nextkeyframe_pos = joint.positionkeys.Length - 1;\r
+                                        }\r
+                                    }\r
+\r
+                                    if (state.lastkeyframe_pos >= b.joints[jpos].positionkeys.Length)\r
+                                    {\r
+                                        if (b.Loop == true)\r
+                                        {\r
+                                            state.lastkeyframe_pos = 0;\r
+                                            state.currenttime_pos = 0;\r
+\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            state.lastkeyframe_pos = joint.positionkeys.Length - 1;\r
+                                        }\r
+                                    }\r
+                                }\r
+\r
+                                binBVHJointKey pos = b.joints[jpos].positionkeys[state.lastkeyframe_pos];\r
+\r
+\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
+\r
+                                if (delta > 1)\r
+                                    delta = 1;\r
+\r
+                                poslerp = Vector3.Lerp(pos.key_element, pos2.key_element, delta) *-1;\r
+\r
+                            }\r
+\r
+\r
+                            Vector3 rotlerp = Vector3.Zero;\r
+                            if (b.joints[jpos].rotationkeys.Length > 0)\r
+                            {\r
+                                binBVHJointKey rot2 = b.joints[jpos].rotationkeys[state.nextkeyframe_rot];\r
+\r
+                                if (state.currenttime_rot > rot2.time)\r
+                                {\r
+                                    state.lastkeyframe_rot++;\r
+                                    state.nextkeyframe_rot++;\r
+\r
+                                    if (state.nextkeyframe_rot >= b.joints[jpos].rotationkeys.Length)\r
+                                    {\r
+                                        if (b.Loop == true)\r
+                                        {\r
+                                            state.nextkeyframe_rot = 0;\r
+                                            state.currenttime_rot = 0;\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            state.nextkeyframe_rot = joint.rotationkeys.Length - 1;\r
+                                        }\r
+                                    }\r
+\r
+                                    if (state.lastkeyframe_rot >= b.joints[jpos].rotationkeys.Length)\r
+                                    {\r
+                                        if (b.Loop == true)\r
+                                        {\r
+                                            state.lastkeyframe_rot = 0;\r
+                                            state.currenttime_rot = 0;\r
+\r
+                                        }\r
+                                        else\r
+                                        {\r
+                                            state.lastkeyframe_rot = joint.rotationkeys.Length - 1;\r
+                                        }\r
+                                    }\r
+                                }\r
+                              \r
+                                binBVHJointKey rot = b.joints[jpos].rotationkeys[state.lastkeyframe_rot];\r
+                                rot2 = b.joints[jpos].rotationkeys[state.nextkeyframe_rot];\r
+\r
+                                float deltarot = (rot2.time - rot.time) / ((state.currenttime_rot) - (rot.time - b.joints[jpos].rotationkeys[0].time));\r
+\r
+                               \r
+                                if (deltarot < 0)\r
+                                    deltarot = 0;\r
+\r
+                                if (deltarot > 1)\r
+                                    deltarot = 1;\r
+\r
+                                rotlerp = Vector3.Lerp(rot.key_element, rot2.key_element, deltarot);\r
+\r
+                            }\r
+\r
+                            b.joints[jpos].Tag = (object)state;\r
+                        \r
+                            deformbone(joint.Name, poslerp, new Vector3(0, 0, 0), new Quaternion(rotlerp.X, rotlerp.Y, rotlerp.Z));\r
+\r
+                            jpos++;\r
+                        }\r
+\r
+                        mNeedsMeshRebuild = true;\r
+                    }\r
 \r
             mNeedsUpdate = false;\r
         }\r
@@ -2227,8 +2378,8 @@ namespace Radegast.Rendering
 \r
         public void deformbone(Vector3 pos, Vector3 scale, Quaternion rot)\r
         {\r
-            float[] deform = Math3D.CreateSRTMatrix(scale, rot, this.orig_pos);\r
-            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
+            //float[] deform = Math3D.CreateSRTMatrix(scale, rot, this.orig_pos);\r
+            //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
             this.pos = Bone.mBones[name].orig_pos + pos;\r
             this.scale = Bone.mBones[name].orig_scale + scale;\r
             this.rot = Bone.mBones[name].orig_rot * rot;\r
@@ -2268,16 +2419,22 @@ namespace Radegast.Rendering
                 Vector3 mepre = pos * scale;\r
                 mepre = mepre * totalrot;\r
                 mTotalPos = parento + mepre;\r
-                posdirty = false;\r
-\r
+              \r
                 Vector3 orig = getOrigOffset();\r
                 mDeltaPos = mTotalPos - orig;\r
 \r
+                posdirty = false;\r
+\r
                 return mTotalPos;\r
             }\r
             else\r
             {\r
-                return (pos * scale) * getRotation();\r
+                Vector3 orig = getOrigOffset();\r
+                mTotalPos = (pos * scale);\r
+                mDeltaPos = mTotalPos - orig;\r
+                posdirty = false;\r
+                return mTotalPos;\r
+              \r
             }\r
         }\r
 \r
@@ -2316,7 +2473,7 @@ namespace Radegast.Rendering
         {\r
             if (parent != null)\r
             {\r
-                return (parent.getOrigOffset()) + orig_pos;\r
+                return (parent.getOrigOffset() + orig_pos);\r
             }\r
             else\r
             {\r