//--------------------------------------------------------------------- // Ukazkovy priklad cislo 80 // Autor: Pavel Tisnovsky // // Po spusteni tohoto demonstracniho programu se zobrazi cajova konvicka, // na jejimz povrchu je nanesena jednoducha 2D textura, stejne jako u // demonstracnich prikladu 78 a 79. Pomoci klavesy [S] se da zapinat a // vypinat test na Scissor Box, stejne jako u prikladu 79. Pomoci klavesy // [T] se da zapinat a vypinat Scissor Test. Pri zapnutem Scissor Testu // prosvita pod konvickou jiny obrazek - modra koule. // Pomoci leveho tlacitka mysi lze telesem otacet, prave tlacitko // slouzi k priblizeni nebo vzdaleni telesa od kamery. //--------------------------------------------------------------------- #ifdef __BORLANDC__ #include <windows.h> #endif #include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL #define WINDOW_WIDTH 450 // velikost okna #define WINDOW_HEIGHT 450 #define WINDOW_TITLE "Priklad na OpenGL cislo 80"// titulek okna #define TEXTURE_WIDTH 64 // rozmery textury #define TEXTURE_HEIGHT 64 #define GRAY_MATERIAL 1 // symbolicka jmena pouzitych materialu #define BLUE_MATERIAL 2 enum { // operace, ktere se mohou provadet s mysi: ROTATE, // rotace objektu TRANSLATE, // posun objektu } operation=ROTATE; int xnew=30, ynew=30, znew=30; // soucasna pozice mysi, ze ktere se pocitaji rotace a posuvy int xold=30, yold=30, 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 int scissorTest=0; // priznak provadeni scissor testu int stencilTest=1; // priznak provadeni stencil testu unsigned char texture[TEXTURE_HEIGHT][TEXTURE_WIDTH][4];// pole pro ulozeni pixmapy textury // parametry sedeho materialu konvicky GLfloat grayMaterialAmbient[]={0.3f, 0.3f, 0.3f, 1.0f}; // ambientni slozka barvy materialu GLfloat grayMaterialDiffuse[]={0.8f, 0.4f, 0.4f, 1.0f}; // difuzni slozka barvy materialu GLfloat grayMaterialSpecular[]={1.0f, 1.0f, 1.0f, 1.0f};// barva odlesku GLfloat grayMaterialShininess[]={30.0f}; // faktor odlesku // parametry modreho materialu koule GLfloat blueMaterialAmbient[]={0.1f, 0.1f, 0.1f, 1.0f}; // ambientni slozka barvy materialu GLfloat blueMaterialDiffuse[]={0.1f, 0.1f, 0.7f, 1.0f}; // difuzni slozka barvy materialu GLfloat blueMaterialSpecular[]={0.2f, 1.0f, 1.0f, 1.0f};// barva odlesku GLfloat blueMaterialShininess[]={30.0f}; // faktor odlesku // parametry svetel GLfloat lightPosition[]={1.0f, 1.0f, 1.0f, 0.0f}; // pozice svetla GLfloat lightAmbient[]={1.0f, 1.0f, 1.0f, 1.0f}; // ambientni slozka svetla //--------------------------------------------------------------------- // Vytvoreni rastroveho vzorku pro texturu //--------------------------------------------------------------------- void makeRasterTexture(void) { int i,j,c; // pocitadla smycek unsigned char * P; // ukazatel na zapisovany subtexel for (j=0; j<TEXTURE_HEIGHT; j++) { // pro vsechny radky pixmapy P=texture[j][0]; for (i=0; i<TEXTURE_WIDTH; i++) { // pro vsechny texely na radku c=((((i&0x20)==0)^((j&0x20))==0)) * 255; *P++=(unsigned char)c; // zapsat barevne slozky RGB *P++=(unsigned char)c; *P++=(unsigned char)c; *P++=(unsigned char)255; // alfa slozka texelu } } } //--------------------------------------------------------------------- // Nastaveni parametru textury //--------------------------------------------------------------------- void setTextureParameters(void) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // zpusob ulozeni bytu v texture 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); // pri zmene meritka glTexImage2D(GL_TEXTURE_2D, 0, 4, // nahrani rastrovych dat do textury TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);// nastaveni rezimu textury glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);// korektni mapovani textur glEnable(GL_TEXTURE_2D); // povoleni texturovani } //--------------------------------------------------------------------- // Nastaveni parametru svetla //--------------------------------------------------------------------- void setLightParameters(void) { glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);// nastaveni pozice svetla glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glEnable(GL_LIGHTING); // globalni povoleni stinovani glEnable(GL_LIGHT0); // povoleni prvniho svetla } //--------------------------------------------------------------------- // Nastaveni parametru materialu telesa //--------------------------------------------------------------------- void setMaterialParameters(void) { glNewList(GRAY_MATERIAL, GL_COMPILE); // prvni material glMaterialfv(GL_FRONT, GL_AMBIENT, grayMaterialAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, grayMaterialDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, grayMaterialSpecular); glMaterialfv(GL_FRONT, GL_SHININESS, grayMaterialShininess); glEndList(); glNewList(BLUE_MATERIAL, GL_COMPILE); // druhy material glMaterialfv(GL_FRONT, GL_AMBIENT, blueMaterialAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, blueMaterialDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, blueMaterialSpecular); glMaterialfv(GL_FRONT, GL_SHININESS, blueMaterialShininess); glEndList(); } //--------------------------------------------------------------------- // Funkce pro inicializaci vykreslovani //--------------------------------------------------------------------- void onInit(void) { glClearColor(0.5f, 0.5f, 0.5f, 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 setTextureParameters(); // nastaveni parametru textury setLightParameters(); // nastaveni parametru osvetleni setMaterialParameters(); // nastaveni parametru materialu telesa glClearStencil(0x00); // nastaveni mazaci hodnoty stencil bufferu } //--------------------------------------------------------------------- // 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 } //--------------------------------------------------------------------- // Nastaveni perspektivni projekce //--------------------------------------------------------------------- void setPerspectiveProjection(void) { glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) gluPerspective(50.0, (double)windowWidth/(double)windowHeight, 0.1f, 90.0f);// nastaveni perspektivni kamery glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice glLoadIdentity(); // nahrat jednotkovou matici } //--------------------------------------------------------------------- // 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 informacniho textu do okna //--------------------------------------------------------------------- void displayInfoText(void) { setOrthogonalProjection(); // nastaveni ortogonalni kamery glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); // zakaz jakekoli zmeny barvy glColor3f(1.0, 1.0, 1.0); printString(10, 24, "Press [S] to enable/disable scissor test"); printString(10, 10, "Press [T] to enable/disable stencil test"); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); } //--------------------------------------------------------------------- // 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; // prekresleni sablony glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w<=h) gluOrtho2D(-3.0, 3.0, -3.0*h/w, 3.0*h/w); else gluOrtho2D(-3.0*w/h, 3.0*w/h, -3.0, 3.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_STENCIL_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x01, 0x01); // kreslit do stencil bufferu glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glBegin(GL_QUADS); // vykresleni maskovaci plochy glVertex2f(-1.5, 0.0); glVertex2f( 0.0, 1.5); glVertex2f( 1.5, 0.0); glVertex2f( 0.0, -1.5); glEnd(); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // nemenit hodnoty ve stencil bufferu glFlush(); glutSwapBuffers(); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); } //-------------------------------------------------------------------- // Tato funkce je volana pri kazdem prekresleni okna //-------------------------------------------------------------------- void onDisplay(void) { if (scissorTest) { glEnable(GL_SCISSOR_TEST); if (windowWidth>100 && windowHeight>100) glScissor(50, 50, windowWidth-100, windowHeight-100); } else { glDisable(GL_SCISSOR_TEST); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// vymazani barvoveho bufferu i pameti hloubky displayInfoText(); 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); if (stencilTest) glEnable(GL_STENCIL_TEST); // povoleni testovani fragmentu vuci stencil bufferu glStencilFunc(GL_NOTEQUAL, 0x01, 0x01); // zobraz konvicku tam, kde neni stencil roven 1 glCallList(GRAY_MATERIAL); // nastavit modry material glutSolidTeapot(7.0f); // vykresleni cajove konvicky glStencilFunc(GL_EQUAL, 0x01, 0x01); // kouli zobraz tam, kde je stencil roven 1 setPerspectiveProjection(); glTranslatef(0.0f, 0.0f, -30.0f); // posun objektu dale od kamery glDisable(GL_TEXTURE_2D); glCallList(BLUE_MATERIAL); glutSolidSphere(7.0f, 64, 64); glEnable(GL_TEXTURE_2D); glDisable(GL_STENCIL_TEST); glFlush(); // provedeni a vykresleni vsech zmen glutSwapBuffers(); // a prohozeni predniho a zadniho bufferu } //--------------------------------------------------------------------- // Tato funkce je volana pri stlaceni ASCII klavesy //--------------------------------------------------------------------- #ifdef __BORLANDC__ #pragma option -w-par #endif 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 's': scissorTest=!scissorTest; // povoleni/zakazani scissor testu glutPostRedisplay();break; case 't': stencilTest=!stencilTest; // povoleni/zakazani stencil testu glutPostRedisplay();break; default: break; } } #ifdef __BORLANDC__ #pragma option -w+par #endif //--------------------------------------------------------------------- // 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 | GLUT_STENCIL);// nastaveni dvou barvovych bufferu, pameti hloubky a stencil bufferu 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 //---------------------------------------------------------------------