deskpet — 작업 규칙
규칙만 둔다. 상태·이력은
handoff.md, 완료건은archive.md.
🆕 신규
- 2026-07-29 ⚠상업 사용 가능한 4족 모캡은 없다(조사 확정). AI4Animation 개 mocap·PFERD 말 mocap = CC BY-NC / Truebones Zoo = 제3자 IP 의혹 / motion_imitation = Apache지만 척추·꼬리 없는 19값 / 유니티·언리얼 팩 = 엔진 락인. 리타게팅 경로를 다시 제안하지 말 것. 대신 논문 실측 관절각(PLOS ONE CC0·PMC CC-BY)을 목표값으로 쓰는 절차생성이 정답. 원문 =
deskpet/out/_motion_research.json. - 2026-07-29 보행은 관절각에 사인파를 물리지 마라 — 발끝 궤적을 먼저 정하고 IK로 역산해라. 사인파를 관절에 직접 넣으면 지지기에도 발이 원호를 그리며 미끄러져 앞다리가 진자처럼 흔들려 보인다(페페 지적). 지지기 = 발 고정·등속 후퇴, 유각기 = easeInOutCubic 복귀 + 포물선 리프트. 시상면 2마디 해석 IK면 충분하다(
skel.jsik2). - 2026-07-29 앞다리 팔꿈치는 뒤로, 뒷다리 무릎은 앞으로 꺾인다. IK bend 부호 = 앞 −1 / 뒤 +1. 뒤집으면 즉시 곤충 다리가 된다.
- 2026-07-29 척추 회전은 반드시 분절에 나눠라. 한 관절에 몰면 꺾인 것처럼 보인다(실측 고양이는 천골 앞 7±1 관절이 나눠 굽고 진폭은 꼬리쪽이 크다).
spineArc(total)로 총합만 지정한다. - 2026-07-29 발바닥이 늘어나면 말단 본의 로컬 회전을 의심해라. 발끝에 본이 없는 리그는 발 전체가 말단 본 하나에 실려서 로컬 회전이 크면 경계에서 스킨이 밀린다. 지지기=월드 수평 유지, 유각기=부모 추종(로컬 0)으로 블렌드하면 크게 준다. 근본 해결은 Blender 발끝 본 추가 + 오토웨이트 재계산.
- 2026-07-29 외곽선 두께는 캐릭터 크기에 비례시켜라. 고정 px로 두면 축소했을 때 수염 같은 얇은 판형 지오메트리가 자기 외곽선(법선확장 BackSide 껍데기)에 통째로 삼켜져 검은 덩어리가 된다(60%에서 실측). 머리를 크게 숙이는 포즈에서 특히 잘 보인다.
- 2026-07-29 색 보정 경계값은 눈대중 금지 — 마스터 분율로 격자탐색해라. 복면 흰털 마스크를 눈대중으로 잡았더니 흰털이 40.9%로 마스터(20.6%)의 2배였다.
sweep_white.py(빠른 모드 = idle 2장만, 9초/회)로 스윕해 20.2%로 맞췄고 일치도가 0.8075→0.870으로 올랐다. - 2026-07-29 흰털은 색이 아니라 위치로 갈라야 한다. 회색과 흰색은 채도가 겹쳐 색 조건만으론 못 가른다. 바인드포즈 정규화 높이(ny)·전후(nz)로 해부학적 복면을 정의하는 게 유일하게 되는 방법. 잉크선 보존용 밝기 게이트는 흰털 확신 구역에서만 문턱을 낮춰야 검은 얼룩(마스터에 없는 Tripo 텍스처 잔재)이 지워진다.
- 2026-07-29 poin-agent 게시글을 외부 UI에서 고칠 땐
board_cli.py를 거쳐라. 행 ID =sha1(섹션 본문 등장순번)[:10]이고 규칙은board_rows.py가 단일 출처다. 표시용으로 JS 미러가 필요하면(파이썬 기동이 방당 2.6초라 팝업에선 못 부른다) 반드시spike3d/test_rowid.js로 파이썬 결과와 대조해라 — 어긋나면 편집이 엉뚱한 행에 붙는다. -
2026-07-29 크기 조절은 한 군데만 고치면 반드시 어긋난다. 모델 스케일·히트박스(halfW·petH)·외곽선 두께·이동속도(보폭×스케일)를 한 함수(
applyScale)에서 같이 갱신할 것. -
2026-07-29 ⚠⚠본 회전축을 하드코딩하지 마라 — 바인드 월드 쿼터니언에서 유도해라. 이 리그(Tripo 오토리깅)는 전 본의 로컬 +Y가 뼈 길이방향이고 로컬 X는 월드 Z(전후축)를 가리킨다. 그래서
[1,0,0]으로 돌리면 굴곡이 아니라 다리를 옆으로 벌리는 외전이 된다(각도를 아무리 키워도 앉거나 눕는 그림이 안 나온다). 해부학적 굴곡/신전은 월드 X 회전이므로worldQ⁻¹ · (1,0,0)을 축으로 써야 한다 =spike3d/skel.js. 모델이 바뀌어도 그대로 동작한다. - 2026-07-29 자세는 '월드 기준 각도'로 지정하고 부모 누적은 코드가 빼게 해라. 로컬 델타로 직접 쓰면 척추를 세운 만큼을 앞다리에서 손으로 빼야 하는데 여기서 반드시 틀린다(구판 sit의 앞다리가 뒤로 꺾여 있었다).
Clip.wchain(bones, worldDegs, parentAcc)사용. - 2026-07-29 접지 기준 = 본별 '살 두께 반지름'이지 바인드 높이가 아니다. 비절·팔꿈치는 서 있을 땐 안 닿지만 앉거나 엎드리면 닿는 접점이다. 바인드 높이(0.14/0.31)를 접지 기준으로 삼으면 몸이 그만큼 공중에 뜬다. 실측 반지름 = 앞발목 0.079 / 뒷발 0.028 / 비절 0.032 / 팔꿈치 0.050.
- 2026-07-29 바닥면은 상수로 박지 말고 바인드에서 역산해라.
boneLocalPos가 본 체인만 누적하면 아마추어 공간이라 모델 공간 상수와 어긋난다 → 캐릭터가 통째로 0.44 떠올랐다(실측). 뒷발 본의 바인드 Y − 반지름으로 바닥을 구한다. - 2026-07-29 자세형 클립 스샷은 상태전환 1.3~2.3초 뒤에 찍어라. 램프(길이의 0.25~0.35) + 크로스페이드 0.35초가 지나야 자세가 완성된다. 일괄 0.7초로 찍으면 절반만 잡힌 포즈를 보고 각도를 헛튜닝하게 된다(실제로 여러 라운드 낭비했다).
- 2026-07-29 스샷 판정은 잘라서 확대하고 접지선을 그려라. 1920px 화면에 캐릭터가 300px뿐이라 원본 크기로는 자세가 안 보인다. 알파 bbox로 크롭 → 2배 확대 → idle 접지 y에 빨간 선 → 그때부터 판단이 된다.
- 2026-07-29 포즈가 안 변할 땐 스샷 대신 숫자를 봐라. 클립 빌드 시 포즈를 실제 적용해 관절 높이(엉덩이·무릎·비절·발·어깨·팔꿈치·앞발·가슴·머리)를 리포트에 뽑으면 "발이 0.1 떠 있다"가 즉시 보인다. 진단 프레임은 u=1이 아니라 회전량 최대 프레임으로 잡아야 stretch류가 원위치로 안 잡힌다.
- 2026-07-29 Tripo 본 이름은 해부학과 다르다.
Head_0=흉곽(앞다리·목이 달리는 허브) ·Head_3=왼쪽 귀(짝bone_7=오른쪽 귀) · 턱 본 없음(하품을 입벌림으로 못 만든다 → 목 신전·귀 눕힘·수염 벌림으로 표현) ·bone_13/17=견갑골 ·bone_21/22=꼬리 뿌리 2마디(꼬리는 3마디가 아니라 5마디다). - 2026-07-29 꼬리 각도는 바인드가 이미 68° 들려 있는 걸 감안해라. alert에서 −52°를 더 줬더니 꼬리가 등 위로 넘어가 몸통 실루엣에 묻혔다. 수직까지는 −20°면 충분하다.
- 2026-07-29 폴리곤 감량은
gltf-transform simplify가 정답.npx @gltf-transform/cli simplify in.glb out.glb --ratio 0.015 --error 0.01→ 195만→2.9만 tri, 본 34개·스킨웨이트·텍스처 전부 보존, 마스터 일치도는 오히려 상승(0.7966→0.8075). 목표 비율 = 목표tri/현재tri. -
2026-07-29 이동속도는 상수로 두지 말고 클립이 잰 보폭에서 산출해라. 지지기 동안 발이 몸 기준으로 밀린 거리 ÷ 주기 = 미끄러지지 않는 속도. 손으로 정한 상수는 반드시 어긋난다.
-
2026-07-29 ⚠최대 함정:
GLTFLoader는 본 이름의::를 제거한다. Tripo GLB 원본tripo::Spine_0→ 로드 후 실제 이름은tripoSpine_0(언더스코어 아님,PropertyBinding.sanitizeNodeName). 트랙 이름을 원본이나tripo_Spine_0으로 쓰면 에러 0·경고 0으로 조용히 아무 본에도 안 붙고 포즈가 전혀 안 변한다. 부호·축·각도를 아무리 고쳐도 그림이 똑같으면 이걸 의심할 것. 진단 = 리포트에skeleton.getBoneByName(name)결과와 실제bones[].name을 같이 찍는다. - 2026-07-29 렌더러 콘솔을 main에서 파일로 뽑아라. 셰이더 컴파일 에러·
Uncaught SyntaxError는window.onerror에 안 잡혀서 리포트가errors: []로 나온다. app3d가 통째로 안 돌아도 이전 스샷이 남아 "수치 무변화"로 오진한다(실제 발생).win.webContents.on('console-message', …)→out/console.log. 스샷 mtime도 같이 확인. - 2026-07-29 JS 문자열에 실제 개행을 넣지 말 것. 파이썬 패치 스크립트로
'varying vec3 vObjP;\n'를 쓸 때\n이 진짜 줄바꿈으로 들어가 SyntaxError가 났다. heredoc 안에서\\n으로 이스케이프하거나 Edit 도구를 쓴다. - 2026-07-29 색보정 순서 = 채도감쇠 → warm부스트, 단 warm 마스크는 '감쇠 후' 채도로 잰다. 감쇠 전 채도로 재면 방금 흰색으로 보낸 배·다리가 다시 누렇게 물들어 흰색 분율이 0이 된다(실측 0.27→0.00).
- 2026-07-29 Tripo 무료 경로 = 뷰어 네트워크에서 GLB 회수. 내보내기 버튼은 유료 페이월(구독 모달)이지만, 리깅 결과를 뷰어가 로드할 때
tripo-data.*/…_meshopt.glb를 받는다 → CDPNetwork.getResponseBody로 저장하면 리깅 스켈레톤 포함 GLB를 얻는다. 크레딧 = 이미지→3D 55 + 오토리깅 20. 멀티뷰는 구독자 전용이라 단일뷰로 만들면 텍스처가 좌우 대칭이 되어 페페냥 비대칭 무늬가 사라진다(셰이더로 되살림). - 2026-07-29 playwright
connect_over_cdp가 얹히면 raw CDP로 우회. 브라우저 레벨 attach에서 무한 대기하는 경우가 있다 →spike3d/cdp.py(websocket-client로 페이지 웹소켓 직결). ⚠create_connection에suppress_origin=True없으면 Chrome이 403(Origin 헤더 거부). -
2026-07-29 Tripo 로그인 = 이메일 인증코드 + Gmail MCP 자동화. 구글 원탭(FedCM)은 CDP
FedCm.enable로도 다이얼로그가 안 잡혀 실패했다.Continue with Email→ 코드 발송 →mcp__claude_ai_Gmail__search_threads로from:tripo3d.ai코드 회수 → 입력. 계정 = delix0731·poin3133 둘 다 가입돼 있음. -
2026-07-28 Electron 앱을 코디가 실행할 땐
ELECTRON_RUN_AS_NODE를 벗겨라. VS Code 확장호스트가 이 환경변수를1로 걸어두고 자식 셸에 상속시킨다 →electron.exe가 GUI 없이 node로 뜨고require('electron')이 경로 문자열을 반환해ipcMain is undefined로 죽는다(로직 버그로 오진하기 쉽다). 실행은env -u ELECTRON_RUN_AS_NODE ./node_modules/electron/dist/electron.exe . <flags>. deskpet뿐 아니라 모든 Electron 앱 공통. - 2026-07-28 툰 외곽선이 안 나오면 법선부터 의심. 외곽선은 자작 BackSide 껍데기든 three 공식
OutlineEffect든 정점 법선을 밀어서 만든다. glTF에NORMAL속성이 없으면normalize(vec3(0))=NaN이라 외곽선 메시가 통째로 사라지는데 에러는 0이다(무음 실패 → 두께·색·머티리얼을 헛되이 만지게 된다). 모델 로드 직후geometry.hasAttribute('normal')확인하고 없으면computeVertexNormals(). Khronos Fox.glb가 실제로 법선 없음. - 2026-07-28 외곽선은 자작하지 말고
three/addons/effects/OutlineEffect.js를 쓴다. 스킨드 메시·두께 화면비율 환산까지 이미 처리돼 있다. 자작 BackSide 클론은 스켈레톤 바인딩·단위계 환산을 다 직접 해야 하고 실익이 없다. - 2026-07-28 모델 크기·방향은 하드코딩 금지, 로드 시 산출한다. 모델마다 단위계(Fox=79 로컬유닛)와 정면축이 제각각이다 → bbox로
scale = 목표px / localH를 구하고, 외곽선 두께 같은 파생값도 px 기준으로 주고 나눠 쓴다. 정면축은BASE_YAW상수 하나로 흡수. - 2026-07-28 접지선(발바닥)은 바인드포즈 bbox로 잡으면 어긋난다. 애니 클립이 루트를 내리면 발이 화면 아래로 삐져나온다. 스파이크는 여유값(
GROUND = H-90)으로 덮었고, 실파이프라인은 클립별 포즈 샘플링으로 최저점을 구해야 한다(미구현·이월). - 2026-07-28 스타일 확정 =
02-anime-watercolor(페페 지시). ⚠이름과 달리 실제 산출물은 수채화가 아니라 애니 셀화다 — 균일한 진한 잉크 외곽선 + 플랫 색면, 번짐·종이결 없음. 형태를 만드는 건 음영이 아니라 외곽선과 무늬 라인이다. 따라서 3D 재현 시 ①툰 계조를 세게 주면 안 된다(색이 날아가 무늬가 안 읽힘 — 램프 2단 저대비[222,255], ambient 1.05/dir 0.55) ②외곽선이 스타일의 정체성이라 반드시 살려야 한다. 진짜 수채(번짐·종이결)였다면 훨씬 어려웠을 것. - 2026-07-28 절차적 무늬의 노이즈 좌표는 정규화값(0~1)으로 준다. 모델 로컬 좌표(Fox는 ±50유닛)로 주면 노이즈 셀이 수십 개 깔려 무늬가 마블링으로 뭉갠다(실측). 무늬 계산은
n = (vObj - bboxMin) / bboxSize로 정규화한 뒤 스케일 2~9 정도를 곱해 쓴다. - 2026-07-28 무늬는 '바인드포즈 위치'로 계산한다. 셰이더에서
#include <begin_vertex>직후의transformed(=스키닝 전)를 varying으로 넘겨 쓴다. 스키닝 후 위치를 쓰면 무늬가 공간에 고정돼 몸이 그 앞을 지나가는 꼴이 된다. - 2026-07-28
OutlineEffect는 이 구성(직교 카메라 + 스킨드 메시)에서 화면에 안 나온다.isCompatible(법선 존재)을 통과하고 프로그램도 컴파일되는데 결과가 안 보인다 — 원인 미규명. 자작 BackSide 껍데기로 대체했고 이건 정상 동작한다(법선만 있으면 됨). ⚠중간에 "외곽선이 보인다"고 오판한 적이 있는데 그건 툰 램프 하한이 어두워서 생긴 계조 테두리였다. 외곽선 유무는 램프를 밝게 한 상태에서 판정할 것. - 2026-07-28 좌우 전환은 미러가 아니라 Y축 회전. 페페냥은 무늬가 비대칭(주황 볼 한쪽)이라 스프라이트 미러링이 원천적으로 불가했다 — 2D 파이프라인이 좌우 프레임에서 계속 깨진 근본 원인. 3D는
rotation.y += π한 줄로 해결되고 이 이점이 3D 채택의 핵심 근거다.