annotate lump.mm @ 4:79c7cf39a0a0

Fixed new mesh crash - static array bounds. Made home made mutex for wavetable access. Less clicks?
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Mon, 10 Dec 2012 13:00:03 +0000
parents c667dfe12d47
children 085d80989ba7
rev   line source
rt300@0 1 /*
rt300@0 2 * lump.cpp
rt300@0 3 * simplespring
rt300@0 4 *
rt300@0 5 * Created by Robert Tubb on 01/06/2011.
rt300@0 6 * Copyright 2011 __MyCompanyName__. All rights reserved.
rt300@0 7 *
rt300@0 8 */
rt300@0 9 #include "lump.h"
rt300@0 10 #include "testApp.h"
rt300@0 11 #include <iostream>
rt300@0 12 #include "globalForces.h"
rt300@0 13 #include "globalUI.h"
rt300@0 14 extern GlobalForces globalForces;
rt300@0 15 extern GlobalUI globalUI;
rt300@0 16 //int Lump::numLumps = 0;
rt300@0 17 //--------------------------------------------------------------
rt300@0 18 // default constr
rt300@4 19 Lump::Lump(){
rt300@0 20 //cout << "constructing a default lump" << endl;
rt300@0 21 mass = 10.0;
rt300@0 22 inverseMass = 1.0/mass; // not needed - used csquared for force
rt300@0 23 friction = 0.996;
rt300@0 24 position.x = 0.5;
rt300@0 25 position.y = 0.5;
rt300@0 26 velocity.x = 0.0;
rt300@0 27 velocity.y = 0.0;
rt300@0 28 accel.x = 0.0;
rt300@0 29 accel.y = 0.0;
rt300@0 30 numAttachedSprings = 0;
rt300@0 31 grabbed = false;
rt300@0 32 highlighted = false;
rt300@0 33 constrained = false;
rt300@0 34 totalForceMag = 0.0;
rt300@0 35 size = 3; //sqrt(mass/3.0);
rt300@0 36 isInScanPath = false;
rt300@4 37 isScanPathStart = false;
rt300@4 38 isScanPathEnd = false;
rt300@4 39
rt300@0 40 previousPosition.setCoord(0.5,0.5);
rt300@0 41 zeroRefPos.setCoord(0.0,0.0);
rt300@0 42 constrainMode = NOT_CONSTRAINED;
rt300@4 43
rt300@0 44
rt300@0 45 grabID = -1;
rt300@0 46
rt300@0 47 }
rt300@0 48 //--------------------------------------------------------------
rt300@0 49 // arg constructor
rt300@4 50 Lump::Lump(double aMass,double aFriction, double positionX, double positionY){
rt300@0 51 // set members
rt300@0 52
rt300@0 53 }
rt300@0 54
rt300@0 55 //--------------------------------------------------------------
rt300@0 56 Lump::~Lump(){
rt300@4 57
rt300@0 58 }
rt300@0 59 //--------------------------------------------------------------
rt300@0 60 void Lump::attachSpring(Spring* aSpring){
rt300@0 61
rt300@4 62
rt300@4 63 attachedSprings.push_back(aSpring);
rt300@4 64 numAttachedSprings++;
rt300@4 65
rt300@0 66 }
rt300@0 67 //--------------------------------------------------------------
rt300@0 68 Spring * Lump::checkConnectedTo(Lump * otherLump){
rt300@0 69 // loop thru all attached springs looking at other end
rt300@4 70 for(int i = 0; i<attachedSprings.size(); i++){
rt300@0 71 if(attachedSprings[i]->getLumpOnOtherEnd(this) == otherLump){
rt300@0 72 return attachedSprings[i];
rt300@0 73 }
rt300@0 74 }
rt300@0 75 return NULL;
rt300@0 76 }
rt300@0 77 //--------------------------------------------------------------
rt300@0 78 void Lump::constrain(){
rt300@0 79 // TODO1 different constrain modes
rt300@0 80 constrained = true;
rt300@0 81 constrainMode = CONSTRAIN_XY;
rt300@0 82 setZeroRefPos();
rt300@0 83 //cout << "constraining lump "<< endl;
rt300@0 84
rt300@0 85 }
rt300@0 86 //--------------------------------------------------------------
rt300@0 87 void Lump::constrain(ConstrainMode aconstrainMode){
rt300@0 88 constrained = true;
rt300@0 89 constrainMode = aconstrainMode;
rt300@0 90 setZeroRefPos();
rt300@0 91 //cout << "constraining lump "<< endl;
rt300@0 92
rt300@0 93 }
rt300@0 94 void Lump::setInvMass(double aInvMass){
rt300@0 95 // use csquared
rt300@0 96 inverseMass = aInvMass;
rt300@0 97 }
rt300@0 98 //--------------------------------------------------------------
rt300@0 99
rt300@0 100 void Lump::draw(){
rt300@0 101 /*
rt300@0 102
rt300@0 103
rt300@0 104 */
rt300@0 105
rt300@0 106 if(grabbed){
rt300@0 107
rt300@0 108 int xpos = position.x * ofGetHeight() + globalUI.borderSize;
rt300@0 109 int ypos = position.y * ofGetHeight();
rt300@0 110 // draw a circle round it
rt300@0 111 ofSetColor(255, 0, 0);
rt300@0 112 ofNoFill();
rt300@0 113 ofCircle(xpos, ypos, 35.0);
rt300@0 114 ofFill();
rt300@0 115 }else if(isInScanPath){
rt300@0 116 ofSetColor(0, 200, 20);
rt300@0 117 int xpos = position.x * ofGetHeight() + globalUI.borderSize;
rt300@0 118 int ypos = position.y * ofGetHeight();
rt300@0 119 ofEllipse(xpos,ypos, 6, 6);
rt300@4 120 if(isScanPathEnd){
rt300@4 121 ofSetColor(255, 255, 0);
rt300@4 122 ofNoFill();
rt300@4 123 ofCircle(xpos, ypos, 6.0);
rt300@4 124 ofFill();
rt300@4 125 }
rt300@4 126 if(isScanPathStart){
rt300@4 127 ofSetColor(0, 255, 255);
rt300@4 128 ofNoFill();
rt300@4 129 ofCircle(xpos, ypos, 7.0);
rt300@4 130 ofFill();
rt300@4 131 }
rt300@0 132 // code to display restpos and displacement
rt300@0 133 /*
rt300@0 134 ofSetColor(0, 0, 0);
rt300@0 135 int rxpos = zeroRefPos.x * ofGetHeight() + 128;
rt300@0 136 int rypos = zeroRefPos.y * ofGetHeight();
rt300@0 137 ofEllipse(rxpos,rypos, 6, 6);
rt300@0 138
rt300@0 139 ofSetColor(100, 100, 100);
rt300@0 140
rt300@0 141 ofLine(rxpos,rypos,xpos,ypos);
rt300@0 142 */
rt300@0 143
rt300@0 144 }else if(highlighted){
rt300@0 145 ofSetColor(200, 0, 0);
rt300@0 146 int xpos = position.x * ofGetHeight() + globalUI.borderSize;
rt300@0 147 int ypos = position.y * ofGetHeight();
rt300@0 148 ofEllipse(xpos,ypos, 2, 2);
rt300@0 149 }else if (constrained){
rt300@4 150 ofSetColor(200,5,5);
rt300@4 151 int xpos = position.x * ofGetHeight() + globalUI.borderSize;
rt300@4 152 int ypos = position.y * ofGetHeight();
rt300@4 153 ofEllipse(xpos,ypos, 2, 2);
rt300@0 154 }else{
rt300@0 155 // dont draw 'normal ' lumps
rt300@0 156 return;
rt300@0 157 //ofSetColor(23, 23, 200);
rt300@0 158 }
rt300@0 159 }
rt300@0 160
rt300@0 161 //--------------------------------------------------------------
rt300@0 162
rt300@0 163 TwoVector Lump::applyForce(){
rt300@0 164
rt300@0 165
rt300@0 166 if(grabbed || constrainMode == CONSTRAIN_XY){
rt300@0 167
rt300@0 168 // don't bother
rt300@0 169 return position;
rt300@0 170 }
rt300@0 171 // called LOTS so optimise
rt300@0 172 // use spring force to calc accel - vel - pos
rt300@0 173
rt300@0 174 TwoVector springForce(0.0,0.0);
rt300@0 175 TwoVector totalForce(0.0,0.0);
rt300@0 176
rt300@0 177 // sum up force from each attached spring
rt300@4 178 for(int i = 0;i<attachedSprings.size(); i++){
rt300@0 179
rt300@0 180 springForce = (attachedSprings[i])->getForce(this);
rt300@0 181
rt300@0 182 //cout << "spring number " << i << " force x " << springForce.x << endl;
rt300@0 183 totalForce.x += springForce.x;
rt300@0 184 totalForce.y += springForce.y;
rt300@0 185 }
rt300@0 186
rt300@0 187 // get the global forces, gravity and so on
rt300@0 188 totalForce.x += globalForces.getAllForceAt(position.x,position.y).x;
rt300@0 189 totalForce.y += globalForces.getAllForceAt(position.x,position.y).y;
rt300@0 190
rt300@0 191 if (constrainMode != CONSTRAIN_X){
rt300@0 192 accel.x = totalForce.x*inverseMass;
rt300@0 193 }else{
rt300@0 194 accel.x = 0.0;
rt300@0 195 }
rt300@0 196 if(constrainMode != CONSTRAIN_Y){
rt300@0 197 accel.y = totalForce.y*inverseMass;
rt300@0 198 }else{
rt300@0 199 accel.y = 0.0;
rt300@0 200 }
rt300@0 201
rt300@0 202 // DIFFERENCE EQUATIONS HERE. This is the bit that controls the movement!
rt300@0 203
rt300@0 204 // Heun
rt300@0 205
rt300@0 206 double pvx = velocity.x*friction + accel.x*2/3;
rt300@0 207 double pvy = velocity.y*friction + accel.y*2/3;
rt300@0 208
rt300@0 209
rt300@0 210 velocity.x = 0.75*pvx + 0.25*velocity.x;
rt300@0 211 velocity.y = 0.75*pvy + 0.25*velocity.y;
rt300@0 212
rt300@0 213 double px = position.x + velocity.x*2/3;
rt300@0 214 double py = position.y + velocity.y*2/3;
rt300@0 215
rt300@0 216
rt300@0 217 position.x = 0.75*px + 0.25*position.x;
rt300@0 218 position.y = 0.75*py + 0.25*position.y;
rt300@0 219
rt300@0 220
rt300@0 221 // Newton's 2nd law
rt300@0 222 /*
rt300@0 223 velocity.x += accel.x;
rt300@0 224 velocity.x *= friction;
rt300@0 225 position.x += velocity.x;
rt300@0 226
rt300@0 227 velocity.y += accel.y;
rt300@0 228 velocity.y *= friction;
rt300@0 229 position.y += velocity.y;
rt300@0 230 */
rt300@0 231
rt300@0 232
rt300@0 233 // WALLS
rt300@0 234 if (position.x < 0.0){
rt300@0 235 position.x = -position.x;
rt300@0 236 velocity.x = -velocity.x * globalForces.wallBounce;
rt300@0 237
rt300@0 238 } else if (position.x > 1.0){
rt300@0 239 position.x = 2.0 - position.x;
rt300@0 240 velocity.x = -velocity.x * globalForces.wallBounce;
rt300@0 241
rt300@0 242 }
rt300@0 243 if (position.y < 0.0){
rt300@0 244 position.y = -position.y;
rt300@0 245 velocity.y = -velocity.y * globalForces.wallBounce;
rt300@0 246
rt300@0 247 } else if (position.y > 1.0){
rt300@0 248 position.y = 2.0 - position.y;
rt300@0 249 velocity.y = -velocity.y * globalForces.wallBounce;
rt300@0 250
rt300@0 251 }
rt300@0 252 return position;
rt300@0 253
rt300@0 254 }
rt300@0 255 //---------------------------------------------
rt300@0 256 void Lump::homingFilter(double amt){
rt300@0 257 // includes a little bit of the zero pos in the position, so sound will exponentially decay
rt300@0 258
rt300@0 259 if (constrained || grabbed) return;
rt300@0 260
rt300@0 261 position.x = (1 - amt)*position.x + amt*zeroRefPos.x;
rt300@0 262 position.y = (1 - amt)*position.y + amt*zeroRefPos.y;
rt300@0 263
rt300@0 264 }
rt300@0 265 //---------------------------------------------
rt300@0 266 void Lump::averagingFilter(double amt){
rt300@0 267 // NOT USED AVERAGING FILTER NOW IN MESH
rt300@0 268 // amt is between 0 and 1
rt300@0 269 if (constrained || grabbed) return;
rt300@0 270 double avx = 0.0, avy = 0.0;
rt300@0 271 // average the position of all the attached lumps
rt300@4 272 for(int i = 0;i<attachedSprings.size(); i++){
rt300@0 273
rt300@0 274 Lump* otherLump = attachedSprings[i]->getLumpOnOtherEnd(this);
rt300@0 275 avx += otherLump->position.x;
rt300@0 276 avy += otherLump->position.y;
rt300@0 277 }
rt300@4 278 avx /= attachedSprings.size();
rt300@4 279 avy /= attachedSprings.size();
rt300@0 280
rt300@0 281 // mix in the average with the 'real'
rt300@0 282 position.x = (1 - amt)*position.x + amt*avx;
rt300@0 283 position.y = (1 - amt)*position.y + amt*avy;
rt300@0 284
rt300@0 285 }
rt300@0 286 //---------------------------------------------
rt300@0 287 TwoVector Lump::averageOfConnected(){
rt300@0 288 TwoVector av;
rt300@0 289 if (constrained || grabbed) return position; // don't want constrained ones moving
rt300@0 290 //TODO what if edges unconstrained? this is why filtered unconstrained just ends up as a line...
rt300@0 291
rt300@0 292 // average the position of all the attached lumps
rt300@4 293 for(int i = 0;i<attachedSprings.size(); i++){
rt300@0 294
rt300@0 295 Lump* otherLump = attachedSprings[i]->getLumpOnOtherEnd(this);
rt300@0 296 av.x += otherLump->position.x;
rt300@0 297 av.y += otherLump->position.y;
rt300@0 298 }
rt300@4 299 av.x /= attachedSprings.size();
rt300@4 300 av.y /= attachedSprings.size();
rt300@0 301
rt300@0 302 return av;
rt300@0 303
rt300@0 304 }
rt300@0 305 //--------------------------------------------------------------
rt300@0 306 void Lump::setPosition(double ax, double ay){
rt300@0 307 // set INITIAL position
rt300@0 308 // Called from mesh set up. not used for updates
rt300@0 309
rt300@0 310 position.x = ax;
rt300@0 311 position.y = ay;
rt300@0 312 zeroRefPos.x = ax;
rt300@0 313 zeroRefPos.y = ay;
rt300@0 314 }
rt300@0 315 //--------------------------------------------------------------
rt300@0 316 void Lump::setVelocity(double ax, double ay){
rt300@0 317
rt300@0 318 velocity.x = ax;
rt300@0 319 velocity.y = ay;
rt300@0 320
rt300@0 321 }
rt300@0 322 //--------------------------------------------------------------
rt300@0 323
rt300@0 324 void Lump::setFriction(double aF){
rt300@0 325 friction = aF;
rt300@0 326 }
rt300@0 327 //--------------------------------------------------------------
rt300@0 328
rt300@0 329 void Lump::setZeroRefPos(){
rt300@0 330 // sets the reference point from which displacement is measured for scan amplitudes
rt300@0 331 zeroRefPos = position;
rt300@0 332 }
rt300@0 333 //--------------------------------------------------------------
rt300@0 334 double Lump::getTotalForceMag(){
rt300@0 335 return totalForceMag;
rt300@0 336 }
rt300@0 337 //--------------------------------------------------------------
rt300@0 338 double Lump::scanDisplacement(){
rt300@0 339 // returns the absolute distance from 'home'
rt300@0 340 return position.distanceTo(zeroRefPos);
rt300@0 341 }
rt300@0 342 //--------------------------------------------------------------
rt300@0 343 double Lump::scanLumpSpeed(){
rt300@0 344 // returns the absolute magnitude of the lumps velocity
rt300@0 345 return velocity.norm();
rt300@0 346 }
rt300@0 347 //--------------------------------------------------------------
rt300@0 348 double Lump::scanYPos(){
rt300@0 349 // returns the y displ
rt300@0 350 return position.y - zeroRefPos.y;
rt300@0 351 }
rt300@0 352 //--------------------------------------------------------------
rt300@0 353 double Lump::scanXPos(){
rt300@0 354 // returns the x displ
rt300@0 355 return position.x - zeroRefPos.x;
rt300@0 356 }
rt300@0 357 // -------------------
rt300@0 358 double Lump::scanRadialDisplacement(){
rt300@0 359 // returns the distance from circle zero line
rt300@0 360 // need to know where the centre point of the circle is and default radius
rt300@0 361
rt300@0 362 //return position.y - 0.5;
rt300@0 363 return position.distanceTo(zeroRefPos);
rt300@0 364
rt300@0 365 }
rt300@0 366 //--------------------------------------------------------------
rt300@0 367 void Lump::addToScanPath(){
rt300@0 368 isInScanPath = true;
rt300@0 369 setZeroRefPos();
rt300@0 370 }
rt300@0 371 //--------------------------------------------------------------
rt300@0 372 void Lump::removeFromScanPath(){
rt300@0 373 isInScanPath = false;
rt300@0 374
rt300@0 375 }
rt300@0 376 //--------------------------------------------------------------
rt300@0 377 void Lump::grab(int aGrabID){
rt300@0 378 // hover hilight doesn't work on touchscreens if(highlighted) grabbed = true;
rt300@0 379 grabbed = true;
rt300@0 380 grabID = aGrabID;
rt300@0 381 velocity.x = 0.0;
rt300@0 382 velocity.y = 0.0;
rt300@0 383 }
rt300@0 384 //--------------------------------------------------------------
rt300@0 385 void Lump::drag(double ax, double ay, int aGrabID){
rt300@0 386 if(aGrabID == grabID){
rt300@0 387 //cout << "dragging lump ID: " << grabID << endl;
rt300@0 388 position.x = ax;
rt300@0 389 position.y = ay;
rt300@0 390 velocity.x = previousPosition.x - position.x;
rt300@0 391 velocity.y = previousPosition.y - position.y;
rt300@0 392 previousPosition = position; // sets velocity too
rt300@0 393 }
rt300@0 394 }
rt300@0 395 //--------------------------------------------------------------
rt300@0 396 void Lump::unGrab(){
rt300@0 397 cout << "ungrabbed something\n";
rt300@0 398 grabbed = false;
rt300@0 399 grabID = -1;
rt300@0 400 velocity.x = 0.0;
rt300@0 401 velocity.y = 0.0;
rt300@0 402 }
rt300@0 403 //--------------------------------------------------------------
rt300@0 404 void Lump::unconstrain(){
rt300@0 405 constrained = false;
rt300@0 406 constrainMode = NOT_CONSTRAINED;
rt300@0 407 }
rt300@0 408
rt300@0 409
rt300@0 410 //--------------------------------------------------------------
rt300@0 411
rt300@0 412 bool Lump::isGrabbed(){
rt300@0 413 return grabbed;
rt300@0 414 }
rt300@0 415
rt300@0 416 //--------------------------------------------------------------
rt300@0 417
rt300@0 418 void Lump::highlight(){
rt300@0 419 highlighted = true;
rt300@0 420 }
rt300@0 421
rt300@0 422 //--------------------------------------------------------------
rt300@0 423
rt300@0 424 void Lump::unhighlight(){
rt300@0 425 highlighted = false;
rt300@0 426 }
rt300@0 427 //--------------------------------------------------------------