WFSM格式规范文档_v2.0

WFS / FIRM ENGINE
WFSM 专属模型文件格式
完整技术规范文档
|
文档版本 |
v2.0 |
|
文件扩展名 |
.wfsm / .firmmdl / .wfspkg |
|
所属系统 |
WFS Engine / FIRM Platform |
|
密级 |
机密 · 仅限内部使用 |
|
创建日期 |
2025-03-19 |
|
最后修订 |
2026-03-19 |
目录
第一章文档概述—
1.1 编写目的—
1.2 适用范围—
1.3 相关参考文档—
第二章设计背景与目的—
2.1 为什么不使用通用格式—
2.2 格式设计目标—
2.2.1 完整性—
2.2.2 可编辑性—
2.2.3 可扩展性—
2.2.4 安全性—
2.2.5 高性能—
2.2.6 版本兼容—
2.3 格式命名与扩展名—
第三章文件基础结构—
3.1 文件整体布局—
3.2 各数据块说明—
3.2.1 HEADER — 文件头—
3.2.2 META — 元信息块—
3.2.3 OBJECTS — 对象列表块—
3.2.4 GEOMETRY — 几何数据块—
3.2.5 TOPOLOGY — 拓扑数据块(核心)—
3.2.6 MATERIALS — 材质数据块—
3.2.7 PARAMS — 参数化历史块—
3.2.8 EDITORSTATE — 编辑器状态块—
第四章加密与安全机制—
4.1 安全尾部结构—
4.2 完整性校验流程—
4.3 权限级别说明—
4.4 数据块加密—
第五章文件读取与写入流程—
5.1 文件读取流程—
5.1.1 阶段一:文件头验证—
5.1.2 阶段二:安全校验—
5.1.3 阶段三:块索引加载—
5.1.4 阶段四:按需解析块数据—
5.2 文件写入流程—
5.3 解析器错误码参考—
第六章版本兼容策略—
6.1 主版本(Major)变更规则—
6.2 次版本(Minor)变更规则—
6.3 兼容性矩阵—
第七章扩展区与未来规划—
7.1 扩展块机制—
7.2 已规划扩展模块—
附录 A术语表—
附录 B文档修订记录—
�
第一章文档概述
1.1 编写目的
本文档是 WFSM(WFS Model)专属模型文件格式的完整技术规范,面向 WFS Engine 及 FIRM Platform 的系统开发人员、工具链维护者和合规审计人员。
文档涵盖格式的设计动机、整体结构、各数据块字段定义、加密与签名机制、读取与写入流程,以及版本兼容策略,旨在作为解析器开发和格式演进的唯一权威参考。
1.2 适用范围
本规范适用于以下场景:
•WFS Editor 编辑器的模型保存与载入模块
•FIRM Platform 资产管理系统的文件索引与权限校验
•游戏引擎运行时的模型资源加载器
•第三方工具的格式兼容性开发(须获得授权)
•合规审计中的文件完整性与授权合法性验证
1.3 相关参考文档
本文档与以下内部文档配合使用:
•WFS Engine 渲染管线规范(内部文档 WFS-REN-001)
•FIRM Platform 资产权限管理规范(内部文档 FIRM-SEC-002)
•WFS Editor 用户手册(公开文档)
第二章设计背景与目的
2.1 为什么不使用通用格式
市面上已有多种成熟的三维模型交换格式,如 .obj、.fbx、.gltf 等。这些格式在跨软件交换”最终渲染结果”方面表现良好,但均无法满足本系统对”可编辑工程状态”的核心需求。
具体而言,通用格式存在以下根本性局限:
|
需求维度 |
通用格式(.obj/.gltf) |
WFSM 专属格式 |
|
拓扑结构保存 |
仅三角面索引,无拓扑关系 |
完整半边数据结构,支持邻域查询 |
|
参数化历史 |
仅保存最终网格结果 |
保存完整操作历史,可重新调参 |
|
编辑器状态 |
不支持 |
摄像机、选中项、操作历史全保留 |
|
材质生成逻辑 |
仅保存最终参数值 |
保存程序化生成种子与规则 |
|
文件加密保护 |
不支持或仅基础加密 |
AES-256-GCM + Ed25519 签名 |
|
权限分级控制 |
不支持 |
支持查看/编辑/导出/分发四级权限 |
|
版本向后兼容 |
视具体格式,通常较差 |
主次版本号机制,明确兼容策略 |
2.2 格式设计目标
WFSM 格式的设计遵循以下六大核心目标,各目标之间相互约束,共同构成格式的设计哲学:
2.2.1 完整性
文件必须能保存模型的全部编辑状态,包括几何顶点坐标、拓扑半边结构、材质参数与生成逻辑、UV 展开数据、对象层级关系、参数化构造历史,以及编辑器的工作现场状态。
2.2.2 可编辑性
模型文件载入系统后,必须能恢复为”可继续编辑”的状态,而不仅仅是显示一个静态网格。这是 WFSM 与所有通用交换格式的根本区别。
2.2.3 可扩展性
格式通过扩展块(Extensions)机制支持未来新增功能模块,如骨骼绑定、动画数据、物理碰撞、粒子系统等,而不破坏现有解析器的兼容性。
2.2.4 安全性
格式内置数字签名与哈希校验机制,支持可选数据加密,支持四级权限控制(查看/编辑/导出/分发),并区分”编辑版”与”发布版”两种分发模式。
2.2.5 高性能
通过分块式索引表设计,解析器可在不全量读取文件的前提下直接跳转到任意数据块,实现关键数据的快速访问。几何二进制数据支持 zstd/lz4 压缩。
2.2.6 版本兼容
采用主次版本号(major.minor)策略:主版本变更代表破坏性更改,旧解析器应拒绝;次版本变更保持向后兼容,旧解析器可跳过未知字段继续读取。
2.3 格式命名与扩展名
系统提供以下三种扩展名,对应不同的使用场景:
|
扩展名 |
全称 |
适用场景 |
|
.wfsm |
WFS Model |
编辑器内部原生工程文件,包含完整可编辑状态,供系统内部使用 |
|
.firmmdl |
FIRM Model |
FIRM 平台品牌级格式,强调平台归属,用于 FIRM 世界内的资产交换 |
|
.wfspkg |
WFS Package |
发布与分发包,包含模型+材质+贴图+配置+权限签名的完整封装 |
第三章文件基础结构
WFSM 文件采用分块式结构(Chunk-Based Architecture)。整个文件被划分为多个独立的逻辑数据块,每个块负责存储一类信息。块与块之间通过块索引表相互关联,解析器可以在不全量读取文件的前提下直接定位任意块。
3.1 文件整体布局
一个完整的 WFSM 文件由以下部分按顺序构成:
┌─────────────────────────────────────────┐
│HEADER固定 64 字节,永不压缩│
├─────────────────────────────────────────┤
│META模型元信息 (JSON)│
│SCENE场景配置 (JSON)│
│OBJECTS对象列表 (JSON Array)│
│GEOMETRY几何数据 (Binary Buffers)│
│TOPOLOGY拓扑结构 (Binary)│
│MATERIALS材质定义 (JSON)│
│UVSETSUV 数据 (Binary)│
│PARAMS参数化历史 (JSON)│
│EDITORSTATE编辑器状态 (JSON)│
│EXTENSIONS扩展块 (Optional)│
├─────────────────────────────────────────┤
│CHUNK TABLE块索引表│
├─────────────────────────────────────────┤
│SECURITYFOOTER 安全尾部,固定 96 字节│
└─────────────────────────────────────────┘
|
关键设计:HEADER 永远位于文件起始,SECURITYFOOTER 永远位于文件末尾,两者均不参与哈希或压缩计算。其余所有数据块的顺序由块索引表记录,理论上可以任意排列,解析器通过索引表定位而非依赖顺序。 |
3.2 各数据块说明
3.2.1 HEADER — 文件头
文件头固定占 64 字节,不压缩、不加密,是解析器读取的第一个结构。通过魔数快速识别文件类型,通过版本号判断兼容性,通过块索引表偏移实现任意块的 O(1) 跳转访问。
|
字段名 |
类型 |
说明 |
|
magic |
char[4] |
文件魔数,固定值 “WFSM”(0x57 0x46 0x53 0x4D)。不匹配则立即拒绝文件。 |
|
version_major |
uint16_le |
主版本号,当前值为 2。主版本不同代表破坏性变更,解析器应拒绝或警告。 |
|
version_minor |
uint16_le |
次版本号,当前值为 0。次版本变更保持向后兼容,解析器可跳过未知字段。 |
|
endian |
uint8 |
字节序标志。0 = little-endian(推荐),1 = big-endian,影响所有后续数值字段。 |
|
encoding |
uint8 |
描述性块的编码方式。0 = JSON+二进制混合(推荐),1 = 纯二进制,2 = MessagePack。 |
|
compression |
uint8 |
大数组块的压缩算法。0 = 不压缩,1 = zstd(推荐),2 = lz4。Header 本身永不压缩。 |
|
_reserved |
uint8 |
保留字节,当前固定为 0xFF,供未来扩展使用。 |
|
generator |
char[32] |
生成工具标识,UTF-8 编码,不足 32 字节用 0x00 填充。例如 “WFS Editor v2.0″。 |
|
chunk_count |
uint32_le |
文件中块的总数量。解析器根据此值确定块索引表的读取范围。 |
|
chunk_table_offset |
uint64_le |
块索引表在文件中的字节偏移地址,是快速跳读的核心入口。 |
3.2.2 META — 元信息块
META 块保存模型的描述性信息,采用 UTF-8 JSON 编码,便于外部工具快速索引而无需理解几何数据。
|
字段名 |
类型 |
说明 |
|
modelId |
UUID v4 |
全局唯一标识符,格式 xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx。不随重命名改变,是系统内资源引用的永久键值。 |
|
modelName |
string |
人类可读的模型名称,支持 Unicode。显示于编辑器标题栏和资产列表。 |
|
author |
string |
模型创建者名称,可为用户账号 ID 或真实姓名。 |
|
createdAt |
ISO 8601 |
创建时间戳,格式 “2025-03-19T10:30:00Z”,UTC 时区,由系统自动填充。 |
|
updatedAt |
ISO 8601 |
最后修改时间戳,每次执行保存操作时系统自动更新。 |
|
project |
string |
所属项目名称,用于编辑器资产面板的分组过滤。 |
|
category |
enum |
资产类别枚举:weapon / armor / prop / character / environment / vfx,影响导出流水线选择。 |
|
tags |
string[] |
自由标签数组,用于搜索与批量操作。示例:[“sci-fi”,”melee”,”tier-2″]。 |
|
description |
string |
自由描述文本,支持 Markdown 子集格式。 |
|
thumbnail_ref |
string |
缩略图引用,可为相对路径或内嵌 base64 data URI(建议 64KB 以下内嵌,否则外部引用)。 |
|
license |
string |
许可证标识,如 “FIRM-INTERNAL-1.0” 或 “CC-BY-4.0″,配合 SecurityFooter 权限字段使用。 |
3.2.3 OBJECTS — 对象列表块
OBJECTS 块以 JSON 数组形式保存场景中每个对象单元。对象通过 parentId 字段构成树形层级,通过 geometryRef 和 materialRef 引用其他块数据,实现几何数据的多对象共享(实例化基础)。
|
字段名 |
类型 |
说明 |
|
objectId |
UUID |
对象的唯一标识,系统内引用的基础键值。删除对象时,所有引用此 ID 的数据均应级联清理。 |
|
objectName |
string |
对象显示名称,显示于编辑器大纲视图,可重复但建议唯一。 |
|
type |
enum |
对象类型:mesh(标准网格)/ curve(样条曲线)/ helper(辅助对象)/ locator(空标记)/ collision(碰撞体)/ group(分组)/ parametric_source(参数化源)。 |
|
visible |
boolean |
视口显示开关。不影响导出,导出控制通过独立的 exportFlags 字段管理。 |
|
locked |
boolean |
编辑锁定标志。锁定状态下对象不响应选择和变形操作,但仍可渲染和导出。 |
|
parentId |
UUID | null |
父对象 ID,null 表示根级对象。系统加载时根据此字段重建场景树层级关系。 |
|
transform |
float32[16] |
Column-major 4×4 仿射变换矩阵,局部坐标系,相对于父对象。含位移、旋转、缩放信息。 |
|
geometryRef |
UUID | null |
引用 GEOMETRY 块中某条几何数据的 ID。type 为 group / locator 时为 null。 |
|
materialRef |
UUID[] |
材质 ID 列表,顺序对应 Geometry 子网格的 submesh 索引,实现多材质分配。 |
|
userData |
JSON object |
自定义扩展字段,系统不解析、原样保留。用于游戏引擎附加数据、AI 标记、挂点信息等。 |
3.2.4 GEOMETRY — 几何数据块
GEOMETRY 块保存网格的纯几何数据,全部使用二进制缓冲区存储,是文件体积最大的块。顶点属性以连续缓冲区存放,索引使用 uint32 格式以支持超大网格(最大 4G+ 顶点)。
|
字段名 |
类型 |
说明 |
|
geometryId |
UUID |
此几何数据的唯一 ID,供 OBJECTS 块的 geometryRef 引用,支持多对象共享同一几何数据。 |
|
vertexCount |
uint32 |
顶点总数,用于校验缓冲区长度合法性。positions 的字节长度必须等于 vertexCount × 12。 |
|
indexCount |
uint32 |
索引总数,必须为 3 的倍数(每 3 个索引构成一个三角面)。 |
|
positions |
Float32Array |
顶点位置坐标 [x,y,z],连续存储。总字节数 = vertexCount × 12。默认 float32,高精度模式可选 float64。 |
|
normals |
Float32Array? |
顶点法线 [nx,ny,nz],单位向量。可选字段,省略时系统在导出时自动计算平滑法线。 |
|
tangents |
Float32Array? |
切线向量 [tx,ty,tz,w],w 分量为副切线方向(+1 或 -1)。法线贴图渲染所需,可选。 |
|
colors |
Uint8Array? |
顶点色 [r,g,b,a],uint8 范围 0~255。可选,用于顶点绘制工具和 AO 烘焙数据存储。 |
|
uvSets |
Float32Array[] |
多套 UV 坐标数组,每套 [u,v] 每顶点 8 字节。index 0 为主贴图 UV,index 1 通常为 lightmap UV。 |
|
indices |
Uint32Array |
三角面顶点索引,每三个为一组 [i0,i1,i2],按逆时针顺序定义正面朝向。 |
|
submeshes |
Submesh[] |
子网格分段数组,每段有独立的 indexStart、indexCount、materialIndex,对应一个材质槽。 |
|
lodLevels |
LodLevel[]? |
LOD 级别数组,每级包含独立的精简索引缓冲区与切换距离阈值,可选。 |
3.2.5 TOPOLOGY — 拓扑数据块(核心)
TOPOLOGY 块是 WFSM 格式最关键的差异化特性。它以半边数据结构(Half-Edge Data Structure)保存完整的网格拓扑关系,使系统在载入文件后能够进入真正的编辑状态,支持挤出、倒角、环选等所有拓扑敏感操作。
|
为什么需要拓扑数据:仅保存三角索引(通用格式的做法)无法恢复以下编辑信息:挤出关系、边界边、相邻面、面环、可编辑边流、半边配对关系。保存完整拓扑后,系统可重新进入真正的编辑态,而非”导入后只剩静态网格”。 |
半边数据结构(HalfEdge DS)的核心不变量:每条边被分裂为两条方向相反的半边。每条半边携带以下五个引用:
•vert:此半边”指向”的目标顶点(终点)
•pair:与之配对的反向半边,边界半边此值为 -1
•next:同一面内的下一条半边(逆时针方向)
•prev:同一面内的上一条半边
•face:所属面的索引,边界半边此值为 -1
通过这五个引用,可以在 O(1) 时间内完成所有邻域查询(顶点一环邻面、相邻边、边界检测等)。
|
字段名 |
类型 |
说明 |
|
TopoVertex |
struct |
顶点拓扑单元:pos(坐标)、halfEdgeIdx(出发半边入口)、flags(边界/非流形/锁定/选中标志位)。 |
|
HalfEdge |
struct |
半边单元:vert(目标顶点)、pair(配对半边)、next(面内下一)、prev(面内上一)、face(所属面)、flags。 |
|
TopoEdge |
struct |
边单元:he0/he1(两条配对半边索引)、boundary(边界标记)。支持边级选择与边折叠操作。 |
|
TopoFace |
struct |
面单元:halfEdgeIdx(面环入口半边)、normal(面法线)、matIdx(材质槽索引)。 |
|
flags(顶点) |
uint8 bits |
bit0=边界顶点,bit1=非流形,bit2=锁定,bit3=选中,bit4~7=用户自定义标记。 |
|
flags(半边) |
uint8 bits |
bit0=边界半边(无 pair),bit1=折叠边,bit2=UV 缝合边,bit3=锁定边。 |
3.2.6 MATERIALS — 材质数据块
MATERIALS 块不仅保存 PBR 渲染参数,还保存材质的生成逻辑与状态,包括磨损种子、程序化贴图参数和锁定覆盖规则,使材质可以无损重生成。
|
字段名 |
类型 |
说明 |
|
materialId |
UUID |
材质唯一标识符,供 OBJECTS 块的 materialRef 引用。 |
|
baseColor |
float32[4] |
基础色 RGBA,取值范围 [0,1]。 |
|
metalness |
float32 |
金属度,范围 [0,1],0 为非金属,1 为纯金属。 |
|
roughness |
float32 |
粗糙度,范围 [0,1],0 为镜面,1 为完全漫反射。 |
|
emissive |
float32[3] |
自发光 RGB,支持 HDR(可超过 1.0)。 |
|
normalMap |
TextureRef? |
法线贴图引用,切线空间,Linear 色彩空间。 |
|
wearValue |
float32 |
WFS 专属磨损值,范围 [0,1],0 为全新,1 为极度磨损。 |
|
wearSeed |
uint32 |
磨损随机种子,保证磨损纹理在不同机器上可精确复现。 |
|
lockedOverride |
boolean |
true 时此材质不受外部磨损逻辑影响,保持当前状态。 |
|
proceduralMap |
JSON? |
程序化贴图生成参数,包含生成器类型、参数字典和复现种子,可回放重生成。 |
3.2.7 PARAMS — 参数化历史块
PARAMS 块记录模型的参数化构造历史,是专属格式与通用交换格式最核心的差别。保存此块后,重新打开文件时系统可从参数历史完全重建模型,而不是仅加载静止网格。每条 ParamEntry 记录一次操作,按顺序执行即可重建最终结果。
|
字段名 |
类型 |
说明 |
|
paramId |
UUID |
此参数步骤的唯一 ID,用于历史栈中的定位与引用。 |
|
op |
enum |
操作类型:extrude / bevel / subdivide / boolean_union / boolean_sub / mirror / lathe / solidify / array / cloth_panel 等。 |
|
targetId |
UUID |
此操作作用的对象 ID,指向 OBJECTS 块中的某个对象。 |
|
params |
JSON |
操作参数字典,不同 op 类型有不同参数,如 extrude 有 {depth, keepFace, cap}。 |
|
timestamp |
ISO 8601 |
操作执行时间,用于历史审计。 |
|
enabled |
boolean |
false 时跳过此步骤但保留记录,类似 3ds Max 的 modifier 开关功能。 |
|
locked |
boolean |
true 时此步骤参数被锁定,不允许普通用户修改,需管理员权限才能解锁。 |
3.2.8 EDITORSTATE — 编辑器状态块
EDITORSTATE 块保存用户工作现场的完整快照。重新打开文件时,编辑器能几乎完整地恢复到关闭时的状态,减少用户重新定位的时间成本。
|
字段名 |
类型 |
说明 |
|
selectedObjects |
UUID[] |
当前已选中的对象 ID 列表。 |
|
selectedVerts |
uint32[] |
选中的顶点索引列表(编辑模式下有效)。 |
|
selectedEdges |
uint32[] |
选中的边索引列表(编辑模式下有效)。 |
|
selectedFaces |
uint32[] |
选中的面索引列表(编辑模式下有效)。 |
|
cameraTransform |
float32[16] |
视口摄像机的 4×4 变换矩阵,记录相机位置和朝向。 |
|
viewportMode |
enum |
视口模式:perspective(透视)/ orthographic(正交)/ front / back / left / right / top / bottom。 |
|
editMode |
enum |
编辑模式:object / vertex / edge / face。 |
|
gizmoState |
JSON |
Gizmo 工具状态,包含激活的变换类型(translate/rotate/scale)和坐标系(local/global)。 |
|
historyIndex |
int32 |
当前历史栈的指针位置,用于恢复 undo/redo 状态。 |
|
recentTools |
string[] |
最近使用工具列表(最多 10 条),用于快速访问栏的恢复。 |
第四章加密与安全机制
WFSM 格式内置多层次的安全机制,通过 SECURITYFOOTER 块实现文件完整性校验、来源认证和权限控制。安全机制分为三个层面:哈希完整性、数字签名和可选数据加密。
4.1 安全尾部结构
SECURITYFOOTER 固定占 96 字节,永远位于文件最末尾,不参与哈希计算自身。其结构如下:
|
字段名 |
类型 |
说明 |
|
contentHash |
bytes[32] |
SHA-256 摘要,对文件中 Header 至 SECURITYFOOTER 起始前的全部内容计算,用于检测文件是否被篡改。 |
|
signature |
bytes[64] |
Ed25519 数字签名,由创建工具持有的私钥对 contentHash 签名,用于验证文件来源的合法性。 |
|
permissions |
uint8 |
权限位字段。bit0=允许查看,bit1=允许编辑,bit2=允许导出,bit3=允许分发,bit7=管理员超级标志。 |
|
expireAt |
uint64_le |
到期时间 Unix 时间戳(秒),值为 0 表示永久有效。过期后系统拒绝加载(发布版文件适用)。 |
|
originId |
UUID |
生成此文件的系统实例标识,用于来源追踪和授权系统验证。 |
|
encryptionInfo |
JSON? 可选 |
加密信息描述。若某些块被加密,此字段记录算法名称(如 AES-256-GCM)、IV 和密钥来源提示,但不含密钥本身。 |
4.2 完整性校验流程
每次文件加载时,解析器应执行以下完整性校验流程:
•Step 1:读取文件末尾 96 字节,解析 SECURITYFOOTER 结构
•Step 2:对文件 Header 至 SecurityFooter 起始前的全部字节计算 SHA-256 摘要
•Step 3:将计算结果与 contentHash 字段比较,不一致则报告”文件已被篡改”并拒绝加载
•Step 4:使用系统内置公钥对 signature 字段执行 Ed25519 签名验证,失败则报告”来源不合法”
•Step 5:检查 expireAt 字段,若当前时间已超过到期时间则拒绝加载(返回错误码 WFSM_ERR_EXPIRED)
•Step 6:读取 permissions 字段,根据当前用户的操作类型检查对应权限位是否已授权
|
安全提示:在非受信任环境中加载文件时,步骤 3 和 4 均不可跳过。系统应提供选项允许管理员在明确知情的情况下覆盖校验(需要管理员权限),但任何情况下都不应在用户不知情时静默绕过安全检查。 |
4.3 权限级别说明
permissions 字段为 1 字节位标志,支持对文件操作进行细粒度控制:
|
位 |
权限名称 |
说明 |
|
bit0 |
VIEW(查看) |
允许在系统内打开并查看模型,但不允许进行任何编辑操作。适用于审核人员或客户预览场景。 |
|
bit1 |
EDIT(编辑) |
允许修改模型的拓扑、几何、材质、参数等所有可编辑内容,并保存修改结果。 |
|
bit2 |
EXPORT(导出) |
允许将模型导出为 .obj / .glb / .fbx 等通用交换格式。即使有此权限也不代表可以编辑原文件。 |
|
bit3 |
DISTRIBUTE(分发) |
允许将文件分发给其他账号或系统实例。发布版文件通常设置此位,编辑版通常不设置。 |
|
bit4~6 |
(保留) |
当前未使用,保留供未来权限扩展,当前必须为 0。 |
|
bit7 |
OVERRIDE(超级) |
管理员超级标志,置 1 时覆盖所有其他权限限制。仅由系统管理员账号颁发。 |
4.4 数据块加密
除完整性校验外,WFSM 支持对特定数据块进行内容加密,使未授权方即使获得文件也无法读取核心数据。加密方案采用 AES-256-GCM(认证加密),每块独立加密,互不影响。
加密规则如下:HEADER 和 SECURITYFOOTER 永远不加密(需要被解析器直接读取);META 通常不加密(便于资产管理系统索引);GEOMETRY、TOPOLOGY、PARAMS 等核心数据块可选加密。加密密钥通过系统密钥管理服务分发,不存储于文件内。
加密块的二进制结构:
┌────────────────────────────────────────────┐
│ chunk_id[4 bytes]块类型标识│
│ flags[1 byte]bit0=1 表示已加密│
│ iv_nonce[12 bytes] AES-GCM 随机 IV│
│ auth_tag[16 bytes] GCM 认证标签│
│ encrypted_data [N bytes] 加密后的实际数据│
└────────────────────────────────────────────┘
第五章文件读取与写入流程
5.1 文件读取流程
WFSM 解析器的标准读取流程分为以下阶段。每个阶段失败都应返回明确的错误码,不应静默忽略。
5.1.1 阶段一:文件头验证
•读取文件前 64 字节解析 HEADER 结构
•检查 magic 字段是否等于 “WFSM”,不匹配则返回 WFSM_ERR_INVALID_MAGIC
•检查 version_major 是否等于当前解析器支持的主版本,不匹配则返回 WFSM_ERR_VERSION_MISMATCH
•记录 endian、encoding、compression 字段,后续解析均依赖这三个值
5.1.2 阶段二:安全校验
•读取文件末尾 96 字节解析 SECURITYFOOTER
•对文件中除最后 96 字节外的全部内容计算 SHA-256,与 contentHash 对比
•使用内置公钥验证 Ed25519 signature,失败则返回 WFSM_ERR_INVALID_SIGNATURE
•检查 expireAt 字段,过期则返回 WFSM_ERR_EXPIRED
•根据当前操作意图检查 permissions 位,权限不足则返回 WFSM_ERR_PERMISSION_DENIED
5.1.3 阶段三:块索引加载
•通过 HEADER.chunk_table_offset 定位块索引表
•读取 HEADER.chunk_count 个 ChunkTableEntry,建立 chunkId → {offset, byteLength, flags} 的映射
•此后解析器可按需跳转读取任意块,无需顺序扫描
5.1.4 阶段四:按需解析块数据
建立块索引后,解析器根据需求决定解析顺序。推荐的加载优先级如下:
•META — 最先加载,用于显示模型名称和检查权限
•OBJECTS — 建立场景树结构,确定需要加载哪些几何数据
•GEOMETRY + TOPOLOGY — 载入几何和拓扑数据,准备进入编辑状态
•MATERIALS + UVSETS — 应用材质和 UV,准备渲染显示
•PARAMS — 恢复参数面板(可延迟加载)
•EDITORSTATE — 恢复工作现场(可延迟加载)
•EXTENSIONS — 按需加载(骨骼/动画等,可延迟加载)
5.2 文件写入流程
WFSM 文件的写入遵循以下步骤,确保文件结构和安全性的正确性:
1.序列化所有数据块:将各块数据序列化为二进制缓冲区,对 Geometry/Topology 等大块执行可选压缩
2.构建块索引表:记录每个块的 chunkId、起始偏移、字节长度和标志位
3.写入所有块数据及块索引表到缓冲区
4.计算当前 chunk_table_offset,构建 HEADER(64 字节)并写入文件起始
5.对 HEADER + 所有块数据 + 块索引表的全部内容计算 SHA-256 哈希
6.使用系统私钥对哈希值执行 Ed25519 签名
7.构建 SECURITYFOOTER(96 字节),写入文件末尾
8.验证写入结果:读取刚写入的文件执行一次完整的 Header 验证和哈希校验
|
重要约束:写入过程中不得修改已序列化块的内容,否则最终哈希将与各块的哈希不一致。若需要修改某块数据,必须重新序列化该块,并从步骤 2 重新开始。 |
5.3 解析器错误码参考
WFSM 解析器应实现以下标准错误码,便于上层系统进行统一的错误处理:
|
错误码 |
含义与处理建议 |
|
WFSM_OK (0) |
成功,无错误。 |
|
WFSM_ERR_INVALID_MAGIC (1) |
魔数不匹配,不是合法的 WFSM 文件,应立即拒绝并提示用户。 |
|
WFSM_ERR_VERSION_MISMATCH (2) |
主版本号不兼容,需要升级解析器版本才能读取。 |
|
WFSM_ERR_HASH_MISMATCH (3) |
SHA-256 哈希不一致,文件可能被篡改,应拒绝加载并警告用户。 |
|
WFSM_ERR_INVALID_SIGNATURE (4) |
Ed25519 签名验证失败,文件来源不合法。 |
|
WFSM_ERR_EXPIRED (5) |
文件已超过授权到期时间,需要联系内容所有者重新授权。 |
|
WFSM_ERR_PERMISSION_DENIED (6) |
当前用户的权限不足,无法执行此操作。 |
|
WFSM_ERR_DECRYPT_FAILED (7) |
数据块解密失败,可能是密钥错误或数据损坏。 |
|
WFSM_ERR_CORRUPT_CHUNK (8) |
块数据长度或格式不符合规范,文件可能局部损坏。 |
|
WFSM_ERR_UNKNOWN_CHUNK (9) |
遇到未知块 ID 且该块标记为必须(non-optional),无法继续解析。 |
|
WFSM_ERR_TOPOLOGY_INVALID (10) |
拓扑数据不满足半边结构不变量,文件数据存在逻辑错误。 |
第六章版本兼容策略
WFSM 格式采用语义化版本号(Semantic Versioning)策略,通过 HEADER 的 version_major 和 version_minor 两个字段共同控制兼容性行为。
6.1 主版本(Major)变更规则
主版本号变更(如从 2.x 升至 3.0)代表格式发生了不向后兼容的破坏性变更。低版本解析器遇到高主版本文件时,应返回 WFSM_ERR_VERSION_MISMATCH 并拒绝加载。
触发主版本变更的场景包括:
•HEADER 结构本身发生字段布局变更
•块索引表结构发生不兼容变更
•SECURITYFOOTER 结构或签名算法变更
•核心块(GEOMETRY/TOPOLOGY)的数据格式发生根本性重构
6.2 次版本(Minor)变更规则
次版本号变更(如从 2.0 升至 2.1)代表向后兼容的功能新增。老解析器读取高次版本文件时,遇到不认识的块可以跳过(前提是该块在块索引表中标记为 optional),遇到不认识的字段可以忽略,不影响已知数据的正确解析。
触发次版本变更的场景包括:
•新增可选数据块(如新增 ANIMATION 块),并在块索引表中标记为 optional
•在现有块的末尾新增可选字段
•新增 PARAMS 操作类型枚举值
•新增 MATERIALS 材质类型枚举值
6.3 兼容性矩阵
|
解析器版本 |
文件版本 |
结果 |
|
v2.0 |
v2.0 |
完全兼容 |
|
v2.0 |
v2.1 |
兼容,跳过新增可选块 |
|
v2.1 |
v2.0 |
完全兼容(向前兼容) |
|
v2.x |
v3.0 |
拒绝加载,返回版本不兼容错误 |
|
v1.x |
v2.0 |
拒绝加载,返回版本不兼容错误 |
第七章扩展区与未来规划
EXTENSIONS 块为未来系统功能模块预留了扩展空间。每个扩展模块使用独立的命名空间,不影响现有解析器的兼容性。
7.1 扩展块机制
每个扩展模块在块索引表中注册时,其 chunkId 以扩展命名空间前缀标识(如 “EXT_SKEL” 表示骨骼扩展)。块索引表的 flags 字段中,bit2 表示此块为”可选”(optional):解析器遇到不认识的 optional 块时跳过即可,不影响核心数据的加载。
7.2 已规划扩展模块
|
Chunk ID |
模块名称 |
用途说明 |
|
EXT_SKEL |
骨骼绑定 |
角色与武器的骨骼层级、蒙皮权重数据,支持角色动画系统集成 |
|
EXT_ANIM |
动画片段 |
关键帧动画数据,支持位移/旋转/缩放/形态键四种通道 |
|
EXT_PHYS |
物理碰撞 |
碰撞体形状定义(球/胶囊/凸包/三角网格),供物理引擎直接使用 |
|
EXT_PART |
粒子发射器 |
绑定于模型的粒子发射器配置,用于特效挂载点定义 |
|
EXT_TAIL |
裁缝结构 |
服装裁片数据:腰围半径、裙长、褶皱频率等服装参数化构造数据 |
|
EXT_DMGE |
战斗损伤 |
模型的可损伤区域定义、损伤等级贴图集和损坏状态过渡参数 |
|
EXT_NAVX |
导航碰撞壳 |
为 AI 寻路系统提供的碰撞壳几何体,与渲染网格分离 |
|
EXT_LOGI |
逻辑触发器 |
模型上的交互触发区域定义,供游戏逻辑事件系统使用 |
附录 A术语表
|
术语 |
定义 |
|
半边结构 (HalfEdge DS) |
一种网格拓扑数据结构,将每条边分裂为两条有向半边,支持 O(1) 时间的邻域查询,是编辑器实现挤出、倒角、边环选择等操作的底层基础。 |
|
Chunk(块) |
WFSM 文件的基本存储单元,每个块存储一类信息。块与块之间通过块索引表相互关联,解析器可按需跳转读取。 |
|
SHA-256 |
一种密码学哈希算法,输出 256 位(32 字节)的摘要。用于检测文件内容是否被篡改,相同内容始终产生相同哈希,哈希不可逆推原内容。 |
|
Ed25519 |
一种基于椭圆曲线密码学的数字签名算法,使用 32 字节私钥签名、32 字节公钥验证,签名结果为 64 字节。速度快、安全性高。 |
|
AES-256-GCM |
一种对称认证加密算法,使用 256 位密钥,GCM 模式提供数据加密和完整性认证(产生 16 字节认证标签),防止密文被篡改。 |
|
LOD (Level of Detail) |
多级细节技术,根据对象与摄像机的距离选择不同精度的网格,远处使用低精度网格以提升渲染性能。 |
|
submesh(子网格) |
在同一几何体内按材质分段的子区域,每个子网格有独立的索引范围和材质分配,允许一个模型使用多种不同材质。 |
|
参数化构造 |
将建模操作(挤出、倒角、细分等)以参数形式记录而非直接写死最终几何结果,允许事后修改参数重新生成模型。 |
|
魔数 (Magic Number) |
文件开头固定的字节序列,用于标识文件类型。WFSM 的魔数为 “WFSM”(0x57 0x46 0x53 0x4D)。 |
|
DXA |
Document eXtended Units of Measure 的缩写,Word 文档中的长度单位,1 英寸 = 1440 DXA。 |
附录 B文档修订记录
|
版本 |
日期 |
修订人 |
变更说明 |
|
v1.0 |
2024-06-01 |
WFS Team |
初版发布,定义 Header、Meta、Geometry 基础结构 |
|
v1.5 |
2025-11-15 |
WFS Team |
新增 Topology 块、Params 块,引入半边数据结构 |
|
v2.0 |
2026-03-19 |
WFS Team |
新增 SecurityFooter 安全机制、权限分级、AES-256-GCM 加密支持,扩展版本兼容策略 |
— 文档结束 —
本文档为 WFS Engine / FIRM Platform 撰写
版权由StarMeter Studio所有
夜雨聆风