Getting Started with OpenFrameworks

After months of peeking curiosity, this past week I finally downloaded and starting playing with OpenFrameworks and taking my first steps to learning C++.

If you have a Flash / AS3 background like me you’ll quickly find that the two languages are vastly different not just in their syntax but in the way you structure a project and setup its dependencies.

With that in mind, this post will hopefully ease the process and help you sidestep some potentially confusing pitfalls especially if you are coming to OpenFrameworks from an AS3 background and have experience with Object Oriented Programming.

Before you begin.

Here is a fantastic example of the emitter created in this tutorial as extended by reader Silvio Paganini.

So first off, if you don’t already have oF download it from here and follow this guide to setting up your IDE and compiling an example test project to make sure everything works.

Assuming you got through that ok, (if you didn’t I suggest hitting the oF forums for more help on getting setup), let’s walk through a very simple example that builds a basic particle emitter / starfield.

particles

Anatomy of an oF project.

While there are probably many different ways you can approach structuring a C++ project, I like to follow the conventions of Object Oriented design and place code definitions into separate class files in an effort to keep things legible and easy to maintain. While this approach is probably overkill for such a simple example, using separate header and class files will help you get into the practice of organizing your code in such a way that will make your life much easier as you start developing more complex projects.

So first things first.

The first concept to grasp when starting out with OpenFrameworks is understanding how your program initializes.

Just like in Java, Every C++ program has an entry point in the form of a function called Main. This is analogous to the constructor of your ‘Document Class’ in AS3. If your AS3 document Class is called ‘MyFlashApp’ which subsequently links to a class file called ‘MyFlashApp.as’, the constructor in ‘MyFlashApp’ will be the first function that is called when your application starts. It is here you can place calls to other functions that will execute after your program has initialized.

Typical Document Class Constructor in AS3

public function MyFlashApp()
{
    // trace("hello world"); 
    // NowDoSomethingElse();
    // NowDoSomethingAfterThat();
}

Every oF project should start with a main.cpp file that defines the Main function that will serve as the entry point to the program

int main( ){
    ofAppGlutWindow window;
    ofSetupOpenGL(&window, 1280, 720, OF_FULLSCREEN);
    // this kicks off the running of my app
    // can be OF_WINDOW or OF_FULLSCREEN
    // pass in width and height too:
    ofRunApp( new ParticleEmitter());
}

The above snippet is just boiler plate code that every OpenFrameworks program should start with. Basically we’re just creating a window object to draw our program into and setting up the OpenGL graphics engine before we get rolling.

Notice the last line of the function where we call the oF function “ofRunApp” and pass it an instance of our ParticleEmitter. This is where we point OpenFrameworks to the custom ParticleEmitter program we are about to build thus linking the two together.

Creating the Particle Emitter – Header Declarations and Class Definitions

In C++ we build class objects using two files. Header declarations(.h) and class definitions(.cpp). While you can get away with declaring everything in one .cpp file, I feel that using separate header and class files helps keep the project organized and easier to maintain and read.

That said consider the following code inside of the header file “ParticleEmitter.h”

#ifndef _EMITTER
#define _EMITTER
 
#include "ofMain.h"
#include "Particle.h"
#define size 5000
 
class ParticleEmitter : public ofBaseApp{
 
	private:
 
	int centerX;
	int centerY;
	float rotation;
 
	public:
 
	void setup();
	void update();
	void draw();
 
	Particle* p[size];
};
#endif

The #ifndef, #define, and #endif statements are what is called a “header guard” which is used by the C compiler to check if our ParticleEmitter class has already been included in the program. If it has not, the compiler registers the header file for us which in turn allows us to create instances of the ParticleEmitter class. If you attempt to include a header file more than once, the compiler will complain and your program will probably crash. Header guards help prevent against this. You can read more about them here.

After the header guards we have two include statements. The first includes the “ofMain.h” header file which gives us access to the entire oF framework. This is necessary as you’ll see in a moment because our Particle Emitter is going to extend the class “ofBaseApp”, a fundamental base object of the oF library that provides us with access to a number of core oF properties and commands.

The second include just gives us access to a Particle class that we will define here in a moment.

It might help to think of “ofBaseApp” as similar to the AS3 Sprite object in that both typically serve as the necessary base class to their respective programs. In AS3 any class that extends Sprite automatically gains access to the x and y properties of the Sprite class for instance. Similarly, since our ParticleEmitter class extends ofBaseApp we will gain access to the frame rate and background color properties of the ofBaseApp class via inheritance as we’ll see in the ParticleEmitter class definition in a moment.

Looking at the ParticleEmitter class declaration itself inside of ParticleEmitter.h

class ParticleEmitter : public ofBaseApp {

Translates in AS3 to:

public class ParticleEmitter extends ofBaseApp {

Once we’re inside the class declaration we define all the properties and methods that our class will use. Notice how the private and public properties are grouped together. Further note that the ‘Private’ keyword is entirely optional, by default any member variables or methods in a class declared before the ‘Public’ keyword will automatically be assigned a private scope by the C++ compiler. If you are new to member access specifiers you can read about them here.

class ParticleEmitter : public ofBaseApp{
 
