Communitygithub.com

machine

한 줄의 설명(예: "터보팬 제트 엔진", "기계식 시계", "LVAD 심장 펌프")을 바탕으로 해당 기계의 실제 물리 기반 포토리얼 대화형 3D 시뮬레이션을 단일 HTML 파일과 20~30초 분량의 영상으로 제작하는 스킬입니다. 실제 미터 단위 비율, 실제 재료(PBR 금속, 도료, 폴리머, 유리), 소프트 섀도우가 있는 스튜디오 조명, 추력, 토크, RPM, 유량, 압력, 효율 등의 실제 수치를 계산하는 작은 솔버로 구동되는 움직이는 부품, 분해, 절개, X-ray, 슬로우 모션, 라벨링, 파손 모드를 지원합니다.

machine란 무엇인가요?

Machine 스킬은 개발자나 AI 에이전트 사용자가 '기계의 작동 방식을 보여줘'라는 요청을 하면, 해당 기계의 포토리얼리스틱한 3D 시뮬레이션을 자동으로 생성합니다. 사용자는 '터보팬 제트 엔진', '기계식 시계', 'LVAD 심장 펌프'와 같은 간단한 한 줄 설명만 입력하면 됩니다. 이 스킬은 단일 HTML 파일(three.js 기반)과 함께, 20~30초 분량의 영화를 생성하는 스크립트를 제공합니다. 기계는 실제 미터 단위 비율과 PBR 재질(금속, 도료, 폴리머, 유리)로 제작되며, 추력, 토크, RPM 등 실제 물리 법칙을 계산하는 솔버가 내장되어 있습니다. 또한 분해도, 절개도, X-ray, 슬로우 모션, 라벨, 파손 모드 등 다양한 시각화 모드를 지원하여 엔지니어링 교육, 제품 프레젠테이션, 기술 문서 등에 활용할 수 있습니다. Cursor, Claude Code, Codex 등 다양한 개발 환경에서 사용할 수 있습니다.

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/WU7475/skill-backup/tree/main/machine

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Machine Skill (기계 스킬)

당신은 마치 제품 스튜디오에서 사진을 찍고 엔지니어가 설명하듯 기계를 구축합니다: 실제 크기, 실제 재료, 깨끗한 스튜디오 세트, 실제 방정식으로 작동합니다. 한 줄 입력, 하나의 HTML 파일 출력, 한 번의 명령으로 영화까지.

출력물은 항상 다음과 같습니다:

  1. <name>.html: 단일 자체 포함 페이지(jsDelivr의 three.js 0.170, 키트는 인라인). 디스크, 정적 호스트, 또는 iframe 내에서 열립니다.
  2. 영화: node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:<Category>/<Name>.

먼저 examples/를 열어보세요. 모든 예제는 페이지 상단의 한 줄 설명으로 만들어졌습니다. examples/turbofan.html이 참조 예제입니다: 무언가를 작성하기 전에 처음부터 끝까지 읽어보세요.

기준

시작하기 전에, 시청자가 3초 후에 보게 될 프레임을 상상해보세요. 이미 실제 기계의 스튜디오 제품 사진처럼 보여야 합니다: 올바른 실루엣과 비율, 금속은 금속처럼 읽히고, 종이 바닥에 부드러운 그림자, 떠 있거나 잘리거나 임시방편인 것 없이. 그런 다음 움직이고, 화면의 모든 숫자는 계산됩니다.

다음 중 하나라도 해당되면 결과물은 완료된 것이 아닙니다:

  • 정비사가 예상할 부품이 누락됨(연소실에 연료 노즐 없음, 시계에 이스케이프먼트 없음, 엔진에 밸브 없음)
  • 무언가가 떠 있거나, 교차하거나, 이음새에 보이는 틈이나 간격이 있음
  • 재료가 금속이어야 하는데 플라스틱처럼 보이거나, 모든 것이 하나의 회색임
  • 화면의 숫자가 솔버에 의해 계산되지 않고 입력된 값임
  • 절개도가 단단한 단면 대신 빈 껍질을 보여줌
  • 영화의 첫 프레임이 아름답지 않음

워크플로우

1. 실제 기계 조사 (5분, 코드 없음)

머신 스크립트 상단의 주석 블록에, 알고 있는 것(그리고 웹에서 찾은 것)을 기록하세요:

  • 실제 치수(미터): 실루엣을 정의하는 5~10개 부품의 치수 (터보팬: 팬 직경 2.85m, 길이 4.9m, 나셀 최대 직경 3.44m).
  • 부품 목록: 조립 순서, 각 재료와 함께. 15~40개의 이름이 있는 부품을 목표로 하세요; 반복되는 부품(블레이드, 톱니, 볼트, 코일)은 개별적으로 계산합니다.
  • 물리: 작동 원리, 3~6개의 방정식(실제 상수와 작동점 포함)으로 표현 (터보팬: Brayton 사이클, 이륙 시 N1 100%, OPR 42, T4 1,750K, 약 330kN).
  • 하나의 숫자: 시청자가 관심을 가질 한 가지 수치(주인공: 추력, 토크, 시간당 박동수, 유량, 출력). 큰 세리프 숫자와 얇은 막대로 표시됩니다.
  • 입력: 시청자가 제어하고 싶어하는 하나의 슬라이더 (스로틀, 풍속, RPM, 펌프 속도, 분쇄도).
  • 파손: 엔지니어가 걱정하는 고장과 솔버가 예측하는 결과 (팬 블레이드 이탈 및 언밸런스 하중, 레드라인 이상의 밸브 플로트, 펌프 스톨, 과압). 이는 계산된 결과여야 하며, 애니메이션이 아니어야 합니다.

2. 템플릿에서 페이지 구축

kit/template.html을 <name>.html로 복사하세요. 여기에는 import 맵([email protected] 고정), 글꼴, 키트가 들어갈 표시된 블록, 그리고 당신이 채울 네 개의 섹션이 있습니다:

const { THREE, Lab, MAT, GEO, heatGlow, clamp, lerp, approach, fmt } = window.LabKit
const lab = new Lab({ prompt, no, title, sub, size, view, cut })   // 1. 랩
// 2. 부품      lab.mesh(GEO..., MAT..., { name, pos, explode, xray, count })
// 3. 솔버     lab.hero(...); lab.slider(...); lab.onTick((dt, lab) => { ... lab.setHero(...) })
// 4. 파손, 설명, 영화      lab.breakIt(...); lab.how(...); lab.autoFilm(...); lab.start()

복사 직후, node <skill dir>/scripts/inline.mjs <name>.html을 실행하세요: 키트를 표시된 블록에 붙여넣어 페이지가 어디에 있든 단일 자체 포함 파일이 되도록 합니다(템플릿의 src="../kit/lab-kit.js"는 이 저장소 내에서만 해결됩니다). 그런 다음 두 번째 스크립트 블록에 기계를 작성하세요.

3. 지오메트리: 실제 크기의 실제 솔리드

기계 자체 프레임에서 미터 단위로 작업하고, Y는 위쪽, ground를 설정하지 않으면 바닥은 y = 0입니다. size를 가장 긴 실제 치수로 설정하세요; 키트는 모든 기계가 세트에서 동일하게 앉도록 디스플레이를 조정하고, 스케일 바는 실제 크기를 보여줍니다.

  • 원형 부품(샤프트, 디스크, 케이싱, 노즐, 콘, 스피너, 피스톤, 베젤): GEO.lathe([[r, y], ...])로 닫힌 프로파일 사용. 벽: GEO.shell(profile, thickness), 튜브: GEO.tube(rOut, rIn, h), 모따기된 디스크: GEO.disc(r, h). 모서리는 선명하게 유지되고 곡선은 자동으로 부드럽게 음영 처리됩니다.
  • 블레이드 및 베인: GEO.rotor({ count, axis, r0, r1, chord, thick, camber, twist, pitch, sweep })는 실제 캠버, 비틀린 익형(NACA 두께)을 닫힌 솔리드로 구축하고 링으로 배열합니다. 코드, 두께 및 캠버에 [root, tip] 배열을 사용하세요.
  • 기어: GEO.gear({ teeth, module, width, bore, helix, spokes, rim }). 중심 거리 (z1 + z2) * module / 2에서 두 기어를 메쉬하고 역 톱니 비율로 회전시키되, 반 톱니 오프셋을 적용하세요.
  • 파이프, 호스, 와이어: GEO.pipe(points, r) (닫힘, 캡 있음). 포트에서 포트로 구조를 따라 경로를 지정하고, 절대 부품을 통과하지 않게 하세요.
  • 체결구: 모든 플랜지에 GEO.bolts(n, R, size, h). 스프링: GEO.spring(R, wire, turns, len). 상자: GEO.rbox(w, h, d, r) (항상 둥글게, 날카롭지 않게). 구멍이 있는 플레이트: GEO.extrude(shape, depth).
  • 질량 및 관성은 지오메트리에서 비롯됩니다: GEO.volume(geo)는 부피와 중심을 제공하고, 실제 밀도를 곱하세요.

