/////////////////////////////////////////////////////////////////////////////// // Zaklady pocitacove grafiky // Cviceni #7 // // Autor: Adam Herout, modified by Michal Spanel // // Obsah cviceni: "Informativni nejzakladnejsi zaklady OpenGL" // // Demonstrovane jevy: // - OpenGL + GLUT // - vykreslovani // - display-listy // - barvy // - osvetleni // - pruhlednost // - stencil buffer // // *) Ovladani programu: // mys + leve tl. - rotace cele sceny // mys + prave tl. - priblizeni sceny // 1,2,3 - polygony vyplnit, carami, body // // Opravy: // /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // include #ifdef _WIN32 # include #endif #include #include //#include #include #include #include /////////////////////////////////////////////////////////////////////////////// // globalni konstanty // titulek hlavniho okna const char * PROGRAM_TITLE = "IZG Labs #07, Informativni nejzakladnejsi zaklady OpenGL"; const float fov = 45.0; // zorny uhel - field of view const float near_plane = 10.0; // blizsi orezavaci rovina const float far_plane = 250.0; // zdalenejsi orezavaci rovina const int default_w = 600; // defaultni velikost okna const int default_h = 600; /////////////////////////////////////////////////////////////////////////////// // globalni promenne int scene_rot_x = 0; // rotace sceny dana mysovanim int scene_rot_y = 0; int scene_move_z = -50; // posuv sceny int time = 0; // virtualni cas [s] /////////////////////////////////////////////////////////////////////////////// // zakladni nastaveni OpenGL // - funkce se vola jednou, pri zacatku programu // void Init(void) { // nastaveni clear color glClearColor(0.0, 0.0, 0.0, 0.0); // parametry svetla GLfloat light_ambient[] = {0.5, 0.5, 0.5, 1.0}; // ambientni slozka svetla GLfloat light_specular[] = {0.8, 0.8, 0.8, 1.0}; // barva odlesku GLfloat light_diffuse[] = {0.9, 0.9, 0.9, 1.0}; // difuzni slozka svetla GLfloat light_position[] = {15.0, 0.0, 0.0, 1.0}; // definice pozice svetla // nastaveni svetla glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); // nastaveni osvetlovaciho modelu // glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT); // povoleni z-bufferu glClearDepth(1000.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // velikost bodu, pokud se nejaky kresli... glPointSize(5.0); } /////////////////////////////////////////////////////////////////////////////// // vygenerovani display-listu ozubeneho kolecka // - funkce se vola pri zacatku programu // - vraci id vytvoreneho display-listu // zakladni parametry kolecka #define COG_COUNT 14 // pocet zubu kola #define RADIUS 4.0 // radius kola (vnitrni radius zubu) // dalsi parametry kolecka #define COG_HEIGHT 1.0 // vyska zubu #define RADIUS_AXLE 1.0 // radius diry pro osu v kole #define WHEEL_THICKNESS 3.0 // tloustka kola #define CONST_PI 3.141592653589793 // identifikator display-listu kolecka int wheel; int wheel2; int InitWheelDisplayList(double radius, int cog_count) { double phi = 0; // vygeneruje identifikator display-listu int id = glGenLists(1); // naplneni display-listu s koleckem glNewList(id, GL_COMPILE); { glBegin(GL_QUADS); // vykreslujem same ctyruhelniky for (int i = 0; i < cog_count; i++) { // pro kazdy zub... glNormal3f(0, 0, -1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 2/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 2/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 2/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 2/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glNormal3f(cos(phi + 2/7.0*2*CONST_PI/cog_count/2), sin(phi + 2/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 2/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 2/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0 ); glVertex3f((radius+COG_HEIGHT)*cos(phi + 2/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 2/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), WHEEL_THICKNESS/2.0); glNormal3f(0, 0, 1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 2/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 2/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 2/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 2/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glNormal3f(-cos(phi + 2/7.0*2*CONST_PI/cog_count/2), -sin(phi + 2/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 2/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 2/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 2/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 2/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); phi += 2/7.0*2*CONST_PI/cog_count; glNormal3f(0, 0, -1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 1/7.0*2*CONST_PI/cog_count), radius*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glNormal3f(cos(phi + 1/7.0*2*CONST_PI/cog_count/2), sin(phi + 1/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 1/7.0*2*CONST_PI/cog_count), radius*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 1/7.0*2*CONST_PI/cog_count), radius*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), WHEEL_THICKNESS/2.0); glNormal3f(0, 0, 1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi), (radius+COG_HEIGHT)*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 1/7.0*2*CONST_PI/cog_count), radius*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glNormal3f(-cos(phi + 1/7.0*2*CONST_PI/cog_count/2), -sin(phi + 1/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); phi += 1/7.0*2*CONST_PI/cog_count; glNormal3f(0, 0, -1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 3/7.0*2*CONST_PI/cog_count), radius*sin(phi + 3/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 3/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 3/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glNormal3f(cos(phi + 3/7.0*2*CONST_PI/cog_count/2), sin(phi + 3/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(radius*cos(phi), radius*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 3/7.0*2*CONST_PI/cog_count), radius*sin(phi + 3/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 3/7.0*2*CONST_PI/cog_count), radius*sin(phi + 3/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), WHEEL_THICKNESS/2.0); glNormal3f(0, 0, 1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi + 3/7.0*2*CONST_PI/cog_count), radius*sin(phi + 3/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 3/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 3/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glNormal3f(-cos(phi + 3/7.0*2*CONST_PI/cog_count/2), -sin(phi + 3/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 3/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 3/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 3/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 3/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); phi += 3/7.0*2*CONST_PI/cog_count; glNormal3f(0, 0, -1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 1/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glNormal3f(cos(phi + 1/7.0*2*CONST_PI/cog_count/2), sin(phi + 1/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(radius*cos(phi), radius*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 1/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 1/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), WHEEL_THICKNESS/2.0); glNormal3f(0, 0, 1); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f(radius*cos(phi), radius*sin(phi), WHEEL_THICKNESS/2.0); glVertex3f((radius+COG_HEIGHT)*cos(phi + 1/7.0*2*CONST_PI/cog_count), (radius+COG_HEIGHT)*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glNormal3f(-cos(phi + 1/7.0*2*CONST_PI/cog_count/2), -sin(phi + 1/7.0*2*CONST_PI/cog_count/2), 0.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), -WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi + 1/7.0*2*CONST_PI/cog_count), RADIUS_AXLE*sin(phi + 1/7.0*2*CONST_PI/cog_count), WHEEL_THICKNESS/2.0); glVertex3f(RADIUS_AXLE*cos(phi), RADIUS_AXLE*sin(phi), WHEEL_THICKNESS/2.0); phi += 1/7.0*2*CONST_PI/cog_count; } // konec cyklu pro kazdy zub glEnd(); // GL_QUADS } glEndList(); // to je ke kolecku vsechno... // vratime identifikator display-listu return id; } /////////////////////////////////////////////////////////////////////////////// // vygenerovani display-listu pro dva materialy // - funkce se vola jednou, pri zacatku programu // identifikatory display-listu pro materialy int red_mat, blue_mat; void InitMaterialDisplayLists() { // vygenerujeme display listy pro dva dulezite materialy red_mat = glGenLists(1); // cerveny material - display-list glNewList(red_mat, GL_COMPILE); // budeme plnit prislusny display-list { GLfloat mat_diffuse[] = {0.9, 0.0, 0.0, 1.0}; // difuzni (matna) slozka materialu GLfloat mat_ambient[] = {0.2, 0.2, 0.2, 1.0}; // ambient (rozptylena) slozka materialu GLfloat mat_specular[] = {0.5, 0.5, 0.5, 1.0}; // spekularni (odleskova) slozka materialu glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80); // lesklost materialu - 1-128 } glEndList(); // konec cerveneho materialu // vygenerujeme display-list pro modry material blue_mat = glGenLists(1); glNewList(blue_mat, GL_COMPILE); { GLfloat mat_diffuse[] = {0.0, 0.0, 0.9, 1.0}; // difuzni slozka materialu GLfloat mat_ambient[] = {0.2, 0.2, 0.2, 1.0}; // ambient (rozptylena) slozka materialu GLfloat mat_specular[] = {0.5, 0.5, 0.5, 1.0}; // spekularni slozka materialu glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 120); } glEndList(); // konec popisu modreho materialu } /////////////////////////////////////////////////////////////////////////////// // vygenerovani textury - bitmapy RGBA o vhodnych rozmerech // - funkce se vola jednou, pri zacatku programu // parametry textury #define TEXTURE_WIDTH 256 // sirka textury - musi byt mocnina 2 #define TEXTURE_HEIGHT 256 // vyska textury - musi byt mocnina 2 // pole kde budou data textury unsigned char texture[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4]; // identifikator ("jmeno") textury unsigned texid; void InitTexture() { unsigned char *p = texture; // ukazatel, ktery "leze" pres texturu for (int i = 0; i < TEXTURE_HEIGHT; ++i) { for (int j = 0; j < TEXTURE_WIDTH; ++j) { *p++ = (((int)(i+10*(sin(j/20.0)+1))&0x10)^(j&0x10)) ? 0xff:160; // red *p++ = (((int)(i+10*(sin(j/20.0)+1))&0x10)^(j&0x10)) ? 0xff:180; // green *p++ = (((int)(i+10*(sin(j/20.0)+1))&0x10)^(j&0x10)) ? 0xff:180; // blue *p++ = (((int)(i+10*(sin(j/20.0)+1))&0x10)^(j&0x10)) ? 0xff:160; // alpha } } // vygeneruje (prideli) identifikator textury - ulozi do promenne texid glGenTextures(0, &texid); // texid bude aktivni textura glBindTexture(GL_TEXTURE_2D, texid); // nastaveni parametru textury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // vytvoreni textury - podle naseho vygenerovaneho pole v promenne texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); } /////////////////////////////////////////////////////////////////////////////// // nastaveni souradneho systemu podle velikosti okna // - funkci zavola GLUT vzdy, kdyz se zmeni rozmery okna void onReshape(int w, int h) { glViewport(0, 0, w, h); // viditelna oblast glMatrixMode(GL_PROJECTION); // nastavujeme projekcni matici glLoadIdentity(); // nahrat jednotkovou matici gluPerspective(fov, (double)w / (double)h, near_plane, far_plane); // perspektivni projekce glMatrixMode(GL_MODELVIEW); // modelova matice glLoadIdentity(); } /////////////////////////////////////////////////////////////////////////////// // tato funkce je volana pro prekresleni okna // - vola ji GLUT, kdyz okno vystoupi do popredi, nebo kdyz si to // objedname funkci glutPostRedisplay() void onDisplay(void) { // vymazani bufferu glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); // bude se menit modelova matice glLoadIdentity(); // nahrat jednotkovou matici //////////////////////////////////////////////////////////////// // nastaveni kamery glTranslatef(0.0f, 0.0f, scene_move_z); // posun sceny podle pohybu mysi glRotatef(scene_rot_x, 1.0, 0.0, 0.0); // rotace sceny podle pohybu kurzoru mysi glRotatef(scene_rot_y, 0.0, 1.0, 0.0); //////////////////////////////////////////////////////////////// // vykresleni sceny // kolecka vpredu #if 1 glPushMatrix(); // zapamatovat souradny system glTranslatef(0.0, 0.0, 6.0); glCallList(red_mat); // cerveny material - display-list glPushMatrix(); // zapamatujem souradny system glCallList(wheel); // vykreslime kolecko glPopMatrix(); // vratime souradny system glCallList(blue_mat); glPushMatrix(); glRotatef(time, 0, 0, 1); glTranslatef(((2 * RADIUS + COG_HEIGHT) / 2) + 2.5, 0, 0); glRotatef(2 * time - 14, 0, 0, 1); glCallList(wheel2); glPopMatrix(); glPopMatrix(); // vratit zapamatovany souradny system #endif // vykresleni POLOHY zrcadla do stencil-bufferu glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // zakaze zapis do color-bufferu glDepthMask(GL_FALSE); // zakaze zapis do depth-bufferu glEnable(GL_CULL_FACE); // vykreslovani jen licu polygonu glEnable(GL_STENCIL_TEST); // zapne praci se stencil-bufferem glStencilFunc(GL_ALWAYS, 1, 1); // zapis VZDY glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // inkrementujeme hodnotu ve stencil-bufferu glBegin(GL_QUADS); // obdelnik glVertex3f(-16.0, -11.0, 0.0); glVertex3f( 16.0, -11.0, 0.0); glVertex3f( 16.0, 11.0, 0.0); glVertex3f(-16.0, 11.0, 0.0); glEnd(); glDisable(GL_CULL_FACE); // vratit nastaveni - licove i rubove strany polygonu glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // vratit nastaveni - bude se kreslit glDepthMask(GL_TRUE); // vratit nastaveni - bude se psat do depth-bufferu #if 1 // kolecka jeste jednou - tentokrate za zrcadlem glEnable(GL_STENCIL_TEST); // zapne praci se stencil-bufferem glStencilFunc(GL_EQUAL, 1, 1); // podminka stencil bufferu - musi tam byt 1 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // operace stencil bufferu - necha tam, co bylo glPushMatrix(); glScalef(1.0, 1.0, -1.0); glTranslatef(0, 0, 6); glCallList(red_mat); glPushMatrix(); glCallList(wheel); glPopMatrix(); glCallList(blue_mat); glPushMatrix(); glRotatef(time, 0, 0, 1); glTranslatef(((2 * RADIUS + COG_HEIGHT) / 2) + 2.5, 0, 0); glRotatef(2 * time - 14, 0, 0, 1); glCallList(wheel2); glPopMatrix(); glPopMatrix(); glDisable(GL_STENCIL_TEST); // vratit nastaveni - vypneme praci se stencil bufferem #endif // mrizka z car dole glDisable(GL_LIGHTING); // nepracujeme se svetlem - porad stejne sede glColor3f(0.5, 0.5, 0.5); // seda barva glLineWidth(1.0); // tloustka cary - 1 pixel glBegin(GL_LINES); // budem kreslit cary for (int i = -10; i <= 10; i++) { glColor3f(1, 0, 0); glVertex3f(1.5*i, -11.0, -20.0); glColor3f(0, 1, 0); glVertex3f(1.5*i, -11.0, 20.0); glColor3f(1, 1, 1); glVertex3f(-20.0, -11.0, 1.5*i); glColor3f(0, 0, 0); glVertex3f( 20.0, -11.0, 1.5*i); } glEnd(); glEnable(GL_LIGHTING); // vratit nastaveni - zapnout osvetleni #if 1 // material zrcadla GLfloat mat_diffuse[] = {0.8, 0.8, 0.0, 1.0}; // difuzni (matna) slozka materialu GLfloat mat_ambient[] = {0.4, 0.4, 0.0, 1.0}; // ambient (rozptylena) slozka materialu GLfloat mat_specular[]= {0.6, 0.9, 0.7, 1.0}; // specular (odleskova) slozka materialu glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125); // vykresleni zrcadla s texturou, ktera udava barvy a pruhlednost glEnable(GL_TEXTURE_2D); // zapnout texturovani glEnable(GL_BLEND); // zapnout pruhlednost glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // pruhlednostni funkce - alpha slozka materialu glBegin(GL_QUADS); glNormal3f(0.0, 0.0, 1.0); // nastaveni normaloveho vektoru glTexCoord2f(0.0, 0.0); glVertex3f(-16.0, -11.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f( 16.0, -11.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f( 16.0, 11.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-16.0, 11.0, 0.0); glEnd(); glDisable(GL_BLEND); // vratit nastaveni - vypnout michani/pruhlednost glDisable(GL_TEXTURE_2D); // vratit nastaveni - vypnout texturovani #endif // takrka povinne ukonceni glFlush(); // provedeni vsech prikazu glutSwapBuffers(); // a prohozeni bufferu } /////////////////////////////////////////////////////////////////////////////// // funkce volana pri stisku klavesy // - vola ji GLUT, kdyz uzivatel stiskne klavesu void onKeyboard(unsigned char key, int x, int y) { // uprava velkych pismen na mala if (key >= 'A' && key <= 'Z') key += 'a' - 'A'; // rozeskok podle stlacene klavesy switch (key) { // prepnuti na zobrazeni pouze vrcholu case '1': glPolygonMode(GL_FRONT, GL_FILL); glPolygonMode(GL_BACK, GL_FILL); break; // prepnuti na zobrazeni dratoveho modelu case '2': glPolygonMode(GL_FRONT, GL_LINE); glPolygonMode(GL_BACK, GL_LINE); break; // prepnuti na zobrazeni vyplnenych sten case '3': glPolygonMode(GL_FRONT, GL_POINT); glPolygonMode(GL_BACK, GL_POINT); break; // ukonceni programu case 27: // klavesa Escape case 'q': case 'x': exit(0); break; // prepnuti na celou obrazovku case 'f': glutFullScreen(); break; // prepnuti zpet do okna case 'w': glutReshapeWindow(default_w, default_h); break; default: break; } // vyvolani prekresleni OpenGL okna glutPostRedisplay(); } /////////////////////////////////////////////////////////////////////////////// // funkce volana pri stisku tlacitek mysi // - vola GLUT, kdyz uzivatel stiskne tlacitko mysi int old_mouse_x = 0, old_mouse_y = 0; // minula pozice mysi, ze ktere se pocitaji rotace int stav = 0; // stav tlacitek mysi void onMouseClick(int button, int state, int x, int y) { // zapamatovat pozici kurzoru mysi old_mouse_x = x; old_mouse_y = y; if (button == GLUT_LEFT_BUTTON) { // leve tlacitko aktivuje rotaci stav = (state == GLUT_DOWN) ? 1 : 0; // otestuj stlaceni } else if (button == GLUT_RIGHT_BUTTON) { // prave tlacitko aktivuje posun stav = (state == GLUT_DOWN) ? 2 : 0; // otestuj stlaceni } else { stav = 0; } // prekresleni sceny glutPostRedisplay(); } /////////////////////////////////////////////////////////////////////////////// // funkce volana jestlize se mys pohybuje a je stlaceno nektere tlacitko // - vola GLUT, kdyz uzivatel pohne mysi void onMouseMotion(int x, int y) { if (stav == 1) { // rotace sceny scene_rot_y += x - old_mouse_x; // vypocitat novou pozici scene_rot_x += y - old_mouse_y; glutPostRedisplay(); // a prekreslit scenu } else if (stav == 2) { // posuv sceny scene_move_z += old_mouse_y - y; glutPostRedisplay(); } // zapamatovat novou pozici kurzoru old_mouse_x = x; old_mouse_y = y; } /////////////////////////////////////////////////////////////////////////////// // funkce volana 40x za sekundu // - vola GLUT void onTimer(int x) { time++; // zaznacime, ze doslo ke zmene stavu glutPostRedisplay(); // a rekneme, ze ma dojit k prekresleni glutTimerFunc(25, onTimer, 0); // naplanujeme, ze za dalsich 25ms se ma funkce zavolat } /////////////////////////////////////////////////////////////////////////////// // hlavni funkce koznolove aplikace // argc - pocet vstupnich parametru // argv - pole vstupnich parametru int main(int argc, char **argv) { // inicializace knihovny GLUT glutInit(&argc, argv); // nastaveni grafickeho modu okna glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); // pocatecni velikost okna glutInitWindowSize(default_w, default_h); // pocatecni pozice okna // glutInitWindowPosition(200, 100); // vytvoreni okna pro kresleni glutCreateWindow(PROGRAM_TITLE); // registrace funkce volane pri prekreslovani glutDisplayFunc(onDisplay); // registrace funkce volane pri zmene velikosti glutReshapeFunc(onReshape); // registrace funkce volane pri stisku klavesy glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stisku tlacitek mysi glutMouseFunc(onMouseClick); // registrace funkce volane pri pohybu mysi glutMotionFunc(onMouseMotion); // registrace funkce volane za 25 milisekund glutTimerFunc(25, onTimer, 0); // provest nasi uzivatelskou inicializaci Init(); InitMaterialDisplayLists(); wheel = InitWheelDisplayList(RADIUS, COG_COUNT); wheel2 = InitWheelDisplayList(RADIUS/2, COG_COUNT/2); InitTexture(); // nekonecna smycka volajici registrovane funkce glutMainLoop(); // ANSI C potrebuje ukoncit fci main prikazem return return 0; } /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////