# [ADR-cad-0001] STEP 임포트 전략: Blender 자동화 사전 컨버팅

작성: 2026-05-07
상태: ✅ 확정
관련: `architecture/0001-product-vision.md` R1·R2 리스크

## 결정

STEP 파일을 Unity에 직접 임포트하지 않는다. **factory00 자체 컨버터 도구**가 **Mayo CLI(OCCT 기반 컨버터) + Blender headless(메시 정리·LOD)** 2단계 파이프라인을 subprocess로 호출한다. 사용자에겐 두 도구 모두 보이지 않는다.

```
[사용자] 드래그앤드롭 .step
   ↓
[factory00-converter (GUI)]
   ↓ subprocess
[mayo-conv.exe — BSD 2-Clause / OCCT(LGPL) 동적 링크]
   ↓ glTF 1차 (어셈블리 계층 보존)
   ↓ subprocess
[Blender headless 4.2.20 LTS — GPL]
   ↓ Python 스크립트 (데시메이션 / LOD / 내부 부품 제거 / 재export)
   ↓
[.factory.glb 최종 출력]
   ↓
[factory00 메인 앱이 glTF 임포트]
```

**Mayo만으로 끝나는 fast path도 허용** — 메시 품질·크기가 충족되면 Blender 단계 스킵 (옵션).

### Import-CAD-Model 애드온 우회 사유 (2026-05-07 평가)

`chenpaner/Import-CAD-Model` 평가 결과 **이 애드온은 Mayo CLI의 Blender 래퍼**일 뿐이며 **GPL v3 라이선스**다. 우리가 직접 Mayo CLI를 호출하면:
1. GPL 감염 회피 (Import-CAD-Model을 우리 도구에 포함하지 않음)
2. 변환 단계 디버깅 쉬움 (Blender 외부에서 Mayo만 단독 실행 가능)
3. Mayo의 BSD 2-Clause로 우리 도구 어떤 라이선스든 호환

## 핵심 원칙

| # | 원칙 |
|---|---|
| 1 | **Unity 메인 앱은 glTF/glb만 받는다.** STEP 직접 임포트 금지. |
| 2 | **사용자는 Blender를 모른다.** 컨버터는 GUI, Blender는 내부적으로 spawn. |
| 3 | **Blender는 별도 프로세스(subprocess)로 호출**한다. 메인 앱에 임베드 금지 (Blender GPL 감염 회피). |
| 4 | **고급 사용자는 컨버터 우회 가능**. glTF 표준만 맞으면 외부 변환 도구 결과물도 메인 앱이 받음. |

## "커스텀 가능"의 정의 (사용자 결정 2026-05-07)

= **임포트 후 시뮬레이터 내부에서 메시 단위 조작**.

ADR-0001에서 "커스텀 가능" 의미를 4가지 후보 중 사용자가 **3번**(임포트 후 메시 커스텀)으로 확정:

- 사용자가 임포트한 어셈블리의 특정 부품을 **다른 메시로 교체** 가능
- 부품을 **재배치**(translate/rotate/scale) 가능
- 부품 단위 **분리·재결합** 가능
- (= 임포트 파라미터 커스텀이 아님 → 컨버터 도구는 **자동 모드**가 디폴트, 사용자 노출 최소화)

## 채택하지 않은 대안

### A. STEP 직접 임포트 (UnitySTEPImporter, CADLink, Asset Transformer)

**기각 사유:**
- 산업 어셈블리 STEP는 100만~1000만 트라이앵글 흔함 → Unity 30fps 깨짐
- tessellation 파라미터를 라이브러리가 결정 → 메시 품질 일관성 불가
- 내부 부품(베어링 내륜, 볼트 머리 곡면) 제거 불가
- LOD 자동 생성 어려움
- CADLink는 Editor 전용이라 사용자 빌드 임포트 불가
- Asset Transformer는 $1,350/seat/년 (솔로 부담)
- UnitySTEPImporter는 LGPL 가능하나 폴리곤 폭증 문제 동일

→ P2 응급 fallback으로만 보존: "변환 못 할 때 일단 보고 싶다" 시나리오 한정.

### B. 사용자가 직접 Blender로 변환

**기각 사유 (사용자 결정 2026-05-07):**
- 타겟 사용자(설비 설계자·자동화 엔지니어)는 Blender 모름
- 자동화가 필수 → 우리가 컨버터 도구로 Blender 사용을 숨겨야 함

### C. Blender Python(bpy) 모듈 임베드

**기각 사유:**
- Blender GPL → bpy 임베드 시 메인 앱 GPL 감염 위험
- bpy 모듈 ~수백 MB, Python 런타임 의존 추가
- subprocess CLI 호출이 라이선스·격리 양면에서 안전

