#blender #run-time #name #version

blend

Blender 的 .blend 文件解析器和运行时

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

MIT 许可协议

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::ErrOption::None

最后,这被开发出来是为了方便游戏开发,但也应该适用于任何用例。

限制

此crate不支持压缩的 .blend 文件,也不支持写入 .blend 文件。要解决第一个问题,可以在将数据传递给 Blend::from_data 之前解压缩文件,请参阅 print_blend 示例。第二个问题由于代码的组织方式,难度略高,但欢迎提交 PR!

GLOBRENDTEST 块尚未完全支持。代码的某些部分已支持这些块,但尚未完全实现,因为我还没有找到使用这些块的场景。如果您想要支持这些,请提出一个问题!

依赖项