//--------------------------------------------------------------------- // Ukazkovy priklad cislo 61 // Autor: Pavel Tisnovsky // // Program, ktery zobrazi ctverec s nanesenou texturou. Pomoci leveho // tlacitka mysi lze menit souradnice s,t v jednotlivych vrcholech // ctverce v rozmezi 0.0-2.0. Je nastaveno opakovani textury ve smeru // souradne osy 's' a protazeni textury ve smeru souradne osy 't'. //--------------------------------------------------------------------- #include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL #define TEXTURE_WIDTH 64 // sirka textury zadana v texelech #define TEXTURE_HEIGHT 64 // vyska textury zadana v texelech #define CTRL_MINX 300 // mezni hodnoty pro ridici body na obrazovce #define CTRL_MAXX 500 #define CTRL_MINY 100 #define CTRL_MAXY 300 #define DELTA_X (CTRL_MAXX-CTRL_MINX) // sirka ctverce s ridicimi body #define DELTA_Y (CTRL_MAXY-CTRL_MINY) // vyska ctverce s ridicimi body unsigned int points[4][2]={ // souradnice s,t v texture {CTRL_MINX, CTRL_MINY}, // prevedene na souradnice v okne {CTRL_MINX+DELTA_X/2, CTRL_MINY}, {CTRL_MINX+DELTA_X/2, CTRL_MINY+DELTA_Y/2}, {CTRL_MINX, CTRL_MINY+DELTA_Y/2}, }; unsigned char texture[TEXTURE_HEIGHT][TEXTURE_WIDTH][4];// pole pro ulozeni pixmapy textury int activePoint=-1; // vybrany ridici bod int height; // vyska okna //--------------------------------------------------------------------- // 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&0x08)==0)^((j&0x08))==0)) * 255; *P++=(unsigned char)c; // zapsat barevne slozky RGB *P++=(unsigned char)(i<<2); *P++=(unsigned char)(j<<2); *P++=(unsigned char)255; // alfa slozka } } } //--------------------------------------------------------------------- // Vycisleni souradnice 's' nebo 't' zadaneho vrcholu //--------------------------------------------------------------------- float getTexCoord(int vertex, int st) { if (!st) return (float)(points[vertex][0]-CTRL_MINX)/DELTA_X*2.0; else return (float)(points[vertex][1]-CTRL_MINY)/DELTA_Y*2.0; } //--------------------------------------------------------------------- // 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 souradnic v texture //--------------------------------------------------------------------- void drawInformations(void) { char str[100]; int i; glDisable(GL_TEXTURE_2D); glColor3f(1.0f, 1.0f, 1.0f); for (i=0; i<4; i++) { // vsechny ctyri vrcholy sprintf(str, "tex.coord %d: [%4.2f, %4.2f]", i, getTexCoord(i, 0), getTexCoord(i, 1)); printString(10, 75-i*18, str); } } //--------------------------------------------------------------------- // Funkce pro vykresleni otexturovaneho ctverce //--------------------------------------------------------------------- void drawSquare(void) { glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(getTexCoord(0, 0), getTexCoord(0, 1)); glVertex2i( 50, 100); glTexCoord2f(getTexCoord(1, 0), getTexCoord(1, 1)); glVertex2i(250, 100); glTexCoord2f(getTexCoord(2, 0), getTexCoord(2, 1)); glVertex2i(250, 300); glTexCoord2f(getTexCoord(3, 0), getTexCoord(3, 1)); glVertex2i( 50, 300); glEnd(); } //--------------------------------------------------------------------- // Funkce pro vykresleni mezi ridicich bodu //--------------------------------------------------------------------- void drawControlField(void) { glDisable(GL_TEXTURE_2D); glColor3f(0.8f, 0.8f, 0.8f); glBegin(GL_LINE_LOOP); glVertex2i(CTRL_MINX-5, CTRL_MINY-5); glVertex2i(CTRL_MAXX+5, CTRL_MINY-5); glVertex2i(CTRL_MAXX+5, CTRL_MAXY+5); glVertex2i(CTRL_MINX-5, CTRL_MAXY+5); glEnd(); } //--------------------------------------------------------------------- // Funkce pro vykresleni ridicich bodu //--------------------------------------------------------------------- void drawControlPoints(void) { int i; glDisable(GL_TEXTURE_2D); glColor3f(0.7f, 0.7f, 1.0f); glBegin(GL_LINE_LOOP); for (i=0; i<=3; i++) glVertex2i(points[i][0], points[i][1]); glEnd(); glPointSize(5.0f); glBegin(GL_POINTS); for (i=0; i<=3; i++) glVertex2i(points[i][0], points[i][1]); glEnd(); } //--------------------------------------------------------------------- // Funkce pro vykresleni aktivniho ridiciho bodu //--------------------------------------------------------------------- void drawActivePoint(void) { if (activePoint==-1) return; glDisable(GL_TEXTURE_2D); glColor3f(1.0f, 0.7f, 0.7f); glPointSize(8.0f); glBegin(GL_POINTS); glVertex2i(points[activePoint][0], points[activePoint][1]); glEnd(); } //--------------------------------------------------------------------- // Funkce pro inicializaci vykreslovani //--------------------------------------------------------------------- void onInit(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi obrazku 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 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_CLAMP); // a protazeni textury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // volba filtru glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, // nahrani rastrovych dat do textury TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// vylepseni zobrazovani glEnable(GL_POINT_SMOOTH); // povoleni antialiasingu bodu glEnable(GL_TEXTURE_2D); // povoleni texturovani } //--------------------------------------------------------------------- // 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) glOrtho(0, w, 0, h, -1, 1); // mapovani abstraktnich souradnic do souradnic okna height=h; } //-------------------------------------------------------------------- // Tato funkce je volana pri kazdem prekresleni okna //-------------------------------------------------------------------- void onDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // vymazani barvoveho bufferu i pameti hloubky drawSquare(); // vykresleni otexturovaneho ctverce drawControlField(); // vykresleni mezi ridicich bodu drawControlPoints(); // vykresleni ridicich bodu drawActivePoint(); // vykresleni aktivniho ridiciho bodu drawInformations(); // vykresleni souradnic v texture 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) { int i; if (button==GLUT_LEFT_BUTTON) { // pri zmene stavu leveho tlacitka if (state==GLUT_DOWN) { // pri stlaceni tlacitka activePoint=-1; for (i=0; i<=3; i++) { // najit ridici bod pod kurzorem if ((abs(x-points[i][0])<11) && (abs(height-y-points[i][1]<9))) { activePoint=i; // bod jsme nasli glutPostRedisplay(); return; } } } else { // pri pusteni tlacitka mysi activePoint=-1; // zrusit aktivni bod glutPostRedisplay(); } } } //--------------------------------------------------------------------- // Tato funkce je volana pri pohybu mysi se stlacenym tlacitkem. //--------------------------------------------------------------------- void onMouseMotion(int x, int y) { if (activePoint==-1) return; // neni vybran zadny ridici bod y=height-y; if (x>=CTRL_MINX && x<=CTRL_MAXX) // kurzor mysi je v zadanem ctverci points[activePoint][0]=x; // posunout ridici bod if (y>=CTRL_MINY && y<=CTRL_MAXY) points[activePoint][1]=y; glutPostRedisplay(); } //--------------------------------------------------------------------- // Hlavni funkce konzolove aplikace //--------------------------------------------------------------------- int main(int argc, char **argv) { glutInit(&argc, argv); // inicializace knihovny GLUT glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);// nastaveni dvou barvovych bufferu a pameti hloubky glutInitWindowPosition(30, 30); // pocatecni pozice leveho horniho rohu okna glutInitWindowSize(550, 400); // pocatecni velikost okna glutCreateWindow("Priklad na OpenGL cislo 61");// 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 //---------------------------------------------------------------------