惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
Arctic Wolf
T
The Blog of Author Tim Ferriss
月光博客
月光博客
Recent Announcements
Recent Announcements
V
V2EX
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 三生石上(FineUI控件)
P
Proofpoint News Feed
The Register - Security
The Register - Security
博客园 - 叶小钗
博客园 - Franky
The Cloudflare Blog
雷峰网
雷峰网
罗磊的独立博客
M
MIT News - Artificial intelligence
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
爱范儿
爱范儿
博客园 - 司徒正美
Recorded Future
Recorded Future
酷 壳 – CoolShell
酷 壳 – CoolShell
Google DeepMind News
Google DeepMind News
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
F
Full Disclosure
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog
大猫的无限游戏
大猫的无限游戏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
腾讯CDC
WordPress大学
WordPress大学
小众软件
小众软件
K
Kaspersky official blog
Attack and Defense Labs
Attack and Defense Labs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Forbes - Security
Forbes - Security
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
The Last Watchdog
The Last Watchdog
N
News and Events Feed by Topic
B
Blog RSS Feed
S
Security @ Cisco Blogs
美团技术团队
量子位
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cloudbric
Cloudbric
Hacker News - Newest:
Hacker News - Newest: "LLM"

智伤帝的个人博客

Maya 拍屏方案汇总 C++ 道法器术 C++ 基础入门 Maya RBF 算法应用 Maya 顶点色单通道笔刷 Maya CurveBrush 笔刷开发 Unreal C++ 工具开发最小实践 Maya C++ pyd 模块开发 Unreal C++ VScode 配置 Maya C++ mll hot reload 研究 Maya CMake 构建 C++ 插件编译环境 Unreal Python 导出 MetaHuman 控制器关键帧 TA 工具人知乎分享 Python 代码规范 Python - Import 机制 Python doit 库 Python dependencies 库 Python blinker 库 Python marshmallow 库
FBX 二进制数据解析
智伤帝 · 2022-11-06 · via 智伤帝的个人博客

前言

  最近遇到了一个比较难搞的需求,好不容易解决了,在这里记录一下。
  需求是这样的,公司有大佬在 motionbuilder 写了插件,利用 mobu API 做了一个自定义的节点并在里面通过 FBXStore API 存入了自定义数据。
  我需要将这些操作通过 Python FBXSDK 来完成这些数据的写入。
  主要原因是 motionbuilder 的稳定性不可靠,如果可以利用纯外部调用 FBXSDK 的形式解决问题,就不需要依赖 mobu 了。

  用 FBXSDK 来还原自定义节点操作都好说。
  主要蛋疼的地方在于需要解决 FBXStore API 调用背后怎么转换成二进制的问题。

motion builder C++ 插件编译

  在 motion builder 的安装路径有 OpenRealitySDK 文件夹,里面的 samples 有很多开发 mobu 的参考代码。
  其中比较具有代表性的脚本就是 OpenRealitySDK\samples\devices\devicecamera\ordevicecamera_device.cxx
  这个脚本就定义怎么将自定义数据存入 FBX 当中,并且利用 FbxRetrieve 方法将功能读取回来。

  我们可以把这个东西编译出来作为我们这次测试的内容。

  默认 motionbuilder 的 samples 里面提供了 sln 工程,可以直接用 VS 打开。

image

  打开之后需要将平台工具集升级到最新的 VS 版支持的工具集,默认是 2012 工具集太过古老了。
  改完之后本想着愉快地编译,然而这样会报错。

image

  这个问题只能归结为新的平台工具集已经去掉了支持,但是头文件依旧引入相应的文件,解决也很简单,将报错的那一行注释即可。

image

  编译完成会默认去到 bin\x64\plugins 的目录,这样只要重启 motion builder 就能加载到这个 dll 了。

image

  这样将这个图标拖拽到场景就可以创建一个 device.
  将这场景以 ascii 的格式保存。
  检查保存的 FBX 文件,可以看到 FBXStore 的写入逻辑,会将信息写入到节点的 MoBuAttrBlindData 属性上

image

  存储出来可以看到相应的信息。
  这里官方的插件将信息转成了 KString 所以里面的信息也是以 FBX ASCII 的形式存在。
  但如果将 FBX 存成 Binary 模式,然后再用 Python FBXSDK 来转存成 ASCII 的话,这些 FBXStore 的数据会转成 base64 的二进制数据。

image

  如果用 base64 解码,可以看到里面存储的二进制数据。

1
2
3
4
5
6
7
8
import base64

