简介:这是一套专为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语义脱钩:
- 建模与标注阶段:在 Blender 中用 Collection 分组管理场景单元(如
WALLS、LIGHTS、TRIGGERS),为每个 Object 添加自定义属性dark_type(值为wall/light/trigger)、dark_flags(整数位掩码,控制碰撞/可见性)、dark_script(绑定.e中的脚本函数名); - 导出
.e文件阶段:运行插件「Export Dark Entities」,生成纯文本.e文件,内含所有 Object 的位置、旋转、缩放、类型、标志位、脚本引用,以及图像路径(如textures/brick.png); - 导出
.bin文件阶段:运行「Export Dark Geometry」,调用BSP.exe -bin命令,将当前 Collection 下所有 Mesh Object 的顶点/面数据序列化为二进制.bin,同时生成.bin.meta描述文件(含 AABB 包围盒、材质索引偏移); - 合成 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 常用命令与作用域说明
| 命令 | 参数示例 | 作用域 | 说明 |
|---|---|---|---|
-compile | BSP.exe -compile scene.e scene.bin | 全局 | 主编译命令,生成.bsp;要求.e与.bin同名且同目录 |
-bin | BSP.exe -bin model.obj model.bin | 几何专用 | 将 OBJ/PLY 等格式转.bin,本 Toolkit 不调用此命令(自行生成.bin) |
-texconv | BSP.exe -texconv textures/brick.png | 纹理专用 | 单独转换贴图,生成.pal/.raw;调试纹理问题时可用 |
-verbose | BSP.exe -compile -verbose scene.e scene.bin | 全局 | 输出详细日志,包括每个实体解析步骤,排错必备 |
-output | BSP.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块——这些动作已刻进肌肉记忆。工具链的价值不在多炫酷,而在把「不确定」压到最低:你知道改哪行代码、动哪个参数、看哪条日志,就能让模型稳稳站在黑暗的走廊里,火把明明灭灭。希望帮到你。
本文还有配套的精品资源,点击获取