Archive for the ‘ OpenGL ’ Category

OpenGL Camera


The concept of a camera in a Graphics application is simple. Just imagine that what you see is the view of the camera. So adjusting the camera lens or moving\rotating it should affect your view. In the base OpenGL library, there is no concept of a camera. However, it can be simulated by applying the inverse of the camera transformation on the objects\pixels in the scene. Instead of having to build the matrix and invert it ourselves, the GLU library provides the gluLookAt function, which would do the work for us. This function takes as a parameter the location (x, y, z) of the camera\eye, the location (x, y, z) of the point to look at, and the coordinates (x, y, z) of the Up vector (rotation of the camera around its origin). Note that this function should be called on the ModelView matrix before any transformation is applied on objects in the scene. Avoid calling this function on the Projection matrix (more details here).

Given the description above, after specifying the camera attributes with a call to gluLookAt then drawing the objects in the scene, one would expect to see the objects in the scene based on the view of the camera. This expectation is completely valid, however, there is one more variable that affects what we see: the viewing volume (similar to real-world camera focus), which is controlled by calls on the projection matrix. Try to imagine what you’ll see if you run the code below:

GLdouble eyeX = 0, eyeY = 0, eyeZ = 2;
GLdouble centerX = 0, centerY = 0, centerZ = 0;
GLdouble upX = 0, upY = 1, pZ = 0;

void display()
{
    //  Set up camera properties
    glMatrixMode (GL_MODELVIEW);
    gluLookAt (eyeX, eyeY, eyeZ,
               centerX, centerY, centerZ,
               upX, upY, upZ);

    //  Draw an Object at the origin
    drawObject ();
}

The answer to the question above is that you’ll see nothing! The reason is that eyeZ = 2, the viewing volume is glOrtho(-1, 1, -1, 1, -1, 1) by default, and the object is drawn at the origin. Here is a visual demonstration using Nate Robin’s interactive OpenGL tutorial (projection.exe).

If we change zFar (last parameter of glOrtho) of projection to 3 or if we change eyeZ of the camera to 0.5, then we’ll be able to see the object.

To summarize all of this, I am taking advantage of one of the slides of the Siggraph OpenGL tutorial.

If you’ve used one of those 3D modeling software out there (like 3ds Max, Maya, etc…), then you’ve certainly seen multiple orthogonal views (Front, Back, Top, Bottom, Left, Right) of your 3D drawing. Here is a screenshot from 3ds Max.

Using the OpenGL camera, I’m going to create an OpenGL app that has 6 sub-windows each displaying the same object, but from a different camera angle. The world coordinates will be glOrtho(-1, 1, -1, 1, -2, 2) and the views will be: Front, Back, Top, Bottom, Left, and Right. The parameters that are going to be passed to gluLookAt will vary based on the view:

The program looks as follows.

Note that you can use the left mouse button to rotate the object, right mouse button to translate the object, and middle mouse button to scale it. Also, the ‘r’ key will reset the object transformations in the scene. You can find the full source code here. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library.

GLUT Menu World


This post demonstrates how to create a GLUT menu and add to it sub-menus and menu items.

In the above sample app, clicking on a menu item in the popup menu will log that menu item’s ID to the console window. Below is the function setupMenus() that creates the main menu and adds to it all the sub-menus and menu items. You can change it based on your needs then call it in the init() method.

//-------------------------------------------------------------------------
//  Set up the GLUT Menus.
//-------------------------------------------------------------------------
void setupMenus ()
{
    int subMenuCount;  //  Count of sub menus
    int menuItemCount; //  Count of menu items in a submenu
    int *menuIds;      //  Submenu IDs
    char str[256];     //  The string of the current menu item
    int i, j;          //  Iterators

    //  Generate a random value for submenu count
    subMenuCount = rand() % 20;

    //  Allocate memory for the submenu IDs
    menuIds = (int *) xmalloc (subMenuCount * sizeof (int));

    //  Create all the sub menus
    for (i = 0; i < subMenuCount; i++)
        menuIds[i] = glutCreateMenu (showMenuItem);

    for (i = 1; i < subMenuCount; i++)
    {
        //  Set sub menu string
        sprintf (str, "SubMenu %d", i);

        //  Add the current submenu to previous submenu
        glutSetMenu (menuIds[i-1]);
        glutAddSubMenu (str, menuIds[i]);

        //  New menu item count for the new submenu
        menuItemCount = rand () % 20;

        //  Add menu items to the current submenu
        for (j = 1; j < menuItemCount; j++)
        {
            sprintf (str, "Menu Item %d", j);
            glutAddMenuEntry (str, j);
        }
    }

    //  Set main menu as the current menu
    glutSetMenu (menuIds[0]);

    //  Attach the menu to the RMB
    glutAttachMenu(GLUT_RIGHT_BUTTON);
}

