HMMO 构建工具

在Hmmsim中制作动画模型


编程: Nemo (zbx1425)
转载请注明作者及本页链接

本程序能干什么?

在Hmmsim2游戏中只有内置的HMMO格式支持动画模型。由于该格式Jeminie并未公布,制作Hmmsim中可开门列车在很长一段时间内只能通过贴图修改和模型叠加等不仅侵权而且复杂的方式实现。
本人研究了HMMO文件的格式与原理,并制作了此工具。它可以将BVE的CSV模型文件构建为HMMO,并且施加动画效果,使得自定义模型的开关门列车成为可能。

下载 v1.5

本工具之发布已得到Hmmsim开发者Jeminie本人认可。以下为邮件原文 (2020-5-9 00:24 CST):

You are the first person to completely disassemble the Hmmo format!
I configured the Hmmo format as binary, because even though the format structure is simple, I wanted the model not to be extracted.
So I hope you haven't posted a tool to convert Hmmo to Csv.

However, tools to create Hmmo are always welcome.
1. KeyFrame consists of translation XYZ, rotating XYZ, and scale XYZ.
2. The door animation is fixed at 5 seconds. Even if the animation is long, it will play in 5 seconds.
3. Local means the Local matrix of the mesh. This is not necessary if there is only a translation, such as a door, but it is very meaningful when rotation is required.
4. Unfortunately, the only mesh name in which animation works on Hmmsim 2 is that.
Regards.

单个模型使用说明

打开本工具后会显示文件选择对话框,直接选择要转换的模型即可。可同时选择多个文件。
由于只有单文件,不能实现动画效果。
应 Jeminie 本人要求,HMMO-CSV转换功能已被禁用。

在 CSV-HMMO 的转换过程中,BlendModeWrapMode等数据由于HMMO不支持将丢失。

如需使用LightMap光照贴图,请将图片命名为使用的日间材质名后添加"LM" (blahblah.bmp -> blahblah_LM.bmp),构建工具将自动识别加载。将使用相同UV。

多模型/动画使用说明

本构建工具使用.conf格式文件来向构建工具提供关于动画和多个模型的信息。其格式与OpenBVE的.Animated模型格式略显类似。
在一个 .conf 文件内写明要使用的模型和动画信息,转换时只需导入 .conf 文件即可自动读取所有模型并处理,无需提前逐个转换。

.csv.hmmo引用构建工具Converter输入.conf输出

.conf 构建工具配置文件 格式示例:


[Config]
Hack      = Legacy Extension

[Object]
States    = body.csv

[Object]
States    = doora1.csv
Position  = 1.5, 0, 0
Name      = DoorR
KeyTX     = 0 0.02
KeyTZ     = 0 EaseInOutCubic*8 0.6

[Object]
States    = doora2.csv
Position  = 1.5, 0, 0
Name      = DoorR
KeyTX     = 0 0.02
KeyTZ     = 0 EaseInOutCubic*8 -0.6
......
  1. [Config]

    CONF中可有一个或多个 [Config] 部分,指定其下 [Mesh] 转换时的选项。也可不设置。
    一般不需书写 [Config] 部分。但如果输出模型有问题,可尝试调整选项能否修复。

  2. Hack = [Legacy] [Extension] [Cylinder]

    有三个修复选项可供开启。建议如无问题就不要开启。如需开启多个,以空格分隔名称。
    最常见的问题是光照过暗。原因是使用同样的日间及夜间材质来使表面常亮的做法已不受OpenBVE官方支持,必须打开此选项才可启用。顺带一提,正确做法是使用SetEmissiveColor。

    • Legacy: 等同于 OpenBVE 菜单中的 "Enable hacks for buggy older content"。打开后其他两个选项才可生效。
    • Extension: 修复光照问题时忽略文件扩展名。如果打开Legacy没有修复光照问题,可以再试试这个。
    • Cylinder: 如果圆柱体显示不正确,可以打开。需要和Legacy一同使用。

  3. DontOptimize = [Object] [Material]

    有两个优化可以禁用。默认情况下优化全部开启。如需禁用多个,以空格分隔名称。
    如果模型或材质混乱,可能是优化时搞砸的缘故。如能确定问题是由优化引起(关闭优化后问题即消失),请联系开发人员。
    关闭优化将大幅降低游玩时的FPS。

    • Object: 不合并重复顶点,不删除未使用顶点。
    • Material: 不合并重复材质。

  4. [Mesh] 或 [Object]

    两种写法均可,可按喜好使用。以下称作 [Mesh]。
    CONF文件内有一个或多个 [Mesh] 部分。表示一个模型部分的开始。

  5. Model = 文件名States = 文件名

    两种写法均可,可按喜好使用。表示这个 [Mesh] 部分所使用的CSV模型。需使用相对路径。
    如需使用多个,可用逗号隔开,届时会将其一同叠加后使用。
    只支持CSV模型。ANIMATED请修改后并入CONF中,OBJ请先转换到CSV。

  6. Name = Mesh名称

    指定 [Mesh] 部分的名称。
    将其命名为 DoorLDoorR (区分大小写!) 将启用使模型跟随左/右侧车门开闭进行动画的功能。
    对于不需动画的部件,必须省略,否则无法获得性能优化。

  7. Position = X, Y, Z

    移动导入的模型在最终模型中的位置。三个逗号分隔的数字代表X, Y, Z方向上的位移。
    用法与 ANIMATED 中同名指令相同。如果无需可省略。

  8. Local = a11, a12, a13, a21, a22, a23, a31, a32, a33, a41, a42, a43

    本配置项毫无效果,省略即可。目前Jeminie仅仅预留了数据位置,尚未实现此功能。

    模型的局部变换矩阵 (Local Matrix)。十二个逗号分隔的数字,代表三维变换矩阵去除最右侧一列后的12个有效值。
    默认为 1,0,0,0,1,0,0,0,1,0,0,0,代表这个不作变换的矩阵:

    1

    0

    0

    0

    0

    1

    0

    0

    0

    0

    1

    0

    0

    0

    0

    1

  9. 关键帧动画设置

    HMMO中共有九个动画参数可供调整。以下九个对应的设置项用来配置关键帧动画:

    名称Key0Key1Key2Key3Key4Key5Key6Key7Key8
    别称KeyTXKeyTYKeyTZKeyRXKeyRYKeyRZKeySXKeySYKeySZ
    用途X位移Y位移Z位移//////

    虽然有九个参数可调整,但后六个是完全没有效果的。原因是Jeminie原本计划支持旋转和缩放动画功能,但最终没有制作。
    书写CONF时使用名称或别称均可识别。

    HMMO中的动画是以关键帧形式进行的。几个关键帧平分一个固定的动画总时间:5秒。
    关键帧设置项包括多个用空格分割的数字,每个数字表示一帧时的参数。

    示例: KeyTZ = 0 1

    这使得车门开启时匀速向前移动 1m。
    关闭时反之且同样匀速。

    示例: KeyTZ = 0 0 0.5 0.8 1

    车门在开门声音响起时先不运动,然后先快后慢地打开。
    关闭时反之,即立刻开始运动且先慢后快。

    同时,为了方便开发者无需手调关键帧就能做出缓动特效,构建工具内置了一组缓动函数可供插值。
    用法为 [函数名]*[插值帧数] 或 [插值帧数]*[函数名]。插值指令的前后必须是数字,然后将生成给定数量的在两端间缓动过渡的帧。
    具体可用的缓动函数可参见 https://easings.net/cn。名称均相同,直接复制使用即可。
    除此之外还有三个插值方法,分别为 Linear(线性), ConstBegin, ConstEnd(重复首尾值,可省字)

    示例: KeyTZ = 0 EaseInOutCubic*8 0.6

    蓝色: 该帧根据缓动函数自动算出
    立方缓动的数学式:

    f(x) = x^3 (x < 1/2)
    1/2 (2p-2)3 + 1 (x ≧ 1/2)

    移动 0.6m,先慢后快再慢,立方缓动效果。

    没必要纠结数学,上easing.net看哪个看起来舒服用着就行 :D

    值得注意的是,HMMO中九组帧数据是配对写入文件中的。也就是说,九组关键帧并不是独立播放的。
    如果一组的帧数少于其他组,将重复最后一帧以补齐数量。解释起来有些抽象,请看示例:

    示例: KeyTZ = 0 EaseInOutCubic*8 0.6
    KeyTX = 0 0.1

    如图,KeyTX只包含2帧,而KeyTZ包含10帧,因此KeyTX的最后一帧 (0.1) 被重复以使关键帧配套。

    示例: KeyTZ = 0 EaseInOutCubic*8 0.6
    KeyTX = 0 ConstBegin*8 0.1

    使用ConstBegin插值或重复手打的方式重复第一帧,来让第二帧移到动画末尾。

    相同数据重复的简便写法:

    直接写入 Duplicate 将复制上一个同类帧数据。例如:

    [Object]
    States = doora.csv
    Position = 0.01,0,5.2
    KeyTZ = 0 0 -0.5 -0.9 -0.9
    Name = DoorL
    
    [Object]
    States = doorb.csv
    Position = 0.01,0,-0.25
    KeyTZ = duplicate
    Name = DoorL

    复制的数据来源是最后一个给出了实际值的同类帧数据。因此可连续复制到多个Mesh。

提示

  1. 动画不能用在非列车物件上。否则毫无效果。
  2. 转换过程中构建工具有时会生成形如 lm_xxxxxx.autogen.bmp 的文件,请务必原样打包。

致谢

    本软件制作过程中使用了多个开源库,包括 OpenBVE 的 CSV解析器@yinyue200 移植的 Mozilla Universal Charset Detector,及 @Simwak 的 Confused。感谢Jeminie大佬在本程序制作期间耐心解释我不明确的HMMO相关机制。

Changelog