4 个版本 (2 个重大更新)
0.8.0 | 2023年4月20日 |
---|---|
0.7.0 | 2023年4月17日 |
0.6.1 | 2019年9月20日 |
0.6.0 | 2019年9月20日 |
#1560 在 解析器实现
每月41次 下载
用于 bevy_blender
1.5MB
2K SLoC
Blend - 一个用于解析 Blender 的 .blend 文件的 crate
示例
use blend::Blend;
/// Prints the name and position of every object
fn main() {
let blend = Blend::from_path("examples/blend_files/3_5.blend").expect("error loading blend file");
for obj in blend.instances_with_code(*b"OB") {
let loc = obj.get_f32_vec("loc");
let name = obj.get("id").get_string("name");
println!("\"{}\" at {:?}", name, loc);
}
}
Blend 文件
为了充分利用此 crate,了解 .blend 文件的工作原理很有帮助。简而言之:Blender 通过将内存内容写入磁盘来创建保存文件,这意味着 .blend 文件是一系列类似于 C 语言的结构体,可以包含基本类型、数组、指针和其他结构体。以下是在 Blender 内存中以 Rust 类似语法定义摄像机的方式:
struct Camera {
id: ID {
name: [u8; 66] = "CACamera"
//[... other ommited properties ...]
},
adt: *AnimData = null,
type: u8 = 0,
dtx: u8 = 0,
flag: f32 = 4,
passepartalpha: f32 = 0.5,
clipsta: f32 = 0.1,
clipend: f32 = 100,
lens: f32 = 50,
ortho_scale: f32 = 7.3142858,
drawsize: f32 = 1,
sensor_x: f32 = 36,
sensor_y: f32 = 24,
shiftx: f32 = 0,
shifty: f32 = 0,
YF_dofdist: f32 = 0,
ipo: *Ipo = null,
dof_ob: *Object = null,
//[... other ommited properties ...]
}
其他概念在文档中解释,这些概念对于理解相关方法是必要的。
了解更多
关于 .blend 文件的文档相对较少,但最常见的信息来源是 Blend 的奥秘,建议从官方 Blender 仓库获取,并应用以下 补丁。
此 crate
此 crate 提供了解析和运行这些结构的解析器和运行时,这意味着您可以像访问内存中的简单对象一样访问它们。目标是简化接口:.blend 文件至少有三种定义事物的列表的方法,此 crate 提供了统一所有这些的方法。
这个 crate 是惰性的。虽然需要前期工作来查找结构和它们的类型定义,但直到实际访问它们之前,不会解析这些块的二进制数据。
使用技巧
知道从文件中读取什么可能有些挑战。一个简单的 .blend 文件就有超过 400 个“块”,每个块可以代表一个或多个结构体。如果您不确定要访问什么,可以使用 print_blend
示例。您可以使用它将整个 .blend 文件保存为文本到磁盘。如果您知道您需要什么,也可以打印单个结构体实例。
需要注意的是,在打印 Instance
时,如果它们的属性之一是列表,则除了第一个元素以外的元素将被跳过。如果您需要查看整个列表,只需访问它并逐个打印其成员。
为 Instance
实现的 Display
略显粗糙,因此较大的 .blend 文件可能会导致栈溢出,但可以通过在发布模式下运行代码来修复。如果您发现任何破坏格式的行为,请提出一个问题。
支持版本
由于 .blend 文件是自描述的,因此应该可以解析来自每个 Blender 版本的文件(已在 2.72 到 2.80 版本的文件上进行了测试)。尽管如此,有些事情被认为是始终成立的:例如,类型 int
总是被认为是与 Rust 的 i32
等效,但文件规范中并没有保证这一点。然而,几乎没有理由相信 Blender 会更改其原始类型。
警告
这个crate旨在与受信任的 .blend 文件一起使用,虽然预期从读取恶意文件不会出现不安全或未定义的行为,但可能可以构建一个 .blend 文件,在运行时导致恐慌。
由于规范的一些怪癖,库的某些部分在允许的转换方面略显宽松。例如:任何具有正确大小的块都可以解析为浮点数列表。为什么?因为有些块实际上是浮点数数组,但我们没有足够的信息来确保这一点。这意味着用户需要决定在访问数据时想要什么。
这个crate还稍微有点恐慌。虽然应该始终可以检查您正在访问的字段是否存在、是否有效、是否包含特定类型的数据等,但您应该事先知道您正在访问什么,因此几乎所有函数在错误输入时都不会返回 Result::Err
或 Option::None
。
最后,这被开发出来是为了方便游戏开发,但也应该适用于任何用例。
限制
此crate不支持压缩的 .blend 文件,也不支持写入 .blend 文件。要解决第一个问题,可以在将数据传递给 Blend::from_data
之前解压缩文件,请参阅 print_blend
示例。第二个问题由于代码的组织方式,难度略高,但欢迎提交 PR!
GLOB
、REND
和 TEST
块尚未完全支持。代码的某些部分已支持这些块,但尚未完全实现,因为我还没有找到使用这些块的场景。如果您想要支持这些,请提出一个问题!