• CSharpGL(50)使用Assimp加载骨骼动画


    CSharpGL(50)使用Assimp加载骨骼动画

    在(http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html)介绍了C++用Asismp库加载骨骼动画的原理和流程。

    在(http://wiki.jikexueyuan.com/project/modern-opengl-tutorial/tutorial45.html)是其中文版译文。

    本文用CSharpGL借助Assimp库实现加载和渲染骨骼动画的功能。

    下载

    CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

    在.NET下使用Assimp

    三维模型解析库Assimp本身是用C++编写的,所幸有一个C#的封装(https://github.com/assimp/assimp-net)。使用此封装即可直接在CSharpGL中调用Assimp了。

    将Assimp32.dll、Assimp64.dll和AssimpNet.dll都放到项目所在目录下,在Reference中添加对AssimpNet.dll的引用即可。

     

     

    渲染骨骼动画

    Assimp加载模型后得到的数据结构如下:

    1 public sealed class Scene
    2 {
    3     public Animation[] Animations { get; }
    4     public Material[] Materials { get; }
    5     public Mesh[] Meshes { get; }
    6     public Node RootNode { get; }
    7 }

    按我的理解,其中的RootNode就是骨骼的根结点。整个骨骼构成一个树结构。每个结点都包含一个mat4 Transform矩阵,用于描述自己相对于父结点的方位变化。子结点代表的骨骼,其绝对方位由根结点的Transform逐步地乘到自己的Transform来得到。“绝对方位”指的就是在Model Space中的方位。

     

    如图所示,红色的小方块描述了骨骼所在的绝对位置(这里的骨骼对应人体的关节)。从红到白渐变的线条描述了骨骼之间的父子关系,红色一端为父结点,白色一端为子结点。两脚之间的那个红色小方块,就是根结点RootNode。用半透明方式渲染的两臂水平摆放的,就是模型的默认位置。

    上图这个模型,只有一个“拿起灯左右查看”的动作(Animation)。其他模型可能有多个动作,它们构成一个数组(Assimp.Animation[])。每个Animation都指定了这个模型的所有骨骼在所有关键帧上的Transform值。这样,通过按时间顺序依次经历各个关键帧(更准确地说,是在2个相邻的关键帧之间插值),就可以得到骨骼在各个时刻的Transform。再让模型的顶点依附于骨骼而动,就实现了骨骼动画。

    模型上的一个顶点,要记录自己都依附于哪几个骨骼,自己对这几个骨骼依附的权重分别是多少(权重之和为1)。然后,就可以从默认的初始位置(用半透明方式渲染的两臂水平摆放的那个位置)变换到骨骼要求的位置。

    顶点的这一变换过程我还没弄明白。这里需要的Offset Matrix到底是什么。据我查资料,外加计算,Offset Matrix就是那个让骨骼结点变换到绝对方位的矩阵的逆矩阵。但是总觉得有点想不通的地方,确不知道是哪里。

    经高人goodpgr提醒,Offset Matrix就是那个让骨骼结点变换到model space的矩阵的逆。非常感谢!

    将其推导过程陈列如下:

    「Offset Matrix就是那个让骨骼结点变换到绝对方位的矩阵的逆矩阵」:
    可以改寫成
    「Offset Matrix就是那个让骨骼结点变换到model space的矩阵的逆」:
    因為skin mesh的頂點資料是在model space定義的
    假設在右小腿附近有1個頂點P,用model space的三把尺和原點來測量
    它在model space可能是 p'=(10,20,0)
    (y向上是天空)
    但對右小腿Bone來說,用它的三把尺和原點測量頂點P
    得到的值可能是 p=(10,0,0) => local bone space
    假設右小腿Bone的階層長這樣
    RootBone // 右骨盆Bone // 右大腿Bone // 右小腿Bone
    它們對映到的矩陣分別是
    Mroot // Mc // Mb // Ma
    那 p和p'會有下面的關系
    p'=(Mroot Mc Mb Ma) p
    (Mroot Mc Mb Ma)^-1 p'=p
    MatrixModelSpaceToBoneLocal * p' = p
    MatrixModelSpaceToBoneLocal = Offset_Matrix
    mesh綁定到bone上,實際上是綁定到bone的local space
    但一開始mesh的資料是在model space建模的

    总结

    骨骼动画的原理网上有很多介绍了。我还没有透彻理解,所以不对本文的原理部分负责。

  • 相关阅读:
    django 项目需要注意的一些点
    VUE之路
    Oracle 表格碎片的查看方法
    RHEL 6.x or 7.x 使用分区绑定ASM 磁盘的方法
    RMAN 修复主库 nologging 操作导致物理备库的坏块
    Oracle 数据库19c 回退降级到 11.2.0.4 方案
    如何评估oracle 数据库rman全备和增量备份大小
    在将Oracle GI和DB升级到19c或降级到以前的版本之前需要应用的补丁 (Doc ID 2668071.1)
    Oracle 数据库坏块处理
    opatch auto 安装11.2.0.4.20190115 PSU遇到 OUI-67133: Execution of PRE script failed,with returen value 1 报错
  • 原文地址:https://www.cnblogs.com/bitzhuwei/p/csharpgl-50-bones-animation.html
Copyright © 2020-2023  润新知