Major GLUT functions briefly explained:

  • glutCreateMenu creates the main menu or sub-menu and returns its ID. It takes as a parameter a pointer to a function with the signature void func (int menuItemId). This function is called every time the  user clicks a menu item in the menu and the parameter menuItemId passed to it represents the id of the menu item.
  • glutAddSubMenu adds another menu to current menu.
  • glutAddMenuEntry adds a menu item to the current menu.
  • glutSetMenu sets the current menu. So when we call glutAddSubMenu or glutAddMenuEntry, they get added to the current menu.
  • glutAttachMenu(GLUT_RIGHT_BUTTON) attaches the “current” menu to the right click button. So when you right click the mouse, the popup menu will show up.

This is the function that we are passing to glutCreateMenu in our sample app. Every time the user clicks on a menu item, this function is called and it will simply display the menu item id on the console window.

//-------------------------------------------------------------------------
//  Displays the menu item id on the console window
//-------------------------------------------------------------------------
void showMenuItem (int val)
{
    printf ("Menu Item: %d\n", val);
}

Download the full source code here.

OpenGL Color Interpolation


Using the GL_LINES mode, OpenGL will draw for us a line for every two vertices we specify.

glBegin (GL_LINES);

    glColor3f  (1, 0, 0);
    glVertex2f (x0, y0);
    glColor3f  (0, 0, 1);
    glVertex2f (x1, y1);

glEnd ();

Behind the scenes, OpenGL is using interpolation to draw the line. That is, given 2 points, OpenGL will determine the set of pixels that the line would cross through and then change their color based on the color of the line. Bresenham‘s algorithm is a famous algorithm for drawing lines, and it (or some extension of it) is probably the one used internally by OpenGL.

Using the basic linear equation we all learned in school (y = ax + b), we should be able to get to an algorithm that draws the points across the lines. We are drawing a line segment from vertex v0 (x0, y0) to vertex v1 (x1, y1). Let’s denote any point across the line as vertex v with coordinates (x, y). Given those three vertices, we can build the following 3 independent equations.

Now, we should try to create some relationship between those 3 independent equations and try to get rid of the unknowns a and b. Let’s first try to get rid of b.

Let’s try y – y0 and y1 – y0, we will get the following two independent equations.

Now, let’s try to create a relationship between those 2 independent equations and at the same time try to get rid of a.

We can now sample some values of x between x0 and x1 and get the value of y using the above equation. This is the basic idea behind drawing a line. In addition to drawing the line, OpenGL is also doing something else behind the scenes: Color Interpolation. If you run the above code sample in OpenGL, you’ll see the following line:

As points are moving from vertex v0 to vertex v1, their color is also transitioning from v0 color to v1 color. This is handled by the OpenGL Smooth shading model. OpenGL supports two shading models: Smooth and Flat. Flat shading means that no shading calculations are performed on the interior of the primitives. The color of the interiors is the color of the last vertex specified. You can set it by calling glShadeModel (GL_FLAT). Smooth shading is thedefault shading model in OpenGL and you can explicitly set it by calling glShadeModel (GL_SMOOTH).

Even though OpenGL automatically does color interpolation (in case of smooth shading), it would be interesting if we try to implement it and experiment a little bit with it.

To implement the linear interpolation of the points and their colors, we are going to use the below generic linear interpolation method, where u is any value we select from 0 to 1.

First, let’s define the point data structure.

//  Define the point data structure
typedef struct Point
{
    float x;                  //  x position of the point
    float y;                  //  y position of the point
    float z;                  //  z position of the point
    float r;                  //  red color component of the point
    float g;                  //  green color component of the point
    float b;                  //  blue color component of the point
    float a;                  //  alpha color component of the point
} Point;

Next we set the number N of how many points we want to sample on the line, and initialize the array that will hold the points.

//  represents the number of points the line consists of
#define N 250

//  Declare the array of points
Point linePoints[N];

Now, we generate the location and color components for the points on the line using the above linear interpolation formula.

