BGE Animations: Adding blendin for Shape Actions.

This commit is contained in:
Mitchell Stokes 2011-06-29 01:05:12 +00:00
parent caef67eb92
commit de3c95a09c
3 changed files with 87 additions and 23 deletions

@ -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);
}

@ -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);
// Blend the poses
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;
}
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);
}

@ -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();