目前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/morph)基本原理。

大体上讲就是在拓扑结构相同的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()的代码便可以直接想象出来了:

1,对于只有一个变形目标的通道(非渐近变形),只要根据通道变形进度weight在变形物体和变形目标间插值。

2,对于含有多个变形目标的通道(渐近变形),看变形进度weight落在哪两个变形目标的fullWeight之间,然后计算weight将此区间分成的比例得到此区间上的变形进度weightOfSpan,再根据此区间变形进度在上述两个变形目标间插值。

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

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

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

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

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

我在c3dEngine2(https://github.com/wantnon2/c3dEngine2)中添加了一个app_fbxLoader_shapeDeformTest demo,效果视频:

转载于:https://www.cnblogs.com/wantnon/p/4306170.html

FBX BlendShape/Morph动画解析相关推荐

  1. 【转】Unity3d:读取FBX中的动画

    [转]Unity3d:读取FBX中的动画 从模型中获得切割好的动画clip,并且对其中设置好的动画事件进行修改方法: 1.动画模型后缀为.FBX.在Unity3d中,能够显示FBX中的动画.要加载模型 ...

  2. 爱奇艺播放按钮动画解析

    一.动画过程分析 1.拆分动画 正常动画效果如下: 操作 现象 结论 放慢动画 这个效果可以反复多看几次,观察一下这个动画是由那几部分组成的,然后再往下看 添加辅助颜色 可以看出,整个动画有四部分组成 ...

  3. 3D引擎中的大量Morph 动画, 变形变形变形

    请见Demo: Vox APP 大量的morph动画,请见Demo: Vox APP 3D系统中 Morph 动画需要改变顶点坐标.可以再GPU中完成计算,也可以在CPU中完成计算再将数据传到GPU. ...

  4. CSS3动画解析抖音 LOGO制作

    为什么80%的码农都做不了架构师?>>>    前言 "字节跳动"现今也是如日中天,旗下产品,除头条外,还有短视频平台"抖音",人气也是非常高 ...

  5. three.js案例解析之代码实现morph动画

    你好,我先给你截图效果. 变形前: 变形后: 你可以先了解一下这个变形动画的参数: spherify,圆化度 twist,弯曲度 本案例用到的three.js知识点 Scene 场景是你放置物体.灯光 ...

  6. 一道简约而不简单的算法题——数据流的中位数 | 附动画解析

    作者 | 程序员小吴 转载自微信公众号(ID:CXYxiaowu) 题目来源于 LeetCode 上第 295 号问题:数据流的中位数.难度级别为 Hard,目前通过率为 33.5% . 题目描述 中 ...

  7. 微信小程序实现FBX模型的动画加载

    鉴于有CSDN友问我FBX模型在小程序端加载的问题,我就在这里给大家介绍一下吧~ 首先,加载fbx模型,我们用到的是three.js和不同的模型类型的加载库,那么,我们在得到了web版本的加载库的前提 ...

  8. 动画解析:图的遍历方式有哪些?

    点击关注上方"五分钟学算法", 设为"置顶或星标",第一时间送达干货. 转自景禹 小禹禹,你们好呀,景禹今天给你们说一说图的遍历方法! 小禹禹: 好呀好呀,图的 ...

  9. 微信小程序动画解析以及transitionend重复 animationiteration animationend失效问题解析

    github项目代码 github项目代码 https://github.com/MrITzhongzi/small_routine_components/tree/master/5.danmu_co ...

最新文章

  1. adb devices 找不到设备的解决方法
  2. BZOJ1076 [SCOI2008] 奖励关
  3. 图片操作scipy.ndimage.imread和scipy.misc.imresize
  4. python 对excel文件进行分词并进行词频统计_教你背单词 | 利用python分析考研英语阅读并生成词频降序表...
  5. windows server 2008中IIS7的功能模塊
  6. spring AOP 代理(静态与动态+使用cglib实现)
  7. 2008-03-17 淋湿的心情
  8. iPhone 11 820-01523 N104手机电路原理图+位号图
  9. There is no index in the referenced table where the referenced columns appear as the first columns.
  10. 谱聚类(spectral clustering)
  11. 第一只WiFi蠕虫的诞生:完整解析博通WiFi芯片Broadpwn漏洞(含EXP/POC)
  12. 加大货币发行量 quantitative easing
  13. 【HTML------樱花雨】
  14. 小繁的Binary_Indexed_Tree学习笔记
  15. [GIS算法] 矢量(数组基础、编程基础)
  16. 【PostgreSQL】客户端请求处理 PostgresMain()
  17. PMBOK泛读(第三章) - 项目经理的角色
  18. 时间序列(一):上手体验
  19. 数据赋能 兴业惠民 | 山东省第三届数据应用创新创业大赛潍坊分赛场火热报名中
  20. android开发步步为营之112:关于Camera镜像上下左右颠倒问题的解决办法

热门文章

  1. IT公司架构以及发展路线
  2. x86、x64、x32和64位、32位的区别与联系
  3. 工作管理工具|职场人提升工作效率必备的五大工具(项目管理必备)
  4. Snyk安全漏洞扫描使用记录
  5. Synopsys Sentaurus TCAD系列教程之-- Svisual《一》看图工具
  6. Qt 之图形(QPainterPath)
  7. 读论文-SOD-U2Net算法研究
  8. BMI 指数测试 BMI = 体重 (kg) / 身高² (m)
  9. 罗斯魔影消消乐h5游戏源码
  10. 林锐 de 大学十年