学习笔记 --- 3dMax骨骼绑定(第二篇)
0.前序
好的笔接上文...
有关3dMax骨骼动画与Unity的导出对接,相关知识点,标准工作流程,骨骼绑定原则,
已经在隔壁开了文章,不妨看看
18.骨骼的伸缩与装配
---18.x 三种角色动画形式
我们通过3dMax制作 动画,或者说角色的动作 导入到Unity中,
对于实现角色动作,主要有三种动画形式
1. FK-Transfrom级位移/旋转/缩放
直接在3dMax场景中,位移/旋转/缩放一个物体,在其Transfrom矩阵上产生动画,并结合Transform矩阵嵌套表现出的 FK父子关系 来生成动画
我们之前提到的 所有绑定的手段 ,包括父子关系,连线参数,约束,反应管理器,IK,这些效果 在3dMax导出时,都可以通过动画烘焙+重采样的形式,转为FK,Transform矩阵性质的动画效果

并且这一基本的动画效果,可以被Unity从FBX文件中默认解析
2. 骨骼动画
首先通过构建骨架,绑定骨骼,为骨架中的骨骼节点生成FK-Transfrom级的动画
随后通过蒙皮修改器,为网格上的顶点赋予对不同骨骼节点的权重, 在游戏渲染时,根据骨骼节点的位置以及权重,来影响网格顶点的位置
目前Unity只能默认解析Skin蒙皮修改器 中的权重信息,并将网格通过 Skinned Mesh Renderer 组件渲染出来
并且FBX文件也只支持导出Skin蒙皮生成的顶点权重信息,Physique蒙皮在导出时会被转为Skin蒙皮
3.变形动画
变形动画是直接在网格顶点层级记录顶点的位移属性,来生成动画
相比骨骼动画,变形动画的功能往往更加强大,可以实现复杂而细腻的效果
但变形动画无法直接保存在FBX文件中 ,需要通过 点缓存 文件来导出和应用
---18.x 3dMax中的几种变形动画
上文说到我们可以在编辑骨骼---对象属性中,取消骨骼的 冻结长度 ,并启用 缩放/挤压 ,两种拉伸模式,进而对蒙皮在骨骼上的顶点集,产生 单轴缩放/单轴挤压缩放 的效果
借助这个效果我们就可以制作一些 肌肉的牵动 , 关节运动导致肌肉隆起 的效果
不过这个牵动的效果,是直接作用于顶点的 变形动画 ,无法直接通过FBX导出并应用到Unity中,需要使用 点缓存修改器 ,导出 点缓存数据 ,并在Unity中使用 MegaFiers插件 来读取应用
同样的我们之前提到的, 蒙皮变形修改器 产生的效果,也属于变形动画,也可以通过点缓存+MegaFiers插件来导出应用

Unity当中的 骨骼动画 ,是读取Skin蒙皮修改器中的顶点权重,并结合骨骼节点的位移/旋转/缩放动画,在渲染时计算影响模型顶点, 一些直接作用于顶点的动画效果(变形动画)不在这个范畴之中
不过 Morpher/Blend Shape 变形器动画 效果,Unity是支持解析的,可以在Untiy模型导入的设置中找到读取选项
骨骼的FK-Transfrom级位移/旋转/缩放动画,以及对于蒙皮顶点的骨骼动画影响是被默认导出,应用到Unity中的
因此一个思路是 取消长度冻结后,将拉伸模式改为无 ,借助下文的 骨骼装配技巧 , 以及反应管理器控制骨骼的单轴缩放/挤压缩放 ,来产生肌肉的拉伸,隆起一类效果
从而转由骨骼绑定,来生成FK-Transform动画效果给骨骼节点,并通过骨骼动画的形式作用于网格顶点
这样的效果便能够跟随FBX文件被默认导出,应用到Unity中


---18.1 脖子伸缩骨骼的装配
首先要注意的是,我们 应在装配开始前完成复制 ,装配后,父子关系的绑定以及约束控制器的加入,经常导致镜像复制出错, 注意使用骨骼工具的镜像 ,通过旋转实现的镜像效果,而不是-1缩放

父骨骼取消冻结,开启缩放伸长模式
我们创建一个点辅助对象 对齐到末端的子骨骼上

之后我们将点辅助物体绑定的肩胛骨上

我们将末端的子骨骼 位置约束 到点辅助对象上
前文中已经提到,此时约束作用将会产生 截断效果 ,子物体的位置将不再受父骨骼的影响,而是在世界位置上绝对跟随点辅助物体
而父骨骼又取消了冻结旋转,此时在脖子骨带动父骨骼向一侧旋转的同时,由于子骨骼位置锁定,父骨骼就会被拉伸