//  Location and color interpolation
for (i = 0; i < N; i++)
{
    u = (float)i/(N - 1);

    linePoints[i].x = v0.x * (1.0 - u) + v1.x * u;
    linePoints[i].y = v0.y * (1.0 - u) + v1.y * u;
    linePoints[i].z = v0.z * (1.0 - u) + v1.z * u;
    linePoints[i].r = v0.r * (1.0 - u) + v1.r * u;
    linePoints[i].g = v0.g * (1.0 - u) + v1.g * u;
    linePoints[i].b = v0.b * (1.0 - u) + v1.b * u;
    linePoints[i].a = v0.a * (1.0 - u) + v1.a * u;
}

Finally, we draw this set of points.

glBegin (GL_POINTS);

for (i = 0; i < N; i++)
{
    glColor4f  (linePoints[i].r, linePoints[i].g, linePoints[i].b, linePoints[i].a);
    glVertex3f (linePoints[i].x, linePoints[i].y, linePoints[i].z);
}

glEnd ();

More implementation details are available in the full source code of this OpenGL app. You can use this app for experimenting with color interpolation and you might even notice how the OpenGL interpolation method is way faster than our simplistic implementation (if you have a machine with a relatively slow processor). If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library.

OpenGL Resolution


This is a simple OpenGL app that runs in full screen (game mode), shows every other pixel in alternating color, and displays the screen resolution (m x n grid of pixels) and the screen dimension in millimeters.


Note: The pixels are actually black and white, but because this screenshot is reduced in size, you see a gray background. Click on this image to see the full sized one.

The implementation is very simple. We use glutGet (GLUT_SCREEN_WIDTH) to get the screen width in pixels and glutGet (GLUT_SCREEN_HEIGHT) to get the screen height. To get the width and height in millimeters, we use glutGet (GLUT_SCREEN_WIDTH_MM) and glutGet (GLUT_SCREEN_HEIGHT_MM) consecutively. This would even tell us the width and height of a single pixel in millimeters. For example, pixel width in millimeters is equal to screen width in millimeters divided by the screen width in pixels. Same can be done for the height.

//-------------------------------------------------------------------------
//  Draw string representing the resolution of your screen
//-------------------------------------------------------------------------
void drawResolutionStr ()
{
    glColor3f (0, 0, 1);

    printw (20, 20, 0,
            "Resolution: %d x %d pixels, %d x %d mm",
            glutGet (GLUT_SCREEN_WIDTH), glutGet (GLUT_SCREEN_HEIGHT),
            glutGet (GLUT_SCREEN_WIDTH_MM), glutGet (GLUT_SCREEN_HEIGHT_MM));

    glColor3f (1, 0, 0);

    printw (20, 45, 0,
            "Pixel Dimensions: %.4f x %.4f mm",
            (float)glutGet (GLUT_SCREEN_WIDTH_MM) / glutGet (GLUT_SCREEN_WIDTH),
            (float)glutGet (GLUT_SCREEN_HEIGHT_MM) / glutGet (GLUT_SCREEN_HEIGHT));
}

You can find the full source code here. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library.

Download GL\GLUT\GLAUX\GLUI .lib, .h and .dll


Looking for the lib, header, or dll files for OpenGL, GLUT,  GLAUX or GLUI on Windows? I have collected them from different sources so they can be easily downloaded as a single package: http://cid-e38f9fc6490b29d9.skydrive.live.com/self.aspx/Public/GL%20Files.zip. It contains the following content:

Folder Files
dll
  • glu32.dll
  • glut32.dll
  • opengl32.dll
include\GL
  • gl.h
  • glu.h
  • glaux.h
  • glut.h
  • glui.h
Lib
  • opengl32.lib
  • glu32.lib
  • glaux.lib
  • glut.lib
  • glui.lib

Disclaimer: I have not created or modified any of those files, nor do I claim any ownership of them. They were simply collected from different sources and redistributed.

OpenGL Image Generator


