//---------------------------------------------------------------------
// Ukazkovy priklad cislo 31
// Autor: Pavel Tisnovsky
//
// Tento priklad svym ovladanim navazuje na priklad cislo 28, ktery byl
// prezentovany v minulem dilu tohoto serialu. Funkcni zustavaji veskere
// klavesove kombinace i ovladani, je pouze pridano submenu pro
// povoleni, zakazani a nastaveni jedne orezavaci roviny. Narozdil od
// predchoziho prikladu je orezavaci rovina nastavena az po nastaveni
// vsech projekcnich matic.
//
// Program lze ovladat kombinaci mysi a klavesnice. Pomoci leveho
// tlacitka mysi se aplikuje nektera operace, prave tlacitko mysi slouzi
// k zobrazeni kontextoveho menu. Zakladni udaje o scene se vypisuji
// primo do okna aplikace.
//
// Funkce klaves v tomto programu:
// ESC - ukonceni aplikace
// 'q' - ukonceni aplikace
// 'r' - rezim rotace objektu
// 't' - rezim posunu objektu dale/blize ke kamere
// 'z' - rezim posunu blizke orezavaci roviny
// 'x' - rezim posunu vzdalene orezavaci roviny
// 'f' - prepnuti do rezimu full-screen
// 'w' - prepnuti zpet do okna
// 'e' - povoleni testu pameti hloubky
// 'd' - zakazani testu pameti hloubky
// '[' - povoleni orezavani
// ']' - zakaz orezavani
// '.' - zmenseni zorneho uhlu
// ',' - zvetseni zorneho uhlu
// '>' - rychlejsi zmenseni zorneho uhlu
// '<' - rychlejsi zvetseni zorneho uhlu
// '0'-'9' - zmena rezimu vykreslovani prednich a zadnich stran polygonu
//---------------------------------------------------------------------
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL
#include <stdio.h>
#include <stdlib.h>
enum { // operace, ktere se mohou provadet s mysi
ROTATE,
TRANSLATE,
NEAR_PLANE,
FAR_PLANE
} operation=ROTATE;
enum { // prikazy z kontextoveho menu
COMMAND_ROTATE,
COMMAND_TRANSLATE,
COMMAND_NEAR_PLANE,
COMMAND_FAR_PLANE,
COMMAND_FRONT_FACE_DISABLE,
COMMAND_FRONT_FACE_ENABLE,
COMMAND_FRONT_FACE_POINTS,
COMMAND_FRONT_FACE_LINES,
COMMAND_FRONT_FACE_POLYGONS,
COMMAND_BACK_FACE_DISABLE,
COMMAND_BACK_FACE_ENABLE,
COMMAND_BACK_FACE_POINTS,
COMMAND_BACK_FACE_LINES,
COMMAND_BACK_FACE_POLYGONS,
COMMAND_ENABLE_DEPTH_TEST,
COMMAND_DISABLE_DEPTH_TEST,
COMMAND_DEPTH_FUNC_NEVER,
COMMAND_DEPTH_FUNC_LESS,
COMMAND_DEPTH_FUNC_LEQUAL,
COMMAND_DEPTH_FUNC_EQUAL,
COMMAND_DEPTH_FUNC_GEQUAL,
COMMAND_DEPTH_FUNC_GREATER,
COMMAND_DEPTH_FUNC_NOTEQUAL,
COMMAND_DEPTH_FUNC_ALWAYS,
COMMAND_FULL_SCREEN,
COMMAND_WINDOW,
COMMAND_CLIP_PLANE_ENABLE,
COMMAND_CLIP_PLANE_DISABLE,
COMMAND_CLIP_PLANE_XY,
COMMAND_CLIP_PLANE_XZ,
COMMAND_CLIP_PLANE_YZ,
COMMAND_CLIP_PLANE_POSITIVE_DIRECTION,
COMMAND_CLIP_PLANE_NEGATIVE_DIRECTION,
COMMAND_CLIP_PLANE_DIST_0,
COMMAND_CLIP_PLANE_DIST_1,
COMMAND_CLIP_PLANE_DIST_2,
COMMAND_CLIP_PLANE_DIST_3,
COMMAND_CLIP_PLANE_DIST_4,
COMMAND_CLIP_PLANE_DIST_5,
COMMAND_QUIT,
COMMAND_NONE
} command;
int xnew=0, ynew=0, znew=0; // soucasna pozice mysi, ze ktere se pocitaji rotace a posuvy
int xold=0, yold=0, zold=0; // minula pozice mysi, ze ktere se pocitaji rotace a posuvy
int xx, yy, zz; // bod, ve kterem se nachazi kurzor mysi
int np_old=1, np_new=1, npp=1; // priznaky blizke orezavaci roviny
int fp_old=900, fp_new=900, fpp=900; // priznaky vzdalene orezavaci roviny
float fov=70.0; // hodnota zorneho uhlu - field of view
float nearPlane=0.1; // blizsi orezavaci rovina
float farPlane=90.0; // vzdalenejsi orezavaci rovina
int windowWidth; // sirka okna
int windowHeight; // vyska okna
int depthBufferEnabled=1; // priznak, zda je povolena pamet hloubky
int frontFaceEnabled=1; // priznak viditelnosti prednich sten
int backFaceEnabled=1; // priznak viditelnosti zadnich sten
int clipPlaneNormal=COMMAND_CLIP_PLANE_XY; // normala orezavaci roviny
int clipPlaneDirection=COMMAND_CLIP_PLANE_POSITIVE_DIRECTION;// orientace normaly
int clipPlaneDistance=COMMAND_CLIP_PLANE_DIST_0;// vzdalenost orezavaci roviny od pocatku
//---------------------------------------------------------------------
// Funkce, ktera je zavolana pri vyberu prikazu z kontextoveho menu
//---------------------------------------------------------------------
void onMenu(int command)
{
switch (command) { // rozeskok podle vybraneho prikazu
case COMMAND_ROTATE: operation=ROTATE; break;
case COMMAND_TRANSLATE: operation=TRANSLATE; break;
case COMMAND_NEAR_PLANE: operation=NEAR_PLANE; break;
case COMMAND_FAR_PLANE: operation=FAR_PLANE; break;
case COMMAND_FRONT_FACE_DISABLE: glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); glutPostRedisplay(); break;
case COMMAND_FRONT_FACE_ENABLE: glDisable(GL_CULL_FACE); glutPostRedisplay(); break;
case COMMAND_FRONT_FACE_POINTS: glPolygonMode(GL_FRONT, GL_POINT); glutPostRedisplay(); break;
case COMMAND_FRONT_FACE_LINES: glPolygonMode(GL_FRONT, GL_LINE); glutPostRedisplay(); break;
case COMMAND_FRONT_FACE_POLYGONS: glPolygonMode(GL_FRONT, GL_FILL); glutPostRedisplay(); break;
case COMMAND_BACK_FACE_DISABLE: glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glutPostRedisplay(); break;
case COMMAND_BACK_FACE_ENABLE: glDisable(GL_CULL_FACE); glutPostRedisplay(); break;
case COMMAND_BACK_FACE_POINTS: glPolygonMode(GL_BACK, GL_POINT); glutPostRedisplay(); break;
case COMMAND_BACK_FACE_LINES: glPolygonMode(GL_BACK, GL_LINE); glutPostRedisplay(); break;
case COMMAND_BACK_FACE_POLYGONS: glutPostRedisplay(); glPolygonMode(GL_BACK, GL_FILL); break;
case COMMAND_ENABLE_DEPTH_TEST: depthBufferEnabled=1; glEnable(GL_DEPTH_TEST); glutPostRedisplay(); break;
case COMMAND_DISABLE_DEPTH_TEST: depthBufferEnabled=0; glDisable(GL_DEPTH_TEST); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_NEVER: glDepthFunc(GL_NEVER); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_LESS: glDepthFunc(GL_LESS); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_LEQUAL: glDepthFunc(GL_LEQUAL); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_EQUAL: glDepthFunc(GL_EQUAL); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_GEQUAL: glDepthFunc(GL_GEQUAL); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_GREATER: glDepthFunc(GL_GREATER); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_NOTEQUAL: glDepthFunc(GL_NOTEQUAL); glutPostRedisplay(); break;
case COMMAND_DEPTH_FUNC_ALWAYS: glDepthFunc(GL_ALWAYS); glutPostRedisplay(); break;
case COMMAND_FULL_SCREEN: glutFullScreen(); break;
case COMMAND_WINDOW: glutReshapeWindow(500, 500); break;
case COMMAND_CLIP_PLANE_ENABLE: glEnable(GL_CLIP_PLANE0); glutPostRedisplay(); break;
case COMMAND_CLIP_PLANE_DISABLE: glDisable(GL_CLIP_PLANE0); glutPostRedisplay(); break;
case COMMAND_CLIP_PLANE_XY:
case COMMAND_CLIP_PLANE_XZ:
case COMMAND_CLIP_PLANE_YZ: clipPlaneNormal=command; glutPostRedisplay(); break;
case COMMAND_CLIP_PLANE_POSITIVE_DIRECTION:
case COMMAND_CLIP_PLANE_NEGATIVE_DIRECTION: clipPlaneDirection=command; glutPostRedisplay(); break;
case COMMAND_CLIP_PLANE_DIST_0:
case COMMAND_CLIP_PLANE_DIST_1:
case COMMAND_CLIP_PLANE_DIST_2:
case COMMAND_CLIP_PLANE_DIST_3:
case COMMAND_CLIP_PLANE_DIST_4:
case COMMAND_CLIP_PLANE_DIST_5:
clipPlaneDistance=command; glutPostRedisplay(); break;
case COMMAND_QUIT: exit(0); break;
case COMMAND_NONE: break;
}
}
//---------------------------------------------------------------------
// Funkce pro inicializaci vykreslovani
//---------------------------------------------------------------------
void onInit(void)
{
GLdouble equation[]={0.0, 1.0, 0.0, 0.0};
int menu; // identifikatory jednotlivych menu a submenu
int menuMode;
int menuDepth;
int menuDFunc;
int menuFrontFace;
int menuBackFace;
int menuClipping, menuClipNormal, menuClipDirection, menuClipDistance;
int menuQuit;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi obrazku
glClearDepth(1.0f); // implicitni hloubka ulozena v pameti hloubky
glEnable(GL_DEPTH_TEST); // povoleni funkce pro testovani hodnot v pameti hloubky
glDepthFunc(GL_LESS); // funkce pro testovani fragmentu
glShadeModel(GL_SMOOTH); // nastaveni stinovaciho rezimu
glPolygonMode(GL_FRONT, GL_FILL); // nastaveni rezimu vykresleni modelu
glPolygonMode(GL_BACK, GL_FILL); // jak pro predni tak pro zadni steny
glPointSize(3.0f); // body zobrazovat s prumerem 3 pixely
glEnable(GL_POINT_SMOOTH); // povoleni antialiasingu bodu
glLineWidth(1.0f); // usecky zobrazovat siroke 1 pixel
glEnable(GL_LINE_SMOOTH); // povoleni antialiasingu usecek
glDisable(GL_CULL_FACE); // zadne hrany ani steny se nebudou odstranovat
glClipPlane(GL_CLIP_PLANE0, equation);
menuMode=glutCreateMenu(onMenu); // vytvoreni kontextoveho menu a jeho submenu
glutSetMenu(menuMode);
glutAddMenuEntry("Rotate object\tR", COMMAND_ROTATE);
glutAddMenuEntry("Translate object\tT", COMMAND_TRANSLATE);
glutAddMenuEntry("Translate near clipping plane\tZ", COMMAND_NEAR_PLANE);
glutAddMenuEntry("Translate far clipping plane\tX", COMMAND_FAR_PLANE);
menuDepth=glutCreateMenu(onMenu);
glutSetMenu(menuDepth);
glutAddMenuEntry("Enable depth test\tE", COMMAND_ENABLE_DEPTH_TEST);
glutAddMenuEntry("Disable depth test\tD", COMMAND_DISABLE_DEPTH_TEST);
menuDFunc=glutCreateMenu(onMenu);
glutSetMenu(menuDFunc);
glutAddMenuEntry("Never", COMMAND_DEPTH_FUNC_NEVER);
glutAddMenuEntry("Less", COMMAND_DEPTH_FUNC_LESS);
glutAddMenuEntry("Less or Equal", COMMAND_DEPTH_FUNC_LEQUAL);
glutAddMenuEntry("Equal", COMMAND_DEPTH_FUNC_EQUAL);
glutAddMenuEntry("Greater or Equal", COMMAND_DEPTH_FUNC_GEQUAL);
glutAddMenuEntry("Greater", COMMAND_DEPTH_FUNC_GREATER);
glutAddMenuEntry("Not Equal", COMMAND_DEPTH_FUNC_NOTEQUAL);
glutAddMenuEntry("Always", COMMAND_DEPTH_FUNC_ALWAYS);
menuFrontFace=glutCreateMenu(onMenu);
glutSetMenu(menuFrontFace);
glutAddMenuEntry("Disable\t1", COMMAND_FRONT_FACE_DISABLE);
glutAddMenuEntry("Enable\t2", COMMAND_FRONT_FACE_ENABLE);
glutAddMenuEntry("Points\t3", COMMAND_FRONT_FACE_POINTS);
glutAddMenuEntry("Lines\t4", COMMAND_FRONT_FACE_LINES);
glutAddMenuEntry("Polygons\t5", COMMAND_FRONT_FACE_POLYGONS);
menuBackFace=glutCreateMenu(onMenu);
glutSetMenu(menuBackFace);
glutAddMenuEntry("Disable\t6", COMMAND_BACK_FACE_DISABLE);
glutAddMenuEntry("Enable\t7", COMMAND_BACK_FACE_ENABLE);
glutAddMenuEntry("Points\t8", COMMAND_BACK_FACE_POINTS);
glutAddMenuEntry("Lines\t9", COMMAND_BACK_FACE_LINES);
glutAddMenuEntry("Polygons\t0", COMMAND_BACK_FACE_POLYGONS);
menuClipNormal=glutCreateMenu(onMenu);
glutSetMenu(menuClipNormal);
glutAddMenuEntry("x-axis", COMMAND_CLIP_PLANE_YZ);
glutAddMenuEntry("y-axis", COMMAND_CLIP_PLANE_XZ);
glutAddMenuEntry("z-axis", COMMAND_CLIP_PLANE_XY);
menuClipDirection=glutCreateMenu(onMenu);
glutSetMenu(menuClipDirection);
glutAddMenuEntry("Positive", COMMAND_CLIP_PLANE_POSITIVE_DIRECTION);
glutAddMenuEntry("Negative", COMMAND_CLIP_PLANE_NEGATIVE_DIRECTION);
menuClipDistance=glutCreateMenu(onMenu);
glutSetMenu(menuClipDistance);
glutAddMenuEntry("0", COMMAND_CLIP_PLANE_DIST_0);
glutAddMenuEntry("1", COMMAND_CLIP_PLANE_DIST_1);
glutAddMenuEntry("2", COMMAND_CLIP_PLANE_DIST_2);
glutAddMenuEntry("3", COMMAND_CLIP_PLANE_DIST_3);
glutAddMenuEntry("4", COMMAND_CLIP_PLANE_DIST_4);
menuClipping=glutCreateMenu(onMenu);
glutSetMenu(menuClipping);
glutAddMenuEntry("Enable clipping", COMMAND_CLIP_PLANE_ENABLE);
glutAddMenuEntry("Disable clipping", COMMAND_CLIP_PLANE_DISABLE);
glutAddSubMenu("Normal", menuClipNormal);
glutAddSubMenu("Normal' direction", menuClipDirection);
glutAddSubMenu("Distance", menuClipDistance);
menuQuit=glutCreateMenu(onMenu);
glutSetMenu(menuQuit);
glutAddMenuEntry("Yes\tQ", COMMAND_QUIT);
glutAddMenuEntry("No", COMMAND_NONE);
menu=glutCreateMenu(onMenu);
glutAddSubMenu("Mode", menuMode);
glutAddSubMenu("Front faces", menuFrontFace);
glutAddSubMenu("Back faces", menuBackFace);
glutAddSubMenu("Depth test", menuDepth);
glutAddSubMenu("Depth function", menuDFunc);
glutAddSubMenu("Clipping", menuClipping);
glutAddMenuEntry("Full screen\tF", COMMAND_FULL_SCREEN);
glutAddMenuEntry("Window\tW", COMMAND_WINDOW);
glutAddSubMenu("Quit", menuQuit);
glutAttachMenu(GLUT_RIGHT_BUTTON); // menu je navazano na prave tlacitko mysi
}
//---------------------------------------------------------------------
// Nastaveni souradneho systemu v zavislosti na velikosti okna
//---------------------------------------------------------------------
void onResize(int w, int h) // argumenty w a h reprezentuji novou velikost okna
{
glViewport(0, 0, w, h); // viditelna oblast pres cele okno
windowWidth=w; // zapamatovat si velikost okna
windowHeight=h;
}
//---------------------------------------------------------------------
// Nastaveni perspektivni projekce
//---------------------------------------------------------------------
void setPerspectiveProjection(void)
{
glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice
glLoadIdentity(); // vymazani projekcni matice (=identita)
gluPerspective(fov, (double)windowWidth/(double)windowHeight, nearPlane, farPlane);// nastaveni perspektivni kamery
glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice
glLoadIdentity(); // nahrat jednotkovou matici
}
//---------------------------------------------------------------------
// Nastaveni ortogonalni projekce
//---------------------------------------------------------------------
void setOrthogonalProjection(void)
{
glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice
glLoadIdentity(); // vymazani projekcni matice (=identita)
glOrtho(0, windowWidth, 0, windowHeight, -1, 1);
glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice
glLoadIdentity(); // nahrat jednotkovou matici
}
//---------------------------------------------------------------------
// Funkce pro nastaveni orezavaci roviny
//---------------------------------------------------------------------
void setClipPlane(void)
{
GLdouble dir=1.0; // je bud -1 nebo 1 podle orientace normaly
GLdouble equation[]={0.0f, 0.0f, 0.0f, 0.0f};// parametry A, B, C, D ze vztahu Ax+By+Cz+D=0
if (clipPlaneDirection==COMMAND_CLIP_PLANE_NEGATIVE_DIRECTION)
dir=-1.0; // podle vyberu z menu se muze zmenit orientace normaly
switch (clipPlaneNormal) { // zmena smeru normaly
case COMMAND_CLIP_PLANE_XY: equation[2]=dir; break;
case COMMAND_CLIP_PLANE_XZ: equation[1]=dir; break;
case COMMAND_CLIP_PLANE_YZ: equation[0]=dir; break;
}
equation[3]=clipPlaneDistance-COMMAND_CLIP_PLANE_DIST_0;// vzdalenost orezavaci roviny
glClipPlane(GL_CLIP_PLANE0, equation); // nastaveni orezavaci roviny
}
//---------------------------------------------------------------------
// Vypsani retezce do okna na pozici [x,y]
//---------------------------------------------------------------------
void printString(int x, int y, char *text)
{
glRasterPos2i(x, y); // pozice prvniho znaku retezce
for (; *text; text++) // pruchod retezcem
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *text);// vykresleni jednoho znaku
}
//--------------------------------------------------------------------
// Vypsani informaci o nastavenych parametrech
//---------------------------------------------------------------------
void drawInfoText(void)
{
char str[100];
int ce=glIsEnabled(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE0); // text by se mel vypsat vzdy, proto vypneme orezavani
glColor3f(1.0,1.0,1.0);
sprintf(str, "Rotation x: %d", xnew);
printString(10, 100, str); // vypsat rotaci ve smeru osy x
sprintf(str, "Rotation y: %d", ynew);
printString(10, 85, str); // vypsat rotaci ve smeru osy y
sprintf(str, "Translation: %d", znew);
printString(10, 70, str); // vypsat posun objektu od kamery
sprintf(str, "Near plane: %5.2f", nearPlane);
printString(10, 55, str); // vzdalenost blizke orezavaci roviny
sprintf(str, "Far plane: %5.2f", farPlane);
printString(10, 40, str); // vzdalenost vzdalene orezavaci roviny
sprintf(str, "Field of view: %5.2f", fov);
printString(10, 25, str); // zorny uhel kamery
sprintf(str, "Clip plane: %s", ce ? "enabled":"disabled");
printString(10, 10, str); // povoleni ci zakazani orezavaci roviny
if (ce) glEnable(GL_CLIP_PLANE0); // opetovne zapnuti orezavani
}
//--------------------------------------------------------------------
// Vykresleni objektu
//---------------------------------------------------------------------
void drawObject(void)
{
glBegin(GL_QUADS); // vykresleni otevrene krychle - sten domecku
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glEnd();
glBegin(GL_TRIANGLES); // vykresleni strechy domecku z trojuhelniku
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glEnd();
}
//--------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//---------------------------------------------------------------------
void onDisplay(void)
{
if (depthBufferEnabled) // podle povoleni pameti hloubky
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// vymazani barvoveho bufferu i pameti hloubky
else
glClear(GL_COLOR_BUFFER_BIT); // vymazani vsech bitovych rovin barvoveho bufferu
setOrthogonalProjection(); // ortogonalni rezim pro kresleni 2D obrazku
drawInfoText(); // vypsat informace o nastaveni
setPerspectiveProjection(); // nastaveni perspektivni kamery
glTranslatef(0.0f, 0.0f, -50.0f); // posun objektu dale od kamery
glTranslatef(0.0f, 0.0f, znew); // priblizeni ci vzdaleni objektu podle pohybu kurzoru mysi
glRotatef(ynew, 1.0f, 0.0f, 0.0f); // rotace objektu podle pohybu kurzoru mysi
glRotatef(xnew, 0.0f, 1.0f, 0.0f);
setClipPlane(); // nastaveni orezavaci roviny
drawObject(); // vykresleni objektu
glFlush(); // provedeni a vykresleni vsech zmen
glutSwapBuffers(); // a prohozeni predniho a zadniho bufferu
}
//---------------------------------------------------------------------
// Tato funkce je volana pri stlaceni ASCII klavesy
//---------------------------------------------------------------------
void onKeyboard(unsigned char key, int x, int y)
{
if (key>='A' && key<='Z') // uprava velkych pismen na mala
key+='a'-'A'; // pro zjednoduseni prikazu switch
switch (key) {
case 27: exit(0); break; // ukonceni aplikace
case 'q': exit(0); break; // ukonceni aplikace
case 'f': onMenu(COMMAND_FULL_SCREEN); break; // prepnuti do full-screen rezimu
case 'w': onMenu(COMMAND_WINDOW); break; // prepnuti zpet do okna
case 'e': onMenu(COMMAND_ENABLE_DEPTH_TEST); break; // povoleni funkce pameti hloubky
case 'd': onMenu(COMMAND_DISABLE_DEPTH_TEST); break; // zakazani funkce pameti hloubky
case 'r': onMenu(COMMAND_ROTATE); break; // rezim rotace objektu
case 't': onMenu(COMMAND_TRANSLATE); break; // rezim posunu objektu
case 'z': onMenu(COMMAND_NEAR_PLANE); break; // rezim posunu blizke orezavaci roviny
case 'x': onMenu(COMMAND_FAR_PLANE); break; // rezim posunu vzdalene orezavaci roviny
case '[': onMenu(COMMAND_CLIP_PLANE_ENABLE); break; // povoleni orezavani
case ']': onMenu(COMMAND_CLIP_PLANE_DISABLE); break; // zakaz orezavani
case '.': fov--; glutPostRedisplay(); break; // zmenseni zorneho uhlu
case ',': fov++; glutPostRedisplay(); break; // zvetseni zorneho uhlu
case '>': fov-=5; glutPostRedisplay(); break; // rychlejsi zmenseni zorneho uhlu
case '<': fov+=5; glutPostRedisplay(); break; // rychlejsi zvetseni zorneho uhlu
case '1': onMenu(COMMAND_FRONT_FACE_DISABLE); break; // zakaz vykresleni prednich sten
case '2': onMenu(COMMAND_FRONT_FACE_ENABLE); break; // povoleni vykresleni prednich sten
case '3': onMenu(COMMAND_FRONT_FACE_POINTS); break; // predni steny se vykresli jako body
case '4': onMenu(COMMAND_FRONT_FACE_LINES); break; // predni steny se vykresli jako usecky
case '5': onMenu(COMMAND_FRONT_FACE_POLYGONS);break; // predni steny se vykresli jako polygony
case '6': onMenu(COMMAND_BACK_FACE_DISABLE); break; // zakaz vykresleni zadnich sten
case '7': onMenu(COMMAND_BACK_FACE_ENABLE); break; // povoleni vykresleni zadnich sten
case '8': onMenu(COMMAND_BACK_FACE_POINTS); break; // zadni steny se vykresli jako body
case '9': onMenu(COMMAND_BACK_FACE_LINES); break; // zadni steny se vykresli jako usecky
case '0': onMenu(COMMAND_BACK_FACE_POLYGONS); break; // zadni steny se vykresli jako polygony
default: break;
}
}
//---------------------------------------------------------------------
// Tato funkce je volana pri stisku ci pusteni tlacitka mysi
//---------------------------------------------------------------------
void onMouseButton(int button, int state, int x, int y)
{
if (button==GLUT_LEFT_BUTTON) { // pri zmene stavu leveho tlacitka
switch (operation) {
case ROTATE: // rotace objektu
if (state==GLUT_DOWN) { // pri stlaceni tlacitka
xx=x; // zapamatovat pozici kurzoru mysi
yy=y;
}
else { // pri pusteni tlacitka
xold=xnew; // zapamatovat novy pocatek
yold=ynew;
}
glutPostRedisplay(); // prekresleni sceny
break;
case TRANSLATE: // posun objektu
if (state==GLUT_DOWN) zz=y; // pri stlaceni tlacitka zapamatovat polohu kurzoru mysi
else zold=znew; // pri pusteni tlacitka zapamatovat novy pocatek
glutPostRedisplay(); // prekresleni sceny
break;
case NEAR_PLANE: // zmena polohy blizke orezavaci roviny
if (state==GLUT_DOWN) npp=y; // pri stlaceni tlacitka zapamatovat polohu kurzoru mysi
else np_old=np_new;
break;
case FAR_PLANE: // zmena polohy vzdalene orezavaci roviny
if (state==GLUT_DOWN) fpp=y; // pri stlaceni tlacitka zapamatovat polohu kurzoru mysi
else fp_old=fp_new;
break;
default:
break;
}
}
}
//---------------------------------------------------------------------
// Tato funkce je volana pri pohybu mysi se stlacenym tlacitkem.
// To, ktere tlacitko je stlaceno si musime predem zaznamenat do
// globalni promenne stav ve funkci onMouseButton()
//---------------------------------------------------------------------
void onMouseMotion(int x, int y)
{
switch (operation) {
case ROTATE: // stav rotace objektu
xnew=xold+x-xx; // vypocitat novou pozici
ynew=yold+y-yy;
glutPostRedisplay(); // a prekreslit scenu
break;
case TRANSLATE: // stav priblizeni/oddaleni objektu
znew=zold+y-zz; // vypocitat novou pozici
glutPostRedisplay(); // a prekreslit scenu
break;
case NEAR_PLANE: // priblizeni/vzdaleni blizke orezavaci roviny
np_new=np_old+y-npp;
nearPlane=np_new/100.0;
onResize(windowWidth, windowHeight);// zmena projekcni matice
glutPostRedisplay(); // a prekreslit scenu
break;
case FAR_PLANE: // priblizeni/vzdaleni vzdalene orezavaci roviny
fp_new=fp_old+y-fpp;
farPlane=fp_new/10.0;
onResize(windowWidth, windowHeight);// zmena projekcni matice
glutPostRedisplay(); // a prekreslit scenu
break;
}
}
//---------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//---------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);// nastaveni dvou barvovych bufferu a pameti hloubky
glutInitWindowPosition(30, 30); // pocatecni pozice leveho horniho rohu okna
glutInitWindowSize(500, 500); // pocatecni velikost okna
glutCreateWindow("Priklad na OpenGL cislo 31");// vytvoreni okna pro kresleni
glutDisplayFunc(onDisplay); // registrace funkce volane pri prekreslovani okna
glutReshapeFunc(onResize); // registrace funkce volane pri zmene velikosti okna
glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stlaceni klavesy
glutMouseFunc(onMouseButton); // registrace funkce volane pri stlaceni ci pusteni tlacitka
glutMotionFunc(onMouseMotion); // registrace funkce volane pri pohybu mysi se stlacenym tlacitkem
onInit(); // inicializace vykreslovani
glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce
return 0; // navratova hodnota vracena operacnimu systemu
}
//---------------------------------------------------------------------
// Konec zdrojoveho souboru
//---------------------------------------------------------------------