---18.x 约束的取消与错误
我们可以通过运动---参数面板,修改子骨骼位置控制器为位置约束
也可以通过Max菜单中的动画---约束---位置约束,选中点虚拟体的方式来快速添加
不过使用Max菜单添加,是 使用了一个位置列表,在下方添加了一个位置约束

这么做的意义在于日后,当我们想 取消位置约束时 ,我们只需在位置列表中删除掉位置约束即可
而指定旋转控制器为位置约束,如果我们想取消约束,恢复独立运动,当我们切换修改器时会产生错误,首先物体会在切换修改器后被移动至一个奇怪的方位,并且可能无法移动


对于直接使用约束修改器的取消
有时候可能我们没有注意到要使用Max菜单中的动画---约束,通过列表的方式添加约束
而是直接变更旋转控制器为约束,这种情况下我们再变更回EurlAngelXYZ或者位置XYZ修改器就会产生错误

此时我们可以先将修改器变更为旋转列表,保留已有的约束控制

下方添加新的EulerXYZ和注视约束,和最上方原有的约束使用相同的设置
随后删除最上方原有的注视约束,再删除下方添加出的注视约束即可
删除后可能旋转/位置仍有偏差,但不会出现bug

---18.1 脖子伸缩骨骼的装配
好的回到骨骼装配
我们给父骨骼添加一个注视约束,目标选择点辅助物体

此时父骨骼在伸长的同时会保持注视向子骨骼,就如同是子骨骼一侧角点固定,被脖子的旋转拉长了一样,就如同一条被牵引的 肌腱

关于位置约束和注视约束,之前的动画系统基础入门篇有详细的介绍,这里就不过多赘述了
视线虚拟体可以通过勾选掉绝对视线长度,再将长度置0来消除

如果我们希望将脖子肌肉拉伸的效果导出应用到Unity中,就不能使用骨骼属性自带的拉伸
在前面的装配基础上,我们应将父骨骼接触冻结长度, 拉伸模式置为无,并通过反应管理器,脖子旋转控制父骨骼缩放的形式来进行拉伸效果的表现 ,从而将对顶点的影响, 以蒙皮骨骼动画的形式表现出来


同样的思路后面的几种装配,对于骨骼的伸缩/挤压伸长效果,如果想要导入Unity中的话,都可以对骨骼节点应用反应管理器产生Transfrom的缩放,之后就不再赘述了
---18.2 手臂伸缩骨骼的装配
我们在前视图中创建出这样的一条骨骼

骨骼编辑模式,结合其它视图调整位置,尽量让骨骼平行于Biped大臂骨

调整骨骼的大小

骨骼属性,取消冻结长度,挤压拉伸模式

同样 注意在装配开始前,完成复制

和之前的方法一样,我们创建一个点虚拟体对齐到子骨骼
将子骨骼位置约束到点上,并将点绑定到小臂上
我们 不需要给父骨骼添加注释约束 ,我们只需将父骨骼绑定到大臂上,并 让其沿自身的原轴向产生挤压缩放即可
这里的骨骼就如同一个固定位置/方位的伸缩器,在转用反应管理器时我们可以 只创建这一块骨骼 并进行挤压缩放控制即可
用于保持朝向的末端子骨骼&点虚拟体无需创建

类似的方法,我们再在大臂背侧创建一条骨骼,控制背侧的顶点,在屈臂时产生牵拉的效果
这里启用拉伸缩放模式+注释约束,产生 肌腱效果

此时屈臂,
后方的骨骼会被拉伸,并在注视下向轴关节内侧旋转,从而控制大臂背侧的顶点,产生肌肉的牵拉,收缩效果
前方的骨骼则会在挤压缩放下扩大,从而产生大臂前肌肉隆起的效果

同样的方法,我们完成另一侧的装配

19.胸部肌肉牵动&呼气起伏效果
---19.1 胸腔骨骼搭建
先创建如图所示的一组骨骼,注意结合不同视图,骨骼编辑模式调整

胸部肌肉位置使用两片骨骼,注意调整宽高填充,并旋转贴合肌肤走势

创建一根中心骨作为胸腔骨骼的最高父骨骼,调整居中(X轴位置归0,子骨骼X轴位置归0),同样旋转贴合肌肤走势

镜像复制骨骼,将四片骨骼链接到中心骨上

中心骨链接至Biped的最高位脊椎骨上

创建一个点辅助物体用于装配,将点辅助物体也先链接到Biped最高位父骨骼上

随后复制点,复制中将保留父子关系,我们为子骨骼的每一个节点位置都复制一个顶点用于辅助装配

旋转以下Biped脊椎,检查确认能带动所有胸腔骨骼和点辅助物体

---19.2 骨骼装配
与前面一样的思路,进行 肌腱效果装配
我们将四片胸脯位置的骨骼,添加注视约束指向各自的点辅助物体,注意勾选 保持初始偏移 ,消除虚拟视线