깔끔함을 유지하기 위한 규칙:

  • 모든 부품은 닫힌 솔리드입니다(닫힌 선반 프로파일, 두께가 있는 쉘, 캡이 있는 파이프). 이것이 절개도가 단단한 단면을 그릴 수 있게 하는 이유입니다. 열린 표면은 절단 시 속이 빈 것으로 표시됩니다.
  • 아무것도 눈에 띄게 교차하거나 떠 있지 않습니다. 모든 부품은 그것을 고정하는 것과 접촉합니다(플랜지는 면 위에, 샤프트는 베어링 안에, 포스트는 바닥에 닿음). 클로즈업에서 조인트를 확인하세요.
  • 눈이 가는 곳에 디테일을 넣으세요: 플랜지의 볼트 원, 모따기, 립, 라벨 플레이트, 연료 라인, 하네스. 넓은 평평한 영역에는 이음매, 패널 라인 또는 텍스처 마감 처리를 하세요.
  • 기계에 베이스를 제공하세요: 스탠드, 크래들, 받침대, 벤치 또는 발이 바닥에 닿는 마운트. 실제 생활에서 기계는 거의 공중에 떠 있지 않습니다.
  • 예산: 최대 약 700k 삼각형과 200개의 메시. 반복되는 정적 부품은 GEO.merge / GEO.ring으로 병합하고, 움직이는 그룹은 분리하여 유지하세요.

4. 재료: 절대 단일 회색 금지

MAT.* 프리셋을 사용하세요; 측정된 반사율을 포함하여 강철, 티타늄, 알루미늄, 황동 및 구리가 나란히 있을 때 다르게 보입니다. 모든 프리셋은 재정의(color, roughness, clearcoat, 모든 MeshPhysicalMaterial 필드)와 finish(미세 거칠기 텍스처: 선반 부품의 turned 링, brushed 줄무늬, cast 얼룩, smudge, knurl)를 허용합니다.

용도프리셋
샤프트, 디스크, 가공 부품MAT.steel, MAT.stainless, MAT.chrome
하우징, 주조품MAT.aluminium, MAT.castIron, MAT.steelDark
블레이드, 항공우주MAT.titanium, MAT.inconel (+ heatGlow)
피팅, 배선MAT.brass, MAT.copper, MAT.gold
도장된 본체MAT.paint({ color }), MAT.satin, MAT.anodised({ color })
폴리머MAT.plastic, MAT.rubber, MAT.carbon
창문, 크리스탈MAT.glass, MAT.sapphire, MAT.ruby, MAT.enamel
빛, 화염, 뜨거운 가스MAT.glow, heatGlow(material, kelvin)

산업 디자이너처럼 팔레트를 선택하세요: 주로 금속과 한두 가지 도장된 색상, 최대 한 가지 악센트. 뜨거운 부품은 솔버의 온도에서 빛납니다(material.userData.heat.value = T).

5. 솔버: 진짜 숫자 아니면 없음

입력과 상태로부터 표시하는 모든 숫자까지 작고 순수한 함수를 작성하세요. 실제 단위와 실제 상수를 사용하세요. approach(1차 지연: 스풀업, 열 질량) 또는 rk4(스프링, 이스케이프먼트, 진자)로 동역학을 통합하세요. 그런 다음 솔버로부터 모션을 구동하세요: 솔버의 RPM은 샤프트를 회전시키고, 솔버의 유량은 입자를 움직이며, 온도는 금속을 가열합니다.

  • 하나의 주인공: lab.hero({ label, unit, max }) 그런 다음 매 틱마다 lab.setHero(value, { state, sub, bad }). state는 23단어(스풀업 중, 이륙, 질식 흐름). sub는 23개의 추가 숫자가 있는 한 줄입니다.
  • 하나의 슬라이더: lab.slider({ id, label, min, max, value, unit, ends }). 기계가 정말로 필요로 하는 경우에만 두 번째 슬라이더를 추가하세요.
  • 라벨은 단면 평면의 지점에서 정적 부품에 부착됩니다: lab.label(obj, 'HP 터빈', { at: [x, y, z], value: () => '12,979 rpm' }).
  • lab.how(words, equations)는 "계산 방법"을 채웁니다: 평범한 단어로 된 모델과 코드에 작성된 방정식. 단순화된 부분을 명시하세요.
  • 모션이 너무 빨라 보기 어려운 경우(2,700 rpm 팬), 느리게 표시하고 how에서 그렇게 말하세요("회전 1:60으로 표시됨"). 숫자를 절대 느리게 하지 마세요.
  • 1단계에서 기록한 공개 수치에 대해 작동점의 타당성을 확인하세요. 약 20% 이상 차이가 나면 숫자가 아닌 모델을 수정하세요.

6. 유체, 열 및 효과

  • lab.flow({ paths, count, length, color, parent }): 실제 유로(덕트를 통한 공기, 펌프를 통한 혈액, 퍽을 통한 물)를 따라 구축한 경로를 따라 흐르는 줄무늬. .speed를 솔버에서 설정하고 .opacity를 lab.state.cut에서 설정하여 절개도 내부에 표시되도록 하세요. 계산된 양(온도, 압력)으로 색상을 지정하세요.
  • lab.plume({ radius, length, dir, color: 'rocket' | 'jet', shocks }): 마하 다이아몬드가 있는 배기 가스; .power를 솔버에서 설정하세요.
  • lab.sparks.emit(worldPos, n, speed) 및 lab.shed(mesh, v, w)는 파손용: 불꽃은 중력과 함께 떨어지고 튕깁니다; 떨어진 부품은 바닥에 착지하는 강체가 됩니다.

7. 모드 (키트가 수행하며, 당신이 설정)

  • 분해: 각 lab.add/lab.mesh는 상위 프레임에서 explode: [dx, dy, dz](미터)를 사용합니다. 조립 축을 따라 부품을 이동하고, 외부 쉘을 가장 멀리, 코어는 제자리에 유지하세요. 나가는 길에 어떤 것도 서로 교차해서는 안 됩니다.
  • 절개: Lab에서 cut: { a, b, center, reach }. a와 b는 제거된 영역의 방향입니다: a = [0,0,1], b = [0,1,0]은 시청자 쪽으로 위쪽 사분면을 제거합니다(축이 있는 물체에 가장 적합). b = a는 절반을 제거합니다. 단면은 모든 닫힌 솔리드에 대해 자동으로 그려지며, 희미한 해치가 적용됩니다.
  • X-ray: 외부 케이싱의 xray: 'shell'은 이를 유리로 바꾸고 미세한 모서리를 추가하여 코어가 작동 중에 보이도록 합니다.
  • 슬로우 모션, 라벨, 일시 중지는 기본 제공됩니다(키 S, L, Space). 대화형 부분은 마우스 궤도, 슬라이더 및 버튼입니다.
  • 파괴: lab.breakIt({ label, run(lab), reset(lab) }). run은 솔버 상태를 변경하고(블레이드 분리, 밸브 스턱, 씰 파손) 솔버가 결과를 계산합니다. 주인공(bad: true)과 불꽃, 파편 또는 흔들림으로 표시하세요.

8. 비평가처럼 보기 (필수)

만든 모든 이미지를 렌더링하고 읽으세요. 스크립트를 사용하세요:

