95cfe0aa93
- export_step_to_gltf.py: STEP→GLB via RWGltf_CafWriter + BRepBuilderAPI_Transform (mm→m pre-scaling, XCAFDoc_ShapeTool.GetComponents_s static method) - Blender scripts (blender_render.py, still_render.py, turntable_render.py, export_gltf.py, export_blend.py): import GLB instead of STL, remove _scale_mm_to_m - step_tasks.py: add generate_gltf_production_task, remove generate_stl_cache, replace _bbox_from_stl with _bbox_from_glb (trimesh), auto-queue geometry GLB after thumbnail render - render_blender.py: replace _stl_from_cache_or_convert with _glb_from_step, remove convert_step_to_stl and export_per_part_stls - domains/rendering/tasks.py: update render_turntable_task, export_gltf/blend tasks to use GLB instead of STL - cad.py: remove STL download/generate endpoints, add generate-gltf-production - admin.py: generate-missing-stls → generate-missing-geometry-glbs - Frontend: replace STL cache UI with GLB generate buttons, remove stl_cached field Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
"""Blender headless script: export a STEP-derived scene as a production GLB.
|
|
|
|
Usage:
|
|
blender --background --python export_gltf.py -- \\
|
|
--stl_path /path/to/file.stl \\
|
|
--output_path /path/to/output.glb \\
|
|
[--asset_library_blend /path/to/library.blend] \\
|
|
[--material_map '{"SrcMat": "LibMat"}']
|
|
|
|
The script:
|
|
1. Imports the STL file (with mm→m scale).
|
|
2. Optionally applies asset library materials from a .blend.
|
|
3. Exports as GLB (Draco-compressed if available, otherwise standard).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import traceback
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
argv = sys.argv
|
|
if "--" not in argv:
|
|
print("No arguments after --", file=sys.stderr)
|
|
sys.exit(1)
|
|
rest = argv[argv.index("--") + 1:]
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--glb_path", required=True,
|
|
help="Geometry GLB from export_step_to_gltf.py (already in metres)")
|
|
parser.add_argument("--output_path", required=True)
|
|
parser.add_argument("--asset_library_blend", default=None)
|
|
parser.add_argument("--material_map", default="{}")
|
|
return parser.parse_args(rest)
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
material_map: dict = json.loads(args.material_map)
|
|
|
|
import bpy # type: ignore[import]
|
|
import math as _math
|
|
|
|
# Clean scene
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
|
|
# Import geometry GLB from export_step_to_gltf.py (already in metres, Y-up)
|
|
bpy.ops.import_scene.gltf(filepath=args.glb_path)
|
|
print(f"Imported geometry GLB: {args.glb_path} "
|
|
f"({len([o for o in bpy.data.objects if o.type == 'MESH'])} mesh objects)")
|
|
|
|
# Apply smooth shading with 30° angle threshold (Blender 4.1+ API)
|
|
for obj in bpy.data.objects:
|
|
if obj.type == "MESH":
|
|
bpy.context.view_layer.objects.active = obj
|
|
obj.select_set(True)
|
|
try:
|
|
bpy.ops.object.shade_smooth_by_angle(angle=_math.radians(30))
|
|
except Exception:
|
|
pass
|
|
|
|
# Apply asset library materials if provided.
|
|
# link=False (append) is required: the GLTF exporter can only traverse
|
|
# local (appended) Principled BSDF node trees to extract PBR values.
|
|
if args.asset_library_blend and material_map:
|
|
import os
|
|
sys.path.insert(0, os.path.dirname(__file__))
|
|
from asset_library import apply_asset_library_materials
|
|
apply_asset_library_materials(args.asset_library_blend, material_map, link=False)
|
|
|
|
# Export production GLB with full PBR material data
|
|
try:
|
|
bpy.ops.export_scene.gltf(
|
|
filepath=args.output_path,
|
|
export_format="GLB",
|
|
export_apply=True,
|
|
use_selection=False,
|
|
export_materials="EXPORT",
|
|
export_image_format="AUTO",
|
|
)
|
|
except Exception as exc:
|
|
print(f"GLB export failed: {exc}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print(f"Production GLB exported to {args.output_path}")
|
|
|
|
|
|
try:
|
|
main()
|
|
except SystemExit:
|
|
raise
|
|
except Exception:
|
|
traceback.print_exc()
|
|
sys.exit(1)
|