Debug help (backface culling)

I have a small program below that draws an Icosahedron. I’m supposed to have controls that can enable lighting, backface culling, change the field of view, and polygon mode. I can’t seem to get the backface culling or field of view to work. When I click the backface culling checkbox, nothing happens. It’s a toggle so it should enable/disable it. Also, the field of view does not change gradually. Changing by 10 degrees has no effect but changing by 30 does. Any help is greatly appreciated.

#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#include <iostream.h>
#include “glui.h”

#pragma comment( linker, “/subsystem:"windows" /entry:"mainCRTStartup"” )

#define X .525731112119133606
#define Z .850650808352039932

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] = {
{1,4,0}, {4,9,0}, {4,5,9}, {8,5,4}, {1,8,4},
{1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2},
{3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0},
{10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7}
};

struct CameraPosition {

float x;
float y;
float z;

};

int vfov = 60;
int hfov = 60;
float Znear = 0.1;
float Zfar = 1000.0;
CameraPosition cam_pos;
GLenum renderMode;
int window_id;
int totaldepth = 0;
int lighting = 1;
int obj = 2;
int backface_culling = 1;
float viewpoint_x = 0;
float viewpoint_y = 0;
float viewpoint_z = 0;

void openglReshape(int w, int h)
{

glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(vfov, hfov/vfov, Znear, Zfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

void control_cb(int control)
{

}

void normalize(float v[3])
{

GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (d == 0.0){
cout << “zero length vector”;
return;
}
v[0] /= d;
v[1] /= d;
v[2] /= d;

}

void drawtriangle(float *v1, float *v2, float *v3)
{

glColor3f(0.5, 1.0, 0.5);
glBegin(GL_TRIANGLES);
glNormal3fv(v1);
glVertex3fv(v1);
glNormal3fv(v2);
glVertex3fv(v2);
glNormal3fv(v3);
glVertex3fv(v3);
glEnd();

}

void subdivide(float *v1, float *v2, float *v3, long depth)
{

GLfloat v12[3], v23[3], v31[3];
GLint i;

if (depth == 0){
drawtriangle(v1, v2, v3);
return;
}
for(i=0; i < 3; i++){
v12[i] = (v1[i]+v2[i])/2.0;
v23[i] = (v2[i]+v3[i])/2.0;
v31[i] = (v3[i]+v1[i])/2.0;
}
normalize(v12);
normalize(v23);
normalize(v31);
subdivide(v1, v12, v31, depth-1);
subdivide(v2, v23, v12, depth-1);
subdivide(v3, v31, v23, depth-1);
subdivide(v12, v23, v31, depth-1);

}

void drawIcosahedron(void)
{

switch(obj){
case 0:
renderMode = GL_POINT;
break;
case 1:
renderMode = GL_LINE;
break;
case 2:
renderMode = GL_FILL;
break;
}
glPolygonMode(GL_FRONT_AND_BACK, renderMode);

if (lighting == 1){
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
else{
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
}

if (backface_culling = 1){
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
}
else{
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
}

int i;
for (i=0; i < 20; i++){
subdivide(&vdata[tindices[i][0]][0],
&vdata[tindices[i][1]][0],
&vdata[tindices[i][2]][0], totaldepth);

}

//gluPerspective(vfov, hfov/vfov, Znear, Zfar);

glFlush();
}

void openglDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(vfov, hfov/vfov, Znear, Zfar);
glMatrixMode(GL_MODELVIEW);

glCullFace(GL_BACK);
glColor3f(0.5, 1.0, 0.5);
glLoadIdentity();
gluLookAt(cam_pos.x, cam_pos.y, cam_pos.z, viewpoint_x, viewpoint_y, viewpoint_z, 0.0, 1.0, 0.0);

drawIcosahedron();
glutSwapBuffers();

}

void changeCameraPosition(int key, int x, int y)
{

switch(key) {
case GLUT_KEY_UP :
cam_pos.y -= 0.25;
viewpoint_y -= 0.25;
openglDisplay();
break;
case GLUT_KEY_DOWN :
cam_pos.y += 0.25;
viewpoint_y += 0.25;
openglDisplay();
break;
case GLUT_KEY_RIGHT :
cam_pos.x -= 0.25;
viewpoint_x -= 0.25;
openglDisplay();
break;
case GLUT_KEY_LEFT :
cam_pos.x += 0.25;
viewpoint_x += 0.25;
openglDisplay();
break;
case GLUT_KEY_PAGE_UP :
cam_pos.z -= 0.25;
viewpoint_z -= 0.25;
openglDisplay();
break;
case GLUT_KEY_PAGE_DOWN :
cam_pos.z += 0.25;
viewpoint_z += 0.25;
openglDisplay();
break;
}

}

void myGlutIdle( void )
{
/* According to the GLUT specification, the current window is
undefined during an idle callback. So we need to explicitly change
it if necessary */
if ( glutGetWindow() != window_id )
glutSetWindow(window_id);

glutPostRedisplay();
}

int main(int argc, char *argv)
{

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowPosition(0,0);
glutInitWindowSize(400, 400);
window_id = glutCreateWindow(“Assignment 1”);
glutDisplayFunc(openglDisplay);
glutReshapeFunc(openglReshape);
// glutMouseFunc(Mouse);
// glutMotionFunc(worldMotion);
glutSpecialFunc(changeCameraPosition);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.0, 0.0, 0.0, 0.0);

cam_pos.x = 0;
cam_pos.y = 0;
cam_pos.z = 2.5;

GLUI *glui = GLUI_Master.create_glui(“Controls”,1, 412, 0);

glui->add_checkbox(“Lighting”, &lighting);

GLUI_Spinner *depth_spinner = glui->add_spinner(“Depth:”, GLUI_SPINNER_INT, &totaldepth);
depth_spinner->set_int_limits(0, 5);

GLUI_Panel *obj_panel = glui->add_panel (“Object Type”);
GLUI_RadioGroup *group1 = glui->add_radiogroup_to_panel(obj_panel,&obj,4,control_cb);
glui->add_radiobutton_to_group(group1, “Points”);
glui->add_radiobutton_to_group(group1, “Wireframe”);
glui->add_radiobutton_to_group(group1, “Solid”);

GLUI_Spinner *hfov_spinner = glui->add_spinner(“Horizontal FOV:”, GLUI_SPINNER_INT, &hfov);
hfov_spinner->set_int_limits(1, 180);

GLUI_Spinner *vfov_spinner = glui->add_spinner(“Vertical FOV:”, GLUI_SPINNER_INT, &vfov);
vfov_spinner->set_int_limits(1, 180);

glui->add_checkbox(“Backface Culling”, &backface_culling);

glui->set_main_gfx_window(window_id);
GLUI_Master.set_glutIdleFunc(myGlutIdle);

glutMainLoop();
return 0;

}

  1. hfov and vfov should be floats, not ints.

  2. Are you sure that backface culling has no effect ? Of course, it has no visual effect, but it should run faster with backface culling. The only way to be sure is to make a simple FPS counter.

Morglum

Thanks for the reply Morglum. Shouldn’t I see a visual effect with backface culling when it’s a wireframe model though? My professor said we should. Also a demo in class showed only the front face wires with backface culling enabled but also the back face wires when he turned it off. Any thoughts?

Oh yes you’re right. There’s no visual effect with filled rendering, but there’s what you’ve described with wireframe rendering.

I’ve just seen an error in your code. That’s in the drawIcosahedron function. The error’s in the line

if (backface_culling = 1){

that should of course be

if (backface_culling == 1){

Does it work now ?
Morglum

:smacks forehead: Yeah, I actually fixed that yesterday. I was hoping no one would notice here (since I spent 3 hours looking over that code and not noticing it). Everything works fine now. Thanks again for your help.