84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
import argparse
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
BLENDER = "/Applications/Blender.app/Contents/MacOS/Blender"
|
|
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--input", required=True)
|
|
ap.add_argument("--outdir", required=True)
|
|
ap.add_argument("--params", default="{}")
|
|
args = ap.parse_args()
|
|
p = json.loads(args.params)
|
|
|
|
target = p.get("target", "glb")
|
|
outdir = Path(args.outdir)
|
|
out_name = Path(args.input).stem + "." + target
|
|
out_path = outdir / out_name
|
|
|
|
bpy_script = outdir / "_convert.py"
|
|
bpy_script.write_text(f"""
|
|
import bpy, json, sys
|
|
src = {json.dumps(args.input)}
|
|
dst = {json.dumps(str(out_path))}
|
|
params = json.loads({json.dumps(json.dumps(p))})
|
|
ext = src.rsplit('.', 1)[-1].lower()
|
|
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
importers = {{
|
|
'glb': lambda: bpy.ops.import_scene.gltf(filepath=src),
|
|
'gltf': lambda: bpy.ops.import_scene.gltf(filepath=src),
|
|
'obj': lambda: bpy.ops.wm.obj_import(filepath=src),
|
|
'fbx': lambda: bpy.ops.import_scene.fbx(filepath=src),
|
|
'stl': lambda: bpy.ops.wm.stl_import(filepath=src),
|
|
'ply': lambda: bpy.ops.wm.ply_import(filepath=src),
|
|
'usd': lambda: bpy.ops.wm.usd_import(filepath=src),
|
|
'usdz': lambda: bpy.ops.wm.usd_import(filepath=src),
|
|
'usda': lambda: bpy.ops.wm.usd_import(filepath=src),
|
|
'dae': lambda: bpy.ops.wm.collada_import(filepath=src),
|
|
'abc': lambda: bpy.ops.wm.alembic_import(filepath=src),
|
|
}}
|
|
if ext == 'blend':
|
|
bpy.ops.wm.open_mainfile(filepath=src)
|
|
else:
|
|
importers[ext]()
|
|
|
|
scale = params.get('scale', 1.0)
|
|
if scale != 1.0:
|
|
for ob in bpy.context.scene.objects:
|
|
ob.scale = [s * scale for s in ob.scale]
|
|
if params.get('apply_transforms', True):
|
|
for ob in bpy.context.scene.objects:
|
|
ob.select_set(True)
|
|
if bpy.context.scene.objects:
|
|
bpy.context.view_layer.objects.active = bpy.context.scene.objects[0]
|
|
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
|
|
|
tgt = dst.rsplit('.', 1)[-1].lower()
|
|
exporters = {{
|
|
'glb': lambda: bpy.ops.export_scene.gltf(filepath=dst, export_format='GLB'),
|
|
'fbx': lambda: bpy.ops.export_scene.fbx(filepath=dst),
|
|
'obj': lambda: bpy.ops.wm.obj_export(filepath=dst),
|
|
'stl': lambda: bpy.ops.wm.stl_export(filepath=dst),
|
|
'ply': lambda: bpy.ops.wm.ply_export(filepath=dst),
|
|
'usd': lambda: bpy.ops.wm.usd_export(filepath=dst),
|
|
'usdz': lambda: bpy.ops.wm.usd_export(filepath=dst),
|
|
'blend': lambda: bpy.ops.wm.save_as_mainfile(filepath=dst),
|
|
}}
|
|
exporters[tgt]()
|
|
print('exported', dst)
|
|
""")
|
|
|
|
cmd = [BLENDER, "-b", "--python", str(bpy_script)]
|
|
print("+", " ".join(cmd), flush=True)
|
|
res = subprocess.run(cmd, stdout=sys.stdout, stderr=subprocess.STDOUT)
|
|
bpy_script.unlink(missing_ok=True)
|
|
if res.returncode != 0 or not out_path.exists():
|
|
sys.exit(res.returncode or 1)
|
|
|
|
(outdir / "result.json").write_text(json.dumps(
|
|
{"outputs": [{"path": out_name}]}))
|
|
print("done", flush=True)
|