//---------------------------------------------------------------------
// Ukazkovy priklad cislo 25
// Autor: Pavel Tisnovsky
//
// V tomto programu se provede nastaveni kamery v ortogonalnim rezimu.
// Pote se vykresli jednoduche teleso ve tvaru domecku, se kterym lze
// rotovat a posouvat pomoci mysi (podle stlaceneho tlacitka mysi).
// Domecek se poprve vykresli jako vyplneny model, ale pomoci klaves
// '0' az '9' lze provest prepnuti na jiny zpusob vykreslovani.
// Pod domeckem je vykreslena mrizka, aby se vykreslovani trosku
// zpomalilo a byl videt vyznam double-bufferingu.
// V tomto prikladu je double-buffering pouzit.
//---------------------------------------------------------------------
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL
#include <stdio.h>
int xnew=0, ynew=0, xnew2=0, ynew2=0; // soucasna pozice mysi, ze ktere se pocitaji rotace a posuny
int xold=0, yold=0, xold2=0, yold2=0; // minula pozice mysi, ze ktere se pocitaji rotace a posuny
int xx, yy, xx2, yy2; // bod, ve kterem se nachazi kurzor mysi
int stav; // stav tlacitek mysi
//---------------------------------------------------------------------
// Funkce pro inicializaci vykreslovani
//---------------------------------------------------------------------
void onInit(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi
glPolygonMode(GL_FRONT, GL_FILL); // nastaveni rezimu vykresleni polygonalniho modelu
glPolygonMode(GL_BACK, GL_FILL); // jak pro zadni tak pro predni steny
glDisable(GL_CULL_FACE); // zadne hrany ani steny se nebudou odstranovat
glPointSize(5.0); // velikost vykreslovanych bodu
glEnable(GL_POINT_SMOOTH); // povoleni antialiasingu bodu
}
//---------------------------------------------------------------------
// 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(-20, 20, -20, 20, -30, 30); // nastaveni ortogonalni projekce
// zkuste zde zmenit polohu orezavacich ploch
}
//---------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//---------------------------------------------------------------------
void onDisplay(void)
{
float i;
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(xnew2/10.0f, -ynew2/10.0f, 0.0f); // posun objektu podle pohybu kurzoru mysi
gluLookAt(4.0f, 4.0f, 18.0f, // bod, odkud se kamera diva
0.0f, 0.0f, 0.0f, // bod, kam se kamera diva
0.0f, 1.0f, 0.0f); // poloha "stropu" ve scene
glRotatef(ynew, 1.0f, 0.0f, 0.0f); // rotace objektu podle pohybu kurzoru mysi
glRotatef(xnew, 0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINES);
for (i=-10.0f; i<=10.0f; i+=0.5f) { // vykresleni mrizky pod domeckem pro zdrzeni
glVertex3f(-10.0f, -5.0f, i);
glVertex3f( 10.0f, -5.0f, i);
glVertex3f( i, -5.0f, -10.0f);
glVertex3f( i, -5.0f, 10.0f);
}
glEnd();
glBegin(GL_QUADS); // vykresleni otevrene krychle - sten domecku
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f(-5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 5.0f, -5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, -5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 0.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glEnd();
glBegin(GL_TRIANGLES); // vykresleni strechy domecku z trojuhelniku
glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 5.0f, 5.0f, 5.0f);
glColor3f(0.0f, 1.0f, 1.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, 5.0f);
glColor3f(1.0f, 1.0f, 0.0f); glVertex3f(-5.0f, 5.0f, -5.0f);
glColor3f(1.0f, 1.0f, 1.0f); glVertex3f( 0.0f, 11.0f, 0.0f);
glEnd();
glFlush(); // provedeni a vykresleni vsech zmen
glutSwapBuffers(); // 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 '1': // prepnuti na zobrazeni pouze vrcholu
glPolygonMode(GL_FRONT,GL_POINT);
glPolygonMode(GL_BACK,GL_POINT);
glutPostRedisplay();
break;
case '2': // prepnuti na zobrazeni dratoveho modelu
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_LINE);
glutPostRedisplay();
break;
case '3': // prepnuti na zobrazeni vyplnenych sten
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_FILL);
glutPostRedisplay();
break;
case '4': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_LINE);
glutPostRedisplay();
break;
case '5': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_FILL);
glutPostRedisplay();
break;
case '6': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_POINT);
glPolygonMode(GL_BACK,GL_FILL);
glutPostRedisplay();
break;
case '7': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_POINT);
glutPostRedisplay();
break;
case '8': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_POINT);
glPolygonMode(GL_BACK,GL_LINE);
glutPostRedisplay();
break;
case '9': // dalsi mozny zpusob vykreslovani polygonu
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_POINT);
glutPostRedisplay();
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) { // reakce na zmenu stavu leveho tlacitka mysi
if (state==GLUT_DOWN) { // pri stlaceni
stav=1; // nastaveni pro funkci motion
xx=x; // zapamatovat pozici kurzoru mysi
yy=y;
}
else { // GLUT_UP
stav=0; // normalni stav
xold=xnew; // zapamatovat novy pocatek rotace
yold=ynew;
}
}
if (button==GLUT_RIGHT_BUTTON) { // reakce na zmenu stavu praveho tlacitka mysi
if (state==GLUT_DOWN) { // pri stlaceni
stav=2; // nastaveni pro funkci motion
xx2=x; // zapamatovat pozici kurzoru mysi
yy2=y;
}
else { // GLUT_UP
stav=0; // normalni stav
xold2=xnew2; // zapamatovat novy pocatek posunu
yold2=ynew2;
}
}
glutPostRedisplay(); // prekresleni sceny
}
//---------------------------------------------------------------------
// Tato funkce je volana pri pohybu mysi se stlacenym tlacitkem
// To, ktere tlacitko je stlaceno si musime zaznamenat do glob. promenne
//---------------------------------------------------------------------
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 presunu objektu
xnew2=xold2+x-xx2; // vypocitat novou pozici
ynew2=yold2+y-yy2;
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);// nastaveni predniho a zadniho barvoveho bufferu
glutInitWindowPosition(30, 30); // pocatecni pozice leveho horniho rohu okna
glutInitWindowSize(500, 500); // pocatecni velikost okna
glutCreateWindow("Priklad na OpenGL cislo 25");// 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
//---------------------------------------------------------------------