FBX BlendShape/Morph动画解析

目前fbx 2015.1中支持三种变形器:skinDeformer,blendShapeDeformer,vertexCacheDeformer。定义在fbxdeformer.h中:

enum EDeformerType {

  eUnknown, //!< Unknown deformer type

  eSkin, //!< Type FbxSkin

  eBlendShape, //!< Type FbxBlendShape

  eVertexCache //!< Type FbxVertexCacheDeformer

};

前两种变形器分别对应:骨骼蒙皮动画 和 变形动画,(第三种还没研究)。

相应的播放代码都可以在ViewScene示例中找到。

其中 骨骼蒙皮动画 游戏里用得最多,所以研究得较早。这几天又看了一下 变形动画(BlendShape/Morph animation),散乱记录一下若干注意事项。

一,blendShape基本原理。

大体上讲就是在拓扑结构相同的mesh之间插值。细节在下文中会提到。

典型应用是做表情动画。

二,在3dmax中制作带有 变形动画 的模型。

我用的是3dmax 2012(中文版)。

1,先建一个模型X,然后复制出一份X1。

2,对X1在保持拓扑结构不变的条件下进行变形。

3,为X添加“变形器”修改器,将X1添加到“变形器”修改器的一个通道中,则X1成为X的一个变形目标。

4,调整通道值,便可看到X受X1影响发生变形。

5,打开自动关键点,记录变形动画。

可以重复上面方法为X添加多个变形目标。

“变形器”修改器的一个通道可以添加多个变形目标,通道名称将显示为此通道中所添加的第一个变形目标的名称,此通道所添加的所有变形目标可以在”渐进变形“栏的”目标列表“中看到。

当一个通道中添加多个变形目标时,称为progressive morph,X将按目标列表中目标的顺序依次变形。

另外注意,并非对X1的任何保持拓扑的修改都能对X产生影响,只有局部空间的修改(例如使用局部空间修改器进行的修改、直接拖动顶点位置进行的修改等)才起作用,而对X1整体进行的修改(例如对X1整体进行旋转、平移、缩放等)则不会起作用。

三,fbx变形动画原理。

fbx sdk的ViewScene示例中的ComputeShapeDeformation()函数实现变形动画的数据提取和播放,通过阅读这部分代码,可以了解fbx中变形动画数据的逻辑结构:

一个mesh包含多个blendShape,

一个blendShape包含多个blendShapeChannel,

一个blendShapeChannel包含多个targetShape和一个weight动画曲线weightCurve。

targetShape中包含controlPoints和一个fullWeight值。

这些结构与3dmax中的对应关系如下:

mesh对应的就是3dmax中的模型,

blendShape对应“变形器”修改器,一个模型可以添加多个“变形器”修改器,

blendShapeChannel对应“变形器”修改器的通道,blendShapeChannel->GetName()得到通道名称.

targetShape对应变形目标,一个通道可以添加多个变形目标。targetShape->GetName()得到变形目标名称。

通道的weightCurve给出各时间点此通道变形进度weight。

targetShape的fullWeight值表示的是本通道变形进度weight值达到多少时恰好完全变形为本targetShape。对于只有一个targetShape的通道,targetShape的fullWeight必定是100;而对于含有多个targetShape的通道,各targetShape的fullWeight值按顺序依次增大,并且最后一个targetShape的fullWeight必定是100。

可见,非常符合直观,至此变形插值算法几乎不用再看ComputeShapeDeformation()的代码便可以直接想象出来了。

下面是ComputeShapeDeformation()中的注释,用具体例子说明在progressive morph和progressive morph情况下的插值算法,与我们的直观想象完全一致:

If there is only one targetShape on this channel, the influence is easy to calculate:

influence = (targetShape - baseGeometry) * weight * 0.01

dstGeometry = baseGeometry + influence

But if there are more than one targetShapes on this channel, this is an in-between

blendshape, also called progressive morph. The calculation of influence is different.

For example, given two in-between targets, the full weight percentage of first target

is 50, and the full weight percentage of the second target is 100.

When the weight percentage reach 50, the base geometry is already be fully morphed

