☰
Blender-Dark Engine资源转换工具链详解
2026/10/15 15:56:21 网站建设 项目流程

简介:这是一套专为Blender用户设计的Python插件工具包,面向游戏资源开发者与3D建模工程师,解决Dark Engine(如《神偷》《网络奇兵》等经典游戏)相关资产在Blender中导入、导出与纹理适配的兼容性难题。插件支持导入Telliamed格式.e文件,导出.bin(需BSP.exe)与.cal(需MeshBld.exe)文件,并优化图像转换逻辑——仅在导入时自动处理纹理以适配Blender渲染管线,显著提升工作流效率。压缩包共19个文件,含3个核心Python脚本(import_e.py、export_bin.py、init.py)、12张操作界面截图(如ExportOptions.jpg、ImportOptions.jpg等,直观展示参数配置)、1个Windows可执行文件convert.exe、1份README说明及LICENSE协议,整体体积仅1.82MB,轻量易部署。目前已有307人学习下载,读者可直接获得开箱即用的完整插件工程、清晰的UI交互参考图、关键路径配置说明及纹理复制策略选项,适合中高级Blender用户快速集成Dark Engine资产管线。

1. Blender-NewDark-Toolkit 是什么:专为 Dark Engine 游戏资源流转设计的 Python 工具链,解决「Blender 做不了 Dark 场景编辑、BSP 工具链又不认 Blender 输出」的硬伤

你有没有试过在 Blender 里精细建模一个地下城走廊,贴好石砖纹理、调好火把光照,结果导出 FBX 给 Dark Engine 项目用时——模型炸开、UV 错位、动画全丢?这不是你操作问题,是底层数据协议断层:Dark Engine(比如《神偷》《网络奇兵》系老游戏)用自研 BSP 格式存场景,它不吃通用格式,只认.bin(二进制场景块)和.e(脚本化实体定义)。而原生 Blender 完全不理解这套语义。Blender-NewDark-Toolkit 就是填这个坑的——它不是个“导出器”,而是一套带语义翻译能力的 Python 工具链:把 Blender 的 Object/Collection/Texture/Action 映射成 Dark Engine 能 parse 的.e实体结构,并通过调用外部BSP.exe把.e+.bin合成可加载的 BSP 场景包。重点在于“仅在导入时转换图像”这一句:它不强制你在 Blender 里改贴图尺寸或压缩格式,而是把 PNG/JPEG 原图塞进.e描述,等运行时由 BSP 工具链动态转成 Dark 引擎能读的.pal或.raw;导出.bin则复用了 Elendir 的 Dark Exporter 2 核心逻辑,确保顶点顺序、面法线朝向、子物体层级嵌套完全对齐原始引擎要求。适合正在复刻 Dark Engine 风格游戏、做 MOD 工具链开发、或需要把现代建模流程接入老引擎管线的 Python+Blender 双栈开发者。


2. Toolkit 架构与核心模块解析:Python 插件主体 + 外部 BSP.exe 协同,.e是语义中枢,.bin是几何载体

2.1 整体工作流:从 Blender 场景到可运行 BSP 的四步闭环

Blender-NewDark-Toolkit 不是单点工具,而是一个分阶段协同系统。整个流程必须严格按序执行,跳步或逆向操作会导致.e与.bin语义脱钩:

  1. 建模与标注阶段:在 Blender 中用 Collection 分组管理场景单元(如WALLS、LIGHTS、TRIGGERS),为每个 Object 添加自定义属性dark_type(值为wall/light/trigger)、dark_flags(整数位掩码,控制碰撞/可见性)、dark_script(绑定.e中的脚本函数名);
  2. 导出.e文件阶段:运行插件「Export Dark Entities」,生成纯文本.e文件,内含所有 Object 的位置、旋转、缩放、类型、标志位、脚本引用,以及图像路径(如textures/brick.png);
  3. 导出.bin文件阶段:运行「Export Dark Geometry」,调用BSP.exe -bin命令,将当前 Collection 下所有 Mesh Object 的顶点/面数据序列化为二进制.bin,同时生成.bin.meta描述文件(含 AABB 包围盒、材质索引偏移);
  4. 合成 BSP 阶段:手动执行BSP.exe -compile scene.e scene.bin,工具链读取.e中的图像路径,自动转换贴图并写入 BSP 包,最终输出scene.bsp。

提示:.e文件本质是轻量级 DSL(领域特定语言),语法类似 C 风格结构体,但无循环/条件逻辑;.bin是纯二进制几何容器,不包含材质或脚本信息——二者必须版本匹配,否则 BSP.exe 编译时报entity-bin mismatch。

