//---------------------------------------------------------------------
// Ukazkovy priklad k serii clanku OpenGL a GLU
//
// Autor: Pavel Tisnovsky
// Cislo clanku: 3
// Cislo prikladu: 3
//
// Tento program po svem spusteni zobrazi 3D teleso nastavenou kamerou.
// Pomoci mysi a klavesnice je mozne ovlivnit vsechny parametry kamery,
// tj. parametry funkce gluLookAt().
// Se stlacenou klavesou SHIFT se modifikuje vektor "center", bez teto
// klavesy se modifikuje vektor "eye".
// Klavesou ESC je mozne program ukoncit.
//---------------------------------------------------------------------
#ifdef __BORLANDC__
#include <windows.h> // oprava chyby v nekterych Borlandskych prekladacich
#endif
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL
#ifdef __BORLANDC__
#pragma hdrstop // konec predkompilovanych hlavicek pro Borlandske prekladace
#endif
#define WINDOW_WIDTH 450 // velikost okna
#define WINDOW_HEIGHT 450
#define WINDOW_TITLE "OpenGL a GLU, priklad 3.3" // titulek okna
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 eyeX=10, eyeY=10, eyeZ=10; // pozice kamery
int centerX=0, centerY=0, centerZ=0; // bod, na ktery se kamera diva
int upX=0, upY=0, upZ=1; // vektor smerujici nahoru ke "stropu"
int newX=0, newY=0, newZ=0; // soucasna pozice, ze ktere se pocitaji dalsi parametry
int oldX=0, oldY=0, oldZ=0; // body, ve kterych se nachazi kurzor mysi
int mouseStatus=0; // stav tlacitek mysi
int modify=0; // ktery vektor se ma modifikovat
float fieldOfView=45.0; // zorny uhel - field of view
float nearClippingPlane=0.1; // blizsi orezavaci rovina
float farClippingPlane=200.0; // vzdalenejsi orezavaci rovina
//---------------------------------------------------------------------
// Funkce pro inicializaci vykreslovani
//---------------------------------------------------------------------
void onInit(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi obrazku
glClearDepth(1.0f); // implicitni hloubka ulozena v pameti hloubky
glShadeModel(GL_SMOOTH); // nastaveni stinovaciho rezimu
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
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) // 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)
gluPerspective(fieldOfView, (double)w/(double)h, nearClippingPlane, farClippingPlane);
}
//--------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//--------------------------------------------------------------------
void onDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // vymazani barvoveho a hloubkoveho bufferu
glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice
glLoadIdentity(); // nahrat jednotkovou matici
// nastaveni pozice a orientace kamery
if (modify) {
gluLookAt(eyeX, eyeY, eyeZ, centerX+newX, centerY+newY, centerZ+newZ, upX, upY, upZ);
// lze menit take vektor "up"
//gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX+newX, upY+newY, upZ+newZ);
}
else {
gluLookAt(eyeX+newX, eyeY+newY, eyeZ+newZ, centerX, centerY, centerZ, upX, upY, upZ);
}
glutSolidTeapot(5); // vykresleni telesa
glFlush(); // provedeni a vykresleni vsech zmen
glutSwapBuffers();
}
//---------------------------------------------------------------------
// Tato funkce je volana pri stlaceni ASCII klavesy
//---------------------------------------------------------------------
#ifdef __BORLANDC__
#pragma option -w-par // zabranit warningum pri prekladu
#endif // u borlandskych prekladacu
void onKeyboard(unsigned char key, int x, int y)
{
if (key>='A' && key<='Z') // uprava velkych pismen na mala
key+=(unsigned char)('a'-'A'); // pro zjednoduseni prikazu switch
switch (key) {
case 27: exit(0); break; // ukonceni aplikace
case 'q': exit(0); break; // ukonceni aplikace
default: break;
}
}
#ifdef __BORLANDC__
#pragma option -w+par
#endif
//---------------------------------------------------------------------
// Tato funkce je volana pri zmene stavu tlacitek mysi
//---------------------------------------------------------------------
void onMouseClick(int button, int state, int x, int y)
{
if (glutGetModifiers()==GLUT_ACTIVE_SHIFT) { // zjistit stav klavesy SHIFT
modify=1;
}
else {
modify=0;
}
if (button==GLUT_LEFT_BUTTON) { // leve tlacitko mysi
if (state==GLUT_DOWN) { // pri stlaceni
mouseStatus=1;
oldX=x;
oldY=y;
}
else { // pri pusteni tlacitka
mouseStatus=0;
oldX=x;
oldY=y;
}
}
if (button==GLUT_RIGHT_BUTTON) { // prave tlacitko mysi
if (state==GLUT_DOWN) { // pri stlaceni
mouseStatus=2;
oldZ=y;
}
else { // pri pusteni tlacitka
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) { //
newX=x-oldX;
newY=y-oldY;
glutPostRedisplay();
}
if (mouseStatus==2) {
newZ=y-oldZ;
glutPostRedisplay();
}
}
//---------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//---------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // nastaveni dvou barvovych bufferu a pameti hloubky
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(onMouseClick); // registrace funkce volane pri stlaceni nebo pusteni tlacitka mysi
glutMotionFunc(onMouseDrag); // registrace funkce volane pri posunu 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
//---------------------------------------------------------------------