当前位置:网站首页>[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;
}
边栏推荐
- String reverse order
- 7-3 count the number of words in a line of text
- Dllexport and dllimport
- Zzuli:1052 sum of sequence 4
- 提高效率 Or 增加成本,开发人员应如何理解结对编程?
- Zzuli:1049 square sum and cubic sum
- 【7.3】146. LRU缓存机制
- 牛客 BM83 字符串变形(大小写转换,字符串反转,字符串替换)
- Adc128s022 ADC Verilog design and Implementation
- Puzzle (016.3) is inextricably linked
猜你喜欢
随机推荐
表单文本框的使用(一) 选择文本
ConstraintLayout 的使用
Piwigo 2.7.1 sqli learning
分布式事务(Seata) 四大模式详解
adc128s022 ADC verilog设计实现
My QT learning path -- how qdatetimeedit is empty
Zzuli:1052 sum of sequence 4
Timecho of Tianmou technology completed an angel round financing of nearly 100 million yuan to create a native timing database of the industrial Internet of things
Mongodb index
洛谷P5018 [NOIP2018 普及组] 对称二叉树 题解
【7.3】146. LRU caching mechanism
NOI OPENJUDGE 1.3(06)
如何查询淘宝天猫的宝贝类目
Tailing rushes to the scientific and Technological Innovation Board: it plans to raise 1.3 billion, and Xiaomi Changjiang is the shareholder
Awvs batch operation script
Zzuli:1056 lucky numbers
ShowMeBug入驻腾讯会议,开启专业级技术面试时代
China PETG market forecast and Strategic Research Report (2022 Edition)
tonybot 人形机器人 红外遥控玩法 0630
MySQL multi table query subquery