천 시뮬레이션
canvas
- Canvas
- 물리 시뮬레이션
- Verlet
- 인터랙션
코드
1<!DOCTYPE html>
2<html lang="ko">
3 <head>
4 <meta charset="UTF-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6 <title>천 시뮬레이션</title>
7 <link rel="stylesheet" href="./style.css" />
8 </head>
9 <body>
10 <canvas id="cloth">천 시뮬레이션 데모</canvas>
11 <p id="fallback"></p>
12 <div id="hint">드래그로 잡아당기기 · 세게 당기면 찢어짐 · 더블클릭 리셋</div>
13 <script src="./script.js"></script>
14 </body>
15</html>
16아이디어
천은 점(질량)과 그 사이를 잇는 제약(constraint)의 격자다. 각 점은 베를레 적분으로 움직이고, 제약은 매 프레임 길이를 원래대로 되돌리려 한다. 한계 이상으로 늘어난 제약은 끊어진다 — 그것이 '찢김'이다.
핵심 코드
베를레 적분은 속도를 저장하지 않는다. 현재 위치와 이전 위치의 차이가 곧 속도다.
1const vx = (p.x - p.px) * friction; 2const vy = (p.y - p.py) * friction; 3p.px = p.x; 4p.py = p.y; 5p.x += vx; 6p.y += vy + gravity * dt * dt;
제약 이완은 두 점을 원래 길이로 끌어당기고, 너무 늘어났으면 끊는다.
1const d = Math.hypot(dx, dy); 2if (d > rest * TEAR) removeConstraint(); 3else applyCorrection((rest - d) / d);
인터랙션
드래그로 천의 한 점을 잡아 끈다. 세게 당기면 제약이 한계를 넘어 찢어진다. 바람이 천을 흔든다. 더블클릭으로 리셋.