Rewrite _traverse_xcaf → _author_xcaf_to_usd that recursively authors
USD prims mirroring the XCAF assembly tree:
- Assembly nodes become UsdGeom.Xform prims with local transforms from
each component label's Location (not composed with parents)
- Leaf shapes get definition-space vertices (face_loc only, no instance
placement) — the USD scene graph composes transforms hierarchically
- Coordinate swap (X,-Z,Y) now authored once as a root Xform on
/Root/Assembly instead of per-vertex transformation
- Sharp/seam edges extracted per-part from definition shape (not global)
This fixes misplaced geometry for sub-assembly parts (e.g. KOMP-EIN
roller cages with -45° Z rotation) that were previously lost by the
flat traversal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Material prims now use resolved canonical names (e.g.
SCHAEFFLER_010101_Steel_Bare) instead of source object names. When
importing USD in Blender, materials show the correct SCHAEFFLER names
directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- export_step_to_usd.py: change stage from Y-up to Z-up, keep (X,-Z,Y)
transform — matches GLB orientation exactly (verified: bounding box match)
- export_glb.py: include canonical_material in resolved_material_assignments
DB field (was being dropped during manifest parsing)
- import_usd.py: use pxr customData read (not string primvars — Blender
ignores those, confirmed by testing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- export_step_to_usd.py: accept --material_map CLI arg, write
schaeffler:canonicalMaterialName as customData on each Mesh prim,
fix geometry transform (strip shape Location before face exploration,
apply both face_loc and shape_loc sequentially)
- import_usd.py: after Blender USD import, use pxr to read customData
directly from the USD file — builds {part_key: material_name} lookup
(Blender ignores STRING primvars and customData, but pxr reads both)
- _blender_materials.py: add apply_material_library_direct() for exact
dict-based material assignment without name-matching heuristics
- _blender_scene_setup.py: prefer direct USD lookup, fall back to
name-matching for legacy USD files without material metadata
- export_glb.py (generate_usd_master_task): resolve material_map via
material_service.resolve_material_map() and pass to subprocess;
include material hash in cache key for invalidation
- ROADMAP.md: update P5 status, add M5-M7 milestones
Tested: 3/3 parts matched (ans_lfs120), 172/175 parts matched
(F-802007.TR4-D1-H122AG). Previous: 0/25 matched.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The queue handles far more than thumbnails: OCC tessellation, USD master
generation, GLB production, order line renders, and workflow renders.
asset_pipeline better reflects its role as the render-worker's primary queue.
Updated all references in: task decorators, celery_app.py, beat_tasks.py,
docker-compose.yml worker command, worker.py MONITORED_QUEUES, admin.py,
CLAUDE.md, LEARNINGS.md, Dockerfile, helpTexts.ts, test files,
and all .claude/commands/*.md skill files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In _extract_mesh(), BRep_Tool.Triangulation_s(face, face_loc) returns a face_loc
that already encodes the instance's full placement transform when a compound shape
is tessellated with BRepMesh_IncrementalMesh. Applying shape_trsf on top doubled
every rotation/translation, causing multiple roller elements to collapse to the same
wrong world position (e.g. Z(-75°)×2 ≡ Z(+105°)×2 mod 360° → identical positions).
Fix: use elif so shape_loc is only applied as a fallback when face_loc is identity.
Adds seam edge extraction (UV seam primvar) and improves _traverse_xcaf doc.
docs: learning erfasst - OCC face_loc double-transform in compound tessellation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>