Donations

Today we are opening the openFrameworks donations page!

For years we’ve developed openFrameworks through the voluntary, non-paid contributions of many people around the world.

These contributions are often part of the process of people using openFrameworks for their work or practice. As they discover bugs or need new features, they contribute these changes back to openFrameworks, benefiting the community and project as whole.

This workflow has worked fairly well for openFrameworks up to this point. However it means that the growth of the project is limited by the particular interests and available time of contributors and has meant that some areas of the project have fallen behind.

We are opening up the donations page to fund some of these areas and to help OF continue forward in a more sustainable way. Your donations will contribute to the following:

Documentation

Documentation is one of the main areas that has been behind the rest of the project. We think that it could be that the users who are confident enough to contribute to the openFrameworks codebase don’t rely as much on the the documentation and the people who do rely on it and run into unclear or missing documentation usually don’t feel confident enough to contribute to it.

We’ve organized documentation sprints which has been helpful in the short term, but it doesn’t take long for the documentation to begin to drift out of sync with this codebase and as it is an area where there isn’t active ongoing contributions we believe it needs us to take a different approach.

With financial contributions from individuals, companies and institutions we would be able to fund a team, over the long term to work on the documentation, make sure it was up to date with the API and provide good examples and tutorials for all areas of the project.

Infrastructure

As the openFrameworks project has grown we are relying on wide range of services and infrastructure to keep the project running. We have a distributed build system, continuous integration services ( CI ) that allow us to check that changes don’t break the codebase and a tool for compiling all the libraries for the many different platforms OF supports ( Apothecary ).

There is also a lot of work that needs to be done not directly related to using OF itself, like maintaining the forum, updating the CI or fixing the multiple servers we use when something breaks, as well as keeping them up to date. Maintaining these services and development systems is something we’ve been doing up until now unpaid, but the amount of time it requires isn’t sustainable to continue in the long term.

Diversity

Making openFrameworks more accessible and the community of users more diverse is another big goal of the project that we think we can really improve if we have a significant and ongoing financial contribution.

Until now we’ve been relying on a community of contributors who had enough free time to work on the project but we’ve come to realize that because of very different factors like for example, wages inequality, it is much harder for some people like women, people of color or people living in developing countries to work without being paid in their free time. By being able to pay for some contributions we expect to help overcome that barrier and increase range of people contributing and shaping the future of openFrameworks.

A more sustainable model

Opening up the donations page is only a first step. We are currently working on the outline for a more sustainable model for openFrameworks, which would allow the project to get broader, institutional level funding. Individual donations in the meantime will help immensely with us moving quicker towards our goals, offloading work onto a more diverse group of contributors and help achieve more regular, higher quality and better documented releases.

To donate

If you have used openFrameworks in your personal practice, or you represent a studio or company that has used openFrameworks in your work and you would like to financially support the project, please do so now at the donations link below.

Thanks for your support!

glm

OpenGL Mathematics

OpenGL Mathematics GLM has become the defacto standard for graphics vector math in C++ in the latest years. It’s syntax mimics that of glsl so working with it while working with OpenGL, shaders… makes things easier cause the syntax is almost the same across the different languages.

openFrmaeworks, since version 0.10 uses GLM as it’s default vector math library in the core and although old projects using ofVec* classes should work with minimal changes, if you are starting a new project we recomend to use GLM instead.

Namespace

GLM classes and functions are in the glm namespace so to use them you need to either prefix them with glm:::

glm::vec3 v(2.f, 2.f, 2.f);
float l = glm::length(v);

Or in your .cpp files import the glm namespace at the very beginning:

using namespace glm;

And then use the classes and functions without prefix:

vec3 v(2.f, 2.f, 2.f);
float l = length(v);

Functions not methods

GLM classes like vectors, matrices or quaternions don’t have methods. Instead glm uses functions to operate on those classes so if you want to for example normalize a vector you would do:

glm::vec3 v(2.f, 2.f, 2.f);
glm::vec3 n = glm::normalize(v);

The only exceptions to this rule are operators which you don’t use directly but instead allow to do arithmetic operations so you can do things like:

