vmdpython命令_【MMD】⽤python解析VMD格式读取
前⾔
MikuMikuDance(简称MMD)是⼀款动画软件,早期视为Vocaload⾓⾊制作动画的软件,现在还经常能在B站等视频⽹站,或⼀些动画⽹站(某I站)看到MMD作品。
我在⾼中也简单学过操作这款软件以及PE、⽔杉等软件,学会了简单k帧、套动作、调渲染、加后期、压缩等技术,这与我学习计算机专业有很⼤的关系(虽然学校学的和这个⼋竿⼦打不着,或许我应该学美术去),现在已经分不清很多东西了,封⾯静画就是杂七杂⼋过⽓MME⼀锅扔的成果,得益于G渲的强⼤,还能看出⼀点效果。
现在我想学⼀些3D的开发,包括⽤程序读取模型、动作等,很快我就想到之前⽤过的MMD。
⼀些3D姿势估计(3D pose estimate)或许能得到⾻骼位置以及PAF(⾻骼间关系),但我需要知道3D动画是如何储存动作数据的,才能想到怎样将姿势估计得到的数据转化为动作数据。
因此我了⼀些资料解析MMD的动作数据VMD(Vocaload Mation Data)⽂件,并写下这篇记录。
我的参考⽂献:
python怎么读取文件中的数据MMD中的VMD⽂件格式详解国内博客,解释VMD格式并⽤Java读取
VMD file formatMMD Wiki
本⽂会⽤python解析vmd⽂件,并纠正上述⽂章的⼀点错误。
根据MMD的规矩,上借物表:
名称
来源
MikuMikuDanceE_v803
圝龙⿓龖龘圝
⼋重樱
神帝宇
封⾯静画:
名称
类别\来源
LightBloom
背光
AutoLuminousBasic
⾃发光特效
HgSAO
阴影
SoftLightSB
柔化
SvSSAO
阴影
景深
dGreenerShader
G渲
Tokyo Stage
场景
⼀、格式说明
⾸先,vmd⽂件本⾝是⼀个⼆进制⽂件,⾥⾯装着类型不同的数据:uint8、uint32_t、float,甚⾄还有不同编码的字符串,因此我们需要⼆进制流读⼊这个⽂件。
vmd格式很像计算机⽹络的协议格式,某某位是什么含义,区别是,vmd⽂件的长度理论上是⽆限的,让我们来看看。
vmd的⼤致格式如下:
头部
关键帧数量
关键帧
头部
最开始的就是头部(header),看到这就有⼗分强烈的既视感:
类型
长度
含义
byte
30
版本信息
byte
10 or 20
模型名称
其中,版本信息(VersionInformation)长度为30,是ascii编码的字符串,翻译过来有两种,⼀为“Vocaloid Motion Data file”,⼆
为“Vocaloid Motion Data 0002”,长度不⾜30后⽤\0(或者说b'\x00')填充。这是由于vmd版本有两种,⼤概是为了解决模型名称长度不⾜,因此后续只影响模型名称的占⽤长度。
模型名称(ModelName),是动作数据保存时⽤的模型的模型名,通过这个我们可以获取到那个名称,我们知道,⼀个动作数据想要运作起来,只要套⽤模型的⾻骼名称是标准的模板就可以,因此我想象不出这个名称有何⽤处,或许某些模型带有特殊⾻骼,例如翅膀之类的,这样能⽅便回溯?模型名称的长度根据版本⽽决定,version1为10,version长度为20。编码原⽂写的是shift-JIS,是⽇语编码,这样想没错,然⽽我试验后发现并⾮如此,例如经常改模型的⼤神神帝宇的模型,他的模型名称⽤shift-JIS为乱码,⽤gb2312竟然能正常读出来;还有机动⽜⾁⼤神的模型,他的模型名称⽤gb2312⽆法解码,⽤shift-JIS解码竟然是正常的简体中⽂怎么做到的?
⾻骼关键帧(BoneKeyFrame)
⾻骼关键帧,分为两部分:⾻骼关键帧数、⾻骼关键帧记录:
类型
长度
uint32_t
4
⾻骼关键帧数量 BoneKeyFrameNumber 类型
长度
含义
byte
15
⾻骼名称 BoneName
uint32_t
4
关键帧时间 FrameTime
float*3
12
x,y,z空间坐标
float*4
16
旋转四元数x,y,z,w
uint8_t * 16 or uint32 * 4
16
补间曲线x的坐标 XCurve
uint8_t * 16 or uint32 * 4
16
补间曲线y的坐标 YCurve
uint8_t * 16 or uint32 * 4
16
补间曲线z的坐标 ZCurve
uint8_t * 16 or uint32 * 4
16
补间曲线旋转的坐标 RCurve
byte
111
合计
为何要分开写呢?因为⾻骼关键帧数量只需要⼀个就够了,⽽后⾯⾻骼关键帧记录的数量会和前⾯的⾻骼关键帧数量保持⼀致,最后⼤概是这种效果:
我们可以查⼀下,每个⾻骼关键帧的数量为111字节。
旋转坐标
⼀开始还没发现,旋转坐标竟然有四个,分别为x, y, z, w,急的我去MMD⾥查看⼀下,发现和我印象中没有什么差别
都是[-180, 180]的⾓度值,我⽤程序跑的时候,这四个值完全看不懂;幸好在英⽂⽹站上到这个表⽰⽅法:四元数。四元数是⽤四个值
表⽰旋转的⽅法
其中
都是虚数,我上⽹了⼀堆资料,并且得到了四元数转化欧拉⾓的公式
得到的是⾓度制,我们通过⾓度制转弧度制的公式即可算出和MMD中等同的⾓度表⽰。
补间曲线
为何补间曲线的类型不确定呢?上⾯csdn博客的教程说“uint8_t那⾥有冗余,每四个只读第⼀个就⾏”。说的没有问题,⾸先我们要清楚这个补间曲线坐标的含义。
我们打开MMD,读⼊模型,随意改变⼀个⾻骼点,记录帧,就会发现左下⾓会出现补间曲线。
  补间曲线的⽤处,就是⾃动补齐当前记录帧与上⼀个记录帧之间动作的变化顺序,曲线斜率越⾼,动作变化越快,具体教程可以参照贴
吧中的教程,我们可以通过拖动红⾊的⼩x改变调节线,从⽽改变曲线
每⼀组⼩红x的坐标,就可以唯⼀确定⼀条补间曲线,因此,上⾯的补间曲线存储的就是⼩红x的坐标
,其中左下⾓调整线的⼩红x是看做点1,通过程序读取,我知道,⼩红x的坐标取值为[0~127]间的整
数,因此⽤1字节完全可以存下,可能是当时的设计错误,⽤了32位整数存,⾼24位完全浪费了,完全可以不⽤读取,因此我们可以直接读取32位⽆符号整数或读取8位⽆符
号整数,然后跳过24位。
如果曲线只有⼀个,那么为什么会有四个补间曲线呢?实际上不⽌⼀个,补间曲线框的右上⾓就有个下拉菜单可以选择,对于圆形⾻骼,没有相对位置变化,x, y, z补间曲线没有⽤,只有旋转速率可以调节,⽽⽅框⾻骼可以移动,因此x, y, z, 旋转补间曲线都有⽤处。
回过头来,再说⼀下补间曲线的坐标,在这⾥,是以左下⾓为原点,横纵⽅向[0, 127]的坐标轴
1.png
后⾯的格式与这个格式⼤同⼩异。
表情关键帧(MorphKeyFrame)
表情关键帧分为:表情关键帧数、表情关键帧记录:
类型
长度
含义
uint32_t
4
表情关键帧数量 MorphKeyFrameNumber
类型
长度
含义
byte
15
表情名称 MorphName
uint32_t
4
关键帧时间 FrameTime
float
4
程度 Weight
byte
23
合计
表情关键帧每个记录长度为23字节,其中程度(Weight)是取值为[0, 1]之间的浮点数,在MMD中的表现如下:镜头(CameraKeyFrame)
镜头关键帧分为:镜头关键帧数、镜头关键帧记录:
类型
长度
含义
uint32_t
4
镜头关键帧数量 CameraKeyFrameNumber
类型
长度
含义
uint32_t
4
关键帧时间 FrameTime
float
4
距离 Distance
float*3
12
x,y,z空间坐标

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。