/examples/springies/source.scm

http://github.com/dharmatech/abstracting · Scheme · 441 lines · 258 code · 138 blank · 45 comment · 0 complexity · f23320325339aee2e8ae43dd4074a3b6 MD5 · raw file

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. (define (vector-nth i) (cut vector-ref <> i))
  3. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4. (define (scalar-projection a b)
  5. (/ (dot a b)
  6. (norm b)))
  7. (define (vector-projection a b)
  8. (pt*n (normalize b)
  9. (scalar-projection a b)))
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  11. (define (pt-sum-4 a b c d)
  12. (pt+ (pt+ (pt+ a b) c) d))
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. (define *nodes* #f)
  15. (define *springs* #f)
  16. (define *time-slice* #f)
  17. (define *gravity* #t)
  18. ;; (define *world-width* #f)
  19. ;; (define *world-height* #f)
  20. (define *world-width* 500)
  21. (define *world-height* 500)
  22. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  23. (define (node-id id)
  24. (list-ref *nodes* (- id 1)))
  25. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  26. (define (node pos vel mass elas)
  27. (let ((acc (pt 0.0 0.0))
  28. (force (pt 0.0 0.0))
  29. (cur-pos #f)
  30. (cur-vel #f)
  31. (pos-k1 #f)
  32. (vel-k1 #f)
  33. (pos-k2 #f)
  34. (vel-k2 #f)
  35. (pos-k3 #f)
  36. (vel-k3 #f)
  37. (pos-k4 #f)
  38. (vel-k4 #f))
  39. (let ((apply-force
  40. (lambda (v)
  41. (set! force (pt+ force v))))
  42. (reset-force
  43. (lambda ()
  44. (set! force (pt 0 0))))
  45. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  46. (new-acc (lambda () (pt/n force mass)))
  47. (new-vel (lambda () (pt+ vel (pt*n acc *time-slice*))))
  48. (new-pos (lambda () (pt+ pos (pt*n vel *time-slice*))))
  49. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  50. (k1-step
  51. (lambda ()
  52. (set! cur-pos pos)
  53. (set! cur-vel vel)
  54. (set! pos-k1 (pt*n vel *time-slice*))
  55. (set! vel-k1 (pt*n acc *time-slice*))
  56. (set! pos (pt+ cur-pos (pt/n pos-k1 2.0)))
  57. (set! vel (pt+ cur-vel (pt/n vel-k1 2.0)))))
  58. (k2-step
  59. (lambda ()
  60. (set! pos-k2 (pt*n vel *time-slice*))
  61. (set! vel-k2 (pt*n acc *time-slice*))
  62. (set! pos (pt+ cur-pos (pt/n pos-k2 2.0)))
  63. (set! vel (pt+ cur-vel (pt/n vel-k2 2.0)))))
  64. (k3-step
  65. (lambda ()
  66. (set! pos-k3 (pt*n vel *time-slice*))
  67. (set! vel-k3 (pt*n acc *time-slice*))
  68. (set! pos (pt+ cur-pos pos-k3))
  69. (set! vel (pt+ cur-vel vel-k3))))
  70. (k4-step
  71. (lambda ()
  72. (set! pos-k4 (pt*n vel *time-slice*))
  73. (set! vel-k4 (pt*n acc *time-slice*))))
  74. (find-next-position
  75. (let ((handle-bounce
  76. (let ((below? (lambda () (< (y pos) 0)))
  77. (above? (lambda () (>= (y pos) *world-height*)))
  78. (beyond-left? (lambda () (< (x pos) 0)))
  79. (beyond-right? (lambda () (>= (x pos) *world-width*)))
  80. (bounce-top
  81. (lambda ()
  82. (y! pos (- *world-height* 1.0))
  83. (y! vel (- (* (y vel) elas)))))
  84. (bounce-bottom
  85. (lambda ()
  86. (y! pos 0.0)
  87. (y! vel (- (* (y vel) elas)))))
  88. (bounce-left
  89. (lambda ()
  90. (x! pos 0.0)
  91. (x! vel (- (* (x vel) elas)))))
  92. (bounce-right
  93. (lambda ()
  94. (x! pos (- *world-width* 1.0))
  95. (x! vel (- (* (x vel) elas))))))
  96. (lambda ()
  97. (cond ((above?) (bounce-top))
  98. ((below?) (bounce-bottom))
  99. ((beyond-left?) (bounce-left))
  100. ((beyond-right?) (bounce-right))
  101. (else 'ok))))))
  102. (lambda ()
  103. (set! pos (pt+ cur-pos
  104. (pt/n (pt-sum-4 (pt/n pos-k1 2.0)
  105. pos-k2
  106. pos-k3
  107. (pt/n pos-k4 2.0))
  108. 3.0)))
  109. (set! vel (pt+ cur-vel
  110. (pt/n (pt-sum-4 (pt/n vel-k1 2.0)
  111. vel-k2
  112. vel-k3
  113. (pt/n vel-k4 2.0))
  114. 3.0)))
  115. (handle-bounce)))))
  116. (let ((update-acceleration
  117. (lambda ()
  118. (set! acc (new-acc))
  119. (reset-force))))
  120. (vector 'node
  121. (lambda () pos)
  122. (lambda () vel)
  123. apply-force
  124. k1-step
  125. k2-step
  126. k3-step
  127. k4-step
  128. find-next-position
  129. update-acceleration
  130. (lambda (new) (set! vel new)))
  131. ))))
  132. (define (pos node) ((vector-ref node 1)))
  133. (define (vel node) ((vector-ref node 2)))
  134. (define (apply-force node v) ((vector-ref node 3) v))
  135. (define (k1-step node) ((vector-ref node 4)))
  136. (define (k2-step node) ((vector-ref node 5)))
  137. (define (k3-step node) ((vector-ref node 6)))
  138. (define (k4-step node) ((vector-ref node 7)))
  139. (define (find-next-position node) ((vector-ref node 8)))
  140. (define (update-acceleration node) ((vector-ref node 9)))
  141. (define (vel! node new) ((vector-ref node 10) new))
  142. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  143. (define (apply-gravity node)
  144. (apply-force node (pt 0 -9.8)))
  145. (define (do-gravity)
  146. (if *gravity*
  147. (for-each apply-gravity *nodes*)))
  148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  149. ;; spring
  150. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  151. (define (spring rest-length k damp node-a node-b)
  152. (vector 'spring rest-length k damp node-a node-b))
  153. (define rest-length (vector-nth 1))
  154. (define k (vector-nth 2))
  155. (define damp (vector-nth 3))
  156. (define node-a (vector-nth 4))
  157. (define node-b (vector-nth 5))
  158. (define (spring-length spr)
  159. (norm (pt- (pos (node-b spr))
  160. (pos (node-a spr)))))
  161. (define (stretch-length spr)
  162. (- (spring-length spr)
  163. (rest-length spr)))
  164. (define (dir spr)
  165. (normalize (pt- (pos (node-b spr))
  166. (pos (node-a spr)))))
  167. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  168. ;; Hooke
  169. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  170. ;;
  171. ;; F = -kx
  172. ;;
  173. ;; k :: spring constant
  174. ;; x :: distance stretched beyond rest length
  175. ;;
  176. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  177. (define hooke-force-mag (bi k stretch-length *)) ;; spring -- mag
  178. (define hooke-force (bi dir hooke-force-mag pt*n)) ;; spring -- force
  179. (define (act-on-nodes-hooke spr)
  180. (let ((F (hooke-force spr)))
  181. (apply-force (node-a spr) F)
  182. (apply-force (node-b spr) (pt-neg F))))
  183. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  184. ;; damping
  185. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  186. ;;
  187. ;; F = -bv
  188. ;;
  189. ;; b :: Damping constant
  190. ;; v :: Velocity
  191. ;;
  192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  193. (define relative-velocity-a (bi (uni node-a vel) (uni node-b vel) pt-))
  194. (define unit-vec-b->a (bi (uni node-a pos) (uni node-b pos) pt-))
  195. (define relative-velocity-along-spring-a ;; spring -- vel
  196. (bi relative-velocity-a unit-vec-b->a vector-projection))
  197. (define damping-force-a
  198. (bi relative-velocity-along-spring-a damp (uni2 pt*n pt-neg)))
  199. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  200. (define relative-velocity-b (bi (uni node-b vel) (uni node-a vel) pt-))
  201. (define unit-vec-a->b (bi (uni node-b pos) (uni node-a pos) pt-))
  202. (define relative-velocity-along-spring-b ;; spring -- vel
  203. (bi relative-velocity-b unit-vec-a->b vector-projection))
  204. (define damping-force-b ;; spring -- vec
  205. (bi relative-velocity-along-spring-b damp (uni2 pt*n pt-neg)))
  206. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  207. (define (act-on-nodes-damping spr)
  208. (apply-force (node-a spr) (damping-force-a spr))
  209. (apply-force (node-b spr) (damping-force-b spr)))
  210. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  211. (define (act-on-nodes spr)
  212. (act-on-nodes-hooke spr)
  213. (act-on-nodes-damping spr))
  214. (define (loop-over-springs)
  215. (for-each act-on-nodes *springs*))
  216. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  217. (define (update-nodes-acceleration)
  218. (for-each update-acceleration *nodes*))
  219. (define (accumulate-acceleration)
  220. (do-gravity)
  221. (loop-over-springs)
  222. (update-nodes-acceleration))
  223. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  224. (define (iterate-system-runge-kutta)
  225. (accumulate-acceleration) (for-each k1-step *nodes*)
  226. (accumulate-acceleration) (for-each k2-step *nodes*)
  227. (accumulate-acceleration) (for-each k3-step *nodes*)
  228. (accumulate-acceleration) (for-each k4-step *nodes*)
  229. (for-each find-next-position *nodes*))
  230. (define iterate-system iterate-system-runge-kutta)
  231. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  232. (define (mass id x y x-vel y-vel mass elas)
  233. (set! *nodes*
  234. (append *nodes*
  235. (list
  236. (node (pt x y) (pt x-vel y-vel) mass elas)))))
  237. (define (spng id id-a id-b k damp rest-length)
  238. (set! *springs*
  239. (append *springs*
  240. (list
  241. (spring rest-length k damp (node-id id-a) (node-id id-b))))))
  242. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  243. (define (pt-gl-vertex p) (glVertex2d (x p) (y p)))
  244. (define (draw-node node)
  245. (let ((pos (pos node)))
  246. (glBegin GL_LINE_LOOP)
  247. (pt-gl-vertex (pt+ pos '#(pt -5 -5)))
  248. (pt-gl-vertex (pt+ pos '#(pt 5 -5)))
  249. (pt-gl-vertex (pt+ pos '#(pt 5 5)))
  250. (pt-gl-vertex (pt+ pos '#(pt -5 5)))
  251. (glEnd)))
  252. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  253. (define (draw-spring spring)
  254. (glBegin GL_LINES)
  255. (pt-gl-vertex (pos (node-a spring)))
  256. (pt-gl-vertex (pos (node-b spring)))
  257. (glEnd))
  258. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  259. (define (draw-nodes) (for-each draw-node *nodes*))
  260. (define (draw-springs) (for-each draw-spring *springs*))
  261. (define (display-system)
  262. (glClearColor 0.0 0.0 0.0 1.0)
  263. (glClear GL_COLOR_BUFFER_BIT)
  264. (draw-nodes)
  265. (draw-springs))
  266. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  267. (define (run-springies)
  268. (glutInitDisplayMode GLUT_DOUBLE)
  269. (glutInit (vector 0) (vector ""))
  270. (glutInitWindowSize 500 500)
  271. (glutCreateWindow "Springies")
  272. (glutReshapeFunc
  273. (lambda (w h)
  274. (set! *world-width* w)
  275. (set! *world-height* h)
  276. (glEnable GL_BLEND)
  277. (glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA)
  278. (glViewport 0 0 w h)
  279. (glMatrixMode GL_PROJECTION)
  280. (glLoadIdentity)
  281. (glOrtho 0.0 (- *world-width* 1.0) 0.0 (- *world-height* 1.0) -1.0 1.0)))
  282. (glutDisplayFunc
  283. (lambda ()
  284. (glMatrixMode GL_MODELVIEW)
  285. (glLoadIdentity)
  286. (display-system)
  287. (glutSwapBuffers)))
  288. (glutIdleFunc
  289. (lambda ()
  290. (iterate-system)
  291. (glutPostRedisplay)))
  292. (glutKeyboardFunc
  293. (lambda (key x y)
  294. (let ((key (if (char? key) key (integer->char key))))
  295. (case key
  296. ((#\2)
  297. (set! *time-slice* (- *time-slice* 0.01))
  298. (print "*time-slice* is now " *time-slice* "\n"))
  299. ((#\3)
  300. (set! *time-slice* (+ *time-slice* 0.01))
  301. (print "*time-slice* is now " *time-slice* "\n"))))))
  302. (glutMainLoop))
  303. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;