OpenGL obserwator

0
#include<windows.h>
#include<stdio.h>

/* Główna bibloteka OpenGL */
#include<GL/gl.h>
/* Biblioteka GLUT */
#include<GL/glut.h>
#include<math.h>

/* Deklaracje funkcji narzędziowych */
void DrawScene(void);
void DrawSceneAxes(void);
void InitOpenGL(void);
void ReshapeWindow(int width, int height);
void drawFractal(GLclampf a,GLclampf x, GLclampf y, GLfloat z,GLshort depth);
void drawTetraedr(GLclampf a, GLclampf x, GLclampf y, GLfloat z, GLclampf r, GLclampf g, GLclampf b);
void MouseFunc(int button, int state, int x, int y);
void MouseMotion(GLsizei x, GLsizei y);
/* Deklaracja globalnych zmiennych */
int x=1,y=1;
float light_pos[]={0.0,0.0,0.0};
GLfloat viewer_pos[] = { 10.0, 0.0, 0.0 };
GLfloat R = 10.0f;
GLfloat thetax = 0.0f;
GLfloat thetay = 0.0f;
GLfloat thetax1 = 0.0f;
GLfloat thetay1 = 0.0f;
GLfloat pixels2angle = 0.0;
GLint lbutton_status = 0;
GLint rbutton_status = 0;
GLint x_last_pos = 0; 
GLint y_last_pos = 0;
GLint x_delta = 0;
GLint y_delta = 0;
int mainWindow;
///////////////////////
GLshort Depth = 1.0;///
///////////////////////
struct vertex_coord {
    GLfloat x;
    GLfloat y;
    GLfloat z;
};
struct vertex_coord w1;
struct vertex_coord w2;
struct vertex_coord w3;
struct vertex_coord w4;

void mKeyboard(unsigned char c, int /*x*/,int /*y*/);
/* Funkcja main */
int main(int argc, char **argv){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(1000, 690);
    glutInitWindowPosition(370,10);
    mainWindow = glutCreateWindow("ZADANIE DO DOMU :)");
    if(mainWindow == 0){
        puts("Nie mozna stworzyc okna!!!\nWyjscie z programu.\n");
        exit(-1);
    }
    glutSetWindow(mainWindow);
    InitOpenGL();
    glutDisplayFunc(DrawScene);
    glutReshapeFunc(ReshapeWindow);
    glutMouseFunc(MouseFunc);
    glutMotionFunc(MouseMotion);
    glutKeyboardFunc(mKeyboard);
    glEnable(GL_DEPTH_TEST);
    glutMainLoop();
    return(0);
}
void DrawScene(void){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    gluLookAt(viewer_pos[0],viewer_pos[1],viewer_pos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    if(!x)
    {
        InitOpenGL();
    }
    DrawSceneAxes();
    if(lbutton_status == 1){
        if(x){
        thetax += x_delta*pixels2angle/50;
        thetay += y_delta*pixels2angle/50;
        }
        else{
        thetax1 += x_delta*pixels2angle/50;
        thetay1 += y_delta*pixels2angle/50;
        }
    }
    if(rbutton_status == 1){
        R+=(y_delta/2);
    }
    viewer_pos[0] = abs(R)*cos(thetax)*cos(thetay);
    viewer_pos[1] = abs(R)*sin(thetay);
    viewer_pos[2] = abs(R)*cos(thetay)*sin(thetax);

    light_pos[0] = R*cos(thetax1)*cos(thetay1);
    light_pos[1] = R*sin(thetay1);
    light_pos[2] = R*cos(thetay1)*sin(thetax1);

    printf("%lf %lf %lf \n",viewer_pos[0] ,viewer_pos[1] ,viewer_pos[2]  );
    //printf("[%lf %lf %lf] \n",light_pos[0] ,light_pos[1] ,light_pos[2]  );
    drawFractal(5.0f,0.0f,3.0f,0.0f,Depth);
    //DrawSierp(0,0,0,5, 4);
    glFlush();
    glutSwapBuffers();

}

void drawTetraedr(GLclampf a, GLclampf x, GLclampf y, GLfloat z, GLclampf r, GLclampf g, GLclampf b) {
    GLfloat h = (a * sqrt(3.0f))/2;
    GLfloat h1 = h/3;
    GLfloat h2 = 2*h1;
    glBegin(GL_TRIANGLE_STRIP);
        glColor3f(0, 0.9, 1); 

            w1.x=x;
            w1.y=y;
            w1.z=z;

            w2.x= x + 0.5*a;
            w2.y=y-h;
            w2.z=z-h1;

            w3.x=x - 0.5*a ;
            w3.y=y-h;
            w3.z=z-h1;

            w4.x= x;
            w4.y=y - h;
            w4.z=z + h2;

        glVertex3f(x, y, z);
        glVertex3f(x - 0.5*a, y-h, z-h1);
        glVertex3f(x + 0.5*a, y-h, z-h1);
        glVertex3f(x, y - h, z + h2);
        glVertex3f(x, y, z);
        glVertex3f(x - 0.5*a, y-h, z-h1);
    glEnd();
}
void drawFractal(GLclampf a,GLclampf x, GLclampf y, GLfloat z,GLshort depth){
     if(depth == 1) {
        drawTetraedr(a, x, y, z, 1.0f , 1.0f, 1.0f);
     } else {
        GLfloat h = (a * sqrt(3.0f))/2;
        GLfloat h1 = h/3;
        GLfloat h2 = 2*h1;
        GLfloat mh = ((0.5*a) * sqrt(3.0f))/2;
        GLfloat mh1 = mh/3;
        GLfloat mh2 = (2*mh)/3;
        drawFractal(0.5*a,x,y,z,depth-1);
        drawFractal(0.5*a,x,y-mh,z+h2-mh2,depth-1);
        drawFractal(0.5*a,x-0.25*a,y-mh,z-h1+mh1,depth-1);
        drawFractal(0.5*a,x+0.25*a,y-mh,z-h1+mh1,depth-1);
     }
}
void MouseFunc(int button, int state, int x, int y){
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
        x_last_pos = x;
        y_last_pos = y;
        lbutton_status = 1;
    } else {
        lbutton_status = 0;
    }
    if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
        x_last_pos = x;
        y_last_pos = y;
        rbutton_status = 1;
    } else {
        rbutton_status = 0;
    }
}
void MouseMotion(GLsizei x, GLsizei y){
    x_delta = x - x_last_pos;
    y_delta = y - y_last_pos;
    x_last_pos = x;
    y_last_pos = y;
    glutPostRedisplay();
}
void DrawSceneAxes(void)
{
    // Definiujemy nowy typ jako tablicę 3-elementową
    typedef float pt3d[3];

    // Początek i koniec osi X
    pt3d x_beg = { -10.0f, 0.0f, 0.0f };
    pt3d x_end = {  10.0f, 0.0f, 0.0f };

    // Poczatek i koniec osi Y
    pt3d y_beg = { 0.0f, -10.0f, 0.0f };
    pt3d y_end = { 0.0f,  10.0f, 0.0f };

    // Początek i koniec osi Z
    pt3d z_beg = { 0.0f, 0.0f, -10.0f };
    pt3d z_end = { 0.0f, 0.0f,  10.0f };

    // Rysujemy osie
    glBegin(GL_LINES);
        // Czerwony kolor dla osi X
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3fv(x_beg);
        glVertex3fv(x_end);

        // Zielony kolor dla osi Y
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3fv(y_beg);
        glVertex3fv(y_end);

        // Niebieski kolor dla osi Z
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3fv(z_beg);
        glVertex3fv(z_end);
    glEnd();

}
void InitOpenGL(void){
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // współczynniki ka =[kar,kag,ka dla światła otoczenia
    GLfloat mat_ambient[] = {1.0, 1.0, 1.0, 1.0};    
    // współczynniki kd =[kdr,kdg,kd światła rozproszonego
    GLfloat mat_diffuse[] = {1.0, 1.0, 1.0, 1.0};
    // współczynniki ks =[ksr,ksg,ks dla światła odbitego 
    GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0};               
    // współczynnik n opisujący połysk powierzchni
    GLfloat mat_shininess  = {20.0};

    //światło 1 
    // składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
    GLfloat light_ambient1[] = {2.0, 0.0, 0.0, 1.0};
    // składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
    GLfloat light_diffuse1[] = {2.0, 0.0, 0.0, 1.0};
    // składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
    GLfloat light_specular1[] = {2.0, 0.0, 0.0, 1.0};

    //światło 2
    // składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
    GLfloat light_ambient2[] = {0.0, 0.1, 0.0, 1.0};
    // składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
    GLfloat light_diffuse2[] = {0.0, 2.0, 0.0, 1.0};    
    // składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
    GLfloat light_specular2[] = {0.0, 2.0, 0.0, 1.0};

    //światło 3
    // składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
    GLfloat light_ambient3[] = {0.0, 0.0, 0.1, 1.0};
    // składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
    GLfloat light_diffuse3[] = {0.0, 0.0, 2.0, 1.0};    
    // składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
    GLfloat light_specular3[] = {0.0, 0.0, 2.0, 1.0};

    //światło 4
    // składowe intensywności świecenia źródła światła otoczenia// Ia = [Iar,Iag,Iab
    GLfloat light_ambient4[] = {0.0, 0.1, 0.1, 1.0};
    // składowe intensywności świecenia źródła światła powodującego// odbicie dyfuzyjne Id = [Idr,Idg,Id
    GLfloat light_diffuse4[] = {0.0, 1.0, 1.0, 1.0};    
    // składowe intensywności świecenia źródła światła powodującego// odbicie kierunkowe Is = [Isr,Isg,Is
    GLfloat light_specular4[] = {0.0, 1.0, 1.0, 1.0};

    GLfloat light_position1[] = {0.0 + light_pos[0],10.0 + light_pos[1],0.0 + light_pos[2], 0.0};
    GLfloat light_position2[] = {0.0 + light_pos[0],3.0 + light_pos[1],-9.0 + light_pos[2], 0.0};
    GLfloat light_position3[] = {8.3 + light_pos[0],3.0 + light_pos[1],4.5 + light_pos[2], 0.0};
    GLfloat light_position4[] = {-7.8 +light_pos[0],4.5 + light_pos[1],4.3 + light_pos[2], 0.0};
    // składowa stała ds dla modelu zmian oświetlenia w funkcji // odległości od źródła
    GLfloat att_constant  = {1.0};
    // składowa liniowa dl dla modelu zmian oświetlenia w funkcji // odległości od źródła
    GLfloat att_linear    = {0.05}; 
    // składowa kwadratowa dq dla modelu zmian oświetlenia w funkcji// odległości od źródła
    GLfloat att_quadratic  = {0.001};

