Intro to FLTK and GLM

by asperling on February 12, 2015

Make sure you have Visual Studio set up on your computer before doing this tutorial. See the first Visual Studio tutorial for details.

Getting Started

We have provided a zip package of all the tools we will use for the projects. Download it here and extract it to your Program Files (x86) directory.

Note: putting libraries in your Program Files directory is only for getting your personal machine set up to be like the CSL machines. For yourself, you might prefer to put the libraries in different places – but putting them in the same place as CSL does will save you hassle when you go to move your code to the lab machines (which you will have to do to turn projects in).

You can then download our 559 Base Project, which should have all the correct configuration options set properly. This project was made with Visual Studio 2013, so it will be compatible with the software in the CSL. (It probably won’t get used for actual class projects, but it’s nice to have.)

An aside on Visual Studio projects:

While the Base Project has everything you need to start an OpenGL/FLTK project, sometimes (ok…most of the time) your setup at home will be different than the labs. In the labs, FLTK and GLM were located in Program Files (x86) while Glew was in Program Files for some reason. It’s important to know how to set project properties so Visual Studio recognizes the libraries.

There are four relevant changes to make to the Project Properties (right click the project name -> properties):

  1. Make sure the “Configuration” setting at the top left is set to “All Configurations” and not “Active(Debug),” so your changes apply to both the Debug and Release project configurations.
  2. In the C++(General) menu, edit the “Additional Include Directories” to point to where you have the FLTK, GLM, and Glew include files. See the base project for examples.
  3. In the Linker(General) menu, edit the “Additional Library Dependencies” in a similar way to point to the relevant .lib files.
  4. In the Linker(Input) menu, add the names of the needed library files to the “Additional Dependencies” field. Usually, these will be some FLTK and Glew libraries, but it will vary with each project.

FLTK

Note: You won’t have to learn much about FlTk. We’ll give you framework code for the projects that use it and do most of what you need.

FLTK (Fast Light Toolkit) is the window manager we will use this semester. Past semesters have used tools such as freeGLUT to create windows, but FLTK has additional functionality. FLTK allows you to have on-screen buttons, sliders, menus, and more along with a fully interactive OpenGL window.

To get a sense of how FlTk works, especially how it interacts with OpenGL, there are tutorials from the 2007 edition of the class. FlTk hasn’t really changed. The stuff about setting up Visual Studio 2005 projects is a bit different, but you can look at the Base project for how to do it with 2013. The OpenGL Survival Guide is recommended reading.

The FLTK “Hello World”

#include <FL/Fl.H>
#include <FL/Fl_Window.H>

int main(int argc, char * argv[]) {
    Fl_Window myWindow(800, 600, "Hello World");
    myWindow.show();
    return Fl::run();
}

If Visual Studio is configured correctly, running this program should display an 800×600 window with “Hello World” as the title and absolutely nothing inside! That’s boring, so let’s add some widgets. FLTK calls things like buttons and sliders “widgets,” and they all must be included individually just like the Fl_Window class.

#include <FL/Fl_Button.H>

Creating a button is just like creating a window:

[in main]
Fl_Button myButton(10, 10, 100, 25, "Push me!");

The arguments to the button’s constructor are it’s position (x,y), dimensions (w,h), and a title. In order for the button to do anything, we need to add a callback function. Callback functions are run every time an “event” happens, and in this case, the event is a button press.


#include <iostream>

void ButtonPress(Fl_Widget * w, void * userData) {
    std::cout << "Button pressed!" << std::endl;
}

...
[in main]
myButton.callback(ButtonPress);

Pressing the button will now display “Button pressed!” in the console screen. More information about common widgets (and everything else about FLTK) can be found in the online documentation.

While buttons are fun to play with, we actually want a space to draw things on the screen. (This is a graphics class after all!) For that purpose, FLTK provides a widget called Fl_Gl_Window. Fl_Gl_Windows are not as simple to add as buttons; they must be implemented in a custom class first:

[in a my_GL_Window.h file]

#include <FL/Fl_Gl_Window.H>

class my_Gl_Window : public Fl_Gl_Window { // For those unfamiliar, this is how you extend a class in C++
public:
    my_Gl_Window( int x, int y, int w, int h, const char * label = 0); // a basic constructor

    // the only 2 required functions are draw() and handle()
    virtual void draw();
    virtual int handle(int);
    // more public functions can be added as needed

private:
    // private members are added here as needed
}

This is only a taste of what FLTK can do. We will actually implement the draw() function and get to some real OpenGL in the lab.

GLM

Many of you have already used GLM in your assignments, but here is a very basic introduction in case you have not used it before. The complete documentation can be found here.

The two main data types you’ll want to focus on are vec3 (3D vector) and mat4 (4×4 matrix). As you’ve seen in class, we use these a lot in graphics. GLM provides some handy functions for using and manipulating vectors and matrices.

#include <glm/glm.hpp>

using namespace glm; // if you don't want to type glm:: before every matrix and vector

int main(int argc, char * argv[]) {
    // declare some vectors of floats
    vec3 a(1.0f,0,0);
    vec3 b(0,1.0f,0);
    vec3 c(0,0,1.0f);

    float d = distance(a,b); // find the distance between 2 vectors

    mat4 m(1.0f); // fill a 4x4 matrix with 1's
    mat4 n(3.0f);

    float x = dot(a,b); // take a dot product
    vec3 y = cross(b,c); // take a cross product
    mat4 z = m * n; // multiply matrices
    float z = determinant(m); // take the determinant

}

Previous post:

Next post: