# -*- coding: utf-8 -*- """ 批量转换:把 catalog\step\ 下所有 STEP 转成 glTF/GLB(网页 3D 轻量化用)。 用法: python batch-convert-glb.py [deflection] 说明: - 走本地 OCCT 服务的 /convert 接口(需先启动 occt_service.py) - 同名 .step → .glb,断点续传(已存在且非空的 .glb 跳过) - 单线程、逐文件,避免给服务造成压力 - 默认 deflection=0.5(屏幕预览够用) """ import os import sys import time import urllib.request OCCT_URL = os.environ.get("OCCT_URL", "http://localhost:8090") def convert_one(step_path, glb_path, deflection): with open(step_path, "rb") as f: data = f.read() req = urllib.request.Request( "%s/convert?deflection=%s" % (OCCT_URL, deflection), data=data, method="POST", headers={"Content-Type": "application/octet-stream"}, ) resp = urllib.request.urlopen(req, timeout=120) out = resp.read() if not out or out[:4] != b"glTF": raise RuntimeError("转换失败(非法 glb): %s" % step_path) # 原子写:先写临时再改名 tmp = glb_path + ".tmp" with open(tmp, "wb") as f: f.write(out) os.replace(tmp, glb_path) def main(): if len(sys.argv) < 3: print("用法: python batch-convert-glb.py [deflection]") sys.exit(1) step_dir = sys.argv[1] out_dir = sys.argv[2] deflection = float(sys.argv[3]) if len(sys.argv) > 3 else 0.5 os.makedirs(out_dir, exist_ok=True) steps = [] for root, _, files in os.walk(step_dir): for fn in files: if fn.lower().endswith((".step", ".stp")): steps.append(os.path.join(root, fn)) steps.sort() ok = 0 skip = 0 fail = 0 t0 = time.time() for i, sp in enumerate(steps): base = os.path.splitext(os.path.basename(sp))[0] gp = os.path.join(out_dir, base + ".glb") if os.path.exists(gp) and os.path.getsize(gp) > 0: skip += 1 continue try: convert_one(sp, gp, deflection) ok += 1 if (ok + skip) % 50 == 0: print("[%d/%d] ok=%d skip=%d fail=%d %.1fs" % (i + 1, len(steps), ok, skip, fail, time.time() - t0)) except Exception as e: fail += 1 print("[FAIL] %s: %s" % (os.path.basename(sp), e)) print("完成: 总 %d, 转换 %d, 跳过 %d, 失败 %d, 耗时 %.1fs" % (len(steps), ok, skip, fail, time.time() - t0)) if fail: sys.exit(2) if __name__ == "__main__": main()