//--------------------------------------------------------------------- // Ukazkovy priklad cislo 69 // Autor: Pavel Tisnovsky // // V tomto ukazkovem programu se provede nastaveni kamery v takzvanem // perspektivnim rezimu, tj. rezimu, kdy se na stinitku meni vzdalenosti // zadavanych vrcholu podle jejich hloubky. // Pote se vykresli jednoduche teleso ve tvaru domecku, se kterym lze // rotovat a pohybovat pomoci mysi. Domecek se vykresli jako vyplneny // model. Pred domeckem jsou zobrazeny dve polopruhledne roviny, kazda // ma jinou barvu a vzdalenost. Pomoci klavesy 'f' lze provest prepnuti // do celeho okna, klavesou 'w' se provede nastaveni velikosti okna na // puvodni velikost 500x500 // pixelu. Program lze ukoncit stlacenim klavesy 'q' nebo ESC. // Pomoci klavesy 'e' lze zapnout funkci pameti hloubky, klavesou 'd' se // pamet hloubky naopak zakaze. Klavesami '.' a ',' (tecka a carka) je // mozne menit zorny uhel kamery. //--------------------------------------------------------------------- #include // hlavickovy soubor funkci GLUTu a OpenGL #include 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 stav; // stav tlacitek mysi 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 //--------------------------------------------------------------------- // Funkce pro inicializaci vykreslovani //--------------------------------------------------------------------- void onInit(void) { glClearColor(0.7f, 0.7f, 0.7f, 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 } //--------------------------------------------------------------------- // 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 glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) gluPerspective(fov, (double)w/(double)h, nearPlane, farPlane);// nastaveni perspektivni kamery windowWidth=w; // zapamatovat si velikost okna windowHeight=h; } //--------------------------------------------------------------------- // 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 glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice glLoadIdentity(); // nahrat jednotkovou matici // zde se bude provadet nastaveni 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); glBegin(GL_QUADS); // vykresleni otevrene krychle - sten domecku glColor3f(0.2f, 0.2f, 0.8f); glVertex3f(-5.0f, -5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.2f); glVertex3f(-5.0f, -5.0f, 5.0f); glColor3f(0.2f, 0.8f, 0.8f); glVertex3f( 5.0f, -5.0f, 5.0f); glColor3f(0.8f, 0.2f, 0.2f); glVertex3f( 5.0f, -5.0f, -5.0f); glColor3f(0.8f, 0.2f, 0.8f); glVertex3f(-5.0f, 5.0f, -5.0f); glColor3f(0.8f, 0.8f, 0.2f); glVertex3f(-5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.8f, 0.8f); glVertex3f( 5.0f, 5.0f, 5.0f); glColor3f(0.2f, 0.2f, 0.2f); glVertex3f( 5.0f, 5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.2f); glVertex3f(-5.0f, -5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.8f); glVertex3f(-5.0f, -5.0f, 5.0f); glColor3f(0.8f, 0.2f, 0.2f); glVertex3f(-5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.2f, 0.8f); glVertex3f(-5.0f, 5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.2f); glVertex3f( 5.0f, -5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.8f); glVertex3f( 5.0f, -5.0f, 5.0f); glColor3f(0.8f, 0.2f, 0.2f); glVertex3f( 5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.2f, 0.8f); glVertex3f( 5.0f, 5.0f, -5.0f); glEnd(); glBegin(GL_TRIANGLES); // vykresleni strechy domecku z trojuhelniku glColor3f(0.2f, 0.2f, 0.8f); glVertex3f(-5.0f, 5.0f, -5.0f); glColor3f(0.2f, 0.8f, 0.8f); glVertex3f( 5.0f, 5.0f, -5.0f); glColor3f(0.8f, 0.8f, 0.8f); glVertex3f( 0.0f, 11.0f, 0.0f); glColor3f(0.8f, 0.2f, 0.2f); glVertex3f( 5.0f, 5.0f, -5.0f); glColor3f(0.8f, 0.8f, 0.2f); glVertex3f( 5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.8f, 0.8f); glVertex3f( 0.0f, 11.0f, 0.0f); glColor3f(0.2f, 0.8f, 0.2f); glVertex3f( 5.0f, 5.0f, 5.0f); glColor3f(0.2f, 0.8f, 0.8f); glVertex3f(-5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.8f, 0.8f); glVertex3f( 0.0f, 11.0f, 0.0f); glColor3f(0.2f, 0.8f, 0.2f); glVertex3f(-5.0f, 5.0f, 5.0f); glColor3f(0.8f, 0.8f, 0.2f); glVertex3f(-5.0f, 5.0f, -5.0f); glColor3f(0.8f, 0.8f, 0.8f); glVertex3f( 0.0f, 11.0f, 0.0f); glEnd(); glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice glLoadIdentity(); // nahrat jednotkovou matici glTranslatef(0.0f, 0.0f, -50.0f); // posun objektu dale od kamery glDepthMask(GL_FALSE); // Z-buffer v rezimu read-only glEnable(GL_BLEND); // povoleni michani glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);// michaci funkce glBegin(GL_QUADS); // vykresleni dvou rovin glColor4f(1.0, 0.5, 0.5, 0.7); glVertex3f(-14.0, -8.0, 30.0); glVertex3f( -0.0, -8.0, 30.0); glVertex3f( -0.0, 8.0, 30.0); glVertex3f(-14.0, 8.0, 30.0); glColor4f(0.5, 0.5, 1.0, 0.7); glVertex3f( 0.0, -8.0, 25.0); glVertex3f( 14.0, -8.0, 25.0); glVertex3f( 14.0, 8.0, 25.0); glVertex3f( 0.0, 8.0, 25.0); glEnd(); glDepthMask(GL_TRUE); // Z-buffer v rezimu read-write glDisable(GL_BLEND); // zakazani michani 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: case 'q': exit(0); break; // pokud byla stlacena klavesa ESC, konec programu case 'f': glutFullScreen(); // prepnuti na celou obrazovku break; case 'w': glutReshapeWindow(500, 500); // prepnuti zpet do okna break; case 'e': // povoleni funkce pameti hloubky depthBufferEnabled=1; glEnable(GL_DEPTH_TEST); glutPostRedisplay(); // prekresleni sceny break; case 'd': // zakazani funkce pameti hloubky depthBufferEnabled=0; glDisable(GL_DEPTH_TEST); glutPostRedisplay(); // prekresleni sceny break; case '.': fov--; // zmenseni zorneho uhlu kamery glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) gluPerspective(fov, (double)windowWidth/(double)windowHeight, nearPlane, farPlane); glutPostRedisplay(); // prekresleni sceny break; case ',': fov++; // zvetseni zorneho uhlu kamery glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) gluPerspective(fov, (double)windowWidth/(double)windowHeight, nearPlane, farPlane); glutPostRedisplay(); // prekresleni sceny 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 if (state==GLUT_DOWN) { // pri stlaceni tlacitka stav=1; // nastaveni pro funkci motion xx=x; // zapamatovat pozici kurzoru mysi yy=y; } else { // pri pusteni tlacitka stav=0; // normalni stav xold=xnew; // zapamatovat novy pocatek yold=ynew; } } if (button==GLUT_RIGHT_BUTTON) { // pri zmene stavu praveho tlacitka if (state==GLUT_DOWN) { // pri stlaceni tlacitka stav=2; // nastaveni pro funkci motion zz=y; // zapamatovat pozici kurzoru mysi } else { // pri pusteni tlacitka stav=0; zold=znew; // 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) { if (stav==1) { // stav rotace objektu xnew=xold+x-xx; // vypocitat novou pozici ynew=yold+y-yy; glutPostRedisplay(); // a prekreslit scenu } if (stav==2) { // stav priblizeni/oddaleni objektu znew=zold+y-zz; // vypocitat novou pozici glutPostRedisplay(); // a prekreslit scenu } } //--------------------------------------------------------------------- // 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 69");// 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 //---------------------------------------------------------------------