2021SC@SDUSC
骨骼动画是角色模型动画的一种,互相连接的骨骼组成骨架结构,通过改变骨骼的位置和关节处的夹角来生成动画。例如,当我们的屈肘的时候,小臂绕肘关节运动,其他的关节不动,随着肘关节的弯曲,肱二头肌会收缩;而举手时,大臂将带动手臂整体绕肩关节运动。即当我们动一个关节的时候,会带动其子关节以及一部分肌肉动起来。在骨骼控制下,通过顶点混合动态计算蒙皮网格的顶点,而骨骼的运动相对于其父骨骼,并由动画关键帧数据驱动。Maya和Dust3D都主要采用的这种骨骼动画。
Maya中的骨骼绑定:
Dust3D中的gesture和motion系统:
正向运动学FK
我们首先从运动学方法开始说起。运动学方法主要包含Forward Kinematics (FK) 正向运动学以及Inverse Kinematics (IK)逆向运动学。
正向运动学指定每块骨骼的变换参数,系统据此确定各关节的位置及末端影响器的位置。
但对于使用者来说,通过指定联合值来将图形定位到最终位置是非常繁琐的,所以引入了逆向运动学。
逆向运动学IK
实际应用当中更常见的是逆向运动学。逆向运动学指定末端影响器位置,系统计算各骨骼变换参数。
当方程足够简单时可直接使用解析法求解,当存在多个解时需要使用数值迭代法求解。
SkeletonIkMover
SkeletonIkNode结构体存储关节编号、位置以及变换后的位置。SkeletonIkMover类存储SkeletonIkNode信息以及变换信息,将数据传递给CcdIkSolver类进行变换。
struct SkeletonIkNode
{
QUuid id;
QVector3D position;
QVector3D newPosition;
};
class SkeletonIkMover : public QObject
{
Q_OBJECT
public:
SkeletonIkMover();
~SkeletonIkMover();
void setTarget(const QVector3D &target);
void setUpdateVersion(unsigned long long version);
unsigned long long getUpdateVersion();
void addNode(QUuid id, QVector3D position);
const std::vector<SkeletonIkNode> &ikNodes();
signals:
void finished();
public slots:
void process();
private:
void resolve();
private:
unsigned long long m_updateVersion = 0;
std::vector<SkeletonIkNode> m_ikNodes;
QVector3D m_target;
};
SkeletonIkMover类声明的一些操作:
void SkeletonIkMover::addNode(QUuid id, QVector3D position)
{
//将当前的骨骼数据存储到一个SkeletonIkNode序列中
SkeletonIkNode ikNode;
ikNode.id = id;
ikNode.position = ikNode.newPosition = position;
m_ikNodes.push_back(ikNode);
}
void SkeletonIkMover::process()
{
resolve();
emit finished()