//---------------------------------------------------------------------
// Ukazkovy priklad k serii clanku OpenGL a GLU
//
// Autor:          Pavel Tisnovsky
// Cislo clanku:   10
// Cislo prikladu: 3
//
// Zobrazeni prubehu funkce b2() pomoci lomene cary.
// Pomoci klavesy 'f' lze provest prepnuti do celeho okna, klavesou 'w'
// se provede nastaveni puvodni velikosti okna, tj. 450x450 pixelu.
// Klavesou ESC je mozne program ukoncit.
//---------------------------------------------------------------------



#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#define WINDOW_WIDTH    450                         // velikost okna
#define WINDOW_HEIGHT   600
#define WINDOW_TITLE    "OpenGL a GLU, priklad 10.3" // titulek okna

// bazove funkce
float b0(const float t, const int i);
float b1(const float t, const int i);
float b2(const float t, const int i);
float b3(const float t, const int i);

#define MAX 6

// x-ove souradnice ridicich bodu
float x[MAX]={000,000,100,100,200,300};

// y-ove souradnice ridicich bodu
float y[MAX]={000,100,100,000,000,100};

// uzlovy vektor
float knot[]={0,0,0,1,2,3,4,4,4};



//---------------------------------------------------------------------
// Bazova funkce b0()
//---------------------------------------------------------------------
float b0(const float t, const int i)
{
    float   p;

    if ((knot[i]<=t)&&(t<knot[i+1])) p=1.0;
    else                             p=0.0;
    return  p;
}



//---------------------------------------------------------------------
// Bazova funkce b1()
//---------------------------------------------------------------------
float b1(const float t, const int i)
{
    float   p,a,b;

    a=(t-knot[i]);
    b=(knot[i+1]-knot[i]);
    if (b==0)   p=0.0;
    else        p=b0(t,i)*a/b;

    a=(knot[i+2]-t);
    b=(knot[i+2]-knot[i+1]);
    if (b==0)   p+=0.0;
    else        p+=b0(t,i+1)*a/b;

    return  p;
}



//---------------------------------------------------------------------
// Bazova funkce b2()
//---------------------------------------------------------------------
float b2(const float t, const int i)
{
    float   p,a,b;

    a=(t-knot[i]);
    b=(knot[i+2]-knot[i]);
    if (b==0)   p=0.0;
    else        p=b1(t,i)*a/b;

    a=(knot[i+3]-t);
    b=(knot[i+3]-knot[i+1]);
    if (b==0)   p+=0.0;
    else        p+=b1(t,i+1)*a/b;

    return  p;
}



//---------------------------------------------------------------------
// Bazova funkce b3()
//---------------------------------------------------------------------
float b3(const float t, const int i)
{
    float   p,a,b;

    a=(t-knot[i]);
    b=(knot[i+3]-knot[i]);
    if (b==0)   p=0.0;
    else        p=b2(t,i)*a/b;

    a=(knot[i+4]-t);
    b=(knot[i+4]-knot[i+1]);
    if (b==0)   p+=0.0;
    else        p+=b2(t,i+1)*a/b;

    return  p;
}



//---------------------------------------------------------------------
// Funkce pro inicializaci vykreslovani
//---------------------------------------------------------------------
void onInit(void)
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glEnable(GL_LINE_SMOOTH);
}



//--------------------------------------------------------------------
// Tato funkce je volana pri kazdem prekresleni okna
//--------------------------------------------------------------------
void onDisplay(void)
{
    float d,f,x,y;
    int i,j;
    glClear(GL_COLOR_BUFFER_BIT);

    // vykresleni prubehu bazove funkce b0()
    for (i=0; i<6; i++) {                           // ctyri ruzne prubehu pro ctyri pozice v uzlovem vektoru
        glBegin(GL_LINE_STRIP);
        for (d=0; d<4; d+=0.05) {                   // smycka pro vypocet bodu na krivce
            x=50+80.0*d;
            f=b2(d, i);                             // vypocet hodnoty funkce b2()
            y=100*i+80-60.0*f;
            glVertex2f(x,y);                        // vykresleni dalsiho vrcholu lomene cary
        }
        glEnd();
    }
    glFlush();
}



//---------------------------------------------------------------------
// Nastaveni souradneho systemu v zavislosti na velikosti okna
//---------------------------------------------------------------------
void onResize(GLsizei w, GLsizei h)
{
    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
    glScalef(1, -1, 1);                             // inverze y-ove osy, aby se y zvetsovalo smerem dolu
    glTranslatef(0, -h, 0);                         // posun pocatku do leveho horniho rohu
}



//---------------------------------------------------------------------
// 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
        case 'f':   glutFullScreen();   break;      // prepnuti na celou obrazovku
        case 'w':   glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT); 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_RGB);                  // 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
    onInit();                                       // inicializace vykreslovani
    glutMainLoop();                                 // nekonecna smycka, kde se volaji zaregistrovane funkce
    return 0;                                       // navratova hodnota vracena operacnimu systemu
}



//---------------------------------------------------------------------
// Konec zdrojoveho souboru
//---------------------------------------------------------------------