	private:
 
	int centerX;
	int centerY;
	float rotation;
 
	public:
 
	void setup();
	void update();
	void draw();
 
	Particle* p[size];
};

So within our ParticleEmitter declaration we’ve declared that we’re going to have an x and y value to position our emitter on the screen and a rotation value to rotate the emitter over time. We also declare three methods, setup, update, and draw that will define what our emitter will do every time the application cycles through a frame. Lastly we declare an Array called “p” that will store all of the Particles that are currently on the screen. The pointer syntax(*) that declares the “p” array is out of the scope of this article, however you can learn about pointers and how they work in C++ via this excellent tutorial here.

Lastly, note the hanging semicolon after the closing brace of the class declaration. For some reason the closing brace is not enough by itself to tell the C compiler you’ve finished your class declaration. If you are experiencing strange errors or your compliler starts throwing EXC_BAD_ACCESS statements at you, ensure that this guy is hanging on there.

Setup, Update and Draw.

Now that our ParticleEmitter class is declared, we move on to write its class definition.

One way to think about C++ header and class files is that headers declare the member variables that a class will define. It is like a contract between the two files where anything declared in the header must be defined in its accompanying class file. This is very similar to how interfaces work in AS3. Note however that in C++ headers you are also declaring instance variables where as AS3 interfaces are limited to only method declarations and final static variables.

So with all that said consider the following skeleton code for ParticleEmitter.cpp

#include "ParticleEmitter.h"
 
void ParticleEmitter::setup()
{
    centerX = 0;
    centerY = 0
    rotation = 0;
    p[0] = new Particle();
}
void ParticleEmitter::update()
{
 
}
void ParticleEmitter::draw()
{
 
}

If you look back at Main.cpp you’ll remember we created an instance of our ParticleEmitter class within the call to ofRunApp() with the line :

ofRunApp( new ParticleEmitter() );

The “new” keyword is used to call the class’s constructor which creates and returns a new instance of that class, however notice that inside our ParticleEmitter class definition no constructor method is ever defined. It’s important to note that, like in AS3, constructor methods are entirely optional. However if your class extends ofBaseApp and you chose not to provide a constructor for it, you MUST declare the setup method which gives your custom class the chance to initialize the variables you declared in its header file.

An example of how to use a constructor method inside of a class will be shown in the Particle class coming up.

AS3 onEnterFrame vs C++ Update and Draw

Once we’ve created our ParticleEmitter and have initialized its variables via the setup method, we’re ready to start calculating expressions and drawing to the screen.

In AS3, once a Flash program initializes we’re automatically given an onEnterFrame listener that runs in the background listening for changes in application state such as user input. This is essentially what allows things like Event Listeners to work by comparing whether the mouse was up on one frame or was down on another. When the change in state is heard an event is dispatched by the Flash player which allows us to write handlers and execute code based on the new conditions.

In OpenFrameworks this is accomplished a bit differently via two methods of the ofBaseApp class called update and draw. Basically the idea is both of the functions are called every frame and you want to evaluate your expressions in the update method and execute commands that render the screen from within draw.

In AS3 the following code would create a ball and move it 1 pixel to the right every frame.

private var ball;
// constructor 
public function MyFlashApp()
{
    ball = new Ball();
    this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void
{
    ball.x +=1;
}

This same code written in a C++ class file using oF could be written as follows:

void MyOFApp::setup()
{
    x = 0;
    ball* = new Ball();
}
void MyOFApp::update()
{
    x +=1;
}
void MyOFApp::draw()
{
    ball.xpos = x;
}

As you can see in C++ we get a little more granular by placing expressions into their own separate update method that is executed right before the draw method where the screen is redrawn.

Adding in the details of ParticleEmitter.cpp

First lets fill in our setup method by setting the framerate, background color, telling OpenGL to smooth our particles and hide the cursor. centerX and centerY just capture the center point of the screen which we’ll want since we told oF in Main.cpp to open in Fullscreen mode. Next we initialize rotation to zero so we can add to it and the last line is a for loop that fills our ‘p’ array with a number of particles equal to the constant ‘size’ as defined in the ParticleEmitter.h header file, which in our case is 5000.

void ParticleEmitter::setup()
{
    ofSetFrameRate(100);
    ofBackground(0, 0, 0);
    ofHideCursor();
    ofEnableSmoothing();
    centerX = ofGetScreenWidth() / 2;
    centerY = ofGetScreenHeight() / 2;
    rotation = 0;
    for (int i=0; i<size; i++) p[i] = new Particle();
}

Now that we got some 5000 particles stored in our ‘p’ array, we can define inside of update what to do with them on every frame that ticks by. Here our update method is going to loop over all the particles in the array calling each particles ‘update’ method and checking if its ‘dead’ property evaluates to true. If it does the ParticleEmitter will delete it from the ‘p’ array and create a brand new particle to store in its place. This ensures that we always have a constant number of particles in the ‘p’ array at all times, again a value equal to whatever we define ‘size’ to be in the header file. Lastly we increment our rotation var that keeps track with the current rotation of the emitter.

void ParticleEmitter::update()
{
    for (int i=0; i<size; i++) {
        p[i]->update();
	if (p[i]->dead==true) {
	    delete p[i];	
	    p[i] = new Particle();
	} 
    }
    rotation+=.05;
}

After our array of particles is updated we are ready to refresh the screen.

void ParticleEmitter::draw()
{			
    ofTranslate(centerX, centerY);
    ofRotate(rotation);
    for (int i=0; i<size; i++) p[i]->draw();
}

ofTranslate is special method of the oF graphics package that allows up to reposition the current ‘display object’ on the screen, In this case our ParticleEmitter. Since our ParticleEmitter does not come with a baked in x and y property as we would have with a display object in Flash, we need to use ofTranslate(x, y) to position it in the center of the screen. We then call ofRotate() and pass in the rotation value we incremented in the update method to slowly rotate the emitter around the center of the screen. Lastly we iterate over all of the particles in our ‘p’ array calling the draw method on each one which is what actually redraws them to the screen.

With that our Particle Emitter is complete so we can now set up and define the Particle objects themselves.

The Particle Header Declaration – Particle.h

#ifndef PARTICLE
#define PARTICLE
 
#import "ofMain.h"
 
class Particle {
 
	private:
	float x;
	float y;
 
	int color;
	int radius;
	int age;
	int maxAge;
	float speedX;
	float speedY;
 
	public:
	Particle();
 
	void update();
	void draw();
	bool dead;
};
#endif

Once again we wrap the declaration in header guards and import the oF framework via the command #import “ofMain.h”. Next within the actual class declaration we’ll define some private instance variables so the particle knows where it is. After that we explicitly declare a public constructor method which allows us the opportunity to customize each particle before we start calling its update and draw methods. Then after the constructor we have public declarations for update, draw and the boolean variable ‘dead’ which will let our ParticleEmitter class know when to remove one particle and replace it with another.

The Particle Class Definition – Particle.cpp

The Particle Class definition itself should hopefully be pretty straightforward. Notice the syntax of the first method Particle::Particle which is the constructor method where we can initialize the variables we declared in the header file.

#include "Particle.h"
 
Particle::Particle()
{
	x = ofRandomf();
	y = ofRandomf();
	speedX = ofRandom(0,4);
	speedY = ofRandom(0,4);
	radius = ofRandom(0,4);
	color = ofRandom(0, 0xff0000);	
 
	age = 0;
	dead = false;
	maxAge = ofRandom(0, 50)+250;
}
 
void Particle::update()
{
	age++;
	x += (x>0) ? speedX : speedX*-1;
	y += (y>0) ? speedY : speedY*-1;
	if (age >= maxAge) dead = true;
}
 
void Particle::draw()
{
	ofSetColor(color);
	ofCircle(x, y, radius);
}

ofRandomf() is an oF function that returns a random number (float) between -1 and 1. We use random values here in the constructor to ensure that every particle has a slightly unique starting position, color, radius and speed. maxAge is simply a variable to contain a duration value of how long this particle should exist. A value that we’ll be counting up to every time ‘update’ is called which increments this particles current age.

As the application runs the update method is called on every frame incrementing this particles age, its x and y position and checking to see if its current age is >= the max age in which case it sets it ‘dead’ property to true.

void Particle::update()
{
    age++;
    x += (x>0) ? speedX : speedX*-1;
    y += (y>0) ? speedY : speedY*-1;
    if (age >= maxAge) dead = true;
}

Next in the draw method, which is called immediately after update, we set the application’s color to the color of this particle and draw the particle to its new x and y position on the screen.

void Particle::draw()
{
    ofSetColor(color);
    ofCircle(x, y, radius);
}

So in linear terms the running of the application can be thought of as such :

  • function main() called inside of main.cpp to start (bootstrap) the application
  • ofRunApp(new ParticleEmitter()) creates a new instance of the Particle Emitter class and passes it to our running OpenFrameworks application
  • When the ParticleEmitter is created its setup() method is automatically called by oF which initializes its variables and creates 5000 particles to store in the ‘p’ array
  • ParticleEmitter.update() is automatically called by OpenFrameworks.
  • ParticleEmitter.update() loops over the ‘p’ array and calls the update method on each of the particles which calculates their new x and y position.
  • ParticleEmitter.draw() is automatically called by OpenFrameworks.
  • ParticleEmitter.draw() positions the emitter in the center of the screen, rotates it slightly, and again loops over all the particles in the array and redraws each one at its new x and y position

And that’s about it. Note that this is still very much a learning process for me so any feedback or suggestions on how to improve is always welcome in the comments below.

Download xCode project and source files here

To use the attached files, place the ParticleEmitter folder inside of the directory in which you keep your oF programs. This should be a folder inside of the ‘apps’ directory where you installed OpenFrameworks.
Ex. OpenFrameworks->apps->myApps->ParticleEmitter.