//---------------------------------------------------------------------
// Priklad cislo 18
// Autor: Pavel Tisnovsky
//
// Vykresleni trojrozmernych objektu vytvorenych v knihovne GLUT.
//---------------------------------------------------------------------
#include <math.h>
#include <GL/glut.h>
float materialAmbient[]={0.3, 0.2, 0.2, 1.0}; // ambientni slozka materialu
float materialDiffuse[]={0.9, 0.1, 0.1, 1.0}; // difuzni slozka materialu
float materialSpecular[]={0.0, 1.0, 1.0, 0.5}; // barva odlesku
float lightAmbient[]= {0.5, 0.5, 0.5, 1.0}; // ambientni slozka svetla
float lightDiffuse[]= {0.9, 0.9, 0.9, 1.0}; // difuzni slozka svetla
float lightSpecular[]={0.0, 0.0, 0.0, 1.0}; // barva odlesku
float lightPosition[]={1.0, 1.0, 1.0, 0.0}; // definice pozice svetla
int newX=0, newY=0, newZ=0; // soucasna pozice, ze ktere se pocitaji rotace a posuny
int oldZ=0; // minula pozice, ze ktere se pocitaji posuny
int mouseX=0, mouseY=0, mouseZ=0; // body, ve kterych se nachazi kurzor mysi
int mouseStatus=0; // stav tlacitek mysi
float fieldOfView=45.0; // zorny uhel - field of view
float nearClippingPlane=0.1; // blizsi orezavaci rovina
float farClippingPlane=200.0; // vzdalenejsi orezavaci rovina
int objectType=9; // typ vykreslovaneho objektu
//---------------------------------------------------------------------
// Tato funkce provede zakladni nastaveni vykreslovani teles
//---------------------------------------------------------------------
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); // barva pro mazani color-bufferu
glShadeModel(GL_SMOOTH); // nastaveni Gouraudova stinovani
glClearDepth(1.0f); // barva pro mazani Z-bufferu
glEnable(GL_DEPTH_TEST); // nastaveni funkce pro testovani hodnot v Z-bufferu
glDepthFunc(GL_LESS); // nastaveni porovnavaci funkce pro Z-buffer
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);// vylepseni zobrazovani pri vypoctu perspektivy
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // stav vykresleni vyplnenych polygonu
glPointSize(5.0); // velikost vykreslovanych bodu
glLineWidth(3.0); // sirka vykreslovanych car
glEnable(GL_POINT_SMOOTH); // povoleni antialiasingu bodu
glEnable(GL_LINE_SMOOTH); // povoleni antialiasingu car
glLightfv(GL_LIGHT0,GL_AMBIENT,lightAmbient); // nastaveni parametru svetla
glLightfv(GL_LIGHT0,GL_DIFFUSE,lightDiffuse);
glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);
glEnable(GL_LIGHTING); // povoleni osvetleni
glEnable(GL_LIGHT0); // zapnuti prvniho svetla
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,materialAmbient);// nastaveni vlastnosti materialu
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,materialDiffuse);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,materialSpecular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.0);
}
//---------------------------------------------------------------------
// Nastaveni souradneho systemu v zavislosti na velikosti okna
//---------------------------------------------------------------------
void onResize(int w, int h)
{
glViewport(0, 0, w, h); // viditelna oblast
glMatrixMode(GL_PROJECTION); // zmena projekcni matice
glLoadIdentity(); // nastaveni perspektivni projekce
gluPerspective(fieldOfView, (double)w/(double)h, nearClippingPlane, farClippingPlane);
glMatrixMode(GL_MODELVIEW); // zmena modelove matice
}
//---------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//---------------------------------------------------------------------
void onDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // vymazani barvoveho bufferu
glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice
glLoadIdentity(); // nahrat jednotkovou matici
glTranslatef(0.0f, 0.0f, -50.0f); // posun modelu dale od kamery
glTranslatef(0.0f, 0.0f, newZ);
glRotatef(newY, 1.0, 0.0, 0.0); // rotace objektu podle pohybu kurzoru mysi
glRotatef(newX, 0.0, 1.0, 0.0);
switch (objectType) { // vykresleni vybraneho objektu
case 0: glutWireCube(5); break;
case 1: glutWireSphere(5, 16, 16); break;
case 2: glutWireCone(5, 5, 16, 16); break;
case 3: glutWireTorus(2, 5, 16, 16); break;
case 4: glScalef(3,3,3); glutWireDodecahedron(); break;
case 5: glScalef(3,3,3); glutWireOctahedron(); break;
case 6: glScalef(3,3,3); glutWireTetrahedron(); break;
case 7: glScalef(3,3,3); glutWireIcosahedron(); break;
case 8: glutWireTeapot(5); break;
case 9: glutSolidCube(5); break;
case 10: glutSolidSphere(5,16,16); break;
case 11: glutSolidCone(5,5,16,16); break;
case 12: glutSolidTorus(2,5,16,16); break;
case 13: glScalef(3,3,3); glutSolidDodecahedron(); break;
case 14: glScalef(3,3,3); glutSolidOctahedron(); break;
case 15: glScalef(3,3,3); glutSolidTetrahedron(); break;
case 16: glScalef(3,3,3); glutSolidIcosahedron(); break;
case 17: glutSolidTeapot(5); break;
}
glFlush(); // provedeni vsech prikazu
glutSwapBuffers(); // a prohozeni bufferu
}
//---------------------------------------------------------------------
// Tato funkce je volana pri stlaceni ASCII klavesy
//---------------------------------------------------------------------
void onKeyboard(unsigned char key, int x, int y)
{
key=(key>'A' && key<='Z') ? key+'a'-'A':key; // prevod na mala pismena
switch (key) { // rozeskok podle stlacene klavesy
case 27: // klavesa Escape
exit(0); // ukonceni programu
break;
case 'f':
glutFullScreen(); // prepnuti na celou obrazovku
break;
case 'w':
glutReshapeWindow(500, 500); // prepnuti zpet do okna
glutPositionWindow(50, 50);
break;
default:
break;
}
}
//---------------------------------------------------------------------
// Tato funkce je volana pri zmene stavu tlacitek mysi
//---------------------------------------------------------------------
void onMouseClick(int button, int state, int x, int y)
{
if (button==GLUT_RIGHT_BUTTON) { // prave tlacitko aktivuje posun od pozorovatele
if (state==GLUT_DOWN) { // pri stlaceni
mouseStatus=1; // nastaveni pro funkci motion
mouseZ=y; // zapamatovat pozici kurzoru mysi
}
else {
mouseStatus=0;
oldZ=newZ; // zapamatovat novy pocatek
}
}
glutPostRedisplay(); // prekresleni sceny
}
//---------------------------------------------------------------------
// Tato funkce je volana pri posunu mysi se stlacenym tlacitkem
//---------------------------------------------------------------------
void onMouseDrag(int x, int y)
{
if (mouseStatus==1) { // provadi se presun
newZ=oldZ+y-mouseZ; // vypocitat novou pozici
glutPostRedisplay(); // a prekreslit scenu
}
}
//---------------------------------------------------------------------
// Tato funkce je volana pri posunu mysi bez stlaceneho tlacitka
//---------------------------------------------------------------------
void onMouseMove(int x, int y)
{
newX=x; // zapamatovat si pozici kurzoru
newY=y; // pro otaceni
glutPostRedisplay(); // prekreslit scenu
}
//---------------------------------------------------------------------
// Tato funkce je zavolana pri vyberu polozky z menu
//---------------------------------------------------------------------
void onCommand(int command)
{
if (command<18) // byla vybrana polozka s nazvem objektu
objectType=command;
switch (command) {
case 18: // zobrazovat se budou pouze vrcholy polygonu
glPolygonMode(GL_FRONT,GL_POINT);
glPolygonMode(GL_BACK,GL_POINT);
break;
case 19: // zobrazovat se budou pouze hrany polygonu
glPolygonMode(GL_FRONT,GL_LINE);
glPolygonMode(GL_BACK,GL_LINE);
break;
case 20: // zobrazovat se budou vyplnene polygony
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_FILL);
break;
case 21: // ukonceni aplikace
exit(0);
default:
break;
}
glutPostRedisplay(); // prekreslit scenu
}
//---------------------------------------------------------------------
// Tato funkce vytvori menu a navaze ho na leve tlacitko mysi
//---------------------------------------------------------------------
void createMenu(void)
{
int i, j, k, l;
i=glutCreateMenu(onCommand); // vytvoreni submenu a registrace callback funkce
glutAddMenuEntry("Wireframe cube", 0);
glutAddMenuEntry("Wireframe sphere", 1);
glutAddMenuEntry("Wireframe cone", 2);
glutAddMenuEntry("Wireframe torus", 3);
glutAddMenuEntry("Wireframe dodecahedron", 4);
glutAddMenuEntry("Wireframe octahedron", 5);
glutAddMenuEntry("Wireframe tetrahedron", 6);
glutAddMenuEntry("Wireframe icosahedron", 7);
glutAddMenuEntry("Wireframe teapot", 8);
j=glutCreateMenu(onCommand); // vytvoreni submenu a registrace callback funkce
glutAddMenuEntry("Solid cube", 9);
glutAddMenuEntry("Solid sphere", 10);
glutAddMenuEntry("Solid cone", 11);
glutAddMenuEntry("Solid torus", 12);
glutAddMenuEntry("Solid dodecahedron", 13);
glutAddMenuEntry("Solid octahedron", 14);
glutAddMenuEntry("Solid tetrahedron", 15);
glutAddMenuEntry("Solid icosahedron", 16);
glutAddMenuEntry("Solid teapot", 17);
k=glutCreateMenu(onCommand); // vytvoreni submenu a registrace callback funkce
glutAddMenuEntry("Points", 18);
glutAddMenuEntry("Lines", 19);
glutAddMenuEntry("Fill", 20);
l=glutCreateMenu(onCommand); // vytvoreni submenu a registrace callback funkce
glutAddMenuEntry("Yes", 21);
glutAddMenuEntry("No", 22);
glutCreateMenu(onCommand); // vytvoreni menu
glutAddSubMenu("Wireframe objects", i);
glutAddSubMenu("Solid objects", j);
glutAddSubMenu("Polygon mode", k);
glutAttachMenu(GLUT_LEFT_BUTTON);
}
//---------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//---------------------------------------------------------------------
int main(int argc, char *argv[])
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); // graficky mod okna
glutInitWindowSize(500, 500); // pocatecni velikost okna
glutInitWindowPosition(10, 10); // pocatecni pozice okna
glutCreateWindow("Priklad cislo 18"); // vytvoreni okna pro kresleni
glutReshapeWindow(500, 500); // nastaveni velikosti okna
glutDisplayFunc(onDisplay); // registrace funkce volane pri prekreslovani okna
glutReshapeFunc(onResize); // registrace funkce volane pri zmene velikosti okna
glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stlaceni ASCII klavesy
glutMouseFunc(onMouseClick); // registrace funkce volane pri stlaceni nebo pusteni tlacitka mysi
glutMotionFunc(onMouseDrag); // registrace funkce volane pri posunu mysi se stlacenym tlacitkem
glutPassiveMotionFunc(onMouseMove); // registrace funkce volane pri posunu mysi bez stlaceneho tlacitka
init(); // inicializace vykreslovani
createMenu(); // vytvoreni menu s vyberem telesa
glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce
return 0; // navratova hodnota vracena operacnimu systemu
}
//---------------------------------------------------------------------
// Konec zdrojoveho souboru
//---------------------------------------------------------------------