just a test

Dependencies:   mbed

Fork of scoreLight_Advanced by Alvaro Cassinelli

Committer:
mbedalvaro
Date:
Tue Dec 02 04:28:42 2014 +0000
Revision:
48:7633d8e7b0d3
Parent:
47:2312a8dc9658
this is the working version of the skin games sowtware (aka, scorelight but with pre-determined "games")

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedalvaro 31:5f039cbddee8 1 /*
mbedalvaro 31:5f039cbddee8 2 * elasticLoop.cpp
mbedalvaro 31:5f039cbddee8 3 * laserBlobPure
mbedalvaro 31:5f039cbddee8 4 *
mbedalvaro 31:5f039cbddee8 5 * Created by CASSINELLI ALVARO on 5/20/11.
mbedalvaro 31:5f039cbddee8 6 * Copyright 2011 TOKYO UNIVERSITY. All rights reserved.
mbedalvaro 31:5f039cbddee8 7 *
mbedalvaro 31:5f039cbddee8 8 */
mbedalvaro 31:5f039cbddee8 9
mbedalvaro 31:5f039cbddee8 10 #include "elasticLoop.h"
mbedalvaro 31:5f039cbddee8 11
mbedalvaro 31:5f039cbddee8 12 // SHOULD NOT BE HERE: (only because I am using AD_MIRRIOR... max and min in the set region function that should not be here)
mbedalvaro 31:5f039cbddee8 13 #include "hardwareIO.h"
mbedalvaro 31:5f039cbddee8 14
mbedalvaro 31:5f039cbddee8 15 elasticLoop::elasticLoop() {
mbedalvaro 31:5f039cbddee8 16 }
mbedalvaro 31:5f039cbddee8 17
mbedalvaro 31:5f039cbddee8 18 elasticLoop::~elasticLoop() {
mbedalvaro 31:5f039cbddee8 19 // no need to do clear, this is done by default when clearing the vector container?
mbedalvaro 31:5f039cbddee8 20 massesLoop.clear();
mbedalvaro 31:5f039cbddee8 21 loopSpringArray.clear();
mbedalvaro 31:5f039cbddee8 22 hairVector.clear();
mbedalvaro 31:5f039cbddee8 23 lightForce.clear();
mbedalvaro 31:5f039cbddee8 24 centralSpringArray.clear();
mbedalvaro 31:5f039cbddee8 25 displaySensingBuffer.lsdTrajectory.clear();
mbedalvaro 31:5f039cbddee8 26 }
mbedalvaro 31:5f039cbddee8 27
mbedalvaro 47:2312a8dc9658 28 void elasticLoop::showChildParameters() {
mbedalvaro 47:2312a8dc9658 29 // pc.printf("Mirror delay :%d\n", displaySensingBuffer.delayMirrorSamples);
mbedalvaro 47:2312a8dc9658 30 // pc.printf("Angle correction force :%d\n", angleCorrectionForceLoop);
mbedalvaro 47:2312a8dc9658 31 pc.printf("Integration Step Loop :%f\n", integrationStepLoop);
mbedalvaro 47:2312a8dc9658 32 pc.printf("Integration Step Anchor :%f\n", integrationStepAnchor);
mbedalvaro 46:90516893793a 33 }
mbedalvaro 31:5f039cbddee8 34
mbedalvaro 31:5f039cbddee8 35 void elasticLoop::createBlob(int _id, ElasticLoopMode _elasticBlobMode, vector2Df _initPos, vector2Df _initSpeed) {
mbedalvaro 31:5f039cbddee8 36 // (1) set ID:
mbedalvaro 31:5f039cbddee8 37 identifier=_id;
mbedalvaro 31:5f039cbddee8 38
mbedalvaro 31:5f039cbddee8 39 startCenter=_initPos;
mbedalvaro 31:5f039cbddee8 40 startSpeed=_initSpeed;
mbedalvaro 31:5f039cbddee8 41
mbedalvaro 31:5f039cbddee8 42 // (2) Initialize common variables of all blobs (base class):
mbedalvaro 45:a3b984a79d5d 43 // initCommonVariables();
mbedalvaro 31:5f039cbddee8 44
mbedalvaro 31:5f039cbddee8 45 // (3) initialize common variables for the elastic blob types:
mbedalvaro 46:90516893793a 46 integrationStepLoop=0.22;
mbedalvaro 46:90516893793a 47 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 48
mbedalvaro 31:5f039cbddee8 49 slidingDirection=true; // (will change when touching wall)
mbedalvaro 31:5f039cbddee8 50 // Sending data:
mbedalvaro 31:5f039cbddee8 51 periodSendingData=15; // in ms
mbedalvaro 31:5f039cbddee8 52 sendingLoopPositions=false;
mbedalvaro 31:5f039cbddee8 53 sendingBlobArea=true;
mbedalvaro 31:5f039cbddee8 54 sendingKineticEnergy=true;
mbedalvaro 32:52273c3291fe 55 sendingBlobMaxMin=true;
mbedalvaro 32:52273c3291fe 56 // send ALWAYS, regardless of the fact the blob is being touched or not, in case of elastic loops:
mbedalvaro 32:52273c3291fe 57 sendingOnlyWhenTouch=false;
mbedalvaro 31:5f039cbddee8 58
mbedalvaro 31:5f039cbddee8 59 // (3) Initialize secondary variables depending on the blob type and mode:
mbedalvaro 31:5f039cbddee8 60
mbedalvaro 31:5f039cbddee8 61 // NOTE (!): the mode does not affect the update method; in fact, all these elastic loops have different behaviours because of different parameters (but the booleans modes could
mbedalvaro 31:5f039cbddee8 62 // actually be "condensed" in a mode...)
mbedalvaro 31:5f039cbddee8 63
mbedalvaro 31:5f039cbddee8 64 switch (_elasticBlobMode) {
mbedalvaro 31:5f039cbddee8 65 case RELAX:
mbedalvaro 31:5f039cbddee8 66
mbedalvaro 31:5f039cbddee8 67 // Name of this kind of spot:
mbedalvaro 31:5f039cbddee8 68 sprintf(spotName,"loop_relax"); //this is an relaxing elastic loop
mbedalvaro 31:5f039cbddee8 69
mbedalvaro 31:5f039cbddee8 70 // Color: (use parameter in the future):
mbedalvaro 31:5f039cbddee8 71 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 72 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 73 blueTouch=true;
mbedalvaro 31:5f039cbddee8 74
mbedalvaro 31:5f039cbddee8 75 // default (initial) shape (the scafold belongs to the base class):
mbedalvaro 31:5f039cbddee8 76 startRadius=400;
mbedalvaro 31:5f039cbddee8 77 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 78
mbedalvaro 31:5f039cbddee8 79 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 80 massLoopParticle=0.25;
mbedalvaro 31:5f039cbddee8 81 dampMotionMassesLoop=0.025;//0.17;
mbedalvaro 31:5f039cbddee8 82 massAnchor=2.0;
mbedalvaro 31:5f039cbddee8 83 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 84 // Springs:
mbedalvaro 31:5f039cbddee8 85 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 86 centralSpringRelax=startRadius;// use the radius of the scafold
mbedalvaro 31:5f039cbddee8 87 interSpringK=0.46;
mbedalvaro 31:5f039cbddee8 88 interSpringRelax=20;
mbedalvaro 31:5f039cbddee8 89 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 90 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 91 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 92
mbedalvaro 31:5f039cbddee8 93 searchActive=false;
mbedalvaro 31:5f039cbddee8 94 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 95
mbedalvaro 31:5f039cbddee8 96 // Active/inactive forces:
mbedalvaro 31:5f039cbddee8 97 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 98 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 99 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 100 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 101 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 102 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 103
mbedalvaro 31:5f039cbddee8 104 // Recentering vector:
mbedalvaro 31:5f039cbddee8 105 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 106 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 107 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 108 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 109
mbedalvaro 31:5f039cbddee8 110 factorLightForce=4.0;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 111 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size(); // use number of points in the scafold
mbedalvaro 31:5f039cbddee8 112 factorRecenteringLoopMass=0.3;
mbedalvaro 31:5f039cbddee8 113 factorPressureLoopMass=1.0;
mbedalvaro 31:5f039cbddee8 114 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 115
mbedalvaro 31:5f039cbddee8 116 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 117 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 118 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 119
mbedalvaro 31:5f039cbddee8 120 break;
mbedalvaro 31:5f039cbddee8 121
mbedalvaro 31:5f039cbddee8 122 case CONTRACT:
mbedalvaro 31:5f039cbddee8 123
mbedalvaro 31:5f039cbddee8 124 sprintf(spotName,"loop_contract"); //this is an relaxing elastic loop
mbedalvaro 31:5f039cbddee8 125
mbedalvaro 31:5f039cbddee8 126 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 127 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 128
mbedalvaro 31:5f039cbddee8 129 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 130 startRadius =400;
mbedalvaro 31:5f039cbddee8 131 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 132
mbedalvaro 31:5f039cbddee8 133 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 134 massLoopParticle=0.25;
mbedalvaro 31:5f039cbddee8 135 dampMotionMassesLoop=0.024;//0.17;
mbedalvaro 31:5f039cbddee8 136 massAnchor=2.0;
mbedalvaro 31:5f039cbddee8 137 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 138 // Springs:
mbedalvaro 31:5f039cbddee8 139 centralSpringK=0.5;
mbedalvaro 31:5f039cbddee8 140 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 141 interSpringK=0.4;//46;
mbedalvaro 31:5f039cbddee8 142 interSpringRelax=30;
mbedalvaro 31:5f039cbddee8 143 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 144 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 145 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 146
mbedalvaro 31:5f039cbddee8 147 searchActive=false;
mbedalvaro 31:5f039cbddee8 148 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 149
mbedalvaro 31:5f039cbddee8 150 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 151 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 152 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 153 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 154 nuclearForceOnLoop=true;//true;
mbedalvaro 31:5f039cbddee8 155 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 156 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 157 // Recentering vector:
mbedalvaro 31:5f039cbddee8 158 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 159 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 160 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 161 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 162
mbedalvaro 31:5f039cbddee8 163 factorLightForce=6.0;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 164 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 165 factorRecenteringLoopMass=0.3;
mbedalvaro 31:5f039cbddee8 166 factorPressureLoopMass=1.0;
mbedalvaro 31:5f039cbddee8 167 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 168
mbedalvaro 31:5f039cbddee8 169 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 170 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 171 displaySensingBuffer.setDelayMirrors(2); // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 172
mbedalvaro 31:5f039cbddee8 173 break;
mbedalvaro 46:90516893793a 174 case CONTRACT_CENTRAL: // this is the "big mouth"
mbedalvaro 31:5f039cbddee8 175
mbedalvaro 47:2312a8dc9658 176 integrationStepLoop=0.4;
mbedalvaro 46:90516893793a 177 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 178
mbedalvaro 31:5f039cbddee8 179 sprintf(spotName,"contract_central");
mbedalvaro 31:5f039cbddee8 180
mbedalvaro 31:5f039cbddee8 181 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 182 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 183 blueTouch=true;
mbedalvaro 31:5f039cbddee8 184
mbedalvaro 31:5f039cbddee8 185 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 186 startRadius=400;
mbedalvaro 31:5f039cbddee8 187 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 45); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 188
mbedalvaro 31:5f039cbddee8 189 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 190 massLoopParticle=0.3;
mbedalvaro 31:5f039cbddee8 191 dampMotionMassesLoop=0.023;//0.17;
mbedalvaro 31:5f039cbddee8 192 massAnchor=0.5;
mbedalvaro 31:5f039cbddee8 193 dampMotionAnchorMass=0.001;
mbedalvaro 31:5f039cbddee8 194 // Springs:
mbedalvaro 31:5f039cbddee8 195 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 196 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 197 interSpringK=0.54;//46;
mbedalvaro 47:2312a8dc9658 198 interSpringRelax=25;//30;
mbedalvaro 31:5f039cbddee8 199 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 200 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 201 factorInterParticleForce=18.0;
mbedalvaro 31:5f039cbddee8 202
mbedalvaro 31:5f039cbddee8 203 searchActive=false;
mbedalvaro 31:5f039cbddee8 204 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 205
mbedalvaro 31:5f039cbddee8 206 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 207 springForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 208 lightForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 209 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 210 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 211 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 212 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 213 // Recentering vector:
mbedalvaro 31:5f039cbddee8 214 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 215 recenteringForceOnLoop=false ; //true; !!!!!!!!!!!!!!!
mbedalvaro 31:5f039cbddee8 216 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 217 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 218
mbedalvaro 47:2312a8dc9658 219 factorLightForce=8.0;//4.3;
mbedalvaro 31:5f039cbddee8 220 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 221 factorRecenteringLoopMass=0.045;
mbedalvaro 31:5f039cbddee8 222 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 223 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 224
mbedalvaro 31:5f039cbddee8 225 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 226 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 44:46e25fa1669b 227 displaySensingBuffer.setDelayMirrors(1);
mbedalvaro 31:5f039cbddee8 228
mbedalvaro 31:5f039cbddee8 229 break;
mbedalvaro 31:5f039cbddee8 230
mbedalvaro 31:5f039cbddee8 231 case CONTRACT_CENTRAL_FAST:
mbedalvaro 31:5f039cbddee8 232
mbedalvaro 31:5f039cbddee8 233 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 234 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 235 blueTouch=true;
mbedalvaro 31:5f039cbddee8 236
mbedalvaro 31:5f039cbddee8 237 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 238 startRadius=150;
mbedalvaro 31:5f039cbddee8 239 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 240
mbedalvaro 31:5f039cbddee8 241 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 242 massLoopParticle=0.06;
mbedalvaro 31:5f039cbddee8 243 dampMotionMassesLoop=0.021;//0.17;
mbedalvaro 31:5f039cbddee8 244 massAnchor=0.5;
mbedalvaro 31:5f039cbddee8 245 dampMotionAnchorMass=0.01;
mbedalvaro 31:5f039cbddee8 246 // Springs:
mbedalvaro 31:5f039cbddee8 247 centralSpringK=0.3;
mbedalvaro 31:5f039cbddee8 248 centralSpringRelax=startRadius;
mbedalvaro 31:5f039cbddee8 249 interSpringK=0.54;//46;
mbedalvaro 31:5f039cbddee8 250 interSpringRelax=40;
mbedalvaro 31:5f039cbddee8 251 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 252 interParticleRange=150;
mbedalvaro 31:5f039cbddee8 253 factorInterParticleForce=160.0;
mbedalvaro 31:5f039cbddee8 254
mbedalvaro 31:5f039cbddee8 255 searchActive=false;
mbedalvaro 31:5f039cbddee8 256 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 257
mbedalvaro 31:5f039cbddee8 258 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 259 springForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 260 lightForcesOnLoop= true;
mbedalvaro 31:5f039cbddee8 261 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 262 nuclearForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 263 interParticleForceOnLoop=true; //!!!
mbedalvaro 31:5f039cbddee8 264 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 265 // Recentering vector:
mbedalvaro 31:5f039cbddee8 266 angleCorrectionForceLoop=90;// in deg
mbedalvaro 31:5f039cbddee8 267 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 268 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 269 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 270
mbedalvaro 31:5f039cbddee8 271 factorLightForce=-4;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 272 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 273 factorRecenteringLoopMass=0.06;
mbedalvaro 31:5f039cbddee8 274 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 275 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 276
mbedalvaro 44:46e25fa1669b 277 displaySensingBuffer.setDelayMirrors(1);
mbedalvaro 31:5f039cbddee8 278 break;
mbedalvaro 31:5f039cbddee8 279
mbedalvaro 31:5f039cbddee8 280 case CONTOUR_FOLLOWING:
mbedalvaro 31:5f039cbddee8 281 sprintf(spotName,"following"); //this is a contour-following loop
mbedalvaro 31:5f039cbddee8 282
mbedalvaro 46:90516893793a 283 integrationStepLoop=0.22;
mbedalvaro 46:90516893793a 284 integrationStepAnchor=0.4;
mbedalvaro 46:90516893793a 285
mbedalvaro 31:5f039cbddee8 286 //setColor(0x07);//0x04+0x02>>i);
mbedalvaro 31:5f039cbddee8 287 setColor(0x04);
mbedalvaro 45:a3b984a79d5d 288 blueTouch=true;
mbedalvaro 31:5f039cbddee8 289
mbedalvaro 31:5f039cbddee8 290 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 291 startRadius=100;
mbedalvaro 31:5f039cbddee8 292 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 293
mbedalvaro 31:5f039cbddee8 294 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 295 massLoopParticle=0.05;
mbedalvaro 31:5f039cbddee8 296 dampMotionMassesLoop=0.27;//0.17;
mbedalvaro 31:5f039cbddee8 297 massAnchor=3.0;
mbedalvaro 31:5f039cbddee8 298 dampMotionAnchorMass=0.03;
mbedalvaro 31:5f039cbddee8 299 // Springs:
mbedalvaro 44:46e25fa1669b 300 centralSpringK=0.4;
mbedalvaro 31:5f039cbddee8 301 centralSpringRelax=100;//bluePrint.radius;
mbedalvaro 44:46e25fa1669b 302 interSpringK=0.4;
mbedalvaro 31:5f039cbddee8 303 interSpringRelax=0.7*startRadius*2*sin(1.0* PI/ bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 304 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 305 interParticleRange=70;
mbedalvaro 31:5f039cbddee8 306 factorInterParticleForce=4.0;
mbedalvaro 31:5f039cbddee8 307
mbedalvaro 31:5f039cbddee8 308 searchActive=true;
mbedalvaro 31:5f039cbddee8 309 pseudopodesMode=true; // this is for contour following.
mbedalvaro 31:5f039cbddee8 310
mbedalvaro 31:5f039cbddee8 311 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 312 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 313 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 314 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 315 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 316 interParticleForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 317 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 318 // Recentering vector:
mbedalvaro 44:46e25fa1669b 319 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 320 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 321 angleCorrectionForceNucleus=180;// in deg
mbedalvaro 31:5f039cbddee8 322 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 323
mbedalvaro 40:ee217eff826c 324 factorLightForce=2.4;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 325 factorRecenteringAnchorMass=1.0;//20.0/scafold.size();
mbedalvaro 44:46e25fa1669b 326 factorRecenteringLoopMass=0.2;
mbedalvaro 31:5f039cbddee8 327 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 328 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 329 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 330 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 44:46e25fa1669b 331 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 332
mbedalvaro 31:5f039cbddee8 333 break;
mbedalvaro 31:5f039cbddee8 334 case CONTOUR_FOLLOWING_FAST:
mbedalvaro 31:5f039cbddee8 335 sprintf(spotName,"following_fast");
mbedalvaro 31:5f039cbddee8 336
mbedalvaro 31:5f039cbddee8 337 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 338 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 339
mbedalvaro 31:5f039cbddee8 340 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 341 startRadius=100;
mbedalvaro 31:5f039cbddee8 342 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 30); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 343
mbedalvaro 31:5f039cbddee8 344 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 345 massLoopParticle=0.05;
mbedalvaro 31:5f039cbddee8 346 dampMotionMassesLoop=0.27;//0.17;
mbedalvaro 31:5f039cbddee8 347 massAnchor=3.0;
mbedalvaro 31:5f039cbddee8 348 dampMotionAnchorMass=0.03;
mbedalvaro 31:5f039cbddee8 349 // Springs:
mbedalvaro 31:5f039cbddee8 350 centralSpringK=-200;
mbedalvaro 31:5f039cbddee8 351 centralSpringRelax=100;//bluePrint.radius;
mbedalvaro 31:5f039cbddee8 352 interSpringK=0.5;//46;
mbedalvaro 31:5f039cbddee8 353 interSpringRelax=0.7*startRadius*2*sin(1.0* PI/bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 354 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 355 interParticleRange=80;
mbedalvaro 31:5f039cbddee8 356 factorInterParticleForce=4.0;
mbedalvaro 31:5f039cbddee8 357
mbedalvaro 31:5f039cbddee8 358 searchActive=false;
mbedalvaro 31:5f039cbddee8 359 pseudopodesMode=true; // this is for contour following.
mbedalvaro 31:5f039cbddee8 360
mbedalvaro 31:5f039cbddee8 361 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 362 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 363 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 364 forceBorderOnLoop=false;
mbedalvaro 31:5f039cbddee8 365 nuclearForceOnLoop=false;//true;
mbedalvaro 31:5f039cbddee8 366 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 367 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 368 // Recentering vector:
mbedalvaro 31:5f039cbddee8 369 angleCorrectionForceLoop=243;// in deg
mbedalvaro 31:5f039cbddee8 370 recenteringForceOnLoop=true;
mbedalvaro 31:5f039cbddee8 371 angleCorrectionForceNucleus=180;// in deg
mbedalvaro 31:5f039cbddee8 372 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 373
mbedalvaro 31:5f039cbddee8 374 factorLightForce=2.3;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 375 factorRecenteringAnchorMass=1.0;//20.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 376 factorRecenteringLoopMass=0.09;
mbedalvaro 31:5f039cbddee8 377 factorPressureLoopMass=1.5;
mbedalvaro 31:5f039cbddee8 378 factorForceBorder=150;
mbedalvaro 31:5f039cbddee8 379
mbedalvaro 31:5f039cbddee8 380 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 381 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 382 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 383 break;
mbedalvaro 31:5f039cbddee8 384 case BOUNCING:
mbedalvaro 31:5f039cbddee8 385 sprintf(spotName,"bouncing");
mbedalvaro 31:5f039cbddee8 386
mbedalvaro 31:5f039cbddee8 387 setColor(0x07);//0x04+0x02>>i);
mbedalvaro 45:a3b984a79d5d 388 blueTouch=true;
mbedalvaro 45:a3b984a79d5d 389
mbedalvaro 31:5f039cbddee8 390 // default (initial) shape:
mbedalvaro 31:5f039cbddee8 391 startRadius=70;
mbedalvaro 31:5f039cbddee8 392 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints);
mbedalvaro 31:5f039cbddee8 393
mbedalvaro 31:5f039cbddee8 394 // Numeric parameters for the simulated mechanical system:
mbedalvaro 31:5f039cbddee8 395 massLoopParticle=5.0;
mbedalvaro 31:5f039cbddee8 396 dampMotionMassesLoop=0.001;//0.17;
mbedalvaro 31:5f039cbddee8 397 massAnchor=1.0;
mbedalvaro 31:5f039cbddee8 398 dampMotionAnchorMass=0.002;
mbedalvaro 31:5f039cbddee8 399 // Springs:
mbedalvaro 31:5f039cbddee8 400 centralSpringK=1.0;
mbedalvaro 31:5f039cbddee8 401 centralSpringRelax=70;//bluePrint.radius;
mbedalvaro 31:5f039cbddee8 402 interSpringK=0.4;//46;
mbedalvaro 31:5f039cbddee8 403 interSpringRelax==1.0*startRadius*2*sin(1.0* PI/bluePrint.scafold.size()); // if factor=1, this makes for a perfect polygon at relax for all springs...
mbedalvaro 31:5f039cbddee8 404 // for "zack-like" blob:
mbedalvaro 31:5f039cbddee8 405 interParticleRange=100;
mbedalvaro 31:5f039cbddee8 406 factorInterParticleForce=3.0;
mbedalvaro 31:5f039cbddee8 407
mbedalvaro 31:5f039cbddee8 408 searchActive=false;
mbedalvaro 31:5f039cbddee8 409 pseudopodesMode=false; // this is for contour following.
mbedalvaro 31:5f039cbddee8 410
mbedalvaro 31:5f039cbddee8 411 // Active/Inactive Forces:
mbedalvaro 31:5f039cbddee8 412 springForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 413 lightForcesOnLoop=true;
mbedalvaro 31:5f039cbddee8 414 forceBorderOnLoop=true;
mbedalvaro 31:5f039cbddee8 415 nuclearForceOnLoop=true;//true;
mbedalvaro 31:5f039cbddee8 416 interParticleForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 417 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box)
mbedalvaro 31:5f039cbddee8 418 // Recentering vector:
mbedalvaro 31:5f039cbddee8 419 angleCorrectionForceLoop=0;// in deg
mbedalvaro 31:5f039cbddee8 420 recenteringForceOnLoop=false;
mbedalvaro 31:5f039cbddee8 421 angleCorrectionForceNucleus=0;// in deg
mbedalvaro 31:5f039cbddee8 422 recenteringForceOnNucleus=false;//true;
mbedalvaro 31:5f039cbddee8 423
mbedalvaro 31:5f039cbddee8 424 factorLightForce=0.6;//3.0;//8.0;
mbedalvaro 31:5f039cbddee8 425 factorRecenteringAnchorMass=100.0/bluePrint.scafold.size();
mbedalvaro 31:5f039cbddee8 426 factorRecenteringLoopMass=5.0;
mbedalvaro 31:5f039cbddee8 427 factorPressureLoopMass=2.0;
mbedalvaro 31:5f039cbddee8 428 factorForceBorder=4.5;
mbedalvaro 31:5f039cbddee8 429
mbedalvaro 31:5f039cbddee8 430 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0.
mbedalvaro 31:5f039cbddee8 431 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software):
mbedalvaro 31:5f039cbddee8 432 displaySensingBuffer.setDelayMirrors(2);
mbedalvaro 31:5f039cbddee8 433 break;
mbedalvaro 31:5f039cbddee8 434 }
mbedalvaro 31:5f039cbddee8 435
mbedalvaro 31:5f039cbddee8 436 // Finally, we can create the loop using these parameters, and the positions given in the scafold:
mbedalvaro 31:5f039cbddee8 437 createLoopFromScafold(); // this sets the number of masses
mbedalvaro 31:5f039cbddee8 438
mbedalvaro 31:5f039cbddee8 439 // Excursion limits (ATTN!!! this will set the limits for all the masses, so we need FIRT to call to createLoopFromScafold - NO NEEDED ANYMORE: now calling to static member method of pointMass...)
mbedalvaro 31:5f039cbddee8 440 setRegionMotion(MIN_AD_MIRRORS, MIN_AD_MIRRORS, MAX_AD_MIRRORS, MAX_AD_MIRRORS);
mbedalvaro 31:5f039cbddee8 441
mbedalvaro 31:5f039cbddee8 442 // draw it once on the display buffer for good initialization:
mbedalvaro 31:5f039cbddee8 443 draw();
mbedalvaro 31:5f039cbddee8 444 }
mbedalvaro 31:5f039cbddee8 445
mbedalvaro 31:5f039cbddee8 446 void elasticLoop::speedFactor(float speedfactor) {
mbedalvaro 31:5f039cbddee8 447 // This method is more appropiate for rigid loop, but we can "simulate" speed up in case of elastic loop by changing some parameters, even if the loop is not
mbedalvaro 31:5f039cbddee8 448 // set in "contour following" mode.
mbedalvaro 31:5f039cbddee8 449 factorRecenteringLoopMass*=speedfactor;
mbedalvaro 31:5f039cbddee8 450 }
mbedalvaro 31:5f039cbddee8 451
mbedalvaro 31:5f039cbddee8 452 void elasticLoop::initSizeBlob(int _numMasses) {
mbedalvaro 31:5f039cbddee8 453 // Iinitialize blob size (number of points for the loop, as well as other structures such as lsdTrajectory)
mbedalvaro 31:5f039cbddee8 454 numMasses=_numMasses;
mbedalvaro 31:5f039cbddee8 455 // Since this is an elastic loop object, let's create an elastic loop of masses:
mbedalvaro 31:5f039cbddee8 456 massesLoop.resize(numMasses);
mbedalvaro 31:5f039cbddee8 457 loopSpringArray.resize(numMasses); // springs connecting consecutive masses
mbedalvaro 31:5f039cbddee8 458 // NOTE: to save memory, we can drop hairVector (use lightForce instead)
mbedalvaro 31:5f039cbddee8 459 hairVector.resize(numMasses); // the perpendiculars to the loop
mbedalvaro 31:5f039cbddee8 460 lightForce.resize(numMasses); // light force in each particle
mbedalvaro 31:5f039cbddee8 461 //vector2D totalLightForce; // this belongs to the base class now
mbedalvaro 31:5f039cbddee8 462 centralSpringArray.resize(numMasses); // springs connecting each mass to the anchorMass.
mbedalvaro 31:5f039cbddee8 463
mbedalvaro 31:5f039cbddee8 464 // Sensing and Display trajectory:
mbedalvaro 31:5f039cbddee8 465 displaySensingBuffer.lsdTrajectory.resize(numMasses); // the lsdTrajectory and the elastic loop will have the same number of points (this could be different - decimation?).
mbedalvaro 31:5f039cbddee8 466 }
mbedalvaro 31:5f039cbddee8 467
mbedalvaro 31:5f039cbddee8 468 // We will build the masses from the scafold shape (and maybe render it once on the lsdTrajectory to initialize this array?)
mbedalvaro 31:5f039cbddee8 469 void elasticLoop::createLoopFromScafold(void) {
mbedalvaro 31:5f039cbddee8 470 initSizeBlob(bluePrint.scafold.size()); // important: we will have here the same number of points in the scafold and the elastic loop (massLoop)
mbedalvaro 31:5f039cbddee8 471
mbedalvaro 31:5f039cbddee8 472 // Initial conditions for the loop masses:
mbedalvaro 31:5f039cbddee8 473 for (int i = 0; i < numMasses; i++) {
mbedalvaro 46:90516893793a 474 massesLoop[i].setIntegrationStep(integrationStepLoop);//22);//19); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed.
mbedalvaro 31:5f039cbddee8 475 massesLoop[i].setInitialCondition(startCenter.x+bluePrint.scafold[i].x,startCenter.y+bluePrint.scafold[i].y, startSpeed.x, startSpeed.y);
mbedalvaro 31:5f039cbddee8 476 massesLoop[i].mass=massLoopParticle;
mbedalvaro 31:5f039cbddee8 477 massesLoop[i].dampMotion=dampMotionMassesLoop;
mbedalvaro 31:5f039cbddee8 478 }
mbedalvaro 31:5f039cbddee8 479
mbedalvaro 31:5f039cbddee8 480 // Springs for the loop:
mbedalvaro 31:5f039cbddee8 481 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 482 loopSpringArray[i].distance =interSpringRelax;
mbedalvaro 31:5f039cbddee8 483 // if we want an perfect polygon: =startRadius*2*sin(1.0* PI/ numMasses);
mbedalvaro 31:5f039cbddee8 484 // loopSpringArray[i].distance = startRadius*2*sin(1.0* PI/ numMasses);
mbedalvaro 31:5f039cbddee8 485 loopSpringArray[i].springiness = interSpringK;//*(i%5==0? .6 : 1);//0.4;//4f;
mbedalvaro 31:5f039cbddee8 486 loopSpringArray[i].massA = & (massesLoop[i ]);
mbedalvaro 31:5f039cbddee8 487 loopSpringArray[i].massB = & (massesLoop[(i+1) % numMasses]);
mbedalvaro 31:5f039cbddee8 488 }
mbedalvaro 31:5f039cbddee8 489
mbedalvaro 31:5f039cbddee8 490 // Central (anchor mass):
mbedalvaro 31:5f039cbddee8 491 anchorMass.setIntegrationStep(0.3); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed.
mbedalvaro 31:5f039cbddee8 492 anchorMass.setInitialCondition(startCenter, startSpeed);
mbedalvaro 31:5f039cbddee8 493 anchorMass.mass=massAnchor;
mbedalvaro 31:5f039cbddee8 494 anchorMass.dampMotion = dampMotionAnchorMass;
mbedalvaro 31:5f039cbddee8 495
mbedalvaro 31:5f039cbddee8 496
mbedalvaro 31:5f039cbddee8 497 // Initial conditions for central springs:
mbedalvaro 31:5f039cbddee8 498 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 499 centralSpringArray[i].distance =centralSpringRelax;// + 60* cos ( (1.0*i / numMasses) * 7* 2 * PI);
mbedalvaro 31:5f039cbddee8 500 centralSpringArray[i].springiness =centralSpringK;// 0.4f;
mbedalvaro 31:5f039cbddee8 501 centralSpringArray[i].massA = & (anchorMass);
mbedalvaro 31:5f039cbddee8 502 centralSpringArray[i].massB = & (massesLoop[i]);
mbedalvaro 31:5f039cbddee8 503 }
mbedalvaro 31:5f039cbddee8 504 }
mbedalvaro 31:5f039cbddee8 505
mbedalvaro 31:5f039cbddee8 506
mbedalvaro 31:5f039cbddee8 507 void elasticLoop::setRegionMotion(float mmix, float mmiy, float mmax, float mmay) { // Attention: the initial position should be INSIDE this...
mbedalvaro 31:5f039cbddee8 508 /*
mbedalvaro 31:5f039cbddee8 509 for (int i = 0; i<numMasses; i++) {
mbedalvaro 31:5f039cbddee8 510 massesLoop[i].setWallLimits(mmix, mmiy, mmax, mmay);
mbedalvaro 31:5f039cbddee8 511 }
mbedalvaro 31:5f039cbddee8 512 anchorMass.setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 513 */
mbedalvaro 31:5f039cbddee8 514
mbedalvaro 31:5f039cbddee8 515 // Use the static method of the class pointMass:
mbedalvaro 31:5f039cbddee8 516 // pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 517 pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10);
mbedalvaro 31:5f039cbddee8 518 }
mbedalvaro 31:5f039cbddee8 519
mbedalvaro 31:5f039cbddee8 520 void elasticLoop::update(vector2Df referencePos) {
mbedalvaro 31:5f039cbddee8 521
mbedalvaro 31:5f039cbddee8 522 // (I) Process loop geometry (compute "hair vectors", area and first order moment):
mbedalvaro 31:5f039cbddee8 523 processLoopData();
mbedalvaro 31:5f039cbddee8 524
mbedalvaro 31:5f039cbddee8 525 // (II) Process sensing buffer and compute light forces
mbedalvaro 44:46e25fa1669b 526 // displaySensingBuffer.processSensedData();
mbedalvaro 31:5f039cbddee8 527
mbedalvaro 31:5f039cbddee8 528 // (III) Reset all forces:
mbedalvaro 31:5f039cbddee8 529 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 530 massesLoop[i].resetForce();
mbedalvaro 31:5f039cbddee8 531 }
mbedalvaro 31:5f039cbddee8 532 anchorMass.resetForce();
mbedalvaro 31:5f039cbddee8 533
mbedalvaro 31:5f039cbddee8 534 // (IV) COMPUTE FORCES (motion is not update yet):
mbedalvaro 31:5f039cbddee8 535 //== (1) Compute each particle light force as well as total light force (this will be stored separatedly from the final total particle force to send to OSC):
mbedalvaro 31:5f039cbddee8 536 totalLightForce.set(0,0);
mbedalvaro 31:5f039cbddee8 537 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 538 // NOTE: to save memory, we can drop hairVector...
mbedalvaro 31:5f039cbddee8 539 lightForce[i]=hairVector[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone;
mbedalvaro 44:46e25fa1669b 540 lightForce[i].rotateDeg(angleCorrectionForceLoop); // correction by hand (interactive)
mbedalvaro 31:5f039cbddee8 541 // lightForce[i]=lightForce[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone;
mbedalvaro 31:5f039cbddee8 542 //compute total light force, not only on lighted zones, because it will mean AWAY from black zones:
mbedalvaro 31:5f039cbddee8 543 totalLightForce+=lightForce[i]; // note: bad value choice (negative means TOUCH, and equal to -1), TO CHANGE this in future implementations
mbedalvaro 31:5f039cbddee8 544 }
mbedalvaro 44:46e25fa1669b 545 recenteringVectorLoop=totalLightForce;//.getRotated(angleCorrectionForceLoop);
mbedalvaro 44:46e25fa1669b 546 //== (2) Compute the "recentering vector" from the total light force:
mbedalvaro 31:5f039cbddee8 547 // Compute redundant quantities:
mbedalvaro 31:5f039cbddee8 548 normRecenteringVector=recenteringVectorLoop.length();
mbedalvaro 31:5f039cbddee8 549 angleRecenteringVector=recenteringVectorLoop.angleDegHoriz();
mbedalvaro 31:5f039cbddee8 550 recenteringVectorNucleus=totalLightForce.getRotatedDeg(angleCorrectionForceNucleus);
mbedalvaro 31:5f039cbddee8 551 //== (3) Compute forces on the loop:
mbedalvaro 31:5f039cbddee8 552 //----(a) Nearest neighbour inter-particle springs on the loop (always? we can have still another mode, following the center mass only, etc...)
mbedalvaro 31:5f039cbddee8 553 if (springForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 554 for (int i = 0; i < numMasses; i++) { // if putting -1, the loop is broken
mbedalvaro 31:5f039cbddee8 555 loopSpringArray[i].update();// this add forces to the particles
mbedalvaro 31:5f039cbddee8 556 }
mbedalvaro 31:5f039cbddee8 557 }
mbedalvaro 31:5f039cbddee8 558 //----(b) Direct forces from light pressure (COULD BE MERGED WITH FORCE RECENTERING!!)
mbedalvaro 31:5f039cbddee8 559 if (pseudopodesMode) {
mbedalvaro 44:46e25fa1669b 560 // special "patches" on blob membrane, to "ATTACH" like a zip to the black drawing:
mbedalvaro 31:5f039cbddee8 561 if (lightForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 562 int sign=1;
mbedalvaro 31:5f039cbddee8 563 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 564 if ((i%2)==0) sign*=-1;
mbedalvaro 44:46e25fa1669b 565 //sign=5*cos(6*2*PI*1.0*i/(numMasses-1))-2;
mbedalvaro 31:5f039cbddee8 566 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) // this means touching something black: make SOME points attracted by it (pseudopodes!!) - but not all!
mbedalvaro 44:46e25fa1669b 567 massesLoop[i].addForce(lightForce[i]*(sign<0? -1.24 : 1.4)); // sign<0 means this is a pseudopode attracted by dark zones
mbedalvaro 31:5f039cbddee8 568 else // this means something white: do nothing, all forces are towards the exterior
mbedalvaro 46:90516893793a 569 massesLoop[i].addForce(lightForce[i]*2.3); // this force tends to make the blob "inflate", but is not "directional"
mbedalvaro 31:5f039cbddee8 570 }
mbedalvaro 31:5f039cbddee8 571 }
mbedalvaro 44:46e25fa1669b 572 //----(c) Forces from the recentering vector on each particle (WITH PATCHES on the loop?): THIS IS RESPONSIBLE FOR THE "FOLLOWING" BEHAVIOUR
mbedalvaro 31:5f039cbddee8 573 if (recenteringForceOnLoop) {
mbedalvaro 31:5f039cbddee8 574
mbedalvaro 44:46e25fa1669b 575 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-145) : recenteringVectorLoop.getRotatedDeg(145))*factorRecenteringLoopMass*1;
mbedalvaro 40:ee217eff826c 576 //vector2Df auxForce2= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5;
mbedalvaro 40:ee217eff826c 577 //vector2Df auxForce3= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5;
mbedalvaro 44:46e25fa1669b 578 vector2Df auxForce2= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-50) : recenteringVectorLoop.getRotatedDeg(50))*factorRecenteringLoopMass*0.5;//*1.8;
mbedalvaro 44:46e25fa1669b 579 vector2Df auxForce3= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-30) : recenteringVectorLoop.getRotatedDeg(30))*factorRecenteringLoopMass*0.6;//1.2;
mbedalvaro 44:46e25fa1669b 580
mbedalvaro 40:ee217eff826c 581
mbedalvaro 31:5f039cbddee8 582 int sign=1;
mbedalvaro 31:5f039cbddee8 583 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 584 if ((i%2)==0) sign*=-1;
mbedalvaro 31:5f039cbddee8 585 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) {// this means touching something black: behaviour may depend on the pseudopode presence:
mbedalvaro 44:46e25fa1669b 586 massesLoop[i].addForce((sign<0? auxForce2 : auxForce3)); // auxForce3: nothing, or sign, or corrected angle
mbedalvaro 44:46e25fa1669b 587 }
mbedalvaro 44:46e25fa1669b 588 else massesLoop[i].addForce(auxForce); // this force is responsible for the behaviour (contour following or not)
mbedalvaro 31:5f039cbddee8 589 }
mbedalvaro 31:5f039cbddee8 590 }
mbedalvaro 31:5f039cbddee8 591 } else { // no special zones in the "cell membrane":
mbedalvaro 31:5f039cbddee8 592 if (lightForcesOnLoop) {
mbedalvaro 31:5f039cbddee8 593 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 594 massesLoop[i].addForce(lightForce[i]);
mbedalvaro 31:5f039cbddee8 595 }
mbedalvaro 31:5f039cbddee8 596 }
mbedalvaro 31:5f039cbddee8 597 //----(c') Forces from the recentering vector on each particle:
mbedalvaro 31:5f039cbddee8 598 if (recenteringForceOnLoop) {
mbedalvaro 44:46e25fa1669b 599 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-90) : recenteringVectorLoop.getRotatedDeg(90))*factorRecenteringLoopMass;
mbedalvaro 31:5f039cbddee8 600 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce(auxForce);
mbedalvaro 31:5f039cbddee8 601 }
mbedalvaro 31:5f039cbddee8 602 }
mbedalvaro 31:5f039cbddee8 603
mbedalvaro 31:5f039cbddee8 604 //----(d) Forces from the anchorMass (depending on how we set the equilibrium position for each central spring, we can have a nice blob shape at equilibrium... like a gear for instance)
mbedalvaro 31:5f039cbddee8 605 if (nuclearForceOnLoop) {
mbedalvaro 31:5f039cbddee8 606 // Springs:
mbedalvaro 31:5f039cbddee8 607 for (int i = 0; i < numMasses; i++) centralSpringArray[i].update();//assymetricUpdate();
mbedalvaro 31:5f039cbddee8 608 // note: if using centralSpringArray[i].update(), we will add forces to the particles AND to the anchor mass...
mbedalvaro 31:5f039cbddee8 609 // Inverse square (attractive):
mbedalvaro 31:5f039cbddee8 610 //for (int i = 0; i < numMasses; i++) massesLoop[i].addInterInvSquareForce(anchorMass, 10, 300, centralSpringK);
mbedalvaro 31:5f039cbddee8 611 }
mbedalvaro 31:5f039cbddee8 612 //----(d) Inter loop-particles forces (Zach-Liebermann-like blob):
mbedalvaro 31:5f039cbddee8 613 if (interParticleForceOnLoop) {
mbedalvaro 31:5f039cbddee8 614 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 615 for (int j = 0; j < i-1; j++) massesLoop[i].addInterSpringForce(massesLoop[j], interParticleRange, factorInterParticleForce);
mbedalvaro 31:5f039cbddee8 616 }
mbedalvaro 31:5f039cbddee8 617 }
mbedalvaro 31:5f039cbddee8 618 //----(e) Internal blob pressure force (my faster method to have a blob-like behaviour):
mbedalvaro 31:5f039cbddee8 619 if (forceInternalPressureOnLoop) {
mbedalvaro 31:5f039cbddee8 620 // NOTE on the Physics of the thing: the force on the membrane of a ballon is proportional to the DIFFERENCE of pressures (outside and inside):
mbedalvaro 31:5f039cbddee8 621 // so: f= factor/area - cte, with cte=factor/area0, with area0 being the area at equilibrium.
mbedalvaro 31:5f039cbddee8 622 // (And of course, to make it even more exact, we should do pressure*surface, but this will be considered constant)
mbedalvaro 31:5f039cbddee8 623 // float area0=30000; // area in pixels when at equilibrium
mbedalvaro 31:5f039cbddee8 624 //float factorPressureLoopMass=-0.1*(1.0/area-1.0/area0);
mbedalvaro 31:5f039cbddee8 625 //float factorPressureLoopMass=500000.0*(1.0/(area*area)-1.0/(area0*area0));
mbedalvaro 31:5f039cbddee8 626 //float factorPressureLoopMass=20000.0*(1.0/sqrt(area)-1.0/sqrt(area0));
mbedalvaro 31:5f039cbddee8 627 // Constant force seems to work well too... but produces an annoying blob reversal (probably solved by using negative light forces instead of internal blob pressure):
mbedalvaro 31:5f039cbddee8 628 //float factorPressureLoopMass=2.5;//4.8;
mbedalvaro 31:5f039cbddee8 629 // Now, add the pressure force proportional to the inverse of the area to all particles, or just a signed constant:
mbedalvaro 31:5f039cbddee8 630 int auxsign=(area>=0? -1: 1);
mbedalvaro 31:5f039cbddee8 631 auxsign=-1;
mbedalvaro 31:5f039cbddee8 632 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce( hairVector[i] * factorPressureLoopMass* auxsign);
mbedalvaro 31:5f039cbddee8 633 }
mbedalvaro 31:5f039cbddee8 634 //----(f) force from border:
mbedalvaro 31:5f039cbddee8 635 if (forceBorderOnLoop) {
mbedalvaro 31:5f039cbddee8 636 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 637 if (massesLoop[i].bWallCollision) massesLoop[i].addForce(massesLoop[i].innerCollitionDirection*factorForceBorder);
mbedalvaro 31:5f039cbddee8 638 }
mbedalvaro 31:5f039cbddee8 639 }
mbedalvaro 31:5f039cbddee8 640
mbedalvaro 31:5f039cbddee8 641 //== (4) Compute forces on the anchor mass:
mbedalvaro 31:5f039cbddee8 642 //----(a) Force from data send by OSC? (ex: from mouse?)
mbedalvaro 31:5f039cbddee8 643 // anchorMass.addSpringForce(mx, my, 500, -10.2f);
mbedalvaro 31:5f039cbddee8 644 // or direct control:
mbedalvaro 31:5f039cbddee8 645 // anchorMass.pos.x=mx;anchorMass.pos.y=my;
mbedalvaro 31:5f039cbddee8 646 //----(b) Force from the total light force (aka, the "recentering vector"!):
mbedalvaro 31:5f039cbddee8 647 if (recenteringForceOnNucleus) {
mbedalvaro 31:5f039cbddee8 648 anchorMass.addForce(recenteringVectorNucleus*factorRecenteringAnchorMass);
mbedalvaro 31:5f039cbddee8 649 }
mbedalvaro 31:5f039cbddee8 650
mbedalvaro 31:5f039cbddee8 651 // when nothing is touching it for a while:
mbedalvaro 31:5f039cbddee8 652 if (searchActive) {
mbedalvaro 31:5f039cbddee8 653 if (!displaySensingBuffer.lightTouched) {
mbedalvaro 31:5f039cbddee8 654 if (firstTimeNoTouch) {
mbedalvaro 31:5f039cbddee8 655 firstTimeNoTouch=false;
mbedalvaro 31:5f039cbddee8 656 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 657 randomForce.set(2000-cx,2000-cy);
mbedalvaro 31:5f039cbddee8 658 randomForce.normalize();
mbedalvaro 31:5f039cbddee8 659 randomForce= randomForce.getRotatedDeg(rand()%50-25);
mbedalvaro 31:5f039cbddee8 660 }
mbedalvaro 31:5f039cbddee8 661 if (noTouchedCounter>0) {
mbedalvaro 31:5f039cbddee8 662 // add random force, modulated:
mbedalvaro 31:5f039cbddee8 663 float aux=1.0*noTouchedCounter/1150;
mbedalvaro 31:5f039cbddee8 664 vector2Df randf=randomForce.getRotatedDeg(40.0*sin(aux*2*PI*2))*20.0;//*(1.0-aux)*0.3;
mbedalvaro 44:46e25fa1669b 665 for (int i = 0; i < 1; i=i+1) { // only on some of the particles (or only one...), and better if these are in the "black attractive" patch!
mbedalvaro 31:5f039cbddee8 666 massesLoop[i].addForce(randf);
mbedalvaro 31:5f039cbddee8 667 }
mbedalvaro 31:5f039cbddee8 668 // and a special point?
mbedalvaro 31:5f039cbddee8 669 //massesLoop[numMasses/2].addForce(randf);
mbedalvaro 31:5f039cbddee8 670 // plus amoeba effect ?
mbedalvaro 31:5f039cbddee8 671 // for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 672 // massesLoop[i].addForce(hairVector[i]*18*cos( (0.0*noTouchedCounter/1000 + 1.0*i/(numMasses-1)*2*PI*3)));
mbedalvaro 31:5f039cbddee8 673 //}
mbedalvaro 31:5f039cbddee8 674
mbedalvaro 31:5f039cbddee8 675 if ((noTouchedCounter>1150)||(blobWallCollision)) {
mbedalvaro 31:5f039cbddee8 676 noTouchedCounter=0;
mbedalvaro 31:5f039cbddee8 677 // compute force towards the center, slightly rotated to make the blob wander about:
mbedalvaro 31:5f039cbddee8 678 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 679 randomForce.set(2000-cx,2000-cy);
mbedalvaro 31:5f039cbddee8 680 randomForce.normalize();
mbedalvaro 31:5f039cbddee8 681 randomForce= randomForce.getRotatedDeg(rand()%50-25);
mbedalvaro 31:5f039cbddee8 682 }
mbedalvaro 31:5f039cbddee8 683 }
mbedalvaro 31:5f039cbddee8 684 } else {
mbedalvaro 31:5f039cbddee8 685 firstTimeNoTouch=true;
mbedalvaro 31:5f039cbddee8 686 noTouchedCounter=0;
mbedalvaro 31:5f039cbddee8 687 }
mbedalvaro 31:5f039cbddee8 688 noTouchedCounter++;
mbedalvaro 31:5f039cbddee8 689 }
mbedalvaro 31:5f039cbddee8 690
mbedalvaro 31:5f039cbddee8 691 // (V) UPDATE DYNAMICS
mbedalvaro 31:5f039cbddee8 692 //== (1) particules on the loop:
mbedalvaro 31:5f039cbddee8 693 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 694 #ifndef VERLET_METHOD
mbedalvaro 31:5f039cbddee8 695 massesLoop[i].addDampingForce(); // only in case of EULER method (damping in VERLET mode is done automatically when updating)
mbedalvaro 31:5f039cbddee8 696 #endif
mbedalvaro 31:5f039cbddee8 697 massesLoop[i].update(); // unconstrained
mbedalvaro 31:5f039cbddee8 698 massesLoop[i].bounceOffWalls(); // constrain position (and compute wall "hit")
mbedalvaro 31:5f039cbddee8 699 }
mbedalvaro 31:5f039cbddee8 700 //== (2) For the anchorMass:
mbedalvaro 31:5f039cbddee8 701 #ifndef VERLET_METHOD
mbedalvaro 31:5f039cbddee8 702 anchorMass.addDampingForce(); // // only in case of EULER method (damping in VERLET mode is done automatically when updating)
mbedalvaro 31:5f039cbddee8 703 #endif
mbedalvaro 31:5f039cbddee8 704 anchorMass.update(); // unconstrained
mbedalvaro 31:5f039cbddee8 705 anchorMass.bounceOffWalls(); // constrain position (and compute wall "hit")
mbedalvaro 31:5f039cbddee8 706
mbedalvaro 31:5f039cbddee8 707 // OTHER PARTICULAR THINGS:
mbedalvaro 31:5f039cbddee8 708 // (1) current color: change with touch? NO
mbedalvaro 31:5f039cbddee8 709 // if (displaySensingBuffer.lightTouched)
mbedalvaro 31:5f039cbddee8 710 // transientBlobColor=blobColor|0x02; // set green ON on the trajectory, regardless of the initial color
mbedalvaro 31:5f039cbddee8 711 // else
mbedalvaro 31:5f039cbddee8 712 transientBlobColor=blobColor; // just the original blob color
mbedalvaro 31:5f039cbddee8 713
mbedalvaro 31:5f039cbddee8 714 // change sliding direction (for countour following):
mbedalvaro 31:5f039cbddee8 715 if (blobWallCollision) {
mbedalvaro 31:5f039cbddee8 716 if (wallCounter>10) {
mbedalvaro 31:5f039cbddee8 717 slidingDirection=!slidingDirection;
mbedalvaro 31:5f039cbddee8 718 wallCounter=0;
mbedalvaro 31:5f039cbddee8 719 }
mbedalvaro 31:5f039cbddee8 720 }
mbedalvaro 31:5f039cbddee8 721 wallCounter++;
mbedalvaro 31:5f039cbddee8 722 }
mbedalvaro 31:5f039cbddee8 723
mbedalvaro 31:5f039cbddee8 724 // Drawing the graphics - this will in fact use the graphic renderer - if any - and produce the trajectory to be displayed by the laser
mbedalvaro 31:5f039cbddee8 725 void elasticLoop::draw() {
mbedalvaro 31:5f039cbddee8 726 // for the time being, there is no "opengl" like renderer, so we just copy the coordinates of the mass into the lsdTrajectory:
mbedalvaro 31:5f039cbddee8 727 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 728 displaySensingBuffer.lsdTrajectory[i].x= (unsigned short)( massesLoop[i].pos.x ); // note: it should be an unsigned short
mbedalvaro 31:5f039cbddee8 729 displaySensingBuffer.lsdTrajectory[i].y= (unsigned short)( massesLoop[i].pos.y );
mbedalvaro 31:5f039cbddee8 730
mbedalvaro 31:5f039cbddee8 731 //displaySensingBuffer.lsdTrajectory[i]= massesLoop[i].pos.y; // NOTE: doing this means converting from unsigned short to float (vector2Dd to vector2Df)
mbedalvaro 31:5f039cbddee8 732
mbedalvaro 31:5f039cbddee8 733 //displaySensingBuffer.lsdTrajectory[i].color=blobColor; // perhaps per point color is not a good idea for the time being...
mbedalvaro 31:5f039cbddee8 734 }
mbedalvaro 31:5f039cbddee8 735
mbedalvaro 31:5f039cbddee8 736 // Global color for the whole loop:
mbedalvaro 31:5f039cbddee8 737 displaySensingBuffer.displayColor=transientBlobColor;
mbedalvaro 31:5f039cbddee8 738 }
mbedalvaro 31:5f039cbddee8 739
mbedalvaro 31:5f039cbddee8 740 void elasticLoop::processLoopData() {
mbedalvaro 31:5f039cbddee8 741
mbedalvaro 31:5f039cbddee8 742 // (0) Check if the blob touched the borders:
mbedalvaro 31:5f039cbddee8 743 blobWallCollision=false;
mbedalvaro 31:5f039cbddee8 744 for (int i = 0; i < numMasses; i++) blobWallCollision= (blobWallCollision || massesLoop[i].bWallCollision);
mbedalvaro 31:5f039cbddee8 745
mbedalvaro 31:5f039cbddee8 746 // (1) Compute all the "hairvectors" for the loop (this is, the normals to the particles, pointing outwards).
mbedalvaro 31:5f039cbddee8 747 // This will be approximated by taking the 90 deg rotated difference between contiguous particles positions.
mbedalvaro 31:5f039cbddee8 748 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 749 vector2Df diff;
mbedalvaro 31:5f039cbddee8 750 diff.set(massesLoop[(i+1)%numMasses].pos-massesLoop[i].pos);
mbedalvaro 31:5f039cbddee8 751 // normalize and rotate 90 deg:
mbedalvaro 31:5f039cbddee8 752 // NOTE: to save memory, we can drop hairVector...
mbedalvaro 31:5f039cbddee8 753 hairVector[i]=diff.getPerpendicularNormed(CW);
mbedalvaro 31:5f039cbddee8 754 //lightForce[i]=diff.getPerpendicularNormed(CW);
mbedalvaro 31:5f039cbddee8 755 }
mbedalvaro 31:5f039cbddee8 756
mbedalvaro 31:5f039cbddee8 757 // (2) Compute area:
mbedalvaro 31:5f039cbddee8 758 // (a) using Green method:
mbedalvaro 31:5f039cbddee8 759 area=0;
mbedalvaro 31:5f039cbddee8 760 float dx;
mbedalvaro 31:5f039cbddee8 761 for (int i = 0; i < numMasses-1; i++){
mbedalvaro 31:5f039cbddee8 762 dx=massesLoop[i].pos.x-massesLoop[i+1].pos.x;
mbedalvaro 31:5f039cbddee8 763 area+=dx*massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 764 }
mbedalvaro 31:5f039cbddee8 765 // to avoid computation problems:
mbedalvaro 31:5f039cbddee8 766 // if (area<=0) area=1; // or just norm: area CAN be negative! (a loop that is larger than the original blob...)
mbedalvaro 31:5f039cbddee8 767
mbedalvaro 31:5f039cbddee8 768 // (b) Compute approximate area from enclosing rectangle:
mbedalvaro 31:5f039cbddee8 769 computeBoundingBox();
mbedalvaro 31:5f039cbddee8 770
mbedalvaro 31:5f039cbddee8 771 // (c) Compute kinetic energy:
mbedalvaro 31:5f039cbddee8 772 totalKineticEnergy=0;
mbedalvaro 31:5f039cbddee8 773 for (int i = 0; i < numMasses; i++){
mbedalvaro 31:5f039cbddee8 774 totalKineticEnergy+=massesLoop[i].getSpeed().squareLength();
mbedalvaro 31:5f039cbddee8 775 }
mbedalvaro 31:5f039cbddee8 776 }
mbedalvaro 31:5f039cbddee8 777
mbedalvaro 31:5f039cbddee8 778
mbedalvaro 31:5f039cbddee8 779 void elasticLoop::computeBoundingBox() {
mbedalvaro 31:5f039cbddee8 780 float minx=4096, maxx=-1, miny=4096, maxy=-1;
mbedalvaro 31:5f039cbddee8 781 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 782 if (i == 0) {
mbedalvaro 31:5f039cbddee8 783 minx = massesLoop[i].pos.x;
mbedalvaro 31:5f039cbddee8 784 maxx = massesLoop[i].pos.x;
mbedalvaro 31:5f039cbddee8 785 miny = massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 786 maxy = massesLoop[i].pos.y;
mbedalvaro 31:5f039cbddee8 787 } else {
mbedalvaro 31:5f039cbddee8 788
mbedalvaro 31:5f039cbddee8 789 minx = min(minx, massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 790 maxx = max(maxx, massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 791 miny = min(miny, massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 792 maxy = max(maxy, massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 793 }
mbedalvaro 31:5f039cbddee8 794 }
mbedalvaro 31:5f039cbddee8 795
mbedalvaro 31:5f039cbddee8 796 // final results:
mbedalvaro 31:5f039cbddee8 797 w = maxx - minx;
mbedalvaro 31:5f039cbddee8 798 h = maxy - miny;
mbedalvaro 31:5f039cbddee8 799 cx = minx+0.5*w; // note: center will be initialized with posX and posY when calling setInitialPos() of blobConfig
mbedalvaro 31:5f039cbddee8 800 cy = miny+0.5*h;
mbedalvaro 31:5f039cbddee8 801
mbedalvaro 31:5f039cbddee8 802 // approx area:
mbedalvaro 31:5f039cbddee8 803 approxArea=w*h;
mbedalvaro 31:5f039cbddee8 804 }
mbedalvaro 31:5f039cbddee8 805
mbedalvaro 31:5f039cbddee8 806 void elasticLoop::sendDataSpecific() {
mbedalvaro 31:5f039cbddee8 807 char auxstring[10];
mbedalvaro 31:5f039cbddee8 808 myled2=1; // for tests...
mbedalvaro 31:5f039cbddee8 809
mbedalvaro 31:5f039cbddee8 810 // First, set the top address of the message to the ID of the blob (not the name):
mbedalvaro 31:5f039cbddee8 811 // sprintf(auxstring, "%d", identifier);
mbedalvaro 31:5f039cbddee8 812 // sendMes.setTopAddress("0");//auxstring);
mbedalvaro 31:5f039cbddee8 813
mbedalvaro 31:5f039cbddee8 814 // ===================== OSC ======================
mbedalvaro 31:5f039cbddee8 815 if (sendOSC) {
mbedalvaro 31:5f039cbddee8 816
mbedalvaro 31:5f039cbddee8 817 // (new) Total kinetic energy:
mbedalvaro 31:5f039cbddee8 818 if (sendingKineticEnergy) {
mbedalvaro 31:5f039cbddee8 819 sprintf(auxstring, "/k %d",identifier);
mbedalvaro 31:5f039cbddee8 820 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 821 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 822 x=(long)(totalKineticEnergy);
mbedalvaro 31:5f039cbddee8 823 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 824 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 825 }
mbedalvaro 31:5f039cbddee8 826 // (a) Anchor mass:
mbedalvaro 31:5f039cbddee8 827 if (sendingAnchorPosition) {
mbedalvaro 31:5f039cbddee8 828 sprintf(auxstring, "/p %d",identifier);
mbedalvaro 31:5f039cbddee8 829 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 830 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 831 x=(long)(anchorMass.pos.x);
mbedalvaro 31:5f039cbddee8 832 y=(long)(anchorMass.pos.y);
mbedalvaro 31:5f039cbddee8 833 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 834 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 835 }
mbedalvaro 31:5f039cbddee8 836 if (sendingAnchorForce) {
mbedalvaro 31:5f039cbddee8 837 sendMes.setSubAddress("/aforce");
mbedalvaro 31:5f039cbddee8 838 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 839 x=(long)(anchorMass.totalForce.x);
mbedalvaro 31:5f039cbddee8 840 y=(long)(anchorMass.totalForce.y);
mbedalvaro 31:5f039cbddee8 841 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 842 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 843 }
mbedalvaro 31:5f039cbddee8 844 if (sendingAnchorTouchWall) {// note: not an else (we can send different data simultaneously)
mbedalvaro 31:5f039cbddee8 845 sendMes.setSubAddress("/awall");
mbedalvaro 31:5f039cbddee8 846 long wall=(long)(anchorMass.bWallCollision? 1 : 0);
mbedalvaro 31:5f039cbddee8 847 sendMes.setArgs( "i", &wall);
mbedalvaro 31:5f039cbddee8 848 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 849 }
mbedalvaro 31:5f039cbddee8 850 // (b) data from blob points:
mbedalvaro 31:5f039cbddee8 851 if (sendingLoopPositions) {
mbedalvaro 31:5f039cbddee8 852 #ifdef SEND_AS_POINTS
mbedalvaro 31:5f039cbddee8 853 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 854 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 855 sprintf(auxstring, "/p %d", i); // auxstring read as "/p1", "/p2", ...
mbedalvaro 31:5f039cbddee8 856 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 857 x=(long)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 858 y=(long)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 859 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 860 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 861 }
mbedalvaro 31:5f039cbddee8 862 #endif
mbedalvaro 31:5f039cbddee8 863 #ifdef SEND_AS_BLOB
mbedalvaro 31:5f039cbddee8 864 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()...
mbedalvaro 31:5f039cbddee8 865 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates
mbedalvaro 31:5f039cbddee8 866 for (int i = 0; i < numMasses; i++ ) {
mbedalvaro 31:5f039cbddee8 867 // note: massesLoop[i].pos.x is a "float"
mbedalvaro 31:5f039cbddee8 868 uint16_t x=(uint16_t)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 869 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 870 blobdata[4*i+1]=(uint8_t)x;
mbedalvaro 31:5f039cbddee8 871
mbedalvaro 31:5f039cbddee8 872 uint16_t y=(uint16_t)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 873 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 874 blobdata[4*i+3]=(uint8_t)y;
mbedalvaro 31:5f039cbddee8 875 }
mbedalvaro 31:5f039cbddee8 876 osc.sendOscBlob(&(blobdata[0]), 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes
mbedalvaro 31:5f039cbddee8 877 #endif
mbedalvaro 31:5f039cbddee8 878 #ifdef SEND_AS_STRING
mbedalvaro 31:5f039cbddee8 879 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()...
mbedalvaro 31:5f039cbddee8 880 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates
mbedalvaro 31:5f039cbddee8 881 for (int i = 0; i < numMasses; i++ ) {
mbedalvaro 31:5f039cbddee8 882 // note: massesLoop[i].pos.x is a "float"
mbedalvaro 31:5f039cbddee8 883 uint16_t x=(uint16_t)(massesLoop[i].pos.x);
mbedalvaro 31:5f039cbddee8 884 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 885 blobdata[4*i+1]=(uint8_t)x;
mbedalvaro 31:5f039cbddee8 886
mbedalvaro 31:5f039cbddee8 887 uint16_t y=(uint16_t)(massesLoop[i].pos.y);
mbedalvaro 31:5f039cbddee8 888 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE)
mbedalvaro 31:5f039cbddee8 889 blobdata[4*i+3]=(uint8_t)y;
mbedalvaro 31:5f039cbddee8 890 }
mbedalvaro 31:5f039cbddee8 891 osc.sendOscString(blobdata, 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes
mbedalvaro 31:5f039cbddee8 892 #endif
mbedalvaro 31:5f039cbddee8 893 }
mbedalvaro 31:5f039cbddee8 894 if (sendingLoopForces) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...)
mbedalvaro 31:5f039cbddee8 895 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 896 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 897 sprintf(auxstring, "/f%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 898 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 899 x=(long)(massesLoop[i].totalForce.x);
mbedalvaro 31:5f039cbddee8 900 y=(long)(massesLoop[i].totalForce.y);
mbedalvaro 31:5f039cbddee8 901 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 902 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 903 }
mbedalvaro 31:5f039cbddee8 904 }
mbedalvaro 31:5f039cbddee8 905 if (sendingLoopForcesLight) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...)
mbedalvaro 31:5f039cbddee8 906 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 907 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 908 sprintf(auxstring, "/g%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 909 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 910 x=(long)(1000*lightForce[i].x);
mbedalvaro 31:5f039cbddee8 911 y=(long)(1000*lightForce[i].y);
mbedalvaro 31:5f039cbddee8 912 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 913 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 914 }
mbedalvaro 31:5f039cbddee8 915 }
mbedalvaro 31:5f039cbddee8 916
mbedalvaro 31:5f039cbddee8 917 if (sendingLoopRegions) {
mbedalvaro 31:5f039cbddee8 918 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 919 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 920 sprintf(auxstring, "/r%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 921 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 922 x=(long)(displaySensingBuffer.lsdTrajectory[i].lightZone>0? 1 : 0);
mbedalvaro 31:5f039cbddee8 923 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 924 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 925 }
mbedalvaro 31:5f039cbddee8 926 }
mbedalvaro 31:5f039cbddee8 927 if (sendingLoopTouchWall) { // global touch wall for the loop (not per point)
mbedalvaro 31:5f039cbddee8 928 long wall; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 929 sprintf(auxstring, "/bWall");
mbedalvaro 31:5f039cbddee8 930 sendMes.setSubAddress(auxstring);
mbedalvaro 31:5f039cbddee8 931 wall=(long)(blobWallCollision? 1 : 0);
mbedalvaro 31:5f039cbddee8 932 sendMes.setArgs( "i", &wall);
mbedalvaro 31:5f039cbddee8 933 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 934 }
mbedalvaro 31:5f039cbddee8 935 // (c) Blob geometry:
mbedalvaro 31:5f039cbddee8 936 if (sendingBlobArea) {
mbedalvaro 31:5f039cbddee8 937 /* sendMes.setSubAddress("/a");
mbedalvaro 31:5f039cbddee8 938 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 939 // x=(long)(area);//approxArea); // area or approxArea
mbedalvaro 31:5f039cbddee8 940 x=(long)(area>0? approxArea : -approxArea);
mbedalvaro 31:5f039cbddee8 941 sendMes.setArgs( "i", &x); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!)
mbedalvaro 31:5f039cbddee8 942 */
mbedalvaro 31:5f039cbddee8 943 // HACK for the time being (for Daito):
mbedalvaro 31:5f039cbddee8 944 sendMes.setSubAddress("/a");
mbedalvaro 31:5f039cbddee8 945 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 946 // x=(long)(area);//approxArea); // area or approxArea
mbedalvaro 31:5f039cbddee8 947 x=(long)(w); y=(long)(h);
mbedalvaro 31:5f039cbddee8 948 sendMes.setArgs( "ii", &x, &y); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!)
mbedalvaro 31:5f039cbddee8 949
mbedalvaro 31:5f039cbddee8 950 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 951 }
mbedalvaro 31:5f039cbddee8 952 if (sendingBlobNormals) {
mbedalvaro 31:5f039cbddee8 953 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 954 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 955 sprintf(auxstring, "nf%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 956 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 957 x=(long)(hairVector[i].x);
mbedalvaro 31:5f039cbddee8 958 y=(long)(hairVector[i].y);
mbedalvaro 31:5f039cbddee8 959 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 960 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 961 }
mbedalvaro 31:5f039cbddee8 962 }
mbedalvaro 31:5f039cbddee8 963 if (sendingBlobAngles) {
mbedalvaro 31:5f039cbddee8 964 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 965 for (int i = 0; i < numMasses; i++) {
mbedalvaro 31:5f039cbddee8 966 sprintf(auxstring, "/a%d", i); // auxstring read as "/f1", "/f2", ...
mbedalvaro 31:5f039cbddee8 967 sendMes.setSubAddress(auxstring); // ATTENTION: the host computer needs to know in advance how many points are in the loop (I did not implement "bundle" messages yet...)
mbedalvaro 31:5f039cbddee8 968 x=(long)(hairVector[i].angleDegHoriz());
mbedalvaro 31:5f039cbddee8 969 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 970 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 971 }
mbedalvaro 31:5f039cbddee8 972 }
mbedalvaro 31:5f039cbddee8 973 // (d) Light sensing statistics:
mbedalvaro 31:5f039cbddee8 974 if (sendingBlobMaxMin) {
mbedalvaro 31:5f039cbddee8 975 sendMes.setSubAddress("/maxmin");
mbedalvaro 31:5f039cbddee8 976 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 977 x=(long)(displaySensingBuffer.maxI);
mbedalvaro 31:5f039cbddee8 978 y=(long)(displaySensingBuffer.minI);
mbedalvaro 31:5f039cbddee8 979 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 980 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 981 }
mbedalvaro 31:5f039cbddee8 982 if (sendingLightForce) {
mbedalvaro 31:5f039cbddee8 983 sendMes.setSubAddress("/lforce");
mbedalvaro 31:5f039cbddee8 984 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 985 x=(long)(totalLightForce.x);
mbedalvaro 31:5f039cbddee8 986 y=(long)(totalLightForce.y);
mbedalvaro 31:5f039cbddee8 987 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 988 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 989 }
mbedalvaro 31:5f039cbddee8 990 // (e) Recentering vector: (note: redundant with sendingLightForce, IF the correction angle is known).
mbedalvaro 31:5f039cbddee8 991 if (sendingRecenteringVector) {
mbedalvaro 31:5f039cbddee8 992 sendMes.setSubAddress("/rvector");
mbedalvaro 31:5f039cbddee8 993 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 994 x=(long)(recenteringVectorLoop.x);
mbedalvaro 31:5f039cbddee8 995 y=(long)(recenteringVectorLoop.y);
mbedalvaro 31:5f039cbddee8 996 sendMes.setArgs( "ii", &x, &y);
mbedalvaro 31:5f039cbddee8 997 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 998 }
mbedalvaro 31:5f039cbddee8 999 if (sendingRecenteringAngle) {
mbedalvaro 31:5f039cbddee8 1000 sendMes.setSubAddress("/rangle");
mbedalvaro 31:5f039cbddee8 1001 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 1002 x=(long)(angleRecenteringVector);
mbedalvaro 31:5f039cbddee8 1003 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 1004 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1005 }
mbedalvaro 31:5f039cbddee8 1006 if (sendingRecenteringNorm) {
mbedalvaro 31:5f039cbddee8 1007 sendMes.setSubAddress("/rnorm");
mbedalvaro 31:5f039cbddee8 1008 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!)
mbedalvaro 31:5f039cbddee8 1009 x=(long)(normRecenteringVector);
mbedalvaro 31:5f039cbddee8 1010 sendMes.setArgs( "i", &x);
mbedalvaro 31:5f039cbddee8 1011 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1012 }
mbedalvaro 31:5f039cbddee8 1013
mbedalvaro 31:5f039cbddee8 1014 if (sendingTouched) {
mbedalvaro 31:5f039cbddee8 1015 if (displaySensingBuffer.lightTouched) {
mbedalvaro 31:5f039cbddee8 1016 sendMes.clearArgs(); // there are no arguments to send
mbedalvaro 31:5f039cbddee8 1017 sendMes.setSubAddress("/touched");
mbedalvaro 31:5f039cbddee8 1018 osc.sendOsc( &sendMes );
mbedalvaro 31:5f039cbddee8 1019 }
mbedalvaro 31:5f039cbddee8 1020 }
mbedalvaro 31:5f039cbddee8 1021
mbedalvaro 31:5f039cbddee8 1022 } // end of OSC sending per-spot
mbedalvaro 31:5f039cbddee8 1023
mbedalvaro 31:5f039cbddee8 1024 // ===================== SERIAL ======================
mbedalvaro 31:5f039cbddee8 1025 if (sendSerial) {
mbedalvaro 31:5f039cbddee8 1026 //.. to do
mbedalvaro 31:5f039cbddee8 1027 }
mbedalvaro 31:5f039cbddee8 1028
mbedalvaro 31:5f039cbddee8 1029 myled2=0; // for tests...
mbedalvaro 31:5f039cbddee8 1030 }
mbedalvaro 31:5f039cbddee8 1031