glm::vec3 v1(1.f, 1.f, 1.f);
glm::vec3 v2(2.f, 2.f, 2.f);
glm::vec3 v3 = v1 + v2;

Warning

GLM vector have a static length function which returns the dimension of the vector type, so glm::vec2::length() returns 2, glm::vec3::length() returns 3…

Because C++ allows to call static methods on instances of that class you can make the error of calling:

glm::vec3 v(2.f, 2.f, 2.f);
float length = v.length();

To try and get the length of the vector instead of the number of dimensions of the type. The correct way of doing that would be:

glm::vec3 v(2.f, 2.f, 2.f);
float length = glm::length(v);

Mostly when porting old code form ofVec to glm, because ofVec included such a method, it’s easy to try and call that function which will compile without errors but won’t do what you expect.

When doing that, most modern compilers should show a warning because of calling a static method on an instance instead of a class, so be on the look for those when porting old code to GLM.

Type strictness

glm has a strict type system, similar to how things work in glsl, meaning that you can’t autoconvert from one type to another automatically as it was the case with ofVectorMath.

For example:

glm::vec2 v2(2.f, 2.f);
glm::vec3 v3 = v2;

Won’t work anymore, you need to do now:

glm::vec3 v3 = glm::vec3(v2, 0.f);

Or in the oposite case:

glm::vec3 v3(2.f, 2.f, 2.f);
glm::vec2 v2 = glm::vec2(v3)

or even:

glm::vec2 v2(v3)

Constants

GLM has some useful constants but the way to use them might be a little bit weird at first. The main problem comes from the fact that this constants are defined as templated functions so to call them you need to specify the type as in:

float p = glm::pi<float>();
double dp = glm::pi<double>();

Multiplication order

Finally, if you are used to the old openFrameworks vector math classes you would multiply vector and matrices like:

ofVec3 v;
ofVec3f projected = v * model * view * projection;

with glm as in glsl the multiplication order is the oposite so now you would do:

glm::vec3 v;
glm::vec3 projected = projection * view * model * v;

Android refactoring

Many OpenFrameworks Android apps are composed from a single activity, which derives from OFActivity and allow you to draw GL content in a canvas. This fits most cases. However, sometimes you need multiple activities, some with GL drawing and some without. OpenFrameworks Android supports such cases.

Add application initialization code

We can distinguish between application initialization and gl initialization. There are two methods in main.cpp, one for each. In most cases, there’s nothing to do in ‘ofAndroidApplicationInit’, and in ‘ofAndroidActivityInit’ we initialize the ofApp class.

‘ofAndroidApplicationInit’ allow you to do some initialization when the cpp side is created, even if the first activity is not a gl activity (for example, a completely native splash activity).

‘ofAndroidActivityInit’ is called when the gl canvas is initialized. This happens when the first OFActivity is created. Notice that if a second OFActivity is created on top of it, the canvas is recycled and this initialization code is not called again. However, if all OFActivites are destroyed, the canvas is indeed destroyed so when a new OFActivity is created, ‘ofAndroidActivityInit’ will be called again. The default implementation for this method instantiates the ofApp class, but you can add more code to it as needed.

Note that due to current architectural constraints, all activities share a single ofApp class and a single canvas. You cannot switch to different ofApp classes for drawing different activities as OpenFrameworks cannot currently hold multiple instances of the ofApp class in memory. It is up to you to signal the cpp side when a different activity is shown (when onResume is called on that activity), and perform different update/draw code to draw different content on the canvas.

Customizing the Android activity

OpenFrameworks supplies a base activity called OFActivity when the following conditions suits the project:

1) The first activity is this activity, meaning, the first activity in the application shows a gl canvas. 2) You want your activity to inherit from regular Android Activity class.

However, OpenFrameworks allows for more complicated scenarios, like having the first activity initializing the cpp side, but not the gl drawing (the first activity doesn’t draw gl at all, for example, a simple splash activity) or inheriting your activities from other classes, for example AppCompatActivity.

In order to achieve one or both the objectives above, you need to notify OpenFrameworks yourself on certain events, just like the original OFActivity does it:

In ANY activity in the application:

1) Whenever ANY activity is created OR resumed, you need to notify OpenFrameworks about it by calling OFAndroidLifeCycle.setActivity with this activity. 2) On the first activity created, you need to call OFAndroidLifeCycle.init() in order to initialize the cpp side. If this activity SHOULD NOT draw GL, you should call it with the parameter false in order to postpone canvas initialization.

In gl drawing activities:

1) in onCreate, call OFAndroidLifeCycle.glCreate() 2) in onResume, call OFAndroidLifeCycle.glResume() 3) in onPause, call OFAndroidLifeCycle.glPause() 4) in onDestroy, call OFAndroidLifeCycle.glDestroy()

You can look at the original OFActivity as a reference, and there’s also a detailed example with multiple activities in the android examples folder, called androidMultiOFActivityExample.

Tal Lavi & Artem Pyatishev.

OpenGL new features

Transform feedback

Transform feedback is a relatively new feature in opengl (present since 4.3 and so not available in macos). It allows to store the output of a vertex, geometry or tessellation shader into a buffer object.

For example we can draw a sphere in an ofVboMesh, draw it using a vertex shader that deforms the vertices using a noise function and get the result in a new buffer, then we can assign that buffer to an ofVbo for drawing.

This allows to do expensive transformations in the GPU only once, store them and then draw them instead of having to do the calculations every frame.

It also allows to do several steps of vertex shaders for example or to generate geometry with a geometry shader and then use a different vertex shader to draw…

The download for 0.10.0 for windows and linux, includes an example explaining how to use it in gl/tranformFeedbackExample

That example generates a mesh with a certain number of points but without setting them at all then draws the mesh using a shader with a transform feedback which modifies the poitns to distribute them along the surface of a semi-sphere uniformly and sets each vertex color depending on their position.

The resulting buffer is assigned to a vbo and drawn later in the draw function without having to calculate the positions every frame.

GL debug callback

OpenGL provides an extension (promoted to core in 4.3, which again means it won’t work in macos) that allows to debug the context for errors.

In OF 0.10.0 you can now call:

ofEnableGLDebugLog()

And if any error or any other internal message happens you’ll get a debug trace in the console. You can even set a breakpoint while debugging inside ofGLUtils.cpp in the function gl_debug_callback to know which call is producing the message. Once the breakpoint is set the debugger will stop whenever a message happens and you can see in the stacktrace the original in your code that is triggering it.

This is useful to debug obscure GL bugs like buffers not correctly bound or similar problems which are really hard to debug usually.

To disable the logging you can call:

ofDisableGLDebugLog()

Custom materials extensions

ofMaterial, when used with opengl version 3 or more runs internally a glsl program that calculates the phong shading per fragment using all the lights enabled at that moment.

Sometimes we want to change the behaviour of that shader. To do so, since 0.10.0 you can setup a material using ofMaterialSettings and there specify a function which will be called after the lighting has been calculated. It receives the final color of the fragment as parameter and returns the modified color which will be the final color assign to that fragment:

vec4 postFragment(vec4 localColor){
   return localColor;
}

That function has access to all the uniforms and varyings available in the fragment shader but we can also specify additional uniforms by using customUniforms in ofMaterialSettings and then setCustomUniform* while we use the material.

There’s more information in the header of ofMaterial and soon in the online docs in the OF site

Arturo

Events

ofEventListener

Up until now listening to an event in OF looked something like:

 ofAddListener(ofEvents().mouseMovedEvent, this, &MyClass::mouseMoved);

And removing the listener:

 ofRemoveListener(ofEvents().mouseMovedEvent, this, &MyClass::mouseMoved);

That has several problems mainly if we want to add a class to listen to a mouse event we would be tempted to do something like:


class CircleMovingWithMouse{ public: CircleMovingWithMouse(){ ofAddListener(ofEvents().mouseMovedEvent, this, CircleMovingWithMouse::mouseMoved); } ~CircleMovingWithMouse(){ ofRemveListener(ofEvents().mouse, this, &CircleMovingWtihMouse::mouseMoved); } ... }

So when creating an instance of that class it would listen to the mouse and when the object is destroyed it’ll remove itself as a listener so there’s no calls once the object has been destroyed, otherwise we would get a crash.

The problem with this is if we do something like:

void ofApp::setup(){
  CircleMovingWithMouse circle;
  circles.push_back(circle);
}

The circle won’t receive the events anymore cause the copy won’t be listening to events anymore and the original will be destroyed as soon as we go out of setup.

Even worse if we try to put this class in a vector as before but register the event after we add it like:

void ofApp::setup(){
  for(int i = 0; i<10; i++){
    CircleMovingWithMouse circle;
    circles.push_back(circle);
    circles.back().registerEvents()
  }
}

The vector will move it’s objects in memory when it runs out of contiguous memory which will make the address for our objects stored in the event invalid so we will likely get a segmentation fault and the application will crash.

By the rule of 3 (the rule of 5 since c++11) https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming) when we add a destructor as we did above we should also implement a copy constructor and equal operator.

Doing so would solve our problem if in the copy constructor we re-add the new copy as a listener as well. But introducing a copy constructor is error prone since from now on we’ll need to copy every new member we add to the class.

To solve this issues in 0.10 we’ve introduced a new way to listen to events: ofEventListener. Now to listen to an event the preferred method is something like:


class CircleMovingWithMouse{ private: ofEventListener listener; public: CircleMovingWithMouse(){ listener = ofEvents().mouseMovedEvent.newListener(this, &CircleMovingWithMouse::mouseMoved); } }

The listener will now auto unregister itself when the object is destroyed so there’s no need for a explicit destructor. Also ofEventListener forbids to copy (or even move) an instance of a class containing it so if you now try to put a class listening to an event into a vector you’ll get a compiler error.

You can still work around it by creating your copy/move constructors and equal operator but at least the error happens at compile instead of at run time.

It’s still not recommended to implement copy constructors since it’s really error prone and difficult to maintain. Instead if you want for example a collection of objects that listen to an event like the above you can put them in a collection that won’t move it’s elements in memory as a vector does, like a list or a deque and create them using emplace_backinstead of push_back:

std::list<CircleMovingWtihMouse> circles;

objects.emplace_back(); // This crreates a new object in the list
objects.back().doSomething();  //This calls a method on the last element added to the list

There’s some limitations to this collections, for example you won’t be able to access a random position on a list, only to iterate thorough all it’s elements as in:

for(CircleMovingWtihMouse & o: objects){
}

And you won’t be able to remove a random position of a deque containing listeners cause it would need to move it’s elements in memory and the ofEventListener forbids that to avoid illegal memory accesses.

Another way to work around this is to wrap the objects in a smart pointer before putting them in a vector but be aware that doing so allocates every object in non contiguous locations in the heap so some of the advantages of using a vector are lost.

In general this new way of using events won’t let you do anything that might crash or have an undefined behaviour.

If you need to add more than one listener to a class you can also use ofEventListeners:

class CircleMovingWithMouse{
private:
  ofEventListeners listeners;

public:
  CircleMovingWithMouse(){
    listeners.push(ofEvents().mouseMovedEvent.newListener(this, &CircleMovingWithMouse::mouseMoved);
    listeners.push(ofEvents().mousePressedEvent.newListener(this, &CircleMovingWithMouse::mousePressed);
  }
}

Key events

Key event arguments now carry much more information than before. Until now a key event was just an integer with the ascii for the pressed key but from 0.10.0 and in line with our effort to support UTF8 across the core it now looks like:

class ofKeyEventArgs{
public: 
    /// For special keys, one of OF_KEY_* (@see ofConstants.h). For all other keys, the Unicode code point you'd expect if this key combo (including modifier keys that may be down) was pressed in a text editor (same as codepoint).
    int key;
    /// The keycode returned by the windowing system, independent of any modifier keys or keyboard layout settings. For ofAppGLFWWindow this value is one of GLFW_KEY_* (@see glfw3.h) - typically, ASCII representation of the symbol on the physical key, so A key always returns 0x41 even if shift, alt, ctrl are down.
    int keycode;
    /// The raw scan code returned by the keyboard, OS and hardware specific.
    int scancode;
    /// The Unicode code point you'd expect if this key combo (including modifier keys) was pressed in a text editor, or 0 for non-printable characters.
    uint32_t codepoint;
    /// If this is a repeat event
    bool isRepeat;
    /// Key modifiers
    int modifiers = 0;

    bool hasModifier(int modifier){
        return modifiers & modifier;
    }
}

You can keep using ofKeyEventArgs::key as before but if you want to listen for keypresses to create a text you should use ofKeyEventArgs::codepoint which holds the utf8 code of the key except in the case of special keys like OF_KEY_SHIFT, OF_KEY_CONTROL, … where it’s equal to 0.

Also when you receive a key event you can also check if a modifier is pressed at the same time using ofKeyEventArgs::hasModifier() as in:

void MyClass::keyPressed(ofKeyEventArgs & key){
    if(key.hasModifier(OF_KEY_CONTROL) && key.codepoint==`a`){
         ...
    }
}

hasModifier() also exists for mouse events so you can query it when a mouse event happens as in:

void MyClass::mousePressed(ofMouseEventArgs & mouse){
    if(mouse.hasModifier(OF_KEY_CONTROL) && mouse.button = OF_MOUSE_LEFT){
         ...
    }
}

The callbacks in ofApp are still the simple ones that just receive the int key for key events and the position x and y and mouse button for mouse events but you can easily change them to:

void ofApp::mousePressed(ofMouseEventArgs & mouse){
}

and it’ll just work without having to explicitly listen to that event. For any other class but applicaiton instances started with ofRunApp you’ll need to register an event using newListener (or ofAddListener / ofRemoveListener)

Lambda functions

And finally since 0.10.0 you’ll be able to use lambda functions to listen to events instead of having to create a specific method as in:

class MyClass{
private:
    ofEventListener listener;

public:
    MyClass(){
        listener = ofEvents().mousePressed.newListener([this]{
            std::cout << mouse.pos << std::endl;
        });
    }
}

Again since we are using ofEventListener the listener will be unsubscribed automatically when destroyed.

Lambdas can only be used with newListener and not with ofAddListener / ofRemoveListener for this reason.

Arturo

UTF8 support

In 0.10.0 there’s (finally) full support for UTF8 both as utilities to manipulate strings but also in ofTruetypefont.

String manipulation

Some of this utilities where already introduced in 0.9.0 but there’s some more now and the API has been cleaned to make it more consistent.

All this functions start as ofUTF8* and if you want to do something with text which might have characters other than ascci, because UTF8 has variable length characters you should be using this functions instead of the corresponding string methods. for example instead of doing:


str.insert(pos, chr);

to insert a character you should be using:


ofUTF8Insert(str, pos, chr)

or when creating a string from keypresses:


ofUTF8Append(str, key);

there’s also ofUTF8Substring, ofUTF8ToString and ofUTF8Length

Also to iterate over a string don’t iterate over it’s characters but use:


for(uint32_t & c: ofUTF8Iterator(str)){
}

ofTrueTypeFont alphabets

To load a true type font in 0.10 you can now do:


ofTrueTypeFontSettings settings("EmojiSymbols-Regular.ttf", 64);
settings.antialiased = true;
settings.dpi = 72;
settings.direction = OF_TTF_LEFT_TO_RIGHT;
settings.addRanges(ofAlphabet::Emoji);
ttf.load(settings);
...

ttf.drawString("🍱 🍲 🍳 🍴 🍵 🍶 🍷 🍸 🍹 🍺", 20, 100);

which looks like:



Or:

ofTrueTypeFontSettings settings("Noto Sans CJK JP", 32);
settings.antialiased = true;
settings.dpi = 72;
settings.direction = OF_TTF_LEFT_TO_RIGHT;
settings.addRanges(ofAlphabet::Japanese);
ttf.load(settings);
...
ttf.drawString(
"色はにほへど 散りぬるを\n\
我が世たれぞ 常ならむ\n\
有為の奥山  今日越えて\n\
浅き夢見じ  酔ひもせず", 20, 60);
image

This one using a font installed in the system by it’s name.


You can setup a font with any unicode range and it’ll preload those characters in a texture so it’s faster to draw them.

Instead of having to figure out each unicode range there’s a set of predefined alphabets that you can pass to addRanges, right now:


ofAlphabet::Emoji;
ofAlphabet::Japanese;
ofAlphabet::Chinese;
ofAlphabet::Korean;
ofAlphabet::Arabic;
ofAlphabet::Devanagari;
ofAlphabet::Latin;
ofAlphabet::Greek;
ofAlphabet::Cyrillic;

Let us know if any of them is wrong or you want us to add any that is missing!

There’s still one thing that is not working yet, ligatures, some alphabets like arabic join some combinations of characters, that’s still not working but there’s tools that you can use to reshape the text and paste it into you OF code (like: http://mpcabd.xyz/python-arabic-text-reshaper/). We’ll try to figure this one out for next release

Arturo


ps: Thanks to Hiroshi Matoba for his help with the Japanese example and figuring out a couple of missing characters in the Japanese alphabet

ofxGui new features

The first post in the series about the new features in the 0.10.0 release, is going to be a short one about the gui.

Color picker

Up until 0.9.8 editing colors in the gui could only be done by adjusting the different rgb values using individual sliders which was not very intuitive:

In 0.10.0 it looks like this:

The new color picker is based on ofxColorPicker by Lukasz Karluk adapted to work with ofxGui and ofParameter

Text fields

In 0.10.0 ofxGui will add a text field for any ofParameter or you can create it manually using ofxInputField.

This new control is based on the original ofxInputField by Felix Lange with additions to better support selection, utf8 and clipboard.

Additionally any slider can be turned into an input field temporarily by right clicking on it, allowing for much more precise input.

Apart from this, one can now add an ofParameter<void> in a parameter group to get a button, add listeners to the save and load buttons to override the default save and load behavior:

panel.savePressedE.addListener([this]{
    // custom save

    return true; // to mark the event as attended 
                 // so the gui doesn't do the default save
});

panel.loadPressedE.addListener([this]{
    // custom load

    return true; // to mark the event as attended 
                 // so the gui doesn't do the default load
});

Also specifying a “.json” file when creating a panel instead of an “.xml” will load and save from json.

Arturo

2015/2016 Community Survey

Hi all,

The annual community survey is live! This survey helps us get information about how people are using openFrameworks, who our community is, and how we can best continue development and support.

It’s helpful to hear from everyone who’s using OF – so if you’re a total beginner, a longtime expert, a community organizer, a programmer, a student, etc – all opinions are appreciated! If you’ve filled out the survey in past years, we’d love for you to complete this year’s too.

The survey is published in several languages; feel free to fill out the survey in the language of your choice and the results will be aggregated together.

SURVEY IN ENGLISH:

http://goo.gl/forms/TnjXZE4Egr

ENCUESTA EN ESPAÑOL:

http://goo.gl/forms/FIWczPbe0h

SONDAGE EN FRANÇAIS:

http://goo.gl/forms/uV2sH2gS2R

UMFRAGE AUF DEUTSCH:

http://goo.gl/forms/JDhT9rquPJ

日本語での調査:

http://goo.gl/forms/e5zxj6TWNF

在中国调查:

http://goo.gl/forms/cf7LH7dvkF

Thanks from the OF team!

openFrameworks 0.9.0: ofThreadChannel, UTF-8 and ofSoundBuffer

OF 0.9.0 Overview Part 1 - Major Changes
OF 0.9.0 Overview Part 2 - OpenGL 4.5
OF 0.9.0 Overview Part 3 - Multi-window and ofMainLoop
OF 0.9.0 Overview Part 4 - ofThreadChannel and UTF-8 support

ofThreadChannel

Multi-threaded applications are more and more common given that most computers and devices have more than one CPU.

Threading is useful if we have a process-intensive task that we don’t want to interfere with the main thread’s task which is usually drawing at 60fps. Threading provides a way to continue drawing quickly and allowing process-intensive tasks to continue in the background. Once a background task is complete, the data or result can be accessed from the main thread.

Keep reading