Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of scoreLight_Advanced by
elasticLoop.cpp
00001 /* 00002 * elasticLoop.cpp 00003 * laserBlobPure 00004 * 00005 * Created by CASSINELLI ALVARO on 5/20/11. 00006 * Copyright 2011 TOKYO UNIVERSITY. All rights reserved. 00007 * 00008 */ 00009 00010 #include "elasticLoop.h" 00011 00012 // SHOULD NOT BE HERE: (only because I am using AD_MIRRIOR... max and min in the set region function that should not be here) 00013 #include "hardwareIO.h" 00014 00015 elasticLoop::elasticLoop() { 00016 } 00017 00018 elasticLoop::~elasticLoop() { 00019 // no need to do clear, this is done by default when clearing the vector container? 00020 massesLoop.clear(); 00021 loopSpringArray.clear(); 00022 hairVector.clear(); 00023 lightForce.clear(); 00024 centralSpringArray.clear(); 00025 displaySensingBuffer.lsdTrajectory.clear(); 00026 } 00027 00028 void elasticLoop::showChildParameters() { 00029 // pc.printf("Mirror delay :%d\n", displaySensingBuffer.delayMirrorSamples); 00030 // pc.printf("Angle correction force :%d\n", angleCorrectionForceLoop); 00031 pc.printf("Integration Step Loop :%f\n", integrationStepLoop); 00032 pc.printf("Integration Step Anchor :%f\n", integrationStepAnchor); 00033 } 00034 00035 void elasticLoop::createBlob(int _id, ElasticLoopMode _elasticBlobMode, vector2Df _initPos, vector2Df _initSpeed) { 00036 // (1) set ID: 00037 identifier=_id; 00038 00039 startCenter=_initPos; 00040 startSpeed=_initSpeed; 00041 00042 // (2) Initialize common variables of all blobs (base class): 00043 // initCommonVariables(); 00044 00045 // (3) initialize common variables for the elastic blob types: 00046 integrationStepLoop=0.22; 00047 integrationStepAnchor=0.4; 00048 00049 slidingDirection=true; // (will change when touching wall) 00050 // Sending data: 00051 periodSendingData=15; // in ms 00052 sendingLoopPositions=false; 00053 sendingBlobArea=true; 00054 sendingKineticEnergy=true; 00055 sendingBlobMaxMin=true; 00056 // send ALWAYS, regardless of the fact the blob is being touched or not, in case of elastic loops: 00057 sendingOnlyWhenTouch=false; 00058 00059 // (3) Initialize secondary variables depending on the blob type and mode: 00060 00061 // 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 00062 // actually be "condensed" in a mode...) 00063 00064 switch (_elasticBlobMode) { 00065 case RELAX: 00066 00067 // Name of this kind of spot: 00068 sprintf(spotName,"loop_relax"); //this is an relaxing elastic loop 00069 00070 // Color: (use parameter in the future): 00071 //setColor(0x07);//0x04+0x02>>i); 00072 setColor(0x04); 00073 blueTouch=true; 00074 00075 // default (initial) shape (the scafold belongs to the base class): 00076 startRadius=400; 00077 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos, int _numScafoldPoints); 00078 00079 // Numeric parameters for the simulated mechanical system: 00080 massLoopParticle=0.25; 00081 dampMotionMassesLoop=0.025;//0.17; 00082 massAnchor=2.0; 00083 dampMotionAnchorMass=0.001; 00084 // Springs: 00085 centralSpringK=0.3; 00086 centralSpringRelax=startRadius;// use the radius of the scafold 00087 interSpringK=0.46; 00088 interSpringRelax=20; 00089 // for "zack-like" blob: 00090 interParticleRange=100; 00091 factorInterParticleForce=18.0; 00092 00093 searchActive=false; 00094 pseudopodesMode=false; // this is for contour following. 00095 00096 // Active/inactive forces: 00097 springForcesOnLoop=true; 00098 lightForcesOnLoop=true; 00099 forceBorderOnLoop=false; 00100 nuclearForceOnLoop=false;//true; 00101 interParticleForceOnLoop=false; 00102 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00103 00104 // Recentering vector: 00105 angleCorrectionForceLoop=0;// in deg 00106 recenteringForceOnLoop=false; 00107 angleCorrectionForceNucleus=0;// in deg 00108 recenteringForceOnNucleus=false;//true; 00109 00110 factorLightForce=4.0;//3.0;//8.0; 00111 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size(); // use number of points in the scafold 00112 factorRecenteringLoopMass=0.3; 00113 factorPressureLoopMass=1.0; 00114 factorForceBorder=4.5; 00115 00116 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00117 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00118 displaySensingBuffer.setDelayMirrors(2); 00119 00120 break; 00121 00122 case CONTRACT: 00123 00124 sprintf(spotName,"loop_contract"); //this is an relaxing elastic loop 00125 00126 setColor(0x07);//0x04+0x02>>i); 00127 blueTouch=true; 00128 00129 // default (initial) shape: 00130 startRadius =400; 00131 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00132 00133 // Numeric parameters for the simulated mechanical system: 00134 massLoopParticle=0.25; 00135 dampMotionMassesLoop=0.024;//0.17; 00136 massAnchor=2.0; 00137 dampMotionAnchorMass=0.001; 00138 // Springs: 00139 centralSpringK=0.5; 00140 centralSpringRelax=startRadius; 00141 interSpringK=0.4;//46; 00142 interSpringRelax=30; 00143 // for "zack-like" blob: 00144 interParticleRange=100; 00145 factorInterParticleForce=18.0; 00146 00147 searchActive=false; 00148 pseudopodesMode=false; // this is for contour following. 00149 00150 // Active/Inactive Forces: 00151 springForcesOnLoop=true; 00152 lightForcesOnLoop=true; 00153 forceBorderOnLoop=false; 00154 nuclearForceOnLoop=true;//true; 00155 interParticleForceOnLoop=false; 00156 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00157 // Recentering vector: 00158 angleCorrectionForceLoop=0;// in deg 00159 recenteringForceOnLoop=false; 00160 angleCorrectionForceNucleus=0;// in deg 00161 recenteringForceOnNucleus=false;//true; 00162 00163 factorLightForce=6.0;//3.0;//8.0; 00164 factorRecenteringAnchorMass=20.0/bluePrint.scafold.size(); 00165 factorRecenteringLoopMass=0.3; 00166 factorPressureLoopMass=1.0; 00167 factorForceBorder=4.5; 00168 00169 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00170 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00171 displaySensingBuffer.setDelayMirrors(2); // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00172 00173 break; 00174 case CONTRACT_CENTRAL: // this is the "big mouth" 00175 00176 integrationStepLoop=0.4; 00177 integrationStepAnchor=0.4; 00178 00179 sprintf(spotName,"contract_central"); 00180 00181 //setColor(0x07);//0x04+0x02>>i); 00182 setColor(0x04); 00183 blueTouch=true; 00184 00185 // default (initial) shape: 00186 startRadius=400; 00187 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 45); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00188 00189 // Numeric parameters for the simulated mechanical system: 00190 massLoopParticle=0.3; 00191 dampMotionMassesLoop=0.023;//0.17; 00192 massAnchor=0.5; 00193 dampMotionAnchorMass=0.001; 00194 // Springs: 00195 centralSpringK=0.3; 00196 centralSpringRelax=startRadius; 00197 interSpringK=0.54;//46; 00198 interSpringRelax=25;//30; 00199 // for "zack-like" blob: 00200 interParticleRange=100; 00201 factorInterParticleForce=18.0; 00202 00203 searchActive=false; 00204 pseudopodesMode=false; // this is for contour following. 00205 00206 // Active/Inactive Forces: 00207 springForcesOnLoop= true; 00208 lightForcesOnLoop= true; 00209 forceBorderOnLoop=false; 00210 nuclearForceOnLoop=false;//true; 00211 interParticleForceOnLoop=false; 00212 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00213 // Recentering vector: 00214 angleCorrectionForceLoop=0;// in deg 00215 recenteringForceOnLoop=false ; //true; !!!!!!!!!!!!!!! 00216 angleCorrectionForceNucleus=0;// in deg 00217 recenteringForceOnNucleus=false;//true; 00218 00219 factorLightForce=8.0;//4.3; 00220 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size(); 00221 factorRecenteringLoopMass=0.045; 00222 factorPressureLoopMass=1.5; 00223 factorForceBorder=150; 00224 00225 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00226 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00227 displaySensingBuffer.setDelayMirrors(1); 00228 00229 break; 00230 00231 case CONTRACT_CENTRAL_FAST: 00232 00233 //setColor(0x07);//0x04+0x02>>i); 00234 setColor(0x04); 00235 blueTouch=true; 00236 00237 // default (initial) shape: 00238 startRadius=150; 00239 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 40); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00240 00241 // Numeric parameters for the simulated mechanical system: 00242 massLoopParticle=0.06; 00243 dampMotionMassesLoop=0.021;//0.17; 00244 massAnchor=0.5; 00245 dampMotionAnchorMass=0.01; 00246 // Springs: 00247 centralSpringK=0.3; 00248 centralSpringRelax=startRadius; 00249 interSpringK=0.54;//46; 00250 interSpringRelax=40; 00251 // for "zack-like" blob: 00252 interParticleRange=150; 00253 factorInterParticleForce=160.0; 00254 00255 searchActive=false; 00256 pseudopodesMode=false; // this is for contour following. 00257 00258 // Active/Inactive Forces: 00259 springForcesOnLoop= true; 00260 lightForcesOnLoop= true; 00261 forceBorderOnLoop=false; 00262 nuclearForceOnLoop=false; 00263 interParticleForceOnLoop=true; //!!! 00264 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00265 // Recentering vector: 00266 angleCorrectionForceLoop=90;// in deg 00267 recenteringForceOnLoop=true; 00268 angleCorrectionForceNucleus=0;// in deg 00269 recenteringForceOnNucleus=false;//true; 00270 00271 factorLightForce=-4;//3.0;//8.0; 00272 factorRecenteringAnchorMass= 20.0/bluePrint.scafold.size(); 00273 factorRecenteringLoopMass=0.06; 00274 factorPressureLoopMass=1.5; 00275 factorForceBorder=150; 00276 00277 displaySensingBuffer.setDelayMirrors(1); 00278 break; 00279 00280 case CONTOUR_FOLLOWING: 00281 sprintf(spotName,"following"); //this is a contour-following loop 00282 00283 integrationStepLoop=0.22; 00284 integrationStepAnchor=0.4; 00285 00286 //setColor(0x07);//0x04+0x02>>i); 00287 setColor(0x04); 00288 blueTouch=true; 00289 00290 // default (initial) shape: 00291 startRadius=100; 00292 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00293 00294 // Numeric parameters for the simulated mechanical system: 00295 massLoopParticle=0.05; 00296 dampMotionMassesLoop=0.27;//0.17; 00297 massAnchor=3.0; 00298 dampMotionAnchorMass=0.03; 00299 // Springs: 00300 centralSpringK=0.4; 00301 centralSpringRelax=100;//bluePrint.radius; 00302 interSpringK=0.4; 00303 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... 00304 // for "zack-like" blob: 00305 interParticleRange=70; 00306 factorInterParticleForce=4.0; 00307 00308 searchActive=true; 00309 pseudopodesMode=true; // this is for contour following. 00310 00311 // Active/Inactive Forces: 00312 springForcesOnLoop=true; 00313 lightForcesOnLoop=true; 00314 forceBorderOnLoop=false; 00315 nuclearForceOnLoop=false;//true; 00316 interParticleForceOnLoop=true; 00317 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00318 // Recentering vector: 00319 angleCorrectionForceLoop=0;// in deg 00320 recenteringForceOnLoop=true; 00321 angleCorrectionForceNucleus=180;// in deg 00322 recenteringForceOnNucleus=false;//true; 00323 00324 factorLightForce=2.4;//3.0;//8.0; 00325 factorRecenteringAnchorMass=1.0;//20.0/scafold.size(); 00326 factorRecenteringLoopMass=0.2; 00327 factorPressureLoopMass=1.5; 00328 factorForceBorder=150; 00329 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00330 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00331 displaySensingBuffer.setDelayMirrors(2); 00332 00333 break; 00334 case CONTOUR_FOLLOWING_FAST: 00335 sprintf(spotName,"following_fast"); 00336 00337 setColor(0x07);//0x04+0x02>>i); 00338 blueTouch=true; 00339 00340 // default (initial) shape: 00341 startRadius=100; 00342 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 30); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00343 00344 // Numeric parameters for the simulated mechanical system: 00345 massLoopParticle=0.05; 00346 dampMotionMassesLoop=0.27;//0.17; 00347 massAnchor=3.0; 00348 dampMotionAnchorMass=0.03; 00349 // Springs: 00350 centralSpringK=-200; 00351 centralSpringRelax=100;//bluePrint.radius; 00352 interSpringK=0.5;//46; 00353 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... 00354 // for "zack-like" blob: 00355 interParticleRange=80; 00356 factorInterParticleForce=4.0; 00357 00358 searchActive=false; 00359 pseudopodesMode=true; // this is for contour following. 00360 00361 // Active/Inactive Forces: 00362 springForcesOnLoop=true; 00363 lightForcesOnLoop=true; 00364 forceBorderOnLoop=false; 00365 nuclearForceOnLoop=false;//true; 00366 interParticleForceOnLoop=false; 00367 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00368 // Recentering vector: 00369 angleCorrectionForceLoop=243;// in deg 00370 recenteringForceOnLoop=true; 00371 angleCorrectionForceNucleus=180;// in deg 00372 recenteringForceOnNucleus=false;//true; 00373 00374 factorLightForce=2.3;//3.0;//8.0; 00375 factorRecenteringAnchorMass=1.0;//20.0/bluePrint.scafold.size(); 00376 factorRecenteringLoopMass=0.09; 00377 factorPressureLoopMass=1.5; 00378 factorForceBorder=150; 00379 00380 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00381 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00382 displaySensingBuffer.setDelayMirrors(2); 00383 break; 00384 case BOUNCING: 00385 sprintf(spotName,"bouncing"); 00386 00387 setColor(0x07);//0x04+0x02>>i); 00388 blueTouch=true; 00389 00390 // default (initial) shape: 00391 startRadius=70; 00392 bluePrint.buildCircularScafold(startRadius, vector2Dd(0,0), 20); //(float _radius, vector2Dd _pos,vector2D _vel, int _numScafoldPoints); 00393 00394 // Numeric parameters for the simulated mechanical system: 00395 massLoopParticle=5.0; 00396 dampMotionMassesLoop=0.001;//0.17; 00397 massAnchor=1.0; 00398 dampMotionAnchorMass=0.002; 00399 // Springs: 00400 centralSpringK=1.0; 00401 centralSpringRelax=70;//bluePrint.radius; 00402 interSpringK=0.4;//46; 00403 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... 00404 // for "zack-like" blob: 00405 interParticleRange=100; 00406 factorInterParticleForce=3.0; 00407 00408 searchActive=false; 00409 pseudopodesMode=false; // this is for contour following. 00410 00411 // Active/Inactive Forces: 00412 springForcesOnLoop=true; 00413 lightForcesOnLoop=true; 00414 forceBorderOnLoop=true; 00415 nuclearForceOnLoop=true;//true; 00416 interParticleForceOnLoop=false; 00417 forceInternalPressureOnLoop=false; // (when true, either constant force or calculated area using Green function or approximation by bounding box) 00418 // Recentering vector: 00419 angleCorrectionForceLoop=0;// in deg 00420 recenteringForceOnLoop=false; 00421 angleCorrectionForceNucleus=0;// in deg 00422 recenteringForceOnNucleus=false;//true; 00423 00424 factorLightForce=0.6;//3.0;//8.0; 00425 factorRecenteringAnchorMass=100.0/bluePrint.scafold.size(); 00426 factorRecenteringLoopMass=5.0; 00427 factorPressureLoopMass=2.0; 00428 factorForceBorder=4.5; 00429 00430 // per-blob mirror delay (if things were well adjusted - in particular mirror waiting times, then this could be 0. 00431 //But in case of unique blobs, it may be interesting to accelerate display AND correct the delay by software): 00432 displaySensingBuffer.setDelayMirrors(2); 00433 break; 00434 } 00435 00436 // Finally, we can create the loop using these parameters, and the positions given in the scafold: 00437 createLoopFromScafold(); // this sets the number of masses 00438 00439 // 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...) 00440 setRegionMotion(MIN_AD_MIRRORS, MIN_AD_MIRRORS, MAX_AD_MIRRORS, MAX_AD_MIRRORS); 00441 00442 // draw it once on the display buffer for good initialization: 00443 draw(); 00444 } 00445 00446 void elasticLoop::speedFactor(float speedfactor) { 00447 // 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 00448 // set in "contour following" mode. 00449 factorRecenteringLoopMass*=speedfactor; 00450 } 00451 00452 void elasticLoop::initSizeBlob(int _numMasses) { 00453 // Iinitialize blob size (number of points for the loop, as well as other structures such as lsdTrajectory) 00454 numMasses=_numMasses; 00455 // Since this is an elastic loop object, let's create an elastic loop of masses: 00456 massesLoop.resize(numMasses); 00457 loopSpringArray.resize(numMasses); // springs connecting consecutive masses 00458 // NOTE: to save memory, we can drop hairVector (use lightForce instead) 00459 hairVector.resize(numMasses); // the perpendiculars to the loop 00460 lightForce.resize(numMasses); // light force in each particle 00461 //vector2D totalLightForce; // this belongs to the base class now 00462 centralSpringArray.resize(numMasses); // springs connecting each mass to the anchorMass. 00463 00464 // Sensing and Display trajectory: 00465 displaySensingBuffer.lsdTrajectory.resize(numMasses); // the lsdTrajectory and the elastic loop will have the same number of points (this could be different - decimation?). 00466 } 00467 00468 // We will build the masses from the scafold shape (and maybe render it once on the lsdTrajectory to initialize this array?) 00469 void elasticLoop::createLoopFromScafold(void) { 00470 initSizeBlob(bluePrint.scafold.size()); // important: we will have here the same number of points in the scafold and the elastic loop (massLoop) 00471 00472 // Initial conditions for the loop masses: 00473 for (int i = 0; i < numMasses; i++) { 00474 massesLoop[i].setIntegrationStep(integrationStepLoop);//22);//19); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed. 00475 massesLoop[i].setInitialCondition(startCenter.x+bluePrint.scafold[i].x,startCenter.y+bluePrint.scafold[i].y, startSpeed.x, startSpeed.y); 00476 massesLoop[i].mass=massLoopParticle; 00477 massesLoop[i].dampMotion=dampMotionMassesLoop; 00478 } 00479 00480 // Springs for the loop: 00481 for (int i = 0; i<numMasses; i++) { 00482 loopSpringArray[i].distance =interSpringRelax; 00483 // if we want an perfect polygon: =startRadius*2*sin(1.0* PI/ numMasses); 00484 // loopSpringArray[i].distance = startRadius*2*sin(1.0* PI/ numMasses); 00485 loopSpringArray[i].springiness = interSpringK;//*(i%5==0? .6 : 1);//0.4;//4f; 00486 loopSpringArray[i].massA = & (massesLoop[i ]); 00487 loopSpringArray[i].massB = & (massesLoop[(i+1) % numMasses]); 00488 } 00489 00490 // Central (anchor mass): 00491 anchorMass.setIntegrationStep(0.3); // VERY IMPORTANT! in the case of verlet integration, we need to set dt BEFORE setting the initial speed. 00492 anchorMass.setInitialCondition(startCenter, startSpeed); 00493 anchorMass.mass=massAnchor; 00494 anchorMass.dampMotion = dampMotionAnchorMass; 00495 00496 00497 // Initial conditions for central springs: 00498 for (int i = 0; i<numMasses; i++) { 00499 centralSpringArray[i].distance =centralSpringRelax;// + 60* cos ( (1.0*i / numMasses) * 7* 2 * PI); 00500 centralSpringArray[i].springiness =centralSpringK;// 0.4f; 00501 centralSpringArray[i].massA = & (anchorMass); 00502 centralSpringArray[i].massB = & (massesLoop[i]); 00503 } 00504 } 00505 00506 00507 void elasticLoop::setRegionMotion(float mmix, float mmiy, float mmax, float mmay) { // Attention: the initial position should be INSIDE this... 00508 /* 00509 for (int i = 0; i<numMasses; i++) { 00510 massesLoop[i].setWallLimits(mmix, mmiy, mmax, mmay); 00511 } 00512 anchorMass.setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10); 00513 */ 00514 00515 // Use the static method of the class pointMass: 00516 // pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10); 00517 pointMass::setWallLimits(mmix+10, mmiy+10, mmax-10, mmay-10); 00518 } 00519 00520 void elasticLoop::update(vector2Df referencePos) { 00521 00522 // (I) Process loop geometry (compute "hair vectors", area and first order moment): 00523 processLoopData(); 00524 00525 // (II) Process sensing buffer and compute light forces 00526 // displaySensingBuffer.processSensedData(); 00527 00528 // (III) Reset all forces: 00529 for (int i = 0; i < numMasses; i++) { 00530 massesLoop[i].resetForce(); 00531 } 00532 anchorMass.resetForce(); 00533 00534 // (IV) COMPUTE FORCES (motion is not update yet): 00535 //== (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): 00536 totalLightForce.set(0,0); 00537 for (int i = 0; i < numMasses; i++) { 00538 // NOTE: to save memory, we can drop hairVector... 00539 lightForce[i]=hairVector[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone; 00540 lightForce[i].rotateDeg(angleCorrectionForceLoop); // correction by hand (interactive) 00541 // lightForce[i]=lightForce[i]*factorLightForce*displaySensingBuffer.lsdTrajectory[i].lightZone; 00542 //compute total light force, not only on lighted zones, because it will mean AWAY from black zones: 00543 totalLightForce+=lightForce[i]; // note: bad value choice (negative means TOUCH, and equal to -1), TO CHANGE this in future implementations 00544 } 00545 recenteringVectorLoop=totalLightForce;//.getRotated(angleCorrectionForceLoop); 00546 //== (2) Compute the "recentering vector" from the total light force: 00547 // Compute redundant quantities: 00548 normRecenteringVector=recenteringVectorLoop.length(); 00549 angleRecenteringVector=recenteringVectorLoop.angleDegHoriz(); 00550 recenteringVectorNucleus=totalLightForce.getRotatedDeg(angleCorrectionForceNucleus); 00551 //== (3) Compute forces on the loop: 00552 //----(a) Nearest neighbour inter-particle springs on the loop (always? we can have still another mode, following the center mass only, etc...) 00553 if (springForcesOnLoop) { 00554 for (int i = 0; i < numMasses; i++) { // if putting -1, the loop is broken 00555 loopSpringArray[i].update();// this add forces to the particles 00556 } 00557 } 00558 //----(b) Direct forces from light pressure (COULD BE MERGED WITH FORCE RECENTERING!!) 00559 if (pseudopodesMode) { 00560 // special "patches" on blob membrane, to "ATTACH" like a zip to the black drawing: 00561 if (lightForcesOnLoop) { 00562 int sign=1; 00563 for (int i = 0; i < numMasses; i++) { 00564 if ((i%2)==0) sign*=-1; 00565 //sign=5*cos(6*2*PI*1.0*i/(numMasses-1))-2; 00566 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) // this means touching something black: make SOME points attracted by it (pseudopodes!!) - but not all! 00567 massesLoop[i].addForce(lightForce[i]*(sign<0? -1.24 : 1.4)); // sign<0 means this is a pseudopode attracted by dark zones 00568 else // this means something white: do nothing, all forces are towards the exterior 00569 massesLoop[i].addForce(lightForce[i]*2.3); // this force tends to make the blob "inflate", but is not "directional" 00570 } 00571 } 00572 //----(c) Forces from the recentering vector on each particle (WITH PATCHES on the loop?): THIS IS RESPONSIBLE FOR THE "FOLLOWING" BEHAVIOUR 00573 if (recenteringForceOnLoop) { 00574 00575 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-145) : recenteringVectorLoop.getRotatedDeg(145))*factorRecenteringLoopMass*1; 00576 //vector2Df auxForce2= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5; 00577 //vector2Df auxForce3= (slidingDirection? totalLightForce.getRotatedDeg(-90) : totalLightForce.getRotatedDeg(90))*factorRecenteringLoopMass*1.5; 00578 vector2Df auxForce2= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-50) : recenteringVectorLoop.getRotatedDeg(50))*factorRecenteringLoopMass*0.5;//*1.8; 00579 vector2Df auxForce3= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-30) : recenteringVectorLoop.getRotatedDeg(30))*factorRecenteringLoopMass*0.6;//1.2; 00580 00581 00582 int sign=1; 00583 for (int i = 0; i < numMasses; i++) { 00584 if ((i%2)==0) sign*=-1; 00585 if (displaySensingBuffer.lsdTrajectory[i].lightZone>0) {// this means touching something black: behaviour may depend on the pseudopode presence: 00586 massesLoop[i].addForce((sign<0? auxForce2 : auxForce3)); // auxForce3: nothing, or sign, or corrected angle 00587 } 00588 else massesLoop[i].addForce(auxForce); // this force is responsible for the behaviour (contour following or not) 00589 } 00590 } 00591 } else { // no special zones in the "cell membrane": 00592 if (lightForcesOnLoop) { 00593 for (int i = 0; i < numMasses; i++) { 00594 massesLoop[i].addForce(lightForce[i]); 00595 } 00596 } 00597 //----(c') Forces from the recentering vector on each particle: 00598 if (recenteringForceOnLoop) { 00599 vector2Df auxForce= (slidingDirection? recenteringVectorLoop.getRotatedDeg(-90) : recenteringVectorLoop.getRotatedDeg(90))*factorRecenteringLoopMass; 00600 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce(auxForce); 00601 } 00602 } 00603 00604 //----(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) 00605 if (nuclearForceOnLoop) { 00606 // Springs: 00607 for (int i = 0; i < numMasses; i++) centralSpringArray[i].update();//assymetricUpdate(); 00608 // note: if using centralSpringArray[i].update(), we will add forces to the particles AND to the anchor mass... 00609 // Inverse square (attractive): 00610 //for (int i = 0; i < numMasses; i++) massesLoop[i].addInterInvSquareForce(anchorMass, 10, 300, centralSpringK); 00611 } 00612 //----(d) Inter loop-particles forces (Zach-Liebermann-like blob): 00613 if (interParticleForceOnLoop) { 00614 for (int i = 0; i < numMasses; i++) { 00615 for (int j = 0; j < i-1; j++) massesLoop[i].addInterSpringForce(massesLoop[j], interParticleRange, factorInterParticleForce); 00616 } 00617 } 00618 //----(e) Internal blob pressure force (my faster method to have a blob-like behaviour): 00619 if (forceInternalPressureOnLoop) { 00620 // 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): 00621 // so: f= factor/area - cte, with cte=factor/area0, with area0 being the area at equilibrium. 00622 // (And of course, to make it even more exact, we should do pressure*surface, but this will be considered constant) 00623 // float area0=30000; // area in pixels when at equilibrium 00624 //float factorPressureLoopMass=-0.1*(1.0/area-1.0/area0); 00625 //float factorPressureLoopMass=500000.0*(1.0/(area*area)-1.0/(area0*area0)); 00626 //float factorPressureLoopMass=20000.0*(1.0/sqrt(area)-1.0/sqrt(area0)); 00627 // 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): 00628 //float factorPressureLoopMass=2.5;//4.8; 00629 // Now, add the pressure force proportional to the inverse of the area to all particles, or just a signed constant: 00630 int auxsign=(area>=0? -1: 1); 00631 auxsign=-1; 00632 for (int i = 0; i < numMasses; i++) massesLoop[i].addForce( hairVector[i] * factorPressureLoopMass* auxsign); 00633 } 00634 //----(f) force from border: 00635 if (forceBorderOnLoop) { 00636 for (int i = 0; i < numMasses; i++) { 00637 if (massesLoop[i].bWallCollision) massesLoop[i].addForce(massesLoop[i].innerCollitionDirection*factorForceBorder); 00638 } 00639 } 00640 00641 //== (4) Compute forces on the anchor mass: 00642 //----(a) Force from data send by OSC? (ex: from mouse?) 00643 // anchorMass.addSpringForce(mx, my, 500, -10.2f); 00644 // or direct control: 00645 // anchorMass.pos.x=mx;anchorMass.pos.y=my; 00646 //----(b) Force from the total light force (aka, the "recentering vector"!): 00647 if (recenteringForceOnNucleus) { 00648 anchorMass.addForce(recenteringVectorNucleus*factorRecenteringAnchorMass); 00649 } 00650 00651 // when nothing is touching it for a while: 00652 if (searchActive) { 00653 if (!displaySensingBuffer.lightTouched) { 00654 if (firstTimeNoTouch) { 00655 firstTimeNoTouch=false; 00656 computeBoundingBox(); 00657 randomForce.set(2000-cx,2000-cy); 00658 randomForce.normalize(); 00659 randomForce= randomForce.getRotatedDeg(rand()%50-25); 00660 } 00661 if (noTouchedCounter>0) { 00662 // add random force, modulated: 00663 float aux=1.0*noTouchedCounter/1150; 00664 vector2Df randf=randomForce.getRotatedDeg(40.0*sin(aux*2*PI*2))*20.0;//*(1.0-aux)*0.3; 00665 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! 00666 massesLoop[i].addForce(randf); 00667 } 00668 // and a special point? 00669 //massesLoop[numMasses/2].addForce(randf); 00670 // plus amoeba effect ? 00671 // for (int i = 0; i < numMasses; i++) { 00672 // massesLoop[i].addForce(hairVector[i]*18*cos( (0.0*noTouchedCounter/1000 + 1.0*i/(numMasses-1)*2*PI*3))); 00673 //} 00674 00675 if ((noTouchedCounter>1150)||(blobWallCollision)) { 00676 noTouchedCounter=0; 00677 // compute force towards the center, slightly rotated to make the blob wander about: 00678 computeBoundingBox(); 00679 randomForce.set(2000-cx,2000-cy); 00680 randomForce.normalize(); 00681 randomForce= randomForce.getRotatedDeg(rand()%50-25); 00682 } 00683 } 00684 } else { 00685 firstTimeNoTouch=true; 00686 noTouchedCounter=0; 00687 } 00688 noTouchedCounter++; 00689 } 00690 00691 // (V) UPDATE DYNAMICS 00692 //== (1) particules on the loop: 00693 for (int i = 0; i < numMasses; i++) { 00694 #ifndef VERLET_METHOD 00695 massesLoop[i].addDampingForce(); // only in case of EULER method (damping in VERLET mode is done automatically when updating) 00696 #endif 00697 massesLoop[i].update(); // unconstrained 00698 massesLoop[i].bounceOffWalls(); // constrain position (and compute wall "hit") 00699 } 00700 //== (2) For the anchorMass: 00701 #ifndef VERLET_METHOD 00702 anchorMass.addDampingForce(); // // only in case of EULER method (damping in VERLET mode is done automatically when updating) 00703 #endif 00704 anchorMass.update(); // unconstrained 00705 anchorMass.bounceOffWalls(); // constrain position (and compute wall "hit") 00706 00707 // OTHER PARTICULAR THINGS: 00708 // (1) current color: change with touch? NO 00709 // if (displaySensingBuffer.lightTouched) 00710 // transientBlobColor=blobColor|0x02; // set green ON on the trajectory, regardless of the initial color 00711 // else 00712 transientBlobColor=blobColor; // just the original blob color 00713 00714 // change sliding direction (for countour following): 00715 if (blobWallCollision) { 00716 if (wallCounter>10) { 00717 slidingDirection=!slidingDirection; 00718 wallCounter=0; 00719 } 00720 } 00721 wallCounter++; 00722 } 00723 00724 // Drawing the graphics - this will in fact use the graphic renderer - if any - and produce the trajectory to be displayed by the laser 00725 void elasticLoop::draw() { 00726 // for the time being, there is no "opengl" like renderer, so we just copy the coordinates of the mass into the lsdTrajectory: 00727 for (int i = 0; i < numMasses; i++) { 00728 displaySensingBuffer.lsdTrajectory[i].x= (unsigned short)( massesLoop[i].pos.x ); // note: it should be an unsigned short 00729 displaySensingBuffer.lsdTrajectory[i].y= (unsigned short)( massesLoop[i].pos.y ); 00730 00731 //displaySensingBuffer.lsdTrajectory[i]= massesLoop[i].pos.y; // NOTE: doing this means converting from unsigned short to float (vector2Dd to vector2Df) 00732 00733 //displaySensingBuffer.lsdTrajectory[i].color=blobColor; // perhaps per point color is not a good idea for the time being... 00734 } 00735 00736 // Global color for the whole loop: 00737 displaySensingBuffer.displayColor=transientBlobColor; 00738 } 00739 00740 void elasticLoop::processLoopData() { 00741 00742 // (0) Check if the blob touched the borders: 00743 blobWallCollision=false; 00744 for (int i = 0; i < numMasses; i++) blobWallCollision= (blobWallCollision || massesLoop[i].bWallCollision); 00745 00746 // (1) Compute all the "hairvectors" for the loop (this is, the normals to the particles, pointing outwards). 00747 // This will be approximated by taking the 90 deg rotated difference between contiguous particles positions. 00748 for (int i = 0; i < numMasses; i++) { 00749 vector2Df diff; 00750 diff.set(massesLoop[(i+1)%numMasses].pos-massesLoop[i].pos); 00751 // normalize and rotate 90 deg: 00752 // NOTE: to save memory, we can drop hairVector... 00753 hairVector[i]=diff.getPerpendicularNormed(CW); 00754 //lightForce[i]=diff.getPerpendicularNormed(CW); 00755 } 00756 00757 // (2) Compute area: 00758 // (a) using Green method: 00759 area=0; 00760 float dx; 00761 for (int i = 0; i < numMasses-1; i++){ 00762 dx=massesLoop[i].pos.x-massesLoop[i+1].pos.x; 00763 area+=dx*massesLoop[i].pos.y; 00764 } 00765 // to avoid computation problems: 00766 // if (area<=0) area=1; // or just norm: area CAN be negative! (a loop that is larger than the original blob...) 00767 00768 // (b) Compute approximate area from enclosing rectangle: 00769 computeBoundingBox(); 00770 00771 // (c) Compute kinetic energy: 00772 totalKineticEnergy=0; 00773 for (int i = 0; i < numMasses; i++){ 00774 totalKineticEnergy+=massesLoop[i].getSpeed().squareLength(); 00775 } 00776 } 00777 00778 00779 void elasticLoop::computeBoundingBox() { 00780 float minx=4096, maxx=-1, miny=4096, maxy=-1; 00781 for (int i = 0; i < numMasses; i++) { 00782 if (i == 0) { 00783 minx = massesLoop[i].pos.x; 00784 maxx = massesLoop[i].pos.x; 00785 miny = massesLoop[i].pos.y; 00786 maxy = massesLoop[i].pos.y; 00787 } else { 00788 00789 minx = min(minx, massesLoop[i].pos.x); 00790 maxx = max(maxx, massesLoop[i].pos.x); 00791 miny = min(miny, massesLoop[i].pos.y); 00792 maxy = max(maxy, massesLoop[i].pos.y); 00793 } 00794 } 00795 00796 // final results: 00797 w = maxx - minx; 00798 h = maxy - miny; 00799 cx = minx+0.5*w; // note: center will be initialized with posX and posY when calling setInitialPos() of blobConfig 00800 cy = miny+0.5*h; 00801 00802 // approx area: 00803 approxArea=w*h; 00804 } 00805 00806 void elasticLoop::sendDataSpecific() { 00807 char auxstring[10]; 00808 myled2=1; // for tests... 00809 00810 // First, set the top address of the message to the ID of the blob (not the name): 00811 // sprintf(auxstring, "%d", identifier); 00812 // sendMes.setTopAddress("0");//auxstring); 00813 00814 // ===================== OSC ====================== 00815 if (sendOSC) { 00816 00817 // (new) Total kinetic energy: 00818 if (sendingKineticEnergy) { 00819 sprintf(auxstring, "/k %d",identifier); 00820 sendMes.setSubAddress(auxstring); 00821 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00822 x=(long)(totalKineticEnergy); 00823 sendMes.setArgs( "i", &x); 00824 osc.sendOsc( &sendMes ); 00825 } 00826 // (a) Anchor mass: 00827 if (sendingAnchorPosition) { 00828 sprintf(auxstring, "/p %d",identifier); 00829 sendMes.setSubAddress(auxstring); 00830 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00831 x=(long)(anchorMass.pos.x); 00832 y=(long)(anchorMass.pos.y); 00833 sendMes.setArgs( "ii", &x, &y); 00834 osc.sendOsc( &sendMes ); 00835 } 00836 if (sendingAnchorForce) { 00837 sendMes.setSubAddress("/aforce"); 00838 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00839 x=(long)(anchorMass.totalForce.x); 00840 y=(long)(anchorMass.totalForce.y); 00841 sendMes.setArgs( "ii", &x, &y); 00842 osc.sendOsc( &sendMes ); 00843 } 00844 if (sendingAnchorTouchWall) {// note: not an else (we can send different data simultaneously) 00845 sendMes.setSubAddress("/awall"); 00846 long wall=(long)(anchorMass.bWallCollision? 1 : 0); 00847 sendMes.setArgs( "i", &wall); 00848 osc.sendOsc( &sendMes ); 00849 } 00850 // (b) data from blob points: 00851 if (sendingLoopPositions) { 00852 #ifdef SEND_AS_POINTS 00853 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00854 for (int i = 0; i < numMasses; i++) { 00855 sprintf(auxstring, "/p %d", i); // auxstring read as "/p1", "/p2", ... 00856 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...) 00857 x=(long)(massesLoop[i].pos.x); 00858 y=(long)(massesLoop[i].pos.y); 00859 sendMes.setArgs( "ii", &x, &y); 00860 osc.sendOsc( &sendMes ); 00861 } 00862 #endif 00863 #ifdef SEND_AS_BLOB 00864 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()... 00865 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates 00866 for (int i = 0; i < numMasses; i++ ) { 00867 // note: massesLoop[i].pos.x is a "float" 00868 uint16_t x=(uint16_t)(massesLoop[i].pos.x); 00869 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE) 00870 blobdata[4*i+1]=(uint8_t)x; 00871 00872 uint16_t y=(uint16_t)(massesLoop[i].pos.y); 00873 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE) 00874 blobdata[4*i+3]=(uint8_t)y; 00875 } 00876 osc.sendOscBlob(&(blobdata[0]), 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes 00877 #endif 00878 #ifdef SEND_AS_STRING 00879 sendMes.clearArgs(); // no need, we won't use osc.sendOsc()... 00880 uint8_t blobdata[4*numMasses]; // 2 bytes per coordinate, and 2 coordinates 00881 for (int i = 0; i < numMasses; i++ ) { 00882 // note: massesLoop[i].pos.x is a "float" 00883 uint16_t x=(uint16_t)(massesLoop[i].pos.x); 00884 blobdata[4*i]=(uint8_t)x>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE) 00885 blobdata[4*i+1]=(uint8_t)x; 00886 00887 uint16_t y=(uint16_t)(massesLoop[i].pos.y); 00888 blobdata[4*i+2]=(uint8_t)y>>8; // BIG ENDIAN (send FIRST the MOST SIGNIFICANT BYTE) 00889 blobdata[4*i+3]=(uint8_t)y; 00890 } 00891 osc.sendOscString(blobdata, 4*numMasses, &sendMes ); // second parameter is osc blob size in bytes 00892 #endif 00893 } 00894 if (sendingLoopForces) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...) 00895 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00896 for (int i = 0; i < numMasses; i++) { 00897 sprintf(auxstring, "/f%d", i); // auxstring read as "/f1", "/f2", ... 00898 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...) 00899 x=(long)(massesLoop[i].totalForce.x); 00900 y=(long)(massesLoop[i].totalForce.y); 00901 sendMes.setArgs( "ii", &x, &y); 00902 osc.sendOsc( &sendMes ); 00903 } 00904 } 00905 if (sendingLoopForcesLight) { // ATTN: the force is the TOTAL force on the point (interesting perhaps for making sound...) 00906 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00907 for (int i = 0; i < numMasses; i++) { 00908 sprintf(auxstring, "/g%d", i); // auxstring read as "/f1", "/f2", ... 00909 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...) 00910 x=(long)(1000*lightForce[i].x); 00911 y=(long)(1000*lightForce[i].y); 00912 sendMes.setArgs( "ii", &x, &y); 00913 osc.sendOsc( &sendMes ); 00914 } 00915 } 00916 00917 if (sendingLoopRegions) { 00918 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00919 for (int i = 0; i < numMasses; i++) { 00920 sprintf(auxstring, "/r%d", i); // auxstring read as "/f1", "/f2", ... 00921 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...) 00922 x=(long)(displaySensingBuffer.lsdTrajectory[i].lightZone>0? 1 : 0); 00923 sendMes.setArgs( "i", &x); 00924 osc.sendOsc( &sendMes ); 00925 } 00926 } 00927 if (sendingLoopTouchWall) { // global touch wall for the loop (not per point) 00928 long wall; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00929 sprintf(auxstring, "/bWall"); 00930 sendMes.setSubAddress(auxstring); 00931 wall=(long)(blobWallCollision? 1 : 0); 00932 sendMes.setArgs( "i", &wall); 00933 osc.sendOsc( &sendMes ); 00934 } 00935 // (c) Blob geometry: 00936 if (sendingBlobArea) { 00937 /* sendMes.setSubAddress("/a"); 00938 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00939 // x=(long)(area);//approxArea); // area or approxArea 00940 x=(long)(area>0? approxArea : -approxArea); 00941 sendMes.setArgs( "i", &x); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!) 00942 */ 00943 // HACK for the time being (for Daito): 00944 sendMes.setSubAddress("/a"); 00945 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00946 // x=(long)(area);//approxArea); // area or approxArea 00947 x=(long)(w); y=(long)(h); 00948 sendMes.setArgs( "ii", &x, &y); // ATTENTION: AREA CAN BE NEGATIVE!!! (does MAX handles this well? test this!) 00949 00950 osc.sendOsc( &sendMes ); 00951 } 00952 if (sendingBlobNormals) { 00953 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00954 for (int i = 0; i < numMasses; i++) { 00955 sprintf(auxstring, "nf%d", i); // auxstring read as "/f1", "/f2", ... 00956 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...) 00957 x=(long)(hairVector[i].x); 00958 y=(long)(hairVector[i].y); 00959 sendMes.setArgs( "ii", &x, &y); 00960 osc.sendOsc( &sendMes ); 00961 } 00962 } 00963 if (sendingBlobAngles) { 00964 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00965 for (int i = 0; i < numMasses; i++) { 00966 sprintf(auxstring, "/a%d", i); // auxstring read as "/f1", "/f2", ... 00967 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...) 00968 x=(long)(hairVector[i].angleDegHoriz()); 00969 sendMes.setArgs( "i", &x); 00970 osc.sendOsc( &sendMes ); 00971 } 00972 } 00973 // (d) Light sensing statistics: 00974 if (sendingBlobMaxMin) { 00975 sendMes.setSubAddress("/maxmin"); 00976 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00977 x=(long)(displaySensingBuffer.maxI); 00978 y=(long)(displaySensingBuffer.minI); 00979 sendMes.setArgs( "ii", &x, &y); 00980 osc.sendOsc( &sendMes ); 00981 } 00982 if (sendingLightForce) { 00983 sendMes.setSubAddress("/lforce"); 00984 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00985 x=(long)(totalLightForce.x); 00986 y=(long)(totalLightForce.y); 00987 sendMes.setArgs( "ii", &x, &y); 00988 osc.sendOsc( &sendMes ); 00989 } 00990 // (e) Recentering vector: (note: redundant with sendingLightForce, IF the correction angle is known). 00991 if (sendingRecenteringVector) { 00992 sendMes.setSubAddress("/rvector"); 00993 long x, y; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 00994 x=(long)(recenteringVectorLoop.x); 00995 y=(long)(recenteringVectorLoop.y); 00996 sendMes.setArgs( "ii", &x, &y); 00997 osc.sendOsc( &sendMes ); 00998 } 00999 if (sendingRecenteringAngle) { 01000 sendMes.setSubAddress("/rangle"); 01001 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 01002 x=(long)(angleRecenteringVector); 01003 sendMes.setArgs( "i", &x); 01004 osc.sendOsc( &sendMes ); 01005 } 01006 if (sendingRecenteringNorm) { 01007 sendMes.setSubAddress("/rnorm"); 01008 long x; //ATTENTION: parameters to setArgs should be long or unsigned long only (not int!!) 01009 x=(long)(normRecenteringVector); 01010 sendMes.setArgs( "i", &x); 01011 osc.sendOsc( &sendMes ); 01012 } 01013 01014 if (sendingTouched) { 01015 if (displaySensingBuffer.lightTouched) { 01016 sendMes.clearArgs(); // there are no arguments to send 01017 sendMes.setSubAddress("/touched"); 01018 osc.sendOsc( &sendMes ); 01019 } 01020 } 01021 01022 } // end of OSC sending per-spot 01023 01024 // ===================== SERIAL ====================== 01025 if (sendSerial) { 01026 //.. to do 01027 } 01028 01029 myled2=0; // for tests... 01030 } 01031
Generated on Tue Jul 12 2022 18:50:27 by
1.7.2
