//---------------------------------------------------------------------
// Ukazkovy priklad cislo 57
// Autor: Pavel Tisnovsky
//
// Program, ktery zobrazi ctverec s nanesenou texturou. Pomoci leveho
// tlacitka mysi lze menit souradnice s,t v jednotlivych vrcholech
// ctverce.
//---------------------------------------------------------------------
#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_MAXX, CTRL_MINY},
{CTRL_MAXX, CTRL_MAXY},
{CTRL_MINX, CTRL_MAXY},
};
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
}
}
}
//---------------------------------------------------------------------
// Funkce pro vykresleni otexturovaneho ctverce
//---------------------------------------------------------------------
void drawSquare(void)
{
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f((float)(points[0][0]-CTRL_MINX)/DELTA_X,
(float)(points[0][1]-CTRL_MINY)/DELTA_Y);
glVertex2i( 50, 100);
glTexCoord2f((float)(points[1][0]-CTRL_MINX)/DELTA_X,
(float)(points[1][1]-CTRL_MINY)/DELTA_Y);
glVertex2i(250, 100);
glTexCoord2f((float)(points[2][0]-CTRL_MINX)/DELTA_X,
(float)(points[2][1]-CTRL_MINY)/DELTA_Y);
glVertex2i(250, 300);
glTexCoord2f((float)(points[3][0]-CTRL_MINX)/DELTA_X,
(float)(points[3][1]-CTRL_MINY)/DELTA_Y);
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_REPEAT);
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
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])<9)
&& (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 57");// 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
//---------------------------------------------------------------------