Wings 3D/用户手册/Wings 文件格式
查看 http://wings3d.com/ 获取用 Erlang 编写的开源建模器。
需要查看的重要源文件:.../src/wings.hrl 和 .../src/wings_ff_wings.erl。
另一个参考是 用 Perl 实现的导出器,它已过时。
请注意,Wings 目前正在开发中,包括文件格式的更改,因此建议暂停此文档的工作,直到文件格式再次稳定。
一个 *.wings 文件包含 3 个主要部分
- 1. 头部
- 头部长度为 15 字节,本质上是 ASCII,由人类可读的字符串 "#!WINGS-1.0" 以及十六进制字节 0x0D、0x0A、0x1A、0x04 组成,即 "\r\n^Z^D",即 CR、LF、SUB 和 EOT(Ctrl-Z 在 Windows 中是“输入结束”字符,Ctrl-D 在 UNIX 中也是如此)。
- 2. 数据长度
- 一个 4 字节无符号整数,以大端格式存储整个文件的大小。此值应与磁盘上的文件大小匹配,否则文件丢失数据。
- 3. 数据
- 文件主体,以 Erlang 的 外部项格式 存储,如第 8.1 节所示;具体来说,它是一个Zlib 压缩的项,由前两个字节 131、80 指示。接下来的 4 个字节是一个无符号整数,表示未压缩数据的长度。文件的其余部分是实际的压缩数据/项。
- 当使用 Erlang 或具有完整接口的语言处理 *.wings 文件时(在 Erlang 分发版中存在一个 C 接口 和一个 Java 接口,还有 Python 接口 在其他地方),只需将整个数据部分馈送到相应的函数/方法即可。
- 但是,当在其他语言中处理 *.wings 文件时,这 6 个字节可能被视为额外的头部信息,其余部分必须解压缩,然后进一步处理以重建项的嵌套结构。
为了了解简单的 Wings 模型在 Erlang 语法中如何呈现(在解压缩后;手动缩进和添加注释/链接以强调结构并提供帮助)
{ wings, 2, % The Topmost Tuple { [ % Shapes { object, "tetrahedron1", { winged, [ [ { color_rt, <<0,0,0,0,0,0,0,0,63,128,0,0>> }, { color_lt, <<63,128,0,0,0,0,0,0,0,0,0,0>> }, { edge, 0,1,2,0,4,2,1,3 } ], [ { color_rt, <<0,0,0,0,63,128,0,0,0,0,0,0>> }, { color_lt, <<0,0,0,0,0,0,0,0,63,128,0,0>> }, { edge, 0,2,0,3,3,0,2,5 } ], [ { color_rt, <<63,128,0,0,0,0,0,0,0,0,0,0>> }, { color_lt, <<0,0,0,0,63,128,0,0,0,0,0,0>> }, { edge, 0,3,3,2,5,1,0,4 } ], [ { color_rt, <<0,0,0,0,0,0,0,0,63,128,0,0>> }, { edge, 1,2,1,0,5,4,0,1 } ], [ { color_lt, <<63,128,0,0,0,0,0,0,0,0,0,...>> }, { edge, 1,3,2,1,2,0,3,5 } ], [ { color_rt, <<0,0,0,0,63,128,0,0,0,0,...>> }, { edge, 2,3,1,3,4,3,1,2 } ] ], [ [], [], [], [] ], [ [ <<0,0,0,0,0,0,0,0,63,241,107,40,245,93,114,...>> ], [ <<0,0,0,0,0,0,0,0,191,225,107,40,245,93,...>> ], [ <<191,240,0,0,0,0,0,0,191,225,107,40,245,...>> ], [ <<63,240,0,0,0,0,0,0,191,225,107,40,...>> ] ], [] }, [ { plugin_states, [] }, { mode, vertex} ] } ], % Shapes end [ % Materials { default, [ { maps, [] }, { opengl, [ { ambient, { 1.0,1.0,1.0,1.0 } }, { diffuse, { 1.0,1.0,1.0,1.0 } }, { emission, { 0.0,0.0,0.0,0.0 } }, { shininess, 1.0 }, { specular, { 1.0,1.0,1.0,1.0 } } ] } ] } ], % Materials end [ % Props { scene_prefs, [] }, { plugin_states, [] } ] % Props end } }
您将发现两个基本的复合 Erlang 数据类型元组(用大括号表示,如 {something,someother,somemore})和列表(用方括号表示 [elem1,elem2,...], 还有原子(在本示例中不带引号的所有小写字符串,例如 wings、edge、plugin_states)、一个字符串("tetrahedron1")、一些二进制数据(用双尖括号表示,尖括号之间是字节值,如 <<0,1,2,3>>)以及一些整数和浮点数。您会看到,这些都是高度嵌套的(例如,一个列表包含列表,列表包含元组)。
当您无法使用现有的接口(或想要编写新的接口)时,您需要了解 Erlang 项的外部格式,该格式在 这里有很好的说明。请注意,您需要处理字节流并以某种方式自行重建嵌套结构。作为参考,Erlang/OTP 源代码有一个名为“jinterface”的模块,它提供了一组类来实现 Java 中的读取此格式的功能。
要处理 *.wings 文件,您至少应该准备处理以下内容
- 8.4 SMALL_INTEGER_EXT
- 8.5 INTEGER_EXT
- 8.6 FLOAT_EXT
- 8.7 ATOM_EXT
- 8.11 SMALL_TUPLE_EXT
- 8.13 NIL_EXT
- 8.14 STRING_EXT
- 8.15 LIST_EXT
- 8.16 BINARY_EXT
扩展后的最顶层数据结构是一个带标签的元组,包含 3 个元素
符合规范的加载器应该检查前 2 个元素的存在,并验证第 3 个元素是一个 3 元组。
形状部分包含一个列表,每个列表包含一个四元组(4 元组),用于描述每个独立的对象。对象四元组具有以下格式
- 标签原子 'object'。
- 一个包含对象名称的字符串,例如 "tetrahedron1"
- 另一个包含对象实际数据的四元组,由原子 'winged'(如带翼边数据结构)标记。此元组将在下一节中介绍。
- 一个列表,包含有关此对象的插件状态和选择模式的信息。通常,这在导入器/导出器中不会使用。
Wings3D 使用 带翼边数据结构,使其在涉及邻域操作(例如边循环)的所有操作中速度都非常快。*.wings 文件格式直接存储这些带翼边数据结构,因此大部分数据存储在边本身中,而不是在表中(如 *.3ds 或 *.X 文件格式)。
带标签的元组 'winged' 包含定义对象几何形状所需的所有数据。它采用以下格式
- 原子 'winged'(标签)
- 一个列表,包含一系列列表,每个列表定义一条边。
- 一个列表,包含一系列列表,每个列表定义面与材质之间的映射关系。
- 一个列表,包含一系列列表,每个列表定义一个顶点。
- 一个列表,目前用途未知 - 在示例中为 nil。
在第一个列表(边数据)中,找到一系列列表,每个列表定义一条边。在每个边的列表中,可能会出现以下元组。请注意,一个元组在每个边的列表中最多只能出现一次,否则 Wings 将无法加载它,并且它们的出现顺序无关紧要。
- 带标签的 9 元组 'edge':定义带翼边数据结构,必须存在。格式如下
- 原子 'edge'(标签)
- 起始顶点
- 结束顶点
- 左侧面
- 右侧面
- 左侧前驱
- 左侧后继
- 右侧前驱
- 右侧后继
- 带标签的 2 元组 'color_rt':定义右侧顶点边颜色。格式如下
- 原子 'color_rt'(标签)
- 12 字节二进制块,表示 RGB 表示法中的颜色值。每个分量都存储为 32 位单精度浮点数。
- 带标签的 2 元组 'color_lt':定义左侧顶点边颜色。格式如下
- 原子 'color_lt'(标签)
- 12 字节二进制块,表示 RGB 表示法中的颜色值。每个分量都存储为 32 位单精度浮点数。
- 带标签的 2 元组 'uv_rt':定义右侧顶点 UV 坐标。格式如下
- 原子 'uv_rt'(标签)
- 16 字节二进制块,表示 UV 坐标,每个数字使用 8 字节浮点数。
- 带标签的 2 元组 'uv_lt':定义左侧顶点 UV 坐标。格式如下
- 原子 'uv_lt'(标签)
- 16 字节二进制块,表示 UV 坐标,每个数字使用 8 字节浮点数。
从 Wings 1.1.15 开始,此列表中可能包含 UV 和顶点颜色。之前,只能找到其中之一。
在第二个列表(材质数据)中,为由之前读取的带翼边结构定义的每个面提供一个条目。
- 如果面没有材质(默认材质),则列表中的项为 nil。
- 如果面有材质,则条目是一个列表,其中包含一个带标签的 2 元组,格式如下
- 原子 'material'(标签)
- 材质名称的原子,例如 'tetrahedron1_auv'。这是对材质部分的引用。
示例材质结构
[ [ "Cylinder1_auv", [ [ "maps", [ [ "diffuse", 3 ] ] ], [ "opengl", [ [ "ambient", [ 1,1,1,1 ] ], [ "diffuse", [ 1,1,1,1 ] ], [ "emission", [ 0,0,0,0 ] ], [ "shininess", 1 ], [ "specular", [ 1,1,1,1 ] ], [ "vertex_colors", "ignore" ] ] ] ] ], [ "default", [ [ "maps" ], [ "opengl", [ [ "ambient", [ 0.789853807692308,0.813333333333333,0.694044444444444,1 ] ], [ "diffuse", [ 0.789853807692308,0.813333333333333,0.694044444444444,1 ] ], [ "emission", [ 0,0,0,1 ] ], [ "shininess", 0 ], [ "specular", [ 0,0,0,1 ] ], [ "vertex_colors", "set" ] ] ] ] ] ]
示例道具数据
[ [ "scene_prefs" ], [ "plugin_states", [ [ "wings_shape", [ "no_folder", [ [ "no_folder", [ "open", [ 1, [ 1,"nil","nil" ] ] ] ] ] ] ] ] ], [ "current_view", 0 ], [ "views", [ [ "view", [ [ "name", "current_view" ], [ "aim", [ 0,0,0 ] ], [ "distance_to_aim", 3.14266478310898 ], [ "azimuth", -284.25 ], [ "elevation", 78.5 ], [ "tracking", [ 0,0 ] ], [ "fov", 45 ], [ "hither", 0.1 ], [ "yon", 10000 ] ] ] ] ], [ "images", [ [ 3, [ [ "name", "auvBG" ], [ "width", 256 ], [ "height", 256 ], [ "samples_per_pixel", 3 ], [ "mask_size", 0 ], [ "pixels", /* BinaryNode of 196608 bytes. */ ] ] ] ] ] ]