## 채택안 상세

### factory00-converter 도구 명세

- **위치**: factory00 메인 앱과 분리된 도구 (별도 exe 또는 메인 앱이 spawn)
- **UI**: GUI (드래그앤드롭 + 진행률 표시 + 결과 미리보기)
- **백엔드**: Blender 4.x portable 번들 + Python 스크립트
- **자동 처리**:
  1. STEP 임포트 (STEPper 애드온 또는 Blender 4.x 내장 STEP 임포터 — 검증 필요)
  2. 어셈블리 계층 보존 (Outliner 트리 → glTF nodes)
  3. 데시메이션 (트라이 수 임계값 기반 자동 — 예: 부품당 5000트라이 초과 시 LOD 생성)
  4. 내부 부품 자동 제거 (옵션, 가시성 분석 기반)
  5. 단위 통일 (mm)
  6. glTF 2.0 익스포트 (`.glb` 권장 — 단일 파일)
- **JSON 프리셋**: 데시메이션 비율·LOD 단계는 JSON 프리셋으로 저장. GUI에서 프리셋 선택 (Low/Medium/High 같은 단순 노출). 전문가는 JSON 직접 편집 가능 (= 노출은 최소, 가능성은 열어둠).

### 메시 커스텀 (Q1=3번 답에 따른 메인 앱 기능)

factory00 메인 앱은 임포트 후:
- 부품 트리 뷰 → 클릭 시 해당 부품 메시 선택
- 우클릭 메뉴: "메시 교체 (다른 .glb 임포트)", "재배치", "분리", "삭제"
- 재배치는 transform gizmo로 직접 조작 (Unity 표준)
- 분리: 한 메시를 여러 부품으로 쪼개는 건 MVP 제외 (Blender에서 미리 분리)

## 라이선스 포지션

| 컴포넌트 | 라이선스 | 배포 형태 | 우리 코드 영향 |
|---|---|---|---|
| factory00 메인 앱 | (PoC 후 결정) | exe 단독 | — |
| factory00-converter | (PoC 후 결정) | exe 단독 또는 메인 앱 통합 | — |
| **Mayo (mayo-conv.exe)** | **BSD 2-Clause** | `Tools/mayo/` 번들, subprocess 호출 | LICENSE 동봉만 의무. 어떤 라이선스와도 호환 |
| Mayo 의존 — OCCT | LGPL 2.1 | Mayo가 동적 링크하여 포함 | Mayo subprocess 격리로 우리 코드에 무영향 |
| Mayo 의존 — Qt5 | LGPL v3 | Mayo가 동적 링크 | 동상 |
| Blender 4.2.20 LTS | GPL v2/v3 | `Tools/blender-portable/` 번들, subprocess 호출 | GPL 감염 X (별도 프로세스, FSF 공식 입장) |
| 우리 Blender Python 스크립트 | (선택) | `Tools/blender-portable/scripts/` | Blender 외부에서 단독 실행 안 하므로 영향 거의 없음 |

→ **Mayo의 BSD 2-Clause + Blender 별도 프로세스 호출** 조합으로 factory00 본체 라이선스를 어떤 옵션(상용/BSL/Open-Core/Open)으로 가도 호환되도록 격리 완료.

## PoC 통과 기준 (다음 작업)

다음 세션에서 본 ADR 기반 PoC 수행. 통과 기준:

| # | 항목 | 측정 |
|---|---|---|
| 1 | Blender headless에서 STEP 임포트 가능 | 5단계 부모-자식 샘플 STEP 정상 로드 |
| 2 | 어셈블리 계층 보존 | Outliner 트리 5단계 그대로 보존 → glTF nodes에 반영 |
| 3 | 자동 데시메이션 동작 | 부품당 트라이 수가 임계값 이하로 감소, 형상 충실도 육안 OK |
| 4 | glTF export 후 Unity 임포트 | Unity glTFast 또는 UnityGLTF로 정상 로드, 트리 보존 |
| 5 | 변환 시간 | 어셈블리 100MB 기준 1분 이내 |
| 6 | 사용자 워크플로우 자동화 | CLI 한 줄: `blender --background --python convert.py -- input.step output.glb` |

## 후속 결정 대기

- Blender 4.x 내장 STEP 임포터 vs STEPper 애드온 (둘 다 검증 후 비교)
- factory00-converter UI 프레임워크 (Unity로 만들 것인가, .NET WinForms/WPF로 별도, Avalonia 등)
- Blender portable 번들 시 배포 크기 (~수백 MB) 감수 가부
- 메인 앱 자체 라이선스 결정 (상용/오픈/듀얼)
