Advertisement
here2share

# tk_cloth_sim.py

Mar 26th, 2024 (edited)
684
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.43 KB | None | 0 0
  1. # tk_cloth_sim.py ZZZ
  2.  
  3. import tkinter as tk
  4. from random import uniform
  5.  
  6. cloth_width = 18
  7. cloth_height = 12
  8. cloth_spacing = 30
  9. cloth_damping = 0.98
  10. gravity = 0.1
  11. wind = 0.7
  12.  
  13. ww, hh = 600, 600
  14. root = tk.Tk()
  15. canvas = tk.Canvas(root, width=ww, height=hh)
  16. canvas.pack()
  17.  
  18. points = []
  19. constraints = []
  20. for y in range(cloth_height + 1):
  21.     for x in range(cloth_width + 1):
  22.         point = {
  23.             'x': x * cloth_spacing,
  24.             'y': y * cloth_spacing + 20,
  25.             'old_x': x * cloth_spacing,
  26.             'old_y': y * cloth_spacing,
  27.             'pinned': (x == 0 and y == 0) or (x == cloth_width and y == 0),
  28.         }
  29.         points.append(point)
  30.  
  31.     for x in range(cloth_width):
  32.         a = y * (cloth_width + 1) + x
  33.         b = a + 1
  34.         constraints.append({
  35.             'point_a': points[a],
  36.             'point_b': points[b],
  37.             'length': cloth_spacing,
  38.         })
  39.  
  40. for y in range(cloth_height):
  41.     for x in range(cloth_width + 1):
  42.         a = y * (cloth_width + 1) + x
  43.         b = a + cloth_width + 1
  44.         constraints.append({
  45.             'point_a': points[a],
  46.             'point_b': points[b],
  47.             'length': cloth_spacing,
  48.         })
  49.  
  50. points[cloth_width]['x'] = ww
  51. points[cloth_width]['pinned'] = True
  52.  
  53. drag_point = None
  54.  
  55. def on_mouse_down(event):
  56.     global drag_point
  57.     for point in points:
  58.         if abs(point['x'] - event.x) < cloth_spacing:
  59.             if abs(point['y'] - event.y) < cloth_spacing:
  60.                 drag_point = point
  61.                 drag_point['xm'] = event.x
  62.                 drag_point['ym'] = event.y
  63.                 return
  64.  
  65. def on_mouse_move(event):
  66.     if drag_point:
  67.         drag_point['x'] = drag_point['xm'] = event.x
  68.         drag_point['y'] = drag_point['ym'] = event.y
  69.  
  70. def on_mouse_up(event):
  71.     global drag_point
  72.     drag_point = None
  73.  
  74. canvas.bind('<ButtonPress-1>', on_mouse_down)
  75. canvas.bind('<B1-Motion>', on_mouse_move)
  76. canvas.bind('<ButtonRelease-1>', on_mouse_up)
  77.  
  78. while True:
  79.     for point in points:
  80.         if not point['pinned']:
  81.             velocity_x = (point['x'] - point['old_x']) * cloth_damping
  82.             velocity_y = (point['y'] - point['old_y']) * cloth_damping
  83.             point['old_x'] = point['x']
  84.             point['old_y'] = point['y']
  85.             point['x'] += velocity_x + uniform(-wind, wind)
  86.             point['y'] += velocity_y + gravity + uniform(-wind, wind)
  87.  
  88.     for constraint in constraints:
  89.         point_a = constraint['point_a']
  90.         point_b = constraint['point_b']
  91.         length = constraint['length']
  92.         dx = point_b['x'] - point_a['x']
  93.         dy = point_b['y'] - point_a['y']
  94.         distance = (dx ** 2 + dy ** 2) ** 0.5
  95.         difference = length - distance
  96.         percentage = difference / distance / 2
  97.         offset_x = dx * percentage
  98.         offset_y = dy * percentage
  99.         if not point_a['pinned']:
  100.             point_a['x'] -= offset_x
  101.             point_a['y'] -= offset_y
  102.         if not point_b['pinned']:
  103.             point_b['x'] += offset_x
  104.             point_b['y'] += offset_y
  105.            
  106.     if drag_point:
  107.         drag_point['x'] = drag_point['xm']
  108.         drag_point['y'] = drag_point['ym']
  109.  
  110.     canvas.delete('cloth')
  111.  
  112.     for y in range(cloth_height + 1):
  113.         point_coords = [(points[y * (cloth_width + 1) + x]['x'], points[y * (cloth_width + 1) + x]['y']) for x in range(cloth_width + 1)]
  114.         canvas.create_line(point_coords, tags='cloth', fill='black')
  115.  
  116.     for x in range(cloth_width + 1):
  117.         point_coords = [(points[y * (cloth_width + 1) + x]['x'], points[y * (cloth_width + 1) + x]['y']) for y in range(cloth_height + 1)]
  118.         canvas.create_line(point_coords, tags='cloth', fill='black')
  119.  
  120.     root.update()
  121.  
  122. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement