annotate lump.mm @ 15:d5758530a039 tip

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