Advertisement
here2share

$ JS_cloth_sim.html

Dec 17th, 2022
830
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <title>Stretchy Cloth Simulation</title>
  5. </head>
  6. <body>
  7.   <canvas id="clothCanvas" width="600" height="400"></canvas>
  8.   <button id="resetButton">Reset</button>
  9.   <script>
  10.     // Get canvas and context
  11.     const canvas = document.getElementById('clothCanvas');
  12.     const ctx = canvas.getContext('2d');
  13.  
  14.     // Set up cloth properties
  15.     const clothWidth = 50;
  16.     const clothHeight = 10;
  17.     const clothSpacing = 10;
  18.     const clothStiffness = 0.1;
  19.     const clothDamping = 0.98;
  20.     const clothMass = 1;
  21.     const gravity = 0.1;
  22.  
  23.     // Set up cloth points and constraints
  24.     let points = [];
  25.     let constraints = [];
  26.     for (let y = 0; y <= clothHeight; y++) {
  27.       for (let x = 0; x <= clothWidth; x++) {
  28.         let point = {
  29.           x: x * clothSpacing,
  30.           y: y * clothSpacing,
  31.           oldX: x * clothSpacing,
  32.           oldY: y * clothSpacing,
  33.           pinned: (x === 0 && y === 0) || (x === clothWidth && y === 0),
  34.           mass: clothMass
  35.         };
  36.         points.push(point);
  37.         if (x > 0) {
  38.           constraints.push({
  39.             pointA: points[points.length - 1],
  40.             pointB: points[points.length - 2],
  41.             length: clothSpacing,
  42.             stiffness: clothStiffness
  43.           });
  44.         }
  45.         if (y > 0) {
  46.           constraints.push({
  47.             pointA: points[points.length - 1],
  48.             pointB: points[points.length - clothWidth - 1],
  49.             length: clothSpacing,
  50.             stiffness: clothStiffness
  51.           });
  52.         }
  53.       }
  54.     }
  55.  
  56.     // Set up mouse interaction
  57.     let dragging = false;
  58.     let dragPoint;
  59.     canvas.addEventListener('mousedown', e => {
  60.       let rect = canvas.getBoundingClientRect();
  61.       let x = e.clientX - rect.left;
  62.       let y = e.clientY - rect.top;
  63.       points.forEach(point => {
  64.         if (Math.abs(point.x - x) < clothSpacing && Math.abs(point.y - y) < clothSpacing) {
  65.           dragPoint = point;
  66.           dragging = true;
  67.         }
  68.       });
  69.     });
  70.     canvas.addEventListener('mousemove', e => {
  71.       if (dragging) {
  72.         let rect = canvas.getBoundingClientRect();
  73.         let x = e.clientX - rect.left;
  74.         let y = e.clientY - rect.top;
  75.         dragPoint.x = x;
  76.         dragPoint.y = y;
  77.       }
  78.     });
  79.     canvas.addEventListener('mouseup', () => {
  80.       dragging = false;
  81.       dragPoint = null;
  82.     });
  83.     canvas.addEventListener('contextmenu', e => {
  84.       e.preventDefault();
  85.       if (dragPoint) {
  86.     dragPoint.pinned = !dragPoint.pinned;
  87.       }
  88.     });
  89. // Set up reset button
  90. const resetButton = document.getElementById('resetButton');
  91. resetButton.addEventListener('click', () => {
  92.   points.forEach(point => {
  93.     point.x = point.oldX;
  94.     point.y = point.oldY;
  95.   });
  96. });
  97.  
  98. // Set up animation loop
  99. function animate() {
  100.   // Update points
  101.   points.forEach(point => {
  102.     if (!point.pinned) {
  103.       let velocityX = (point.x - point.oldX) * clothDamping;
  104.       let velocityY = (point.y - point.oldY) * clothDamping;
  105.       point.oldX = point.x;
  106.       point.oldY = point.y;
  107.       point.x += velocityX;
  108.       point.y += velocityY + gravity;
  109.     }
  110.   });
  111.  
  112.   // Satisfy constraints
  113.   constraints.forEach(constraint => {
  114.     let pointA = constraint.pointA;
  115.     let pointB = constraint.pointB;
  116.     let length = constraint.length;
  117.     let stiffness = constraint.stiffness;
  118.  
  119.     let dx = pointB.x - pointA.x;
  120.     let dy = pointB.y - pointA.y;
  121.     let distance = Math.sqrt(dx * dx + dy * dy);
  122.     let difference = length - distance;
  123.     let percentage = difference / distance / 2;
  124.     let offsetX = dx * percentage;
  125.     let offsetY = dy * percentage;
  126.     if (!pointA.pinned) {
  127.       pointA.x -= offsetX;
  128.       pointA.y -= offsetY;
  129.     }
  130.     if (!pointB.pinned) {
  131.       pointB.x += offsetX;
  132.       pointB.y += offsetY;
  133.     }
  134.   });
  135.  
  136.   // Draw cloth
  137.   ctx.clearRect(0, 0, canvas.width, canvas.height);
  138.   ctx.beginPath();
  139.   points.forEach(point => {
  140.     ctx.lineTo(point.x, point.y);
  141.   });
  142.   ctx.stroke();
  143.   ctx.closePath();
  144.  
  145.   // Draw points
  146.   ctx.fillStyle = 'red';
  147.   points.forEach(point => {
  148.     ctx.beginPath();
  149.     ctx.arc(point.x, point.y, clothSpacing / 2, 0, 2 * Math.PI);
  150.     ctx.fill();
  151.   });
  152.  
  153.   requestAnimationFrame(animate);
  154. }
  155.  
  156. animate();
  157. </script>
  158. </body>
  159. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement