Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
209 views
in Technique[技术] by (71.8m points)

glut - Faces missing when drawing icosahedron in OpenGL following code in redBook

I am attempting to draw an icosahedron following this popular OpenGl tutorial in the redBook.

I am using GLUT to handle windowing.

Here is my complete code. It is mostly the code from the tutorial plus some clerical work using GLUT

#include <stdio.h>
#include <GL/glut.h>
#define X .525731112119133606
#define Z .850650808352039932

void mouseEventHandler(int button, int state, int x, int y){
}

void display() {
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    static GLfloat vdata[12][3] = {
        {-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
        {0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
        {Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
    };

    static GLuint tindices[20][3] = { 
        {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},    
        {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},    
        {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6}, 
        {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };

    int i;

    glBegin(GL_TRIANGLES);
    for (i = 0; i < 20; i++){
        glNormal3fv(&vdata[tindices[i][0]][0]);
        glVertex3fv(&vdata[tindices[i][0]][0]);
        glNormal3fv(&vdata[tindices[i][1]][0]);
        glVertex3fv(&vdata[tindices[i][1]][0]);
        glNormal3fv(&vdata[tindices[i][2]][0]);
        glVertex3fv(&vdata[tindices[i][2]][0]);
    }
    glEnd();
    glFlush ( );
}

void windowSetup(){
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowPosition(80, 80);
    glutInitWindowSize(1000,1000);

    glutCreateWindow("OpenGL Ico");

    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode( GL_MODELVIEW);
    glLoadIdentity();           
    gluOrtho2D( -2.0, 2.0, -2.0, 2.0 );
}

int main(int argc, char** argv) {

    glutInit(&argc, argv);
    windowSetup();

    glutDisplayFunc(display);
    glutMouseFunc(&mouseEventHandler);
    glutMainLoop();
}

This is my output: My icosahedron output This is very different from the expected output:
enter image description here

Does someone know why these differ so much?

The differences seem to be:

  • My icosahedron is missing faces

  • My icosahedron is being viewed from a different angle

  • My icosahedron is lit differently

The first one is the most pressing. I have noticed when I change glMatrixMode( GL_MODELVIEW); to glMatrixMode( GL_PROJECTION); the faces that aren't showing up appear and those that are currenty appearing disappear. Does anybody know why this could be?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. missing faces

    most likely you just have wrong order of indices. In such case Reversing them will solve the issue. To check this you can try:

    glDisable(GL_CULL_FACE);
    

    if problem disappears I am right. If not it is different thing (like too close to camera cutting by Z_NEAR but that would look a bit different).

    To identify the correct face you can use glColor based on i for exaple

    if (i==5) glColor3f(1.0,0.0,0.0); else glColor3f(1.0,1.0,1.0);
    

    the red face would be the 6th in this case {8,3,10}

  2. lighting

    You are using vertex coordinates as normals so do not expect FLAT shading. Also I do not see you are setting any lights here (but that can be hidden in GLUT somewhere I do not use it). To remedy this use just single normal per triangle. so average the 3 normals you got and make an unit vector from that and use that (before first glVertex call of each triangle).

  3. orientation

    just rotate your GL_MODELVIEW to desired orientation. Standard perspective GL_PROJECTION has z axis as viewing direction and x,y axises matches the screen (while GL_MODELVIEW is unit)

[Edit1] I tried your code

So the problem is you got reverse order of indices then default polygon winding in OpenGL (at least in my environment) and wrong normals here fixed code:

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
const GLfloat vdata[12][3] =
    {
    {-X,0.0,Z}, {X,0.0,Z}, {-X,0.0,-Z}, {X,0.0,-Z},
    {0.0,Z,X}, {0.0,Z,-X}, {0.0,-Z,X}, {0.0,-Z,-X},
    {Z,X,0.0}, {-Z,X,0.0}, {Z,-X,0.0}, {-Z,-X,0.0},
    };

const GLuint tindices[20][3] =
    {
    {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
    {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
    {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
    {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11}
    };

int i;
GLfloat nx,ny,nz;

glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
glBegin(GL_TRIANGLES);
for (i = 0; i < 20; i++)
    {
    nx =vdata[tindices[i][0]][0];
    ny =vdata[tindices[i][0]][1];
    nz =vdata[tindices[i][0]][2];
    nx+=vdata[tindices[i][1]][0];
    ny+=vdata[tindices[i][1]][1];
    nz+=vdata[tindices[i][1]][2];
    nx+=vdata[tindices[i][2]][0]; nx/=3.0;
    ny+=vdata[tindices[i][2]][1]; ny/=3.0;
    nz+=vdata[tindices[i][2]][2]; nz/=3.0;
    glNormal3f(nx,ny,nz);
    glVertex3fv(vdata[tindices[i][0]]);
    glVertex3fv(vdata[tindices[i][1]]);
    glVertex3fv(vdata[tindices[i][2]]);
    }
glEnd();

And preview:

icosahedron

it is a screenshot and my object is rotating so do not expect correct orientation you expect.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...