1

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?

Spektre
  • 49,595
  • 11
  • 110
  • 380
quantumbutterfly
  • 1,815
  • 4
  • 23
  • 38
  • "Try to glTranslate the GL_MODELVIEW in z direction by a bit if things are changed" Silly question, but what is the syntax for this? – quantumbutterfly Mar 30 '17 at 07:02
  • `glMatrixMode(GL_MODELVIEW); glTranslatef(0.0,0.0,delta);` but I do not think it is the case otherwise the cut of would be in the middle – Spektre Mar 30 '17 at 07:13
  • I see the problem now try to add this `glFrontFace(GL_CW);` to start of your display function – Spektre Mar 30 '17 at 07:25

1 Answers1

2
  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.

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Tried your code, and I'm just getting a blank screen – quantumbutterfly Mar 30 '17 at 07:45
  • Here is the entire file I am running: https://gist.github.com/shaansheikh/835a518097f793e5c720d1f010cb1cf4 Any clue why I see only black? – quantumbutterfly Mar 30 '17 at 07:51
  • @quantumbutterfly if I use your `gluOrtho2D( -2.0, 2.0, -2.0, 2.0 );` instead of my perspective projection it works too I just needed to get rid of the modelview translation but you do not have any of that so it should be working. May be it is some silly thing with your compiler. Another possibility is you are not clearing screen and depth buffer I do not know GLUT it is doing for you or not try to add `glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);` at start of your display function – Spektre Mar 30 '17 at 08:39
  • No dice yet... Going to keep trying – quantumbutterfly Mar 30 '17 at 08:42
  • @quantumbutterfly also I do not use `stdio.h` try to rem it out to be sure it is not messing with some nasty defines with the GLUT or OpenGL. – Spektre Mar 30 '17 at 08:43
  • Still black even with the removal – quantumbutterfly Mar 30 '17 at 08:43
  • @quantumbutterfly try to disable GL_CULL_FACE and GL_DEPTH_TEST just to be sure. It should work as I did not change so much from your old code and that was rendering on your setup. – Spektre Mar 30 '17 at 08:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/139468/discussion-between-quantumbutterfly-and-spektre). – quantumbutterfly Mar 30 '17 at 08:46
  • @quantumbutterfly looks like chat notification still does not work or you just not online :) have added few things in there – Spektre Mar 30 '17 at 09:16
  • going to come back to this tomorrow – quantumbutterfly Mar 30 '17 at 09:29
  • @quantumbutterfly did not see your question in the chat until now `glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);` should work but you are missing that that clears the framebuffer not the image you see so you still need to add `glFlush(); SwapBuffers(hdc);` or their GLUT counterparts. the SwapBuffers is OS dependent so it might be called a bit differently in your environment. `glLoadIdentity` has no meaning that just load unit matrix to lastly set matrix (which can mess up things if you do not use `glMatrixMode` before it) – Spektre Jun 11 '18 at 07:46