// Ustawienie parametrów materiału i źródła światła

// Ustawienie patrametrów materiału 

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);

// Ustawienie parametrów źródła

    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient1);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse1);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular1);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position1);

    glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient2);
    glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse2);
    glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular2);
    glLightfv(GL_LIGHT1, GL_POSITION, light_position2);

    glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient3);
    glLightfv(GL_LIGHT2, GL_DIFFUSE, light_diffuse3);
    glLightfv(GL_LIGHT2, GL_SPECULAR, light_specular3);
    glLightfv(GL_LIGHT2, GL_POSITION, light_position3);

    glLightfv(GL_LIGHT3, GL_AMBIENT, light_ambient4);
    glLightfv(GL_LIGHT3, GL_DIFFUSE, light_diffuse4);
    glLightfv(GL_LIGHT3, GL_SPECULAR, light_specular4);
    glLightfv(GL_LIGHT3, GL_POSITION, light_position4);

    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, att_quadratic);

    glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, att_quadratic);

    glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, att_quadratic);

    glLightf(GL_LIGHT3, GL_CONSTANT_ATTENUATION, att_constant);
    glLightf(GL_LIGHT3, GL_LINEAR_ATTENUATION, att_linear);
    glLightf(GL_LIGHT3, GL_QUADRATIC_ATTENUATION, att_quadratic);

    // Ustawienie opcji systemu oświetlania sceny 

    glShadeModel(GL_SMOOTH); // właczenie łagodnego cieniowania
    glEnable(GL_LIGHTING);   // właczenie systemu oświetlenia sceny 
    glEnable(GL_LIGHT0);     // włączenie źródła o numerze 0
    glEnable(GL_LIGHT1);
    glEnable(GL_LIGHT2);
    glEnable(GL_LIGHT3);

        glEnable(GL_DEPTH_TEST); // włączenie mechanizmu z-bufora 

}

