//---------------------------------------------------------------------
// Ukazkovy priklad k serii clanku o graficke knihovne OpenGL a GLU
//
// Autor: Pavel Tisnovsky
// Cislo clanku: 21
// Cislo prikladu: 1
//
// Program otevre jedno hlavni okno a vykresli do nej slozitejsi
// polygon vytvoreny pomoci teselatoru. Pomoci mezerniku je mozne menit
// pravidla pro zjistovani vnejsi a vnitrni casti polygonu.
// Okno (a tim i celou aplikaci) lze ukoncit stiskem klavesy ESC.
//---------------------------------------------------------------------
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu
#include <stdlib.h>
#include <stdio.h>
#define WINDOW_WIDTH 450 // velikost okna
#define WINDOW_HEIGHT 250
#define WINDOW_TITLE "OpenGL a GLU, priklad 21.1"// titulek okna
#ifndef CALLBACK
#define CALLBACK
#endif
GLdouble currentWinding = GLU_TESS_WINDING_ODD;
GLUtesselator *gluTessObject;
//---------------------------------------------------------------------
// Nastaveni souradneho systemu v zavislosti na velikosti okna
//---------------------------------------------------------------------
void onResize(int w, int h) // w a h reprezentuje 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
glTranslatef(0.0, h, 0.0);
glScalef(1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//---------------------------------------------------------------------
// Callback funkce volana pri zahajeni vykreslovani graficke primitivy
//---------------------------------------------------------------------
void CALLBACK callbackBegin(GLenum which)
{
glBegin(which);
puts("glBegin");
}
//---------------------------------------------------------------------
// Callback funkce volana pri ukonceni vykreslovani graficke primitivy
//---------------------------------------------------------------------
void CALLBACK callbackEnd(void)
{
glEnd();
puts("glEnd");
}
//---------------------------------------------------------------------
// Callback funkce volana pri vyskytu chyby
//---------------------------------------------------------------------
void CALLBACK callbackError(GLenum errorCode)
{
const GLubyte *s=gluErrorString(errorCode);
fprintf(stderr, "chyba pri teselaci: %s\n", s);
exit(0);
}
//---------------------------------------------------------------------
// Tato funkce je volana pri vyskytu pruseciku dvou hran polygonu
//---------------------------------------------------------------------
void CALLBACK callbackCombine(GLdouble coords[3],
GLdouble *data[4],
GLfloat weight[4],
GLdouble **dataOut)
{
GLdouble *vertex;
vertex = (GLdouble *) malloc(3 * sizeof(GLdouble));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
*dataOut = vertex;
puts("combine");
}
//---------------------------------------------------------------------
// Tato funkce je volana pri vytvoreni kazdeho vrcholu teselovaneho
// polygonu
//---------------------------------------------------------------------
void CALLBACK callbackVertex(GLdouble coords[3])
{
printf("glVertex3d(%5.1f, %5.1f, %5.1f)\n", (float)coords[0], (float)coords[1], (float)coords[2]);
glVertex3dv(coords);
}
//---------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//---------------------------------------------------------------------
void onDisplay(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0); // nastaveni mazaci barvy na cernou
glClear(GL_COLOR_BUFFER_BIT); // vymazani bitovych rovin barvoveho bufferu
glShadeModel(GL_FLAT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // rezim vykreslovani polygonu
glEnable(GL_LINE_SMOOTH);
glColor3f(1.0f, 1.0f, 1.0f); // nastaveni barvy pro kresleni
glBegin(GL_POLYGON); // vykresleni konvexniho polygonu
{
double d=0.0;
int i;
for (i=0; i<6; i++) {
glVertex2f(120.0+100.0*sin(d), 125.0-100.0*cos(d));
d+=144.0*3.1415/180.0;
}
};
glEnd();
glColor3f(1.0f, 1.0f, 0.0f); // nastaveni barvy pro kresleni
gluTessObject=gluNewTess(); // vytvoreni objektu pro teselaci
gluTessCallback(gluTessObject, GLU_TESS_VERTEX, callbackVertex);
gluTessCallback(gluTessObject, GLU_TESS_BEGIN, callbackBegin);
gluTessCallback(gluTessObject, GLU_TESS_END, callbackEnd);
gluTessCallback(gluTessObject, GLU_TESS_ERROR, callbackError);
gluTessCallback(gluTessObject, GLU_TESS_COMBINE, callbackCombine);
gluTessProperty(gluTessObject, GLU_TESS_WINDING_RULE, currentWinding);
gluTessBeginPolygon(gluTessObject, NULL); // zahajeni noveho polygonu
gluTessBeginContour(gluTessObject); // zahajeni nove kontury
// specifikace jednotlivych vrcholu kontury
{
static GLdouble vertex[6][3];
double d=0.0;
int i;
for (i=0; i<6; i++) {
vertex[i][0]=330.0+100.0*sin(d);
vertex[i][1]=125.0-100.0*cos(d);
vertex[i][2]=0.0;
d+=144.0*3.1415/180.0;
gluTessVertex(gluTessObject, vertex[i], vertex[i]);
}
}
gluTessEndContour(gluTessObject); // konec specifikace kontury
gluTessEndPolygon(gluTessObject); // konec specifikace polygonu
gluDeleteTess(gluTessObject); // zruseni objektu teselatoru
glFlush(); // provedeni a vykresleni zmen
}
//---------------------------------------------------------------------
// Tato funkce je volana pri stlaceni ASCII klavesy
//---------------------------------------------------------------------
void onKeyboard(unsigned char key, int x, int y)
{
if (key==27) exit(0); // pokud byla stlacena klavesa ESC, konec programu
if (key==' ') {
if (currentWinding == GLU_TESS_WINDING_ODD)
currentWinding = GLU_TESS_WINDING_NONZERO;
else if (currentWinding == GLU_TESS_WINDING_NONZERO)
currentWinding = GLU_TESS_WINDING_POSITIVE;
else if (currentWinding == GLU_TESS_WINDING_POSITIVE)
currentWinding = GLU_TESS_WINDING_NEGATIVE;
else if (currentWinding == GLU_TESS_WINDING_NEGATIVE)
currentWinding = GLU_TESS_WINDING_ABS_GEQ_TWO;
else if (currentWinding == GLU_TESS_WINDING_ABS_GEQ_TWO)
currentWinding = GLU_TESS_WINDING_ODD;
glutPostRedisplay();
}
}
//---------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//---------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // nastaveni jednoho barvoveho bufferu
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
glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce
return 0; // navratova hodnota vracena operacnimu systemu
}
//---------------------------------------------------------------------
// Konec zdrojoveho souboru
//---------------------------------------------------------------------