![]() |
are you ready for a mindfuck? |
|
....::::Menu::::.... ---------------------------...::About::... ...::Articles::... ...::Contact::... ...::Home & News::... ...::Links & Credits::... --------------------------- --------------------------- |
An introduction to GLUTby Elie De BrauwerGoal of this file
This file offers a brief overview of what GLUT is and does and how you can use
GLUT to create and environment that is usefull for the output of an OpenGL application
and how to build these applications. This also contains a list of the most common GLUT
functions and procedures, the document is ended with two examples including screenshots. History of this file
What is GLUTIntroduction
GLUT is the OpenGL Utility Toolkit. GLUT is used in the development
of OpenGL applications. OpenGL is a graphics library which means that
it can do all sorts of things with geometric forms, lightings,
transformations etc. But OpenGL was designed to be portable so it can
be used within various environments / operating systems (Linux, Unix, Solaris,
Windows, Amiga,...) without changing the OpenGL code. SummaryNow, let's summarize, OpenGL is a standard, available on many platforms, it does everything that is related to graphics, it does not handle interaction with the window system. So a seperate library is needed, there are some alternatives but at this point I am using GLUT because the title of this document says so ;-). Using GLUTInstallationOn a default Debian machine GLUT is provided by the libglut3-dev package, the OpenGL files are provided by the xlibmesa-gl-dev package. helios@Kafka:~$ dpkg-query -S /usr/include/GL/glut.h libglut3-dev: /usr/include/GL/glut.h helios@Kafka:~$ dpkg-query -S /usr/include/GL/gl.h xlibmesa-gl-dev: /usr/include/GL/gl.h I presume you have the knowledge how to install these on your system or that you have these installed already. Header filesThere is a little extra advantage when using GLUT, if you were developing an OpenGL application you should include the header files gl.h and glu.h (glu is the OpenGL Utility Library) but when you are including glut.h, glut.h guarantees the inclusion of gl.h and glu.h. So when we start and OpenGL application we start by writing: #include <GL/glut.h> CompilationThe first easy programs using only some OpenGL commands and some glut function calls you should be able to compile using one of the following (normally the first one should work): helios@Kafka:~$ g++ -Wall -lglut -O test.cpp helios@Kafka:~$ g++ -Wall -lGL -lGLU -lglut -O test.cpp Here -l is a linker option stating to include the library followed the -l, -Wall is a way of saying the compiler that it should output all the warnings and -O says the compiler to use some optimisation techniques. If you want more information about these commands I'd suggest you read the g++/gcc manpages. Programming GLUTIntroductionSo this is what you have been waiting for, some action. Now I will cover the following subjects:
After you've been thru this you should have enough knowledge to use GLUT to create a window that is capable
of showing your OpenGL visualisation. If you are still in the need for more information I would advise to visit the
glut 3 specification page
on OpenGL.org, which contains information similar to the manpages. What you should know about windows and GLUT
What you should know about events and GLUTIn order to understand the following I will first explain what a callback is. When a certain event occurs you want a program to do something. So in case of event E call, method/function/procedure M. A callback just occured. Within this part you define which function has to be called when an event happens. (An event is something that happens: you move the mouse, press a key, resize the window,... mostly generated by the user). Now I will define the most commonly used GLUT callbacks.
Important note: You can undo most callbacks by passing NULL as the function name. What you should know about creating 3D objects in GLUTAnother advantage of glut is that glut has some pre defined primitives that you can put on the screen in an easy way. I will list the primitives below, most parameters speak for themselves. Each primitive comes in a solid or in a wireframe taste.
And last but not least, this renders a teapot. If you want to know more about the Utah teapot, try Google. What you should know about menus in GLUTThis sections covers the function calls needed to display popup menus. For a more practical example how to use these menus I suggest you look down at the end of this document to the YATWM example.
What you should know about about actually starting the program and displaying the windowYou can define all the callbacks you want, define the most beautiful scene filled with eyecandy but as long as you haven't entered the main loop nothing will happen, you won't even see the window. So basically you define the window, register the callbacks and enter the main loop by calling void glutMainLoop(void);. Now the window will appear, the idle function will be called and events will be registered. Putting it all together: YAT
The source code below, opens a window, clears it with a black color and draws a teapot, it listens to keyboard presses and
writes out the key that was pressed and the coordinates. The program terminates when the user presses "q". YAT is Yet
Another Teapot. You can find some screenshots below showing some of the other primitives.
#include <iostream>
#include <cstdlib>
#include <GL/glut.h>
using namespace std;
// function prototypes
void disp(void);
void keyb(unsigned char key, int x, int y);
// window identifier
static int win;
int main(int argc, char **argv){
//////////
// INIT //
//////////
// initialize glut
glutInit(&argc, argv);
// specify the display mode to be RGB and single buffering
// we use single buffering since this will be non animated
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
// define the size
glutInitWindowSize(500,500);
// the position where the window will appear
glutInitWindowPosition(100,100);
// if we would want fullscreen:
// glutFullScreen();
// create the window, set the title and keep the
// window identifier.
win = glutCreateWindow("Yet another teapot");
//////////////
// CALLBACK //
//////////////
glutDisplayFunc(disp);
glutKeyboardFunc(keyb);
////////////
// OPENGL //
////////////
// define the color we use to clearscreen
glClearColor(0.0,0.0,0.0,0.0);
// enter the main loop
glutMainLoop();
return 0;
}
void disp(void){
// do a clearscreen
glClear(GL_COLOR_BUFFER_BIT);
// draw something
glutWireTeapot(0.5);
// glutSolidTeapot(0.5);
// glutWireSphere(0.5,100,100);
// glutSolidSphere(0.5,100,100);
// glutWireTorus(0.3,0.5,100,100);
// glutSolidTorus(0.3,0.5,100,100);
// glutWireIcosahedron();
// glutSolidIcosahedron();
// glutWireDodecahedron();
// glutSolidDodecahedron();
// glutWireCone(0.5,0.5,100,100);
// glutSolidCone(0.5,0.5,100,100);
// glutWireCube(0.5);
// glutSolidCube(0.5);
}
void keyb(unsigned char key, int x, int y){
cout << "Pressed key " << key << " on coordinates (" << x << "," << y << ")";
cout << endl;
if(key == 'q'){
cout << "Got q,so quitting " << endl;
glutDestroyWindow(win);
exit(0);
}
}
You can also download the source, some screenshots of the results are visible below: ![]() ![]() ![]() Putting it even more together: YATWMYATWM = Yet Another Teapot With Menus, the example illustrates how to create and use popup menus. Here we create a main
menu that becomes active when the right mouse button is pressed, this menu also contains a submenu. This is basically the
YAT example except the keyboard callback to quit is replaced by the menu callback and we can now choose which primitive to
draw by selecting it from the menu instead of recompiling the code like we had to do with YAT. There is also a screenshot
available below. And just like YAT 2 gl methods had to be used.
#include <iostream>
#include <GL/glut.h>
#include <cstdlib>
using namespace std;
void createMenu(void);
void menu(int value);
void disp(void);
static int win;
static int menid;
static int submenid;
static int primitive = 0;
int main(int argc, char **argv){
// normal initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("GLUT MENU");
// put all the menu functions in one nice procedure
createMenu();
// set the clearcolor and the callback
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(disp);
// enter the main loop
glutMainLoop();
}
void createMenu(void){
//////////
// MENU //
//////////
// Create a submenu, this has to be done first.
submenid = glutCreateMenu(menu);
// Add sub menu entry
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// Create the menu, this menu becomes the current menu
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddSubMenu("Draw", submenid);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void disp(void){
// Just clean the screen
glClear(GL_COLOR_BUFFER_BIT);
// draw what the user asked
if(primitive == 1){
glutPostRedisplay();
}else if(primitive == 2){
glutWireTeapot(0.5);
}else if(primitive == 3){
glutWireCube(0.5);
}else if(primitive == 4){
glutWireTorus(0.3,0.6,100,100);
}
glFlush();
}
void menu(int value){
if(value == 0){
glutDestroyWindow(win);
exit(0);
}else{
primitive=value;
}
// you would want to redraw now
glutPostRedisplay();
}
You can also download the sourcecode, and a screenshot is available below.
The teapot strikes back: YATWTYATWT = Yet Another Teapot With Timers, the example illustrates how to create and use timers. Here we create a main window which is wite and contains a white shape (initial values, it can be easily changed that a random figure in a random color will be used), after that two timers are initialised one that runs 1 second and changes the color tot a random color and another timer that expires after 5 seconds and takes a shape out of 4 predefined possibilities. Here we had to use one extra OpenGL command which is glColor3f which changes the drawing/foreground color to the color we create after a timer is expired. For more information about the random() functions please refer to man srand and man rand on your system. Please note that after a timer has expired we reinitialise him.
#include <iostream> // for output
#include <cstdlib> // for exit and rand
#include <GL/glut.h> // for gl* glut*
#include <ctime> // for seeding rand()
using namespace std;
#define TEAPOT 0
#define TORUS 1
#define CUBE 2
#define SPHERE 3
/////////////////
// global vars //
/////////////////
static int object=1;
static int win;
static float r=1.0;
static float g=1.0;
static float b=1.0;
////////////////
// prototypes //
////////////////
void display(void);
void keyboard(unsigned char key, int x, int y);
void timerColor(int value);
void timerShape(int value);
//////////
// main //
//////////
int main(int argc, char **argv){
// init
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("YATWT");
// callback
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
// change color each second
glutTimerFunc(1000,timerColor,0);
// change the shape after five seconds
glutTimerFunc(5000,timerShape,0);
// clearcolor & main loop
glClearColor(1.0,1.0,1.0,0.0);
// seed random
// see `man srand` for the user of srand and random
time_t timer;
srand(time(&timer));
glutMainLoop();
return 0;
}
/////////////
// display //
/////////////
void display(void){
// clean te window
glClear(GL_COLOR_BUFFER_BIT);
// define the color in which te object has to be drawn
glColor3f(r,g,b);
// determine which object to draw
switch(object){
case TEAPOT:
glutSolidTeapot(0.5);
break;
case TORUS:
glutSolidTorus(0.25,0.50,100,100);
break;
case CUBE:
glutSolidCube(0.5);
break;
case SPHERE:
glutSolidSphere(0.5,100,100);
break;
}
glutSwapBuffers();
}
//////////////
// keyboard //
//////////////
void keyboard(unsigned char key, int x, int y){
if(key=='q'){
cout << "Quitting" << endl;
glutDestroyWindow(win);
exit(0);
}
}
////////////////
// timercolor //
////////////////
void timerColor(int value){
// get new color or a value in [0,1]
r = (1.0*(random()%256))/256.0;
g = (1.0*(random()%256))/256.0;
b = (1.0*(random()%256))/256.0;
// say what we are doing
cout << "New color is (" << r << "," << g << "," << b << ")" << endl;
// draw it + reinitialise timer
glutPostRedisplay();
glutTimerFunc(1000,timerColor,0);
}
////////////////
// timerShape //
////////////////
void timerShape(int value){
// generate new object
object = random()%4;
// say what we are doing
cout << "Next object will be a ";
switch(object){
case TEAPOT:
cout << "teapot" << endl;
break;
case TORUS:
cout << "torus" << endl;
break;
case CUBE:
cout << "cube" << endl;
break;
case SPHERE:
cout << "sphere" << endl;
break;
}
// draw it + reinitialise timer
glutTimerFunc(5000,timerShape,0);
}
You can also download the sourcecode.
#include <iostream> // for output
#include <cstdlib> // for exit and rand
#include <GL/glut.h> // for gl* glut*
#include <ctime> // for seeding rand()
using namespace std;
#define TEAPOT 0
#define TORUS 1
#define CUBE 2
#define SPHERE 3
/////////////////
// global vars //
/////////////////
static int object;
static int win;
static float r;
static float g;
static float b;
////////////////
// prototypes //
////////////////
void display(void);
void keyboard(unsigned char key, int x, int y);
void timerColor(int value);
void changeShape();
//////////
// main //
//////////
int main(int argc, char **argv){
// init
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("YATWT");
// callback
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
// change color each second
timerColor(0);
// clearcolor & main loop
glClearColor(1.0,1.0,1.0,0.0);
// seed random
// see `man srand` for the user of srand and random
time_t timer;
srand(time(&timer));
glutMainLoop();
return 0;
}
////////////////
// timercolor //
////////////////
void timerColor(int value){
static int counter=0;
if(counter == 4){
counter =0;
changeShape();
}else{
counter++;
}
// get new color or a value in [0,1]
r = (1.0*(random()%256))/256.0;
g = (1.0*(random()%256))/256.0;
b = (1.0*(random()%256))/256.0;
// say what we are doing
cout << "New color is (" << r << "," << g << "," << b << ")" << endl;
// draw it + reinitialise timer
glutPostRedisplay();
glutTimerFunc(1000,timerColor,0);
}
/////////////////
// changeShape //
/////////////////
void changeShape(){
// generate new object
object = random()%4;
// say what we are doing
cout << "Next object will be a ";
switch(object){
case TEAPOT:
cout << "teapot" << endl;
break;
case TORUS:
cout << "torus" << endl;
break;
case CUBE:
cout << "cube" << endl;
break;
case SPHERE:
cout << "sphere" << endl;
break;
}
}
You can also download the sourcecode. |