VR-Forces Development_Version Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
exampleOpenGLTransforms

Table of Contents

Overview

This example shows how to create an OpenGL application. This particular application demonstrates geometry transformation within the view. Geometry transforms do not affect the geometry itself, but instead change how it is displayed. Transforms may change the display of the geometry through translation, rotation, scaling and shearing. This example demonstrates only translation and rotation.

The VR-Vantage architecture consists of many layers and at its lowest level is OpenGL. Although it is rare that a developer will have to program at this level we provide a few examples anyway.

Example details

The application creates three separate pieces of geometry for display; a flat polygon representing a ground-plane, a cube and a pyramid. When run, the cube should sit on top of the ground plane with the pyramid sitting on top of the cube. Both the cube and the pyramid revolve in a circle around the center of the scene, and the pyramid rotates around its own axis, spinning on top of the cube.

Of particularly interest in this tutorial is that the three pieces of geometry are all created in the same space, at the center of the sceen. The polygon, the cube and the pyramid all have their local origins at the same location. Even though the three objects are 'modeled' in the same space, they are separated and positioned in the scene using glTranslate and glRotate transformations.

The application is organized into three main sections. First is a section that defines the shape of the objects and helper functions to draw them. The second section has functions for setting up and rendering the scene. Last is the main function which initializes OpenGL and then runs the main loop.

The geometry is defined by a set of vertices.

GLfloat cubeVert[8][3] =
{
{-0.5f, 0.5f, 0.5f}, // 0 left back top
{-0.5f, -0.5f, 0.5f}, // 1 left front top
{ 0.5f, -0.5f, 0.5f}, // 2 right front top
{ 0.5f, 0.5f, 0.5f}, // 3 right back top
{-0.5f, 0.5f, -0.5f}, // 4 left back bottom
{-0.5f, -0.5f, -0.5f}, // 5 left front bottom
{ 0.5f, -0.5f, -0.5f}, // 6 right front bottom
{ 0.5f, 0.5f, -0.5f} // 7 right back bottom
};

These vertices only define points in space, they do not define the faces of the geometry. Faces are defined by the order of vertices making up the edges of each face.

GLint cubeFace[6][4] =
{
{0, 1, 2, 3}, // top
{7, 6, 5, 4}, // bottom
{0, 4, 5, 1}, // left
{2, 6, 7, 3}, // right
{1, 5, 6, 2}, // front
{3, 7, 4, 0} // back
};

Each face is drawn by specifying the type of geometry primitive and the order of the vertices for that primitive.

When drawing the objects, the vertex values generally are not changed, rather transformation are used to position and orient the objects in the scene. This snippet from the display() function spins the pyramid, and places it on top of the cube, then moves both the cube and the pyramid away from the center of the scene and revolves both around the scene's center.

glPushMatrix(); // push the matrix once
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f); // revolve objects around origin
glTranslatef(-4.0f, 0.0f, 0.0f); // move objects away from origin
drawCube(); // draw just the cube
glPushMatrix(); // push the matrix a second time
glTranslatef(0.0f, 0.0f, 1.0f); // move pyramid ontop of cube
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f); // spin pyramid around its axis
drawPyramid(); // draw just the pyramid
glPopMatrix(); // pop back to the first matrix
glPopMatrix(); // pop back to the original matrix

The main function is used to initialize OpenGL and specify which function callbacks to call when rendering before starting the main loop.

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

Building the Example

VR-Vantage includes pre-built versions of the example application. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.

Running the Example

This example is an application. You can run it by running ./bin/exampleOpenGLTransforms.exe (on Windows) or ./bin/exampleOpenGLTransforms (on Linux). For more information about running examples, please see Running Applications and Examples.

Learn More

Example Source Files


exampleOpenGLTransforms.cxx

/******************************************************************************
** Copyright (c) 2012 MAK Technologies, Inc.
** All rights reserved.
******************************************************************************/
// This example creates three geometry objects, a 'ground' polygon, a cube
// and a pyramid. The three objects are each modeled around the scene
// origin. Each object is placed in the scene using glTranslate and glRotate
// transformations. The geometry is animated such that the ground-polygon
// stays fixed in space, the cube sits on top of the ground-polygon revolving
// around the center of the scene, and the pyramid spins on top of the cube,
// revolving with the cube and also rotating around its own axis.
#ifdef _WIN32
#include <windows.h>
#else
// On Linux we need to regulate the rendering speed of rotation.
#include <cerrno>
#include <time.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <iostream>
#include <string>
// The rotation angle for both the cube and pyramid. This value holds an
// angle (in degrees) that is incremented every draw-frame. This angle is
// used to both revolve the cube and pyramid around the scene, and rotate
// (spin) the pyramid while it is revolving.
GLfloat rotAngle = 0.0f;
// Some general colors are defined to color the faces of each object.
GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
GLfloat green[] = {0.0f, 1.0f, 0.0f, 1.0f};
GLfloat blue[] = {0.0f, 0.0f, 1.0f, 1.0f};
GLfloat yellow[] = {1.0f, 1.0f, 0.0f, 1.0f};
GLfloat cyan[] = {0.0f, 1.0f, 1.0f, 1.0f};
GLfloat magenta[] = {1.0f, 0.0f, 1.0f, 1.0f};
GLfloat dark_red[] = {0.5f, 0.0f, 0.0f, 1.0f};
GLfloat dark_green[] = {0.0f, 0.5f, 0.0f, 1.0f};
GLfloat dark_blue[] = {0.0f, 0.0f, 0.5f, 1.0f};
GLfloat dark_yellow[] = {0.5f, 0.5f, 0.0f, 1.0f};
GLfloat dark_cyan[] = {0.0f, 0.5f, 0.5f, 1.0f};
GLfloat dark_magenta[] = {0.5f, 0.0f, 0.5f, 1.0f};
// Vertices are defined to specify the corners of the cube.
// Notice that these vertices define a unit-cube modeled around
// the origin (x=0, y=0, z=0).
GLfloat cubeVert[8][3] =
{
{-0.5f, 0.5f, 0.5f}, // 0 left back top
{-0.5f, -0.5f, 0.5f}, // 1 left front top
{ 0.5f, -0.5f, 0.5f}, // 2 right front top
{ 0.5f, 0.5f, 0.5f}, // 3 right back top
{-0.5f, 0.5f, -0.5f}, // 4 left back bottom
{-0.5f, -0.5f, -0.5f}, // 5 left front bottom
{ 0.5f, -0.5f, -0.5f}, // 6 right front bottom
{ 0.5f, 0.5f, -0.5f} // 7 right back bottom
};
// Arrays of indices to the vertices define the faces of the cube.
// Each sub-array defines the order of verticies making up one
// face of the cube. There is one sub-array for each face.
GLint cubeFace[6][4] =
{
{0, 1, 2, 3}, // top
{7, 6, 5, 4}, // bottom
{0, 4, 5, 1}, // left
{2, 6, 7, 3}, // right
{1, 5, 6, 2}, // front
{3, 7, 4, 0} // back
};
// An array of color values is used to color each face of the cube.
// There is one color per face.
GLfloat* cubeColor[6] =
{
red, // top
red, // bottom
green, // left
green, // right
blue, // front
blue // back
};
// The function to draw a cube. This function draws each face of the
// cube as a GL_QUAD (a four point polygon) using the vertices defined
// above, ordered by the indices of the cube-face.
void drawCube()
{
// For each face in cubeFace...
for (int i = 0; i < 6; ++i)
{
// Set the color for the face
glColor4fv(cubeColor[i]);
// Draw the face using the vertices in cubeVert
// in the order defined by cubeFace[i] where i is
// the index of each face.
glBegin(GL_QUADS);
glVertex3fv(cubeVert[ cubeFace[i][0] ]);
glVertex3fv(cubeVert[ cubeFace[i][1] ]);
glVertex3fv(cubeVert[ cubeFace[i][2] ]);
glVertex3fv(cubeVert[ cubeFace[i][3] ]);
glEnd();
}
}
// Vertices are defined to specify the corners of the pyramid.
// Notice that these vertices are modeled around the origin (x=0, y=0, z=0).
GLfloat pyramidVert[8][3] =
{
{ 0.0f, 0.0f, 0.5f}, // 0 peak
{-0.5f, 0.5f, -0.5f}, // 1 base left back
{-0.5f, -0.5f, -0.5f}, // 2 base left front
{ 0.5f, -0.5f, -0.5f}, // 3 base right front
{ 0.5f, 0.5f, -0.5f} // 4 base right back
};
// Arrays of indices to the vertices define the faces of the pyramid.
// Each sub-array defines the order of verticies making up one
// face of the pyramid. There is one sub-array for each face.
// The base of the pyramid is a square made up of two triangles.
GLint pyramidFace[6][3] =
{
{1, 4, 2}, // base_1
{2, 4, 3}, // base_2
{1, 2, 0}, // left
{3, 4, 0}, // right
{2, 3, 0}, // front
{4, 1, 0} // back
};
// An array of color values is used to color each face of the pyramid.
// There is one color per face.
GLfloat* pyramidColor[6] =
{
yellow, // bottom_1
yellow, // bottom_2
cyan, // left
cyan, // right
magenta, // front
magenta // back
};
// The function to draw a pyramid. This function draws each face of the
// pyramid as a GL_TRIANGLE (a three point polygon) using the vertices
// defined above, ordered by the indices of the pyramid-face.
void drawPyramid()
{
// For each face in pyramidFace...
for (int i = 0; i < 6; ++i)
{
// Set the color for the face
glColor4fv(pyramidColor[i]);
// Draw the face using the vertices in pyramidVert
// in the order defined by pyramidFace[i] where i is
// the index of each face.
glBegin(GL_TRIANGLES);
glVertex3fv(pyramidVert[ pyramidFace[i][0] ]);
glVertex3fv(pyramidVert[ pyramidFace[i][1] ]);
glVertex3fv(pyramidVert[ pyramidFace[i][2] ]);
glEnd();
}
}
// The function to draw a ground-polygon. The polygon is drawn as a single
// GL_QUAD. Notice that this polygon is hard-coded to be modeled around the
// scene origin (x=0, y=0, z=0).
void drawPolygon()
{
// Set the color for the polygon
glColor4fv(dark_green);
// Draw a 10x10 polygon hard-coded around the origin in the z=0.0 plane.
glBegin(GL_QUADS);
glVertex3f(-5.0, 5.0, 0.0);
glVertex3f(-5.0, -5.0, 0.0);
glVertex3f( 5.0, -5.0, 0.0);
glVertex3f( 5.0, 5.0, 0.0);
glEnd();
}
#ifndef _WIN32
// Helper function used to regulate rendering rates for rotation on Linux.
// This function sleeps the thread for the given amount of milliseconds.
void msleep(unsigned long msec)
{
struct timespec req = {0};
time_t sec = (int)(msec / 1000.0);
msec = msec - sec * 1000;
req.tv_sec = sec;
req.tv_nsec = msec * 1000000L;
while (nanosleep(&req, &req) == -1 && errno == EINTR) {}
}
#endif
// This function is the workhorse that draws the scene. It first positions
// the eyepoint to see the objects in the scene. Then it positions and draws
// each object. It then tells OpenGL to render the scene. Finally it does
// some quick math to move all the objects the next time the scene gets
// rendered. This function is repeatedly called to refresh and redraw the
// scene.
void display()
{
#ifndef _WIN32
// On Linux, only update at 24 frames per second.
msleep((unsigned long)((1.0 / 24.0) * 1000.0));
#endif
// Set the matrix mode for geometry
glMatrixMode(GL_MODELVIEW);
// Position the eyepoint
glLoadIdentity();
gluLookAt(7.0f, 7.0f, 7.0f, // eyepoint
0.0f, 0.0f, -1.0f, // target at (0,0,-1)
0.0f, 0.0f, 1.0f); // up is in positive Z direction
// Clear the buffers each frame
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Translate and draw the ground polygon
glPushMatrix();
glTranslatef(0.0f, 0.0f, -0.5f); // push the geometry down a little
drawPolygon(); // draw the ground-plane
glPopMatrix();
// Translate and draw both the cube and pyramid
glPushMatrix(); // push the matrix once
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f); // revolve objects around origin
glTranslatef(-4.0f, 0.0f, 0.0f); // move objects away from origin
drawCube(); // draw just the cube
glPushMatrix(); // push the matrix a second time
glTranslatef(0.0f, 0.0f, 1.0f); // move pyramid ontop of cube
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f); // spin pyramid around its axis
drawPyramid(); // draw just the pyramid
glPopMatrix(); // pop back to the first matrix
glPopMatrix(); // pop back to the original matrix
// Swap buffers, flush rendering, and request this function called again
glutSwapBuffers();
glFlush();
glutPostRedisplay();
// Increment the rotation angle for next frame
rotAngle += 1.0f;
if (rotAngle >= 360.0f) rotAngle = 0.0f;
}
// This function (re)initializes the viewport to the scene.
// When called it sets the viewport to the scene to fill the window, and
// sets the view to be perspective (objects get smaller the further away
// they are from the eye-point). This function is called once when the
// window is created and again everytime the window is resized.
void reshape(int width, int height)
{
// Size the viewport to fill the window
glViewport(0, 0, width, height);
// Setup to be a perspective view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (float)width / (float)height, 0.1f, 50.0f);
}
// This function initialize how the scene will be displayed in the window.
// This is only called once for the application.
void init()
{
// Set the display mode to use double-buffering, a color buffer
// and a depth buffer.
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Create a window to draw in and give it a window title
glutCreateWindow("Transforming cube and pyramid");
// Set the color that when clearing the screen
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
// Use depth buffering for hidden surface culling
glEnable(GL_DEPTH_TEST);
}
// The main function initializes OpenGL and how the window is displayed,
// sets a function to be called if the window is resized, sets a function
// to call to draw the scene, then starts the main rendering loop.
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}

Document ID: Generated on Tue Mar 8 22:13:38 EST 2016 from SVN revision 162938
Copyright © 2005-2015 VT MÄK. All Rights Reserved (www.mak.com)