to the first target shape. When the weight go over 50, it begin to morph from the

first target shape to the second target shape.

To calculate influence when the weight percentage is 25:

1. 25 falls in the scope of 0 and 50, the morphing is from base geometry to the first target.

2. And since 25 is already half way between 0 and 50, so the real weight percentage change to

the first target is 50.

influence = (firstTargetShape - baseGeometry) * (25-0)/(50-0) * 100

dstGeometry = baseGeometry + influence

To calculate influence when the weight percentage is 75:

1. 75 falls in the scope of 50 and 100, the morphing is from the first target to the second.

2. And since 75 is already half way between 50 and 100, so the real weight percentage change

to the second target is 50.

influence = (secondTargetShape - firstTargetShape) * (75-50)/(100-50) * 100

dstGeometry = firstTargetShape + influence

四,多通道同时影响时的叠加方式。

假设变形物体X受channel1和channel2两个通道影响,channel1中只有一个变形目标shape1,通道变形进度为w1;channel2中只有一个变形目标shape2,通道变形进度为w2。设v是X上一点,原始坐标为p;v1是shape1上等位点,坐标为p1;v2是shape2上等位点,坐标为p2。

则v在两个通道影响下变形后的坐标p_deformed应计算如下:

p_deformedByChannel1=p+(p1-p)*w1

p_deformedByChannel1andChannel2=p_deformedByChannel1+(p2-p_deformedByChannel1)*w2

p_deformed=p_deformedByChannel1andChannel2

五,法线问题。

对变形物体进行变形,如果只是顶点位置发生变化,而法线不变的话,那么在有光照的情况下显示效果是不对的,所以法线也需要在变形物体和变形目标之间进行插值。

前面分析fbx变形动画数据逻辑结构时提到“targetShape中包含controlPoints和一个fullWeight值”,是因为在viewScene示例中,只使用targetShape的controlPoints对变形物体的顶点位置进行了变形,而根本没有处理法线的变形。我没有找到由targetShape获得有效normals的方法。而且当我把动画导出为ascii的fbx,查看targetShape的normals数据时发现全是0。

我目前的解决办法是通过targetShape获得targetShapeName,然后再按名称在场景中搜索到与targetShape相对应的模型(mesh),然后从mesh中取得法线数据。这样就要求变形目标模型不能删,且要随变形物体一同导出到fbx文件中。另外一个需要注意的问题是,由于我的引擎中只支持三角网,于是要求或者在3dmax建模时物体就建成三角网,或者在导出为fbx文件时勾选“三角化”选项,或者在引擎载入fbx文件之后调用fbx sdk提供的api转换为三角mesh。但是后两者都不能保证变形物体mesh和变形目标mesh在三角化后仍具有完全相同的拓扑结构。而如果变形物体mesh和变形目标mesh的拓扑结构不同,法线插值就无法进行。

注意:顶点位置插值是不要求变形物体mesh和变形目标mesh拓扑结构相同的,只要顶点能一一对应,顶点位置插值就可以进行,所以如果像ViewScene示例那样只处理顶点变形而不考虑法线变形的话,不必要求模型在3dmax中就建成三角网。(不需要考虑法线变形的情况确实是存在的,例如的像《地铁跑酷》那种无光照的Q版3d游戏,根本不需要法线,因此做变形时也不用考虑法线变形)。

法线插值是向量间插值,与顶点位置插值(点之间插值)是不同的。点之间的插值直接线性插值即可,而向量间插值严格来讲应该使用球面插值(slerp)。不过经过试验,发现在此处两种方法的视觉差异并不很大,且线性插值速度要快得多,所以最后我仍然选择了线性插值。

六,ViewScene示例中变形动画代码有错误。

ViewScene示例中播放变形动画的代码是有错误的,将动画由3dmax中导出为fbx再用viewScene示例播放,会发现viewScene示例播放结果与3dmax中不一样,而且动画会出现跳变等明显错误。

我现在已经记不清具体是什么原因造成的了,但我在自己的播放程序中解决了这些问题。

效果视频:

时间: 2024-10-04 16:04:08