in_data = r"cBsAAAABAAAABQAAAAhDb21tVHlwZUkQAAAANAAAAAEAAAAFAAAAB1ZlcnNpb25JUQMAAGIAAAADAAAAGwAAAAZTZXJpYWxJAQAAAEkAlgAAUwwAAABTY2VuZQABTW9kZWycAAAABAAAACQAAAAJU2ltdWxhdG9yRAAAAAAAAPA/RAAAAAAAAPA/RAAAAAAAAAAARAAAAAAAAAAAwwAAAAIAAAATAAAAB05ldHdvcmtTCQAAADEyNy4wLjAuMUm5CwAA9gAAAAIAAAAaAAAADFNoYXJlZE1lbW9yeVMKAAAASE1DX1NITV9WMVMGAAAAMDAwMDAwFAEAAAEAAAAJAAAACFNldHRpbmdzRAAAAAAAAAAAMgEAAAEAAAAFAAAADFNhbXBsaW5nTW9kZUkAAAAAVAEAAAEAAAAFAAAAEEluc3RydW1lbnRBY3RpdmVJAQAAAG0BAAABAAAABQAAAAdWZXJzaW9uSVEDAACOAQAAAQAAAAUAAAAPTGVuc1RhYmxlTG9hZGVkSQAAAADbAQAABgAAAC4AAAASTWFudWFsTW9kZVNldHRpbmdzSQAAAABEBzDzdETpTEBEAAAAAACARkBJAAAAAEQAAAAAAAAAAEQAAAAAAAAAAP4BAAACAAAACgAAAAxJbnZlcnRWYWx1ZXNJAAAAAEkAAAAAHwIAAAEAAAAJAAAAC0FzcGVjdFJhdGlvRFVVVVVVVfU/QwIAAAEAAAAJAAAADlpvb21NdWx0aXBsaWVyRAAAAAAAAPA/aAIAAAEAAAAJAAAAD05vZGFsTXVsdGlwbGllckQAAAAAAABZQIgCAAABAAAABQAAAA5BbmdsZUluRGVncmVlc0kAAAAAywIAAAQAAAAkAAAAEkVuY29kZXJDYWxpYnJhdGlvbkQAAADgzxJjQUQAAADgzxJjwUQAAADgzxJjQUQAAADgzxJjwRsDAAAGAAAANgAAAA1TdHVkaW9PZmZzZXRzRAAAAAAAAAAARAAAAAAAAAAARAAAAAAAAAAARAAAAAAAAAAARAAAAAAAAAAARAAAAAAAAAAANAMAAAEAAAAFAAAAB1ZlcnNpb25JUQMAAE8DAAABAAAABQAAAAlTeW5jRGVsYXlJBAAAAAAAAAAAAAAAAAAAAAA="

output_path = r"G:\_TEMP\2022-11-1\test_device.bin"

with open(output_path,'wb')as wf:
wf.write(base64.b64decode(in_data))

image

  VScode 安装 Hex Editor 可以查看二进制数据。
  而我这边需要想办法用 Python 写入二进制数据,从而摆脱 motion builder 的依赖。

FBX 数据格式
RenderDoc Python 开发 FBX 导出工具

  之前写 renderdoc 导出 FBX 插件的时候,使用的时 FBX ASCII 格式,通过将数据写入到 FBX ASCII 对应的位置。FBX 就可以被读取到。
  当时踩了的坑也可以从中窥探到 FBX 存储的结构。

Python 二进制处理
Maya 输出顶点动画到引擎

  通过上面的文章,可以了解到 Python 写入二进制数据可以依赖内置的 struct 包。
  写入数据需要了解 C++ 的数据类型的长度,按照长度和数据的写入顺序就可以用 Python 还原二进制数据。


image

  通过 C++ 源码可以知道写入了这些数据

image

  通过源码和二进制的对比,可以窥探到其中意思规则
  比如利用 C++ 可以知道 Version 数据写入的时 0x0351 的数据

1
2
3
>>> import struct
>>> struct.pack("i",0x0351)
b'Q\x03\x00\x00'

  使用 python 将 0x0351 转换为整形会返回 Q\x03\x00\x00

image

  正好和 二进制 数据是对应的,中间的 I 则表示是 Int 整形数据。
  这个规律我经过我对二进制不少数据的解读总结出来的。但还有一些数据的含义是未知的。

  后来在网上搜索了一下这个二进制规则,发现 Blender 官方提供了 FBX 二进制的解读。 链接
  这个文章有非常完整的 FBX 二进制规则。
  通过这个规则可以解读出整个 FBX 二进制数据的存储方式。

  比如开头的 CommmType 前面有14位数据,除去开头第一个 0x70 数据,后面的数据分别对应 EndOffset NumProperties PropertyListLen NameLen
  完全和 Node Record Format 对应。

  理解了数据的存储方式之后,就可以很顺利用 Python 写入同样的二进制数据。

FBXSDK 写入问题

  只是我处理的时候发现 Python FBXSDK 无法直接写入 blob 二进制数据。
  原因是 FbxProperty.Set 不接受 bytes 数据。

image

  这个部分是用 C++ 模板实现的,可能这个功能并没有映射给 Python FBXSDK,导致功能缺失。(也只能说这个功能少用得很)
  为了保证数据的长度,我的处理方式是用 FbxString 写入相同长度的 字符串桩 ,比如一堆 * 的字符串。
  保存出去的 FBX 二进制文件再度用 Python 读取,然后将 字符串桩 替换为真实的 二进制 数据。

总结

  这次深度挖掘了 FBX 二进制格式,对 FBX 的文件处理更加得心应手😄~

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 智伤帝的个人博客

打赏

  • 微信

    微信

  • 支付宝

    支付宝