引擎设计跟踪(九.5) 骨骼蒙皮动画预研
2013-05-09 12:33
507 查看
最近看了骨骼蒙皮的细节,之前只了解大致原理:
用场景图类似的级联层次结构,组织骨骼的框架
运行时根据骨骼的空间参数(旋转,位移,缩放)计算蒙皮顶点.
基本原理
使用级联(父子)层次关系的好处就是能够方便反应真实的情况: 手臂运动时,手掌和手指会跟着运动(这个需要没帧在CPU端计算骨骼树上的所有最终变换).
骨骼蒙皮动画也是关键帧动画,但跟早期的关键帧"顶点动画"(比如md2模型)不同的是,关键帧只保存骨骼的空间信息,而不是顶点位置信息.
一组顶点可能收到多个骨骼影响,所以会在运行时混合(加权平均) 出所有骨骼的最终影响.
每一帧骨骼的动作变换,是相对于骨骼自己所在的空间,所以做蒙皮的时候,要先将顶点从模型空间变换到骨骼空间,在骨骼空间做完当前帧运动计算后再最终转到世界空间.
Pw = Vl * Mb-1 * Mbkf * Mb * Mw;
Vl为原始顶点坐标,局部空间坐标.
Mb-1 为骨骼空间矩阵的逆, 这一步将局部空间坐标转到骨骼空间
Mbkf为当前帧动画的动作变换,完成顶点运动,(这个参数是位于骨骼空间的变换参数,把顶点变换到骨骼空间就是为了他)
Mb则将运动后的顶点再转到局部空间
最后Mw跟平常的局部空间->世界空间变换一样
Mbkf是cpu实时计算(关键帧插值)出来的,当然根据结合律,某些矩阵相乘可以预计算
贴一张GPU Gems上的公式 (source: http://gamedev.stackexchange.com/questions/28012/bones-animation-matrices-and-calculations):
一些技术细节
空间变换通常会用4x3矩阵(去掉w分量),作为骨骼变换矩阵的存储,
但如果忽略缩放的话,也可以用一个四元数(旋转)+一个向量(位移) 来存储,以节省数据传输带宽.
还可以用双四元数(Dual Quaternion)来计算骨骼动画,这里有参考
http://isg.cs.tcd.ie/projects/DualQuaternions/
如果要兼容SM2.0的话,VS的cosntant buffer限制为256个
(参考 http://en.wikipedia.org/wiki/High_Level_Shader_Language )
如果用4x3矩阵的话, 最多骨骼矩阵数量大概为 256/3 = 80多个 (shader里其他基本的参数(比如senmatics)会占用一些)
如果用双四元数(DQ),或者Q(R)+V(T)的话,为 256/2 大概一百多个的样子, 这个会节省相当可观的带宽 (要考虑多遍绘制时的多次传输)
详细论述见Crytek的ppt (http://www.crytek.com/download/izfrey_siggraph2011.pdf )
(per-vertex)blendweight也会传进shader用于加权混合
需要blend indices用来索引骨骼矩阵的数组
关于IK
这个是计划支持的特性(支持程度未定),目前正在找相关资料和看Doom3的与IK相关的源代码.
更新:
每个顶点受影响的骨骼数量, 即每个顶点的blend indices的个数, 一般来说是2-4, 这样方便用一个register保存. blend indices通常用uint8x4保存, blend weight 通常是uint8nx4.
由于每个mesh(一个draw call单位)对应的骨骼数量, 受constant register数量的影响, 会有限制. 如果骨骼太多, 则要把mesh拆分成多个mesh, 即用多个draw call分开bone matrices的绑定.
用场景图类似的级联层次结构,组织骨骼的框架
运行时根据骨骼的空间参数(旋转,位移,缩放)计算蒙皮顶点.
基本原理
使用级联(父子)层次关系的好处就是能够方便反应真实的情况: 手臂运动时,手掌和手指会跟着运动(这个需要没帧在CPU端计算骨骼树上的所有最终变换).
骨骼蒙皮动画也是关键帧动画,但跟早期的关键帧"顶点动画"(比如md2模型)不同的是,关键帧只保存骨骼的空间信息,而不是顶点位置信息.
一组顶点可能收到多个骨骼影响,所以会在运行时混合(加权平均) 出所有骨骼的最终影响.
每一帧骨骼的动作变换,是相对于骨骼自己所在的空间,所以做蒙皮的时候,要先将顶点从模型空间变换到骨骼空间,在骨骼空间做完当前帧运动计算后再最终转到世界空间.
Pw = Vl * Mb-1 * Mbkf * Mb * Mw;
Vl为原始顶点坐标,局部空间坐标.
Mb-1 为骨骼空间矩阵的逆, 这一步将局部空间坐标转到骨骼空间
Mbkf为当前帧动画的动作变换,完成顶点运动,(这个参数是位于骨骼空间的变换参数,把顶点变换到骨骼空间就是为了他)
Mb则将运动后的顶点再转到局部空间
最后Mw跟平常的局部空间->世界空间变换一样
Mbkf是cpu实时计算(关键帧插值)出来的,当然根据结合律,某些矩阵相乘可以预计算
贴一张GPU Gems上的公式 (source: http://gamedev.stackexchange.com/questions/28012/bones-animation-matrices-and-calculations):
一些技术细节
空间变换通常会用4x3矩阵(去掉w分量),作为骨骼变换矩阵的存储,
但如果忽略缩放的话,也可以用一个四元数(旋转)+一个向量(位移) 来存储,以节省数据传输带宽.
还可以用双四元数(Dual Quaternion)来计算骨骼动画,这里有参考
http://isg.cs.tcd.ie/projects/DualQuaternions/
如果要兼容SM2.0的话,VS的cosntant buffer限制为256个
(参考 http://en.wikipedia.org/wiki/High_Level_Shader_Language )
如果用4x3矩阵的话, 最多骨骼矩阵数量大概为 256/3 = 80多个 (shader里其他基本的参数(比如senmatics)会占用一些)
如果用双四元数(DQ),或者Q(R)+V(T)的话,为 256/2 大概一百多个的样子, 这个会节省相当可观的带宽 (要考虑多遍绘制时的多次传输)
详细论述见Crytek的ppt (http://www.crytek.com/download/izfrey_siggraph2011.pdf )
(per-vertex)blendweight也会传进shader用于加权混合
需要blend indices用来索引骨骼矩阵的数组
关于IK
这个是计划支持的特性(支持程度未定),目前正在找相关资料和看Doom3的与IK相关的源代码.
更新:
每个顶点受影响的骨骼数量, 即每个顶点的blend indices的个数, 一般来说是2-4, 这样方便用一个register保存. blend indices通常用uint8x4保存, blend weight 通常是uint8nx4.
由于每个mesh(一个draw call单位)对应的骨骼数量, 受constant register数量的影响, 会有限制. 如果骨骼太多, 则要把mesh拆分成多个mesh, 即用多个draw call分开bone matrices的绑定.
相关文章推荐
- 引擎设计跟踪(九.14.2) 更新记录和骨骼动画导出更新
- 引擎技术中骨骼动画的蒙皮设计与实现
- 引擎设计跟踪(九.14) 更新记录和骨骼动画导出
- 引擎设计跟踪(九.14.2b) 骨骼动画基本完成
- 骨骼蒙皮动画的原理解析
- [3dmax教程] 人物+骨骼+蒙皮+动画教程
- Java动画 重力弹球 如鹏游戏引擎 精灵 设计一个小球加速落地又减速弹起并反复直到停止的Java程序
- 引擎设计跟踪 地形LOD的改进
- 引擎设计跟踪(九.9) 文件包系统(Game Package System)
- 引擎设计跟踪(九.14.2d) [翻译] shader的跨平台方案之2014
- 引擎设计跟踪(九.3) 3DS MAX 导出插件 小总结
- 引擎设计跟踪(九.14.2 final) Inverse Kinematics: CCD 在Blade中的实现
- 引擎设计跟踪(九.14.2i) Android GLES 3.0 完善
- 引擎设计跟踪(二)
- 蒙皮骨骼动画原理
- 引擎设计跟踪(三)
- 【Direct3D游戏开发】——蒙皮骨骼动画学习笔记
- 引擎设计跟踪(九.14.3.4) mile stone 2 - model和fbx导入的补漏
- 骨骼蒙皮动画(Skinned Mesh)的原理解析
- 引擎设计跟踪(九.10) Max插件更新,地形问题备忘