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 //--------------------------------------------------------------
|