aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--msd2D/01_msd2Dtest.pd188
-rw-r--r--msd2D/02_msd2Dadd.pd436
-rw-r--r--msd2D/03_imsd2Dtest.pd191
-rw-r--r--msd2D/04_msd2Dperf.pd207
-rw-r--r--msd2D/Makefile.am51
-rw-r--r--msd2D/help-msd2D.pd78
-rwxr-xr-xmsd2D/main.cpp865
-rw-r--r--msd2D/package.txt2
-rw-r--r--msd3D/01_msd3Dtest.pd204
-rw-r--r--msd3D/02_msd3Dperf.pd145
-rw-r--r--msd3D/03_msd3Dmemb.pd155
-rw-r--r--msd3D/04_msd3Dfilet.pd146
-rw-r--r--msd3D/Makefile.am51
-rw-r--r--msd3D/filet.pd106
-rw-r--r--msd3D/help-msd3D.pd83
-rw-r--r--msd3D/imsd3Dball.pd146
-rwxr-xr-xmsd3D/main.cpp962
-rw-r--r--msd3D/msd3Dball.pd204
-rw-r--r--msd3D/package.txt2
19 files changed, 4222 insertions, 0 deletions
diff --git a/msd2D/01_msd2Dtest.pd b/msd2D/01_msd2Dtest.pd
new file mode 100644
index 0000000..8471b97
--- /dev/null
+++ b/msd2D/01_msd2Dtest.pd
@@ -0,0 +1,188 @@
+#N canvas 396 84 839 834 10;
+#X obj 52 15 loadbang;
+#X obj 314 524 print msd;
+#X obj 633 647 gemwin;
+#X msg 633 625 0 \, destroy;
+#X obj 553 709 gemhead;
+#X obj 553 732 world_light;
+#X msg 633 562 reset \, create \, lighting 1 \, 1;
+#X obj 53 499 msd2D --------------------------------;
+#X obj 122 15 cnv 15 500 270 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X obj 135 261 t a;
+#X obj 135 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 207 71 reset;
+#X text 173 21 reset;
+#X obj 135 42 t b b b b b;
+#X msg 153 160 50 50;
+#X msg 135 235 link souple \$1 \$2 \$3 \$4 \$5;
+#X msg 170 140 mass mob 1 \$1 \$2 \$3;
+#X msg 189 91 mass fix 0 100 50 50;
+#X msg 171 116 100 20 10 \, 200 20 25;
+#X msg 153 181 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0;
+#X obj 50 292 cnv 15 572 80 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#X obj 53 300 gemhead;
+#X obj 53 323 t b;
+#X msg 53 345 bang \, get massesPos \, get linksPos;
+#X text 413 87 CREATION : 3 MASSES \, 2 LINKS;
+#X text 292 313 COMPUTE AND GET ALL MASSES AND LINKS POSITIONS;
+#X obj 50 376 cnv 15 572 110 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X msg 82 442 forceX mob 100;
+#X msg 85 383 setD souple 0.01;
+#X msg 216 384 setK souple 1;
+#X msg 85 403 setD souple 1;
+#X msg 216 404 setK souple 2;
+#X msg 208 443 forceY mob 100;
+#X text 351 396 SET RIGIDITY AND VISCOSITY OF LINKS;
+#X text 367 442 ADD FORCE ON ALL MOBILE MASSES;
+#X obj 47 547 cnv 15 400 200 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 127 57 unpack f f;
+#X obj 125 136 t b f;
+#X connect 0 0 10 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 11 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 3 0;
+#X connect 10 1 5 0;
+#X connect 11 0 9 0;
+#X connect 11 1 1 1;
+#X restore 134 591 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 93 69 unpack f f f f;
+#X obj 44 265 curve 2;
+#X obj 207 121 / 12.5;
+#X obj 207 144 - 4;
+#X obj 261 122 / 12.5;
+#X obj 261 145 - 4;
+#X obj 123 194 pack f f;
+#X msg 123 217 \$1 \$2 0;
+#X obj 207 193 pack f f;
+#X msg 207 216 \$1 \$2 0;
+#X connect 0 0 9 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 15 1;
+#X connect 5 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 15 0;
+#X connect 9 0 1 0;
+#X connect 9 1 3 0;
+#X connect 9 2 11 0;
+#X connect 9 3 13 0;
+#X connect 11 0 12 0;
+#X connect 12 0 17 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 10 1;
+#X connect 17 0 18 0;
+#X connect 18 0 10 2;
+#X restore 53 612 pd linkrender;
+#X obj 53 562 route linksPos massesPos;
+#X text 261 572 DISPLAY MASSES AND LINKS;
+#X text 309 594 WITH GEM;
+#X text 465 563 1 CREATE WINDOW -->;
+#X text 464 626 3 AND DESTROY IT! -->;
+#X text 464 594 2 DRAG THE STRUCTURE WITH THE MOUSE;
+#X msg 135 213 0 1 5 0.5 0.5 \, 1 2 1 0.5 0;
+#N canvas 731 296 450 300 gemmouse 0;
+#X obj 189 77 gemmouse;
+#X obj 189 184 pack f f;
+#X obj 189 218 spigot;
+#X obj 103 244 outlet;
+#X obj 189 131 - 0;
+#X obj 216 131 + 100;
+#X obj 189 108 / 5;
+#X obj 216 108 / -5;
+#X obj 79 51 inlet;
+#X obj 140 75 inlet;
+#X obj 141 120 l;
+#X obj 109 98 t b;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 10 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 3 0;
+#X connect 11 0 10 0;
+#X restore 53 674 pd gemmouse;
+#X obj 53 653 gemhead;
+#X msg 53 695 posX fix \$1;
+#X msg 53 716 posY fix \$2;
+#X text 204 677 SET FIXED MASS TO MOUSE POSITION;
+#X connect 0 0 13 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 7 0 38 0;
+#X connect 7 1 1 0;
+#X connect 9 0 7 0;
+#X connect 10 0 13 0;
+#X connect 11 0 9 0;
+#X connect 13 0 44 0;
+#X connect 13 1 14 0;
+#X connect 13 1 19 0;
+#X connect 13 2 18 0;
+#X connect 13 3 17 0;
+#X connect 13 4 11 0;
+#X connect 14 0 45 1;
+#X connect 15 0 9 0;
+#X connect 16 0 9 0;
+#X connect 17 0 9 0;
+#X connect 18 0 16 0;
+#X connect 19 0 9 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 7 0;
+#X connect 27 0 7 0;
+#X connect 28 0 7 0;
+#X connect 29 0 7 0;
+#X connect 30 0 7 0;
+#X connect 31 0 7 0;
+#X connect 32 0 7 0;
+#X connect 38 0 37 0;
+#X connect 38 1 36 0;
+#X connect 44 0 15 0;
+#X connect 45 0 47 0;
+#X connect 45 0 48 0;
+#X connect 46 0 45 0;
+#X connect 47 0 7 0;
+#X connect 48 0 7 0;
diff --git a/msd2D/02_msd2Dadd.pd b/msd2D/02_msd2Dadd.pd
new file mode 100644
index 0000000..56a3e4b
--- /dev/null
+++ b/msd2D/02_msd2Dadd.pd
@@ -0,0 +1,436 @@
+#N canvas 534 65 716 776 10;
+#X obj 129 376 t a;
+#X obj 137 39 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 209 84 reset;
+#X obj 52 15 loadbang;
+#X obj 137 62 t b b b b b;
+#X obj 313 605 print msd;
+#X obj 52 583 msd2D --------------------------------;
+#X msg 511 526 0 \, destroy;
+#X obj 481 320 gemhead;
+#X obj 481 343 world_light;
+#X msg 191 106 mass fix 0 100 50 50;
+#N canvas 177 95 946 729 synthese 0;
+#X obj 140 66 t b f;
+#X obj 55 219 print x1;
+#X obj 180 139 + 1;
+#X obj 160 107 f 0;
+#X obj 236 45 inlet;
+#X msg 214 315 \$1 50;
+#X obj 214 337 line~;
+#X obj 174 341 *~;
+#X msg 309 315 \$1 50;
+#X obj 309 337 line~;
+#X obj 269 341 *~;
+#X msg 402 317 \$1 50;
+#X obj 402 339 line~;
+#X obj 362 343 *~;
+#X msg 494 315 \$1 50;
+#X obj 494 337 line~;
+#X obj 454 341 *~;
+#X obj 311 389 dac~;
+#X obj 185 255 / 200;
+#X obj 311 261 / 200;
+#X obj 402 263 / 200;
+#X obj 499 261 / 500;
+#X msg 595 318 \$1 50;
+#X obj 595 340 line~;
+#X obj 555 344 *~;
+#X msg 690 318 \$1 50;
+#X obj 690 340 line~;
+#X obj 650 344 *~;
+#X msg 783 320 \$1 50;
+#X obj 783 342 line~;
+#X obj 743 346 *~;
+#X msg 875 318 \$1 50;
+#X obj 875 340 line~;
+#X obj 835 344 *~;
+#X obj 692 392 dac~;
+#X obj 172 285 osc~ 55;
+#X obj 268 285 osc~ 110;
+#X obj 453 286 osc~ 222;
+#X obj 566 258 / 500;
+#X obj 693 264 / 500;
+#X obj 240 161 pack f f f;
+#X obj 231 72 unpack f f;
+#X obj 236 219 unpack f f;
+#X obj 425 225 unpack f f;
+#X obj 611 222 unpack f f;
+#X obj 802 229 unpack f f;
+#X obj 880 264 / 1000;
+#X obj 783 266 / 1000;
+#X obj 180 164 mod 8;
+#X obj 517 190 route 0 2 1 3 4 5 6 7;
+#X msg 204 519 \$1 50;
+#X obj 204 541 line~;
+#X obj 164 545 *~;
+#X msg 299 519 \$1 50;
+#X obj 299 541 line~;
+#X obj 259 545 *~;
+#X msg 392 521 \$1 50;
+#X obj 392 543 line~;
+#X obj 352 547 *~;
+#X msg 484 519 \$1 50;
+#X obj 484 541 line~;
+#X obj 444 545 *~;
+#X obj 301 593 dac~;
+#X obj 175 459 / 200;
+#X obj 301 465 / 200;
+#X obj 392 467 / 200;
+#X obj 489 465 / 500;
+#X msg 585 522 \$1 50;
+#X obj 585 544 line~;
+#X obj 545 548 *~;
+#X msg 680 522 \$1 50;
+#X obj 680 544 line~;
+#X obj 640 548 *~;
+#X msg 773 524 \$1 50;
+#X obj 773 546 line~;
+#X obj 733 550 *~;
+#X msg 865 522 \$1 50;
+#X obj 865 544 line~;
+#X obj 825 548 *~;
+#X obj 682 596 dac~;
+#X obj 162 489 osc~ 55;
+#X obj 258 489 osc~ 110;
+#X obj 351 491 osc~ 166;
+#X obj 443 489 osc~ 222;
+#X obj 544 492 osc~ 444;
+#X obj 639 492 osc~ 890;
+#X obj 732 494 osc~ 1113;
+#X obj 824 492 osc~ 2229;
+#X obj 556 462 / 500;
+#X obj 683 468 / 500;
+#X obj 226 423 unpack f f;
+#X obj 415 429 unpack f f;
+#X obj 601 426 unpack f f;
+#X obj 792 433 unpack f f;
+#X obj 870 468 / 1000;
+#X obj 773 470 / 1000;
+#X obj 361 287 osc~ 165;
+#X obj 554 288 osc~ 267;
+#X obj 649 288 osc~ 311;
+#X obj 742 290 osc~ 444;
+#X obj 834 288 osc~ 509;
+#X connect 0 0 3 0;
+#X connect 0 1 40 1;
+#X connect 2 0 48 0;
+#X connect 3 0 2 0;
+#X connect 4 0 41 0;
+#X connect 5 0 6 0;
+#X connect 6 0 7 1;
+#X connect 7 0 17 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 1;
+#X connect 10 0 17 0;
+#X connect 10 0 17 1;
+#X connect 11 0 12 0;
+#X connect 12 0 13 1;
+#X connect 13 0 17 0;
+#X connect 13 0 17 1;
+#X connect 14 0 15 0;
+#X connect 15 0 16 1;
+#X connect 16 0 17 1;
+#X connect 18 0 5 0;
+#X connect 19 0 8 0;
+#X connect 20 0 11 0;
+#X connect 21 0 14 0;
+#X connect 22 0 23 0;
+#X connect 23 0 24 1;
+#X connect 24 0 34 0;
+#X connect 25 0 26 0;
+#X connect 26 0 27 1;
+#X connect 27 0 34 0;
+#X connect 27 0 34 1;
+#X connect 28 0 29 0;
+#X connect 29 0 30 1;
+#X connect 30 0 34 0;
+#X connect 30 0 34 1;
+#X connect 31 0 32 0;
+#X connect 32 0 33 1;
+#X connect 33 0 34 1;
+#X connect 35 0 7 0;
+#X connect 36 0 10 0;
+#X connect 37 0 16 0;
+#X connect 38 0 22 0;
+#X connect 39 0 25 0;
+#X connect 40 0 49 0;
+#X connect 41 0 0 0;
+#X connect 41 1 40 2;
+#X connect 42 0 18 0;
+#X connect 42 1 19 0;
+#X connect 43 0 20 0;
+#X connect 43 1 21 0;
+#X connect 44 0 38 0;
+#X connect 44 1 39 0;
+#X connect 45 0 47 0;
+#X connect 45 1 46 0;
+#X connect 46 0 31 0;
+#X connect 47 0 28 0;
+#X connect 48 0 3 1;
+#X connect 48 0 40 0;
+#X connect 49 0 42 0;
+#X connect 49 1 43 0;
+#X connect 49 2 44 0;
+#X connect 49 3 45 0;
+#X connect 49 4 90 0;
+#X connect 49 5 91 0;
+#X connect 49 6 92 0;
+#X connect 49 7 93 0;
+#X connect 50 0 51 0;
+#X connect 51 0 52 1;
+#X connect 52 0 62 0;
+#X connect 53 0 54 0;
+#X connect 54 0 55 1;
+#X connect 55 0 62 0;
+#X connect 55 0 62 1;
+#X connect 56 0 57 0;
+#X connect 57 0 58 1;
+#X connect 58 0 62 0;
+#X connect 58 0 62 1;
+#X connect 59 0 60 0;
+#X connect 60 0 61 1;
+#X connect 61 0 62 1;
+#X connect 63 0 50 0;
+#X connect 64 0 53 0;
+#X connect 65 0 56 0;
+#X connect 66 0 59 0;
+#X connect 67 0 68 0;
+#X connect 68 0 69 1;
+#X connect 69 0 79 0;
+#X connect 70 0 71 0;
+#X connect 71 0 72 1;
+#X connect 72 0 79 0;
+#X connect 72 0 79 1;
+#X connect 73 0 74 0;
+#X connect 74 0 75 1;
+#X connect 75 0 79 0;
+#X connect 75 0 79 1;
+#X connect 76 0 77 0;
+#X connect 77 0 78 1;
+#X connect 78 0 79 1;
+#X connect 80 0 52 0;
+#X connect 81 0 55 0;
+#X connect 82 0 58 0;
+#X connect 83 0 61 0;
+#X connect 84 0 69 0;
+#X connect 85 0 72 0;
+#X connect 86 0 75 0;
+#X connect 87 0 78 0;
+#X connect 88 0 67 0;
+#X connect 89 0 70 0;
+#X connect 90 0 63 0;
+#X connect 90 1 64 0;
+#X connect 91 0 65 0;
+#X connect 91 1 66 0;
+#X connect 92 0 88 0;
+#X connect 92 1 89 0;
+#X connect 93 0 95 0;
+#X connect 93 1 94 0;
+#X connect 94 0 76 0;
+#X connect 95 0 73 0;
+#X connect 96 0 13 0;
+#X connect 97 0 24 0;
+#X connect 98 0 27 0;
+#X connect 99 0 30 0;
+#X connect 100 0 33 0;
+#X restore 230 679 pd synthese;
+#N canvas 311 224 316 299 gemmouse 0;
+#X obj 114 29 gemmouse;
+#X obj 114 136 pack f f;
+#X obj 114 170 spigot;
+#X obj 114 196 outlet;
+#X obj 114 83 - 0;
+#X obj 165 97 + 100;
+#X obj 114 60 / 5;
+#X obj 165 74 / -5;
+#X obj 68 97 l;
+#X obj 68 74 t b;
+#X obj 36 37 inlet;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 8 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 3 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X restore 253 493 pd gemmouse;
+#X obj 253 472 gemhead;
+#X msg 253 515 posX fix \$1;
+#X msg 253 537 posY fix \$2;
+#X msg 155 225 50 50;
+#X msg 155 258 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0;
+#X msg 511 503 reset \, create \, lighting 1 \, 1;
+#X obj 52 399 t b;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 127 57 unpack f f;
+#X obj 125 136 t b f;
+#X connect 0 0 10 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 11 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 3 0;
+#X connect 10 1 5 0;
+#X connect 11 0 9 0;
+#X connect 11 1 1 1;
+#X restore 141 657 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 93 69 unpack f f f f;
+#X obj 44 265 curve 2;
+#X obj 207 121 / 12.5;
+#X obj 207 144 - 4;
+#X obj 261 122 / 12.5;
+#X obj 261 145 - 4;
+#X obj 123 194 pack f f;
+#X msg 123 217 \$1 \$2 0;
+#X obj 207 193 pack f f;
+#X msg 207 216 \$1 \$2 0;
+#X connect 0 0 9 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 15 1;
+#X connect 5 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 15 0;
+#X connect 9 0 1 0;
+#X connect 9 1 3 0;
+#X connect 9 2 11 0;
+#X connect 9 3 13 0;
+#X connect 11 0 12 0;
+#X connect 12 0 17 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 10 1;
+#X connect 17 0 18 0;
+#X connect 18 0 10 2;
+#X restore 52 678 pd linkrender;
+#X msg 221 231 mass mob 1 \$1 \$2 \$3;
+#X obj 393 181 random 100;
+#X msg 393 161 seed 1;
+#X obj 318 181 random 100;
+#X obj 241 163 random 100;
+#X msg 318 160 seed 2;
+#X msg 241 143 seed 3;
+#X obj 241 183 + 100;
+#X obj 221 210 pack f f f;
+#X obj 79 208 t b;
+#X obj 79 252 + 1;
+#X obj 121 290 f;
+#X obj 121 270 + 1;
+#X obj 79 273 t f b;
+#X msg 112 229 -1;
+#X obj 79 229 f -1;
+#X obj 70 317 pack f f;
+#X obj 173 148 t b b b;
+#X msg 129 350 link souple \$1 \$2 100 0.5 0.5;
+#X obj 52 379 gemhead;
+#X obj 511 547 gemwin;
+#X obj 52 628 route linksPos massesPos massesSpeedsNo;
+#X msg 52 499 forceX mob -200;
+#X msg 52 420 bang \, get massesPos \, get linksPos \, get massesSpeeds
+1 5 9 13 17 21 25 29;
+#X obj 173 126 repeat 40;
+#X obj 79 187 repeat 40;
+#X msg 52 479 forceX mob 200;
+#X text 175 41 Reset;
+#X text 484 171 Random positions and masses;
+#X text 370 502 1 Create window -->;
+#X text 405 643 3 Drag mouse;
+#X text 174 480 Add force;
+#X msg 522 585 \; pd dsp 1;
+#X text 396 591 2 SET DSP ON -->;
+#X connect 0 0 6 0;
+#X connect 1 0 4 0;
+#X connect 2 0 0 0;
+#X connect 3 0 4 0;
+#X connect 4 0 47 0;
+#X connect 4 1 16 0;
+#X connect 4 1 17 0;
+#X connect 4 2 46 0;
+#X connect 4 3 10 0;
+#X connect 4 4 2 0;
+#X connect 4 4 36 0;
+#X connect 4 4 28 0;
+#X connect 4 4 24 0;
+#X connect 4 4 27 0;
+#X connect 6 0 43 0;
+#X connect 6 1 5 0;
+#X connect 7 0 42 0;
+#X connect 8 0 9 0;
+#X connect 10 0 0 0;
+#X connect 12 0 14 0;
+#X connect 12 0 15 0;
+#X connect 13 0 12 0;
+#X connect 14 0 6 0;
+#X connect 15 0 6 0;
+#X connect 16 0 12 0;
+#X connect 17 0 0 0;
+#X connect 18 0 42 0;
+#X connect 19 0 45 0;
+#X connect 22 0 0 0;
+#X connect 23 0 30 2;
+#X connect 24 0 23 0;
+#X connect 25 0 30 1;
+#X connect 26 0 29 0;
+#X connect 27 0 25 0;
+#X connect 28 0 26 0;
+#X connect 29 0 30 0;
+#X connect 30 0 22 0;
+#X connect 31 0 37 0;
+#X connect 32 0 34 0;
+#X connect 32 0 35 0;
+#X connect 32 0 37 1;
+#X connect 33 0 38 1;
+#X connect 34 0 33 1;
+#X connect 35 0 38 0;
+#X connect 35 1 33 0;
+#X connect 36 0 37 1;
+#X connect 37 0 32 0;
+#X connect 38 0 40 0;
+#X connect 39 0 26 0;
+#X connect 39 1 25 0;
+#X connect 39 2 23 0;
+#X connect 40 0 0 0;
+#X connect 41 0 19 0;
+#X connect 43 0 21 0;
+#X connect 43 1 20 0;
+#X connect 43 2 11 0;
+#X connect 44 0 6 0;
+#X connect 45 0 6 0;
+#X connect 46 0 39 0;
+#X connect 47 0 31 0;
+#X connect 48 0 6 0;
diff --git a/msd2D/03_imsd2Dtest.pd b/msd2D/03_imsd2Dtest.pd
new file mode 100644
index 0000000..d2c6b09
--- /dev/null
+++ b/msd2D/03_imsd2Dtest.pd
@@ -0,0 +1,191 @@
+#N canvas 483 96 839 834 10;
+#X obj 52 15 loadbang;
+#X obj 314 524 print msd;
+#X obj 633 647 gemwin;
+#X msg 633 625 0 \, destroy;
+#X obj 553 709 gemhead;
+#X obj 553 732 world_light;
+#X msg 633 562 reset \, create \, lighting 1 \, 1;
+#X obj 53 499 msd2D --------------------------------;
+#X obj 122 15 cnv 15 500 270 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X obj 135 261 t a;
+#X obj 135 20 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 221 71 reset;
+#X text 173 21 reset;
+#X msg 153 170 50 50;
+#X msg 203 91 mass fix 0 100 50 50;
+#X msg 169 192 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0;
+#X obj 50 292 cnv 15 572 80 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#X obj 53 300 gemhead;
+#X obj 53 323 t b;
+#X obj 50 376 cnv 15 572 110 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X msg 82 442 forceX mob 100;
+#X msg 85 383 setD souple 0.01;
+#X msg 216 384 setK souple 1;
+#X msg 85 403 setD souple 1;
+#X msg 216 404 setK souple 2;
+#X msg 208 443 forceY mob 100;
+#X text 351 396 SET RIGIDITY AND VISCOSITY OF LINKS;
+#X text 367 442 ADD FORCE ON ALL MOBILE MASSES;
+#X obj 47 547 cnv 15 400 200 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 127 57 unpack f f;
+#X obj 125 136 t b f;
+#X obj 48 229 sphere 0.2;
+#X connect 0 0 9 0;
+#X connect 1 0 11 0;
+#X connect 2 0 3 0;
+#X connect 3 0 10 0;
+#X connect 4 0 5 0;
+#X connect 5 0 1 2;
+#X connect 6 0 8 1;
+#X connect 7 0 1 0;
+#X connect 8 0 7 0;
+#X connect 9 0 2 0;
+#X connect 9 1 4 0;
+#X connect 10 0 8 0;
+#X connect 10 1 1 1;
+#X restore 134 591 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 93 69 unpack f f f f;
+#X obj 44 265 curve 2;
+#X obj 207 121 / 12.5;
+#X obj 207 144 - 4;
+#X obj 261 122 / 12.5;
+#X obj 261 145 - 4;
+#X obj 123 194 pack f f;
+#X msg 123 217 \$1 \$2 0;
+#X obj 207 193 pack f f;
+#X msg 207 216 \$1 \$2 0;
+#X connect 0 0 9 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 15 1;
+#X connect 5 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 15 0;
+#X connect 9 0 1 0;
+#X connect 9 1 3 0;
+#X connect 9 2 11 0;
+#X connect 9 3 13 0;
+#X connect 11 0 12 0;
+#X connect 12 0 17 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 10 1;
+#X connect 17 0 18 0;
+#X connect 18 0 10 2;
+#X restore 53 614 pd linkrender;
+#X text 465 563 1 CREATE WINDOW -->;
+#X text 464 626 3 AND DESTROY IT! -->;
+#X text 464 594 2 DRAG THE STRUCTURE WITH THE MOUSE;
+#N canvas 731 296 450 300 gemmouse 0;
+#X obj 189 77 gemmouse;
+#X obj 189 184 pack f f;
+#X obj 189 218 spigot;
+#X obj 103 244 outlet;
+#X obj 189 131 - 0;
+#X obj 216 131 + 100;
+#X obj 189 108 / 5;
+#X obj 216 108 / -5;
+#X obj 79 51 inlet;
+#X obj 140 75 inlet;
+#X obj 141 120 l;
+#X obj 109 98 t b;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 10 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 3 0;
+#X connect 11 0 10 0;
+#X restore 53 674 pd gemmouse;
+#X obj 53 653 gemhead;
+#X msg 53 695 posX fix \$1;
+#X msg 53 716 posY fix \$2;
+#X text 204 677 SET FIXED MASS TO MOUSE POSITION;
+#X msg 186 150 mass mob 1 100 \$1 \$2;
+#X obj 135 42 t b b b b b b;
+#X msg 135 234 iLink inter mob mob 1 2.5 0.5;
+#X msg 186 116 20 50 \, 23 61 \, 29 71 \, 39 77 \, 50 80 \, 61 77 \,
+71 71 \, 77 61 \, 80 50 \, 77 39 \, 71 29 \, 61 23 \, 50 20 \, 39 23
+\, 29 29 \, 23 39;
+#X text 413 87 CREATION : 17 MASSES \, 2 iLINKS;
+#X msg 152 215 iLink intf fix mob 10 2.5 0.5;
+#X msg 625 711 0.9 0.9 0.9;
+#X obj 53 562 route linksPos;
+#X msg 53 345 bang \, get linksPos;
+#X text 292 313 COMPUTE AND GET ALL LINKS POSITIONS;
+#X text 260 572 DISPLAY LINKS WITH GEM;
+#X connect 0 0 40 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 7 0 46 0;
+#X connect 7 1 1 0;
+#X connect 9 0 7 0;
+#X connect 10 0 40 0;
+#X connect 11 0 9 0;
+#X connect 13 0 34 1;
+#X connect 14 0 9 0;
+#X connect 15 0 9 0;
+#X connect 17 0 18 0;
+#X connect 18 0 47 0;
+#X connect 20 0 7 0;
+#X connect 21 0 7 0;
+#X connect 22 0 7 0;
+#X connect 23 0 7 0;
+#X connect 24 0 7 0;
+#X connect 25 0 7 0;
+#X connect 34 0 36 0;
+#X connect 34 0 37 0;
+#X connect 35 0 34 0;
+#X connect 36 0 7 0;
+#X connect 37 0 7 0;
+#X connect 39 0 9 0;
+#X connect 40 0 41 0;
+#X connect 40 1 44 0;
+#X connect 40 2 13 0;
+#X connect 40 2 15 0;
+#X connect 40 3 42 0;
+#X connect 40 4 14 0;
+#X connect 40 5 11 0;
+#X connect 41 0 9 0;
+#X connect 42 0 39 0;
+#X connect 44 0 9 0;
+#X connect 45 0 5 1;
+#X connect 46 0 30 0;
+#X connect 47 0 7 0;
diff --git a/msd2D/04_msd2Dperf.pd b/msd2D/04_msd2Dperf.pd
new file mode 100644
index 0000000..8f90db2
--- /dev/null
+++ b/msd2D/04_msd2Dperf.pd
@@ -0,0 +1,207 @@
+#N canvas 291 84 827 783 10;
+#X obj 167 310 t a;
+#X obj 167 33 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 239 84 reset;
+#X obj 52 15 loadbang;
+#X text 205 34 reset;
+#X msg 281 402 forceX mob 100;
+#X obj 167 55 t b b b b b;
+#X obj 313 658 print msd;
+#X obj 52 583 msd2D --------------------------------;
+#X msg 461 409 0 \, destroy;
+#X obj 481 320 gemhead;
+#X obj 481 343 world_light;
+#X msg 221 104 mass fix 0 100 50 50;
+#N canvas 311 224 450 300 gemmouse 0;
+#X obj 31 26 gemmouse;
+#X obj 31 133 pack f f;
+#X obj 31 167 spigot;
+#X obj 31 193 outlet;
+#X obj 31 80 - 0;
+#X obj 82 94 + 100;
+#X obj 31 57 / 5;
+#X obj 82 71 / -5;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X restore 393 540 pd gemmouse;
+#X obj 360 524 gemhead;
+#X obj 360 575 l;
+#X obj 360 552 t b;
+#X msg 360 602 posX fix \$1;
+#X msg 360 623 posY fix \$2;
+#X msg 185 192 50 50;
+#X msg 167 261 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0;
+#X msg 460 386 reset \, create \, lighting 1 \, 1;
+#X obj 52 301 t b;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 127 57 unpack f f;
+#X obj 125 136 t b f;
+#X connect 0 0 10 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 11 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 3 0;
+#X connect 10 1 5 0;
+#X connect 11 0 9 0;
+#X connect 11 1 1 1;
+#X restore 133 635 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 93 69 unpack f f f f;
+#X obj 44 265 curve 2;
+#X obj 207 121 / 12.5;
+#X obj 207 144 - 4;
+#X obj 261 122 / 12.5;
+#X obj 261 145 - 4;
+#X obj 123 194 pack f f;
+#X msg 123 217 \$1 \$2 0;
+#X obj 207 193 pack f f;
+#X msg 207 216 \$1 \$2 0;
+#X connect 0 0 9 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 15 1;
+#X connect 5 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 15 0;
+#X connect 9 0 1 0;
+#X connect 9 1 3 0;
+#X connect 9 2 11 0;
+#X connect 9 3 13 0;
+#X connect 11 0 12 0;
+#X connect 12 0 17 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 1;
+#X connect 15 0 16 0;
+#X connect 16 0 10 1;
+#X connect 17 0 18 0;
+#X connect 18 0 10 2;
+#X restore 52 656 pd linkrender;
+#X msg 211 170 mass mob 1 \$1 \$2 \$3;
+#X obj 379 180 random 100;
+#X msg 380 158 seed 1;
+#X obj 379 221 random 100;
+#X obj 470 179 random 100;
+#X msg 379 200 seed 2;
+#X msg 470 157 seed 3;
+#X obj 470 201 + 100;
+#X obj 219 140 pack f f f;
+#X obj 591 127 t b;
+#X obj 591 171 + 1;
+#X obj 627 221 f;
+#X obj 628 196 + 1;
+#X obj 568 204 t f b;
+#X msg 622 148 -1;
+#X obj 591 148 f -1;
+#X obj 582 248 pack f f;
+#X obj 380 134 t b b b;
+#X msg 167 284 link souple \$1 \$2 100 0.5 0.5;
+#X obj 52 278 gemhead;
+#X obj 413 432 gemwin;
+#X msg 52 335 bang \, get massesPos \, get linksPos;
+#X obj 52 606 route linksPos massesPos;
+#X msg 465 433 view 0 0 4 0 0 0 0 1 0;
+#X msg 281 425 forceX mob -100;
+#X obj 380 109 repeat 500;
+#X obj 592 105 repeat 500;
+#X msg 445 53 500;
+#X text 478 52 change number of mass to test performance;
+#X connect 0 0 8 0;
+#X connect 1 0 6 0;
+#X connect 2 0 0 0;
+#X connect 3 0 6 0;
+#X connect 5 0 8 0;
+#X connect 6 0 51 0;
+#X connect 6 1 19 0;
+#X connect 6 1 20 0;
+#X connect 6 2 50 0;
+#X connect 6 3 12 0;
+#X connect 6 4 2 0;
+#X connect 6 4 39 0;
+#X connect 6 4 31 0;
+#X connect 6 4 27 0;
+#X connect 6 4 30 0;
+#X connect 8 0 47 0;
+#X connect 8 1 7 0;
+#X connect 9 0 45 0;
+#X connect 10 0 11 0;
+#X connect 12 0 0 0;
+#X connect 13 0 15 1;
+#X connect 14 0 16 0;
+#X connect 15 0 17 0;
+#X connect 15 0 18 0;
+#X connect 16 0 15 0;
+#X connect 17 0 8 0;
+#X connect 18 0 8 0;
+#X connect 19 0 15 0;
+#X connect 20 0 0 0;
+#X connect 21 0 45 0;
+#X connect 22 0 46 0;
+#X connect 25 0 0 0;
+#X connect 26 0 33 2;
+#X connect 27 0 26 0;
+#X connect 28 0 33 1;
+#X connect 29 0 32 0;
+#X connect 30 0 28 0;
+#X connect 31 0 29 0;
+#X connect 32 0 33 0;
+#X connect 33 0 25 0;
+#X connect 34 0 40 0;
+#X connect 35 0 37 0;
+#X connect 35 0 38 0;
+#X connect 35 0 40 1;
+#X connect 36 0 41 1;
+#X connect 37 0 36 1;
+#X connect 38 0 41 0;
+#X connect 38 1 36 0;
+#X connect 39 0 40 1;
+#X connect 40 0 35 0;
+#X connect 41 0 43 0;
+#X connect 42 0 29 0;
+#X connect 42 1 28 0;
+#X connect 42 2 26 0;
+#X connect 43 0 0 0;
+#X connect 44 0 22 0;
+#X connect 46 0 8 0;
+#X connect 47 0 24 0;
+#X connect 47 1 23 0;
+#X connect 48 0 45 0;
+#X connect 49 0 8 0;
+#X connect 50 0 42 0;
+#X connect 51 0 34 0;
+#X connect 52 0 50 1;
+#X connect 52 0 51 1;
diff --git a/msd2D/Makefile.am b/msd2D/Makefile.am
new file mode 100644
index 0000000..59a3dff
--- /dev/null
+++ b/msd2D/Makefile.am
@@ -0,0 +1,51 @@
+#
+# automake template
+# added by tim blechmann
+#
+
+NAME = msd2
+
+BUILT_SOURCES = main.cpp
+
+EXTRA_DIST = main.cpp \
+ $(NAME).mcp \
+ $(NAME).vcproj
+
+CXXFLAGS = @CXXFLAGS@ \
+ @OPT_FLAGS@ \
+ @INCLUDEDIR@ \
+ -I../../source \
+ $(DEFS) \
+ -DFLEXT_SHARED
+
+LDFLAGS = @DYNAMIC_LDFLAGS@ @LDFLAGS@ \
+ $(patsubst %,-framework %,$(FRAMEWORKS))
+
+LIBS = @LIBS@ -lflext-pd
+
+FRAMEWORKS = @FRAMEWORKS@
+
+TARGETDIR = @TARGETDIR@
+
+TARGET =$(NAME).@EXTENSION@
+
+OBJECTS = $(patsubst %.cpp,./%.@OBJEXT@,$(BUILT_SOURCES))
+
+SYSDIR = @SYSDIR@
+
+
+# ----------------------------- targets --------------------------------
+
+all-local: $(OBJECTS)
+ $(CXX) $(LDFLAGS) ./*.@OBJEXT@ $(LIBS) -o ../$(TARGETDIR)/$(TARGET)
+ strip --strip-unneeded ../$(TARGETDIR)/$(TARGET)
+
+./%.@OBJEXT@ : %.cpp
+ $(CXX) -c $(CXXFLAGS) $< -o $@
+
+clean-local:
+ rm -f ../$(TARGETDIR)/$(TARGET)
+ rm -f ./$(OBJECTS)
+
+install-exec-local:
+ install ../$(TARGET) $(SYSDIR)extra
diff --git a/msd2D/help-msd2D.pd b/msd2D/help-msd2D.pd
new file mode 100644
index 0000000..9662c14
--- /dev/null
+++ b/msd2D/help-msd2D.pd
@@ -0,0 +1,78 @@
+#N canvas 0 0 823 885 10;
+#X obj 51 13 cnv 15 610 305 empty empty CREATION 20 12 0 14 -262131
+-66577 0;
+#X msg 68 42 reset;
+#X text 238 73 Add a mass;
+#X text 324 74 \$1 : Id (symbol);
+#X text 323 94 \$2 : fixed or mobile (0/1);
+#X text 323 112 \$3 : mass;
+#X text 323 150 \$1 : Id (symbol);
+#X text 235 150 Add a link;
+#X text 322 170 \$2 : creation No of mass1;
+#X text 322 188 \$3 : creation No of mass2;
+#X text 321 206 \$4 : rigidity;
+#X text 240 43 Delete all masses and links;
+#X text 321 224 \$5 : viscosity;
+#X text 321 241 \$6 : damping;
+#X obj 51 323 cnv 15 610 60 empty empty COMPUTATION 20 12 0 14 -261689
+-66577 0;
+#X msg 71 352 bang;
+#X text 224 352 Compute new masses positions;
+#X obj 50 387 cnv 15 610 220 empty empty DYNAMIC_SETTING 20 12 0 14
+-262131 -66577 0;
+#X msg 158 409 setD \$1 \$2;
+#X text 343 427 \$1 : Id (symbol);
+#X text 343 445 \$2 : New value;
+#X msg 76 409 setK \$1 \$2;
+#X text 339 481 \$1 : Id (symbol);
+#X text 339 499 \$2 : New value;
+#X text 337 538 \$1 : Id (symbol);
+#X text 337 556 \$2 : New value;
+#X msg 76 461 posX \$1 \$2;
+#X text 339 463 Set position of mass(es);
+#X text 336 521 Add force on mass(es);
+#X msg 74 520 forceX \$1 \$2;
+#X msg 244 409 setD2 \$1 \$2;
+#X text 343 409 Set rigidity \, viscosity or damping of link(s);
+#X obj 49 616 cnv 15 610 198 empty empty GET_ATTRIBUTES 20 12 0 14
+-261689 -66577 0;
+#X msg 135 643 massePosL;
+#X msg 135 671 masseForcesL;
+#X text 236 643 output all masses positions in a list on outlet No
+1;
+#X text 235 672 output all masses forces in a list on outlet No 1;
+#X msg 134 709 get \$1 \$2;
+#X text 237 710 Get specific attribute;
+#X text 237 735 \$1 : Attribute type ( massesPos / massesSpeeds / massesForces
+/ linksPos );
+#X text 237 772 \$2 : Id (symbol or creations numbers);
+#X msg 65 150 link \$1 \$2 \$3 \$4 \$5 \$6;
+#X msg 64 257 deleteMass \$1;
+#X text 229 259 Delete a mass and associated links;
+#X text 319 276 \$1 : Creation No of mass;
+#X msg 63 293 deleteLink \$1;
+#X text 228 295 Delete a link;
+#X text 329 295 \$1 : Creation No of link;
+#X msg 132 792 infosL;
+#X text 235 792 Get infos on all masses and links on outlet No 2;
+#X text 336 592 \$1 : Value;
+#X obj 22 820 msd2D;
+#X msg 169 519 forceY \$1 \$2;
+#X msg 158 461 posY \$1 \$2;
+#X msg 68 73 mass \$1 \$2 \$3 \$4 \$5;
+#X text 323 130 \$4 \, \$5 : position;
+#X msg 73 572 Xmin \$1 \, Xmax \$1 \, Ymin \$1 \, Ymax \$1;
+#X text 336 575 Set minimimum and maximum of masses positions;
+#X connect 1 0 51 0;
+#X connect 15 0 51 0;
+#X connect 21 0 51 0;
+#X connect 26 0 51 0;
+#X connect 29 0 51 0;
+#X connect 33 0 51 0;
+#X connect 34 0 51 0;
+#X connect 37 0 51 0;
+#X connect 41 0 51 0;
+#X connect 42 0 51 0;
+#X connect 45 0 51 0;
+#X connect 48 0 51 0;
+#X connect 54 0 51 0;
diff --git a/msd2D/main.cpp b/msd2D/main.cpp
new file mode 100755
index 0000000..9c8460a
--- /dev/null
+++ b/msd2D/main.cpp
@@ -0,0 +1,865 @@
+
+
+/*
+ msd2D - mass spring damper model for Pure Data or Max/MSP
+
+ Written by Nicolas Montgermont for a Master's train in Acoustic,
+ Signal processing and Computing Applied to Music (ATIAM, Paris 6)
+ at La Kitchen supervised by Cyrille Henry.
+
+ Based on Pure Data by Miller Puckette and others
+ Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net)
+ Based on pmpd by Cyrille Henry
+
+
+ Contact : Nicolas Montgermont, montgermont@la-kitchen.fr
+ Cyrille Henry, Cyrille.Henry@la-kitchen.fr
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Version 0.01, 12.04.2005
+
+*/
+
+// include flext header
+#include <flext.h>
+
+#include <math.h>
+
+// define constants
+#define MSD2D_VERSION 0.01
+#define nb_max_link 4000
+#define nb_max_mass 4000
+#define Id_length 20
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401)
+#error You need at least flext version 0.4.1
+#endif
+
+#define max(a,b) ( ((a) > (b)) ? (a) : (b) )
+#define min(a,b) ( ((a) < (b)) ? (a) : (b) )
+
+typedef struct _mass {
+ t_symbol *Id;
+ t_int nbr;
+ t_int mobile;
+ t_float invM;
+ t_float speedX;
+ t_float posX;
+ t_float posX2;
+ t_float forceX;
+ t_float out_forceX;
+ t_float speedY;
+ t_float posY;
+ t_float posY2;
+ t_float forceY;
+ t_float out_forceY;
+ char Id_string[Id_length];
+} t_mass;
+
+typedef struct _link {
+ t_symbol *Id;
+ t_int nbr;
+ t_mass *mass1;
+ t_mass *mass2;
+ t_float K1, D1, D2;
+ t_float longx, longy, longueur;
+ t_float distance_old;
+ char Id_string[Id_length];
+} t_link;
+
+class msd2D:
+ public flext_base
+{
+ FLEXT_HEADER_S(msd2D,flext_base,setup) //class with setup
+
+public:
+ // constructor with no arguments
+ msd2D(int argc,t_atom *argv)
+ {
+ nb_link = 0;
+ nb_mass = 0;
+ id_mass = 0;
+ id_link = 0;
+
+ // --- define inlets and outlets ---
+ AddInAnything("bang, reset, etc."); // default inlet
+ AddOutAnything("infos on masses"); // outlet for integer count
+ AddOutAnything("control"); // outlet for bang
+ }
+
+protected:
+
+// --------------------------------------------------------------- RESET
+
+ void m_reset()
+ {
+ t_int i;
+ t_atom sortie[0];
+
+ for (i=0; i<nb_mass; i++) {
+ delete mass[i];
+ }
+ for (i=0; i<nb_link; i++) {
+ delete link[i];
+ }
+ ToOutAnything(1,gensym("Reset"),0,sortie);
+ nb_link = 0;
+ nb_mass = 0;
+ id_mass = 0;
+ id_link = 0;
+ }
+
+// -------------------------------------------------------------- COMPUTE
+
+ void m_bang()
+ {
+ t_float F=0,Fx=0,Fy=0,distance,vitesse, X_new, Y_new;
+ t_int i;
+ struct _mass mass_1, mass_2;
+
+ for (i=0; i<nb_link; i++) {
+ // compute link forces
+ distance = sqrt(pow(link[i]->mass1->posX-link[i]->mass2->posX,2) +
+ pow(link[i]->mass1->posY-link[i]->mass2->posY,2));
+ F = link[i]->K1 * (distance - link[i]->longueur) ; // F = k1(x1-x2)
+ F += link[i]->D1 * (distance - link[i]->distance_old) ; // F = F + D1(v1-v2)
+ if (distance != 0) {
+ Fx = F * (link[i]->mass1->posX - link[i]->mass2->posX)/distance;
+ Fy = F * (link[i]->mass1->posY - link[i]->mass2->posY)/distance;
+ }
+ link[i]->mass1->forceX -= Fx;
+ link[i]->mass1->forceX -= link[i]->D2*link[i]->mass1->speedX;
+ link[i]->mass2->forceX += Fx;
+ link[i]->mass2->forceX -= link[i]->D2*link[i]->mass2->speedX;
+ link[i]->mass1->forceY -= Fy;
+ link[i]->mass1->forceY -= link[i]->D2*link[i]->mass1->speedY;
+ link[i]->mass2->forceY += Fy;
+ link[i]->mass2->forceY -= link[i]->D2*link[i]->mass2->speedY;
+ link[i]->distance_old = distance;
+ }
+
+ for (i=0; i<nb_mass; i++)
+ // compute new masses position only if mobile = 1
+ if (mass[i]->mobile == 1) {
+ X_new = mass[i]->forceX * mass[i]->invM + 2*mass[i]->posX - mass[i]->posX2;
+ mass[i]->posX2 = mass[i]->posX;
+ mass[i]->posX = max(min(X_new,Xmax),Xmin); // x = x + v
+ mass[i]->speedX = mass[i]->posX - mass[i]->posX2; // v = v + F/M
+ Y_new = mass[i]->forceY * mass[i]->invM + 2*mass[i]->posY - mass[i]->posY2;
+ mass[i]->posY2 = mass[i]->posY;
+ mass[i]->posY = max(min(Y_new,Ymax),Ymin); // x = x + v
+ mass[i]->speedY = mass[i]->posY - mass[i]->posY2; // v = v + F/M
+ }
+
+ for (i=0; i<nb_mass; i++) {
+ // clear forces
+ mass[i]->out_forceX = mass[i]->forceX;
+ mass[i]->forceX = 0;
+ mass[i]->out_forceY = mass[i]->forceY;
+ mass[i]->forceY = 0;
+ }
+ }
+
+// -------------------------------------------------------------- MASSES
+
+ void m_mass(int argc,t_atom *argv)
+ // add a mass
+ // Id, nbr, mobile, invM, speedX, posX, forceX
+ {
+ t_atom sortie[6], aux[2];
+ int M;
+
+ mass[nb_mass] = new t_mass; // new pointer
+ mass[nb_mass]->Id = GetASymbol(argv[0]); // ID
+ mass[nb_mass]->mobile = GetAInt(argv[1]); // mobile
+ if (GetAInt(argv[2])==0)
+ M=1;
+ else M = GetAInt(argv[2]);
+ mass[nb_mass]->invM = 1/((float)M); // invM
+ mass[nb_mass]->speedX = 0; // vx[n]
+ mass[nb_mass]->posX = GetAInt(argv[3]); // x[n]
+ mass[nb_mass]->posX2 = GetAInt(argv[3]); // x[n-1]
+ mass[nb_mass]->forceX = 0; // Fx[n]
+ mass[nb_mass]->speedY = 0; // vy[n]
+ mass[nb_mass]->posY = GetAInt(argv[4]); // y[n]
+ mass[nb_mass]->posY2 = GetAInt(argv[4]); // y[n-1]
+ mass[nb_mass]->forceY = 0; // Fy[n]
+ mass[nb_mass]->nbr = id_mass; // id_nbr
+ SETSYMBOL(aux,GetASymbol(argv[0]));
+ atom_string(aux,mass[nb_mass]->Id_string,Id_length);
+ nb_mass++ ;
+ id_mass++;
+ nb_mass = min ( nb_max_mass -1, nb_mass );
+ SETFLOAT(&(sortie[0]),id_mass-1);
+ SETSYMBOL(&(sortie[1]),GetASymbol(argv[0]));
+ SETFLOAT(&(sortie[2]),mass[nb_mass-1]->mobile);
+ SETFLOAT(&(sortie[3]),M);
+ SETFLOAT(&(sortie[4]),mass[nb_mass-1]->posX);
+ SETFLOAT(&(sortie[5]),mass[nb_mass-1]->posY);
+ ToOutAnything(1,gensym("Mass"),6,sortie);
+ }
+
+ void m_forceX(int argc,t_atom *argv)
+ {
+ // add a force to mass(es) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->forceX += GetAFloat(argv[1]);
+ }
+ }
+
+ void m_forceY(int argc,t_atom *argv)
+ {
+ // add a force to mass(es) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->forceY += GetAFloat(argv[1]);
+ }
+ }
+
+ void m_posX(int argc,t_atom *argv)
+ {
+ // displace mass(es) named Id to a certain position
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ if (GetAFloat(argv[1]) < Xmax && GetAFloat(argv[1]) > Xmin)
+ {
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->posX = GetAFloat(argv[1]);
+ }
+ }
+ }
+
+ void m_posY(int argc,t_atom *argv)
+ {
+ // displace mass(es) named Id to a certain position
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ if (GetAFloat(argv[1]) < Ymax && GetAFloat(argv[1]) > Ymin)
+ {
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->posY = GetAFloat(argv[1]);
+ }
+ }
+ }
+
+ void m_set_mobile(int argc,t_atom *argv)
+ {
+ // set mass No to mobile
+ t_int i,aux;
+
+ aux = GetAInt(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ {
+ if (mass[i]->nbr == aux)
+ mass[i]->mobile = 1;
+ }
+
+ }
+
+ void m_set_fixe(int argc,t_atom *argv)
+ {
+ // set mass No to fixed
+ t_int i,aux;
+
+ aux = GetAInt(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ {
+ if (mass[i]->nbr == aux)
+ mass[i]->mobile = 0;
+ }
+
+ }
+
+ void m_delete_mass(int argc,t_atom *argv)
+ {
+ // Delete mass
+ t_int i,nb_link_delete=0;
+ t_atom sortie[6], aux[nb_link];
+
+ for (i=0; i<nb_link;i++) {
+ if (link[i]->mass1->nbr == GetAInt(argv[0]) || link[i]->mass2->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(aux[nb_link_delete]),link[i]->nbr);
+ nb_link_delete++;
+ }
+ }
+
+ for (i=0; i<nb_link_delete;i++)
+ m_delete_link(1,&aux[i]);
+
+
+ for (i=0; i<nb_mass;i++)
+ if (mass[i]->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(sortie[0]),mass[i]->nbr);
+ SETSYMBOL(&(sortie[1]),mass[i]->Id);
+ SETFLOAT(&(sortie[2]),mass[i]->mobile);
+ SETFLOAT(&(sortie[3]),1/mass[i]->invM);
+ SETFLOAT(&(sortie[4]),mass[i]->posX);
+ SETFLOAT(&(sortie[5]),mass[i]->posY);
+ delete mass[i];
+ mass[i] = mass[nb_mass-1];
+ nb_mass--;
+ ToOutAnything(1,gensym("Mass deleted"),6,sortie);
+ break;
+ }
+ }
+
+
+ void m_Xmax(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ Xmax = GetAFloat(argv[0]);
+ }
+
+ void m_Ymax(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ Ymax = GetAFloat(argv[0]);
+ }
+
+ void m_Xmin(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ Xmin = GetAFloat(argv[0]);
+ }
+
+ void m_Ymin(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ Ymin = GetAFloat(argv[0]);
+ }
+
+// -------------------------------------------------------------- LINKS
+
+ void m_link(int argc,t_atom *argv)
+ // add a link
+ // Id, nbr, *mass1, *mass2, K1, D1
+ {
+ t_atom sortie[7], aux[2];
+ t_int i;
+
+ link[nb_link] = new t_link;
+ link[nb_link]->Id = GetASymbol(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[1]))
+ link[nb_link]->mass1 = mass[i];
+ else if(mass[i]->nbr==GetAInt(argv[2]))
+ link[nb_link]->mass2 = mass[i];
+ link[nb_link]->K1 = GetAFloat(argv[3]);
+ link[nb_link]->D1 = GetAFloat(argv[4]);
+ link[nb_link]->D2 = GetAFloat(argv[5]);
+ link[nb_link]->longx = link[nb_link]->mass1->posX - link[nb_link]->mass2->posX;
+ link[nb_link]->longy = link[nb_link]->mass1->posY - link[nb_link]->mass2->posY;
+ link[nb_link]->longueur = sqrt( pow(link[nb_link]->longx,2) + pow(link[nb_link]->longy,2));
+ link[nb_link]->nbr = id_link;
+ link[nb_link]->distance_old = link[nb_link]->longueur;
+ SETSYMBOL(aux,GetASymbol(argv[0]));
+ atom_string(aux,(link[nb_link]->Id_string),Id_length);
+ nb_link++;
+ id_link++;
+ nb_link = min ( nb_max_link -1, nb_link );
+ SETFLOAT(&(sortie[0]),id_link-1);
+ SETSYMBOL(&(sortie[1]),link[nb_link-1]->Id);
+ SETFLOAT(&(sortie[2]),GetAInt(argv[1]));
+ SETFLOAT(&(sortie[3]),GetAInt(argv[2]));
+ SETFLOAT(&(sortie[4]),link[nb_link-1]->K1);
+ SETFLOAT(&(sortie[5]),link[nb_link-1]->D1);
+ SETFLOAT(&(sortie[6]),link[nb_link-1]->D2);
+ ToOutAnything(1,gensym("Link"),7,sortie);
+ }
+
+ void m_ilink(int argc,t_atom *argv)
+ // add interactor link
+ // Id, nbr, Id masses1, Id masses2, K1, D1
+ {
+ t_atom aux[2], arglist[6];
+ t_int i,j, strvalue, strvalue2, imass1[nb_mass], nbmass1=0, imass2[nb_mass], nbmass2=0;
+ char buffer[Id_length], buffer2[Id_length];
+
+ ToOutAnything(1,gensym("iLink"),0,aux);
+ SETSYMBOL(aux,GetASymbol(argv[1]));
+ atom_string(aux, buffer, Id_length);
+ SETSYMBOL(aux,GetASymbol(argv[2]));
+ atom_string(aux, buffer2, Id_length);
+
+ for (i=0;i<nb_mass;i++) {
+ strvalue=strcmp(buffer,mass[i]->Id_string);
+ strvalue2=strcmp(buffer2,mass[i]->Id_string);
+ if (strvalue ==0) {
+ imass1[nbmass1]=i;
+ nbmass1++;
+ }
+ if (strvalue2 ==0) {
+ imass2[nbmass2]=i;
+ nbmass2++;
+ }
+ }
+
+ for(i=0;i<nbmass1;i++)
+ for(j=0;j<nbmass2;j++)
+ if (imass1[i] != imass2[j]) {
+ SETSYMBOL(&(arglist[0]),GetASymbol(argv[0]));
+ SETFLOAT(&(arglist[1]),mass[imass1[i]]->nbr);
+ SETFLOAT(&(arglist[2]),mass[imass2[j]]->nbr);
+ SETFLOAT(&(arglist[3]),GetAInt(argv[3]));
+ SETFLOAT(&(arglist[4]),GetAFloat(argv[4]));
+ SETFLOAT(&(arglist[5]),GetAFloat(argv[5]));
+ m_link(6,arglist);
+ }
+ }
+
+ void m_setK(int argc,t_atom *argv)
+ {
+ // set rigidity of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->K1 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_setD(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->D1 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_setD2(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->D2 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_delete_link(int argc,t_atom *argv)
+ {
+ // Delete link
+ t_int i;
+ t_atom sortie[7];
+
+ for (i=0; i<nb_link;i++)
+ if (link[i]->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(sortie[0]),link[i]->nbr);
+ SETSYMBOL(&(sortie[1]),link[i]->Id);
+ SETFLOAT(&(sortie[2]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[3]),link[i]->mass2->nbr);
+ SETFLOAT(&(sortie[4]),link[i]->K1);
+ SETFLOAT(&(sortie[5]),link[i]->D1);
+ SETFLOAT(&(sortie[6]),link[i]->D2);
+ delete link[i];
+ link[i]=link[nb_link-1];
+ nb_link--;
+ ToOutAnything(1,gensym("Link deleted"),7,sortie);
+ break;
+ }
+ }
+
+
+// -------------------------------------------------------------- GET
+
+ void m_get(int argc,t_atom *argv)
+ // get attributes
+ {
+ t_int i,j, auxstring1, auxstring2, auxstring3, aux;
+ t_symbol *auxarg;
+ t_atom sortie[4],atom[2];
+ char buffer[Id_length],masses[]="massesPos",buffer2[Id_length], forces[] = "massesForces", links[] = "linksPos";
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, 20);
+ auxstring1 = strcmp(buffer,masses); //auxstring1 : 0 masses, 1 else
+ auxstring2 = strcmp(buffer,forces); //auxstring2 : 0 forces, 1 else
+ auxstring3 = strcmp(buffer,links); //auxstring2 : 0 links, 1 else
+ auxarg = GetASymbol(argv[1]); //auxarg : & symbol, 0 else
+ if (argc == 1)
+ {
+ if (auxstring1 == 0)// get all masses positions
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ ToOutAnything(0,gensym("massesPos"),2,sortie);
+ }
+ else if (auxstring2 == 0)// get all masses forces
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ ToOutAnything(0,gensym("massesForces"),2,sortie);
+ }
+ else if (auxstring3 == 0)// get all links positions
+ for (i=0; i<nb_link; i++)
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass2->posX);
+ SETFLOAT(&sortie[3],link[i]->mass2->posY);
+ ToOutAnything(0,gensym("linksPos"),4,sortie);
+ }
+ else // get all masses speeds
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ ToOutAnything(0,gensym("massesSpeeds"),2,sortie);
+ }
+ }
+ else if (auxstring1 == 0) // get mass positions
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ ToOutAnything(0,gensym("massesPosNo"),2,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ ToOutAnything(0,gensym("massesPosId"),2,sortie);
+ }
+ }
+ }
+ }
+ }
+ else if (auxstring2 == 0) // get mass forces
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ ToOutAnything(0,gensym("massesForcesNo"),2,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ ToOutAnything(0,gensym("massesForcesId"),2,sortie);
+ }
+ }
+ }
+ }
+ }
+ else if (auxstring3 == 0) // get links positions
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_link;i++)
+ if (link[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass2->posX);
+ SETFLOAT(&sortie[3],link[i]->mass2->posY);
+ ToOutAnything(0,gensym("linksPosNo"),4,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_link;i++)
+ {
+
+ aux = strcmp(buffer2,link[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass2->posX);
+ SETFLOAT(&sortie[3],link[i]->mass2->posY);
+ ToOutAnything(0,gensym("linksPosId"),4,sortie);
+ }
+ }
+ }
+ }
+ }
+ else // get mass speeds
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ ToOutAnything(0,gensym("massesSpeedsNo"),2,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ ToOutAnything(0,gensym("massesSpeedsId"),2,sortie);
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+
+ void m_mass_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[2*nb_mass];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[2*i]),mass[i]->posX);
+ SETFLOAT(&(sortie[2*i+1]),mass[i]->posY);
+ }
+ ToOutAnything(0, gensym("massesPosL"), 2*nb_mass, sortie);
+ }
+
+ void m_force_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[2*nb_mass];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[2*i]),mass[i]->out_forceX);
+ SETFLOAT(&(sortie[2*i+1]),mass[i]->out_forceY);
+ }
+ ToOutAnything(0, gensym("massesForcesL"), 2*nb_mass, sortie);
+ }
+
+ void m_link_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[2*nb_link];
+ t_int i;
+
+ for (i=0; i<nb_link; i++) {
+ SETFLOAT(&(sortie[2*i]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[2*i+1]),link[i]->mass2->nbr);
+ }
+ ToOutAnything(0, gensym("linksMassesL"), 2*nb_link, sortie);
+ }
+
+ void m_info_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[7];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[0]),mass[i]->nbr);
+ SETSYMBOL(&(sortie[1]),mass[i]->Id);
+ SETFLOAT(&(sortie[2]),mass[i]->mobile);
+ SETFLOAT(&(sortie[3]),1/mass[i]->invM);
+ SETFLOAT(&(sortie[4]),mass[i]->posX);
+ SETFLOAT(&(sortie[5]),mass[i]->posY);
+ ToOutAnything(1, gensym("Mass"), 6, sortie);
+ }
+
+ for (i=0; i<nb_link; i++) {
+ SETFLOAT(&(sortie[0]),link[i]->nbr);
+ SETSYMBOL(&(sortie[1]),link[i]->Id);
+ SETFLOAT(&(sortie[2]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[3]),link[i]->mass2->nbr);
+ SETFLOAT(&(sortie[4]),link[i]->K1);
+ SETFLOAT(&(sortie[5]),link[i]->D1);
+ SETFLOAT(&(sortie[6]),link[i]->D2);
+ ToOutAnything(1, gensym("Link"), 7, sortie);
+ }
+
+ }
+
+// -------------------------------------------------------------- GLOBAL VARIABLES
+
+ t_link * link[nb_max_link];
+ t_mass * mass[nb_max_mass];
+ t_float Xmin, Xmax, Ymin, Ymax;
+ int nb_link, nb_mass, id_mass, id_link;
+
+// -------------------------------------------------------------- SETUP
+
+private:
+
+ static void setup(t_classid c)
+ {
+ // --- set up meth(i=0; i<nb_link;i++)ods (class scope) ---
+
+ // register a bang method to the default inlet (0)
+ FLEXT_CADDBANG(c,0,m_bang);
+
+ // set up tagged methods for the default inlet (0)
+ // the underscore _ after CADDMETHOD indicates that a message tag is used
+ // no, variable list or anything and all single arguments are recognized automatically, ...
+ FLEXT_CADDMETHOD_(c,0,"reset",m_reset);
+ FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX);
+ FLEXT_CADDMETHOD_(c,0,"forceY",m_forceY);
+ FLEXT_CADDMETHOD_(c,0,"posX",m_posX);
+ FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax);
+ FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin);
+ FLEXT_CADDMETHOD_(c,0,"Ymax",m_Ymax);
+ FLEXT_CADDMETHOD_(c,0,"Ymin",m_Ymin);
+ FLEXT_CADDMETHOD_(c,0,"posY",m_posY);
+ FLEXT_CADDMETHOD_(c,0,"setK",m_setK);
+ FLEXT_CADDMETHOD_(c,0,"setD",m_setD);
+ FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2);
+ FLEXT_CADDMETHOD_(c,0,"mass",m_mass);
+ FLEXT_CADDMETHOD_(c,0,"link",m_link);
+ FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink);
+ FLEXT_CADDMETHOD_(c,0,"get",m_get);
+ FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link);
+ FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass);
+ FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"linksMassesL",m_link_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile);
+ FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe);
+ }
+
+ // for every registered method a callback has to be declared
+ FLEXT_CALLBACK(m_bang)
+ FLEXT_CALLBACK(m_mass_dumpl)
+ FLEXT_CALLBACK(m_force_dumpl)
+ FLEXT_CALLBACK(m_link_dumpl)
+ FLEXT_CALLBACK(m_info_dumpl)
+ FLEXT_CALLBACK(m_reset)
+ FLEXT_CALLBACK_V(m_mass)
+ FLEXT_CALLBACK_V(m_link)
+ FLEXT_CALLBACK_V(m_ilink)
+ FLEXT_CALLBACK_V(m_set_mobile)
+ FLEXT_CALLBACK_V(m_set_fixe)
+ FLEXT_CALLBACK_V(m_Xmax)
+ FLEXT_CALLBACK_V(m_Xmin)
+ FLEXT_CALLBACK_V(m_Ymax)
+ FLEXT_CALLBACK_V(m_Ymin)
+ FLEXT_CALLBACK_V(m_setK)
+ FLEXT_CALLBACK_V(m_setD)
+ FLEXT_CALLBACK_V(m_setD2)
+ FLEXT_CALLBACK_V(m_forceX)
+ FLEXT_CALLBACK_V(m_forceY)
+ FLEXT_CALLBACK_V(m_posX)
+ FLEXT_CALLBACK_V(m_posY)
+ FLEXT_CALLBACK_V(m_get)
+ FLEXT_CALLBACK_V(m_delete_link)
+ FLEXT_CALLBACK_V(m_delete_mass)
+};
+
+// instantiate the class (constructor has a variable argument list)
+FLEXT_NEW_V("msd2D",msd2D)
+
+
diff --git a/msd2D/package.txt b/msd2D/package.txt
new file mode 100644
index 0000000..2a14acc
--- /dev/null
+++ b/msd2D/package.txt
@@ -0,0 +1,2 @@
+NAME=msd2D
+SRCS=main.cpp
diff --git a/msd3D/01_msd3Dtest.pd b/msd3D/01_msd3Dtest.pd
new file mode 100644
index 0000000..475f17b
--- /dev/null
+++ b/msd3D/01_msd3Dtest.pd
@@ -0,0 +1,204 @@
+#N canvas 417 69 863 802 10;
+#X obj 32 13 loadbang;
+#X obj 294 522 print msd;
+#X obj 642 647 gemwin;
+#X msg 642 625 0 \, destroy;
+#X obj 532 707 gemhead;
+#X obj 532 730 world_light;
+#X msg 642 562 reset \, create \, lighting 1 \, 1;
+#X obj 102 13 cnv 15 500 270 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X obj 115 259 t a;
+#X obj 115 18 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 187 69 reset;
+#X text 153 19 reset;
+#X obj 115 40 t b b b b b;
+#X msg 133 158 50 50;
+#X msg 115 233 link souple \$1 \$2 \$3 \$4 \$5;
+#X obj 30 290 cnv 15 572 80 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#X obj 33 298 gemhead;
+#X obj 33 321 t b;
+#X msg 33 343 bang \, get massesPos \, get linksPos;
+#X text 393 85 CREATION : 3 MASSES \, 2 LINKS;
+#X text 272 311 COMPUTE AND GET ALL MASSES AND LINKS POSITIONS;
+#X obj 30 374 cnv 15 572 110 empty empty empty 20 12 0 14 -262131 -66577
+0;
+#X msg 65 381 setD souple 0.01;
+#X msg 196 382 setK souple 1;
+#X msg 65 401 setD souple 1;
+#X msg 196 402 setK souple 2;
+#X text 331 394 SET RIGIDITY AND VISCOSITY OF LINKS;
+#X text 347 440 ADD FORCE ON ALL MOBILE MASSES;
+#X obj 27 545 cnv 15 400 200 empty empty empty 20 12 0 14 -261689 -66577
+0;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 125 136 t b f;
+#X obj 127 57 unpack f f f;
+#X obj 244 87 / 12.5;
+#X obj 244 110 - 4;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 10 1 1 1;
+#X connect 11 0 3 0;
+#X connect 11 1 5 0;
+#X connect 11 2 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 1 3;
+#X restore 114 589 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 44 265 curve 2;
+#X obj 266 117 / 12.5;
+#X obj 266 140 - 4;
+#X obj 320 118 / 12.5;
+#X obj 320 141 - 4;
+#X obj 93 69 unpack f f f f f f;
+#X obj 197 117 / 12.5;
+#X obj 197 142 - 4;
+#X obj 123 194 pack f f f;
+#X msg 123 217 \$1 \$2 \$3;
+#X obj 371 118 / 12.5;
+#X obj 371 141 - 4;
+#X obj 266 189 pack f f f;
+#X msg 266 212 \$1 \$2 \$3;
+#X connect 0 0 14 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 17 1;
+#X connect 5 0 7 1;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 17 0;
+#X connect 10 0 11 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 1;
+#X connect 14 0 1 0;
+#X connect 14 1 3 0;
+#X connect 14 2 15 0;
+#X connect 14 3 10 0;
+#X connect 14 4 12 0;
+#X connect 14 5 19 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 2;
+#X connect 17 0 18 0;
+#X connect 18 0 9 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 2;
+#X connect 21 0 22 0;
+#X connect 22 0 9 2;
+#X restore 33 610 pd linkrender;
+#X obj 33 560 route linksPos massesPos;
+#X text 241 570 DISPLAY MASSES AND LINKS;
+#X text 289 592 WITH GEM;
+#X text 445 561 1 CREATE WINDOW -->;
+#X text 444 624 3 AND DESTROY IT! -->;
+#X text 444 592 2 DRAG THE STRUCTURE WITH THE MOUSE;
+#X msg 115 211 0 1 5 0.5 0.5 \, 1 2 1 0.5 0;
+#N canvas 731 296 450 300 gemmouse 0;
+#X obj 189 77 gemmouse;
+#X obj 189 184 pack f f;
+#X obj 189 218 spigot;
+#X obj 103 244 outlet;
+#X obj 189 131 - 0;
+#X obj 216 131 + 100;
+#X obj 189 108 / 5;
+#X obj 216 108 / -5;
+#X obj 79 51 inlet;
+#X obj 140 75 inlet;
+#X obj 141 120 l;
+#X obj 109 98 t b;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 10 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 3 0;
+#X connect 11 0 10 0;
+#X restore 33 672 pd gemmouse;
+#X obj 33 651 gemhead;
+#X msg 33 693 posX fix \$1;
+#X msg 33 714 posY fix \$2;
+#X text 184 675 SET FIXED MASS TO MOUSE POSITION;
+#X obj 33 497 msd3D --------------------------------;
+#X msg 62 440 forceZ mob 200;
+#X msg 188 441 forceZ mob -200;
+#X msg 151 114 100 20 10 0 \, 200 20 25 0;
+#X msg 151 138 mass mob 1 \$1 \$2 \$3 \$4;
+#X msg 133 179 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 70
+\, Zmin 0;
+#X msg 169 89 mass fix 0 100 50 50 50;
+#X connect 0 0 12 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 8 0 43 0;
+#X connect 9 0 12 0;
+#X connect 10 0 8 0;
+#X connect 12 0 37 0;
+#X connect 12 1 13 0;
+#X connect 12 1 48 0;
+#X connect 12 2 46 0;
+#X connect 12 3 49 0;
+#X connect 12 4 10 0;
+#X connect 13 0 38 1;
+#X connect 14 0 8 0;
+#X connect 16 0 17 0;
+#X connect 17 0 18 0;
+#X connect 18 0 43 0;
+#X connect 22 0 43 0;
+#X connect 23 0 43 0;
+#X connect 24 0 43 0;
+#X connect 25 0 43 0;
+#X connect 31 0 30 0;
+#X connect 31 1 29 0;
+#X connect 37 0 14 0;
+#X connect 38 0 40 0;
+#X connect 38 0 41 0;
+#X connect 39 0 38 0;
+#X connect 40 0 43 0;
+#X connect 41 0 43 0;
+#X connect 43 0 31 0;
+#X connect 43 1 1 0;
+#X connect 44 0 43 0;
+#X connect 45 0 43 0;
+#X connect 46 0 47 0;
+#X connect 47 0 8 0;
+#X connect 48 0 8 0;
+#X connect 49 0 8 0;
diff --git a/msd3D/02_msd3Dperf.pd b/msd3D/02_msd3Dperf.pd
new file mode 100644
index 0000000..097974b
--- /dev/null
+++ b/msd3D/02_msd3Dperf.pd
@@ -0,0 +1,145 @@
+#N canvas 533 109 692 690 10;
+#X obj 177 369 t a;
+#X obj 159 5 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 231 146 reset;
+#X obj 37 10 loadbang;
+#X text 197 96 reset;
+#X obj 159 27 t b b b b b;
+#X obj 313 605 print msd;
+#X msg 456 528 0 \, destroy;
+#X obj 456 583 gemhead;
+#X obj 456 606 world_light;
+#X msg 213 177 mass fix 0 100 50 50;
+#X msg 456 468 reset \, create \, lighting 1 \, 1;
+#X obj 52 391 t b;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 125 136 t b f;
+#X obj 127 57 unpack f f f;
+#X obj 247 86 / 12.5;
+#X obj 247 109 - 4;
+#X obj 48 229 sphere 0.07;
+#X connect 0 0 10 0;
+#X connect 1 0 13 0;
+#X connect 2 0 3 0;
+#X connect 3 0 9 0;
+#X connect 4 0 5 0;
+#X connect 5 0 1 2;
+#X connect 6 0 8 1;
+#X connect 7 0 1 0;
+#X connect 8 0 7 0;
+#X connect 9 0 8 0;
+#X connect 9 1 1 1;
+#X connect 10 0 2 0;
+#X connect 10 1 4 0;
+#X connect 10 2 11 0;
+#X connect 11 0 12 0;
+#X connect 12 0 1 3;
+#X restore 52 625 pd massrender;
+#X obj 425 254 random 100;
+#X msg 425 233 seed 1;
+#X obj 349 254 random 100;
+#X obj 274 233 random 100;
+#X msg 349 233 seed 2;
+#X msg 274 212 seed 3;
+#X obj 274 254 + 100;
+#X obj 586 145 t b;
+#X obj 586 189 + 1;
+#X obj 616 230 f;
+#X obj 632 179 + 1;
+#X obj 586 210 t f b;
+#X msg 632 155 -1;
+#X obj 586 166 f -1;
+#X obj 586 255 pack f f;
+#X msg 177 339 link souple \$1 \$2 100 0.5 0.5;
+#X obj 52 368 gemhead;
+#X obj 456 548 gemwin;
+#X obj 52 583 msd3D --------------------------------;
+#X obj 376 105 t b b b b;
+#X obj 505 254 random 100;
+#X msg 505 233 seed 4;
+#X obj 177 271 pack f f f f;
+#X msg 177 293 mass mob 1 \$1 \$2 \$3 \$4;
+#X msg 177 316 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 100
+\, Zmin 0;
+#X msg 456 508 view 8 0 0.5 0 0 0 0 0 1;
+#X obj 376 83 repeat 300;
+#X obj 586 123 repeat 300;
+#X text 501 21 <-- Number of masses;
+#X obj 456 487 t b;
+#X obj 52 604 route massesPos;
+#X msg 52 425 bang \, get massesPos;
+#X text 265 487 <-- Move masses;
+#X msg 143 479 forceX mob 100;
+#X msg 143 503 forceX mob -100;
+#X msg 459 20 900;
+#X connect 0 0 32 0;
+#X connect 1 0 5 0;
+#X connect 2 0 0 0;
+#X connect 3 0 5 0;
+#X connect 5 0 41 0;
+#X connect 5 1 38 0;
+#X connect 5 2 40 0;
+#X connect 5 3 10 0;
+#X connect 5 4 2 0;
+#X connect 5 4 26 0;
+#X connect 5 4 19 0;
+#X connect 5 4 15 0;
+#X connect 5 4 18 0;
+#X connect 5 4 35 0;
+#X connect 7 0 31 0;
+#X connect 8 0 9 0;
+#X connect 10 0 0 0;
+#X connect 11 0 31 0;
+#X connect 11 0 43 0;
+#X connect 12 0 45 0;
+#X connect 14 0 36 2;
+#X connect 15 0 14 0;
+#X connect 16 0 36 1;
+#X connect 17 0 20 0;
+#X connect 18 0 16 0;
+#X connect 19 0 17 0;
+#X connect 20 0 36 0;
+#X connect 21 0 27 0;
+#X connect 22 0 24 0;
+#X connect 22 0 25 0;
+#X connect 22 0 27 1;
+#X connect 23 0 28 1;
+#X connect 24 0 23 1;
+#X connect 25 0 28 0;
+#X connect 25 1 23 0;
+#X connect 26 0 27 1;
+#X connect 27 0 22 0;
+#X connect 28 0 29 0;
+#X connect 29 0 0 0;
+#X connect 30 0 12 0;
+#X connect 32 0 44 0;
+#X connect 32 1 6 0;
+#X connect 33 0 17 0;
+#X connect 33 1 16 0;
+#X connect 33 1 34 0;
+#X connect 33 2 14 0;
+#X connect 34 0 36 3;
+#X connect 35 0 34 0;
+#X connect 36 0 37 0;
+#X connect 37 0 0 0;
+#X connect 38 0 0 0;
+#X connect 39 0 31 0;
+#X connect 40 0 33 0;
+#X connect 41 0 21 0;
+#X connect 43 0 39 0;
+#X connect 44 0 13 0;
+#X connect 45 0 32 0;
+#X connect 47 0 32 0;
+#X connect 48 0 32 0;
+#X connect 49 0 40 1;
+#X connect 49 0 41 1;
diff --git a/msd3D/03_msd3Dmemb.pd b/msd3D/03_msd3Dmemb.pd
new file mode 100644
index 0000000..ad45d13
--- /dev/null
+++ b/msd3D/03_msd3Dmemb.pd
@@ -0,0 +1,155 @@
+#N canvas 342 69 790 805 10;
+#X obj 32 13 loadbang;
+#X obj 294 641 print msd;
+#X obj 466 735 gemwin;
+#X msg 466 713 0 \, destroy;
+#X obj 688 623 gemhead;
+#X obj 688 646 world_light;
+#X msg 466 622 reset \, create \, lighting 1 \, 1;
+#X obj 130 361 t a;
+#X obj 129 18 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 202 59 reset;
+#X text 167 19 reset;
+#X obj 33 399 gemhead;
+#X msg 65 500 setD souple 0.01;
+#X msg 196 501 setK souple 1;
+#X msg 65 520 setD souple 1;
+#X msg 196 521 setK souple 2;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 44 265 curve 2;
+#X obj 266 117 / 12.5;
+#X obj 266 140 - 4;
+#X obj 320 118 / 12.5;
+#X obj 320 141 - 4;
+#X obj 93 69 unpack f f f f f f;
+#X obj 197 117 / 12.5;
+#X obj 197 142 - 4;
+#X obj 123 194 pack f f f;
+#X msg 123 217 \$1 \$2 \$3;
+#X obj 371 118 / 12.5;
+#X obj 371 141 - 4;
+#X obj 266 189 pack f f f;
+#X msg 266 212 \$1 \$2 \$3;
+#X connect 0 0 14 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 17 1;
+#X connect 5 0 7 1;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 17 0;
+#X connect 10 0 11 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 1;
+#X connect 14 0 1 0;
+#X connect 14 1 3 0;
+#X connect 14 2 15 0;
+#X connect 14 3 10 0;
+#X connect 14 4 12 0;
+#X connect 14 5 19 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 2;
+#X connect 17 0 18 0;
+#X connect 18 0 9 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 2;
+#X connect 21 0 22 0;
+#X connect 22 0 9 2;
+#X restore 33 666 pd linkrender;
+#X obj 33 616 msd3D --------------------------------;
+#X msg 62 559 forceZ mob 200;
+#X msg 148 229 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 70
+\, Zmin 0;
+#X msg 130 255 0 4 \, 4 5 \, 5 6 \, 6 1 \, 7 8 \, 8 9 \, 9 10 \, 10
+11 \, 12 13 \, 13 14 \, 14 15 \, 15 16 \, 17 18 \, 18 19 \, 19 20 \,
+20 21 \, 2 22 \, 22 23 \, 23 24 \, 24 3 \, 0 7 \, 4 8 \, 5 9 \, 6 10
+\, 1 11 \, 7 12 \, 8 13 \, 9 14 \, 10 15 \, 11 16 \, 12 17 \, 13 18
+\, 14 19 \, 15 20 \, 16 21 \, 2 17 \, 18 22 \, 19 23 \, 20 24 \, 21
+3;
+#X msg 166 193 mass mob 1 100 \$1 \$2 \$3;
+#X msg 188 560 forceZ mob -1;
+#X msg 166 130 30 40 40 \, 30 50 40 \, 30 60 40 \, 40 30 40 \, 40 40
+40 \, 40 50 40 \, 40 60 40 \, 40 70 40 \, 50 30 40 \, 50 40 40 \, 50
+50 40 \, 50 60 40 \, 50 70 40 \, 60 30 40 \, 60 40 40 \, 60 50 40 \,
+60 60 40 \, 60 70 40 \, 70 40 40 \, 70 50 40 \, 70 60 40;
+#X msg 130 335 link souple \$1 \$2 10 0.5 1;
+#X msg 466 688 view 0 4 0 0 0 0 0 0 1;
+#X msg 466 646 view 4 0 0.5 0 0 0 0 0 1;
+#X obj 312 479 f;
+#X floatatom 333 456 5 0 0 0 - - -;
+#X obj 312 403 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1
+1;
+#X msg 312 504 forceZ mob \$1;
+#X obj 312 423 metro 65;
+#X msg 466 667 view 0 0 4 0 0 0 0 1 0;
+#X text 370 401 Add a constant force;
+#X msg 33 462 bang \, get linksPos;
+#X obj 33 641 route linksPos;
+#X msg 184 82 mass fix 0 100 30 30 40 \, mass fix 0 100 30 70 40 \,
+mass fix 0 100 70 30 40 \, mass fix 0 100 70 70 40;
+#X msg 527 543 posZ fix \$1;
+#X obj 527 402 vsl 15 128 0 70 0 0 empty empty empty 0 -8 0 8 -262144
+-1 -1 3000 1;
+#X text 573 463 Change altitude of corners;
+#X obj 33 427 t b b b;
+#X text 385 455 Amplitude;
+#X text 362 619 Create window;
+#X text 374 668 Change view;
+#X obj 130 38 t b b b b b;
+#X text 98 428 Multiple draw;
+#X connect 0 0 44 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 7 0 17 0;
+#X connect 8 0 44 0;
+#X connect 9 0 7 0;
+#X connect 11 0 40 0;
+#X connect 12 0 17 0;
+#X connect 13 0 17 0;
+#X connect 14 0 17 0;
+#X connect 15 0 17 0;
+#X connect 17 0 35 0;
+#X connect 17 1 1 0;
+#X connect 18 0 17 0;
+#X connect 19 0 7 0;
+#X connect 20 0 24 0;
+#X connect 21 0 7 0;
+#X connect 22 0 17 0;
+#X connect 23 0 21 0;
+#X connect 24 0 7 0;
+#X connect 25 0 2 0;
+#X connect 26 0 2 0;
+#X connect 27 0 30 0;
+#X connect 28 0 27 1;
+#X connect 29 0 31 0;
+#X connect 30 0 17 0;
+#X connect 31 0 27 0;
+#X connect 32 0 2 0;
+#X connect 34 0 17 0;
+#X connect 34 0 22 0;
+#X connect 35 0 16 0;
+#X connect 36 0 7 0;
+#X connect 37 0 17 0;
+#X connect 38 0 37 0;
+#X connect 40 0 34 0;
+#X connect 40 1 34 0;
+#X connect 40 2 34 0;
+#X connect 44 0 20 0;
+#X connect 44 1 19 0;
+#X connect 44 2 23 0;
+#X connect 44 3 36 0;
+#X connect 44 4 9 0;
diff --git a/msd3D/04_msd3Dfilet.pd b/msd3D/04_msd3Dfilet.pd
new file mode 100644
index 0000000..69d801b
--- /dev/null
+++ b/msd3D/04_msd3Dfilet.pd
@@ -0,0 +1,146 @@
+#N canvas 482 80 863 802 10;
+#X obj 32 13 loadbang;
+#X obj 294 522 print msd;
+#X obj 458 439 gemwin;
+#X msg 458 417 0 \, destroy;
+#X obj 457 469 gemhead;
+#X obj 457 492 world_light;
+#X msg 458 328 reset \, create \, lighting 1 \, 1;
+#X obj 145 205 t a;
+#X obj 144 18 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 203 63 reset;
+#X text 182 19 reset;
+#X obj 33 298 gemhead;
+#X obj 33 321 t b;
+#X msg 33 343 bang \, get massesPos \, get linksPos;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 125 136 t b f;
+#X obj 127 57 unpack f f f;
+#X obj 246 88 / 12.5;
+#X obj 246 111 - 4;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 10 1 1 1;
+#X connect 11 0 3 0;
+#X connect 11 1 5 0;
+#X connect 11 2 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 1 3;
+#X restore 114 589 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 44 265 curve 2;
+#X obj 266 117 / 12.5;
+#X obj 266 140 - 4;
+#X obj 320 118 / 12.5;
+#X obj 320 141 - 4;
+#X obj 93 69 unpack f f f f f f;
+#X obj 197 117 / 12.5;
+#X obj 197 142 - 4;
+#X obj 123 194 pack f f f;
+#X msg 123 217 \$1 \$2 \$3;
+#X obj 371 118 / 12.5;
+#X obj 371 141 - 4;
+#X obj 266 189 pack f f f;
+#X msg 266 212 \$1 \$2 \$3;
+#X connect 0 0 14 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 17 1;
+#X connect 5 0 7 1;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 17 0;
+#X connect 10 0 11 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 1;
+#X connect 14 0 1 0;
+#X connect 14 1 3 0;
+#X connect 14 2 15 0;
+#X connect 14 3 10 0;
+#X connect 14 4 12 0;
+#X connect 14 5 19 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 2;
+#X connect 17 0 18 0;
+#X connect 18 0 9 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 2;
+#X connect 21 0 22 0;
+#X connect 22 0 9 2;
+#X restore 33 610 pd linkrender;
+#X obj 33 539 route linksPos massesPos;
+#X msg 458 392 view 0 4 0 0 0 0 0 0 1;
+#X msg 203 83 symbol reset;
+#X obj 33 497 msd3D --------------------------------;
+#X msg 32 410 forceZ filet -0.2;
+#X msg 145 173 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 70
+\, Zmin -40;
+#X msg 164 140 setFixed 62 \, setFixed 87 \, setFixed 512 \, setFixed
+537;
+#X msg 458 371 view 0 0 4 0 0 0 0 1 0;
+#X obj 183 113 filet 20 30 2 2 20 30;
+#X msg 458 349 view 4 0 0.5 0 0 0 0 0 1;
+#X text 187 408 Ambient force;
+#X text 648 380 Select view;
+#X obj 145 38 t b b b b;
+#X text 383 114 Filet abstraction : x0 y0 stepx stepy nx ny;
+#X text 244 587 Connect mass or link to be viewed \, or both with good
+computer!;
+#X connect 0 0 28 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 7 0 19 0;
+#X connect 8 0 28 0;
+#X connect 9 0 7 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 19 0;
+#X connect 13 0 20 0;
+#X connect 16 1 14 0;
+#X connect 17 0 2 0;
+#X connect 18 0 24 1;
+#X connect 19 0 16 0;
+#X connect 19 1 1 0;
+#X connect 20 0 19 0;
+#X connect 21 0 7 0;
+#X connect 22 0 7 0;
+#X connect 23 0 2 0;
+#X connect 24 0 7 0;
+#X connect 25 0 2 0;
+#X connect 28 0 21 0;
+#X connect 28 1 22 0;
+#X connect 28 2 24 0;
+#X connect 28 3 9 0;
+#X connect 28 3 18 0;
diff --git a/msd3D/Makefile.am b/msd3D/Makefile.am
new file mode 100644
index 0000000..59a3dff
--- /dev/null
+++ b/msd3D/Makefile.am
@@ -0,0 +1,51 @@
+#
+# automake template
+# added by tim blechmann
+#
+
+NAME = msd2
+
+BUILT_SOURCES = main.cpp
+
+EXTRA_DIST = main.cpp \
+ $(NAME).mcp \
+ $(NAME).vcproj
+
+CXXFLAGS = @CXXFLAGS@ \
+ @OPT_FLAGS@ \
+ @INCLUDEDIR@ \
+ -I../../source \
+ $(DEFS) \
+ -DFLEXT_SHARED
+
+LDFLAGS = @DYNAMIC_LDFLAGS@ @LDFLAGS@ \
+ $(patsubst %,-framework %,$(FRAMEWORKS))
+
+LIBS = @LIBS@ -lflext-pd
+
+FRAMEWORKS = @FRAMEWORKS@
+
+TARGETDIR = @TARGETDIR@
+
+TARGET =$(NAME).@EXTENSION@
+
+OBJECTS = $(patsubst %.cpp,./%.@OBJEXT@,$(BUILT_SOURCES))
+
+SYSDIR = @SYSDIR@
+
+
+# ----------------------------- targets --------------------------------
+
+all-local: $(OBJECTS)
+ $(CXX) $(LDFLAGS) ./*.@OBJEXT@ $(LIBS) -o ../$(TARGETDIR)/$(TARGET)
+ strip --strip-unneeded ../$(TARGETDIR)/$(TARGET)
+
+./%.@OBJEXT@ : %.cpp
+ $(CXX) -c $(CXXFLAGS) $< -o $@
+
+clean-local:
+ rm -f ../$(TARGETDIR)/$(TARGET)
+ rm -f ./$(OBJECTS)
+
+install-exec-local:
+ install ../$(TARGET) $(SYSDIR)extra
diff --git a/msd3D/filet.pd b/msd3D/filet.pd
new file mode 100644
index 0000000..3a4575b
--- /dev/null
+++ b/msd3D/filet.pd
@@ -0,0 +1,106 @@
+#N canvas 543 268 669 547 10;
+#X obj 54 407 outlet;
+#X obj 152 71 f \$5;
+#X obj 188 72 f \$6;
+#X obj 115 17 loadbang;
+#X obj 46 134 repeat 0;
+#X obj 172 101 *;
+#X obj 130 45 t b b b b;
+#X obj 46 164 f -1;
+#X obj 46 188 + 1;
+#X msg 297 77 -1;
+#X obj 46 211 t f f;
+#X obj 150 323 pack f f;
+#X obj 46 50 inlet;
+#X obj 297 28 select reset;
+#X obj 297 5 inlet;
+#X obj 46 89 t b b;
+#X obj 330 175 repeat 0;
+#X obj 330 197 f -1;
+#X obj 330 218 + 1;
+#X obj 381 153 - 1;
+#X obj 387 340 moses;
+#X obj 46 257 * \$3;
+#X obj 46 280 + \$1;
+#X obj 176 256 * \$4;
+#X obj 176 278 + \$2;
+#X obj 46 234 mod \$6;
+#X obj 176 234 div \$6;
+#X text 445 35 x0 y0 xstep ystep M N;
+#X obj 414 314 - 1;
+#X obj 357 297 mod \$6;
+#X obj 474 300 div \$6;
+#X obj 366 396 + 1;
+#X obj 336 432 pack f f;
+#X obj 344 59 t b b;
+#X obj 375 370 t b;
+#X obj 334 391 f;
+#X msg 335 468 link fil \$1 \$2 10 2.5 0.5;
+#X obj 330 253 t f f f f;
+#X obj 494 339 moses;
+#X obj 443 431 pack f f;
+#X obj 482 369 t b;
+#X obj 441 390 f;
+#X obj 473 395 + \$6;
+#X obj 521 313 - 1;
+#X msg 54 359 mass filet 1 80 \$1 \$2 50;
+#X connect 1 0 5 0;
+#X connect 1 0 43 0;
+#X connect 2 0 5 1;
+#X connect 2 0 28 0;
+#X connect 3 0 6 0;
+#X connect 4 0 7 0;
+#X connect 5 0 4 1;
+#X connect 5 0 19 0;
+#X connect 6 2 1 0;
+#X connect 6 3 2 0;
+#X connect 6 3 9 0;
+#X connect 7 0 8 0;
+#X connect 8 0 7 1;
+#X connect 8 0 10 0;
+#X connect 9 0 7 1;
+#X connect 9 0 17 1;
+#X connect 10 0 25 0;
+#X connect 10 1 26 0;
+#X connect 11 0 44 0;
+#X connect 12 0 15 0;
+#X connect 13 0 9 0;
+#X connect 13 0 33 0;
+#X connect 14 0 13 0;
+#X connect 15 0 16 0;
+#X connect 15 1 4 0;
+#X connect 16 0 17 0;
+#X connect 17 0 18 0;
+#X connect 18 0 17 1;
+#X connect 18 0 37 0;
+#X connect 19 0 16 1;
+#X connect 20 0 34 0;
+#X connect 21 0 22 0;
+#X connect 22 0 11 0;
+#X connect 23 0 24 0;
+#X connect 24 0 11 1;
+#X connect 25 0 21 0;
+#X connect 26 0 23 0;
+#X connect 28 0 20 1;
+#X connect 29 0 20 0;
+#X connect 30 0 38 0;
+#X connect 31 0 32 1;
+#X connect 32 0 36 0;
+#X connect 33 0 1 0;
+#X connect 33 1 2 0;
+#X connect 34 0 35 0;
+#X connect 35 0 32 0;
+#X connect 36 0 0 0;
+#X connect 37 0 29 0;
+#X connect 37 1 31 0;
+#X connect 37 1 35 1;
+#X connect 37 2 30 0;
+#X connect 37 3 42 0;
+#X connect 37 3 41 1;
+#X connect 38 0 40 0;
+#X connect 39 0 36 0;
+#X connect 40 0 41 0;
+#X connect 41 0 39 0;
+#X connect 42 0 39 1;
+#X connect 43 0 38 1;
+#X connect 44 0 0 0;
diff --git a/msd3D/help-msd3D.pd b/msd3D/help-msd3D.pd
new file mode 100644
index 0000000..aa1d899
--- /dev/null
+++ b/msd3D/help-msd3D.pd
@@ -0,0 +1,83 @@
+#N canvas 0 0 743 844 10;
+#X obj 17 9 cnv 15 610 305 empty empty CREATION 20 12 0 14 -262131
+-66577 0;
+#X msg 34 38 reset;
+#X text 204 69 Add a mass;
+#X text 290 70 \$1 : Id (symbol);
+#X text 289 90 \$2 : fixed or mobile (0/1);
+#X text 289 108 \$3 : mass;
+#X text 289 146 \$1 : Id (symbol);
+#X text 201 146 Add a link;
+#X text 288 166 \$2 : creation No of mass1;
+#X text 288 184 \$3 : creation No of mass2;
+#X text 287 202 \$4 : rigidity;
+#X text 206 39 Delete all masses and links;
+#X text 287 220 \$5 : viscosity;
+#X text 287 237 \$6 : damping;
+#X obj 17 319 cnv 15 610 60 empty empty COMPUTATION 20 12 0 14 -261689
+-66577 0;
+#X msg 37 348 bang;
+#X text 190 348 Compute new masses positions;
+#X obj 16 383 cnv 15 610 220 empty empty DYNAMIC_SETTING 20 12 0 14
+-262131 -66577 0;
+#X msg 124 405 setD \$1 \$2;
+#X text 309 423 \$1 : Id (symbol);
+#X text 309 441 \$2 : New value;
+#X msg 42 405 setK \$1 \$2;
+#X text 305 477 \$1 : Id (symbol);
+#X text 305 495 \$2 : New value;
+#X text 353 532 \$1 : Id (symbol);
+#X text 353 550 \$2 : New value;
+#X msg 42 457 posX \$1 \$2;
+#X text 305 459 Set position of mass(es);
+#X text 352 515 Add force on mass(es);
+#X msg 40 516 forceX \$1 \$2;
+#X msg 210 405 setD2 \$1 \$2;
+#X text 309 405 Set rigidity \, viscosity or damping of link(s);
+#X obj 15 612 cnv 15 610 198 empty empty GET_ATTRIBUTES 20 12 0 14
+-261689 -66577 0;
+#X msg 101 639 massePosL;
+#X msg 101 667 masseForcesL;
+#X text 202 639 output all masses positions in a list on outlet No
+1;
+#X text 201 668 output all masses forces in a list on outlet No 1;
+#X msg 100 705 get \$1 \$2;
+#X text 203 706 Get specific attribute;
+#X text 203 731 \$1 : Attribute type ( massesPos / massesSpeeds / massesForces
+/ linksPos );
+#X text 203 768 \$2 : Id (symbol or creations numbers);
+#X msg 31 146 link \$1 \$2 \$3 \$4 \$5 \$6;
+#X msg 30 253 deleteMass \$1;
+#X text 195 255 Delete a mass and associated links;
+#X text 285 272 \$1 : Creation No of mass;
+#X msg 29 289 deleteLink \$1;
+#X text 194 291 Delete a link;
+#X text 295 291 \$1 : Creation No of link;
+#X msg 98 788 infosL;
+#X text 201 788 Get infos on all masses and links on outlet No 2;
+#X text 302 588 \$1 : Value;
+#X msg 135 515 forceY \$1 \$2;
+#X msg 123 457 posY \$1 \$2;
+#X msg 39 568 Xmin \$1 \, Xmax \$1 \, Ymin \$1 \, Ymax \$1;
+#X text 302 571 Set minimimum and maximum of masses positions;
+#X msg 34 69 mass \$1 \$2 \$3 \$4 \$5 \$6;
+#X text 289 126 \$4 \, \$5 \, \$6 : position;
+#X msg 123 457 posY \$1 \$2;
+#X msg 204 457 posZ \$1 \$2;
+#X msg 229 515 forceZ \$1 \$2;
+#X obj -12 816 msd3D;
+#X msg 39 586 Zmin \$1 \, Zmax \$1;
+#X connect 1 0 60 0;
+#X connect 15 0 60 0;
+#X connect 21 0 60 0;
+#X connect 26 0 60 0;
+#X connect 29 0 60 0;
+#X connect 33 0 60 0;
+#X connect 34 0 60 0;
+#X connect 37 0 60 0;
+#X connect 41 0 60 0;
+#X connect 42 0 60 0;
+#X connect 45 0 60 0;
+#X connect 48 0 60 0;
+#X connect 53 0 60 0;
+#X connect 55 0 60 0;
diff --git a/msd3D/imsd3Dball.pd b/msd3D/imsd3Dball.pd
new file mode 100644
index 0000000..324af35
--- /dev/null
+++ b/msd3D/imsd3Dball.pd
@@ -0,0 +1,146 @@
+#N canvas 458 69 863 802 10;
+#X obj 32 13 loadbang;
+#X obj 294 522 print msd;
+#X obj 442 361 gemwin;
+#X msg 442 339 0 \, destroy;
+#X obj 441 402 gemhead;
+#X obj 441 425 world_light;
+#X msg 442 272 reset \, create \, lighting 1 \, 1;
+#X obj 116 244 t a;
+#X obj 115 18 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 174 62 reset;
+#X text 153 19 reset;
+#X obj 33 298 gemhead;
+#X obj 33 321 t b;
+#X msg 33 343 bang \, get massesPos \, get linksPos;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 125 136 t b f;
+#X obj 127 57 unpack f f f;
+#X obj 244 87 / 12.5;
+#X obj 244 110 - 4;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 10 1 1 1;
+#X connect 11 0 3 0;
+#X connect 11 1 5 0;
+#X connect 11 2 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 1 3;
+#X restore 114 553 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 44 265 curve 2;
+#X obj 266 117 / 12.5;
+#X obj 266 140 - 4;
+#X obj 320 118 / 12.5;
+#X obj 320 141 - 4;
+#X obj 93 69 unpack f f f f f f;
+#X obj 197 117 / 12.5;
+#X obj 197 142 - 4;
+#X obj 123 194 pack f f f;
+#X msg 123 217 \$1 \$2 \$3;
+#X obj 371 118 / 12.5;
+#X obj 371 141 - 4;
+#X obj 266 189 pack f f f;
+#X msg 266 212 \$1 \$2 \$3;
+#X connect 0 0 14 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 17 1;
+#X connect 5 0 7 1;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 17 0;
+#X connect 10 0 11 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 1;
+#X connect 14 0 1 0;
+#X connect 14 1 3 0;
+#X connect 14 2 15 0;
+#X connect 14 3 10 0;
+#X connect 14 4 12 0;
+#X connect 14 5 19 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 2;
+#X connect 17 0 18 0;
+#X connect 18 0 9 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 2;
+#X connect 21 0 22 0;
+#X connect 22 0 9 2;
+#X restore 33 574 pd linkrender;
+#X obj 33 524 route linksPos massesPos;
+#X obj 33 497 msd3D --------------------------------;
+#X msg 135 195 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 70
+\, Zmin 0;
+#X msg 154 170 mass mob 1 100 \$1 \$2 \$3;
+#X msg 154 83 35 50 50 \, 40 60 50 \, 50 65 50 \, 60 60 50 \, 65 50
+50 \, 60 40 50 \, 50 35 50 \, 40 40 50 \, 40 50 60 \, 43.3 56.7 60
+\, 50 60 60 \, 56.7 56.7 60 \, 60 50 60 \, 56.7 43.3 60 \, 50 40 60
+\, 43.3 43.3 60 \, 50 50 65 \, 40 50 40 \, 43.3 56.7 40 \, 50 60 40
+\, 56.7 56.7 40 \, 60 50 40 \, 56.7 43.3 40 \, 50 40 40 \, 43.3 43.3
+40 \, 50 50 35 \, 50 50 50;
+#X msg 116 218 iLink souple mob mob 1 2.5 0.5;
+#X msg 174 436 forceZ mob -10;
+#X msg 62 440 forceZ mob 500;
+#X msg 442 316 view 0 5 0 0 0 0 0 0 1;
+#X obj 116 38 t b b b b;
+#X obj 442 294 t b;
+#X text 310 286 Create window;
+#X connect 0 0 25 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 26 0;
+#X connect 6 0 2 0;
+#X connect 7 0 17 0;
+#X connect 8 0 25 0;
+#X connect 9 0 7 0;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 17 0;
+#X connect 13 0 22 0;
+#X connect 16 0 15 0;
+#X connect 16 1 14 0;
+#X connect 17 0 16 0;
+#X connect 17 1 1 0;
+#X connect 18 0 7 0;
+#X connect 19 0 7 0;
+#X connect 20 0 19 0;
+#X connect 21 0 7 0;
+#X connect 22 0 17 0;
+#X connect 23 0 17 0;
+#X connect 24 0 2 0;
+#X connect 25 0 21 0;
+#X connect 25 1 18 0;
+#X connect 25 2 20 0;
+#X connect 25 3 9 0;
diff --git a/msd3D/main.cpp b/msd3D/main.cpp
new file mode 100755
index 0000000..65bd8f7
--- /dev/null
+++ b/msd3D/main.cpp
@@ -0,0 +1,962 @@
+
+
+/*
+ msd3D - mass spring damper model for Pure Data or Max/MSP
+
+ Written by Nicolas Montgermont for a Master's train in Acoustic,
+ Signal processing and Computing Applied to Music (ATIAM, Paris 6)
+ at La Kitchen supervised by Cyrille Henry.
+
+ Based on Pure Data by Miller Puckette and others
+ Use FLEXT C++ Layer by Thomas Grill (xovo@gmx.net)
+ Based on pmpd by Cyrille Henry
+
+
+ Contact : Nicolas Montgermont, montgermont@la-kitchen.fr
+ Cyrille Henry, Cyrille.Henry@la-kitchen.fr
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Version 0.01, 12.04.2005
+
+*/
+
+// include flext header
+#include <flext.h>
+
+#include <math.h>
+
+// define constants
+#define MSD3D_VERSION 0.01
+#define nb_max_link 4000
+#define nb_max_mass 4000
+#define Id_length 20
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 401)
+#error You need at least flext version 0.4.1
+#endif
+
+#define max(a,b) ( ((a) > (b)) ? (a) : (b) )
+#define min(a,b) ( ((a) < (b)) ? (a) : (b) )
+
+typedef struct _mass {
+ t_symbol *Id;
+ t_int nbr;
+ t_int mobile;
+ t_float invM;
+ t_float speedX;
+ t_float posX;
+ t_float posX2;
+ t_float forceX;
+ t_float out_forceX;
+ t_float speedY;
+ t_float posY;
+ t_float posY2;
+ t_float forceY;
+ t_float out_forceY;
+ t_float speedZ;
+ t_float posZ;
+ t_float posZ2;
+ t_float forceZ;
+ t_float out_forceZ;
+ char Id_string[Id_length];
+} t_mass;
+
+typedef struct _link {
+ t_symbol *Id;
+ t_int nbr;
+ t_mass *mass1;
+ t_mass *mass2;
+ t_float K1, D1, D2;
+ t_float longx, longy, longz, longueur;
+ t_float distance_old;
+ char Id_string[Id_length];
+} t_link;
+
+class msd3D:
+ public flext_base
+{
+ FLEXT_HEADER_S(msd3D,flext_base,setup) //class with setup
+
+public:
+ // constructor with no arguments
+ msd3D(int argc,t_atom *argv)
+ {
+ nb_link = 0;
+ nb_mass = 0;
+ id_mass = 0;
+ id_link = 0;
+
+ // --- define inlets and outlets ---
+ AddInAnything("bang, reset, etc."); // default inlet
+ AddOutAnything("infos on masses"); // outlet for integer count
+ AddOutAnything("control"); // outlet for bang
+ }
+
+protected:
+
+// --------------------------------------------------------------- RESET
+
+ void m_reset()
+ {
+ t_int i;
+ t_atom sortie[0];
+
+ for (i=0; i<nb_mass; i++) {
+ delete mass[i];
+ }
+ for (i=0; i<nb_link; i++) {
+ delete link[i];
+ }
+ ToOutAnything(1,gensym("Reset"),0,sortie);
+ nb_link = 0;
+ nb_mass = 0;
+ id_mass = 0;
+ id_link = 0;
+ }
+
+// -------------------------------------------------------------- COMPUTE
+
+ void m_bang()
+ {
+ t_float F=0,Fx=0,Fy=0, Fz=0,distance,vitesse, X_new, Y_new, Z_new;
+ t_int i;
+ struct _mass mass_1, mass_2;
+
+ for (i=0; i<nb_link; i++) {
+ // compute link forces
+ distance = sqrt(pow(link[i]->mass1->posX-link[i]->mass2->posX,2) +
+ pow(link[i]->mass1->posY-link[i]->mass2->posY,2) + pow(link[i]->mass1->posZ-link[i]->mass2->posZ,2));
+ F = link[i]->K1 * (distance - link[i]->longueur) ; // F = k1(x1-x2)
+ F += link[i]->D1 * (distance - link[i]->distance_old) ; // F = F + D1(v1-v2)
+ if (distance != 0) {
+ Fx = F * (link[i]->mass1->posX - link[i]->mass2->posX)/distance;
+ Fy = F * (link[i]->mass1->posY - link[i]->mass2->posY)/distance;
+ Fz = F * (link[i]->mass1->posZ - link[i]->mass2->posZ)/distance;
+ }
+ link[i]->mass1->forceX -= Fx;
+ link[i]->mass1->forceX -= link[i]->D2*link[i]->mass1->speedX;
+ link[i]->mass2->forceX += Fx;
+ link[i]->mass2->forceX -= link[i]->D2*link[i]->mass2->speedX;
+ link[i]->mass1->forceY -= Fy;
+ link[i]->mass1->forceY -= link[i]->D2*link[i]->mass1->speedY;
+ link[i]->mass2->forceY += Fy;
+ link[i]->mass2->forceY -= link[i]->D2*link[i]->mass2->speedY;
+ link[i]->mass1->forceZ -= Fz;
+ link[i]->mass1->forceZ -= link[i]->D2*link[i]->mass1->speedZ;
+ link[i]->mass2->forceZ += Fz;
+ link[i]->mass2->forceZ -= link[i]->D2*link[i]->mass2->speedZ;
+ link[i]->distance_old = distance;
+ }
+
+ for (i=0; i<nb_mass; i++)
+ // compute new masses position only if mobile = 1
+ if (mass[i]->mobile == 1) {
+ X_new = mass[i]->forceX * mass[i]->invM + 2*mass[i]->posX - mass[i]->posX2;
+ mass[i]->posX2 = mass[i]->posX;
+ mass[i]->posX = max(min(X_new,Xmax),Xmin);
+ mass[i]->speedX = mass[i]->posX - mass[i]->posX2; // vx[n] = x[n] - x[n-1]
+ Y_new = mass[i]->forceY * mass[i]->invM + 2*mass[i]->posY - mass[i]->posY2;
+ mass[i]->posY2 = mass[i]->posY;
+ mass[i]->posY = max(min(Y_new,Ymax),Ymin);
+ mass[i]->speedY = mass[i]->posY - mass[i]->posY2; // vy[n] = y[n] - y[n-1]
+ Z_new = mass[i]->forceZ * mass[i]->invM + 2*mass[i]->posZ - mass[i]->posZ2;
+ mass[i]->posZ2 = mass[i]->posZ;
+ mass[i]->posZ = max(min(Z_new,Zmax),Zmin);
+ mass[i]->speedZ = mass[i]->posZ - mass[i]->posZ2; // vz[n] = z[n] - z[n-1]
+ }
+
+ for (i=0; i<nb_mass; i++) {
+ // clear forces
+ mass[i]->out_forceX = mass[i]->forceX;
+ mass[i]->forceX = 0;
+ mass[i]->out_forceY = mass[i]->forceY;
+ mass[i]->forceY = 0;
+ mass[i]->out_forceZ = mass[i]->forceZ;
+ mass[i]->forceZ = 0;
+ }
+ }
+
+// -------------------------------------------------------------- MASSES
+
+ void m_mass(int argc,t_atom *argv)
+ // add a mass
+ // Id, nbr, mobile, invM, speedX, posX, forceX
+ {
+ t_atom sortie[7], aux[2];
+ int M;
+
+ mass[nb_mass] = new t_mass; // new pointer
+ mass[nb_mass]->Id = GetASymbol(argv[0]); // Id
+ mass[nb_mass]->mobile = GetAInt(argv[1]); // mobile
+ if (GetAInt(argv[2])==0)
+ M=1;
+ else M = GetAInt(argv[2]);
+ mass[nb_mass]->invM = 1/((float)M); // invM
+ mass[nb_mass]->speedX = 0; // vx[n]
+ mass[nb_mass]->posX = GetAInt(argv[3]); // x(n]
+ mass[nb_mass]->posX2 = GetAInt(argv[3]); // x[n-1]
+ mass[nb_mass]->forceX = 0; // Fx[n]
+ mass[nb_mass]->speedY = 0; // vy[n]
+ mass[nb_mass]->posY = GetAInt(argv[4]); // y[n]
+ mass[nb_mass]->posY2 = GetAInt(argv[4]); // y[n-1]
+ mass[nb_mass]->forceY = 0; // Fz[n]
+ mass[nb_mass]->speedZ = 0; // vz[n]
+ mass[nb_mass]->posZ = GetAInt(argv[5]); // z[n]
+ mass[nb_mass]->posZ2 = GetAInt(argv[5]); // z[n-1]
+ mass[nb_mass]->forceZ = 0; // Fz[n]
+ mass[nb_mass]->nbr = id_mass; // id_nbr
+ SETSYMBOL(aux,GetASymbol(argv[0]));
+ atom_string(aux,mass[nb_mass]->Id_string,Id_length);
+ nb_mass++ ;
+ id_mass++;
+ nb_mass = min ( nb_max_mass -1, nb_mass );
+ SETFLOAT(&(sortie[0]),id_mass-1);
+ SETSYMBOL(&(sortie[1]),GetASymbol(argv[0]));
+ SETFLOAT(&(sortie[2]),mass[nb_mass-1]->mobile);
+ SETFLOAT(&(sortie[3]),M);
+ SETFLOAT(&(sortie[4]),mass[nb_mass-1]->posX);
+ SETFLOAT(&(sortie[5]),mass[nb_mass-1]->posY);
+ SETFLOAT(&(sortie[6]),mass[nb_mass-1]->posZ);
+ ToOutAnything(1,gensym("Mass "),7,sortie);
+ }
+
+ void m_forceX(int argc,t_atom *argv)
+ {
+ // add a force to mass(es) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->forceX += GetAFloat(argv[1]);
+ }
+ }
+
+ void m_forceY(int argc,t_atom *argv)
+ {
+ // add a force to mass(es) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->forceY += GetAFloat(argv[1]);
+ }
+ }
+
+ void m_forceZ(int argc,t_atom *argv)
+ {
+ // add a force to mass(es) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->forceZ += GetAFloat(argv[1]);
+ }
+ }
+
+ void m_posX(int argc,t_atom *argv)
+ {
+ // displace mass(es) named Id to a certain position
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ if (GetAFloat(argv[1]) < Xmax && GetAFloat(argv[1]) > Xmin)
+ {
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->posX = GetAFloat(argv[1]);
+ }
+ }
+ }
+
+ void m_posY(int argc,t_atom *argv)
+ {
+ // displace mass(es) named Id to a certain position
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ if (GetAFloat(argv[1]) < Ymax && GetAFloat(argv[1]) > Ymin)
+ {
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->posY = GetAFloat(argv[1]);
+ }
+ }
+ }
+
+ void m_posZ(int argc,t_atom *argv)
+ {
+ // displace mass(es) named Id to a certain position
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ if (GetAFloat(argv[1]) < Zmax && GetAFloat(argv[1]) > Zmin)
+ {
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_mass;i++)
+ {
+ aux = strcmp(buffer,mass[i]->Id_string);
+ if (aux == 0)
+ mass[i]->posZ = GetAFloat(argv[1]);
+ }
+ }
+ }
+
+ void m_set_mobile(int argc,t_atom *argv)
+ {
+ // set mass No to mobile
+ t_int i,aux;
+
+ aux = GetAInt(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ {
+ if (mass[i]->nbr == aux)
+ mass[i]->mobile = 1;
+ }
+
+ }
+
+ void m_set_fixe(int argc,t_atom *argv)
+ {
+ // set mass No to fixed
+ t_int i,aux;
+
+ aux = GetAInt(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ {
+ if (mass[i]->nbr == aux)
+ mass[i]->mobile = 0;
+ }
+
+ }
+
+ void m_delete_mass(int argc,t_atom *argv)
+ {
+ // Delete mass
+ t_int i,nb_link_delete=0;
+ t_atom sortie[7], aux[nb_link];
+
+ for (i=0; i<nb_link;i++) {
+ if (link[i]->mass1->nbr == GetAInt(argv[0]) || link[i]->mass2->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(aux[nb_link_delete]),link[i]->nbr);
+ nb_link_delete++;
+ }
+ }
+
+ for (i=0; i<nb_link_delete;i++)
+ m_delete_link(1,&aux[i]);
+
+
+ for (i=0; i<nb_mass;i++)
+ if (mass[i]->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(sortie[0]),mass[i]->nbr);
+ SETSYMBOL(&(sortie[1]),mass[i]->Id);
+ SETFLOAT(&(sortie[2]),mass[i]->mobile);
+ SETFLOAT(&(sortie[3]),1/mass[i]->invM);
+ SETFLOAT(&(sortie[4]),mass[i]->posX);
+ SETFLOAT(&(sortie[5]),mass[i]->posY);
+ SETFLOAT(&(sortie[6]),mass[i]->posZ);
+ delete mass[i];
+ mass[i] = mass[nb_mass-1];
+ nb_mass--;
+ ToOutAnything(1,gensym("Mass deleted"),7,sortie);
+ break;
+ }
+ }
+
+
+ void m_Xmax(int argc,t_atom *argv)
+ {
+ // set maximum X of all masses
+ Xmax = GetAFloat(argv[0]);
+ }
+
+ void m_Ymax(int argc,t_atom *argv)
+ {
+ // set maximum Y of all masses
+ Ymax = GetAFloat(argv[0]);
+ }
+
+ void m_Zmax(int argc,t_atom *argv)
+ {
+ // set maximum Z of all masses
+ Zmax = GetAFloat(argv[0]);
+ }
+
+ void m_Xmin(int argc,t_atom *argv)
+ {
+ // set minimum X of all masses
+ Xmin = GetAFloat(argv[0]);
+ }
+
+ void m_Ymin(int argc,t_atom *argv)
+ {
+ // set minimum Y of all masses
+ Ymin = GetAFloat(argv[0]);
+ }
+
+ void m_Zmin(int argc,t_atom *argv)
+ {
+ // set minimum Z of all masses
+ Zmin = GetAFloat(argv[0]);
+ }
+// -------------------------------------------------------------- LINKS
+
+ void m_link(int argc,t_atom *argv)
+ // add a link
+ // Id, nbr, *mass1, *mass2, K1, D1
+ {
+ t_atom sortie[7], aux[2];
+ t_int i;
+
+ link[nb_link] = new t_link;
+ link[nb_link]->Id = GetASymbol(argv[0]);
+ for (i=0; i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[1]))
+ link[nb_link]->mass1 = mass[i];
+ else if(mass[i]->nbr==GetAInt(argv[2]))
+ link[nb_link]->mass2 = mass[i];
+ link[nb_link]->K1 = GetAFloat(argv[3]);
+ link[nb_link]->D1 = GetAFloat(argv[4]);
+ link[nb_link]->D2 = GetAFloat(argv[5]);
+ link[nb_link]->longx = link[nb_link]->mass1->posX - link[nb_link]->mass2->posX;
+ link[nb_link]->longy = link[nb_link]->mass1->posY - link[nb_link]->mass2->posY;
+ link[nb_link]->longz = link[nb_link]->mass1->posZ - link[nb_link]->mass2->posZ;
+ link[nb_link]->longueur = sqrt( pow(link[nb_link]->longx,2) + pow(link[nb_link]->longy,2) + pow(link[nb_link]->longz,2));
+ link[nb_link]->nbr = id_link;
+ link[nb_link]->distance_old = link[nb_link]->longueur;
+ SETSYMBOL(aux,GetASymbol(argv[0]));
+ atom_string(aux,(link[nb_link]->Id_string),Id_length);
+ nb_link++;
+ id_link++;
+ nb_link = min ( nb_max_link -1, nb_link );
+ SETFLOAT(&(sortie[0]),id_link-1);
+ SETSYMBOL(&(sortie[1]),link[nb_link-1]->Id);
+ SETFLOAT(&(sortie[2]),GetAInt(argv[1]));
+ SETFLOAT(&(sortie[3]),GetAInt(argv[2]));
+ SETFLOAT(&(sortie[4]),link[nb_link-1]->K1);
+ SETFLOAT(&(sortie[5]),link[nb_link-1]->D1);
+ SETFLOAT(&(sortie[6]),link[nb_link-1]->D2);
+ ToOutAnything(1,gensym("Link "),7,sortie);
+ }
+
+ void m_ilink(int argc,t_atom *argv)
+ // add interactor link
+ // Id, nbr, Id masses1, Id masses2, K1, D1
+ {
+ t_atom aux[2], arglist[6];
+ t_int i,j, strvalue, strvalue2, imass1[nb_mass], nbmass1=0, imass2[nb_mass], nbmass2=0;
+ char buffer[Id_length], buffer2[Id_length];
+
+ ToOutAnything(1,gensym("iLink"),0,aux);
+ SETSYMBOL(aux,GetASymbol(argv[1]));
+ atom_string(aux, buffer, Id_length);
+ SETSYMBOL(aux,GetASymbol(argv[2]));
+ atom_string(aux, buffer2, Id_length);
+
+ for (i=0;i<nb_mass;i++) {
+ strvalue=strcmp(buffer,mass[i]->Id_string);
+ strvalue2=strcmp(buffer2,mass[i]->Id_string);
+ if (strvalue ==0) {
+ imass1[nbmass1]=i;
+ nbmass1++;
+ }
+ if (strvalue2 ==0) {
+ imass2[nbmass2]=i;
+ nbmass2++;
+ }
+ }
+
+ for(i=0;i<nbmass1;i++)
+ for(j=0;j<nbmass2;j++)
+ if (imass1[i] != imass2[j]) {
+ SETSYMBOL(&(arglist[0]),GetASymbol(argv[0]));
+ SETFLOAT(&(arglist[1]),mass[imass1[i]]->nbr);
+ SETFLOAT(&(arglist[2]),mass[imass2[j]]->nbr);
+ SETFLOAT(&(arglist[3]),GetAInt(argv[3]));
+ SETFLOAT(&(arglist[4]),GetAFloat(argv[4]));
+ SETFLOAT(&(arglist[5]),GetAFloat(argv[5]));
+ m_link(6,arglist);
+ }
+ }
+
+ void m_setK(int argc,t_atom *argv)
+ {
+ // set rigidity of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->K1 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_setD(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->D1 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_setD2(int argc,t_atom *argv)
+ {
+ // set damping of link(s) named Id
+ t_int i,aux;
+ t_atom atom[2];
+ char buffer[Id_length];
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, Id_length);
+ for (i=0; i<nb_link;i++)
+ {
+ aux = strcmp(buffer,link[i]->Id_string);
+ if (aux == 0)
+ link[i]->D2 = GetAFloat(argv[1]);
+ }
+ }
+
+ void m_delete_link(int argc,t_atom *argv)
+ {
+ // Delete link
+ t_int i;
+ t_atom sortie[7];
+
+ for (i=0; i<nb_link;i++)
+ if (link[i]->nbr == GetAInt(argv[0])) {
+ SETFLOAT(&(sortie[0]),link[i]->nbr);
+ SETSYMBOL(&(sortie[1]),link[i]->Id);
+ SETFLOAT(&(sortie[2]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[3]),link[i]->mass2->nbr);
+ SETFLOAT(&(sortie[4]),link[i]->K1);
+ SETFLOAT(&(sortie[5]),link[i]->D1);
+ SETFLOAT(&(sortie[6]),link[i]->D2);
+ delete link[i];
+ link[i]=link[nb_link-1];
+ nb_link--;
+ ToOutAnything(1,gensym("Link deleted"),7,sortie);
+ break;
+ }
+ }
+
+
+// -------------------------------------------------------------- GET
+
+ void m_get(int argc,t_atom *argv)
+ // get attributes
+ {
+ t_int i,j, auxstring1, auxstring2, auxstring3, aux;
+ t_symbol *auxarg;
+ t_atom sortie[6],atom[2];
+ char buffer[Id_length],masses[]="massesPos",buffer2[Id_length], forces[] = "massesForces", links[] = "linksPos";
+
+ SETSYMBOL(atom,GetASymbol(argv[0]));
+ atom_string(atom, buffer, 20);
+ auxstring1 = strcmp(buffer,masses); //auxstring1 : 0 masses, 1 else
+ auxstring2 = strcmp(buffer,forces); //auxstring2 : 0 forces, 1 else
+ auxstring3 = strcmp(buffer,links); //auxstring3 : 0 links, 1 else
+ auxarg = GetASymbol(argv[1]); //auxarg : & symbol, 0 else
+ if (argc == 1)
+ {
+ if (auxstring1 == 0)// get all masses positions
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ SETFLOAT(&sortie[2],mass[i]->posZ);
+ ToOutAnything(0,gensym("massesPos"),3,sortie);
+ }
+ else if (auxstring2 == 0)// get all masses forces
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ SETFLOAT(&sortie[2],mass[i]->out_forceZ);
+ ToOutAnything(0,gensym("massesForces"),3,sortie);
+ }
+ else if (auxstring3 == 0)// get all links positions
+ for (i=0; i<nb_link; i++)
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass1->posZ);
+ SETFLOAT(&sortie[3],link[i]->mass2->posX);
+ SETFLOAT(&sortie[4],link[i]->mass2->posY);
+ SETFLOAT(&sortie[5],link[i]->mass2->posZ);
+ ToOutAnything(0,gensym("linksPos"),6,sortie);
+ }
+ else // get all masses speeds
+ for (i=0; i<nb_mass; i++)
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ SETFLOAT(&sortie[2],mass[i]->speedZ);
+ ToOutAnything(0,gensym("massesSpeeds"),3,sortie);
+ }
+ }
+ else if (auxstring1 == 0) // get mass positions
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ SETFLOAT(&sortie[2],mass[i]->posZ);
+ ToOutAnything(0,gensym("massesPosNo"),3,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->posX);
+ SETFLOAT(&sortie[1],mass[i]->posY);
+ SETFLOAT(&sortie[2],mass[i]->posZ);
+ ToOutAnything(0,gensym("massesPosId"),3,sortie);
+ }
+ }
+ }
+ }
+ }
+ else if (auxstring2 == 0) // get mass forces
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ SETFLOAT(&sortie[2],mass[i]->out_forceZ);
+ ToOutAnything(0,gensym("massesForcesNo"),3,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->out_forceX);
+ SETFLOAT(&sortie[1],mass[i]->out_forceY);
+ SETFLOAT(&sortie[2],mass[i]->out_forceZ);
+ ToOutAnything(0,gensym("massesForcesId"),3,sortie);
+ }
+ }
+ }
+ }
+ }
+ else if (auxstring3 == 0) // get links positions
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_link;i++)
+ if (link[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass1->posZ);
+ SETFLOAT(&sortie[3],link[i]->mass2->posX);
+ SETFLOAT(&sortie[4],link[i]->mass2->posY);
+ SETFLOAT(&sortie[5],link[i]->mass2->posZ);
+ ToOutAnything(0,gensym("linksPosNo"),6,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_link;i++)
+ {
+
+ aux = strcmp(buffer2,link[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],link[i]->mass1->posX);
+ SETFLOAT(&sortie[1],link[i]->mass1->posY);
+ SETFLOAT(&sortie[2],link[i]->mass1->posZ);
+ SETFLOAT(&sortie[3],link[i]->mass2->posX);
+ SETFLOAT(&sortie[4],link[i]->mass2->posY);
+ SETFLOAT(&sortie[5],link[i]->mass2->posZ);
+ ToOutAnything(0,gensym("linksPosId"),6,sortie);
+ }
+ }
+ }
+ }
+ }
+ else // get mass speeds
+ {
+ if (auxarg == 0) // No
+ {
+ for (j = 1; j<argc; j++)
+ for (i=0;i<nb_mass;i++)
+ if (mass[i]->nbr==GetAInt(argv[j]))
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ SETFLOAT(&sortie[2],mass[i]->speedZ);
+ ToOutAnything(0,gensym("massesSpeedsNo"),3,sortie);
+ }
+ }
+ else //string
+ {
+ for (j = 1; j<argc; j++)
+ {
+ SETSYMBOL(&atom[1],GetASymbol(argv[j]));
+ atom_string(&atom[1], buffer2, Id_length);
+ for (i=0;i<nb_mass;i++)
+ {
+
+ aux = strcmp(buffer2,mass[i]->Id_string);
+ if (aux==0)
+ {
+ SETFLOAT(&sortie[0],mass[i]->speedX);
+ SETFLOAT(&sortie[1],mass[i]->speedY);
+ SETFLOAT(&sortie[2],mass[i]->speedZ);
+ ToOutAnything(0,gensym("massesSpeedsId"),3,sortie);
+ }
+ }
+ }
+ }
+ }
+
+
+ }
+
+ void m_mass_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[3*nb_mass];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[3*i]),mass[i]->posX);
+ SETFLOAT(&(sortie[3*i+1]),mass[i]->posY);
+ SETFLOAT(&(sortie[3*i+2]),mass[i]->posZ);
+ }
+ ToOutAnything(0, gensym("massesPosL"), 3*nb_mass, sortie);
+ }
+
+ void m_force_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[3*nb_mass];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[3*i]),mass[i]->out_forceX);
+ SETFLOAT(&(sortie[3*i+1]),mass[i]->out_forceY);
+ SETFLOAT(&(sortie[3*i+2]),mass[i]->out_forceZ);
+ }
+ ToOutAnything(0, gensym("massesForcesL"), 3*nb_mass, sortie);
+ }
+
+ void m_link_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[3*nb_link];
+ t_int i;
+
+ for (i=0; i<nb_link; i++) {
+ SETFLOAT(&(sortie[2*i]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[2*i+1]),link[i]->mass2->nbr);
+ }
+ ToOutAnything(0, gensym("linksMassesL"), 2*nb_link, sortie);
+ }
+
+ void m_info_dumpl()
+ // List of masses positions on first outlet
+ {
+ t_atom sortie[7];
+ t_int i;
+
+ for (i=0; i<nb_mass; i++) {
+ SETFLOAT(&(sortie[0]),mass[i]->nbr);
+ SETSYMBOL(&(sortie[1]),mass[i]->Id);
+ SETFLOAT(&(sortie[2]),mass[i]->mobile);
+ SETFLOAT(&(sortie[3]),1/mass[i]->invM);
+ SETFLOAT(&(sortie[4]),mass[i]->posX);
+ SETFLOAT(&(sortie[5]),mass[i]->posY);
+ SETFLOAT(&(sortie[6]),mass[i]->posZ);
+ ToOutAnything(1, gensym("Mass"), 7, sortie);
+ }
+
+ for (i=0; i<nb_link; i++) {
+ SETFLOAT(&(sortie[0]),link[i]->nbr);
+ SETSYMBOL(&(sortie[1]),link[i]->Id);
+ SETFLOAT(&(sortie[2]),link[i]->mass1->nbr);
+ SETFLOAT(&(sortie[3]),link[i]->mass2->nbr);
+ SETFLOAT(&(sortie[4]),link[i]->K1);
+ SETFLOAT(&(sortie[5]),link[i]->D1);
+ SETFLOAT(&(sortie[6]),link[i]->D2);
+ ToOutAnything(1, gensym("Link"), 7, sortie);
+ }
+
+ }
+
+// -------------------------------------------------------------- GLOBAL VARIABLES
+
+ t_link * link[nb_max_link];
+ t_mass * mass[nb_max_mass];
+ t_float Xmin, Xmax, Ymin, Ymax, Zmin, Zmax;
+ int nb_link, nb_mass, id_mass, id_link;
+
+// -------------------------------------------------------------- SETUP
+
+private:
+
+ static void setup(t_classid c)
+ {
+ // --- set up meth(i=0; i<nb_link;i++)ods (class scope) ---
+
+ // register a bang method to the default inlet (0)
+ FLEXT_CADDBANG(c,0,m_bang);
+
+ // set up tagged methods for the default inlet (0)
+ // the underscore _ after CADDMETHOD indicates that a message tag is used
+ // no, variable list or anything and all single arguments are recognized automatically, ...
+ FLEXT_CADDMETHOD_(c,0,"reset",m_reset);
+ FLEXT_CADDMETHOD_(c,0,"forceX",m_forceX);
+ FLEXT_CADDMETHOD_(c,0,"forceY",m_forceY);
+ FLEXT_CADDMETHOD_(c,0,"forceZ",m_forceZ);
+ FLEXT_CADDMETHOD_(c,0,"posX",m_posX);
+ FLEXT_CADDMETHOD_(c,0,"Xmax",m_Xmax);
+ FLEXT_CADDMETHOD_(c,0,"Xmin",m_Xmin);
+ FLEXT_CADDMETHOD_(c,0,"Ymax",m_Ymax);
+ FLEXT_CADDMETHOD_(c,0,"Ymin",m_Ymin);
+ FLEXT_CADDMETHOD_(c,0,"posY",m_posY);
+ FLEXT_CADDMETHOD_(c,0,"Zmax",m_Zmax);
+ FLEXT_CADDMETHOD_(c,0,"Zmin",m_Zmin);
+ FLEXT_CADDMETHOD_(c,0,"posZ",m_posZ);
+ FLEXT_CADDMETHOD_(c,0,"setK",m_setK);
+ FLEXT_CADDMETHOD_(c,0,"setD",m_setD);
+ FLEXT_CADDMETHOD_(c,0,"setD2",m_setD2);
+ FLEXT_CADDMETHOD_(c,0,"mass",m_mass);
+ FLEXT_CADDMETHOD_(c,0,"link",m_link);
+ FLEXT_CADDMETHOD_(c,0,"iLink",m_ilink);
+ FLEXT_CADDMETHOD_(c,0,"get",m_get);
+ FLEXT_CADDMETHOD_(c,0,"deleteLink",m_delete_link);
+ FLEXT_CADDMETHOD_(c,0,"deleteMass",m_delete_mass);
+ FLEXT_CADDMETHOD_(c,0,"massesPosL",m_mass_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"infosL",m_info_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"linksMassesL",m_link_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"massesForcesL",m_force_dumpl);
+ FLEXT_CADDMETHOD_(c,0,"setMobile",m_set_mobile);
+ FLEXT_CADDMETHOD_(c,0,"setFixed",m_set_fixe);
+ }
+
+ // for every registered method a callback has to be declared
+ FLEXT_CALLBACK(m_bang)
+ FLEXT_CALLBACK(m_mass_dumpl)
+ FLEXT_CALLBACK(m_info_dumpl)
+ FLEXT_CALLBACK(m_force_dumpl)
+ FLEXT_CALLBACK(m_link_dumpl)
+ FLEXT_CALLBACK(m_reset)
+ FLEXT_CALLBACK_V(m_mass)
+ FLEXT_CALLBACK_V(m_link)
+ FLEXT_CALLBACK_V(m_ilink)
+ FLEXT_CALLBACK_V(m_Xmax)
+ FLEXT_CALLBACK_V(m_Xmin)
+ FLEXT_CALLBACK_V(m_Ymax)
+ FLEXT_CALLBACK_V(m_Ymin)
+ FLEXT_CALLBACK_V(m_Zmax)
+ FLEXT_CALLBACK_V(m_Zmin)
+ FLEXT_CALLBACK_V(m_setK)
+ FLEXT_CALLBACK_V(m_setD)
+ FLEXT_CALLBACK_V(m_setD2)
+ FLEXT_CALLBACK_V(m_forceX)
+ FLEXT_CALLBACK_V(m_forceY)
+ FLEXT_CALLBACK_V(m_forceZ)
+ FLEXT_CALLBACK_V(m_posX)
+ FLEXT_CALLBACK_V(m_posY)
+ FLEXT_CALLBACK_V(m_posZ)
+ FLEXT_CALLBACK_V(m_get)
+ FLEXT_CALLBACK_V(m_delete_link)
+ FLEXT_CALLBACK_V(m_delete_mass)
+ FLEXT_CALLBACK_V(m_set_mobile)
+ FLEXT_CALLBACK_V(m_set_fixe)
+};
+
+// instantiate the class (constructor has a variable argument list)
+FLEXT_NEW_V("msd3D",msd3D)
+
+
diff --git a/msd3D/msd3Dball.pd b/msd3D/msd3Dball.pd
new file mode 100644
index 0000000..1ffcb08
--- /dev/null
+++ b/msd3D/msd3Dball.pd
@@ -0,0 +1,204 @@
+#N canvas 458 69 863 802 10;
+#X obj 32 13 loadbang;
+#X obj 294 522 print msd;
+#X obj 642 647 gemwin;
+#X msg 642 625 0 \, destroy;
+#X obj 634 704 gemhead;
+#X obj 634 727 world_light;
+#X msg 642 562 reset \, create \, lighting 1 \, 1;
+#X obj 115 259 t a;
+#X obj 115 18 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262131 -1
+-1;
+#X msg 187 69 reset;
+#X text 153 19 reset;
+#X msg 149 136 50 50;
+#X obj 33 298 gemhead;
+#X obj 33 321 t b;
+#X msg 33 343 bang \, get massesPos \, get linksPos;
+#N canvas 643 123 605 590 massrender 0;
+#X obj 127 22 inlet;
+#X obj 48 203 translateXYZ;
+#X obj 48 229 sphere 0.1;
+#X obj 127 86 / 12.5;
+#X obj 127 109 - 4;
+#X obj 192 87 / 12.5;
+#X obj 192 110 - 4;
+#X obj 64 114 gemhead;
+#X obj 48 177 separator;
+#X obj 48 153 any;
+#X obj 125 136 t b f;
+#X obj 127 57 unpack f f f;
+#X obj 244 87 / 12.5;
+#X obj 244 110 - 4;
+#X connect 0 0 11 0;
+#X connect 1 0 2 0;
+#X connect 3 0 4 0;
+#X connect 4 0 10 0;
+#X connect 5 0 6 0;
+#X connect 6 0 1 2;
+#X connect 7 0 9 1;
+#X connect 8 0 1 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 10 1 1 1;
+#X connect 11 0 3 0;
+#X connect 11 1 5 0;
+#X connect 11 2 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 1 3;
+#X restore 114 589 pd massrender;
+#N canvas 284 227 587 558 linkrender 0;
+#X obj 93 25 inlet;
+#X obj 93 117 / 12.5;
+#X obj 93 140 - 4;
+#X obj 147 118 / 12.5;
+#X obj 147 141 - 4;
+#X obj 35 134 gemhead;
+#X obj 44 222 separator;
+#X obj 44 192 any;
+#X obj 93 164 t b f;
+#X obj 44 265 curve 2;
+#X obj 266 117 / 12.5;
+#X obj 266 140 - 4;
+#X obj 320 118 / 12.5;
+#X obj 320 141 - 4;
+#X obj 93 69 unpack f f f f f f;
+#X obj 197 117 / 12.5;
+#X obj 197 142 - 4;
+#X obj 123 194 pack f f f;
+#X msg 123 217 \$1 \$2 \$3;
+#X obj 371 118 / 12.5;
+#X obj 371 141 - 4;
+#X obj 266 189 pack f f f;
+#X msg 266 212 \$1 \$2 \$3;
+#X connect 0 0 14 0;
+#X connect 1 0 2 0;
+#X connect 2 0 8 0;
+#X connect 3 0 4 0;
+#X connect 4 0 17 1;
+#X connect 5 0 7 1;
+#X connect 6 0 9 0;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 8 1 17 0;
+#X connect 10 0 11 0;
+#X connect 11 0 21 0;
+#X connect 12 0 13 0;
+#X connect 13 0 21 1;
+#X connect 14 0 1 0;
+#X connect 14 1 3 0;
+#X connect 14 2 15 0;
+#X connect 14 3 10 0;
+#X connect 14 4 12 0;
+#X connect 14 5 19 0;
+#X connect 15 0 16 0;
+#X connect 16 0 17 2;
+#X connect 17 0 18 0;
+#X connect 18 0 9 1;
+#X connect 19 0 20 0;
+#X connect 20 0 21 2;
+#X connect 21 0 22 0;
+#X connect 22 0 9 2;
+#X restore 33 610 pd linkrender;
+#X obj 33 560 route linksPos massesPos;
+#N canvas 731 296 450 300 gemmouse 0;
+#X obj 189 77 gemmouse;
+#X obj 189 184 pack f f;
+#X obj 189 218 spigot;
+#X obj 103 244 outlet;
+#X obj 189 131 - 0;
+#X obj 216 131 + 100;
+#X obj 189 108 / 5;
+#X obj 216 108 / -5;
+#X obj 79 51 inlet;
+#X obj 140 75 inlet;
+#X obj 141 120 l;
+#X obj 109 98 t b;
+#X connect 0 0 6 0;
+#X connect 0 1 7 0;
+#X connect 0 2 2 1;
+#X connect 1 0 2 0;
+#X connect 2 0 10 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 3 0;
+#X connect 11 0 10 0;
+#X restore 33 672 pd gemmouse;
+#X obj 33 651 gemhead;
+#X msg 33 693 posX fix \$1;
+#X msg 33 714 posY fix \$2;
+#X obj 33 497 msd3D --------------------------------;
+#X msg 62 440 forceZ mob 200;
+#X msg 149 169 Xmax 100 \, Xmin 0 \, Ymax 100 \, Ymin 0 \, Zmax 70
+\, Zmin 0;
+#X msg 251 150 mass mob 1 100 \$1 \$2 \$3;
+#X obj 116 38 t b b b b b b;
+#X msg 254 15 mass fixe 0 100 30 30 20 \, mass fix 0 100 30 70 20 \,
+mass fix 0 100 70 30 20 \, mass fix 0 100 70 70 20;
+#X msg 174 436 forceZ mob -1;
+#X msg 251 63 35 50 50 \, 40 60 50 \, 50 65 50 \, 60 60 50 \, 65 50
+50 \, 60 40 50 \, 50 35 50 \, 40 40 50 \, 40 50 60 \, 43.3 56.7 60
+\, 50 60 60 \, 56.7 56.7 60 \, 60 50 60 \, 56.7 43.3 60 \, 50 40 60
+\, 43.3 43.3 60 \, 50 50 65 \, 40 50 40 \, 43.3 56.7 40 \, 50 60 40
+\, 56.7 56.7 40 \, 60 50 40 \, 56.7 43.3 40 \, 50 40 40 \, 43.3 43.3
+40 \, 50 50 35 \, 50 50 50;
+#X msg 268 199 0 1 \, 1 2 \, 2 3 \, 3 4 \, 4 5 \, 5 6 \, 6 7 \, 7 0
+\, 8 9 \, 9 10 \, 10 11 \, 11 12 \, 12 13 \, 13 14 \, 14 15 \, 15 8
+\, 17 18 \, 18 19 \, 19 20 \, 20 21 \, 21 22 \, 22 23 \, 23 24 \, 24
+17 \, 0 8 \, 1 9 \, 2 10 \, 3 11 \, 4 12 \, 5 13 \, 6 14 \, 7 15 \,
+8 16 \, 9 16 \, 10 16 \, 11 16 \, 12 16 \, 13 16 \, 14 16 \, 15 16
+\, 0 17 \, 1 18 \, 2 19 \, 3 20 \, 4 21 \, 5 22 \, 6 23 \, 7 24 \,
+17 25 \, 18 25 \, 19 25 \, 20 25 \, 21 25 \, 22 25 \, 23 25 \, 24 25
+\, 16 26 \, 26 25 \, 0 26 \, 26 4 \, 1 26 \, 26 5 \, 2 26 \, 26 6 \,
+3 26 \, 26 7 \, 26 8 \, 26 12 \, 26 9 \, 26 13 \, 26 10 \, 26 14 \,
+26 11 \, 26 15 \, 26 17 \, 26 21 \, 26 18 \, 26 22 \, 26 19 \, 26 23
+\, 26 20 \, 26 24 \, 8 12 \, 9 13 \, 10 14 \, 11 15 \, 17 21 \, 18
+22 \, 19 23 \, 20 24 \, 0 2 \, 2 4 \, 4 6 \, 6 0 \, 1 3 \, 3 5 \, 5
+7 \, 7 1 \, 8 10 \, 10 12 \, 12 14 \, 14 8 \, 9 11 \, 11 13 \, 13 15
+\, 15 9 \, 17 19 \, 19 21 \, 21 23 \, 23 17 \, 18 20 \, 20 22 \, 22
+24 \, 24 18 \, 17 8 \, 18 9 \, 19 10 \, 20 11 \, 21 12 \, 22 13 \,
+23 14 \, 24 15 \, 0 25 \, 0 16 \, 1 25 \, 1 16 \, 2 25 \, 2 16 \, 3
+25 \, 3 16 \, 4 25 \, 5 16 \, 5 25 \, 6 16 \, 6 25 \, 7 16 \, 7 25
+;
+#X msg 47 207 link souple \$1 \$2 1 2.5 0.01;
+#X msg 429 544 view 0 3 0 0 0 0 0 0 1;
+#X msg 429 523 view 0 0 1 0 0 0 0 1 0;
+#X msg 429 500 view 3 0 0.5 0 0 0 0 0 1;
+#X connect 0 0 26 0;
+#X connect 3 0 2 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
+#X connect 7 0 22 0;
+#X connect 8 0 26 0;
+#X connect 9 0 7 0;
+#X connect 11 0 18 1;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 22 0;
+#X connect 14 0 28 0;
+#X connect 17 0 16 0;
+#X connect 17 1 15 0;
+#X connect 18 0 20 0;
+#X connect 18 0 21 0;
+#X connect 19 0 18 0;
+#X connect 22 0 17 0;
+#X connect 22 1 1 0;
+#X connect 23 0 22 0;
+#X connect 24 0 7 0;
+#X connect 25 0 7 0;
+#X connect 26 2 11 0;
+#X connect 26 2 24 0;
+#X connect 26 3 30 0;
+#X connect 26 4 27 0;
+#X connect 26 4 29 0;
+#X connect 26 5 9 0;
+#X connect 29 0 25 0;
+#X connect 30 0 31 0;
+#X connect 31 0 7 0;
+#X connect 32 0 2 0;
+#X connect 33 0 6 0;
+#X connect 34 0 2 0;
diff --git a/msd3D/package.txt b/msd3D/package.txt
new file mode 100644
index 0000000..b70eac4
--- /dev/null
+++ b/msd3D/package.txt
@@ -0,0 +1,2 @@
+NAME=msd3D
+SRCS=main.cpp