当前位置:网站首页>[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: sum of 1051 square roots
- NFT new opportunity, multimedia NFT aggregation platform okaleido will be launched soon
- How to query the baby category of tmall on Taobao
- FPGA blocking assignment and non blocking assignment
- Sub GHz wireless solution Z-Wave 800 Series zg23 SOC and zgm230s modules
- Find books ()
- 556. The next larger element III
- Tonybot humanoid robot infrared remote control play 0630
- Talking about part of data storage in C language
- Zzuli:1046 product of odd numbers
猜你喜欢

dllexport和dllimport

Puzzle (016.4) domino effect

How to query the baby category of tmall on Taobao

Zzuli:1053 sine function

Why is this error reported when modifying records in the database

tonybot 人形机器人 查看端口并对应端口 0701

US stock listing of polar: how can the delivery of 55000 units support the valuation of more than 20billion US dollars

Tonybot humanoid robot infrared remote control play 0630

Sub GHz wireless solution Z-Wave 800 Series zg23 SOC and zgm230s modules

基因家族特征分析 - 染色体定位分析
随机推荐
China PETG market forecast and Strategic Research Report (2022 Edition)
Recent learning summary
Adc128s022 ADC Verilog design and Implementation
puzzle(016.3)千丝万缕
Tonybot humanoid robot checks the port and corresponds to port 0701
C language dup2 function
Tonybot humanoid robot starts for the first time 0630
On MEM series functions of C language
Output student grades
C language STR function
Luogu p5018 [noip2018 popularization group] symmetric binary tree problem solution
Code writing and playing method of tonybot humanoid robot at fixed distance
Mongodb index
Why is this error reported when modifying records in the database
The mail function of LNMP environment cannot send mail
puzzle(016.4)多米诺效应
Tonybot humanoid robot infrared remote control play 0630
[qingniaochangping campus of Peking University] in the Internet industry, which positions are more popular as they get older?
Understand the application scenario and implementation mechanism of differential segment
Zzuli:1047 logarithmic table