node scripts/shot.mjs <name>.html out/review.png                               # 첫 번째 보기
node scripts/shot.mjs <name>.html out/cut.png --js "lab.toggle('cut', true); lab.toggle('labels', true)"
node scripts/shot.mjs <name>.html out/near.png --js "lab.setView({ az: 70, el: 8, dist: 0.8, target: [x, y, z] })"
node scripts/shot.mjs <name>.html out/film --film 1,4,8,12,17,22,26                 # 영화 스틸

적어도 네 번의 검토 라운드를 수행하세요. 각각: 전체 보기, 라벨이 있는 절개도, 분해도, 두 개의 조인트 클로즈업, 그리고 영화 스틸. 기억 속의 실제 기계 제품 사진과 비교하세요: 비율, 부품 수, 재료, 빛이 어떻게 떨어지는지. 잘못된 것을 나열하고, 수정하고, 다시 렌더링하세요. 목록이 빌 때까지 멈추지 마세요. 샷 스크립트는 fps, 부품 수 및 삼각형을 출력합니다; 대화형 프레임 속도를 30 이상으로 유지하세요.

9. 영화

lab.autoFilm({ runBeat, runSub, breakBeat, breakSub, sliderTo })는 기계에서 표준 28초 스토리를 작성하며, 편집 캡션이 있는 번호가 매겨진 비트로 구성됩니다:

  1. 한 문장이 전체 브리핑입니다(프롬프트 바가 스스로 입력됨).
  2. Claude가 기계를 구축합니다(부품이 조립 순서대로 날아들고 카운터가 올라갑니다: "3,597개 중 84개 부품").
  3. 작동합니다(커서가 슬라이더를 드래그하고, 주인공 숫자가 솔버에서 올라갑니다).
  4. 열어 봅니다(단면 캡, 실시간 값이 있는 라벨).
  5. 분해합니다(분해).
  6. 파괴합니다(커서가 파괴 버튼을 클릭하고, 솔버가 실패를 결정합니다).

루프: 마지막 카메라 키가 첫 번째로 돌아갑니다. 사용자 정의 영화의 경우 lab.film('name', { len, assemble, shots, events })를 사용하세요: 샷은 카메라 키 { t, az, el, dist, target, fov }이고, 이벤트는 { t, beat: ['07', '굵은 문장.', '회색 문장.'], set: { cut: 1 }, slider: { id, to, dur }, cursor: { to: 'slider:id:0.8' | 'button:break' | [x, y], click: true }, do(lab) {} }입니다.

녹화 (Node 18+, Playwright with Chromium, ffmpeg 필요):

node scripts/record.mjs <name>.html out/<name>.mp4 --music freepd:Classical/Easy_Lemon
node scripts/record.mjs <name>.html out/<name>-portrait.mp4 --w 1080 --h 1350

페이지는 영화 모드(?film=1)로 실행됩니다: 시계는 레코더가 단계를 진행할 때만 움직이므로 모든 프레임이 완전하고 영화는 매 테이크마다 동일합니다. 레코더는 모든 스크린샷을 중단된 헤드리스 GPU가 반환할 수 있는 마젠타 프레임으로부터 보호하고, 완성된 영화를 스캔합니다; 어떤 프레임이 분홍색이면 0이 아닌 값으로 종료됩니다. FreePD의 음악은 CC0입니다; 그럼에도 트랙을 크레딧하세요.

화면에 쓰기

페이지는 대시보드가 아닌 에디토리얼입니다: 프롬프트 바, 이탤릭체 부제목이 있는 세리프 제목, 이탤릭체 단위와 얇은 막대가 있는 하나의 거대한 숫자, 한 줄의 지원 숫자, 하나의 슬라이더. 좋은 캡션처럼 작성하세요: 짧고, 구체적이며, 과장 없고, 공백이 있는 실제 단위(338 kN, 1,750 K, 4.2 L/min), 천 단위 구분. 비트 캡션은 굵은 문장과 회색 문장입니다.

인계할 때 할 말

HTML 파일의 경로, 영화 명령어, 공개 수치에 대해 솔버가 도달하는 작동점, 그리고 단순화한 모든 것을 제공하세요. 다음 기계를 제안하세요.

관련 스킬