MSAPhysics, problems getting ofxMSAAttraction working!

Working my way up the learning curve I’ve started working with the MSAPhysics addOn, so far I’ve managed to get the 1.0 example running using MSAPhysics 1.2.

To keep things simple I’ve hacked the 1.0 example by Memo and stripped it down to be a bunch of 2D lines and circles (completely - by brute force - killing the z-axis). So far, the addOn is behaving really well :smiley:

BUT… I’ve only been using calls like
makeParticle, makeFixed, makeFree, makeSpring, etc. All the calls used in the original example.

The documentation notes mention ‘ofxMSAAttraction’:
http://addons.openframeworks.cc/documents/show/3

// an attraction (or repulsion if -ve strength) between 2 nodes
// *** I’ve not tested this yet!! ***

class ofxMSAAttraction : public ofxMSAConstraint {

float strength;

ofxMSAAttraction(ofxMSAParticle *a, ofxMSAParticle *b, float _strength, float minimumDistance);

(and of course I boldly ignore the disclaimer that this hasn’t been tested!!!) :confused:

Here’s the essence of what I try to add an attraction to the system (pseudo-code for the sake of this post):

  
  
// make a particle to be used with the mouse  
mouse = physics.makeParticle(mouseX, mouseY, 0, PARTICLE_MAX_MASS);  
mouse->makeFixed();  
  
// make some particles and make them attracted to the mouse-particle  
for(int i=0; i<50; i++){  
		ofxMSAParticle *p = physics.makeParticle(  
                ofRandom(-WIDTH/2, WIDTH/2), ofRandom(0, HEIGHT), 0, 1);  
      ofxMSAAttraction(mouse, p, 100.0, 10.0);  
}  
  

Anyone is up for having a look at it?

The entire Xcode project is here:
www.okdeluxe.co.uk/-sharing/of/MSAPhysi-…-e-test.zip

The ‘src’ folder is here:
www.okdeluxe.co.uk/-sharing/of/MSAPhysi-…-t–src.zip[/img]

Hi, indeed I hadn’t tested attractions :stuck_out_tongue: )

That would be the correct syntax. You’ll also need to include #include “ofxMSAAttraction.h” in testApp.cpp, I didn’t include it in ofxMSAPhysics.h cos I hadn’t tested it.

Unfortunately if you do the above you’ll get a bunch of compile errors cos when I went from v1 to v1.2 I made some internal variables protected and provided accessors instead, but forgot to update ofxMSAAttraction.h. So to get it to compile you’d need to change some particle properties in solver() to use getters instead. Here is the fixed code:

  
  
void solve() {  
	if(isOff()) return;  
		  
	ofxVec3f delta = (*_b) - (*_a);  
	float deltaLength2 = delta.lengthSquared();  
	if(deltaLength2 > _minDist2) return;  
		  
	float force = (_b->getMass()) * (_a->getMass()) / deltaLength2;  
		  
	if (!_a->isFixed()) *_a += (_a->getInvMass() * force) * delta;  
	if (!_b->isFixed()) *_b -= (_b->getInvMass() * force) * delta;  
}  
  

Now you can compile and run. I still haven’t tested to see if it behaves correctly and don’t have time right now to see. Theoretically it should, maybe you can tell me if it does or doesn’t…

Hi Memo,

Thanks for the detailed and quick reaction :slight_smile:

I’ve followed the instructions in your post, and yes, it does indeed compile and run! However, there’s a couple of wonky things going on:

  • negative strength doesn’t repulse
  • when particles get very close (I suspect distance equal zero?) they shoot away in great speed.

other than that, the particles attract (and accelerate) nicely towards their target and only react within the restLength distance.

I wish I knew enough to help out in fixing this :confused:

Anyway, thanks for a great AddOn, I hope you’ll get time to implement the remaining bits (let me know here or by email if you need a beginner’s brain to help test the setup).

Thanks,
Mikkel

oh, and here are the updated files:

updated ‘src’ folder:
www.okdeluxe.co.uk/-sharing/of/MSAPhysi-…-src-02.zip

and updated ‘ofxMSAPhysics’ addOn:
www.okdeluxe.co.uk/-sharing/of/MSAPhysi-…-K-EDIT.zip

hey mikkel, you are indeed right, I wasn’t even using the strength parameter!! what was I thinking! I must have been high or something when I wrote that class!
Here is the new class for ofxMSAAttraction ( just made strength private, added getters/setters, and am using that in the force calculation). It works quite well as a kind of collision between particles.

  
  
class ofxMSAAttraction : public ofxMSAConstraint {  
public:	  
	friend class ofxMSAPhysics;  
	  
	ofxMSAAttraction(ofxMSAParticle *a, ofxMSAParticle *b, float strength, float minimumDistance) {  
		this->_a = a;  
		this->_b = b;  
		setStrength(strength);  
		setMinimumDistance(minimumDistance);  
		  
		_type = OFX_MSA_CONSTRAINT_TYPE_ATTRACTION;  
	}  
	  