FBX BlendShape/Morph动画解析的相关文章

Skeleton with Assimp 骨骼动画解析

Skeleton with Assimp 骨骼动画解析 骨骼动画是图形学中十分常见应用很广泛的一个技术,也是比较基础的内容,作为图形学的工程师需要将这一部分内容梳理清晰,主要关键在于几点:第一,分清楚骨骼.节点两个概念:第二,熟悉使用 Assimp(或者其他的)的解析方式,并编程实现骨骼的解析和动画的播放. 理解骨骼 首先,为什么会有骨骼动画这么一种东西的存在呢?如果我们从我们自己的身体上观察,就可以发现,我们全身可以活动的部分,其内部基本都有一根主要的骨头,比如小臂的挥动,小臂上所有的肌肉皮肤

Android动画解析--XML

动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimation 画面转换位置移动动画效果 RotateAnimation 画面转移旋转动画效果 Android动画模式 Animation

自动切割fbx中的动画

自动切割FBX中的动画 最近写了一个有意思的工具,能够自动切割fbx中的动画信息,如下图所示: 本来不想造轮子,从晚上查找一番,发现并没有自己满意的工具,只好自己出手啦. 核心代码如下: [MenuItem("liubo/自动切割骨骼动画2")] public static void AutoClip2() { AutoClip2Impl(""); } static void AutoClip2Impl(string spec) { /* * 读取excel表,获取

animate动画解析

对于这个css3属性,w3c定义其为实验性技术,那么自然对于那些非高帅富浏览器来说都是痛,通过caniuse我们可以直观看见这个属性浏览器支持情况: IE10+和firefox33+支持这个属性切不需要写私有前缀,chrome31+,safari7+,andriod4.1+都需要写上自己的私有前缀才可以支持,不过oprea电脑端支持,但是移动端的却不支持,无解.w3c的官方文档 属性名: animation 属性值: <single-animation># 初始值: 详见独立属性值 应用于:

iOS动画解析

iOS引入动画效果可以使我们的软件得到更好的用户体验,因此动画的深入研究无疑对于开发者一个很好的加分项. 常见的iOS对动画的操作分为两类: CALayer层的操作 UIView的操作 二者有何区别 UIView里面包含有一个CALayer层 UIView之所以能够在屏幕上显示出来,完全因为其内部拥有一个CALayer层 CALayer层的操作更底层更轻量级.性能更高. UIView动画执行完毕之后不会反弹,而CALayer动画改变layer的状态位置,出现假象的改变,其实实际位置并没有改变 开

Android 动画深入解析

动画在安卓的一些娱乐应用上面应用非常广泛,在不牺牲性能的情况下,可以带来很好的体验,下面就详细讲解一下安卓动画的实现方式.学知识就学个明明白白. 动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 Transla

骨骼动画具体解释

转载:http://blog.csdn.net/ccx1234/article/details/6641944 近期,再次研究其骨骼动画,发现这篇文章讲的相当不错,通俗易懂,非常好的学习资源. 骨骼蒙皮动画(Skinned Mesh)的原理解析(一) 一)3D模型动画基本原理和分类 3D模型动画的基本原理是让模型中各顶点的位置随时间变化.主要种类有Morph动画,关节动画和骨骼蒙皮动画(Skinned Mesh).从动画数据的角度来说,三者一般都採用关键帧技术,即仅仅给出关键帧的数据,其它帧的数

Android开发之动画

动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转移旋转动画效果 JavaCode中 AlphaAnimation 渐变透明度动画效果 ScaleAnimation 渐变尺寸伸缩动画效果 TranslateAnimation 画面转换位置移动动画效果 RotateAnimation 画面转移旋转动画效果 Android动画模式 Animation

(四)Android动画开发---Animation动画效果详解

Android 使用Animation的具体操作方法我们将会在这篇文章中做一个详细的介绍.大家可以通过这里举出的代码进行解读,并从中了解到相关操作技巧,方便我们将来开发应用,并且加深对这一操作系统的理解程度. 在Android中,分别可以在xml中定义Animation,也可以在程序代码中定义. 动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面转