当前位置:网站首页>[opengl] bone animation blending effect
[opengl] bone animation blending effect
2022-07-03 14:42:00 【ZJU_ fish1996】
This article mainly discusses the blending effect of two bone animation transitions .

In the game , Animation is often cut into multiple segments (clip), Build the final performance effect through combination and splicing . To ensure a smooth transition when switching actions , Make the whole movement more smooth , You need to mix the front and back actions through interpolation .
Concept introduction
Before discussing specific hybrid calculations , I think it is still necessary to clarify some details of the whole animation system .
One of the problems that needs to be discussed is : What data should be maintained when animation runs , And how to convert into the final rendering process . In the original bone animation demo in , I actually store the skin matrix of each bone in each frame , As a bone animation demonstration, it is more than enough .
But for practical applications , There are at least two problems here : First, the animation data frame by frame is generally the result of baking , stay dcc Animation data in the tool is generally keyframes + Curve type storage , Real time interpolation itself is not time consuming , And it can compress the bandwidth , So animation is often compressed and stored ;
Second, in addition to playing animation , Sometimes we need to do some post-processing for the action —— For example, animation blending discussed in this article , Another example is the effect of reverse dynamics , At this time, only skin matrix is not conducive to operation , We should according to our actual needs , Stored as local transformation matrix or global ( Model space ) Transformation matrix . Specially , If stored as a local transformation matrix , In the process of solving, there are steps to constantly find the parent node multiplication matrix , Arranging the order of bones reasonably here can avoid repeated operations .
Another issue to consider is , Whether the mixing should affect the playback length of the action ? Let's assume the action A The length is ta frame ,B by tb frame , The number of mixed frames is tc, So action A,B After mixing , The total frame length should be ta+tb, still ta+tb+tc, Or between the two ?
To address this issue , I think the friendly design is : The mixing time should not affect the original playback length , Mixing this function itself is only for better performance , It should not destroy the original system . Then there must be an action here “ sacrifice ” Part of the posture . A common idea is to make the target move before tc Convert frame to transition frame , The matrix of each frame and the last frame of the source action are interpolated according to the current time .
Concrete realization
For better mixing operation , We can modify the data stored in the animation to that in the model space transform value , Instead of the final skin matrix . So-called transform That is, store the translation, rotation, and zoom respectively , Then according to RST Construct the matrix :
struct STransform
{
QVector3D position = QVector3D(0, 0, 0);
QVector3D scale = QVector3D(1, 1, 1);
QQuaternion rotation = QQuaternion(0, 0, 0, 1);
};In the actual interpolation operation , We also aim at every bone Translation of model space 、 rotate 、 The zoom Interpolate separately ( Because there is no scaling of bones in the project , Scaling interpolation is not calculated in actual engineering )
Switch to the new action , When we detect that new actions need to be mixed , According to the current action localtime, Sampling action transform value , As caching :
void CAnimationEngine::PlayAnimation(Object* obj, const string& path)
{
if(m_animators.find(path) == m_animators.end())
{
return;
}
int frame = -1;
string oldPath;
// check need blend, save cache pose
if(m_events.find(obj) != m_events.end() && m_animators.find(m_events[obj].m_path) != m_animators.end())
{
if(g_animParam.m_nBlendFrame)
{
oldPath = m_events[obj].m_path;
frame = min(m_animators[oldPath].GetFrameNum(), static_cast<int>(m_events[obj].m_time * FRAME_PER_MS));
}
}
m_events[obj] = SEvent(path, g_animParam.m_bLoop, g_animParam.m_nBlendFrame, g_animParam.m_eBlendCurve, g_animParam.m_fSpeed);
if(!oldPath.empty())
{
CAnimator& animator = m_animators[oldPath];
m_events[obj].m_cachePose = animator.GetTransform(frame);
}
}Next , In the code that updates the bone animation , We translate the sampling action and cache action under the current frame number 、 Rotate and interpolate respectively , Mix weights in time t Company , Contains linear blending (t), And nonlinear mixing (3 * t * t - 2 * t * t).
After interpolation , We reconstruct the global transformation matrix of the model space , And multiply the inverse matrix of the binding matrix to construct the skin matrix , Pass to shader .
bool CAnimationEngine::UpdateAnimation(Object* obj, QOpenGLShaderProgram* program)
{
// ...
if (event.m_blendFrame > 0 && frame <= event.m_blendFrame && event.m_cachePose.size() > 0)
{
vector<QMatrix4x4> final;
float ratio = static_cast<float>(frame + 1) / (event.m_blendFrame + 1);
if (event.m_eBlendCurve == EBlendCurve::Smooth)
{
ratio = ratio * ratio * (-2 * ratio + 3);
}
for(int i = 0;i < size; i++)
{
STransform& transform = animator.GetTransform(frame, i);
QQuaternion quat = QQuaternion::slerp(event.m_cachePose[i].rotation, transform.rotation, ratio);
QVector3D trans = Lerp(event.m_cachePose[i].position, transform.position, ratio);
QMatrix4x4& invBindPose = CAnimationEngine::Inst()->GetBone(i)->m_invBindPose;
QMatrix4x4 mat;
mat.translate(trans);
mat.rotate(quat);
mat = mat * invBindPose;
final.push_back(mat);
}
program->setUniformValueArray(location,final.data(), size);
}
else
{
// ...
}
// ...
return true;
}
边栏推荐
- Zzuli:1052 sum of sequence 4
- On MEM series functions of C language
- Get permissions dynamically
- Zzuli:1042 sum of sequence 3
- 7-22 tortoise and rabbit race (result oriented)
- Plane vector addition
- tonybot 人形机器人 红外遥控玩法 0630
- 7-9 one way in, two ways out (25 points)
- Luogu p5194 [usaco05dec]scales s solution
- Time conversion ()
猜你喜欢

Happy capital new dual currency fund nearly 4billion yuan completed its first account closing

Zhonggan micro sprint technology innovation board: annual revenue of 240million, net loss of 17.82 million, proposed to raise 600million

Understand the application scenario and implementation mechanism of differential segment

Protobuf and grpc

Bucket sorting in C language

puzzle(016.3)千丝万缕

ConstraintLayout 的使用

Frequently asked questions: PHP LDAP_ add(): Add: Undefined attribute type in

Adc128s022 ADC Verilog design and Implementation

How to query the baby category of tmall on Taobao
随机推荐
Rasterization: a practical implementation (2)
数学常数表 by q779
基因家族特征分析 - 染色体定位分析
Some concepts about agile
Accelerating strategy learning using parallel differentiable simulation
Pyqt interface production (login + jump page)
NOI OPENJUDGE 1.6(09)
Zzuli:1054 monkeys eat peaches
Sword finger offer 28 Symmetric binary tree
分布式事务(Seata) 四大模式详解
7-3 rental (20 points)
Adc128s022 ADC Verilog design and Implementation
Zzuli: sum of 1051 square roots
Talking about part of data storage in C language
Zzuli:1040 sum of sequence 1
Tonybot humanoid robot checks the port and corresponds to port 0701
The mail function of LNMP environment cannot send mail
Déformation de la chaîne bm83 de niuke (conversion de cas, inversion de chaîne, remplacement de chaîne)
2021-10-16 initial programming
C language dup2 function