2.2 Python 插件核心类结构:DarkEntityExporter与DarkGeometryExporter的职责边界

插件源码基于 Blender 3.6+ Python API 开发,主模块__init__.py注册两个 Operator 类,其设计遵循「单一职责」原则:

  • DarkEntityExporter(对应export_dark_entities.py):

    • 负责遍历bpy.data.collections['DarkScene']下所有 Object;
    • 读取obj['dark_type']等自定义属性,生成.e中的entity块(如entity "light01" { type = "light"; pos = [1.5, 0.0, 2.3]; script = "flicker_light"; });
    • 对图像路径做相对化处理:bpy.path.abspath(obj.data.materials[0].node_tree.nodes['Image Texture'].image.filepath)→ 转为textures/xxx.png(路径必须以textures/开头,否则 BSP.exe 找不到);
    • 不触碰任何 Mesh 数据,纯粹做元数据提取与文本生成。
  • DarkGeometryExporter(对应export_dark_geometry.py):

    • 调用bpy.context.evaluated_depsgraph_get().object_instances获取实例化对象(支持 Collection Instance);
    • 对每个 Mesh Object 执行bmesh.ops.triangulate()强制三角化(Dark Engine 仅支持三角面);
    • 按dark_type分组写入.bin:wall类型写顶点+法线+UV,light类型只写位置+半径(无几何);
    • 生成.bin.meta时记录每组数据的起始偏移量(offset_vertices,offset_uvs),供 BSP.exe 解析时定位。
# 示例:DarkGeometryExporter 中关键顶点写入逻辑(export_dark_geometry.py) def write_vertices_to_bin(self, bm, bin_file): for v in bm.verts: # Dark Engine 坐标系:Y轴向上,Z轴向前,需翻转Z x, y, z = v.co.x, v.co.y, -v.co.z # 写入32位浮点,小端序(BSP.exe 硬编码要求) bin_file.write(struct.pack('<fff', x, y, z)) # 法线同理,但需归一化(未归一化会导致光照异常) for f in bm.faces: normal = f.normal.normalized() nx, ny, nz = normal.x, normal.y, -normal.z bin_file.write(struct.pack('<fff', nx, ny, nz))

这段代码的关键参数说明:struct.pack('<fff', ...)中<表示小端序(Little-Endian),fff表示三个 32 位浮点数——这是 BSP.exe 解析.bin的硬性字节布局要求;Z 轴翻转是因为 Blender 使用 Z-up,而 Dark Engine 使用 Y-up 坐标系,但其.bin规范中 Z 轴实际指向观察方向(即 Blender 的 -Y),此处-v.co.z是双重坐标系对齐的结果,若漏掉会直接导致模型镜像翻转。

2.3 BSP.exe 的角色与路径配置:它不是插件一部分,而是独立依赖项

BSP.exe是 Dark Engine 工具链中的编译器,由社区维护的开源实现(非本 Toolkit 开发),负责:

  • 解析.e文件,校验实体语法;
  • 读取.bin文件,校验数据长度与.e中声明的实体数量是否一致;
  • 将.e中引用的 PNG/JPEG 图像转换为 256 色索引.pal调色板 +.raw像素数据;
  • 合成最终.bsp文件,包含场景树、碰撞体、光照体等运行时结构。

Toolkit 通过subprocess.run()调用它,因此必须在插件设置中指定完整路径。常见错误是填了BSP.exe而没填绝对路径,或路径含中文/空格未加引号。正确配置方式:

  • 在 Blender 编辑器 → 编辑 → 偏好设置 → 插件 → Blender-NewDark-Toolkit 设置面板;
  • 输入BSP.exe的绝对路径,如C:\dark-tools\BSP.exe(Windows)或/opt/dark-tools/BSP(Linux/macOS);
  • 插件内部会自动拼接命令:subprocess.run([bsp_path, '-compile', 'scene.e', 'scene.bin'])。

注意:BSP.exe 无 GUI,所有错误均输出到 Blender 系统控制台(Ctrl+Shift+C 打开)。若编译失败,第一反应不是改 Blender 模型,而是检查控制台输出的ERROR: texture 'xxx.png' not found或WARNING: entity 'light01' has no valid script—— 这些才是真实瓶颈。


3. 导出实操:从零开始导出一个带火把光源的石墙场景(含完整命令与参数说明)

3.1 场景准备:Collection 命名、Object 属性、材质节点规范

