
简介这是一套专为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 工具链开发、或需要把现代建模流程接入老引擎管线的 PythonBlender 双栈开发者。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分组写入.binwall类型写顶点法线UVlight类型只写位置半径无几何生成.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-Endianfff表示三个 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.exeWindows或/opt/dark-tools/BSPLinux/macOS插件内部会自动拼接命令subprocess.run([bsp_path, -compile, scene.e, scene.bin])。注意BSP.exe 无 GUI所有错误均输出到 Blender 系统控制台CtrlShiftC 打开。若编译失败第一反应不是改 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 ColorPrincipled BSDF连接至Material Output选中Wall_01在 Object Properties → Custom Properties 面板点击添加dark_type字符串类型值填walldark_flags整数类型值填1表示启用碰撞添加一个 Ico Sphere重命名为Torch_01缩放为(0.1, 0.1, 0.1)移至墙面上方新建材质Mat_Torch仅用 Emission 节点Color 白色Strength 5.0为Torch_01添加 Custom Propertiesdark_type字符串值lightdark_flags整数值8表示动态光源dark_script字符串值flicker_torch后续需在.e中定义该函数。提示dark_flags是位掩码常见值1碰撞体2不可见4触发器8动态光源。多个标志用按位或如1|89表示“有碰撞的动态光源”。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_count0是正确的——light类型不导出几何只导出位置其数据写在.e中而非.bin。3.4 手动运行 BSP.exe 编译合成最终.bsp文件打开系统终端CMD/PowerShell/Terminalcd 到项目目录cd D:\my-dark-project\执行编译命令假设 BSP.exe 在C:\dark-tools\BSP.exeC:\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 → 右键 → 「应用 → 旋转」CtrlA → 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 → 右键 → 「应用 → 视觉化几何」CtrlA → 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 subprocess5.1 批量导出用 Blender Python Console 一键导出整个项目所有 Collection当项目包含Dungeon_Floor、Dungeon_Walls、Dungeon_Ceiling多个 Collection 时手动切换导出效率极低。可在 Blender Python ConsoleShiftF4中粘贴执行以下脚本自动遍历所有 Collection 并导出对应.e/.binimport bpy import os # 设置项目根目录必须存在 textures/ 文件夹 project_root rD:\my-dark-project bsp_exe_path rC:\dark-tools\BSP.exe # 遍历所有 Collection for collection in bpy.data.collections: if not collection.name.startswith(Dark_): # 只处理 Dark_ 开头的 Collection continue print(fProcessing 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(filepathe_path) # 导出 .bin bin_path os.path.join(project_root, f{collection.name}.bin) bpy.ops.export_scene.dark_geometry(filepathbin_path) # 调用 BSP.exe 编译 result bpy.app.timers.register( lambda: subprocess.run([bsp_exe_path, -compile, e_path, bin_path], cwdproject_root, capture_outputTrue), first_interval0.1 )逻辑说明脚本利用bpy.ops.export_scene.*调用插件 Operator避免 UI 交互bpy.app.timers.register()延迟执行subprocess.run()防止 Blender 主线程阻塞cwdproject_root确保 BSP.exe 在正确路径下查找textures/。注意subprocess需在脚本开头import subprocess。5.2 自动化 BSP 编译用独立 Python 脚本监控文件变更并触发编译脱离 Blender用外部脚本监听.e/.bin修改自动编译。创建auto_compile.pyimport 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], cwdself.project_dir, capture_outputTrue, textTrue ) 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_exerC:\dark-tools\BSP.exe, project_dirrD:\my-dark-project ) observer.schedule(handler, pathrD:\my-dark-project, recursiveFalse) observer.start() print(BSP Auto-Compiler started. Press CtrlC 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导出前必 CtrlA 应用旋转和几何写完.e必手动补function块——这些动作已刻进肌肉记忆。工具链的价值不在多炫酷而在把「不确定」压到最低你知道改哪行代码、动哪个参数、看哪条日志就能让模型稳稳站在黑暗的走廊里火把明明灭灭。希望帮到你。本文还有配套的精品资源点击获取