void ReshapeWindow(int width, int height){
    pixels2angle = 360.0f/(float)width;
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity();
    gluPerspective(70.0, 1.0, 1.0, 40.0);
    if(width <= height)
    glViewport(0, (height - width)/2, width, width);  
    else
    glViewport((width - height)/2, 0, height, height); 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void mKeyboard(unsigned char c, int /*x*/,int /*y*/)
{
        switch(c)
        {
        case 45:
            if(Depth > 1)
                Depth--;
            DrawScene();
            printf("%d",Depth);

            break;
        case 43:
            if(Depth < 10)
            Depth++;
            DrawScene();
            printf("%d",Depth);
            break;
        case 49:
            if(x)x=0;
            else 
            x=1;DrawScene();
            break;
        case 50://?
            if(y)
            {   glEnable(GL_LIGHT0);     // włączenie źródła o numerze 0
                glEnable(GL_LIGHT1);
                glEnable(GL_LIGHT2);
                glEnable(GL_LIGHT3);
                y=0;
            }
            else 
            {
            glDisable(GL_LIGHT0);     // włączenie źródła o numerze 0
            glDisable(GL_LIGHT1);
            glDisable(GL_LIGHT2);
            glDisable(GL_LIGHT3);
            y=1;
            }
            DrawScene();
            break;
        case 27:
            printf("wyjscie z programu");
            exit(-1);   
        default:
            printf("%d - %c\n",c,c);
        }
}

Pytanie brzmi, dlaczego jak ruszam obserwatorem wzdłuż osi Y ( przy przejściu na 2gą stronę czworościanu) tworzy się nagle przeskok , i jak to naprawić ? Proszę o pomoc

0

Z tego co widze próbujesz zrobić coś a'la Arcball (http://aklimx.sppieniezno.pl/nehepl/display.php?id=48).

Przeskok związany jest albo ze zmianą położenia kamery w linijce:


gluLookAt(viewer_pos[0],viewer_pos[1],viewer_pos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

albo z samymi współrzędnymi wierzchołków fraktala które zmieniasz w trakcie renderingu. Chyba tylko w tych dwóch przypadkach
przekształcasz wierzchołki.
Magiczne wzory odpowiadają chyba z obrót, tak?:

> 
```cpp
 viewer_pos[0] = abs(R)*cos(thetax)*cos(thetay);
 viewer_pos[1] = abs(R)*sin(thetay);
 viewer_pos[2] = abs(R)*cos(thetay)*sin(thetax); 

Może tu leży problem. Sam je wyprowadziłeś?
Do obrotu znacznie wygodniej będzie ci użyć operacji na macierzach jak w linku powyżej.

Zamiast fraktala ustaw sobie jakiś sześcian z wierzchołkami na sztywno i zobacz co się stanie. Jeśli nadal lipa to wina kamery,
a dokładniej wspomnianych wzorów liczących jej pozycje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0