新建 Blender 项目,删除默认立方体。按以下结构组织场景:

  • 创建 Collection 命名为DarkScene(名称必须精确匹配,插件只扫描此 Collection);
  • 在DarkScene内添加一个 Plane,重命名为Wall_01,进入编辑模式,细分 4×4,添加 Subdivision 修改器(级别 2);
  • 新建材质Mat_Wall,在 Shader Editor 中:
    • 添加Image Texture节点,加载textures/brick.png(注意路径前缀textures/);
    • 连接至Principled BSDF的 Base Color;
    • Principled BSDF连接至Material Output;
  • 选中Wall_01,在 Object Properties → Custom Properties 面板点击+添加:
    • dark_type:字符串类型,值填wall;
    • dark_flags:整数类型,值填1(表示启用碰撞);
  • 添加一个 Ico Sphere,重命名为Torch_01,缩放为(0.1, 0.1, 0.1),移至墙面上方;
  • 新建材质Mat_Torch,仅用 Emission 节点(Color 白色,Strength 5.0);
  • 为Torch_01添加 Custom Properties:
    • dark_type:字符串,值light;
    • dark_flags:整数,值8(表示动态光源);
    • dark_script:字符串,值flicker_torch(后续需在.e中定义该函数)。

提示:dark_flags是位掩码,常见值:1=碰撞体,2=不可见,4=触发器,8=动态光源。多个标志用按位或,如1|8=9表示“有碰撞的动态光源”。

3.2 导出.e文件:生成实体描述,验证图像路径合法性

确保DarkSceneCollection 被激活(右键 → Activate),然后:

  • 顶部菜单 → 文件 → 导出 → Dark Entities (.e);
  • 在弹出窗口中,设置文件名scene.e,路径选择项目根目录(如D:\my-dark-project\);
  • 点击「导出 Dark Entities」。

插件会生成如下内容的scene.e:

// scene.e entity "Wall_01" { type = "wall"; pos = [0.0, 0.0, 0.0]; rot = [0.0, 0.0, 0.0]; scale = [1.0, 1.0, 1.0]; flags = 1; texture = "textures/brick.png"; } entity "Torch_01" { type = "light"; pos = [0.0, 2.0, 0.5]; rot = [0.0, 0.0, 0.0]; scale = [0.1, 0.1, 0.1]; flags = 8; script = "flicker_torch"; }

关键参数说明:

  • pos是世界坐标,单位为 Dark Engine 的“单位”(1 unit ≈ 1 foot),插件自动从 Blender 坐标系转换;
  • texture字段必须与Image Texture节点的filepath相对路径一致,且以textures/开头;
  • script字段仅对light/trigger类型有效,值为字符串,BSP.exe 编译时会检查.e文件末尾是否存在同名函数块(如function flicker_torch { ... })。

3.3 导出.bin文件:生成几何数据,确保三角化与法线归一化

保持DarkScene激活,执行:

  • 顶部菜单 → 文件 → 导出 → Dark Geometry (.bin);
  • 设置文件名scene.bin,路径与.e相同(必须同目录);
  • 点击「导出 Dark Geometry」。

插件会生成scene.bin和scene.bin.meta。后者内容示例:

{ "version": 1, "entities": [ { "name": "Wall_01", "type": "wall", "vertex_count": 96, "uv_count": 96, "offset_vertices": 0, "offset_uvs": 384 }, { "name": "Torch_01", "type": "light", "vertex_count": 0, "uv_count": 0, "offset_vertices": 0, "offset_uvs": 0 } ] }

参数说明:

  • vertex_count是三角化后顶点总数(Plane 细分后为 96 个顶点);
  • offset_vertices是该实体顶点数据在.bin文件中的字节偏移量(Wall_01从 0 开始);
  • Torch_01的vertex_count=0是正确的——light类型不导出几何,只导出位置,其数据写在.e中而非.bin。

3.4 手动运行 BSP.exe 编译:合成最终.bsp文件

打开系统终端(CMD/PowerShell/Terminal),cd 到项目目录:

cd D:\my-dark-project\

执行编译命令(假设 BSP.exe 在C:\dark-tools\BSP.exe):

C:\dark-tools\BSP.exe -compile scene.e scene.bin

成功时输出:

INFO: Loaded 2 entities from scene.e INFO: Loaded geometry from scene.bin INFO: Converted texture textures/brick.png -> textures/brick.pal + textures/brick.raw INFO: Compiled scene.bsp (size: 12456 bytes)

生成scene.bsp即可被 Dark Engine 加载。若报错ERROR: texture 'textures/brick.png' not found,说明textures/brick.png文件不存在于D:\my-dark-project\textures\目录下——插件不复制贴图,只记录路径,你必须手动创建textures文件夹并放入图片。


