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.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: