home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xspringies / part04 < prev    next >
Encoding:
Text File  |  1993-04-28  |  40.9 KB  |  1,662 lines

  1. Newsgroups: comp.sources.x
  2. From: dmd@gradient.cis.upenn.edu (Douglas DeCarlo)
  3. Subject: v19i056:  xspringies - it's a spring simulator...no, it's a game, Part04/16
  4. Message-ID: <1993Mar26.161219.9691@sparky.imd.sterling.com>
  5. X-Md4-Signature: 85451a3e15a4c718bfe01bf641f610eb
  6. Date: Fri, 26 Mar 1993 16:12:19 GMT
  7. Approved: chris@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dmd@gradient.cis.upenn.edu (Douglas DeCarlo)
  10. Posting-number: Volume 19, Issue 56
  11. Archive-name: xspringies/part04
  12. Environment: X11
  13. Supersedes: xspringies: Volume 14, Issue 25-30
  14.  
  15. #!/bin/sh
  16. # to extract, remove the header and type "sh filename"
  17. if `test ! -d ./lib`
  18. then
  19.   mkdir ./lib
  20.   echo "mkdir ./lib"
  21. fi
  22. if `test ! -s ./lib/zingy.xsp`
  23. then
  24. echo "writting ./lib/zingy.xsp"
  25. cat > ./lib/zingy.xsp << '\BARFOO\'
  26. #1.0 *** XSpringies data file
  27. cmas 1
  28. elas 1
  29. kspr 10
  30. kdmp 1
  31. fixm 1
  32. shws 1
  33. cent -1
  34. frce 0 0 10 0
  35. frce 1 0 5 2
  36. frce 2 0 10 0
  37. frce 3 0 10000 1
  38. visc 0
  39. stck 0
  40. step 0.025
  41. prec 1
  42. adpt 0
  43. gsnp 20 0
  44. wall 1 1 1 1
  45. mass 1 171.935289037 308.205975009 -32.3569475661 -11.1228790452 1 1
  46. mass 2 184.344717499 319.761393874 -33.9275114697 -9.32414881597 1 1
  47. mass 3 199.652059239 329.255781513 -34.1569967299 -8.50938001294 1 1
  48. mass 4 215.756366128 332.754910417 -33.7557679284 -8.85344594067 1 1
  49. mass 5 232.636046245 329.179539271 -33.7944219518 -10.483547665 1 1
  50. mass 6 247.27317969 319.57188562 -34.1578742598 -10.4650492354 1 1
  51. mass 7 258.4947709 304.027351791 -33.6341992102 -10.5242309965 1 1
  52. mass 8 269.901010184 286.897041567 -19.8119971656 -1.50878323362 1 1
  53. mass 9 281.237342589 275.250479271 -17.223309771 0.760714273218 1 1
  54. mass 10 295.842676388 264.65162579 -17.3397948693 1.26456227504 1 1
  55. mass 11 311.902346148 266.100747153 -17.3316231365 -0.118343196776 1 1
  56. mass 12 327.141125787 274.688346675 -16.2094197998 -1.8325047945 1 1
  57. mass 13 337.343768574 284.456765366 -13.8181100654 -4.09258266147 1 1
  58. mass 14 348.539137599 296.239213714 -15.6027386294 -1.98672964671 1 1
  59. mass 15 268.80967555 440.790258556 -33.7795989133 -7.93987110031 1 1
  60. mass 16 257.899232823 162.277289195 -14.772834743 -2.80664196866 1 1
  61. mass 17 258 478 0 0 -1 1
  62. mass 18 259 123 0 0 -1 1
  63. spng 1 7 15 30 1 137.091210513
  64. spng 2 15 6 30 1 123.17873193
  65. spng 3 5 15 30 1 117.443603487
  66. spng 4 15 4 30 1 120.42009799
  67. spng 5 3 15 30 1 131.228807813
  68. spng 6 15 2 30 1 147.566933966
  69. spng 7 1 15 30 1 164.195006014
  70. spng 8 15 8 30 1 153.209007568
  71. spng 9 9 15 30 1 165.215011425
  72. spng 10 15 10 30 1 177.485210651
  73. spng 11 11 15 30 1 179.401783715
  74. spng 12 15 12 30 1 175.855053951
  75. spng 13 13 15 30 1 170.836178838
  76. spng 14 15 14 30 1 165.680415258
  77. spng 15 1 16 30 1 169.743924781
  78. spng 16 16 2 30 1 174.002873539
  79. spng 17 3 16 30 1 176.78235206
  80. spng 18 16 4 30 1 175.282628917
  81. spng 19 5 16 30 1 168.267643949
  82. spng 20 16 6 30 1 157.03502794
  83. spng 21 7 16 30 1 141.127601836
  84. spng 22 16 8 30 1 125.195846576
  85. spng 23 9 16 30 1 115.572488076
  86. spng 24 16 10 30 1 109.416634933
  87. spng 25 11 16 30 1 117.200682592
  88. spng 26 16 12 30 1 132.098448136
  89. spng 27 13 16 30 1 145.773797371
  90. spng 28 16 14 30 1 161.75598907
  91. spng 29 1 2 100 5 16.9705627485
  92. spng 30 2 3 100 5 18.0277563773
  93. spng 31 3 4 100 5 16.4924225025
  94. spng 32 4 5 100 5 17.2626765016
  95. spng 33 5 6 100 5 17.4928556845
  96. spng 34 6 7 100 5 19.2093727123
  97. spng 35 7 8 100 5 20.6155281281
  98. spng 36 8 9 100 5 16.2788205961
  99. spng 37 9 10 100 5 18.0277563773
  100. spng 38 10 11 100 5 16.1245154966
  101. spng 39 11 12 100 5 17.4928556845
  102. spng 40 12 13 100 5 14.1421356237
  103. spng 41 13 14 100 5 16.2788205961
  104. spng 42 17 15 100 5 38
  105. spng 43 16 18 100 5 39
  106. spng 44 1 3 100 5 34.8281495345
  107. spng 45 2 4 100 5 34.0147027034
  108. spng 46 3 5 100 5 33.0151480384
  109. spng 47 4 6 100 5 34.1760149813
  110. spng 48 5 7 100 5 36.1247837364
  111. spng 49 6 8 100 5 39.8246155035
  112. spng 50 7 9 100 5 36.7967389859
  113. spng 51 8 10 100 5 34.205262753
  114. spng 52 9 11 100 5 32.0156211872
  115. spng 53 10 12 100 5 32.8937684068
  116. spng 54 11 13 100 5 31.4006369362
  117. spng 55 12 14 100 5 30.4138126515
  118. spng 56 1 4 100 5 50.2493781056
  119. spng 57 2 5 100 5 49.244289009
  120. spng 58 3 6 100 5 48.6621002424
  121. spng 59 4 7 100 5 51.6236379966
  122. spng 60 5 8 100 5 56.5685424949
  123. spng 61 6 9 100 5 55.9732078766
  124. spng 62 7 10 100 5 54.4885309033
  125. spng 63 8 11 100 5 47.0106370942
  126. spng 64 9 12 100 5 46.0108682813
  127. spng 65 10 13 100 5 46.0651712251
  128. spng 66 11 14 100 5 47.5078940809
  129. \BARFOO\
  130. else
  131.   echo "will not over write ./lib/zingy.xsp"
  132. fi
  133. if `test ! -s ./lib/zwave.xsp`
  134. then
  135. echo "writting ./lib/zwave.xsp"
  136. cat > ./lib/zwave.xsp << '\BARFOO\'
  137. #1.0 *** XSpringies data file
  138. cmas 0.5
  139. elas 1
  140. kspr 100
  141. kdmp 1
  142. fixm 1
  143. shws 1
  144. cent -1
  145. frce 0 0 10 0
  146. frce 1 0 5 2
  147. frce 2 0 10 0
  148. frce 3 0 10000 1
  149. visc 0
  150. stck 0
  151. step 0.025
  152. prec 1
  153. adpt 0
  154. gsnp 20 1
  155. wall 0 0 0 0
  156. mass 1 21.639729 470.92505 13.392069 -44.74031 -0.5 1
  157. mass 2 51.711478 470.92861 2.9402828e-13 -1.9192124e-12 0.5 1
  158. mass 3 81.64936 470.93216 -8.6518787e-14 2.0792841e-12 0.5 1
  159. mass 4 111.58724 470.93571 3.6924324e-13 -2.1335293e-12 0.5 1
  160. mass 5 141.52512 470.93926 2.3528885e-14 1.228292e-12 0.5 1
  161. mass 6 171.463 470.9428 -1.2769644e-13 9.5427571e-15 0.5 1
  162. mass 7 201.40089 470.94635 -1.576758e-16 3.1216151e-13 0.5 1
  163. mass 8 231.33877 470.9499 -5.5718641e-13 4.9338204e-13 0.5 1
  164. mass 9 261.27665 470.95345 1.1301261e-12 -1.0338929e-12 0.5 1
  165. mass 10 291.21453 470.957 4.4260768e-13 1.1627536e-12 0.5 1
  166. mass 11 321.15241 470.96055 1.536321e-13 -1.938644e-12 0.5 1
  167. mass 12 351.09029 470.9641 -7.5005664e-14 2.7781487e-13 0.5 1
  168. mass 13 381.02817 470.96765 -3.1045444e-13 8.5054484e-13 0.5 1
  169. mass 14 410.96606 470.9712 -7.3361805e-13 1.5346888e-12 0.5 1
  170. mass 15 440.90394 470.97474 7.4892138e-13 -1.7485381e-13 0.5 1
  171. mass 16 470.84182 470.97829 5.6970896e-13 -1.4606473e-12 0.5 1
  172. mass 17 500.7797 470.98184 4.6491659e-13 1.1677946e-12 0.5 1
  173. mass 18 530.71758 470.98539 6.7910642e-13 1.116373e-12 0.5 1
  174. mass 19 560.65546 470.98894 5.2756933e-13 -3.9238237e-12 0.5 1
  175. mass 20 590.59334 470.99249 4.5201415e-13 1.9612051e-12 0.5 1
  176. mass 21 620.44133 470.99603 8.9880047 8.5159468 -0.5 1
  177. mass 22 590.61239 450.97498 -1.2519178e-12 8.0057266e-13 0.5 1
  178. mass 23 560.68208 430.88589 1.2166525e-12 1.3557465e-13 0.5 1
  179. mass 24 530.75177 410.7968 6.3251047e-13 1.3617275e-12 0.5 1
  180. mass 25 500.82146 390.70771 -2.18909e-12 2.8087122e-12 0.5 1
  181. mass 26 470.89115 370.61862 -1.5243802e-12 1.3536881e-12 0.5 1
  182. mass 27 440.96083 350.52953 -9.3463005e-13 2.0526322e-12 0.5 1
  183. mass 28 411.03052 330.44044 -1.9782396e-12 5.9056097e-13 0.5 1
  184. mass 29 381.10021 310.35135 9.9737993e-13 -1.0340691e-12 0.5 1
  185. mass 30 351.1699 290.26226 1.2384388e-13 3.738492e-13 0.5 1
  186. mass 31 321.23959 270.17317 -1.9281981e-12 1.6168234e-14 0.5 1
  187. mass 32 291.30927 250.08408 -1.6838465e-13 1.7544632e-12 0.5 1
  188. mass 33 261.37896 229.99499 -1.1266675e-12 -3.3049241e-13 0.5 1
  189. mass 34 231.44865 209.9059 -4.2246829e-13 8.6427946e-14 0.5 1
  190. mass 35 201.51834 189.81681 -1.369676e-12 9.4255072e-13 0.5 1
  191. mass 36 171.58803 169.72772 -7.700747e-13 1.494e-13 0.5 1
  192. mass 37 141.65771 149.63863 -5.5405463e-13 1.1322969e-12 0.5 1
  193. mass 38 111.7274 129.54954 -5.5710249e-13 7.0186294e-13 0.5 1
  194. mass 39 81.797091 109.46045 -1.6334023e-12 2.9069384e-12 0.5 1
  195. mass 40 51.866779 89.371356 -1.362396e-12 2.1966162e-12 0.5 1
  196. mass 41 22.105673 69.395837 -9.6851415 -22.137054 -0.5 1
  197. mass 42 51.908169 69.425832 1.0139043e-05 -0.00062120184 0.5 1
  198. mass 43 81.807739 69.456051 4.6818224e-06 -0.0009341814 0.5 1
  199. mass 44 111.70731 69.486334 -2.4960264e-06 -0.00033427139 0.5 1
  200. mass 45 141.60688 69.516565 -1.3791049e-06 5.3683436e-05 0.5 1
  201. mass 46 171.50645 69.546882 4.6598698e-06 -0.00076901234 0.5 1
  202. mass 47 201.40602 69.577237 4.5393996e-06 -0.0004633936 0.5 1
  203. mass 48 231.30559 69.607554 -4.2325143e-07 -0.00012803614 0.5 1
  204. mass 49 261.20516 69.637839 -3.6739255e-06 -0.00078432669 0.5 1
  205. mass 50 291.10473 69.667966 -4.5766946e-06 -0.00085760696 0.5 1
  206. mass 51 321.0043 69.698112 -4.4936329e-06 0.00012400123 0.5 1
  207. mass 52 350.90387 69.728366 -2.2494145e-06 -0.00017028775 0.5 1
  208. mass 53 380.80344 69.758602 -1.4282967e-06 0.0001854156 0.5 1
  209. mass 54 410.70301 69.788789 -3.3811341e-06 0.0011435902 0.5 1
  210. mass 55 440.60258 69.81895 -5.3698626e-06 0.00092986523 0.5 1
  211. mass 56 470.50215 69.849121 -4.7984152e-06 -0.00052070023 0.5 1
  212. mass 57 500.40172 69.879302 -2.9327322e-06 -0.00096433796 0.5 1
  213. mass 58 530.30129 69.909444 -1.9193701e-06 0.0003473992 0.5 1
  214. mass 59 560.20086 69.939621 -7.2717789e-07 0.00067834358 0.5 1
  215. mass 60 590.10043 69.96986 -6.7152209e-07 0.00095229897 0.5 1
  216. mass 61 620 70 -1.4489569e-17 0 -0.5 1
  217. spng 1 1 2 100 1 8
  218. spng 2 2 3 100 1 8
  219. spng 3 3 4 100 1 8
  220. spng 4 4 5 100 1 8
  221. spng 5 5 6 100 1 8
  222. spng 6 6 7 100 1 8
  223. spng 7 7 8 100 1 8
  224. spng 8 8 9 100 1 8
  225. spng 9 9 10 100 1 8
  226. spng 10 10 11 100 1 8
  227. spng 11 11 12 100 1 8
  228. spng 12 12 13 100 1 8
  229. spng 13 13 14 100 1 8
  230. spng 14 14 15 100 1 8
  231. spng 15 15 16 100 1 8
  232. spng 16 16 17 100 1 8
  233. spng 17 17 18 100 1 8
  234. spng 18 18 19 100 1 8
  235. spng 19 19 20 100 1 8
  236. spng 20 20 21 100 1 8
  237. spng 21 21 22 100 1 8
  238. spng 22 22 23 100 1 8
  239. spng 23 23 24 100 1 8
  240. spng 24 24 25 100 1 8
  241. spng 25 25 26 100 1 8
  242. spng 26 26 27 100 1 8
  243. spng 27 27 28 100 1 8
  244. spng 28 28 29 100 1 8
  245. spng 29 29 30 100 1 8
  246. spng 30 30 31 100 1 8
  247. spng 31 31 32 100 1 8
  248. spng 32 32 33 100 1 8
  249. spng 33 33 34 100 1 8
  250. spng 34 34 35 100 1 8
  251. spng 35 35 36 100 1 8
  252. spng 36 36 37 100 1 8
  253. spng 37 37 38 100 1 8
  254. spng 38 38 39 100 1 8
  255. spng 39 39 40 100 1 8
  256. spng 40 40 41 100 1 8
  257. spng 41 41 42 100 1 8
  258. spng 42 42 43 100 1 8
  259. spng 43 43 44 100 1 8
  260. spng 44 44 45 100 1 8
  261. spng 45 45 46 100 1 8
  262. spng 46 46 47 100 1 8
  263. spng 47 47 48 100 1 8
  264. spng 48 48 49 100 1 8
  265. spng 49 49 50 100 1 8
  266. spng 50 50 51 100 1 8
  267. spng 51 51 52 100 1 8
  268. spng 52 52 53 100 1 8
  269. spng 53 53 54 100 1 8
  270. spng 54 54 55 100 1 8
  271. spng 55 55 56 100 1 8
  272. spng 56 56 57 100 1 8
  273. spng 57 57 58 100 1 8
  274. spng 58 58 59 100 1 8
  275. spng 59 59 60 100 1 8
  276. spng 60 60 61 100 1 8
  277. \BARFOO\
  278. else
  279.   echo "will not over write ./lib/zwave.xsp"
  280. fi
  281. if `test ! -s ./misc.c`
  282. then
  283. echo "writting ./misc.c"
  284. cat > ./misc.c << '\BARFOO\'
  285. /* misc.c -- misc utility routines for xspringies
  286.  * Copyright (C) 1991,1992  Douglas M. DeCarlo
  287.  *
  288.  * This file is part of XSpringies, a mass and spring simulation system for X
  289.  *
  290.  * XSpringies is free software; you can redistribute it and/or modify
  291.  * it under the terms of the GNU General Public License as published by
  292.  * the Free Software Foundation; either version 1, or (at your option)
  293.  * any later version.
  294.  *
  295.  * XSpringies is distributed in the hope that it will be useful,
  296.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  297.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  298.  * GNU General Public License for more details.
  299.  * 
  300.  * You should have received a copy of the GNU General Public License
  301.  * along with XSpringies; see the file COPYING.  If not, write to
  302.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  303.  *
  304.  */
  305.  
  306. #include "defs.h"
  307.  
  308. #if defined(__STRICT_BSD__) || defined(__STDC__) || defined(_ANSI_C_SOURCE)
  309. extern void *malloc(), *realloc();
  310. #else
  311. extern char *malloc(), *realloc();
  312. #endif
  313.  
  314. /* malloc space, and call fatal if allocation fails */
  315. char *xmalloc (size)
  316. int size;
  317. {
  318.     register char *tmp = (char *)malloc(size);
  319.  
  320.     if (!tmp)
  321.       fatal ("Out of memory");
  322.  
  323.     return tmp;
  324. }
  325.  
  326. /* realloc space, and call fatal if re-allocation fails 
  327.    (also, call malloc if ptr is NULL) */
  328. char *xrealloc (ptr, size)
  329. char *ptr;
  330. int size;
  331. {
  332.     register char *tmp;
  333.  
  334.     if (ptr == NULL)
  335.       return (char *)xmalloc(size);
  336.  
  337.     tmp = (char *)realloc(ptr, size);
  338.  
  339.     if (!tmp)
  340.       fatal ("Out of memory");
  341.  
  342.     return tmp;
  343. }
  344. \BARFOO\
  345. else
  346.   echo "will not over write ./misc.c"
  347. fi
  348. if `test ! -s ./obj.c`
  349. then
  350. echo "writting ./obj.c"
  351. cat > ./obj.c << '\BARFOO\'
  352. /* obj.c -- xspringies object (masses, springs) handling
  353.  * Copyright (C) 1991,1992  Douglas M. DeCarlo
  354.  *
  355.  * This file is part of XSpringies, a mass and spring simulation system for X
  356.  *
  357.  * XSpringies is free software; you can redistribute it and/or modify
  358.  * it under the terms of the GNU General Public License as published by
  359.  * the Free Software Foundation; either version 1, or (at your option)
  360.  * any later version.
  361.  *
  362.  * XSpringies is distributed in the hope that it will be useful,
  363.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  364.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  365.  * GNU General Public License for more details.
  366.  * 
  367.  * You should have received a copy of the GNU General Public License
  368.  * along with XSpringies; see the file COPYING.  If not, write to
  369.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  370.  *
  371.  */
  372.  
  373. #include "defs.h"
  374. #include "obj.h"
  375.  
  376. #define MPROXIMITY    8.0
  377. #define SPROXIMITY    8.0
  378.  
  379. /* Object globals */
  380. mass *masses;
  381. spring *springs;
  382. int num_mass, num_spring;
  383. static int num_mass_alloc, num_spring_alloc;
  384. int fake_mass, fake_spring;
  385. static mass *masses_save = NULL;
  386. static spring *springs_save = NULL;
  387. static int num_mass_saved, num_mass_savedalloc, num_spring_saved, num_spring_savedalloc;
  388.  
  389. /* init_objects: create an initial set of masses and
  390.    springs to work with
  391.    */
  392. void init_objects()
  393. {
  394.     /* Create initial objects */
  395.     num_mass = 0;
  396.     num_mass_alloc = ALLOC_SIZE * 2;
  397.     masses = (mass *)xmalloc(sizeof(mass) * num_mass_alloc);
  398.  
  399.     num_spring = 0;
  400.     num_spring_alloc = ALLOC_SIZE;
  401.     springs = (spring *)xmalloc(sizeof(spring) * num_spring_alloc);
  402.     
  403.     fake_mass = create_mass();
  404.     masses[fake_mass].status = S_FIXED;
  405.     fake_spring = create_spring();
  406.     springs[fake_spring].status = 0;
  407.  
  408.     add_massparent(fake_mass, fake_spring);
  409.     springs[fake_spring].m1 = fake_mass;
  410. }
  411.  
  412. void attach_fake_spring(tomass)
  413. int tomass;
  414. {
  415.     add_massparent(fake_mass, fake_spring);
  416.     springs[fake_spring].m2 = tomass;
  417.     springs[fake_spring].status |= S_ALIVE;
  418.     springs[fake_spring].ks = mst.cur_ks;
  419.     springs[fake_spring].kd = mst.cur_kd;
  420. }
  421.  
  422. void kill_fake_spring()
  423. {
  424.     springs[fake_spring].status &= ~S_ALIVE;
  425. }
  426.  
  427. void move_fake_mass(mx, my)
  428. int mx, my;
  429. {
  430.     masses[fake_mass].x = mx;
  431.     masses[fake_mass].y = my;
  432. }
  433.  
  434. /* create_mass: return the index for a new mass,
  435.    possibly allocating more space if necesary
  436.    */
  437. int create_mass()
  438. {
  439.     if (num_mass >= num_mass_alloc) {
  440.     /* Allocate more masses */
  441.     num_mass_alloc += ALLOC_SIZE;
  442.     masses = (mass *)xrealloc(masses, sizeof(mass) * num_mass_alloc);
  443.     }
  444.     
  445.     /* Set parameters for new mass */
  446.     masses[num_mass].x = masses[num_mass].y = 0.0;
  447.     masses[num_mass].vx = masses[num_mass].vy = 0.0;
  448.     masses[num_mass].ax = masses[num_mass].ay = 0.0;
  449.     masses[num_mass].mass = masses[num_mass].elastic = 0.0;
  450.     masses[num_mass].radius = masses[num_mass].num_pars = 0;
  451.     masses[num_mass].pars = NULL;
  452.     masses[num_mass].status = S_ALIVE;
  453.  
  454.     /* Return next unused mass */
  455.     return num_mass++;
  456. }
  457.  
  458. /* create_spring: return the index for a new spring,
  459.    possibly allocating more space if necesary
  460.    */
  461. int create_spring()
  462. {
  463.     if (num_spring >= num_spring_alloc) {
  464.     /* Allocate more springs */
  465.     num_spring_alloc += ALLOC_SIZE;
  466.     springs = (spring *)xrealloc(springs, sizeof(spring) * num_spring_alloc);
  467.     }
  468.  
  469.     /* Set parameters for new spring */
  470.     springs[num_spring].ks = springs[num_spring].kd = 0.0;
  471.     springs[num_spring].restlen = 0.0;
  472.     springs[num_spring].m1 = springs[num_spring].m2 = 0;
  473.     springs[num_spring].status = S_ALIVE;
  474.  
  475.     /* Return next unused spring */
  476.     return num_spring++;
  477. }
  478.  
  479. void add_massparent(which, parent)
  480. int which, parent;
  481. {
  482.     int len = masses[which].num_pars++;
  483.  
  484.     masses[which].pars = (int *)xrealloc(masses[which].pars, (len + 1) * sizeof(int));
  485.  
  486.     masses[which].pars[len] = parent;
  487. }
  488.  
  489. void del_massparent(which, parent)
  490. int which, parent;
  491. {
  492.     int i;
  493.  
  494.     if (masses[which].status & S_ALIVE) {
  495.     for (i = 0; i < masses[which].num_pars; i++) {
  496.         if (masses[which].pars[i] == parent) {
  497.         if (i == masses[which].num_pars - 1) {
  498.             masses[which].num_pars--;
  499.         } else {
  500.             masses[which].pars[i] = masses[which].pars[--masses[which].num_pars];
  501.         }
  502.         return;
  503.         }
  504.     }
  505.     }
  506. }
  507.  
  508. /* delete_spring: delete a particular spring
  509.  */
  510. void delete_spring(which)
  511. int which;
  512. {
  513.     if (springs[which].status & S_ALIVE) {
  514.         springs[which].status = 0;
  515.     del_massparent(springs[which].m1, which);
  516.     del_massparent(springs[which].m2, which);
  517.     }
  518. }
  519.  
  520. /* delete_mass: delete a particular mass, and all springs
  521.    directly attached to it
  522.    */
  523. void delete_mass(which)
  524. int which;
  525. {
  526.     int i;
  527.  
  528.     if (masses[which].status & S_ALIVE) {
  529.     masses[which].status = 0;
  530.  
  531.     /* Delete all springs connected to it */
  532.     for (i = 0; i < masses[which].num_pars; i++) {
  533.         delete_spring(masses[which].pars[i]);
  534.     }
  535.     }
  536.  
  537.     if (which == mst.center_id)
  538.       mst.center_id = -1;
  539. }
  540.  
  541. /* delete_selected: delete all objects which
  542.    are currently selected
  543.    */
  544. void delete_selected()
  545. {
  546.     int i;
  547.  
  548.     for (i = 0; i < num_mass; i++) {
  549.     if (masses[i].status & S_SELECTED) {
  550.         delete_mass(i);
  551.     }
  552.     }
  553.  
  554.     for (i = 0; i < num_spring; i++) {
  555.     if (springs[i].status & S_SELECTED) {
  556.         delete_spring(i);
  557.     }
  558.     }
  559. }
  560.  
  561. void delete_all()
  562. {
  563.     int i;
  564.  
  565.     for (i = 0; i < num_mass; i++) {
  566.     free(masses[i].pars);
  567.     }
  568.     free(masses);
  569.     num_mass = num_mass_alloc = 0;
  570.     free(springs);
  571.     num_spring = num_spring_alloc = 0;
  572.     mst.center_id = -1;
  573. }
  574.  
  575. void reconnect_masses()
  576. {
  577.     int i;
  578.  
  579.     for (i = 0; i < num_mass; i++) {
  580.     masses[i].num_pars = 0;
  581.     masses[i].pars = NULL;
  582.     }
  583.  
  584.     for (i = 0; i < num_spring; i++) {
  585.     add_massparent(springs[i].m1, i);
  586.     add_massparent(springs[i].m2, i);
  587.     }
  588. }
  589.  
  590. void restore_state()
  591. {
  592.     delete_all();
  593.  
  594.     if (masses_save != NULL) {
  595.     num_mass = num_mass_saved;
  596.     num_mass_alloc = num_mass_savedalloc;
  597.     num_spring = num_spring_saved;
  598.     num_spring_alloc = num_spring_savedalloc;
  599.  
  600.     masses = (mass *)xmalloc(sizeof(mass) * num_mass_alloc);
  601.     bcopy(masses_save, masses, sizeof(mass) * num_mass_alloc);
  602.     springs = (spring *)xmalloc(sizeof(spring) * num_spring_alloc);
  603.     bcopy(springs_save, springs, sizeof(spring) * num_spring_alloc);
  604.  
  605.     reconnect_masses();
  606.     }
  607. }
  608.  
  609. void save_state()
  610. {
  611.     masses_save = (mass *)xmalloc(sizeof(mass) * num_mass_alloc);
  612.     bcopy(masses, masses_save, sizeof(mass) * num_mass_alloc);
  613.     num_mass_saved = num_mass;
  614.     num_mass_savedalloc = num_mass_alloc;
  615.  
  616.     springs_save = (spring *)xmalloc(sizeof(spring) * num_spring_alloc);
  617.     bcopy(springs, springs_save, sizeof(spring) * num_spring_alloc);
  618.     num_spring_saved = num_spring;
  619.     num_spring_savedalloc = num_spring_alloc;
  620. }
  621.  
  622. /* nearest_object:  Find the nearest spring or mass to the position
  623.    (x,y), or return -1 if none are close.  Set is_mass accordingly
  624.    */
  625. int nearest_object(x, y, is_mass)
  626. int x, y;
  627. boolean *is_mass;
  628. {
  629.     int i, closest = -1;
  630.     double dist, min_dist = MPROXIMITY * MPROXIMITY, rating, min_rating = draw_wid * draw_ht;
  631.     boolean masses_only = *is_mass;
  632.  
  633.     *is_mass = TRUE;
  634.  
  635.     if (masses_only)
  636.       min_dist = min_dist * 36;
  637.  
  638.     /* Find closest mass */
  639.     for (i = 0; i < num_mass; i++) {
  640.     if (masses[i].status & S_ALIVE) {
  641.         if ((dist = SQR(masses[i].x - (double)x) + SQR(masses[i].y - (double)y) - (double)SQR(masses[i].radius)) < min_dist) {
  642.         rating = SQR(masses[i].x - (double)x) + SQR(masses[i].y - (double)y);
  643.         if (rating < min_rating) {
  644.             min_dist = dist;
  645.             min_rating = rating;
  646.             closest = i;
  647.         }
  648.         }
  649.     }
  650.     }
  651.  
  652.     if (closest != -1)
  653.       return closest;
  654.  
  655.     if (masses_only)
  656.       return -1;
  657.  
  658.     *is_mass = TRUE;
  659.  
  660.     min_dist = SPROXIMITY;
  661.  
  662.     /* Find closest spring */
  663.     for (i = 0; i < num_spring; i++) {
  664.     double x1, x2, y1, y2;
  665.  
  666.     if (springs[i].status & S_ALIVE) {
  667.         x1 = masses[springs[i].m1].x;
  668.         y1 = masses[springs[i].m1].y;
  669.         x2 = masses[springs[i].m2].x;
  670.         y2 = masses[springs[i].m2].y;
  671.         
  672.         if (x > MIN(x1, x2) - SPROXIMITY && x < MAX(x1, x2) + SPROXIMITY &&
  673.         y > MIN(y1, y2) - SPROXIMITY && y < MAX(y1, y2) + SPROXIMITY) {
  674.         double a1, b1, c1, dAB, d;
  675.         
  676.         a1 = y2 - y1;
  677.         b1 = x1 - x2;
  678.         c1 = y1 * x2 - y2 * x1;
  679.         dAB = sqrt((double)(a1*a1 + b1*b1));
  680.         d = (x * a1 + y * b1 + c1) / dAB;
  681.         
  682.         dist = ABS(d);
  683.         
  684.         if (dist < min_dist) {
  685.             min_dist = dist;
  686.             closest = i;
  687.             *is_mass = FALSE;
  688.         }
  689.         }
  690.     }
  691.     }
  692.  
  693.     return closest;
  694. }
  695.  
  696. void eval_selection()
  697. {
  698.     int i;
  699.     double sel_mass, sel_elas, sel_ks, sel_kd;
  700.     boolean sel_fix;
  701.     boolean found = FALSE, changed = FALSE;
  702.     boolean mass_same, elas_same, ks_same, kd_same, fix_same;
  703.  
  704.     for (i = 0; i < num_mass; i++) {
  705.     if (masses[i].status & S_SELECTED) {
  706.         if (found) {
  707.         if (mass_same && masses[i].mass != sel_mass) {
  708.             mass_same = FALSE;
  709.         }
  710.         if (elas_same && masses[i].elastic != sel_elas) {
  711.             elas_same = FALSE;
  712.         }
  713.         if (fix_same && (masses[i].status & S_FIXED)) {
  714.             fix_same = FALSE;
  715.         }
  716.         } else {
  717.         found = TRUE;
  718.         sel_mass = masses[i].mass;
  719.         mass_same = TRUE;
  720.         sel_elas = masses[i].elastic;
  721.         elas_same = TRUE;
  722.             sel_fix = (masses[i].status & S_FIXED);
  723.         fix_same = TRUE;
  724.         }
  725.     }
  726.     }
  727.  
  728.     if (found) {
  729.     if (mass_same && sel_mass != mst.cur_mass) {
  730.         mst.cur_mass = sel_mass;
  731.         changed = TRUE;
  732.     }
  733.     if (elas_same && sel_elas != mst.cur_rest) {
  734.         mst.cur_rest = sel_elas;
  735.         changed = TRUE;
  736.     }
  737.     if (fix_same && sel_fix != mst.fix_mass) {
  738.         mst.fix_mass = sel_fix;
  739.         changed = TRUE;
  740.     }
  741.     }
  742.     
  743.     found = FALSE;
  744.     for (i = 0; i < num_spring; i++) {
  745.     if (springs[i].status & S_SELECTED) {
  746.         if (found) {
  747.         if (ks_same && springs[i].ks != sel_ks) {
  748.             ks_same = FALSE;
  749.         }
  750.         if (ks_same && springs[i].ks != sel_ks) {
  751.             ks_same = FALSE;
  752.         }
  753.         } else {
  754.         found = TRUE;
  755.         sel_ks = springs[i].ks;
  756.         ks_same = TRUE;
  757.             sel_kd = springs[i].kd;
  758.         kd_same = TRUE;
  759.         }
  760.     }
  761.     }
  762.  
  763.     if (found) {
  764.     if (ks_same && sel_ks != mst.cur_ks) {
  765.         mst.cur_ks = sel_ks;
  766.         changed = TRUE;
  767.     }
  768.     if (kd_same && sel_kd != mst.cur_kd) {
  769.         mst.cur_kd = sel_kd;
  770.         changed = TRUE;
  771.     }
  772.     }
  773.  
  774.     if (changed) {
  775.     redraw_widgets(FALSE);
  776.     }
  777. }
  778.  
  779. boolean anything_selected()
  780. {
  781.     int i;
  782.  
  783.     for (i = 0; i < num_mass; i++) {
  784.     if (masses[i].status & S_SELECTED)
  785.       return TRUE;
  786.     }
  787.     for (i = 0; i < num_spring; i++) {
  788.     if (springs[i].status & S_SELECTED)
  789.       return TRUE;
  790.     }
  791.     return FALSE;
  792. }
  793.  
  794. void select_object(selection, is_mass, shifted)
  795. int selection;
  796. boolean is_mass, shifted;
  797. {
  798.     if (is_mass) {
  799.     if (shifted) {
  800.         masses[selection].status ^= S_SELECTED;
  801.     } else {
  802.         masses[selection].status |= S_SELECTED;
  803.     }
  804.     } else {
  805.     if (shifted) {
  806.         springs[selection].status ^= S_SELECTED;
  807.     } else {
  808.         springs[selection].status |= S_SELECTED;
  809.     }
  810.     }
  811. }
  812.  
  813. void select_objects(ulx, uly, lrx, lry, shifted)
  814. int ulx, uly, lrx, lry;
  815. boolean shifted;
  816. {
  817.     int i;
  818.  
  819.     for (i = 0; i < num_mass; i++) {
  820.     if (masses[i].status & S_ALIVE) {
  821.         if (ulx <= masses[i].x && masses[i].x <= lrx && uly <= masses[i].y && masses[i].y <= lry) {
  822.         select_object(i, TRUE, FALSE);
  823.         }
  824.     }
  825.     }
  826.  
  827.     for (i = 0; i < num_spring; i++) {
  828.     if (springs[i].status & S_ALIVE) {
  829.         int m1, m2;
  830.  
  831.         m1 = springs[i].m1;
  832.         m2 = springs[i].m2;
  833.  
  834.         if (ulx <= masses[m1].x && masses[m1].x <= lrx && uly <= masses[m1].y && masses[m1].y <= lry &&
  835.         ulx <= masses[m2].x && masses[m2].x <= lrx && uly <= masses[m2].y && masses[m2].y <= lry) {
  836.         select_object(i, FALSE, FALSE);
  837.         }
  838.     }
  839.     }        
  840. }
  841.  
  842. void unselect_all()
  843. {
  844.     int i;
  845.  
  846.     for (i = 0; i < num_mass; i++) {
  847.     if (masses[i].status & S_SELECTED) {
  848.         masses[i].status &= ~S_SELECTED;
  849.     }
  850.     }
  851.  
  852.     for (i = 0; i < num_spring; i++) {
  853.     if (springs[i].status & S_SELECTED) {
  854.         springs[i].status &= ~S_SELECTED;
  855.     }
  856.     }    
  857. }
  858.  
  859. void select_all()
  860. {
  861.     int i;
  862.  
  863.     for (i = 0; i < num_mass; i++) {
  864.     if (masses[i].status & S_ALIVE) {
  865.         masses[i].status |= S_SELECTED;
  866.     }
  867.     }
  868.  
  869.     for (i = 0; i < num_spring; i++) {
  870.     if (springs[i].status & S_ALIVE) {
  871.         springs[i].status |= S_SELECTED;
  872.     }
  873.     }    
  874. }
  875.  
  876. void duplicate_selected()
  877. {
  878.     int i, j, *mapfrom, *mapto, num_map, num_map_alloc, spring_start;
  879.     int which;
  880.  
  881.     spring_start = num_spring;
  882.  
  883.     num_map = 0;
  884.     num_map_alloc = ALLOC_SIZE;
  885.     mapfrom = (int *)xmalloc(sizeof(int) * num_map_alloc);
  886.     mapto = (int *)xmalloc(sizeof(int) * num_map_alloc);
  887.  
  888.     for (i = 0; i < num_mass; i++) {
  889.     if (masses[i].status & S_SELECTED) {
  890.         if (num_map >= num_map_alloc) {
  891.         num_map_alloc += ALLOC_SIZE;
  892.         mapfrom = (int *)xrealloc(mapfrom, sizeof(int) * num_map_alloc);
  893.         mapto = (int *)xrealloc(mapto, sizeof(int) * num_map_alloc);
  894.         }
  895.  
  896.         which = create_mass();
  897.         mapto[num_map] = which;
  898.         mapfrom[num_map] = i;
  899.         num_map++;
  900.         masses[which] = masses[i];
  901.         masses[which].status &= ~S_SELECTED;
  902.         masses[which].num_pars = 0;
  903.         masses[which].pars = NULL;
  904.     }
  905.     }
  906.  
  907.     for (i = 0; i < spring_start; i++) {
  908.     if (springs[i].status & S_SELECTED) {
  909.         boolean m1done, m2done;
  910.  
  911.         m1done = m2done = FALSE;
  912.  
  913.         which = create_spring();
  914.         springs[which] = springs[i];
  915.         springs[which].status &= ~S_SELECTED;
  916.  
  917.         for (j = 0; (!m1done || !m2done) && j < num_map; j++) {
  918.         if (!m1done && springs[which].m1 == mapfrom[j]) {
  919.             springs[which].m1 = mapto[j];
  920.             add_massparent(mapto[j], which);
  921.             m1done = TRUE;
  922.         }
  923.         if (!m2done && springs[which].m2 == mapfrom[j]) {
  924.             springs[which].m2 = mapto[j];
  925.             add_massparent(mapto[j], which);
  926.             m2done = TRUE;
  927.         }
  928.         }
  929.         if (!m1done && !m2done) {
  930.         /* delete spring that isn't connected to anyone */
  931.         delete_spring(which);
  932.         }
  933.     }
  934.     }
  935.  
  936.     free(mapfrom);
  937.     free(mapto);
  938. }
  939.  
  940. void translate_selobj(dx, dy)
  941. int dx, dy;
  942. {
  943.     int i;
  944.  
  945.     for (i = 0; i < num_mass; i++) {
  946.     if (masses[i].status & S_SELECTED) {
  947.         masses[i].x += dx;
  948.         masses[i].y += dy;
  949.     }
  950.     }
  951. }
  952.  
  953. void changevel_selobj(vx, vy, relative)
  954. int vx, vy;
  955. boolean relative;
  956. {
  957.     int i;
  958.  
  959.     for (i = 0; i < num_mass; i++) {
  960.     if (masses[i].status & S_SELECTED) {
  961.         if (relative) {
  962.         masses[i].vx += vx;
  963.         masses[i].vy += vy;
  964.         } else {
  965.         masses[i].vx = vx;
  966.         masses[i].vy = vy;
  967.         }
  968.     }
  969.     }
  970. }
  971.  
  972. void tempfixed_obj(store)
  973. boolean store;
  974. {
  975.     int i;
  976.  
  977.     for (i = 0; i < num_mass; i++) {
  978.     if (masses[i].status & S_SELECTED) {
  979.         if (store) {
  980.         masses[i].status &= ~S_TEMPFIXED;
  981.         if (!(masses[i].status & S_FIXED)) {
  982.             masses[i].status |= (S_TEMPFIXED | S_FIXED);
  983.         }
  984.         } else {
  985.         if (masses[i].status & S_TEMPFIXED) {
  986.             masses[i].status &= ~S_FIXED;
  987.         }
  988.         }
  989.     }
  990.     }
  991. }
  992.  
  993. void set_sel_restlen()
  994. {
  995.     int i;
  996.     double dx, dy;
  997.  
  998.     for (i = 0; i < num_spring; i++) {
  999.     if (springs[i].status & S_SELECTED) {
  1000.         dx = masses[springs[i].m1].x - masses[springs[i].m2].x;
  1001.         dy = masses[springs[i].m1].y - masses[springs[i].m2].y;
  1002.         springs[i].restlen = sqrt(dx * dx + dy * dy);
  1003.     }
  1004.     }
  1005. }
  1006.  
  1007. void set_center()
  1008. {
  1009.     int i, cent = -1;
  1010.  
  1011.     for (i = 0; i < num_mass; i++) {
  1012.     if (masses[i].status & S_SELECTED) {
  1013.         if (cent != -1)
  1014.           return;
  1015.  
  1016.         cent = i;
  1017.     }
  1018.     }
  1019.  
  1020.     mst.center_id = cent;
  1021. }
  1022. \BARFOO\
  1023. else
  1024.   echo "will not over write ./obj.c"
  1025. fi
  1026. if `test ! -s ./obj.h`
  1027. then
  1028. echo "writting ./obj.h"
  1029. cat > ./obj.h << '\BARFOO\'
  1030. #define S_ALIVE        0x01
  1031. #define S_SELECTED    0x02
  1032. #define S_FIXED        0x04
  1033. #define S_TEMPFIXED    0x08
  1034.  
  1035. #define ALLOC_SIZE    32
  1036.  
  1037. typedef struct {
  1038.     /* Current position, velocity, acceleration */
  1039.     double x, y;
  1040.     double vx, vy;
  1041.     double ax, ay;
  1042.  
  1043.     /* Mass and radius of mass */
  1044.     double mass;
  1045.     double elastic;
  1046.     int radius;
  1047.  
  1048.     /* Connections to springs */
  1049.     int *pars;
  1050.     int num_pars;
  1051.  
  1052.     int status;
  1053.  
  1054.     /* RK temporary space */
  1055.     double cur_x, cur_y, cur_vx, cur_vy;
  1056.     double old_x, old_y, old_vx, old_vy;
  1057.     double test_x, test_y, test_vx, test_vy;
  1058.     double k1x, k1y, k1vx, k1vy;
  1059.     double k2x, k2y, k2vx, k2vy;
  1060.     double k3x, k3y, k3vx, k3vy;
  1061.     double k4x, k4y, k4vx, k4vy;
  1062. } mass;
  1063.  
  1064. typedef struct {
  1065.     /* Ks, Kd and rest length of spring */
  1066.     double ks, kd;
  1067.     double restlen;
  1068.  
  1069.     /* Connected to masses m1 and m2 */
  1070.     int m1, m2;
  1071.  
  1072.     int status;
  1073. } spring;
  1074.  
  1075. extern mass *masses;
  1076. extern spring *springs;
  1077. extern int num_mass, num_spring, fake_mass, fake_spring;
  1078.  
  1079. \BARFOO\
  1080. else
  1081.   echo "will not over write ./obj.h"
  1082. fi
  1083. if `test ! -s ./patchlevel.h`
  1084. then
  1085. echo "writting ./patchlevel.h"
  1086. cat > ./patchlevel.h << '\BARFOO\'
  1087. #define VERSION 1.1
  1088. #define PATCHLEVEL 0
  1089. \BARFOO\
  1090. else
  1091.   echo "will not over write ./patchlevel.h"
  1092. fi
  1093. if `test ! -s ./phys.c`
  1094. then
  1095. echo "writting ./phys.c"
  1096. cat > ./phys.c << '\BARFOO\'
  1097. /* phys.c -- xspringies physical modeling and numerical solving routines
  1098.  * Copyright (C) 1991,1992  Douglas M. DeCarlo
  1099.  *
  1100.  * This file is part of XSpringies, a mass and spring simulation system for X
  1101.  *
  1102.  * XSpringies is free software; you can redistribute it and/or modify
  1103.  * it under the terms of the GNU General Public License as published by
  1104.  * the Free Software Foundation; either version 1, or (at your option)
  1105.  * any later version.
  1106.  *
  1107.  * XSpringies is distributed in the hope that it will be useful,
  1108.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1109.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1110.  * GNU General Public License for more details.
  1111.  * 
  1112.  * You should have received a copy of the GNU General Public License
  1113.  * along with XSpringies; see the file COPYING.  If not, write to
  1114.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1115.  *
  1116.  */
  1117.  
  1118. #include "defs.h"
  1119. #include "obj.h"
  1120.  
  1121. #ifndef M_PI
  1122. #define M_PI    3.14159265358979323846
  1123. #endif
  1124.  
  1125. #define DT_MIN        0.0001
  1126. #define DT_MAX        0.5
  1127.  
  1128. #define MAXCON        1024
  1129.  
  1130. #define CONSTR_KS    1.0
  1131. #define CONSTR_KD    1.0
  1132.  
  1133. /* Do fudgy bounces */
  1134. #define BOUNCE_FUDGE    1
  1135.  
  1136. /* Stickiness calibration:  STICK_MAG = 1.0, means that a mass = 1.0 with gravity = 1.0 will remain
  1137.    stuck on a wall for all stickiness values > 1.0 */
  1138. #define STICK_MAG    1.0
  1139.  
  1140. void accumulate_accel()
  1141. {
  1142.     double gval, gmisc;
  1143.     double gx = 0, gy = 0, ogx = 0, ogy = 0;
  1144.     double center_x = draw_wid/2.0, center_y = draw_ht/2.0, center_rad = 1.0;
  1145.     mass *m, *m1, *m2;
  1146.     spring *s;
  1147.     register int i;
  1148.     
  1149.     /* ------------------ applied force effects ----------------------- */
  1150.  
  1151.     if (mst.center_id >= 0) {
  1152.     if (masses[mst.center_id].status & S_ALIVE) {
  1153.         center_x = masses[mst.center_id].x;
  1154.         center_y = masses[mst.center_id].y;
  1155.     } else {
  1156.         mst.center_id = -1;
  1157.     }
  1158.     }
  1159.  
  1160.     /* Do gravity */
  1161.     if (mst.bf_mode[FR_GRAV] > 0) {
  1162.     gval = mst.cur_grav_val[FR_GRAV];
  1163.     gmisc = mst.cur_misc_val[FR_GRAV];
  1164.     
  1165.     gx = COORD_DX(gval * sin(gmisc * M_PI / 180.0));
  1166.     gy = COORD_DY(gval * cos(gmisc * M_PI / 180.0));
  1167.     }
  1168.     
  1169.     /* Keep center of mass in the middle force */
  1170.     if (mst.bf_mode[FR_CMASS] > 0) {
  1171.     double mixix = 0.0, mixiy = 0.0, mivix = 0.0, miviy = 0.0, msum = 0.0;
  1172.     gval = mst.cur_grav_val[FR_CMASS];
  1173.     gmisc = mst.cur_misc_val[FR_CMASS];
  1174.     
  1175.     for (i = 0; i < num_mass; i++) {
  1176.         m = masses + i;
  1177.         if (i != mst.center_id && (m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1178.         msum += m->mass;
  1179.         mixix += m->mass * m->x;
  1180.         mixiy += m->mass * m->y;
  1181.         mivix += m->mass * m->vx;
  1182.         miviy += m->mass * m->vy;
  1183.         }
  1184.     }
  1185.     
  1186.     if (msum) {
  1187.         mixix /= msum;
  1188.         mixiy /= msum;
  1189.         mivix /= msum;
  1190.         miviy /= msum;
  1191.         
  1192.         mixix -= center_x;
  1193.         mixiy -= center_y;
  1194.  
  1195.         ogx -= (gval * mixix + gmisc * mivix) / msum;
  1196.         ogy -= (gval * mixiy + gmisc * miviy) / msum;
  1197.     }
  1198.     }
  1199.     
  1200.     /* Apply Gravity, CM and air drag to all masses */
  1201.     for (i = 0; i < num_mass; i++) {
  1202.     m = masses + i;
  1203.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1204.         /* Do viscous drag */
  1205.         if (i != mst.center_id) {
  1206.         m->ax = gx + ogx - mst.cur_visc * m->vx;
  1207.         m->ay = gy + ogy - mst.cur_visc * m->vy;
  1208.         } else {
  1209.         m->ax = gx - mst.cur_visc * m->vx;
  1210.         m->ay = gy - mst.cur_visc * m->vy;
  1211.         }
  1212.     }
  1213.     }
  1214.     
  1215.     /* Do point attraction force */
  1216.     if (mst.bf_mode[FR_PTATTRACT] > 0) {
  1217.     gval = mst.cur_grav_val[FR_PTATTRACT];
  1218.     gmisc = mst.cur_misc_val[FR_PTATTRACT];
  1219.     
  1220.     for (i = 0; i < num_mass; i++) {
  1221.         m = masses + i;
  1222.         if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1223.         double dx, dy, mag, fmag;
  1224.         
  1225.         dx = (center_x - m->x);
  1226.         dy = (center_y - m->y);
  1227.         mag = sqrt(dx * dx + dy * dy);
  1228.         
  1229.         if (mag < m->radius + center_rad) {
  1230.             dx *= mag / (m->radius + center_rad);
  1231.             dy *= mag / (m->radius + center_rad);
  1232.             mag = m->radius + center_rad;
  1233.         }
  1234.         
  1235.         fmag = gval / pow(mag, gmisc);
  1236.         
  1237.         m->ax += fmag * dx / mag;
  1238.         m->ay += fmag * dy / mag;
  1239.         }
  1240.     }
  1241.     }
  1242.     
  1243.     /* Wall attract/repel force */
  1244.     if (mst.bf_mode[FR_WALL] > 0) {
  1245.     double dax, day, dist;
  1246.     
  1247.     gval = -mst.cur_grav_val[FR_WALL];
  1248.     gmisc = mst.cur_misc_val[FR_WALL];
  1249.     
  1250.     for (i = 0; i < num_mass; i++) {
  1251.         m = masses + i;
  1252.         if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1253.         dax = day = 0;
  1254.         
  1255.         if (mst.w_left && (dist = m->x - m->radius) >= 0) {
  1256.             if (dist < 1)  dist = 1;
  1257.             dist = pow(dist, gmisc);
  1258.             dax -= gval / dist;
  1259.         }
  1260.         if (mst.w_right && (dist = draw_wid - m->radius - m->x) >= 0) {
  1261.             if (dist < 1)  dist = 1;
  1262.             dist = pow(dist, gmisc);
  1263.             dax += gval / dist;
  1264.         }
  1265.         if (mst.w_top && (dist = draw_ht - m->radius - m->y) >= 0) {
  1266.             if (dist < 1)  dist = 1;
  1267.             dist = pow(dist, gmisc);
  1268.             day += gval / dist;
  1269.         }
  1270.         if (mst.w_bottom && (dist = m->y - m->radius) >= 0) {
  1271.             if (dist < 1)  dist = 1;
  1272.             dist = pow(dist, gmisc);
  1273.             day -= gval / dist;
  1274.         }
  1275.         
  1276.         m->ax += dax;
  1277.         m->ay += day;
  1278.         }
  1279.     }
  1280.     }
  1281.     
  1282.     /* ------------------ spring effects ----------------------- */
  1283.     
  1284.     /* Spring compression/damping effects on masses */
  1285.     for (i = 0; i < num_spring; i++) {
  1286.     s = springs + i;
  1287.     if (s->status & S_ALIVE) {
  1288.         double dx, dy, force, forcex, forcey, mag, damp, mass1, mass2;
  1289.         
  1290.         m1 = masses + s->m1;
  1291.         m2 = masses + s->m2;
  1292.         
  1293.         dx = m1->x - m2->x;
  1294.         dy = m1->y - m2->y;
  1295.         
  1296.         if (dx || dy) {
  1297.         mag = sqrt(dx * dx + dy * dy);
  1298.         
  1299.         force = s->ks * (s->restlen - mag);
  1300.         if (s->kd) {
  1301.             damp = ((m1->vx - m2->vx) * dx + (m1->vy - m2->vy) * dy) / mag;
  1302.             force -= s->kd * damp;
  1303.         }
  1304.         
  1305.         force /= mag;
  1306.         forcex = force * dx;
  1307.         forcey = force * dy;
  1308.         
  1309.         mass1 = m1->mass;
  1310.         mass2 = m2->mass;
  1311.         
  1312.         m1->ax += forcex / mass1;
  1313.         m1->ay += forcey / mass1;
  1314.         m2->ax -= forcex / mass2;
  1315.         m2->ay -= forcey / mass2;
  1316.         }
  1317.     }
  1318.     }
  1319. }
  1320.  
  1321. void runge_kutta(h, testloc)
  1322. double h;
  1323. boolean testloc;
  1324. {
  1325.     mass *m;
  1326.     int i;
  1327.  
  1328.     accumulate_accel();
  1329.  
  1330.     /* k1 step */
  1331.     for (i = 0; i < num_mass; i++) {
  1332.     m = masses + i;
  1333.  
  1334.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1335.         /* Initial storage */
  1336.         m->cur_x = m->x;
  1337.         m->cur_y = m->y;
  1338.         m->cur_vx = m->vx;
  1339.         m->cur_vy = m->vy;
  1340.  
  1341.         m->k1x = m->vx * h;
  1342.         m->k1y = m->vy * h;
  1343.         m->k1vx = m->ax * h;
  1344.         m->k1vy = m->ay * h;
  1345.         
  1346.         m->x = m->cur_x + m->k1x / 2;
  1347.         m->y = m->cur_y + m->k1y / 2;
  1348.         m->vx = m->cur_vx + m->k1vx / 2;
  1349.         m->vy = m->cur_vy + m->k1vy / 2;
  1350.     }
  1351.     }
  1352.  
  1353.     accumulate_accel();
  1354.  
  1355.     /* k2 step */
  1356.     for (i = 0; i < num_mass; i++) {
  1357.     m = masses + i;
  1358.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1359.         m->k2x = m->vx * h;
  1360.         m->k2y = m->vy * h;
  1361.         m->k2vx = m->ax * h;
  1362.         m->k2vy = m->ay * h;
  1363.         
  1364.         m->x = m->cur_x + m->k2x / 2;
  1365.         m->y = m->cur_y + m->k2y / 2;
  1366.         m->vx = m->cur_vx + m->k2vx / 2;
  1367.         m->vy = m->cur_vy + m->k2vy / 2;
  1368.     }
  1369.     }
  1370.  
  1371.     accumulate_accel();
  1372.  
  1373.     /* k3 step */
  1374.     for (i = 0; i < num_mass; i++) {
  1375.     m = masses + i;
  1376.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1377.         m->k3x = m->vx * h;
  1378.         m->k3y = m->vy * h;
  1379.         m->k3vx = m->ax * h;
  1380.         m->k3vy = m->ay * h;
  1381.         
  1382.         m->x = m->cur_x + m->k3x;
  1383.         m->y = m->cur_y + m->k3y;
  1384.         m->vx = m->cur_vx + m->k3vx;
  1385.         m->vy = m->cur_vy + m->k3vy;
  1386.     }
  1387.     }
  1388.  
  1389.     accumulate_accel();
  1390.  
  1391.     /* k4 step */
  1392.     for (i = 0; i < num_mass; i++) {
  1393.     m = masses + i;
  1394.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1395.         m->k4x = m->vx * h;
  1396.         m->k4y = m->vy * h;
  1397.         m->k4vx = m->ax * h;
  1398.         m->k4vy = m->ay * h;
  1399.     }
  1400.     }
  1401.  
  1402.     /* Find next position */
  1403.     for (i = 0; i < num_mass; i++) {
  1404.     m = masses + i;
  1405.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1406.         if (testloc) {
  1407.         m->test_x = m->cur_x + (m->k1x/2.0 + m->k2x + m->k3x + m->k4x/2.0)/3.0;
  1408.         m->test_y = m->cur_y + (m->k1y/2.0 + m->k2y + m->k3y + m->k4y/2.0)/3.0;
  1409.         m->test_vx = m->cur_vx + (m->k1vx/2.0 + m->k2vx + m->k3vx + m->k4vx/2.0)/3.0;
  1410.         m->test_vy = m->cur_vy + (m->k1vy/2.0 + m->k2vy + m->k3vy + m->k4vy/2.0)/3.0;
  1411.         } else {
  1412.         m->x = m->cur_x + (m->k1x/2.0 + m->k2x + m->k3x + m->k4x/2.0)/3.0;
  1413.         m->y = m->cur_y + (m->k1y/2.0 + m->k2y + m->k3y + m->k4y/2.0)/3.0;
  1414.         m->vx = m->cur_vx + (m->k1vx/2.0 + m->k2vx + m->k3vx + m->k4vx/2.0)/3.0;
  1415.         m->vy = m->cur_vy + (m->k1vy/2.0 + m->k2vy + m->k3vy + m->k4vy/2.0)/3.0;
  1416.         }
  1417.     }
  1418.     }
  1419. }
  1420.  
  1421. void adaptive_runge_kutta()
  1422. {
  1423.     int i;
  1424.     mass *m;
  1425.     double err, maxerr;
  1426.  
  1427.   restart:
  1428.     if (mst.cur_dt > DT_MAX)
  1429.       mst.cur_dt = DT_MAX;
  1430.     if (mst.cur_dt < DT_MIN)
  1431.       mst.cur_dt = DT_MIN;
  1432.  
  1433.     runge_kutta(mst.cur_dt/2.0, FALSE);
  1434.     runge_kutta(mst.cur_dt/2.0, TRUE);
  1435.  
  1436.     for (i = 0; i < num_mass; i++) {
  1437.     m = masses + i;
  1438.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1439.         m->x = m->old_x;
  1440.         m->y = m->old_y;
  1441.         m->vx = m->old_vx;
  1442.         m->vy = m->old_vy;
  1443.     }
  1444.     }
  1445.     runge_kutta(mst.cur_dt, FALSE);
  1446.  
  1447.     /* Find error */
  1448.     maxerr = 0.00001;
  1449.     for (i = 0; i < num_mass; i++) {
  1450.     m = masses + i;
  1451.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1452.         err = fabs(m->x - m->test_x) + fabs(m->y - m->test_y) +
  1453.           fabs(m->vx - m->test_vx) + fabs(m->vy - m->test_vy);
  1454.  
  1455.         if (err > maxerr) {
  1456.         maxerr = err;
  1457.         }
  1458.     }
  1459.     }
  1460.  
  1461.     /* Fudgy scale factor -- user controlled */
  1462.     maxerr /= mst.cur_prec;
  1463.  
  1464.     if (maxerr < 1.0) {
  1465.     mst.cur_dt *= 0.9 * exp(-log(maxerr)/8.0);
  1466.     } else {
  1467.     if (mst.cur_dt > DT_MIN) {
  1468.         for (i = 0; i < num_mass; i++) {
  1469.         m = masses + i;
  1470.         if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1471.             m->x = m->old_x;
  1472.             m->y = m->old_y;
  1473.             m->vx = m->old_vx;
  1474.             m->vy = m->old_vy;
  1475.         }
  1476.         }
  1477.  
  1478.         mst.cur_dt *= 0.9 * exp(-log(maxerr)/4.0);
  1479.         
  1480.         goto restart;
  1481.     }
  1482.     }
  1483. }
  1484.  
  1485. boolean animate_obj()
  1486. {
  1487.     mass *m;
  1488.     spring *s;
  1489.     int i;
  1490.     double stick_mag;
  1491.     static int num_since = 0;
  1492.     static double time_elapsed = 0.0;
  1493.  
  1494.     /* Save initial values */
  1495.     for (i = 0; i < num_mass; i++) {
  1496.     m = masses + i;
  1497.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1498.         m->old_x = m->x;
  1499.         m->old_y = m->y;
  1500.         m->old_vx = m->vx;
  1501.         m->old_vy = m->vy;
  1502.     }
  1503.     }
  1504.  
  1505.     if (mst.adaptive_step) {
  1506.     boolean any_spring = FALSE;
  1507.  
  1508.     for (i = 0; i < num_spring; i++) {
  1509.         s = springs + i;
  1510.         if (s->status & S_ALIVE) {
  1511.         any_spring = TRUE;
  1512.         break;
  1513.         }
  1514.     }
  1515.  
  1516.     /* If no springs, then use dt=DEF_TSTEP */
  1517.     if (any_spring) {
  1518.         adaptive_runge_kutta();
  1519.     } else {
  1520.         runge_kutta(mst.cur_dt = DEF_TSTEP, FALSE);
  1521.     }
  1522.     } else {
  1523.     runge_kutta(mst.cur_dt, FALSE);
  1524.     }
  1525.  
  1526.     stick_mag = STICK_MAG * mst.cur_dt * mst.cur_stick;
  1527.  
  1528.     /* Crappy wall code */
  1529.     for (i = 0; i < num_mass; i++) {
  1530.     m = masses + i;
  1531.  
  1532.     if ((m->status & S_ALIVE) && !(m->status & S_FIXED)) {
  1533.         /* Delete "exploded" objects */
  1534.         if (m->ax - m->ax != 0.0 || m->ay - m->ay != 0.0 || m->x - m->x != 0.0 || m->y - m->y != 0.0) {
  1535.         delete_mass(i);
  1536.         continue;
  1537.         }
  1538.  
  1539.         /* Check if stuck to a wall */
  1540.         if (m->old_vx == 0.0 && m->old_vy == 0.0) {
  1541.         /* Left or right wall */
  1542.         if ((mst.w_left && ABS(m->old_x - m->radius) < 0.5) || (mst.w_right && ABS(m->old_x - draw_wid + m->radius) < 0.5)) {
  1543.             if (ABS(m->vx) < stick_mag / m->mass) {
  1544.             m->vx = m->vy = 0;
  1545.             m->x = m->old_x;
  1546.             m->y = m->old_y;
  1547.  
  1548.             continue;
  1549.             }
  1550.         } else if ((mst.w_bottom && ABS(m->old_y - m->radius) < 0.5) || (mst.w_top && ABS(m->old_y - draw_ht + m->radius) < 0.5)) {
  1551.             /* Top or bottom wall */
  1552.             if (ABS(m->vy) < stick_mag / m->mass) {
  1553.             m->vx = m->vy = 0;
  1554.             m->x = m->old_x;
  1555.             m->y = m->old_y;
  1556.  
  1557.             continue;
  1558.             }            
  1559.         }
  1560.         }
  1561.  
  1562.         /* Bounce off left or right wall */
  1563.         if (mst.w_left && m->x < m->radius && m->old_x >= m->radius) {
  1564.         m->x = m->radius;
  1565.  
  1566.         if (m->vx < 0) {
  1567.             m->vx = -m->vx * m->elastic;
  1568.             m->vy *= m->elastic;
  1569.             
  1570.             /* Get stuck if not going fast enough */
  1571.             if (m->vx > 0) {
  1572.             m->vx -= STICK_MAG * mst.cur_stick / m->mass;
  1573.             
  1574.             if (m->vx < 0) {
  1575.                 m->vx = m->vy = 0;
  1576.             }
  1577.             }
  1578.         }
  1579.         } else if (mst.w_right && m->x > draw_wid - m->radius && m->old_x <= draw_wid - m->radius) {
  1580.         m->x = draw_wid - m->radius;
  1581.         
  1582.         if (m->vx > 0) {
  1583.             m->vx = -m->vx * m->elastic;
  1584.             m->vy *= m->elastic;
  1585.             
  1586.             /* Get stuck if not going fast enough */
  1587.             if (m->vx < 0) {
  1588.             m->vx += STICK_MAG * mst.cur_stick / m->mass;
  1589.             
  1590.             if (m->vx > 0) {
  1591.                 m->vx = m->vy = 0;
  1592.             }
  1593.             }
  1594.         }
  1595.         }
  1596.         /* Stick to top or bottom wall */
  1597.         if (mst.w_bottom && m->y < m->radius && m->old_y >= m->radius) {
  1598.         m->y = m->radius;
  1599.         
  1600.         if (m->vy < 0) {
  1601.             m->vy = -m->vy * m->elastic;
  1602.             m->vx *= m->elastic;
  1603.             
  1604.             /* Get stuck if not going fast enough */
  1605.             if (m->vy > 0) {
  1606.             m->vy -= STICK_MAG * mst.cur_stick / m->mass;
  1607.             
  1608.             if (m->vy < 0) {
  1609.                 m->vx = m->vy = 0;
  1610.             }
  1611.             }
  1612.         }
  1613.         } else if (mst.w_top && m->y > (draw_ht - m->radius) && m->old_y <= (draw_ht - m->radius)) {
  1614.         m->y = draw_ht - m->radius;
  1615.  
  1616.         if (m->vy > 0) {
  1617.             m->vy = -m->vy * m->elastic;
  1618.             m->vx *= m->elastic;
  1619.             
  1620.             /* Get stuck if not going fast enough */
  1621.             if (m->vy < 0) {
  1622.             m->vy += STICK_MAG * mst.cur_stick / m->mass;
  1623.             
  1624.             if (m->vy > 0) {
  1625.                 m->vx = m->vy = 0;
  1626.             }
  1627.             }
  1628.         }
  1629.         }
  1630.     }
  1631.     }
  1632.  
  1633.     time_elapsed += mst.cur_dt;
  1634.  
  1635.     if (time_elapsed > 0.05) {
  1636.         time_elapsed -= 0.05;
  1637.         num_since = 0;
  1638.         return TRUE;
  1639.     }
  1640.  
  1641.     num_since++;
  1642.  
  1643.     if (num_since > 8) {
  1644.         num_since = 0;
  1645.         return TRUE;
  1646.     }
  1647.     return FALSE;
  1648. }
  1649. \BARFOO\
  1650. else
  1651.   echo "will not over write ./phys.c"
  1652. fi
  1653. echo "Finished archive 4 of 16"
  1654. exit
  1655.  
  1656. exit 0 # Just in case...
  1657. -- 
  1658.   // chris@IMD.Sterling.COM            | Send comp.sources.x submissions to:
  1659. \X/  Amiga - The only way to fly!      |
  1660.  "It's intuitively obvious to the most |    sources-x@imd.sterling.com
  1661.   casual observer..."                  |
  1662.