Intro to openFrameworks

Before We Begin

  • If you're confused about something or want to know more, please interrupt me and ask questions!
  • If I'm moving too fast/slow, please let me know!
  • All of the code examples are on GitHub

Setting up openFrameworks

Why openFrameworks?

Why NOT openFrameworks?

  • C++ is not beginner-friendly
  • XCode and Visual Studio are very complicated IDEs
  • Can't easily distribute work on the web (although it's possible!)
  • Documentation could be better
  • Community addons are sometimes out of date

What can you make with openFrameworks?

The Project Generator

Change project path

Include addons

Generate a new project

Update an existing project

Xcode

Choose compilation target

Run your sketch

Stop your sketch

Show file navigator

Show debug console

Add a new file

C++

  • C++ is statically typed: unlike JavaScript or Python, all variables and functions must have explicitly declared types in the source code
  • C++ is compiled: unlike JavaScript or Python, C++ source code has to be compiled into machine code before it can be run
  • C++ is high level & object-oriented like Python or Java (there's a standard library, you can make classes)
  • C++ is also low level, like C (it allows you to manually manage memory)

Syntax

// lines end with a semi-colon (this is not optional)
// variables must be declared with a type before the variable name
int i = 0;

// control structures are similar to JavaScript (for loops, while loops, if/else, etc.)
int value = 0;
for (int i = 0; i < 5; i++) {
  value++;
}

while(value >= 0) {
  value--;
}

// no === in C++, only ==
if (value == 0) {
  value = 1;
} else if (value == 1) {
  value = 2;
} else {
  value = 0;
}

Types

// integers
int i = 1;

// floats
float f = 1.5;

// booleans
bool b = true;

// characters (note the single quotes)
char c = 'a';

// strings
std::string str = "Hello world!";
// OR
using namespace std;
string str = "Hello world!";

// arrays
int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Title Text

/*
 * This will print "Hello World" to the console.
 * 
 * cout << means "send the following stuff to stdout in a formatted way."
 *
 * << endl means "add a carriage return (end-of-line) character to the end of the message."
 */
cout << "Hello World" << endl;

/*
 * You can also chain multiple << in a row.
 * This is useful because, unlike in JavaScript,
 * you can't add values of different types (e.g. string and int).
 */
cout << "Hello World" << 12345 << endl;

Printing to the console

Title Text

// functions must be declared with the type of value that they will return
// and the types of arguments that they take
int addOne(int x) {
  return x + 1;
}

// functions that don't return a value will have a return type of "void"
void doNotReturn() {
  doSomeStuff();
  drawSomething();
}

Functions

Title Text

/*
 * Preprocessor directives modify your code before it is compiled (they pre-process it!).
 * #include tells the C++ compiler to copy/paste some code
 * from another file into your file
 */

// include a header file from the standard library (iostream gives you cout and endl)
#include <iostream>

// include a header file that you (or someone else) wrote
#include "ofMain.h"

// #define defines a constant
#define PI 3.14159265359

// #pragma once tells the C++ compiler to only #include this file once, to prevent duplication
#pragma once

Preprocessor Directives

Title Text

/*
 * namespaces are a way of grouping together identifiers to avoid conflicts.
 * to reference a name in a namespace, we use the :: syntax, e.g. std::string
 */

std::string foo = "bar";

// this tells the C++ compiler to load all the identifiers from the std namespace
using namespace std;

// now we can reference string without the :: syntax
string foo = "bar";

Namespaces

Header Files

  • A header file is like a blueprint for your code, or the ingredient list for a recipe
  • Header file names end with .h, regular C++ file names end with .cpp
  • Header files contain declarations for your functions, classes, and variables, but not implementations

Header Files (cont.)

// add.h

#pragma once

int add(int x, int y);


// add.cpp

#include "add.h"

int add(int x, int y) {
  return x + y;
}


// main.cpp

#include "add.h"

int main() {
  int i = add(1, 2);
}

Classes

// Person.h

#pragma once

class Person {
    // anything that is public can be accessed on an instance of this class
    public:
        Person(string _name); // constructor
        ~Person(); // destructor, don't worry about this too much
        void greet();

    // anything that is private can only be accessed by internal methods of this class
    private:
        string name;
};

// Person.cpp

#include "Person.h"

Person::Person(string _name) : name(_name) {
    cout << "hello " << name << endl;
}

void Person::greet() {
    cout << "greetings " << name << endl;
}

Person::~Person() {
    cout << "goodbye " << name << endl;
}

Classes (cont.)

// main.h

#include Person.h

int main() {
    // make a new Person
    Person me("Oren"); // should print "hello Oren"
    me.greet(); // should print "greetings Oren"

    me.name = "Steve"; // this would cause a compiler error
}

// after main() finishes running, should print "goodbye Oren"

Structs

// structs are another way of storing multiple pieces of data in one object.
// technically they can do anything that classes can do, but I like to use them
// as POD (plain old data) containers, without any constructors, destructors, or methods

typedef struct {
    string name;
    int age;
} Person;

Person me;
me.name = "Oren";
me.age = 25;

Vectors

// vectors are arrays that can dynamically change in size,
// like arrays in JavaScript or ArrayLists in Java

// when we declare a vector, we specify the type of data that it will contain inside <>
vector<int> numbers;

// adding to the back of a vector
for (int i = 0; i < 100; i++) {
  numbers.push_back(i);
}

// accessing a value in a vector by index
int middle = numbers[50];

// removing from the back of a vector
int size = numbers.size();
for (int j = 0; j < size; j++) {
  numbers.pop_back();
}

Reference Variables

// in C++, when we assign a value to a variable, we're usually copying that value.
// however, sometimes we actually want to reference the exact same value in memory,
// e.g. when we are modifying an object in a vector of objects

// ofPoint is an openFrameworks class that stores (x, y) coordinates
vector<ofPoint> points;
for (int i = 0; i < 5; i++) {
    ofPoint p(i, 0);
    points.push_back(p);
}

ofPoint copy = points[0];
copy.x = 10;

cout << points[0].x << endl; // this will still print 0

// we can use the & operator to make a reference variable
ofPoint & reference = points[0];
points[0].x = 10;

cout << points[0].x << endl; // this will print 10

openFrameworks

main.cpp, ofApp.h, ofApp.cpp

  • Why are there 3 files???
  • In Processing and p5.js, all of your global variables are declared at the top of your main file
  • In openFrameworks, you declare global variables and functions in ofApp.h (the header file)
  • ofApp.cpp is where you write your setup(), update(), and draw() functions
  • main.cpp includes ofApp.h and runs the app in the program's main function (all C++ programs have a main function)
  • main.cpp is also where you set the app's window size

setup(), update(), draw()

  • setup() is called once at the beginning of the application
  • update() and draw() are called, in that order, every frame in an infinite loop
  • setup() is where we instantiate the global variables that we declared in ofApp.h
  • update() is where we update the state of our application, do calculations, and update other objects like video players, grabbers, or computer vision helpers
  • draw() is where we draw to the screen!

Useful functions

Useful classes

Example Projects

Additional Resources

Intro to Openframeworks and C++

By Oren Shoham

Intro to Openframeworks and C++

  • 657