//-----------------------------------------------------------------------------
// Fraktaly v pocitacove grafice
// Ukazkovy priklad cislo 46.1
// Autor: Pavel Tisnovsky
//
// Tato demonstracni aplikace slouzi k rekurzivnimu deleni usecky s posunem
// prostredniho bodu.
// Ukonceni aplikace se provede klavesou [Esc].
//-----------------------------------------------------------------------------
#ifdef __BORLANDC__
#include <windows.h>
#endif
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define WINDOW_TITLE "Fraktaly 46.1" // titulek okna
#define WINDOW_WIDTH 512 // pocatecni velikost okna
#define WINDOW_HEIGHT 440
int aa=0; // antialiasing
float Delta=50.0; // "amplituda" posunu bodu
//-----------------------------------------------------------------------------
// Vykresleni retezce na obrazovku
//-----------------------------------------------------------------------------
void drawString(const int x, const int y, // umisteni retezce
const float r, const float g, const float b, // barva pisma
char *str) // ukazatel na retezec
{
char *c;
glColor3f(r, g, b);
glRasterPos2i(x, y);
for (c=str; *c!=0; c++) {
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *c);
}
}
//-----------------------------------------------------------------------------
// Vypsani informaci o zadanych parametrech
//-----------------------------------------------------------------------------
void drawInfo(float Delta)
{
char str[100];
sprintf(str, "[up][down] Delta: %5.0f", Delta);
drawString(10, 10, 1.0, 1.0, 0.0, str);
}
//-----------------------------------------------------------------------------
// Vygenerovani nahodneho cisla v rozsahu 0..1
//-----------------------------------------------------------------------------
float my_random(void)
{
return (float)rand()/(float)RAND_MAX;
}
//-----------------------------------------------------------------------------
// Rekurzivne volana metoda, ktera provede rozdeleni usecky a posun
// prostredniho bodu
//-----------------------------------------------------------------------------
void mdaRecursive1D(float x1, float y1, float x2, float y2, float Delta, int iter)
{
float x,y;
if (!iter) { // pokud jsme dosahli maximalniho mnozstvi iteraci
glVertex2f(x1, y1); // vykresleni rozdelene usecky na nejnizsi urovni
glVertex2f(x2, y2);
return; // a ukonceni rekurze
}
x=(x1+x2)/2.0; // vypocet polohy prostredniho bodu
y=(y1+y2)/2.0;
y+=my_random()*Delta-Delta/2.0; // posun prostredniho bodu
mdaRecursive1D(x1, y1, x, y, Delta/2.0, iter-1); // rekurzivni volani na prvni polovinu usecky
mdaRecursive1D(x, y, x2, y2, Delta/2.0, iter-1); // rekurzivni volani na druhou polovinu usecky
}
//-----------------------------------------------------------------------------
// Prekresleni fraktalu
//-----------------------------------------------------------------------------
void recalcFractal(float Delta)
{
char str[100];
int i;
for (i=0; i<10; i++) { // pro zadany maximalni pocet iteraci
srand(123456); // nastavit vzdy stejne seminko RNG
drawString(10, 30+i*40, 0.0, 1.0, 1.0, itoa(i, str, 10));
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES); // vykresleni rozdelene usecky pro dany pocet iteraci
mdaRecursive1D(20, 30+i*40, WINDOW_WIDTH-10, 30+i*40, Delta, i);
glEnd();
}
}
//-----------------------------------------------------------------------------
// Funkce volana pro inicializaci vykreslovani
//-----------------------------------------------------------------------------
void onInit(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // mod ulozeni pixelu
// parametry pro antialiasing
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
//-----------------------------------------------------------------------------
// 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(0, w, 0, h, -1, 1); // mapovani abstraktnich souradnic do souradnic okna
}
//-----------------------------------------------------------------------------
// Tato callback funkce je zavolana pri kazdem prekresleni okna
//-----------------------------------------------------------------------------
void onDisplay(void)
{
if (aa) { // zapnuti ci vypnuti antialiasingu
glLineWidth(1.5f);
glEnable(GL_LINE_SMOOTH);
}
else {
glLineWidth(1.0f);
glDisable(GL_LINE_SMOOTH);
}
glClear(GL_COLOR_BUFFER_BIT); // vymazani vsech bitovych rovin barvoveho bufferu
drawInfo(Delta); // prekresleni informaci o fraktalu
recalcFractal(Delta); // prekresleni fraktalu
glFlush(); // provedeni a vykresleni vsech zmen
glutSwapBuffers();
}
//-----------------------------------------------------------------------------
// Tato callback funkce je zavolana pri stlaceni ASCII klavesy
//-----------------------------------------------------------------------------
#ifdef __BORLANDC__
#pragma option -w-par
#endif
void onKeyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'a':
case 'A': aa=!aa; glutPostRedisplay(); break; // zapnuti ci vypnuti antialiasingu
case 32: glutPostRedisplay(); break;
case 27: exit(0); break; // pokud byla stlacena klavesa ESC, konec programu
default: break;
}
}
#ifdef __BORLANDC__
#pragma option -w+par
#endif
//-----------------------------------------------------------------------------
// Tato callback funkce je zavolana pri stlaceni non-ASCII klavesy
//-----------------------------------------------------------------------------
#ifdef __BORLANDC__
#pragma option -w-par
#endif
void onSpecial(int key, int x, int y)
{
// posun fraktalu a zmena meritka
switch (key) {
case GLUT_KEY_UP: Delta+=5.0; glutPostRedisplay(); break;
case GLUT_KEY_DOWN: Delta-=5.0; glutPostRedisplay(); break;
default: break;
}
}
#ifdef __BORLANDC__
#pragma option -w+par
#endif
//-----------------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow(WINDOW_TITLE); // vytvoreni okna pro kresleni
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);// zmena velikosti okna
glutPositionWindow(100, 100); // pozice leveho horniho rohu 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 klavesy
glutSpecialFunc(onSpecial); // registrace funkce volane pri stlaceni specialni klavesy
onInit(); // inicializace vykreslovani
glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce
return 0; // navratova hodnota vracena operacnimu systemu
}
//-----------------------------------------------------------------------------
// finito
//-----------------------------------------------------------------------------