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
- Hopefully you already did this!
- Download
- Set up Xcode (OS X)
- Set up Visual Studio (Windows)
Why openFrameworks?
- openFrameworks projects compile to native executables
- iOS and Android development
- Running on a Raspberry Pi for installations
- OF community addons
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