大家好啊,这里是号卧龙字孔明的诸葛不太亮。
最近群里好几个大佬在做mod时,或多或少遇到了要对chain.48文件进行修改,以添加新的骨骼组,或者将其他chain.48文件中的骨骼组合并到同一个文件中的这一流程。但有的人无从下手,所以想着是时候鸽篇教程出来了(
说是这么说,本来想录视频的,毕竟视频比贴子更直观,但考虑到我的硬件配置和电流麦,还是码字更合适(悲)。
好了该回归正题了,直接上正餐。(点击左侧目录即可观看后续内容)
注:关于chain.48文件,笔者也还没有完全搞懂所有的参数,所以我基本只会讲解我明白的,且大都是经常会涉及到的一些参数,如有大佬不吝赐教也乐意至极,当然有错也敬请指出。
本教程用到的工具:
1.十六进制编辑器;
2.REE_Chain.bt(用于010的chain文件模板)以及配套的添加数据脚本;
3.Blender。
当我们打开解包文件的模型路径时,常常会发现模型各部位有配套的chain.48文件,如下图:
而这些文件的主要作用就是决定物理骨骼的运动形态,说白了就是决定披风、裙子、头发、欧派等等的物理效果。(注:崛起本体为chain.35文件)
我们以水芸防具套装的头部为例,也就是pl604的helm部位,将f_hair604.chain.48这个文件拖入010编辑器中。
然后运行REE_Chain.bt模板,选择这个文件,模板结果就会很直观地显示在你的面前,如下图:
暂且将它们分为6个部分,接下来会分别对它们进行讲解。
【1.Chain Version (Change Version Here)】
Chain Version,翻译为链版本。
这一项的数据是文件头部的4个字节,代表chain文件的后缀版本,比如曙光的chain.48文件这里是48,而本体的chain.35文件这里就是35(其他re引擎游戏类似)。
你可以改变这里的数字以在不同的游戏或版本之间移植chain文件。
通常来讲,这一项无需变动。(当你修复本体mod时可以动,具体参考https://www.caimogu.cc/post/217627.html)
【3.struct ChainSettings】
ChainSettings,翻译为链设置。
是的你没看错,我要暂时跳过2项讲3项,因为2项Header部分涉及到后面3456项的内容,所以回头再讲2会更容易理解。
这一项展开层级后,可能会有几个子级项,可以随便点开一个看看样子:
这一项主要包含骨骼链的各种物理参数,图中的英文翻译后能看到如gravity(重力)、damping(阻尼,衰减)、spring(弹性)、friction(摩擦)、elasticity(弹性)、wind(风)、hardness(硬度)等等的参数。这里不便具体讲解各参数的效果,不如自己上手尝试修改来的直观。
而上图中Setting[0]子级项后面对应的那堆名字为xxx_chain_end的东西,则是该Setting子级项所包含的各条骨骼链(组)。即是说这些骨骼组的物理会按照Setting[0]的参数设置来运作,而另外一些骨骼组则是以Setting[1]或Setting[2]的参数来运作。这一点在后面讲解5项时还会提到。
【4.struct Collisions】
Collisions,翻译为碰撞。
这一项展开层级后,也可能会有几个子级项,依旧随便点开一个看看样子:
这一项主要是用来设定物理碰撞体的,如上图所示,Collision[2]的子级项后面跟了个“Spine_01<-->L_Arm_01”的字眼,它实际上是项内部的的两个NameHash参数(图中红框所圈)。
Spine_01是模型的胸膛骨骼,而L_Arm_01则是模型的左大臂骨骼,chain.48文件通过hash值来匹配这些模型的主体骨骼,如图中Spine_01骨骼的hash值为4190776307。而“Spine_01<-->L_Arm_01”则表示在这两个骨骼之间建立一个碰撞体,碰撞体的范围取决于下方的radius参数(lerp可能可以参考求生之路的lerp值?),形状取决于ChainCollisionShape shape这一参数。
设定碰撞体后,当物理骨骼在运动中碰到这些碰撞体时,会被碰撞体阻挡进一步运动,从而避免穿模的发生,而这么多Collisions的子级项就表示加了很多个碰撞体。
【5.struct ChainGroups】
ChainGroups,翻译为链组。
这一项展开层级后,又双叒会有几个子级项(麻了是吧),还是随便点开一个看看样子:
这一项主要决定各骨骼链(组)的骨骼节数和运动方向,以ChainGroup[0]项举例,首先映入眼帘的就是它后面跟着的back_hair_chain_end的字样。结合下方紧挨着的terminalNodename能看出,这个字样实际代表该骨骼链的尾端骨骼,也就是说ChainGroup子级项以尾端骨骼名作为区分。
这里要讲解几个经常需要改动的参数。
紧接着nodeTbl(只是偏移地址而已)的下一个参数settingID,如下图所示,可以看到这里是0,代表该骨骼链(组)所用的ChainSettings子级项是Setting[0],也就是在前文中提到过的,Setting[0]后面包含的那些骨骼链。
参数nodeCount,此处是5,代表该骨骼链一共有5节骨骼(包含尾端骨骼),即back_hair_chain_00~back_hair_chain_03+back_hair_chain_end,在下方的ChainNodeData子项也能看到这些骨骼。
在Blender中可以看到这个骨骼组的分布,实际为水芸后发的物理骨骼,从上至下依次为00~03,尾端骨骼为end。
参数windID,类似settingID,这里是0,代表该骨骼链所用的WindSetting子级项为WindSetting[0],这里涉及到第6大项,所以姑且知道它代表什么即可。
将此值改为-1应该是代表不受风力的影响(个人猜测)。
接着来到ChainNodeData子项,惯例点开第一项参观:
首先第一个参数Quaternion angleLimtiDirection实际是由四个子参数组成的。
它们代表四元数,展开后可以看到xyzw四个数值,这些数值会决定骨骼的运动方向和角度。至于四元数它到底是怎么个运作方式,笔者也没完全弄明白。想直观看到四元数方向的话,可以使用Blender的REE_Chain插件(类似世界的CTC插件)在Blender中实时调整。
参数angleLimitRad,可能代表骨骼的旋转限制弧度,数值0.78为弧度,转换为角度则为45度左右。
参数angleLimitDistance,可能代表骨骼的旋转距离限制,一般不用管,所以我也没测过效果(
参数angleLimitRestitution,可能代表骨骼的旋转恢复限制,紧接着的speed代表恢复停止速度。
参数collisionRadius,代表骨骼的碰撞半径,类似在ChainCollision大项中的radius参数。
参数collisionShape,代表骨骼的碰撞体形状,类似在ChainCollision大项中的shape参数。
最后需要知道的一点是,这里的ChainNodeData子项,即每一节骨骼的数据长度都是80个字节(十六进制为50h),后面讲解添加骨骼时还会提到。
【6.struct WindSetting Wind】
WindSetting,翻译为风力设置。
这一项顾名思义,是用来设置风力参数的。
第一个参数uint id,此处为0,即为ChainGroup大项中提到过的windID,两处都是0,所以会在下方的Joints中看到使用WindSetting[0]子级项的骨骼组名。
这一项看英文有一些阻尼阿,风力形式阿等等的参数,我还没搞明白这些参数的含义,所以待补充(
【2.struct ChainData Header】
ChainData Header,翻译为链数据头。
这一项主要决定后面那些项的数量和偏移地址。
带Tbl字眼的参数,代表后面各项的偏移地址。
如上图中groupTbl的值为1344(此处为十进制),在十六进制数据中显示为40 05(倒插),所以偏移地址为05 40。我们找到ChainGroup大项,它的偏移地址确为0540h。其他项同理。
带Count字眼的参数则代表后面各项子级项的数量,如下图中的settingCount数值为3,这个文件内确实也只有3个ChainSetting的子级项。
这一项中可能需要经常手动修改的值为windSettingTbl,涉及到添加骨骼,后面会再提到。
chain.48文件结构概述讲解至此结束。
在大体了解了chain.48文件的结构后,我们可以着手对它进行某些修改了。
我们在给模型做物理的时候,有时会想给一个部位添加很多个物理骨骼链,这必然也会同时涉及到将它们的数据合并到同一个chain.48文件中。
比如我想给水芸的头发添加一个艾露猫耳朵的模型,那也需要同时将ear_chain_end骨骼链合并到该部位,该怎么做呢。
【1.准备工作】
先找到水芸头发和艾露猫耳朵的模型id,分别为pl604和pl261,并同时读取它们的chain.48文件。
由于艾露猫耳朵的物理骨骼链只有2节,所以我们先在水芸头发的chain.48文件中找到一个2节的骨骼组(即nodeCount值为2)。这里的f_chain_end骨骼组就可以。
【2.添加新的骨骼组】
接下来先将光标移到最后一个骨骼组的位置。
然后需要使用REE_Chain模板配套的添加数据脚本之一——REE_Chain_AddChainGroup.1sc,对水芸头发的chain.48文件运行。
此时会弹出一个框,让你输入新的骨骼组名,我们就命名为ear_chain_end,与艾露猫耳朵相同。
第二个框让你输入要复制的骨骼组id,由于上面以f_chain_end骨骼组为模板,其id为1,所以此处输入1。
确定后,新的骨骼组就已经添加进来了。
但由于我们是复制的f_chain_end骨骼组,所以此处的ear_chain_end骨骼组的数据与其是完全相同的,还需要做些修改。
【3.复制粘贴ChainGroups数据】
接着切到艾露猫耳朵的chain.48文件,找到ear_chain_end骨骼组的2节数据,各80个字节共160个字节,将这160个字节的数据复制,粘贴到刚刚新添加的骨骼组的2节数据上,这样ear_chain_end骨骼组的数据就合并过来了。
【4.添加新的ChainSettings组】
合并骨骼组数据后,我们还需要进一步合并它们的Settings数据,因为Settings管理骨骼的各种物理参数,其中的数据若不同也会影响最终的物理效果。
先将光标移到最靠后的Setting组位置。
然后需要使用REE_Chain模板配套的添加数据脚本之二——REE_Chain_InsertStruct.1sc,仍对水芸头发的chain.48文件运行。
运行后它会自动插入一个新的Setting组,不过它的数据都是0,相当于空组。
【5.复制粘贴ChainSettings数据】
与第3步相同,我们需要切到艾露猫耳朵的chain.48文件,找到其Setting组(此处就1组),将其数据(共168个字节,十六进制为A8h)复制粘贴到刚刚新添加的Setting组内。这样ChainSettings大项的数据也合并进来了。
【6.修改settingID的值】
由于我们新添加的ear_chain_end骨骼组是以f_chain_end骨骼组为模板,所以它们的settingID也是相同的,都使用的是Setting[1]的物理数据,而我们刚添加的Setting[3]并没有派上用场。
此时只需要将settingID改为3即可,刷新后上翻到Setting[3],就可以看到ear_chain_end骨骼的名字已经出现在后面了。
这样它就使用Setting[3]的物理数据了。
到此,艾露猫耳朵的chain.48文件就算是完全合并进来了。之后再将它们模型内的骨骼合并到一起,就可以在游戏内生效了,不过这是模型方面的操作,本帖并不涉及。
我们以刚刚添加进来的ear_chain_end骨骼组为例,它共有2节,但有些时候光这2节骨骼并不能达到我们想要的物理效果,可能需要3节、4节甚至更多的骨骼。那这时候该怎么增加骨骼数呢?
上面也说过,骨骼组的ChainNodeData子项,每一节骨骼的数据长度都是80个字节(十六进制为50h)。
那么如果我想在ear_chain_00骨骼后多添加一节ear_chain_01骨骼,就可以分下面三步走。
【1.插入字节】
先在ear_chain_00骨骼数据的尾端(或者说ear_chain_end骨骼数据的头端)插入80个字节(十六进制为50h)。
添加后如下图所示:
【2.修改nodeCount的值】
由于我们新添加了一节骨骼,所以该骨骼组的nodeCount参数值也需要修改,此处+1即可。
【3.修改windSettingTbl的值】
由于我们新插入了80个字节,而在Chaingroups大项后的唯一大项是WindSetting,所以需要将Header大项中windSettingTbl参数值+80,也就是将windSetting大项的偏移地址后移80个字节。
做完上面3步后,刷新模板就可以看到,ear_chain_01骨骼已经被加进来了,但此视它的数据是空的,都是0,所以你可以根据自己的需求设置它内部的参数值,也可以复制其他的骨骼数据,粘贴到这50h的字节上。
比如我可以复制ear_chain_00的骨骼数据,粘贴上来,这样这两节的骨骼数据是完全相同的:
除此之外,加更多的骨骼,或者要减少骨骼,操作也都是一样的,只不过是数值的累加而已(80个字节乘以n)。
在VC的催更下,算是码完了这个帖子。
结尾依旧宣下群,若对mod安装和制作有任何疑问,可以加俺滴扣扣群640945651,群里面都是做mod的大佬,一个个说话超好听的,超喜欢在里面的。