The idea behind this post is very simple: generate m x n grid of pixels, with each pixel having a random color. Every time the user clicks the mouse or presses the ‘g’ key, a new random color is generated for each pixel. Since we are using the R, G and B components to represent a color, we can have up to 256 * 256 * 256 = 16,777,216 colors per pixel. Assuming m = 512 and n = 512, the total count of pixels is 512 * 512 = 2,704 pixels. The number of possible images that can be generated is 16,777,216 ^ 2,704 = 4.3913556324838811971996510547776e+19535. Suppose we are generating an image every 1 second, then it would take 1.4276931285385069435340105645214e+19528 years to generate all of the possible combinations, including images of our friends, nature, the past, the present, the future or some electronic gadget we have not yet invented. Well, a very unrealistic time. Limiting m x n to 16 x 16 and limiting colors to only black and white, we can generate up to 65,536 images in about 18 hours. Seems possible; maybe even worth doing.

The goal here is to demonstrate the usage of the glDrawPixels function to draw pixels in the frame buffer. First, we will create a 3-dimensional array representing m x n pixels having 3 color components.

GLubyte buffer[m][n][3];

Next, we need to generate random colors for each pixel.

//-------------------------------------------------------------------------
//  Generate new image with random colors
//-------------------------------------------------------------------------
void generateImage ()
{
    int i, j;

    for (i = 0; i < WINDOW_WIDTH; i++)
    {
        for (j = 0; j < WINDOW_HEIGHT; j++)
        {
            buffer[i][j][0] = (GLubyte) (rand () % 256);
            buffer[i][j][1] = (GLubyte) (rand () % 256);
            buffer[i][j][2] = (GLubyte) (rand () % 256);
        }
    }
}

Finally, we pass the buffer to the glDrawPixels, which will write the pixel data from the memory into the frame buffer.

void display ()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawPixels(m, n, GL_RGB, GL_UNSIGNED_BYTE, buffer);
    glutSwapBuffers ();
}

Download full source code here. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library.

OpenGL Frame Rate


Calculating the frames per second in our Graphics application makes sense when we are displaying animation, which is simply a collection of images displayed rapidly and in sequence.When we watch a video\movie, the usual number of frames displayed in a second is 24. Our eyes can’t see all the 24 frames one by one in a single second, and that’s why we get the illusion of something moving, rotating, or growing in size.

In this post, we are going to create an OpenGL app that animates an object and calculates the frames per second for that animation.

FPS

To make this calculation, we need to find a way to keep track of the number of frames and time elapsed. The key here is to do the calculation in the GLUT idle function (callback function passed to glutIdleFunc), which is called only when our application is not busy doing something else (such as drawing the current frame). So every time the idle function is called, we increment the frame count, check the time elapsed, and if the time is greater than or equal to 1 second, we calculate the FPS.

//-------------------------------------------------------------------------
//  This function is called when OpenGL\GLUT is not working on
//  something else... It is mainly used for animation...
//
//  It's like the timers but time intervals are dependent on how busy
//  the app is, instead of having a constant value set by the user.
//-------------------------------------------------------------------------
void idle (void)
{
    //  Animate the object
    animateObject();

    //  Calculate FPS
    calculateFPS();

    //  Call display function (draw the current frame)
    glutPostRedisplay ();
}

As you can see in the code above, the idle function is animating the object, calculating the FPS, then triggering the display function (callback function passed to glutDisplayFunc) by calling glutPostRedisplay().

The display function would basically display the object and text showing the FPS value.

//-------------------------------------------------------------------------
//  This function is passed to glutDisplayFunc in order to display
//	OpenGL contents on the window.
//-------------------------------------------------------------------------
void display (void)
{
    glClear (GL_COLOR_BUFFER_BIT);

    drawObject();
    drawFPS();

    glutSwapBuffers ();
}

To get the time elapsed, we use the glutGet(GLUT_ELAPSED_TIME) function which will get the time passed in milliseconds since the program started or since it was last called. The implementation of calculateFPS would look like this:

//-------------------------------------------------------------------------
// Calculates the frames per second
//-------------------------------------------------------------------------
void calculateFPS()
{
    //  Increase frame count
    frameCount++;

    //  Get the number of milliseconds since glutInit called
    //  (or first call to glutGet(GLUT ELAPSED TIME)).
    currentTime = glutGet(GLUT_ELAPSED_TIME);

    //  Calculate time passed
    int timeInterval = currentTime - previousTime;

    if(timeInterval > 1000)
    {
        //  calculate the number of frames per second
        fps = frameCount / (timeInterval / 1000.0f);

        //  Set time
        previousTime = currentTime;

        //  Reset frame count
        frameCount = 0;
    }
}

Download full source code here. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library. Toby Howard has a different implementation that is not dependent on GLUT. You can find it here.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: