//--------------------------------------------------------------------- // Ukazkovy priklad cislo 34 // Autor: Pavel Tisnovsky // // Tento priklad svym ovladanim navazuje na priklad cislo 28 a jeho // pokracovani. // Nove je pridana funkce pro zmenu prikazu vykreslovani: // krome klasickeho vykreslovani (glBegin, glEnd) lze pouzit i funkce // glArrayElement(), glDrawArrays() a glDrawElements(). // Jsou pridany take ctyri klavesove zkratky - viz nize. // // 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 // F1 - normalni vykreslovani (glBegin() a glEnd()) // F2 - vykreslovani pomoci funkce glArrayElement() // F3 - vykreslovani pomoci funkce glDrawArrays() // F4 - vykreslovani pomoci funkce glDrawElements() //--------------------------------------------------------------------- #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, // rotace objektu TRANSLATE, // posun objektu NEAR_PLANE, // zmena blizsi orezavaci roviny FAR_PLANE // zmena vzdalenejsi orezavaci roviny } operation=ROTATE; enum { // prikazy z kontextoveho menu: COMMAND_ROTATE, // rotace objektu COMMAND_TRANSLATE, // posun objektu COMMAND_NEAR_PLANE, // zmena blizsi orezavaci roviny COMMAND_FAR_PLANE, // zmena vzdalenejsi orezavaci roviny COMMAND_FRONT_FACE_DISABLE, // zakazani zobrazovani prednich sten polygonu COMMAND_FRONT_FACE_ENABLE, // povoleni zobrazovani prednich sten polygonu COMMAND_FRONT_FACE_POINTS, // predni steny polygonu vykreslovat jako body ve vrcholech COMMAND_FRONT_FACE_LINES, // predni steny polygonu vykreslovat jako usecky na hranach COMMAND_FRONT_FACE_POLYGONS, // predni steny polygonu vykreslovat vyplnene COMMAND_BACK_FACE_DISABLE, // zakazani zobrazovani zadnich sten polygonu COMMAND_BACK_FACE_ENABLE, // povoleni zobrazovani zadnich sten polygonu COMMAND_BACK_FACE_POINTS, // zadni steny polygonu vykreslovat jako body ve vrcholech COMMAND_BACK_FACE_LINES, // zadni steny polygonu vykreslovat jako usecky na hranach COMMAND_BACK_FACE_POLYGONS, // zadni steny polygonu vykreslovat vyplnene COMMAND_ENABLE_DEPTH_TEST, // povoleni Z-bufferu COMMAND_DISABLE_DEPTH_TEST, // zakazani Z-bufferu COMMAND_DEPTH_FUNC_NEVER, // | COMMAND_DEPTH_FUNC_LESS, // | COMMAND_DEPTH_FUNC_LEQUAL, // | nastaveni funkci, ktere se budou provadet mezi hodnotou COMMAND_DEPTH_FUNC_EQUAL, // | zapsanou v Z-bufferu a hodnotou prave vykreslovaneho COMMAND_DEPTH_FUNC_GEQUAL, // | fragmentu COMMAND_DEPTH_FUNC_GREATER, // | COMMAND_DEPTH_FUNC_NOTEQUAL, // | COMMAND_DEPTH_FUNC_ALWAYS, // | COMMAND_FULL_SCREEN, // prepnuti do rezimu okna pres celou obrazovku COMMAND_WINDOW, // prepnuti do rezimu normalniho okna COMMAND_CLIP_PLANE_ENABLE, // povoleni pridavne orezavaci roviny COMMAND_CLIP_PLANE_DISABLE, // zakazani pridavne orezavaci roviny COMMAND_CLIP_PLANE_XY, // | COMMAND_CLIP_PLANE_XZ, // | COMMAND_CLIP_PLANE_YZ, // | nastaveni orientace pridavne orezavaci roviny 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, // | nastaveni vzdalenosti pridavne orezavaci roviny COMMAND_CLIP_PLANE_DIST_4, // | COMMAND_CLIP_PLANE_DIST_5, // | COMMAND_DRAW_MODE_NORMAL, // vykreslovani pres funkce glBegin() a glEnd() COMMAND_DRAW_MODE_ARRAY_ELEMENT, // vykreslovani pres funkci glArrayElement() COMMAND_DRAW_MODE_DRAW_ARRAYS, // vykreslovani pres funkci glDrawArrays() COMMAND_DRAW_MODE_DRAW_ELEMENTS, // vykreslovani pres funkci glDrawElements() COMMAND_QUIT, // ukonceni aplikace 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 int drawMode=COMMAND_DRAW_MODE_NORMAL; // zpusob vykreslovani //--------------------------------------------------------------------- // 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_DRAW_MODE_NORMAL: case COMMAND_DRAW_MODE_ARRAY_ELEMENT: case COMMAND_DRAW_MODE_DRAW_ELEMENTS: case COMMAND_DRAW_MODE_DRAW_ARRAYS: drawMode=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 menuDrawMode; 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); menuDrawMode=glutCreateMenu(onMenu); glutSetMenu(menuDrawMode); glutAddMenuEntry("Normal\tF1", COMMAND_DRAW_MODE_NORMAL); glutAddMenuEntry("ArrayElement\tF2", COMMAND_DRAW_MODE_ARRAY_ELEMENT); glutAddMenuEntry("DrawArrays\tF3", COMMAND_DRAW_MODE_DRAW_ARRAYS); glutAddMenuEntry("DrawElements\tF4", COMMAND_DRAW_MODE_DRAW_ELEMENTS); 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("Draw mode", menuDrawMode); 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]; char *dm[]={"normal", "glArrayElement", "glDrawArrays", "glDrawElements"}; 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 sprintf(str, "Draw mode: %s", dm[drawMode-COMMAND_DRAW_MODE_NORMAL]); printString(250, 100, str); if (ce) glEnable(GL_CLIP_PLANE0); // opetovne zapnuti orezavani } //-------------------------------------------------------------------- // Vykresleni objektu //-------------------------------------------------------------------- void drawObjectNormal(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(); } static GLint vertices[]={-5,-5,-5, // pole pozic vrcholu -5,-5, 5, 5,-5, 5, 5,-5,-5, -5, 5,-5, -5, 5, 5, 5, 5, 5, 5, 5,-5, -5,-5,-5, -5,-5, 5, -5, 5, 5, -5, 5,-5, 5,-5,-5, 5,-5, 5, 5, 5, 5, 5, 5,-5}; static GLfloat colors[]={ 0.0f, 0.0f, 1.0f,// pole barev vrcholu 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}; static GLubyte indexes[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //-------------------------------------------------------------------- // vykresleni sceny pomoci funkce glArrayElement() // pro jednoduchost se vykresluje pouze otevrena krychle //-------------------------------------------------------------------- void drawArrayElement(void) { int i; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, colors); glVertexPointer(3, GL_INT, 0, vertices); glBegin(GL_QUADS); for (i=0; i<16; i++) // vykreslit vsechny vrcholy glArrayElement(i); glEnd(); } //-------------------------------------------------------------------- // vykresleni sceny pomoci funkce glDrawArrays() // pro jednoduchost se vykresluje pouze otevrena krychle //-------------------------------------------------------------------- void drawArrays(void) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, colors); glVertexPointer(3, GL_INT, 0, vertices); glDrawArrays(GL_QUADS, 0, 16); } //-------------------------------------------------------------------- // vykresleni sceny pomoci funkce glDrawElements() // pro jednoduchost se vykresluje pouze otevrena krychle // V teto funkci by bylo mozne provest takove zjednoduseni, ze by // se vrcholy v poli vrcholu a barev neopakovaly a indexy v poli // 'indexes' by se samozrejme musely zmenit. //-------------------------------------------------------------------- void drawElements(void) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, colors); glVertexPointer(3, GL_INT, 0, vertices); glDrawElements(GL_QUADS, 16, GL_UNSIGNED_BYTE, indexes); } //-------------------------------------------------------------------- // 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 switch (drawMode) { // vykresleni objektu ve scene case COMMAND_DRAW_MODE_NORMAL: drawObjectNormal(); break; case COMMAND_DRAW_MODE_ARRAY_ELEMENT: drawArrayElement(); break; case COMMAND_DRAW_MODE_DRAW_ARRAYS: drawArrays(); break; case COMMAND_DRAW_MODE_DRAW_ELEMENTS: drawElements(); break; default: break; } 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 zavolana pri stlaceni klavesy, ktera nema ASCII kod //--------------------------------------------------------------------- void onSpecialKey(int key, int x, int y) { switch (key) { case GLUT_KEY_F1: onMenu(COMMAND_DRAW_MODE_NORMAL); break; case GLUT_KEY_F2: onMenu(COMMAND_DRAW_MODE_ARRAY_ELEMENT); break; case GLUT_KEY_F3: onMenu(COMMAND_DRAW_MODE_DRAW_ARRAYS); break; case GLUT_KEY_F4: onMenu(COMMAND_DRAW_MODE_DRAW_ELEMENTS); break; 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 34");// 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 glutSpecialFunc(onSpecialKey); // registrace funkce volane pri stlaceni non-ASCII 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 //---------------------------------------------------------------------