四片骨骼开启缩放伸长

末端子骨骼约束至点辅助物体上

我们将点虚拟体绑定到Biped大臂骨骼上,从而形成胸部指向大臂的肌腱效果,在大臂运动时对胸部肌肉形成一定的牵动效果

将如图骨链每根骨骼节点注视约束到其指向位置的虚拟体上,注意保持初始偏移

注意骨骼物体,我们在场景中看到的 只是一个虚拟体 ,实际在骨骼动画的计算中, 它只是一个空节点(带有Transfrom属性) ,虚拟体的根部位于真正的节点位置,虚拟体指向其子骨骼的节点位置(指向子骨骼虚拟体根部)

仅对末端的两组骨骼使用位置约束,绑定到其根部的虚拟体上

我们创建一个虚拟体用于控制呼吸的起伏(移动+缩放),将所有点虚拟体链接到该虚拟体上,再将其链接到Biped高位第二根脊椎骨上

当我们前移/缩放时,整个胸腔都会产生一个起伏的效果

独立转动第一根脊椎,上部运动,下部四根骨骼位置固定,中间产生牵拉效果

转动第二根脊椎时整个胸腔骨架一起转动

这种绑定的思路,对脊椎后旋的处理就很全面
最上的一块Biped脊椎骨旋转时,会产生类似挺胸的效果,胸脯部分挺起,对下部牵动
下侧的一块Biped脊椎骨旋转时,则是弯腰的效果,我们最下侧的一组骨链恰是胸腔的最下方一条肋骨的位置,从而是整个胸腔一起跟随转动
---19.3 解决骨骼错位问题
存在 父子关系+约束 时,骨骼可能会在运动中产生 位置/旋转的错位 问题(应该是由于万向锁一类运算插值bug导致问题)


我们观察一下错动前后骨骼的位置,发现X轴位置突然被取反

前面提到了约束是具有截断性的,会强制打破父子关系带来的Transfrom矩阵嵌套影响
这里骨骼的旋转被注视约束截断,但位移仍跟随父骨骼,在运动中 位移/旋转使用两种不同的控制模式 ,并且 约束是叠在Transfrom上面的,这就有可能在插值中产生bug
解决方法也很简单,就是给骨骼添加一个位置约束绑定到其父物体上
这样就 完全和Transform矩阵嵌套脱开关系,完全由约束控制物体的位移/旋转 ,从而避免bug的产生

20.眼部骨骼
我们希望在眼球转动的同时能带动头部模型,眼眶周围的部分皮肤一起运动
为此就不能单纯只给眼球添加注视约束,我们可以在眼球上创建一块骨骼带动眼球转动,同时作为眼眶周围网格的蒙皮骨骼

可以看到我们的眼球并不是一个球体,而是在内眼角有一块凸起,这一处凸起我们在最后蒙皮时不会施加权重

这一块是固定于内眼角中的肌肉组织,用于支撑眼球,不会跟随眼球转动

侧视图创建骨骼调整大小

创建新的末端,将眼球轴心调整至球心,父子骨骼XZ轴对齐轴点

我们要将眼球轴心调整到球心,同时父骨骼位置对齐到眼球的球心,保证蒙皮后眼球是绕其球心转动的
镜像复制骨骼给另一侧的眼球

创建一组点和一个长方形辅助物体,对齐位置
将骨骼注视约束到对应的点辅助物体上
我们再将点辅助物体绑定到长方形辅助物体上,用于一并控制双眼的注视

最后我们将两根骨通过父子关系绑定到Biped头骨上
注意长方形属于 辅助物体,不应进入骨链的父子关系中 ,应通过变换---链接约束绑定到Biped头骨上
后面动画中如果存在人物注视,凝视某处,只需改变长方形辅助物体的链接约束绑定到其它注视物体上即可


最后我们移动一下Biped质心Hips,检查所有骨骼,辅助物体跟随

好的至此自定义骨骼结合Biped骨骼搭建已完成
鸟类角色骨骼搭建&绑定实例
好的,接下来的实例中我们通过一个鸟类角色的实例,学习有关角色身体骨骼的搭建与弯曲绑定,手部骨骼的搭建和抓握的绑定效果,以及翅膀骨骼的搭建,伸缩绑定效果
21.身体骨骼的搭建&虚拟体布置
起手依旧是 节点检查 ,角色位置应位于世界原点,脚踩Z=0的“地面”,注意缩放矫正

创建控制尾部的这样一段骨骼,注意节点位置

先创建这样的一整段骨骼布置在脊椎的走势上,注意调整,对齐一下节点相拼的轴点

细化 处理一下,相拼节点左右各细化出一段用于给注视约束提供位点,脊椎细化为三段

创建出这样一段骨链用于控制脖子,注意节点位置要放在拐点,根部留一小段骨骼

