feat(D): OCC mesh attribute extraction + Blender smooth shading integration
Migration 039: cad_files.mesh_attributes JSONB column. domains/products/tasks.py: extract_mesh_attributes Celery task using pythonOCC. still_render.py + turntable_render.py: _apply_mesh_attributes() sets auto-smooth based on curved_ratio and topology threshold from OCC analysis. render_blender.py: passes --mesh-attributes JSON arg to Blender subprocess. render_still_task: loads mesh_attributes from DB and passes to renderer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -157,6 +157,28 @@ def _scale_mm_to_m(parts):
|
||||
print(f"[turntable_render] scaled {len(parts)} parts mm→m (×0.001)")
|
||||
|
||||
|
||||
def _apply_mesh_attributes(objects: list, mesh_attributes: dict) -> None:
|
||||
"""Apply topology-based shading settings from OCC analysis."""
|
||||
import math
|
||||
if not mesh_attributes or mesh_attributes.get("error"):
|
||||
return
|
||||
|
||||
curved_ratio = mesh_attributes.get("curved_ratio", 0.0)
|
||||
threshold_deg = mesh_attributes.get("sharp_angle_threshold_deg", 30.0)
|
||||
threshold_rad = threshold_deg * math.pi / 180.0
|
||||
|
||||
for obj in objects:
|
||||
if obj.type != 'MESH':
|
||||
continue
|
||||
# Enable smooth shading for predominantly curved parts (bearings etc.)
|
||||
if curved_ratio > 0.3:
|
||||
for poly in obj.data.polygons:
|
||||
poly.use_smooth = True
|
||||
# Auto-smooth at topology threshold
|
||||
obj.data.use_auto_smooth = True
|
||||
obj.data.auto_smooth_angle = threshold_rad
|
||||
|
||||
|
||||
def _import_stl(stl_file):
|
||||
"""Import STL into Blender, using per-part STLs if available.
|
||||
|
||||
@@ -351,6 +373,15 @@ def main():
|
||||
bg_color = args[21] if len(args) > 21 else ""
|
||||
transparent_bg = args[22] == "1" if len(args) > 22 else False
|
||||
|
||||
# Named argument: --mesh-attributes <json>
|
||||
_mesh_attrs: dict = {}
|
||||
if "--mesh-attributes" in argv:
|
||||
_idx = argv.index("--mesh-attributes")
|
||||
try:
|
||||
_mesh_attrs = json.loads(argv[_idx + 1])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
os.makedirs(frames_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
@@ -402,6 +433,8 @@ def main():
|
||||
_scale_mm_to_m(parts)
|
||||
# Apply render position rotation before material/camera setup
|
||||
_apply_rotation(parts, rotation_x, rotation_y, rotation_z)
|
||||
# Apply OCC topology-based shading overrides
|
||||
_apply_mesh_attributes(parts, _mesh_attrs)
|
||||
|
||||
# Move imported parts into target collection
|
||||
for part in parts:
|
||||
@@ -480,6 +513,8 @@ def main():
|
||||
_scale_mm_to_m(parts)
|
||||
# Apply render position rotation before material/camera setup
|
||||
_apply_rotation(parts, rotation_x, rotation_y, rotation_z)
|
||||
# Apply OCC topology-based shading overrides
|
||||
_apply_mesh_attributes(parts, _mesh_attrs)
|
||||
|
||||
for i, part in enumerate(parts):
|
||||
_apply_smooth(part, SMOOTH_ANGLE)
|
||||
|
||||
Reference in New Issue
Block a user