BGE Animations: Adding blendin for Shape Actions.
authorMitchell Stokes <mogurijin@gmail.com>
Wed, 29 Jun 2011 01:05:12 +0000 (01:05 +0000)
committerMitchell Stokes <mogurijin@gmail.com>
Wed, 29 Jun 2011 01:05:12 +0000 (01:05 +0000)
source/gameengine/Converter/BL_DeformableGameObject.cpp
source/gameengine/Ketsji/BL_Action.cpp
source/gameengine/Ketsji/BL_Action.h

index bfba054d0d45ba123b83e1ac314c11f1da96ad67..58294f2940ea69521e27fd053ae3d3f9a509c2df 100644 (file)
@@ -87,15 +87,15 @@ bool BL_DeformableGameObject::SetActiveAction(BL_ShapeActionActuator *act, short
 bool BL_DeformableGameObject::GetShape(vector<float> &shape)
 {
        shape.clear();
-       if (m_pDeformer)
+       BL_ShapeDeformer* shape_deformer = dynamic_cast<BL_ShapeDeformer*>(m_pDeformer);
+       if (shape_deformer)
        {
-               Mesh* mesh = ((BL_MeshDeformer*)m_pDeformer)->GetMesh();
                // this check is normally superfluous: a shape deformer can only be created if the mesh
                // has relative keys
-               if (mesh && mesh->key && mesh->key->type==KEY_RELATIVE) 
+               if (shape_deformer->GetKey() && shape_deformer->GetKey()->type==KEY_RELATIVE) 
                {
                        KeyBlock *kb;
-                       for (kb = (KeyBlock*)mesh->key->block.first; kb; kb = (KeyBlock*)kb->next)
+                       for (kb = (KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb = (KeyBlock*)kb->next)
                        {
                                shape.push_back(kb->curval);
                        }
index 90349bcfddd4d2a2652928639ee5a490d932b71f..1741e74a771688853b571c7bcaa0e1b0c37627bc 100644 (file)
@@ -142,6 +142,30 @@ void BL_Action::Play(const char* name,
        m_ipo_flags = ipo_flags;
        InitIPO();
 
+       // Setup blendin shapes/poses
+       if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+       {
+               if (!m_blendpose)
+               {
+                       BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj;
+                       obj->GetMRDPose(&m_blendpose);
+               }
+       }
+       else
+       {
+               BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj;
+               BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer());
+               
+               obj->GetShape(m_blendshape);
+
+               // Now that we have the previous blend shape saved, we can clear out the key to avoid any
+               // further interference.
+               KeyBlock *kb;
+               for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next)
+                       kb->curval = 0.f;
+
+       }
+
        // Now that we have an action, we have something we can play
        m_starttime = KX_GetActiveEngine()->GetFrameTime();
        m_startframe = m_localtime = start;
@@ -197,6 +221,39 @@ void BL_Action::SetLocalTime(float curtime)
        m_localtime = m_startframe + dt;
 }
 
+void BL_Action::IncrementBlending(float curtime)
+{
+       // Setup m_blendstart if we need to
+       if (m_blendstart == 0.f)
+               m_blendstart = curtime;
+       
+       // Bump the blend frame
+       m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
+
+       // Clamp
+       if (m_blendframe>m_blendin)
+               m_blendframe = m_blendin;
+}
+
+
+void BL_Action::BlendShape(Key* key, float srcweight)
+{
+       vector<float>::const_iterator it;
+       float dstweight;
+       KeyBlock *kb;
+       
+       dstweight = 1.0F - srcweight;
+       //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight);
+       for (it=m_blendshape.begin(), kb = (KeyBlock*)key->block.first; 
+                kb && it != m_blendshape.end(); 
+                kb = (KeyBlock*)kb->next, it++) {
+               //printf("OirgKeys: %f\t%f\n", kb->curval, (*it));
+               kb->curval = kb->curval * dstweight + (*it) * srcweight;
+               //printf("NewKey: %f\n", kb->curval);
+       }
+       //printf("\n");
+}
+
 void BL_Action::Update(float curtime)
 {
        // Don't bother if we're done with the animation
@@ -260,25 +317,16 @@ void BL_Action::Update(float curtime)
                        arm->pose = temp;
                }
 
-               // Handle blending between actions
+               // Handle blending between armature actions
                if (m_blendin && m_blendframe<m_blendin)
                {
-                       if (!m_blendpose)
-                       {
-                               obj->GetMRDPose(&m_blendpose);
-                               m_blendstart = curtime;
-                       }
+                       IncrementBlending(curtime);
 
                        // Calculate weight
                        float weight = 1.f - (m_blendframe/m_blendin);
-                       game_blend_poses(m_pose, m_blendpose, weight);
 
-                       // Bump the blend frame
-                       m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
-
-                       // Clamp
-                       if (m_blendframe>m_blendin)
-                               m_blendframe = m_blendin;
+                       // Blend the poses
+                       game_blend_poses(m_pose, m_blendpose, weight);
                }
 
                obj->SetPose(m_pose);
@@ -295,15 +343,25 @@ void BL_Action::Update(float curtime)
                {
                        Key *key = shape_deformer->GetKey();
 
-                       // We go through and clear out the keyblocks so there isn't any interference
-                       // from other shape actions
-                       KeyBlock *kb;
-                       for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
-                               kb->curval = 0.f;
 
                        animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime);
 
-                       // XXX TODO handle blendin
+                       // Handle blending between shape actions
+                       if (m_blendin && m_blendframe < m_blendin)
+                       {
+                               IncrementBlending(curtime);
+
+                               float weight = 1.f - (m_blendframe/m_blendin);
+
+                               // We go through and clear out the keyblocks so there isn't any interference
+                               // from other shape actions
+                               KeyBlock *kb;
+                               for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next)
+                                       kb->curval = 0.f;
+
+                               // Now blend the shape
+                               BlendShape(key, weight);
+                       }
 
                        obj->SetActiveAction(NULL, 0, m_localtime);
                }
index d9d134db9f1baf7762a97f41139ca8031c2215f9..de09ab13c688b9f7457d7f5ac89efe36655cd758 100644 (file)
@@ -29,6 +29,9 @@
 #ifndef __BL_ACTION
 #define __BL_ACTION
 
+
+#include <vector>
+
 #ifdef WITH_CXX_GUARDEDALLOC
 #include "MEM_guardedalloc.h"
 #endif
@@ -43,6 +46,7 @@ private:
        struct PointerRNA *m_ptrrna;
        class SG_Controller *m_sg_contr;
        class KX_GameObject* m_obj;
+       std::vector<float>      m_blendshape;
 
        float m_startframe;
        float m_endframe;
@@ -68,6 +72,8 @@ private:
 
        void InitIPO();
        void SetLocalTime(float curtime);
+       void IncrementBlending(float curtime);
+       void BlendShape(struct Key* key, float srcweight);
 public:
        BL_Action(class KX_GameObject* gameobj);
        ~BL_Action();