创建出控制头部的骨骼,根节点与脖子骨链末端相拼对齐
重创建末端, 骨骼编辑模式下,将末端对齐到父节点 ,从而让骨骼处于精准竖直

复制摆放一下虚拟体,
这里粉红色虚拟体用于控制头骨的旋转,以及脖子/脊椎/尾巴的弯曲链接式旋转
蓝色虚拟体用于控制脖子/脊椎/尾巴的平直式旋转
对于虚拟体的形状,颜色,大小没有什么特别的要求,我们自己喜欢,自己习惯就好
实际制作中虚拟体作为一个绑定的节点,发挥作用的只是其轴心点的Transform,并且导出FBX时我们会丢弃掉虚拟体

最后我们将底部的Root虚拟体复制出来一个,调整旋转缩放,对齐到角色骨盆的方向和位置上,用于控制角色整个上半身骨架的统一运动

22.自定义属性实现归位功能
完成绑定后我们会通过外部一些明显的辅助物体(点辅助对象/样条线)来控制角色的全部动作,这里我们希望实现一个 虚拟物体在移动/旋转/缩放后复位的功能 ,从而让角色恢复到初始姿态

这里我们给控制用的 样条线辅助物体 ,创建一个 点虚拟对象 ,并 对齐到位置和方向


之后我们将样条线绑定到与之对齐的点辅助物体上,成为其子物体

最后别忘记 将点辅助父子绑定到根节点上

借助对齐的点辅助物体作为父轴心,我们就 可以通过将父对象坐标系下的位置/旋转/缩放清0,来实现复位
后续见 30.MaxScript脚本 实现对齐父物体
23.节点重命名
骨骼绑定&蒙皮中存在着大量的节点(骨骼/辅助物体),往往我们 需要通过一定的命名规则来管理这些节点
我们不能使用Max的默认命名 ,Bone,Point,这会导致后续我们导出导入角色/资源时极易发生节点的重名,造成不必要的麻烦(Max导入时不允许导入资源节点与当前场景节点重名)
同样的,在游戏开发中,我们亦需要对角色的骨架节点,采用一定的命名标准来管理
这里Max为我们提供了一个快速完成多节点重命名的功能
工具---重命名对象

我们可以结合选择过滤,选择集,对选中的节点进行统一的重命名

重命名的规则可以根据个人习惯,或是团队/企业规范来确定
前缀/后缀名称,注意手动添加一个下划线 '_',用以区分
节点最终的名称将会是: 前缀+基础名称(中缀)+后缀+编号跑位(不包括+号)


个人的资源命名习惯:
前缀,一般会作为资源的大类标签,例如 Bone_骨骼节点,Tex_纹理资源,Ctrl_控制辅助物体,
中缀,一般是这个节点/资源,所在物体/对象的名称,例如 ZeiO贼鸥,Robot机器人,Safina莎菲娜
后缀,一般是这个节点的具体作用/效果,或者说发挥其作用/效果的位置,例如 _Body身体节点,_Hip骨盆/质心节点,_DiffuseMap漫反射纹理,_NormalMap法线纹理
一些命名的技巧
事实上 只有我们启用了基础名称(中缀)时,节点原本的名称才会被完全替换掉

不启用基础名称,节点原本的名称就会被保留,并叠加上我们设定的前缀/后缀/编号

因此我们可以 先统一命名前缀&基础名称(中缀)

之后再分部选中,施加后缀和编号,或是为特别的非重复节点手动添加后缀



24.局部方向约束---弯曲骨链的绑定方法
这里我们最终想要通过手动搭建骨骼&绑定,实现等同于Biped脊椎骨的效果



这里就需要用到 局部坐标方向 约束
为此我们需要先 将控制物体的父物体方向对齐到骨骼节点上 ,保证其 父物体坐标系下旋转轴向的一致性
注意!!!
这里的 局部--->局部模式的位移旋转控制是参照父物体坐标系 (相对父物体惯性坐标系)进行控制的(和连续参数,反应管理器绑定一样)
关于父坐标系下的,缩放/旋转/位移 轴向问题,详见上一篇第 11.1 节
可以看到我们这里是 拿着控制物体的父物体 (本例中是中间那个点)去对齐骨骼,从而保证骨骼节点和控制物体,的旋转轴向在 父物体坐标系下的轴向一致
这种 局部--->局部模式,要求控制物体必须具有父物体 ,并通过父物体对齐到骨骼轴向,保证控制物体与骨骼,父物体坐标系(相对父物体惯性坐标系)的旋转轴向一致
如果控制物体没有父物体(世界的子物体),那么它的父物体坐标系下旋转轴向,是相对世界原点的惯性坐标系,其轴向无法调整(我们不能改变世界坐标系轴向)

Max中默认骨链节点是以X轴为延伸指向

我们将尾部的骨骼节点 方向约束 到控制样条线上,并启用 局部--->局部 模式

注意!!!先绑定完父子关系再进行约束
约束后如果父子关系改变(绑定/解绑),可能还会产生新的偏移
注意!!!不能勾选保留初始偏移,否则局部方向约束会失效
约束完成后骨骼节点可能有45度/90度的偏移,这里注意使用 动画菜单中约束(以列表添加约束) ,我们激活上方的EulerAngleXYZ控制,对骨骼节点调整转回即可
调整后记得重新激活下方的方向约束
在不勾选保留初始偏移的前提下, 我们也可以通过上面的方法,去设置一定的初始偏移
局部方向约束的原理,并不是对父物体坐标系下,数值上的死绑定,而是 偏移量的绑定 ,即控制物体转5度,并不是将旋转后的数值绑定传递给骨骼,而是传递5度的旋转偏移量,从而骨骼节点也会转5度,因此我们可以通过激活上方的位移/旋转控制器,主动设置一定的初始偏移(记得不要勾保留初始偏移)
保留初始偏移是给世界坐标下的约束使用的 ,世界坐标下的约束,是 数值上的死绑定 ,因此需要勾选保留初始偏移,来产生一定的偏移

我们将尾部骨链的四个节点都局部方向约束到控制虚拟体上

此时由于局部方向跟随,我们在旋转控制物体时,整条骨链每一个节点都 参照其父坐标系下(相对于父物体)产生了旋转跟随 ,从而最终就产生了旋转的叠加效果

之后我们将父节点绑定给用于控制平直旋转的辅助物体上

我们将预先细化出的那一小块父骨骼节点方向约束到控制平直旋转的辅助物体上,这里采用世界模式,保持初始偏移

从而转动控制物体,我们可以通过细化出的那一小段父骨骼令整个尾部直接抬起,实现平直旋转,并且 这两种绑定互不影响