	void setMinimumDistance(float d) {  
		_minDist = d;  
		_minDist2 = d*d;  
	}  
	  
	void setStrength(float newStrength) {  
		_strength = newStrength;  
	}  
	  
	float getStrength() {  
		return _strength;  
	}  
	  
	  
protected:	  
	float _minDist, _minDist2;  
	float _strength;  
	  
	void solve() {  
		if(isOff()) return;  
		  
		ofxVec3f delta = (*_b) - (*_a);  
		float deltaLength2 = delta.lengthSquared();  
		if(_minDist2 && deltaLength2 > _minDist2) return;  
		  
		float force = _strength * (_b->getMass()) * (_a->getMass()) / (deltaLength2 + 0.001);		// to avoid divide by zero  
		  
		if (!_a->isFixed()) *_a += (_a->getInvMass() * force) * delta;  
		if (!_b->isFixed()) *_b -= (_b->getInvMass() * force) * delta;  
	}  
	  
};  
  
  

  • when particles get very close (I suspect distance equal zero?) they shoot away in great speed.

yea thats normal, its because the distance between them gets very very small. What you can do is:

  
  
physics.addConstraint(new ofxMSAAttraction(mouse, p, 1, 0));						// for attraction, 0 min distance means work at all distances  
physics.addConstraint(new ofxMSAAttraction(mouse, p, -10, PARTICLE_DIM * 2));		// for collision  
  

so that attaches two constraints, one for attraction which works at any distance, and a repulsion which works at the distance of the radii of the spheres, so its a kind of collision check. However for this to work, you need to comment out the check for an existing constraint when adding a constraint in ofxMSAPhysics.cpp

  
  
ofxMSAConstraint* ofxMSAPhysics::addConstraint(ofxMSAConstraint *s) {  
//	if(getConstraint(s->_a, s->_b) == NULL) {  
		_constraints.push_back(s);  
		s->setInstanceName(string("constraint ") + ofToString((int)_constraints.size()));  
		(s->_a)->retain();  
		(s->_b)->retain();  
//	}  
	return s;		// so you can configure the constraint  
}  
  

In fact in addRandomParticle (inside the foor loop, , if you do:

  
ofxMSAParticle *p = physics.makeParticle(ofRandom(-WIDTH/2, WIDTH/2), ofRandom(0, HEIGHT), 0, ofRandom(PARTICLE_MIN_MASS, PARTICLE_MAX_MASS));		// create a node in a random position  
for(int j=0; j<physics.numberOfParticles()-1; j++) physics.addConstraint(new ofxMSAAttraction(physics.getParticle(j), p, -2, PARTICLE_DIM * 2));  
  
  

you get collision between all particles. Not the best way of doing it, but works for now (slows down if you have too many particles, using an octree or something would be much faster evantually).

hi memo,
great, it all works!

I just gave your last bit of code a go (the one where they all collide with each other) and yes, that slows things down quite a bit, now I have no idea what you’re talking about when you say ‘octree’, but I assume it’s nothing simple enough to be explained here :wink: (but if someone whips up a simple example I’d love to poke at it to understand it).

now I’ve got a physics system with the features I was hoping for - time to play!

thanks so much :slight_smile:

cheers,
mikkel

hey mikkel, just a note, the main reason why it is so slow is all the line drawings between every particle. The draw function draws a line for all constraints. So if you change the code in draw() to:

  
	if(drawWire){  
		glDisable(GL_BLEND);  
		glEnable(GL_DEPTH_TEST);  
		glEnable(GL_LIGHTING);  
		  
		for(int i=0; i<physics.numberOfSprings(); i++) {  
			ofxMSASpring *spring = (ofxMSASpring *) physics.getSpring(i);  
			if(spring->type()==OFX_MSA_CONSTRAINT_TYPE_SPRING) {  
				ofxMSAParticle *a = spring->getOneEnd();  
				ofxMSAParticle *b = spring->getTheOtherEnd();  
				ofLine(a->x, a->y, b->x, b->y);  
			}  
		}  
	}  
  

It will only draw lines for springs and not every single constraint, and I still get 60fps for quite a lot of particles. I know it is a bit confusing, but physics.numberOfSprings() returns the number of constraints (springs+attractors), not the number of springs. I chose that name cos thats how it was in traer, then i added attractors and it all got a bit confusing. for the next version I’ll name them correctly.

thanks for testing it!

Yeah, I had my eyes on the drawing of lines too, they are what slows things down badly, oh well, the above code example was never meant to be an exercise in optimization, more me trying to figure out how to work the magic of MSAPhysics … but hints in optimization is always appreciated!

I now wanted to move onto reworking some of my Processing/Traer-physics tests, and thought this grid-example would be a good start:

http://vimeo.com/1274197

( auch! I just realised how bumpy a road multi-dimensional arrays can be: http://www.openframeworks.cc/forum/view-…-imensional )

hopefully i’ll be able to submit a couple of examples of MSAPhysics to the forum soon :slight_smile: