tutorial:pointers/arguments/constructors

Being a total newbie to OF, I created a very simple particle system using attraction (http://www.shiffman.net/teaching/nature/forces/ is a great resource for this!).

Because I had a lot of start up troubles (pointers, creating a new project etc…) I wanted to write a tutorial on this for others. Please feel free to add information or to correct me!

step 1 (see readme.txt in OF package)

a) copy the folder inside of apps/exampleApps/ and paste in the same directory
ie: (copy “emptyExample” and paste “copy of emptyExample”)

b) rename the folder, and inside the folder, rename the .xcodeproj file - ie: myExperimentalApp.xcodeproj

c) open the project

d) in the sidebar scroll down to Targets and expand it to show the target. ie: emptyExample

e) with the target selected do Get Info ( either right click or Command-i )

f) in the General Tab rename the Name text field ie: from emptyExample to myExperimentalApp

e and f alternative ) you can also just do right click on the target -> rename in the sidebar directly

g) after you have renamed the target you should change the build from Debug to Release then back again. This refreshes the target app.

step 2 Adding external library

with XCode , go to Project --> add to project and select the lib you need (ofxVectorMath in the addons folder in this case)

step 3 Pointers

  
  
for (int i=0; i<3; i++){  
	particle[i] = new Particle();	  
}  

We store the reference to each Particle into the pointer “particle”. If we want to access those particles we do it like this:

  
for (int i=0; i<3; i++){  
	particle[i]->update();  
        //we can also use this  
        //(*(particle[i])).update();  
  
}  

using -> still treats particle[i] as a pointer, while if we use *(particle[i])) we access the value of that pointer (which is the Particle Object)

step 4 Pointers as arguments

If we want to pass those particles into another function we will use the particle pointer again. attractor is also a pointer, so that why we use the ->

  
for (int i=0; i<3; i++){  
	ofxVec2f f = attractor[0]->calcGravForce(particle[i]);  
}  

the function of attractor[0] will accept a pointer and looks like this:

ofxVec2f Particle::calcGravForce(Particle *p){

  
	  
	cout << p->mass << endl;  
	  
	  
	return direction;  
}  

  
  

Now we can have access to the particle as a pointer (that’s why we use ->)!

**step 5 Constructors with arguments **

If we want constructors which allow arguments, we need to do 2 things.
edit the header file (.h)

  
public:  
	//default constructor  
	Particle();  
	//constructor which takes arguments  
	Particle(ofxVec2f location,ofxVec2f velocity,ofxVec2f accel, float m);  
  

edit the code file (.cpp)

  
Particle::Particle(){  
	  
}  
Particle::Particle(ofxVec2f location,ofxVec2f velocity,ofxVec2f accel, float m){  
	  
	loc= location;  
	vel=velocity;  
	acc=accel;  
	mass=m;  
	  
}  

All the code:

testApp.h

  
  
#ifndef _TEST_APP  
#define _TEST_APP  
  
  
#include "ofMain.h"  
#include "Particle.h"  
  
  
#define numParticles 2000  
#define numAttractors 1  
  
class testApp : public ofBaseApp{  
	  
private:  
	  
	Particle *particle[numParticles];  
	Particle *attractor[numAttractors];  
	  
	  
  
	public:  
	  
		void setup();  
		void update();  
		void draw();  
		void createAttractor();  
  
		void keyPressed  (int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
  
};  
  
#endif  
  
  
  
  

testApp.cpp

  
  
#include "testApp.h"  
#include "ofxVec2f.h"  
#include "Particle.h"  
  
  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
	createAttractor();  
	  
	ofxVec2f l;  
	ofxVec2f v;  
	ofxVec2f a;  
	  
  
	  
	for (int i=0; i<numParticles; i++){  
		float m=ofRandom(1,2);  
		l.set(ofRandom(0,100), ofRandom(0,100));  
		v.set(ofRandom(1,2), ofRandom(1,2));  
		a.set(0, 0);  
		particle[i] = new Particle(l,v,a,m);	  
  
	}	  
}  
  
  
void testApp::createAttractor(){  
	ofxVec2f l;  
	ofxVec2f v;  
	ofxVec2f a;  
	  
	float m=2.2;  
	  
	l.set(400, 400);  
	v.set(0, 0);  
	a.set(0, 0);  
	  
	for (int i=0; i<numAttractors; i++){		  
		attractor[i] = new Particle(l,v,a,m);	  
	}  
		  
}  
//--------------------------------------------------------------  
void testApp::update(){  
	  
	for (int i=0; i<numParticles; i++){  
		  
		ofxVec2f f = attractor[0]->calcGravForce(particle[i]);  
		particle[i]->applyForce(f);  
		particle[i]->update();  
		  
		  
	}	  
  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	  
	  
	attractor[0]->draw();  
	for (int i=0; i<numParticles; i++){  
		  
		particle[i]->draw();  
		  
	}  
  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
  
}  
  
  
  

Particel.h

  
  
#ifndef PARTICLE  
#define PARTICLE  
  
#include "ofMain.h"  
#include "ofxVec2f.h"  
#import "ofMain.h"  
  
  
class Particle  {  
	  
public:  
	Particle();  
	  
	Particle(ofxVec2f location,ofxVec2f velocity,ofxVec2f accel, float m);  
	  
	float x;  
	float y;  
	float mass;  
	float max_vel;  
	float bounce_force;  
	  
	ofxVec2f loc;  
	ofxVec2f vel;  
	ofxVec2f acc;  
	  
	void setup();  
	void update();  
	void draw();  
	void applyForce(ofxVec2f force);  
	ofxVec2f calcGravForce(Particle *p);  
	  
};  
  
#endif  
  
  

Particle.cpp

  
  
  
#include "Particle.h"  
#include "ofxVec2f.h"  
  
  
Particle::Particle(){  
	  
}  
Particle::Particle(ofxVec2f location,ofxVec2f velocity,ofxVec2f accel, float m){  
	  
	loc= location;  
	vel=velocity;  
	acc=accel;  
	mass=m;  
	  
}  
  
void Particle::setup(){  
  
	  
}  
  
ofxVec2f Particle::calcGravForce(Particle *p){  
	  
	ofxVec2f direction = (loc-p->loc);		// Calculate force direction  
    float distance = direction.length();	// Distance between objects  
	if(distance > 25){  
		distance=25;  
	}  
	if(distance<5){  
		distance=5;  
	}  
    direction.normalize();		  
    float force = (1 * mass * p->mass) / (distance * distance);   
    direction=direction*force;	  
	  
	  
	return direction;  
}  
  
void Particle::applyForce(ofxVec2f force){  
	force=force/mass;  
	acc=acc+force;  
}  
  
void Particle::update(){  
	vel=vel+acc;  
    vel=vel.limit(1.1);  
    loc=loc+vel;  
    acc=acc*(0);  
	  
  
}  
  
void Particle::draw(){  
	ofSetColor(0xff0000);  
	ofCircle(loc.x, loc.y, 2);  
}