类似的思路可以应用在所有的骨链中 ,当我们希望实现等同于Biped的扭曲链接旋转+平直旋转模式时,都可以应用这个方法
两个辅助控制物体,局部方向约束模式的旋转叠加,细化小块父骨骼实现平直旋转
---24.1 对比各种绑定
本节我们来对比一下,父子关系,连线参数,局部约束,世界约束,反应管理器这些绑定的内核
记录一下对比中提到的各种绑定方法的详细应用章节方便查阅
1.关于位移/旋转列表的应用,详见上篇 P10节
2.关于连线参数的应用详见上篇 P10 节,本篇 P28 节
3.关于世界约束的应用详见上篇 P8节,结合列表实现等同父子关系效果详见上篇P10节,世界约束解决错位问题详见本篇 P19.3节
4.关于局部约束的应用详见本篇 P24 节
5.关于反应管理器的使用详见上篇 P11节,本篇 P36 节
对于骨链旋转叠加的效果,目前我们已经学习了两种方法
一种是上一篇第10节中提到的,通过 连线参数+旋转列表 的方法实现
另一种是本篇P24节的, 局部方向约束 实现
两者的相同点有二:
1.两者都是参照父物体坐标系下的缩放/旋转/位移轴向(详见上一篇11.1节)
2.两者都可以结合位移/旋转列表应用 ,通过激活上方的位移/旋转修改器来设置初始偏移量,亦可以保持激活,进而节点在接受连线参数方程输出OR局部方向约束偏移量传递,的同时能够进行独立的位移旋转
关于连线参数
由于连续参数可以具体指定那个轴向之间相互绑定,因此只需要 在父物体坐标系下观察确定好轴向,填入正确的公式 即可,控制物体可以是世界的子物体,也可以任意结合进父链
注意 degtorad() 函数的运用,如果我们想要消除或额外施加一个90度的初始偏移,需要写为
角度+degtorad(90)
连线参数的绑定是一种数值上的死绑定, 可以结合旋转列表,提供一个归0位点 ,从而通过激活上方的修改器,手动位移旋转设置一定的初始偏移
亦可以保持上方位移/旋转修改器的激活 ,从而节点能够独立的旋转位移,并在此基础上接受连线参数方程的输出控制
关于局部方向约束
而局部方向约束,是父物体坐标系下的 偏移量传递
这就要求控制物体的父物体坐标轴向必须与骨骼节点对齐(对齐是运动方向的一致性,或者说向量的对齐,坐标数值上可以有一定的偏移量差异)
为了保证父物体坐标系轴向对齐 控制物体必须具有一个父物体,我们需要拿父物体的轴向去对齐到骨骼节点的轴向
由于是偏移量的传递,我们可以通过激活约束上方的位移/旋转修改器,很方便的调整初始偏移量,亦 可以保持激活,进而节点能够独立的位移旋转,也能接收偏移量的传递 (无需在约束修改器下方再增加位移/旋转修改器)
但要注意 不要勾选约束中的“保留初始偏移” ,这个选项是给世界约束使用的,因为世界约束是数值死绑定, 如果在局部约束下开启会导致局部约束失效
关于反应管理器
反应管理器和上面提到的,连线参数&局部方向约束,的相同点一致
1.参照父物体坐标系下的缩放/旋转/位移轴向
2.可以结合位移旋转列表使用, 位移旋转列表也可以给反应管理器提供归0位点(详见下面的36节),我们激活上方的位移旋转修改器也可以设置初始位移/旋转,或者在反应管理器控制的基础上,进行独立的位移和旋转
此外要注意的是,反应管理器是基于关键点(状态记录)之间生成的,输入输出映射曲线,形成的一种数值上的死绑定
绑定只在曲线范围内有效,曲线范围之外参照末端输出恒定 (和动画贝塞尔曲线的恒定越界模式一样)
详见上篇第11.2节的样例
关于列表与父子关系
位移旋转列表的内核其实就是每一层位移旋转修改器,都是在上一层的基础上施加一个额外的增量(在原来的基础上再加一个向量)
因此也不难理阶为什么 可以通过列表实现“归0” ,因为我们考虑每一次变换的时候,都是将已有的变换作为起点(原点)
物体最终相对于父物体的位移/旋转变换是整个列表,从上到下依次叠加的最终效果(向量依次相加)
物体相对于父物体的缩放(S)/旋转(R)/位移(T),这三种变换会合成一个4*4的Transfrom矩阵,在渲染时,用于变换物体顶点的位置
而物体相对于世界的缩放/旋转/位移变换,又需要叠加整个父链传递而来的变换(Transfrom矩阵相乘叠加形成FK正向运动效应,父物体的缩放/旋转/位移会影响到子物体的世界位置)
最终物体顶点的渲染位置,会由子物体Transfrom矩阵,依次相乘父链的Transfrom矩阵,得到的 世界矩阵来完成从模型空间 ---》 世界空间的变换 (这个矩阵记录了,世界坐标系--->物体坐标系的变换,进而可以将模型空间的顶点变换到世界空间,世界和物体在做相反的事情)
当然更多有关父子关系嵌套,矩阵变换的内容,在这里就不展开了,不妨参阅隔壁的文章
关于世界约束
世界约束其实就是在列表中,添加了一个特殊的变换向量
这个向量自身不会主动施加变换,而是到世界约束这一层时, 世界约束会保证物体在叠加了世界约束的向量之后,最终输出的世界位置/旋转能够达到目标 (多个约束目标加权重计算得到)
因此需要参照在这个向量之前,物体相对于世界的变换(叠加父链和列表上方所有修改器的变换),进行运算
也因此, 世界约束具有截断性/绝对性 ,无论上面做了什么变换,世界约束都会让最终输出达到目标
因此一方面我们在添加了世界约束之后, 即便启用上方的位移/旋转修改器,物体也无法进行移动/旋转 (实际那一层的位移/旋转是有效的,但是最终输出被世界约束的运算抵消掉了,我们在删除世界约束后就能看到运动的效果)
另一方面这种绝对性, 可以修正在复杂绑定下的一些错位问题 ,例如本篇第19.3节胸部骨骼的错位问题
此外,我们可以通过 在世界约束下面增设位移/旋转修改器并启用,从而达到等同于父子关系的效果 (节点经过世界约束,位移/旋转跟随到父物体,并在此基础上再进行独立的位移/旋转)
(这和反应管理器,连线参数,局部约束,通过启用上方的修改器保持独立性恰好相反)
注意勾选应用“保持初始偏移”,这个选项是专门为世界约束下,保留初始偏移而存在的
但我们需要在世界约束添加前,设置好初始偏移,世界约束添加后,即便启用上方的位移/旋转修改器 也无法再变换物体(无法设置初始偏移)
25.完成身体骨骼的绑定
脊椎和脖子的弯曲绑定
与24节中相同的思路,我们完成脊椎和脖子的装配绑定
我们将控制脖子平直旋转的辅助物体,它的轴心父点 位置约束 到脊椎的末端骨骼上( 辅助物体--->骨骼 )
脖子的末端骨骼可以直接 父子绑定 到脊椎末端骨骼上( 骨骼--->骨骼 )
头部的骨骼 父子绑定 到脖子的末端骨骼上( 骨骼--->骨骼 )



控制脊椎旋转,带动脖子合头部一起运动

骨盆的绑定
我们将尾部和脊椎,细分出的小块父骨骼,位置约束到控制骨盆的虚拟体上(骨骼--->辅助物体)

控制尾巴和脊椎,平直旋转的虚拟体,轴心父点直接父子链接给骨盆虚拟体(辅助物体--->辅助物体)

头部的绑定
我们将头部的骨骼方向约束到控制头部旋转的虚拟体上,这里使用世界--->世界模式即可

之后将虚拟体的轴心父点,位置约束到脖子末端的骨骼上,使虚拟体跟随脖子一并转动

这种绑定下,当脖子/脊椎发生旋转时,由于 方向约束的截断性 ,头骨不会跟随旋转,而是保持竖直,与Biped的效果一致

26.腿部骨骼的架设
首先在侧视图中创建两根腿骨,注意观察网格布线,找关节位置,位于网格的中点

切换到前视图调整,注意观察网格布线找关节位置

当我们 进行调整后,末端骨骼便不在父骨骼轴线上 ,此时需要我们删除,重创建末端

在大腿根处细化一块骨骼,对齐到脊椎的父骨骼节点上,绑定父子关系,形成一块链接骨,用于更好的控制胯部的网格

借助末端的小块父节点,可以完成整体的平直旋转,亦可以为其它骨链的绑定提供位点
此时我们旋转尾部对腿骨不会影响腿部,而旋转脊椎则会影响到腿部

脚部我们要做出一个爪子的骨骼布置,大致如图

我们在顶视图中,沿着脚趾 先创建一整条骨骼

骨骼编辑模式调整节点位置位于关节处, 删除末端骨骼重创建,保持骨链位于一条轴线上
再细化 出脚趾的第二关节, 局部坐标沿其轴线调整位置,保持骨链位于一条轴线上

同样的方法我们在末端细化出一块骨骼
骨骼编辑模式,视图坐标,对齐到腿骨末端节点上,绑定父子关系

这里的绑定,在视图上有些乱,我们不妨创建一个点辅助物体,对齐,并替换掉大腿末端的骨骼(绑定父子关系)
在骨骼工具中勾选 启用骨骼,将这个点辅助物体,作为一个骨骼节点使用

此时我们双击大腿的父骨骼,将沿骨链父子关系向下传导,一并选中所有腿部骨骼

利用骨骼工具的镜像,完成复制,这里点辅助物体无法直接复制,需要手动完成
我们可以重创建末端,创建点辅助物体对齐,之后绑定父子关系

最后工具---重命名对象,为腿部骨骼进行统一的重命名

27.巧用约束截断与HI实现腿部骨骼的绑定
我们想要实现等同于Biped腿部的效果
当我们选中脚部抬起时,向上对大腿&小腿产生IK传导, 实现抬腿而脚掌不会因抬腿发生旋转

这里如果我们直接添加HI解算器,腿部末端--->大腿
当我们抬脚时,脚掌发生了旋转
这是由于 IK解算器,向下对子节点产生FK正向运动效果 (更多相关HI/HD解算器的知识点可以看看之前机械角色动画篇的笔记,这里就不赘述了)
脚踝处的第一关节不表现旋转,但膝关节处,会在抬腿时发生旋转 ,进而以FK影响到脚掌,使之发生旋转

我们知道HI第一关节是不表现旋转跟随的
因此这里我们直接把腿骨的末端骨骼方向约束到脚掌控制物体上
从而借助约束截断其受膝盖旋转的FK影响,并且对HI链的运动不产生影响

我们再给脚掌的虚拟物体创建一个归位用的点,位置方向对齐到轴心

将这个归位点链接给Root根骨,脚掌控制物体链接到归位点,将HI解算器的 IK 控制点链接给脚掌控制物体

我们可以通过移动脚掌虚拟物体,实现抬腿,且脚掌不发生旋转

当我们主动旋转控制物体时,
HI解算器的IK控制点由于父子关系,跟控制物体旋转发生位移,产生IK效果
脚掌由于方向约束,跟随控制物体产生旋转

28.爪子抓握的绑定
我们希望实现一个抬脚时,爪子自动抓握的效果
这里先给脚掌控制物体加一个浮动限制,防止它移动到地面以下,以及影响到爪子形成反向抓握
浮动限制,是相对于父物体坐标系下的

我们打算使用连线参数来绑定,实现一个简单的角度变化即可
但这里需要解决两个问题

首先 连线参数的控制是相对于父物坐标系下的 ,
(链接前我们应切换到父对象坐标下判断绑定轴向)
如果我们直接绑定那么脚掌在地面时,爪子初始状态就不是平直的,而是父物体坐标下为0


这里我们可以通过之前提到的冻结旋转,来提供一个以当前旋转为初始位置的绑定位点

其次是角度过大的问题,默认表达式是通过一个浮点数控制旋转,而连线参数表达式中,角度的单位是弧度(rad),1rad 大约等于57度,
我们抬脚时会发现骨骼转了一圈又一圈...

这里我们可以通过下面的表达式,认为输入浮点单位是角度,将其转换到弧度

在连线参数编辑器中,我们固定左侧的控制参数不变,依次旋转新的节点,点击上方的刷新,找到对应的被控制参数,Ctrl+V粘贴表达式,快速完成绑定

OK看一下效果,似乎默认的直接映射旋转幅度直接满足了要求,
我们亦可以通过乘除smooth值,以及 sin cos 函数,编写复杂的映射表达式来满足不同的要求

29.露出变换
这里介绍一下露出变换,在辅助创建一栏我们可以找到露出变换辅助物体

通过拾取一个 露出节点 和 参考节点 (默认以露出节点父节点),露出变换会实时检测露出节点相对于世界的位置/角位移,以及 相对参考节点的位移/旋转/距离/角差(通过一次轴-角旋转完成坐标系重合所需的旋转角度)
生成大量的检测参数,为连线参数/反应管理器提供合适的控制位点

30.MaxScript脚本 实现对齐父物体
---30.1 通过脚本添加对齐按键
首先在场景中创建的虚拟物体作为父物体,和一个子物体

我们为子物体添加一个属性承载器,并运行下面的脚本(.ms)

(这知乎代码块怎么没配MaxScript的语法高亮...姑且选了C++)
对齐父物体=attributes 对齐
rollout Align "对齐控制"
width:162 height:47
button btn1 "复位" pos:[36,15] width:80 height:20
label lbl1 " " pos:[6,30] width:3 height:13
on btn1 pressed do --设置点击按钮的事件
try(
--对齐父物体缩放/旋转/位置
$.scale=$.parent.scale;
$.rotation=$.parent.rotation;
$.position=$.parent.position;
redrawViews(); --刷新视图
catch(messagebox("Error!!对象没有父物体"));
custAttributes.add $.modifiers[1] 对齐父物体 --在栈顶修改器上创建按钮


---30.2 MaxScript脚本编程基础
应该后面会专门去学的,届时也会专门开文章来记录
挖坑...
这里我并不打算细讲有关:编程语法,变量,对象,事件,函数/方法,这些东西
因为...其实我本来就是个程序员(最开始我也是先学的编程来着)
这里只打算以一个程序员的视角,解释下上面的代码怎么来的,MaxScript这个工具大概怎么用

如果你是从建模动画学起的,偏美术的方向,关于MaxScript,建议好好找一套面向0基础的教程学习(B站搜了下好像有几套不错的)
首先在Max中我们可以在上方的菜单栏找到脚本这一项卷展菜单
并通过运行,找到之前保存好的 .ms 脚本文件

当我们需要创建新的脚本时,脚本---新建脚本
打开这样的一个代码编辑器

其中的工具---编辑卷展栏


我们可以创建一个Button按钮控件,并调整它的尺寸,通过上方的布局菜单调整控件的位置

选中控件,右侧可调整它的属性
其中的caption 标签属性,就是显示在Button上的Text

事件栏可以选择该控件需要被启用的交互事件

而卷展栏的caption标签对应

我们设置好Button和卷展栏的标签,启用Button的点击事件
点击保存,我们在UI编辑器中的创建的UI就会以代码的形式,出现在脚本编辑器内
MaxScript中
亦是面向对象的编码形式
代码块使用 () 圆括号引启
字符串使用 "" 双引号引启

我们在事件函数中添加对齐到父物体的代码
$.scale=$.parent.scale;
$.rotation=$.parent.rotation;
$.position=$.parent.position;
这里的 $ (英文 Shift+3) 是获取到当前选中对象的指针/引用
访问使用 . (英文句号)
scale/rotation/position 获取到对象在世界坐标下的缩放/旋转/位置
$.parent 获取到对象的父物体
当然可能选定对象并没有父物体,因此我们可以使用经典的 try catch 语句来捕获异常
这里异常比较单一,不用throw id 直接无条件catch即可
捕获异常后,我们使用 messagebox("消息内容") 创建一个经典消息对话框
使用redrawViews(); 函数,在我们完成对齐后立即刷新视图
try (
$.scale=$.parent.scale;
$.rotation=$.parent.rotation;
$.position=$.parent.position;
redrawViews(); --刷新视图
) catch(messagebox("Error!!对象没有父物体"));
为了让这个控件被添加到栈顶的修改器上
我们还需将代码归入一个attributes中
并使用 custAttributes.add $.modifiers[1] 引用attributes名称
为选定对象的栈顶修改器添加这个控件
参考代码:
添加测试按钮 = attributes 测试
rollout 测试卷展 "测试卷展" width:162 height:109
button 'btn2' "测试按钮" pos:[20,20] width:125 height:55 align:#left
on btn2 pressed do
try (
$.scale=$.parent.scale;
$.rotation=$.parent.rotation;
$.position=$.parent.position;
redrawViews(); --刷新视图
) catch(messagebox("Error!!对象没有父物体"));