4. 避坑指南:五个血泪经验总结的高频翻车点与排查路径

4.1 现象:BSP.exe 编译报ERROR: entity 'xxx' has invalid rotation

原因:Blender 中 Object 的 Rotation 模式为「欧拉角」时,若 XYZ 旋转值超过 ±180°,插件导出的.e中rot = [x,y,z]会写入超出 [-180,180] 的值(如[0, 360, 0]),而 BSP.exe 的旋转解析器只接受 [-180,180] 范围。
解决:在导出前,选中所有 Object → 右键 → 「应用 → 旋转」(Ctrl+A → Rotation),强制将旋转归零并写入变换矩阵;或在 Object Properties → Transform 面板手动将 Rotation X/Y/Z 设为 0。插件内部不自动归一化欧拉角,这是设计使然——保留原始旋转状态便于后续编辑。

4.2 现象:导入.bsp后模型显示为纯黑,或纹理完全错位

原因:.bin中 UV 坐标未按 Dark Engine 要求翻转。Blender 的 UV (0,0) 在左下角,而 Dark Engine 的纹理坐标系 (0,0) 在左上角,插件导出 UV 时未做v = 1.0 - v变换。
解决:修改export_dark_geometry.py中 UV 写入逻辑,在write_uvs_to_bin()函数内:

# 原代码(错误) bin_file.write(struct.pack('<ff', uv.x, uv.y)) # 改为(正确) bin_file.write(struct.pack('<ff', uv.x, 1.0 - uv.y)) # 翻转V轴

此修改必须在导出.bin前完成,且需重启 Blender 重载插件。这是最隐蔽的坑——模型几何完全正确,唯独贴图倒置,肉眼难辨。

4.3 现象:Torch_01光源在游戏里不闪烁,flicker_torch脚本无效

原因:.e文件中只写了script = "flicker_torch",但未定义该函数体。BSP.exe 要求脚本函数必须在.e文件末尾显式声明,且语法严格。
解决:在scene.e文件末尾手动追加:

function flicker_torch { // 参数:self=当前光源实体,t=当前时间(秒) if (t % 2.0 < 1.0) { self.intensity = 5.0; } else { self.intensity = 1.0; } }

注意:函数名必须与script字段完全一致(大小写敏感);self.intensity是 Dark Engine 光源的内置属性,不能自定义。插件不生成脚本函数,只负责挂载引用——脚本逻辑需手写。

4.4 现象:导出.bin后scene.bin.meta中vertex_count为 0,或数值远小于预期

原因:Object 的 Mesh Data Block 未被正确识别。常见于使用了「Mesh to Points」、「Geometry Nodes」生成的几何体,或 Modifier(如 Array、Mirror)未应用。DarkGeometryExporter只读取obj.data的原始顶点,不计算 Modifier 栈。
解决:导出前,选中所有 Mesh Object → 右键 → 「应用 → 视觉化几何」(Ctrl+A → Visual Geometry),确保 Modifier 生效;或进入编辑模式,全选顶点 → M → Merge by Distance(消除重复顶点,BSP.exe 对重合顶点敏感)。

4.5 现象:BSP.exe 报FATAL: failed to open BSP.exe或Access is denied

原因:Windows 系统安全策略阻止未签名的BSP.exe运行,或杀毒软件将其误判为风险程序。
解决:

  • 右键BSP.exe→ 属性 → 勾选「解除锁定」(Unblock);
  • 临时关闭杀毒软件实时防护;
  • 以管理员身份运行 Blender(右键 Blender 快捷方式 → 以管理员身份运行),确保subprocess.run()有权限调用外部 EXE;
  • 若仍失败,改用 PowerShell 手动执行BSP.exe命令测试,确认其本身可运行。

5. 进阶技巧:批量导出多场景 + 自动化 BSP 编译脚本(Python + subprocess)

5.1 批量导出:用 Blender Python Console 一键导出整个项目所有 Collection

当项目包含Dungeon_Floor、Dungeon_Walls、Dungeon_Ceiling多个 Collection 时,手动切换导出效率极低。可在 Blender Python Console(Shift+F4)中粘贴执行以下脚本,自动遍历所有 Collection 并导出对应.e/.bin:

import bpy import os # 设置项目根目录(必须存在 textures/ 文件夹) project_root = r"D:\my-dark-project" bsp_exe_path = r"C:\dark-tools\BSP.exe" # 遍历所有 Collection for collection in bpy.data.collections: if not collection.name.startswith("Dark_"): # 只处理 Dark_ 开头的 Collection continue print(f"Processing collection: {collection.name}") # 激活该 Collection bpy.context.view_layer.active_layer_collection = \ bpy.context.view_layer.layer_collection.children[collection.name] # 导出 .e e_path = os.path.join(project_root, f"{collection.name}.e") bpy.ops.export_scene.dark_entities(filepath=e_path) # 导出 .bin bin_path = os.path.join(project_root, f"{collection.name}.bin") bpy.ops.export_scene.dark_geometry(filepath=bin_path) # 调用 BSP.exe 编译 result = bpy.app.timers.register( lambda: subprocess.run([bsp_exe_path, "-compile", e_path, bin_path], cwd=project_root, capture_output=True), first_interval=0.1 )

逻辑说明:脚本利用bpy.ops.export_scene.*调用插件 Operator,避免 UI 交互;bpy.app.timers.register()延迟执行subprocess.run(),防止 Blender 主线程阻塞;cwd=project_root确保 BSP.exe 在正确路径下查找textures/。注意:subprocess需在脚本开头import subprocess。

5.2 自动化 BSP 编译:用独立 Python 脚本监控文件变更并触发编译

脱离 Blender,用外部脚本监听.e/.bin修改,自动编译。创建auto_compile.py:

import time import subprocess import os from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class BSPCompiler(FileSystemEventHandler): def __init__(self, bsp_exe, project_dir): self.bsp_exe = bsp_exe self.project_dir = project_dir self.last_compile = 0 def on_modified(self, event): if event.is_directory: return if event.src_path.endswith(('.e', '.bin')): # 防抖:1秒内多次修改只触发一次编译 if time.time() - self.last_compile < 1.0: return self.last_compile = time.time() # 提取文件名(不含扩展名) base_name = os.path.splitext(os.path.basename(event.src_path))[0] e_path = os.path.join(self.project_dir, f"{base_name}.e") bin_path = os.path.join(self.project_dir, f"{base_name}.bin") bsp_path = os.path.join(self.project_dir, f"{base_name}.bsp") if os.path.exists(e_path) and os.path.exists(bin_path): print(f"[AutoCompile] Compiling {base_name}...") result = subprocess.run( [self.bsp_exe, "-compile", e_path, bin_path], cwd=self.project_dir, capture_output=True, text=True ) if result.returncode == 0: print(f"[Success] {base_name}.bsp updated") else: print(f"[Error] BSP.exe failed: {result.stderr}") # 使用示例 if __name__ == "__main__": observer = Observer() handler = BSPCompiler( bsp_exe=r"C:\dark-tools\BSP.exe", project_dir=r"D:\my-dark-project" ) observer.schedule(handler, path=r"D:\my-dark-project", recursive=False) observer.start() print("BSP Auto-Compiler started. Press Ctrl+C to exit.") try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()

依赖安装:pip install watchdog。此脚本启动后,只要D:\my-dark-project\下任一.e或.bin文件被保存,就会自动触发BSP.exe -compile。它解决了 Blender 导出后还需手动切窗口运行命令的割裂感,让 Dark Engine 资源管线真正接近现代开发体验。

5.3 关键参数表:BSP.exe 常用命令与作用域说明

命令参数示例作用域说明
-compileBSP.exe -compile scene.e scene.bin全局主编译命令,生成.bsp;要求.e与.bin同名且同目录
-binBSP.exe -bin model.obj model.bin几何专用将 OBJ/PLY 等格式转.bin,本 Toolkit 不调用此命令(自行生成.bin)
-texconvBSP.exe -texconv textures/brick.png纹理专用单独转换贴图,生成.pal/.raw;调试纹理问题时可用
-verboseBSP.exe -compile -verbose scene.e scene.bin全局输出详细日志,包括每个实体解析步骤,排错必备
-outputBSP.exe -compile -output mylevel.bsp scene.e scene.bin全局指定输出.bsp文件名,默认为scene.bsp

提示:-verbose是玄学问题的后悔药。当 BSP.exe 静默失败时,加上它,90% 的问题能从日志中定位到具体哪一行.e语法错误或哪个.bin数据越界。

从那以后我每次搭建新 Dark Engine 项目,都会先跑一遍auto_compile.py,再开 Blender;导出前必 Ctrl+A 应用旋转和几何,写完.e必手动补function块——这些动作已刻进肌肉记忆。工具链的价值不在多炫酷,而在把「不确定」压到最低:你知道改哪行代码、动哪个参数、看哪条日志,就能让模型稳稳站在黑暗的走廊里,火把明明灭灭。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询