# 스킨 팩토리 (skin-factory.com)

> GetAmped(겟앰프드) 스킨을 브라우저의 편집기에서 만들어 내려받거나 공유 게시판에 올리는 개인 운영 팬 사이트입니다. 스킨 제작은 로그인한 계정의 편집기에서만 하고, AI는 그 사람의 ChatGPT·Codex·Claude 같은 비서가 브라우저로 편집기를 조작하는 방식으로 씁니다. 이 사이트가 AI를 부르지는 않습니다.

## 페이지

- [스킨 만들기](https://skin-factory.com/studio): 내 캐릭터 목록, 새 캐릭터 만들기(파츠 고르기), 편집기 열기
- [스킨 편집기](https://skin-factory.com/studio/editor/<id>): 한 작업. `?mode=ai` 는 AI 편집 배치
- [AI로 편집기 조작하기](https://skin-factory.com/guide/ai-editing): ChatGPT·Codex 브라우저를 연결하는 방법
- [스킨 편집기 조작 설명서](https://skin-factory.com/guide/editor): 아래 설명서의 HTML판
- [긴 머리 종이 헤어카드 가이드](https://skin-factory.com/guide/hair-cards): 앞머리·옆머리·땋은 머리를 투명 종이카드로 만드는 방법(설명서 뒤에 전문)
- [공유 게시판](https://skin-factory.com/board), [자유게시판](https://skin-factory.com/free), [사이트 소개](https://skin-factory.com/about)

---

# 스킨 편집기 조작 설명서

> 스킨 팩토리의 스킨 편집기를 ChatGPT·Codex·Claude 같은 AI 비서가 브라우저로 조작할 때 알아야 할 것: 화면, 좌표계, 보기, 사이트 도구(WebMCP) 목록, 텍스처 규칙, 저장 규칙. 사람이 읽어도 같은 내용입니다.

편집기: https://skin-factory.com/studio/editor/<id>?mode=ai · 이 설명서(HTML): https://skin-factory.com/guide/editor · 연결 방법: https://skin-factory.com/guide/ai-editing · 긴 머리 종이 헤어카드: https://skin-factory.com/guide/hair-cards

## 1. 편집기가 하는 일

- 게임의 기본 파츠로 만든 캐릭터(작업)의 머리(head)·몸(body) 점을 옮기고, 세 부위(head·body·face)의 텍스처를 칠하거나 그림으로 바꿉니다. 얼굴 판(face)은 게임 공용 모양이라 옮길 수 없고 색과 그림만 바꿉니다.
- 작업은 `/studio/editor/<id>` 에서 열립니다. `?mode=ai` 를 붙이면 AI 편집 배치(원본·현재 3면 띠 + 상태 텍스트)가 되고, 두 배치는 같은 상태를 보여 줍니다.
- 편집은 로그인한 계정의 작업만 열립니다. AI가 쓰는 브라우저에 그 사람의 계정으로 로그인돼 있어야 하고, 주소만으로는 남의 작업이 열리지 않습니다.
- 조작 경로는 둘입니다. ① 화면의 패널·버튼(모두 이름이 붙어 있습니다) ② WebMCP 사이트 도구 `editor_*`(브라우저가 지원하면 페이지가 자동 등록). 둘 다 같은 엔진을 움직이므로 섞어 써도 됩니다.
- 캐릭터가 어떤 파츠로 만들어졌는지는 나중에도 바꿀 수 있습니다(「파츠」 패널 · `editor_parts`·`editor_change_parts`). 바꾸는 파츠는 원래 모습으로 들어오므로 그 파츠에 한 편집은 사라지고, 나머지 파츠의 편집은 남습니다.
- 게임이 받지 않는 파츠가 몇 가지 있어 목록에서 빼 두었습니다. 그 파츠로 만들어진 예전 캐릭터는 그대로 열리지만, 「파츠」 패널과 `editor_parts` 가 그 사실을 알려 주고, 바꾸지 않으면 게임에서 열리지 않습니다.
- 결과 파일은 사람이 [스킨 파일 받기]로 받습니다(게시판에 올릴지는 그때 고릅니다). AI는 저장까지만 합니다.

## 2. 좌표계와 이름

- 단위는 모델 좌표입니다. 캐릭터 키가 약 0.58이고, 모든 좌표는 |값| ≤ 4 안에 있어야 합니다(저장할 때 검사).
- 축: 위가 +y, 얼굴이 향하는 쪽이 −z, 정면에서 봤을 때 화면 오른쪽이 +x (캐릭터 자신의 왼손 쪽).
- 점은 「용접점」입니다: 같은 자리에 겹친 정점들을 한 점으로 묶은 것. id는 0부터 N−1이고 `editor_status`·`editor_points`·`editor_select`·`editor_set_points` 가 모두 이 id를 씁니다. 분리(`editor_separate`)로 나뉜 뒤에는 한 자리에 id가 둘 이상 있을 수 있습니다.
- 이름 붙은 대상: `head:piece:N`(이어진 머리 조각, N은 큰 조각부터 0), `body:slot:<이름>`(몸 부위, 예 `body:slot:body_part_3`), `face`(얼굴 판 전체). 목록은 `editor_targets` 또는 「선택」 패널에 있습니다.
- 몸 부위 가운데 `body_part_0`·`body_part_7` 과 `left_hand_1`·`right_hand_1`·`left_hand_2`·`right_hand_2` 는 손 모양(handPose 0·1·2)에 따라 하나씩만 보입니다.

## 3. 보기(카메라)

| 프리셋 | 이름 | 단축키 | yaw | pitch | 카메라 |
| --- | --- | --- | --- | --- | --- |
| `front` | 정면 | 1 | 0° | 0° | 얼굴 쪽(−z)에서 |
| `side` | 측면 | 2 | 90° | 0° | 정면 기준 화면 오른쪽(+x)에서 |
| `back` | 후면 | 3 | 180° | 0° | 뒤(+z)에서 |
| `quarter` | 대각 | 4 | 45° | 0° | 앞 오른쪽 45°에서 |
| `otherSide` | 반대 측면 | 5 | -90° | 0° | 정면 기준 화면 왼쪽(−x)에서 |
| `backQuarter` | 뒤 대각 | 6 | 135° | 0° | 뒤 오른쪽 45°에서 |
| `top` | 위 | 7 | 0° | -90° | 머리 위에서. 화면 아래쪽이 얼굴 쪽 |
| `bottom` | 아래 | 8 | 0° | 90° | 발 아래에서 |

- yaw는 캐릭터를 세로축으로 돌린 각(도)입니다. 양수면 카메라가 정면에서 화면 오른쪽으로 돕니다. pitch는 음수면 위에서 내려다보고 양수면 아래에서 올려다봅니다(±90°까지).
- zoom은 확대 배율입니다: 1 = 화면에 맞춤, 2 = 두 배 크게, 0.25~4. pan은 화면 평면에서 모델을 미는 양(모델 단위, 오른쪽·위가 양수)입니다.
- `editor_view` 로 프리셋·각도·확대·이동·표정(faceFrame 0~6: 기본·공격·피격 1·2·3·다운·승리)·손 모양(handPose 0~2)·원본 보기(showOriginal)를 바꿉니다. 화면에서는 「보기」 패널의 버튼과 숫자 필드, 마우스(오른쪽 버튼 드래그 회전, 휠 확대, Shift 드래그 이동)입니다.
- 「보기 → 얼굴 표시」 또는 `editor_face_visibility {visible: true|false}`로 얼굴을 켜고 끕니다. 동물형 헤어는 기본 꺼짐이며, 선택은 저장·버전 복원·다운로드에 반영됩니다. 꺼도 얼굴 그림은 지워지지 않습니다. 켜도 헤어의 불투명한 면에 가려진 부분은 그대로 가려집니다. 일부 동물형 헤어는 얼굴을 켜서 내보낼 때 선택한 게임 서버에서만 제대로 보입니다.
- 자세(pose): 기본은 `rest`, 곧 파일이 담고 있는 T포즈이고 편집은 여기에서만 합니다. `idle`(대기)·`walk`(걷기)·`run`(달리기)은 게임이 그 몸통에 실제로 쓰는 동작으로 캐릭터를 움직여 보는 **보기 전용** 자세입니다: 옷자락이 팔에 박히는지, 머리카락이 달릴 때 어떻게 보이는지 확인할 때 씁니다.
- 동작은 몸통이 정합니다. 대부분은 사람의 걸음이지만 동물 룩(고릴라·개·돼지·쥐·닭)은 게임에서 전용 동작을 써서 네발로 걷거나 날개를 펴고 걷습니다. 그 몸통을 골랐으면 여기에서도 그 동작이 나오고, `editor_status` 의 `view.poseMotion` 이 어느 룩의 동작인지 알려 줍니다.
- `editor_view {pose}` 로 고르면 게임 속도로 재생됩니다. `poseFrame` 을 주면 그 프레임에서 멈추고, `posePlay` 로 다시 재생·정지합니다. 프레임 번호는 게임 모션 파일의 번호라 몸통마다 다릅니다(사람은 대기 0~2·걷기 5~9·달리기 10~14). 지금 자세의 범위는 `editor_status` 의 `view.poseRange` 에 있습니다. 움직이는 자세에서는 화면을 끌어도 회전만 되고, 도구를 고르면 T포즈로 돌아옵니다. 좌표를 다루는 도구(`editor_set_points`·`editor_transform`)는 자세와 상관없이 언제나 T포즈 좌표로 움직입니다.
- AI 편집 배치의 3면 띠는 원본(열었을 때)과 현재를 나란히 그립니다. 세트는 둘입니다: `basic` = 정면·측면·후면, `angles` = 대각·반대 측면·위 (`editor_view {strip}` 또는 띠 위의 버튼).
- 어느 각도든 그림으로 보려면 `editor_capture` 입니다. 결과는 「보기」 패널의 「마지막 캡처」에 표시되고, `returnData: true` 면 PNG data URL도 돌려줍니다. `parts` 로 부위만 골라 그릴 수 있습니다.

## 4. 편집 흐름

1. `editor_status` 로 저장 상태·선택·보기를, `editor_targets` 로 조각·부위 목록을 읽습니다. 무엇을 고칠지는 사람이 적은 요청이 정합니다.
2. `editor_select` 로 대상을 고릅니다: `"all"`·`"none"`·이름·좌표 범위·점 id. mode는 replace·add·remove.
3. 옮깁니다: `editor_transform`(이동·회전·크기, pivot 기본은 선택 중심, falloff로 주변 점을 부드럽게) 또는 `editor_set_points`(점마다 절대 좌표). 얼굴 판은 옮길 수 없습니다.
4. 붙어 있던 면이 따라오면 `editor_separate`: 떼어낼 부분의 점을 모두 선택한 뒤 부르면 그 부분만 움직입니다. `editor_join` 은 나뉜 점을 선택한 점 자리로 다시 붙입니다.
5. 색은 `editor_recolor`(선택한 부위의 텍스처만), 그림 전체는 `editor_texture`(data:image URL 또는 https 주소), 지금 그림을 읽으려면 `editor_texture_read`.
6. 확인합니다: 3면 띠, `editor_capture`, `editor_status` 의 selection(범위·중심). 잘못됐으면 `editor_undo`/`editor_redo`.
7. `editor_save {note}` 로 저장합니다. note는 이 버전의 한 줄 설명(약 150자)입니다. 게시는 하지 않습니다.

## 5. 사이트 도구(WebMCP) 목록

지원되는 브라우저에서 편집기 페이지가 등록합니다. 입력은 JSON 객체이고 결과도 JSON입니다. 모든 도구는 화면의 버튼과 같은 엔진 메서드를 부르므로 되돌리기·저장에 그대로 잡힙니다.

| 도구 | 입력 | 결과·비고 |
| --- | --- | --- |
| `editor_manual` | — | 이 설명서 텍스트 |
| `editor_status` | — | work(id·name·serverRevision·unsaved·saveState), view(yaw·pitch·zoom·pan·preset·faceFrame·handPose·showOriginal·strip·pose·poseMotion·poseFrame·poseRange·posePlaying), tool, selection(part·points·ids 최대 200개·min·max·center·size), separatedPlaces, textures(크기·fileTier), history, lastAction, capture |
| `editor_targets` | — | head: [{id: "head:piece:N", points, center, size, placement}], body: [{id: "body:slot:이름", label, hidden, center, size}], face |
| `editor_select` | target: `"all"`·`"none"`·`"head:piece:N"`·`"body:slot:이름"`, 또는 part + range {x: [min, max], y, z}(null = 제한 없음), 또는 part + points [id…]; mode | 선택 요약. `"all"` 에는 part가 필요합니다 |
| `editor_points` | part; 그리고 ids / target / range / selection: true 가운데 하나(없으면 전체); original: true 면 열었을 때 좌표 | {part, count, points: [[id, x, y, z], …]} |
| `editor_set_points` | part(head·body), points: [[id, x, y, z], …] | {moved}. 한 번의 되돌리기 단계. \|좌표\| ≤ 4 |
| `editor_transform` | translate [dx, dy, dz], rotate [도x, 도y, 도z], scale [sx, sy, sz], pivot [x, y, z], falloff | {moved}. 선택이 있어야 합니다 |
| `editor_separate` | — | {separatedPoints, selection} |
| `editor_join` | — | {joinedPlaces} |
| `editor_recolor` | hue(도), saturation·lightness(배율) 또는 fill [r, g, b] + keepShading; allFrames(얼굴) | {changedTexels} |
| `editor_texture` | part, url(`data:image/…` 또는 `https://…`) | {applied, textures} 또는 {error} |
| `editor_texture_read` | part | {dataUrl, width, height, frames, frameSize} — 저장 전의 지금 그림 |
| `editor_view` | preset, yaw, pitch, zoom, pan [x, y], faceFrame, handPose, showOriginal, strip, pose(rest·idle·walk·run), poseFrame, posePlay | view |
| `editor_capture` | preset 또는 yaw·pitch(둘 다 없으면 지금 보기 그대로), zoom, pan, parts [head\|body\|face…], showOriginal, outline, selection, width, height(기본 480×540, 최대 1024), returnData | {label, width, height, dataUrl?}. 「보기」 패널의 「마지막 캡처」에도 표시 |
| `editor_undo` / `editor_redo` | — | {undone} / {redone}, lastAction |
| `editor_save` | note | {saved, revision, message} |
| `editor_parts` | — 또는 find {kind: hair\|body\|eye\|nose\|mouth, query, length, limit} | {parts, names, unusable[], found?} — 지금의 파츠와 게임이 받지 않는 파츠, 그리고 목록 검색 |
| `editor_change_parts` | headId, bodyId, face {eye, nose, mouth} 중 바꿀 것만 | {changed, parts, revision}. 바꾼 파츠의 편집은 사라지고 나머지는 남습니다. 저장하지 않은 변경은 먼저 저장되고, 바꾸기 전 상태는 버전으로 남습니다. 형태가 통째로 바뀌므로 선택과 되돌리기 기록은 초기화됩니다 |

## 6. 텍스처(그림) 규칙

- 텍스처는 셋입니다: 머리·몸은 정사각형 한 장, 얼굴은 표정 7칸(기본·공격·피격 1·2·3·다운·승리)을 가로로 이어 붙인 7:1 아틀라스. 표정 칸 안의 눈·코·입 위치는 게임이 정한 것이라 그 자리에 맞춰 그립니다.
- 허용 크기: 머리 64·128·256, 몸 128·256, 표정 한 칸 64·128·256 (최대 256). 그림을 넣으면 그림이 담기는 가장 작은 허용 크기가 되고, 그보다 크면 256으로 줄입니다. 크기가 파일 종류를 정합니다: 머리·얼굴이 128을 넘으면 .hhskin, 64를 넘거나 몸이 128을 넘으면 .hskin, 아니면 .skin.
- 비율: 머리·몸 1:1, 얼굴은 7:1(아틀라스 전체) 또는 1:1(보고 있는 표정 한 칸만 교체). 둘레에 단색 여백이 붙은 그림은 여백을 잘라 쓰고, 그 밖의 비율은 거절합니다(늘리면 UV가 어긋납니다).
- https 주소의 그림은 서버가 대신 받습니다(사설 주소·localhost 불가, 12MB, PNG/JPG/WEBP/GIF). `data:image` URL은 브라우저가 바로 읽습니다.
- 그릴 때: 알파 10% 미만 텍셀은 그려지지 않지만 외곽선 껍질은 알파를 무시하므로, 투명한 부분이 넓은 삼각형은 뒤에서 보면 어두운 테두리로 남습니다. 불투명한 그림은 삼각형 안에 맞춥니다. UV에서 맞닿은 영역은 경계 1텍셀이 서로 번지니 한 텍셀 여유를 둡니다. 「아틀라스」 패널의 UV 선(주황 = 선택한 부위)으로 어느 텍셀이 어느 면인지 봅니다.

## 7. 저장·버전

- 저장은 바뀐 것이 있을 때만 서버에 갑니다. 서버 버전은 r1, r2…로 오르고 최근 20개를 보관합니다. 「저장한 버전」 패널의 [복원]은 새 버전으로 되돌립니다(되돌리기 단계가 아닙니다).
- 저장하지 않은 상태는 새로고침하면 사라집니다. 다른 탭에서 먼저 저장했으면 버전이 어긋나 저장이 거절되니, 새로고침한 뒤 다시 합니다.
- `editor_change_parts` 로 파츠를 바꾸면 그 자리에서 새 버전이 됩니다. 바꾸기 전 버전에는 그때의 파츠가 적혀 있어, [복원]하면 파츠도 함께 돌아옵니다.
- 저장된 상태는 `GET /api/editor?model=<id>`(JSON: head·body·face 의 positions·unique·uvs·groups, versions)와 `GET /api/editor?texture=<part>&id=<id>`(PNG, `&which=original` 은 열었을 때 그림)로도 읽을 수 있습니다. 저장 전의 상태는 `editor_points`·`editor_texture_read` 로 읽습니다.

## 8. 화면으로만 조작할 때 (WebMCP 없이)

- 패널 id: `#editor-status`(상태 텍스트, JSON 펼침), `#editor-selection`(목록·범위 선택), `#editor-separate`, `#editor-transform`(dx·dy·dz / rx·ry·rz / sx·sy·sz + [이동][회전][크기], 기준점), `#editor-color`, `#editor-atlas`(그림 붙여넣기·주소로 넣기·PNG 내려받기), `#editor-tools`, `#editor-view`(프리셋·각도·확대·캡처), `#editor-parts`(지금의 파츠 · [파츠 바꾸기]), `#editor-versions`, `#editor-help`. 마지막 동작은 `#editor-last-action`, 저장 상태는 `#editor-save-state`.
- 단축키: 도구 Q 선택 · W 이동 · E 회전 · R 크기 · T 칠하기 · C 카메라. 보기 1~8. V 분리. Esc 선택 지우기. 화살표·PageUp/PageDown 은 선택을 0.005씩 옮깁니다(Shift 0.02). Ctrl+Z / Ctrl+Y 되돌리기·다시 실행, Ctrl+S 저장.
- 화면 선택: 클릭 = 가까운 점 하나, 드래그 = 상자 안의 보이는 점, 더블클릭 = 이어진 조각·부위, Shift 추가, Alt 제외. 「뒷면 점도 선택」을 켜면 상자가 가려진 점도 고릅니다.
- 그림 넣기: 파일 선택 창을 못 쓰면 「아틀라스」 패널의 주소 필드에 `data:image` URL이나 https 주소를 넣고 Enter, 또는 페이지에 붙여넣기(Ctrl+V).

## 9. 주의

- 스킨 파일 받기와 게시판 게시·삭제는 사람이 합니다. 로그인 정보나 API 키는 어디에도 넣지 않습니다.
- 스킨 파일(.skin·.hskin·.hhskin)이나 OBJ는 편집기에 넣을 수 없습니다. 그림(PNG/JPG/WEBP)만 들어갑니다.
- 큰 편집은 저장 사이에 나눠 되돌릴 수 있게 하고, 저장할 때 note에 무엇을 했는지 적습니다.
- 긴 머리·앞머리·땋은 머리를 투명 종이카드로 만들 때는 먼저 `/guide/hair-cards`(긴 머리 종이 헤어카드 가이드)를 읽습니다. 파츠 고르기, 원본 그림 투영, 얼굴 외곽선 틈을 피하는 규칙이 있습니다.


---

# 긴 머리 종이 헤어카드 가이드

> 여자 캐릭터의 앞머리·옆머리·긴 머리·땋은 머리를 투명 텍스처를 입힌 종이카드로 만드는 방법. AI 비서가 편집기로 헤어를 만들기 전에 읽는 작업 규칙입니다. 좌표·도구 이름은 편집기 조작 설명서와 같습니다.

이 가이드(HTML): https://skin-factory.com/guide/hair-cards · 편집기 설명서: https://skin-factory.com/guide/editor

## 1. 목표와 원칙

- 고품질은 "원본 캐릭터 그림과 같은 텍스처"입니다. 머리결을 새로 그리지 말고 원본 그림의 머리 픽셀을 오려 카드에 투영합니다. 절차적으로 그린 결·하이라이트·톱니는 원본과 달라 보여 거절됩니다.
- 카드의 모양은 원본 그림의 투명도가 정합니다. 카드는 넉넉하게 크게 만들고, 머리가 없는 부분은 텍스처를 투명하게 둡니다. 사각형 카드 모서리가 그대로 보이면 안 됩니다.
- 원본에 그 방향 그림(옆·뒤·위)이 없으면 사람에게 먼저 요청합니다. 그림이 있으면 그 방향도 투영하고, 끝내 없을 때만 원본의 색·선 굵기로 그려 채웁니다.
- 헤어만 고쳐 달라는 요청이면 몸·얼굴 표정은 건드리지 않습니다.

## 2. 머리 파츠 고르기

종이카드 헤어는 게임이 양면으로 그리고 외곽선을 두르지 않는 머리 파츠에서만 제대로 보입니다. 보통 머리 파츠로 카드를 만들면 카드 뒷면이 검은 외곽선 그림자로 보이고, 스킨으로는 이 성질을 바꿀 수 없습니다. 이런 파츠는 여덟 가지뿐입니다.

| 파츠 이름 | 카드 재료로서 |
| --- | --- |
| 헬멧 SP | 가장 좋음. 서로 겹치지 않는 텍스처 칸이 가장 많고(36칸 · 삼각형 110개), 돔 부분이 그대로 두상 셸이 됩니다. |
| 우럭머리 SP | 다음으로 많음. 가는 조각이 많아 큰 카드는 적습니다. |
| 붉은·파랑·녹색 우럭머리 | 우럭머리 SP보다 삼각형이 적습니다. |
| 밀집모자 SP | 칸은 크지만 서로 겹치는 칸이 많아 쓸 수 있는 카드가 적습니다. |
| 나무모자 | 같은 칸을 여러 삼각형이 나눠 써서 서로 다른 그림을 넣을 곳이 적습니다. |
| 응원 머리띠 | 삼각형이 적어 긴 머리에는 부족합니다. |

- 파츠 바꾸기: `editor_parts` 의 find로 이름을 찾고 `editor_change_parts` 로 머리만 바꿉니다. 바꾸는 머리 파츠의 편집은 사라지고(이전 상태는 버전으로 남음) 몸·얼굴 편집은 남습니다.
- 얼굴(face)은 모양이 고정된 공이고 7개 표정 칸의 텍스처만 바꿀 수 있습니다. 헤어 설계는 이 얼굴 공을 기준으로 합니다(정면 = −z, 얼굴 공 반지름 약 0.13~0.15).

## 3. 역할 나누기 — 얼굴 텍스처와 카드

| 부분 | 어디에 | 어떻게 |
| --- | --- | --- |
| 얼굴 윤곽 안쪽: 이마를 덮는 앞머리, 뺨 위로 내려오는 옆머리 | 얼굴 텍스처(7칸 모두 같게) | 원본 정면 그림을 얼굴 공의 앞을 향한 면에만 정면 투영. 눈·입은 칸마다 그대로 둡니다. |
| 정수리·뒷머리·바깥 옆 볼륨(단발 모양) | 머리 파츠의 돔을 다시 편 "셸" | 돔의 삼각형을 머리 모양 반구로 옮기고, 면이 향한 방향의 원본 그림(정면·옆·뒤)을 투영. |
| 얼굴과 셸 사이 옆머리 띠 | 한쪽에 사각형 카드 2~3장을 위아래로(좌우 거울 짝) | 안쪽 모서리는 얼굴 표면에, 바깥 모서리는 셸 속으로 겹치게. 정면 그림 투영. |
| 양갈래 땋은 머리 | 같은 칸을 4장이 쓰는 사각형 두 개 → 십자로 교차한 카드 두 마디 | 원본의 땋은 머리를 중심선 따라 곧게 편 띠 그림을 붙임. 끈·술은 따로 작은 교차 카드. |
| 아호게 | 짝 없는 칸(가운데 조각)으로 만든 카드 한 장 | 정면에서 조금 돌린 판에 원본 아호게를 투영. 짝 칸을 쓸 때는 한쪽을 숨깁니다. |

- 대부분의 칸은 좌우 거울 짝(두 삼각형이 같은 텍스처)입니다. 오른쪽을 설계하면 왼쪽은 x를 뒤집은 자리에 같은 그림이 거울로 나옵니다. 가운데를 가로지르는 조각이 필요하면 짝 없는 칸을 씁니다.
- 쓰지 않는 삼각형과 다른 칸과 텍스처가 겹치는 삼각형은 머리 속 한 점(예: 얼굴 공 중심)으로 모아 숨깁니다.
- 양갈래 머리의 뿌리는 목덜미 쪽 뒷머리 아래(가운데 가까이)에 숨깁니다. 옆에서 튀어나온 뿌리·연결용 삼각형은 부자연스러워 보입니다.

## 4. 준비 — 삼각형 떼기와 칸 파악

1. 머리 파츠의 모든 삼각형을 하나씩 뗍니다: 삼각형마다 세 점을 `editor_select` 로 고르고 `editor_separate`. 이후 모든 슬롯이 따로 움직입니다(점 id는 `model.head.unique[slot]`, 뗄 때마다 다시 읽음).
2. `/api/editor?model=<id>` 의 head.groups[].corners(슬롯·UV 쌍)로 삼각형마다 UV를 읽고, 같은 UV를 쓰는 삼각형끼리 묶습니다(1장·2장 짝·4장 공유).
3. 256×256 텍스처에 칸을 그려 보고, 다른 칸과 겹치지 않는 칸만 고릅니다(큰 칸부터).
4. 사각형 칸(삼각형 두 개)의 경계는 실제 UV 값에서 구합니다. 손으로 적은 경계(159 대 실제 159.49)는 카드 모서리를 수 mm 어긋나게 해 일자 틈을 만듭니다.
5. 서로 붙어 있는 칸은 경계 텍셀을 나눠 씁니다. 붙은 가장자리가 3D에서도 같은 모서리가 되도록 칸 방향을 정하거나, 그 모서리를 셸 속에 숨깁니다.

## 5. 원본 그림 투영

- 머리카락 오려내기: 머리색과 피부색은 G/R 비율로 가릅니다(머리 < 약 0.875 ≤ 피부). 얼굴은 피부에서 채우기로 한 덩어리로 잡고 구멍(눈·입)을 채워 제외, 선(어두운 픽셀)은 머리에서 3px 이내만 남깁니다. 머리 하이라이트처럼 피부색인 머리 픽셀은 얼굴 덩어리에 이어지지 않으면 머리로 칩니다.
- 정면 맞추기: 원본의 두 눈동자 중심과 얼굴 공의 눈 위치로 배율과 중심을 정합니다. 정면에서 모델의 +x는 그림의 왼쪽입니다(그림 x = 중심 − x·배율). 거울 짝은 |x|로 그림의 한쪽 절반을 씁니다.
- 셸 면마다 바깥 방향으로 하나의 그림을 고릅니다: 앞을 향하면(−z 성분 ≥ 0.35) 정면 그림, 그 밖에는 뒤·옆 중 더 향한 쪽. 위를 향한 정수리 면은 곧장 투영하면 줄무늬로 늘어나므로, 가르마·가마에서 방사형으로 펼쳐 정면·후면 그림을 씁니다.
- 옆 그림의 얼굴 깊이가 모델과 다르면(보통 모델 얼굴이 더 깊음) 옆 그림을 가로로 늘려 옆머리가 시작하는 곳을 모델의 셸 앞 모서리에 맞춥니다.
- 머리 끝선은 원본 그림의 층 경계를 따라 자르고 그 아래를 투명하게 합니다(뒷모습의 낮은 양갈래·목은 잘라 냄). 절차적 톱니 끝은 만들지 않습니다.
- 작은 구멍은 닫기 연산(팽창 후 침식, 약 6px)으로 메웁니다. 셸에는 투명 구멍이 없어야 합니다(끝선 제외).
- 로컬 그림을 편집기 페이지로 넘기는 길이 없으면, 머리만 오린 그림을 모델 좌표 격자(예: 1단위당 540px)로 만들어 WebP data URL(수십 KB)로 넘기고 페이지 안에서 칠합니다.

## 6. 외곽선과 틈 — 가장 많이 틀리는 곳

얼굴 공은 게임이 표면에서 0.013(약 1.3cm) 바깥에 검은 외곽선 껍질을 두릅니다. 양면 머리 파츠에는 외곽선이 없으니, 머리와 얼굴 사이의 검은 점·선은 거의 다 이 얼굴 외곽선입니다.

- 머리 면이 얼굴에서 1.3cm보다 가까우면(또는 얼굴 속으로 들어가면) 검은 점이 비칩니다. 셸과 옆 띠는 얼굴에서 반지름 방향으로 0.017(1.7cm) 이상 띄웁니다. 평평한 카드는 가운데가 둥근 이마 속으로 들어가기 쉬우니 표본 점마다 거리를 재서 밉니다.
- 멀리 띄우면 가장자리 틈으로 얼굴 윤곽선이 보입니다. 셸의 앞 테두리는 이마 아래(눈썹 위)까지 내려 얼굴 표면 가까이 붙이고, 옆 띠의 안쪽 모서리도 얼굴 표면에 붙입니다. 정면 투영은 깊이와 무관하므로 카드를 앞뒤로 옮겨도 정면 모습은 그대로입니다.
- 카드끼리는 겹치게 둡니다: 옆 띠의 윗모서리는 셸 앞 테두리 위·뒤로, 바깥 모서리는 셸 옆면 뒤로 넣습니다. 딱 맞춘 모서리는 각도에 따라 벌어집니다.
- 셸이 투명하면 그 너머 얼굴 외곽선이 보입니다. 원본이 비는 곳은 다른 방향 그림 → 원본 색으로 채우고, 투명은 끝선에만 씁니다.
- 얼굴 텍스처의 머리 밑(턱 옆·목)은 머리가 가려 주지 않는 각도가 있으니 피부색 + 옅은 머리 그림자로 칠합니다. 머리색으로 칠해 두면 머리를 잘라 낸 자리에 분홍 덩어리로 보입니다.
- 대각선으로 볼 때 먼 쪽 얼굴 윤곽의 선은 게임이 모든 스킨에 두르는 얼굴 외곽선이라 헤어로 없앨 수 없습니다. 사람에게는 그렇게 설명합니다.

## 7. 텍스처 규칙

- 머리 텍스처는 256×256 한 장입니다. 게임은 가장 가까운 텍셀만 읽고(부드러운 보간 없음) 알파 0.1 이하를 버립니다. 반투명은 없고 투명/불투명 둘뿐이니 끝선은 텍셀 계단이 됩니다.
- 텍셀은 삼각형 안쪽 중심을 가진 칸이 차지합니다. 칸 밖 1~2텍셀은 같은 칸의 연장으로 칠해 두어야 가장자리에서 옆 칸 색이 새지 않습니다.
- 캔버스로 PNG를 만들면 완전히 투명한 픽셀의 색은 검정이 됩니다. 게임에서는 보이지 않으니 그대로 둬도 됩니다.
- 사람이 칠한 색(예: 갈색)을 "투명으로 지워 달라"고 하면 그 색 픽셀만 지웁니다. 거칠게 칠했다며 정리를 부탁하면, 그 주변 몇 px 안에서만 떨어진 작은 조각을 지우고 들쭉날쭉한 경계를 다듬고 원본 선색으로 가는 경계선을 넣습니다.

## 8. 사람과 같은 창에서 일할 때

- 사람이 같은 편집기 창에서 직접 점을 옮기거나 칠했을 수 있습니다. 편집 전에 `editor_status` 의 unsaved와 되돌리기 목록 끝(내가 하지 않은 "드래그로 이동", "칠하기")을 확인합니다.
- 그런 편집이 있으면 머리 점 전체를 다시 적용하지 않습니다. 바꿀 점·텍셀만 바꾸거나, 현재 점을 `editor_points` 로 읽어 그 위에 작업합니다. 실수로 덮었으면 `editor_undo` 로 내 단계만 되돌리면 사람 편집이 돌아옵니다.
- 사람이 가리킨 조각을 찾을 때는 기억에 기대지 말고 칸마다 다른 색을 임시로 칠해 그 각도로 캡처한 뒤 되돌립니다.
- 고칠 때마다 무엇을 바꿨는지 적어 저장(`editor_save` note)합니다. 서버에 저장된 좌표가 편집기와 같은지 확인하고 보고합니다.

## 9. 확인 목록

1. 정면·측면·반대 측면·후면·뒤 대각을 `editor_capture` 로 봅니다. 정면은 원본 그림과 나란히 비교합니다.
2. 대각선 ±25°·±50°·±70°, 위에서 20~40° 내려다본 앞모습, 정수리(top)를 봅니다. 틈·검은 점·사각 모서리·튀어나온 조각이 이 각도에서 드러납니다.
3. 대기·걷기·달리기 자세(`editor_view` pose)에서 땋은 머리·옆 띠가 몸을 뚫는지 봅니다.
4. 의심스러우면 부위를 나눠 봅니다(parts: head만 / face만). 머리만 볼 때 없고 얼굴과 함께일 때 생기는 검은 선은 얼굴 외곽선입니다.
5. 저장 후 `/api/editor?model=<id>` 의 좌표와 편집기 좌표를 비교해 저장이 맞는지 확인합니다.
