//--------------------------------------------------------------------- // Ukazkovy priklad k serii clanku OpenGL a GLU // // Autor: Pavel Tisnovsky // Cislo clanku: 17 // Cislo prikladu: 2 // // Tento program po svem spusteni zobrazi teleso s nanesenou 2D texturou. // Textura je vytvorena jako mipmapa se zakladnim rozlisenim 64x64 texelu. // // Pri vykreslovani zmenseneho telesa se vyberou dve nejblizsi textury // z mipmapy a z techto se linearni interpolaci vypoctou dve barvy. // Vysledna barva je vycislena jako dalsi linearni interpolace techto // dvou barev. Pri zvetsovani vykresleneho telesa se pouziva linearni // interpolace nejblizsich texelu v texture. // // Pro vytvoreni mipmapy je pouzita funkce gluScaleImage(). // // Proto jsou pouzity filtry: // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Pomoci leveho tlacitka mysi lze telesem otacet, prave tlacitko // slouzi k priblizeni nebo vzdaleni telesa od kamery. //--------------------------------------------------------------------- #include #include #include #include #define WINDOW_WIDTH 450 // velikost okna #define WINDOW_HEIGHT 450 #define WINDOW_TITLE "OpenGL a GLU, priklad 17.2"// titulek okna #define TEXTURE_WIDTH 64 // sirka textury zadana v texelech #define TEXTURE_HEIGHT 64 // vyska textury zadana v texelech enum { // operace, ktere se mohou provadet s mysi: ROTATE, // rotace objektu TRANSLATE, // posun objektu } operation=ROTATE; int xnew=0, ynew=0, znew=30; // soucasna pozice mysi, ze ktere se pocitaji rotace a posuvy int xold=0, yold=0, zold=30; // minula pozice mysi, ze ktere se pocitaji rotace a posuvy int xx, yy, zz; // bod, ve kterem se nachazi kurzor mysi int windowWidth; // sirka okna int windowHeight; // vyska okna unsigned char texture0[TEXTURE_HEIGHT][TEXTURE_WIDTH][3]; // pole pro RGB texturu v plnem rozliseni unsigned char texture1[TEXTURE_HEIGHT >>1][TEXTURE_WIDTH >>1][3]; // pole pro RGB texturu na prvni urovni v mipmape unsigned char texture2[TEXTURE_HEIGHT >>2][TEXTURE_WIDTH >>2][3]; // pole pro RGB texturu na druhe urovni v mipmape unsigned char texture3[TEXTURE_HEIGHT >>3][TEXTURE_WIDTH >>3][3]; // pole pro RGB texturu na treti urovni v mipmape unsigned char texture4[TEXTURE_HEIGHT >>4][TEXTURE_WIDTH >>4][3]; // pole pro RGB texturu na ctvrte urovni v mipmape unsigned char texture5[TEXTURE_HEIGHT >>5][TEXTURE_WIDTH >>5][3]; // pole pro RGB texturu na pate urovni v mipmape unsigned char texture6[TEXTURE_HEIGHT >>6][TEXTURE_WIDTH >>6][3]; // pole pro RGB texturu na seste urovni v mipmape GLuint textureName; // jmeno textury //--------------------------------------------------------------------- // Vytvoreni rastroveho vzorku pro textury v mipmape //--------------------------------------------------------------------- void makeRasterTexture(void) { int i,j,c; // pocitadla smycek unsigned char * P; // ukazatel na zapisovany subtexel // textura na urovni 0 v mipmape for (j=0; j>1, TEXTURE_HEIGHT>>1, GL_BYTE, (void*)texture1); gluScaleImage(GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_BYTE, (void*)texture0, TEXTURE_WIDTH>>2, TEXTURE_HEIGHT>>2, GL_BYTE, (void*)texture2); gluScaleImage(GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_BYTE, (void*)texture0, TEXTURE_WIDTH>>3, TEXTURE_HEIGHT>>3, GL_BYTE, (void*)texture3); gluScaleImage(GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_BYTE, (void*)texture0, TEXTURE_WIDTH>>4, TEXTURE_HEIGHT>>4, GL_BYTE, (void*)texture4); gluScaleImage(GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_BYTE, (void*)texture0, TEXTURE_WIDTH>>5, TEXTURE_HEIGHT>>5, GL_BYTE, (void*)texture5); gluScaleImage(GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_BYTE, (void*)texture0, TEXTURE_WIDTH>>6, TEXTURE_HEIGHT>>6, GL_BYTE, (void*)texture6); } //--------------------------------------------------------------------- // Nastaveni parametru textur //--------------------------------------------------------------------- void setTextures(void) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // zpusob ulozeni bytu v texture glGenTextures(1, &textureName); glBindTexture(GL_TEXTURE_2D, textureName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // opakovani textury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // volba filtru glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, texture0); glTexImage2D(GL_TEXTURE_2D, 1, 3, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1); glTexImage2D(GL_TEXTURE_2D, 2, 3, 16, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, texture2); glTexImage2D(GL_TEXTURE_2D, 3, 3, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, texture3); glTexImage2D(GL_TEXTURE_2D, 4, 3, 4, 4, 0, GL_RGB, GL_UNSIGNED_BYTE, texture4); glTexImage2D(GL_TEXTURE_2D, 5, 3, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, texture5); glTexImage2D(GL_TEXTURE_2D, 6, 3, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, texture6); glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); // vylepseni zobrazovani glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // zpusob vykresleni textury glEnable(GL_TEXTURE_2D); // povoleni texturovani } //--------------------------------------------------------------------- // Funkce pro inicializaci vykreslovani //--------------------------------------------------------------------- void onInit(void) { 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 glDisable(GL_CULL_FACE); // zadne hrany ani steny se nebudou odstranovat makeRasterTexture(); // vytvoreni vzorku v texure setTextures(); // vytvoreni textur a nastaveni parametru } //--------------------------------------------------------------------- // 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(60.0, (double)windowWidth/(double)windowHeight, 2.0f, 190.0f);// nastaveni perspektivni kamery glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice glLoadIdentity(); // nahrat jednotkovou matici } //-------------------------------------------------------------------- // Vykresleni objektu //-------------------------------------------------------------------- void drawObject(void) { glBegin(GL_QUADS); // vykresleni otevrene krychle - sten domecku glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -5.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-5.0f, -5.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, 5.0f, -5.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, -5.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -5.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-5.0f, -5.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-5.0f, 5.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, -5.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, 5.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, -5.0f); glEnd(); glBegin(GL_TRIANGLES); // vykresleni strechy domecku z trojuhelniku glTexCoord2f(0.0, 0.0); glVertex3f(-5.0f, 5.0f, -5.0f); glTexCoord2f(0.0, 1.0); glVertex3f( 5.0f, 5.0f, -5.0f); glTexCoord2f(0.5, 0.8); glVertex3f( 0.0f, 11.0f, 0.0f); glTexCoord2f(0.0, 0.0); glVertex3f( 5.0f, 5.0f, -5.0f); glTexCoord2f(0.0, 1.0); glVertex3f( 5.0f, 5.0f, 5.0f); glTexCoord2f(0.5, 0.8); glVertex3f( 0.0f, 11.0f, 0.0f); glTexCoord2f(0.0, 0.0); glVertex3f( 5.0f, 5.0f, 5.0f); glTexCoord2f(0.0, 1.0); glVertex3f(-5.0f, 5.0f, 5.0f); glTexCoord2f(0.5, 0.8); glVertex3f( 0.0f, 11.0f, 0.0f); glTexCoord2f(0.0, 0.0); glVertex3f(-5.0f, 5.0f, 5.0f); glTexCoord2f(0.0, 1.0); glVertex3f(-5.0f, 5.0f, -5.0f); glTexCoord2f(0.5, 0.8); glVertex3f( 0.0f, 11.0f, 0.0f); glEnd(); } //-------------------------------------------------------------------- // Tato funkce je volana pri kazdem prekresleni okna //-------------------------------------------------------------------- void onDisplay(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// vymazani barvoveho bufferu i pameti hloubky 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); glBindTexture(GL_TEXTURE_2D, textureName); // navazani textury na vykreslovany objekt 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 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 operation=ROTATE; 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 } if (button==GLUT_RIGHT_BUTTON) { operation=TRANSLATE; 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 } } //--------------------------------------------------------------------- // 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; } } //--------------------------------------------------------------------- // 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(WINDOW_WIDTH, WINDOW_HEIGHT);// pocatecni velikost okna glutCreateWindow(WINDOW_TITLE); // 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 //---------------------------------------------------------------------