2016-10-09 1 views
0

J'ai la fonction moveCamera() qui fait tourner la caméra autour de la sphère centrale.Fonction OpenGL et gluLookAt

void moveCamera() 
{ 
    glLoadIdentity(); 
    int vec = ceil(theta/3.1415); 
    int y; 
    if (vec%2) 
     y = 1; 
    else 
     y = -1; 
    gluLookAt(e_x, e_y, e_z, 0, 0, 0, 0, y, 0); 
} 

Cette fonction est appelée à l'intérieur de l'affichage()

void display() 
{ 
    glClearColor(0, 0, 0, 1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    moveCamera(); 

    glCallList(idList); 

    GLfloat pos[] = {0, 0, 0, 1}; 
    glLightfv(GL_LIGHT0, GL_POSITION, pos); 

    glFinish(); 
} 

Dans cette situation, tout fonctionne très bien. Mais j'ai remarqué certaines choses que je ne peux pas expliquer.

Par exemple, si je modifie l'affichage() fonction pour dessiner la ligne rouge dans l'axe X direction comme celui-ci

void display() 
{ 
    glClearColor(0, 0, 0, 1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    glColor3ub(255, 0, 0); 
    glLineWidth(5); 
    glBegin(GL_LINES); 
     glVertex3i(0, 0, 0); 
     glVertex3i(1000, 0, 0); 
    glEnd(); 

    moveCamera(); 

    glCallList(idList); 

    GLfloat pos[] = {0, 0, 0, 1}; 
    glLightfv(GL_LIGHT0, GL_POSITION, pos); 

    glFinish(); 
} 

... rien ne se passait. Pourquoi??? Un autre, si je supprime glLoadIdentity() après glClear() la ligne rouge va dessiner, mais quand je bouge la caméra par les boutons du clavier, je vois un bug dans le rendu de cette ligne (la ligne change leurs coordonnées pour dessiner). Pour le voir, lancez mon code.

Le code complet:

#include <iostream> 
#include <glut.h> 
#include <math.h> 
#include <QDebug> 
using namespace std; 

#define WIDTH 1024 
#define HEIGHT 600 

void display(); 
void reshape(int width, int height); 
void keyboard(unsigned char key, int x, int y); 
void moveCamera(); 
void init(); 
void mkList(); 
void enableLight(); 
//double z(const double &x, const double &y); 
void printMatrix(double *m) 
{ 
    for (int i = 0; i < 4; i++) 
     qDebug() << QString("%1 %2 %3 %4").arg(m[i*4]).arg(m[i*4+1]).arg(m[i*4+2]).arg(m[i*4+3]); 
    qDebug() << "\n"; 
} 

GLuint idList = 0; 

double e_x = 0; 
double e_y = 0; 
double e_z = 0; 
double r = 300; 
double phi = 0; 
double theta = 1.5; 

int main(int argc, char **argv) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH); 
    glutInitWindowSize(WIDTH, HEIGHT); 
    glutInitWindowPosition(30, 100); 
    glutCreateWindow("Lab#2"); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape); 
    glutKeyboardFunc(keyboard); 

    glEnable(GL_DEPTH_TEST); 
    init(); 
    mkList(); 
    enableLight(); 

    glutMainLoop(); 
    return 0; 
} 

void display() 
{ 
    glClearColor(0, 0, 0, 1); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    glColor3ub(255, 0, 0); 
    glLineWidth(5); 
    glBegin(GL_LINES); 
     glVertex3i(0, 0, 0); 
     glVertex3i(1000, 0, 0); 
    glEnd(); 

    moveCamera(); 

    glCallList(idList); 

    GLfloat pos[] = {0, 0, 0, 1}; 
    glLightfv(GL_LIGHT0, GL_POSITION, pos); 

    glFinish(); 
} 

void reshape(int width, int height) 
{ 
    glViewport(0, 0, width, height); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(45, 2, 100, 2000); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
} 

void keyboard(unsigned char key, int x, int y) 
{ 
#define ESCAPE '\033' 

    switch (key) 
    { 
    case ESCAPE: 
     exit(0); 
     break; 
    case 's': 
     theta += 0.1; 
     break; 
    case 'w': 
     theta -= 0.1; 
     break; 
    case 'a': 
     phi += 0.1; 
     break; 
    case 'd': 
     phi -= 0.1; 
     break; 
    case 'q': 
     r-=5; 
     break; 
    case 'e': 
     r+=5; 
     break; 
    default: 
     break; 
    } 
    e_x = r * sin(theta) * cos(phi); 
    e_z = r * sin(theta) * sin(phi); 
    e_y = r * cos(theta); 
    glutPostRedisplay(); 
} 

void moveCamera() 
{ 
    glLoadIdentity(); 
    int vec = ceil(theta/3.1415); 
    int y; 
    if (vec%2) 
     y = 1; 
    else 
     y = -1; 
    gluLookAt(e_x, e_y, e_z, 0, 0, 0, 0, y, 0); 
} 

void init() 
{ 
    e_x = r * sin(theta) * cos(phi); 
    e_z = r * sin(theta) * sin(phi); 
    e_y = r * cos(theta); 
} 

void mkList() 
{ 
    int idInnerList = glGenLists(1); 
    glNewList(idInnerList, GL_COMPILE); 

    glColor3ub(255, 0, 0); 
    glPushMatrix(); 
    glTranslatef(-200, 0, 0); 
    glutWireSphere(50, 10, 10); 
    glPopMatrix(); 

    glColor3ub(0, 255, 0); 
    glPushMatrix(); 
    glTranslatef(200, 0, 0); 
    glutSolidCube(100); 
    glPopMatrix(); 

    glEndList(); 

    idList = glGenLists(1); 
    glNewList(idList, GL_COMPILE); 
    glCallList(idInnerList); 

    glPushMatrix(); 
    glTranslatef(0, 0, 200); 
    glCallList(idInnerList); 
    glPopMatrix(); 

    glPushMatrix(); 
    glTranslatef(0, 0, -200); 
    glCallList(idInnerList); 
    glPopMatrix(); 
    glEndList(); 
} 

void enableLight() 
{ 
    glEnable(GL_LIGHTING); 

    glEnable(GL_COLOR_MATERIAL); 
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 

    GLfloat diffuse[] = {0.7, 0.7, 0.7, 1}; 

    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 

    glEnable(GL_LIGHT0); 
} 
+0

Donc, j'ai remarqué, que la fonction moveCamera(), et que gluLookAt() doit être appelée firtly dans display function(). Pourquoi??? – van9petryk

Répondre

0

Pour commencer, je veux dire ceci: il est 2016 - ne pas utiliser OpenGL hérité. Lisez sur OpenGL moderne avec l'aide de votre moteur de recherche préféré. Si par «rien ne s'est passé», vous voulez dire «je ne pouvais pas voir la ligne rouge» et si j'ai bien compris votre code, c'est juste parce que la ligne sera entièrement écrêtée. Laisse-moi expliquer.

La première chose que vous faites qui affecte la transformation vertex à l'intérieur display() est l'appel glLoadIdentity(). Cela placera le haut de la pile de matrice actuelle dans la matrice d'identité, I. Supposons que la pile actuelle est MODELVIEW et la matrice de projection actuelle, P, est celui défini dans reshape(), votre ligne subira la transformation suivante de-espace local dans clipsable espace:

Vx_clip = P * I * Vx_local 
Vy_clip = P * I * Vy_local 

Étant donné que le modèle -view matrix est l'identité, les deux coordonnées locales resteront les mêmes dans l'espace-monde avant d'être transformées en clip-space. Comme votre plan proche est à z=-100, la ligne sera complètement hors du tronc, c'est-à-dire pas dans l'espace entre le plan proche et le plan lointain, et sera donc entièrement rognée. Mathématiquement, c'est un peu plus complexe, mais conceptuellement exact.

Vous pouvez vous convaincre en définissant la ligne rouge comme celui-ci

glVertex3i(-500, 0, -100); 
glVertex3i(500, 0, -100); 

Maintenant, une partie de la ligne sera à l'intérieur à l'intérieur de votre tronc, même avec une matrice modèle vue identité, car elle recoupe en partie la proximité avion et ne doit donc pas être entièrement coupé.

Si vous appliquez une matrice modèle-vue non-identité d'abord en appelant moveCamera()avant rendre la ligne rouge, vous pourrez également voir en partie la ligne rouge. Pourquoi? Eh bien, supposons que vos coordonnées polaires sont choisies de sorte que la caméra regarde toujours dans la direction (0, 0, -z), puis avec le rayon donné, vous définissez la caméra à (0, 0, 300) dans l'espace-monde, gluLookAt() à une matrice de transformation qui ajoutera simplement une traduction de (0, 0, -300) aux deux sommets.Compte tenu de la définition initiale de votre ligne et de la nouvelle matrice de vue de modèle, les sommets de la ligne seront à (0, 0, -300) et (1000, 0, -300) après avoir multiplié par gauche la matrice de vue de modèle. Après transformation en espace-clip en multipliant à gauche la matrice de projection, la ligne ne sera que partiellement écrêtée et donc visible. Comme je l'ai dit, cela est beaucoup plus impliqué et en fait, ce n'est qu'une partie du pipeline complet de transformation de vertex. Lire this et this pour un traité mathématique du sujet de la transformation vertex. C'est l'informatique graphique 101. Et s'il vous plaît: concentrez-vous sur les mathématiques, pas sur l'utilisation de l'API héritée que vous verrez malheureusement là.