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.
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.
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.
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.
The main function is used to initialize OpenGL and specify which function callbacks to call when rendering before starting the main loop.
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.
#ifdef _WIN32
#include <windows.h>
#else
#include <cerrno>
#include <time.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <iostream>
#include <string>
GLfloat rotAngle = 0.0f;
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};
GLfloat cubeVert[8][3] =
{
{-0.5f, 0.5f, 0.5f},
{-0.5f, -0.5f, 0.5f},
{ 0.5f, -0.5f, 0.5f},
{ 0.5f, 0.5f, 0.5f},
{-0.5f, 0.5f, -0.5f},
{-0.5f, -0.5f, -0.5f},
{ 0.5f, -0.5f, -0.5f},
{ 0.5f, 0.5f, -0.5f}
};
GLint cubeFace[6][4] =
{
{0, 1, 2, 3},
{7, 6, 5, 4},
{0, 4, 5, 1},
{2, 6, 7, 3},
{1, 5, 6, 2},
{3, 7, 4, 0}
};
GLfloat* cubeColor[6] =
{
red,
red,
green,
green,
blue,
blue
};
void drawCube()
{
for (int i = 0; i < 6; ++i)
{
glColor4fv(cubeColor[i]);
glBegin(GL_QUADS);
glVertex3fv(cubeVert[ cubeFace[i][0] ]);
glVertex3fv(cubeVert[ cubeFace[i][1] ]);
glVertex3fv(cubeVert[ cubeFace[i][2] ]);
glVertex3fv(cubeVert[ cubeFace[i][3] ]);
glEnd();
}
}
GLfloat pyramidVert[8][3] =
{
{ 0.0f, 0.0f, 0.5f},
{-0.5f, 0.5f, -0.5f},
{-0.5f, -0.5f, -0.5f},
{ 0.5f, -0.5f, -0.5f},
{ 0.5f, 0.5f, -0.5f}
};
GLint pyramidFace[6][3] =
{
{1, 4, 2},
{2, 4, 3},
{1, 2, 0},
{3, 4, 0},
{2, 3, 0},
{4, 1, 0}
};
GLfloat* pyramidColor[6] =
{
yellow,
yellow,
cyan,
cyan,
magenta,
magenta
};
void drawPyramid()
{
for (int i = 0; i < 6; ++i)
{
glColor4fv(pyramidColor[i]);
glBegin(GL_TRIANGLES);
glVertex3fv(pyramidVert[ pyramidFace[i][0] ]);
glVertex3fv(pyramidVert[ pyramidFace[i][1] ]);
glVertex3fv(pyramidVert[ pyramidFace[i][2] ]);
glEnd();
}
}
void drawPolygon()
{
glColor4fv(dark_green);
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
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
void display()
{
#ifndef _WIN32
msleep((unsigned long)((1.0 / 24.0) * 1000.0));
#endif
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(7.0f, 7.0f, 7.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -0.5f);
drawPolygon();
glPopMatrix();
glPushMatrix();
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f);
glTranslatef(-4.0f, 0.0f, 0.0f);
drawCube();
glPushMatrix();
glTranslatef(0.0f, 0.0f, 1.0f);
glRotatef(rotAngle, 0.0f, 0.0f, 1.0f);
drawPyramid();
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
glFlush();
glutPostRedisplay();
rotAngle += 1.0f;
if (rotAngle >= 360.0f) rotAngle = 0.0f;
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (float)width / (float)height, 0.1f, 50.0f);
}
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Transforming cube and pyramid");
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
glEnable(GL_DEPTH_TEST);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}