[Opengl 2.0] Wireframe + Underlying Solid, having code difficulties.

I have a program that is to be capable of several things, first, if I hit a button multiple times it will toggle between multiple modes.

Right now though while I can toggle between either a wireframe or a solid I can’t have both. I know conceptually the solution is to have “two” objects, one wiremesh and one a solid and then use gloffset etc etc etc.

However I can’t seem to get the code to work:


void display()
{	
	//Background color
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	glEnable(GL_DEPTH_TEST);

	// Matrix setup
	glMatrixMode(GL_PROJECTION);
	glViewport(0, 0, width, height);
	glLoadIdentity();
	gluPerspective(40, (float)width / (float)height, 0.1, 1000);

	// Matrix setup
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0, 0, -3);

	
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glEnable(GL_POLYGON_OFFSET_FILL);
	glPolygonOffset(1.0f, 1.0f);
	glColor3f(0.0f, 0.0f, 0.0f);
	glBegin(GL_TRIANGLES);
		for (int i = 0; i<mesh->nfaces.size(); i += 1)
			for (int j = 0; j<3; j += 1){
		        glNormal3f(mesh->normal[mesh->nfaces[i][j]][0],
				mesh->normal[mesh->nfaces[i][j]][1],
				mesh->normal[mesh->nfaces[i][j]][2]);

				glVertex3f(mesh->vertex[mesh->faces[i][j]][0],
				mesh->vertex[mesh->faces[i][j]][1],
				mesh->vertex[mesh->faces[i][j]][2]);
	        }
	
	cout << "Here 1" << endl;
	glEnd();
	glDisable(GL_POLYGON_OFFSET_FILL);
	
	
	
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	//glEnable(GL_POLYGON_OFFSET_LINE);
	//glPolygonOffset(-2.0f, -2.0f);
	glColor3f(1.0f, 0.0f, 0.0f);	
	//glLineWidth(1.0f);
	//draw object
	glBegin(GL_TRIANGLES);
	for (int i = 0; i<mesh->nfaces.size(); i += 1)
		for (int j = 0; j<3; j += 1){
			glNormal3f(mesh->normal[mesh->nfaces[i][j]][0],
				mesh->normal[mesh->nfaces[i][j]][1],
				mesh->normal[mesh->nfaces[i][j]][2]);

			glVertex3f(mesh->vertex[mesh->faces[i][j]][0],
				mesh->vertex[mesh->faces[i][j]][1],
				mesh->vertex[mesh->faces[i][j]][2]);
		}
	glEnd();
	cout << "Here 2" << endl;
	//glDisable(GL_POLYGON_OFFSET_LINE);

	glutSwapBuffers();
}

Here’s my main with callbacks.


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

	// GLUT initialization.
	glutInit(&argc, argv);	
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(width, height);
	glutCreateWindow("CodeBase");
	
	// Register call backs.
	initialize();
	glutDisplayFunc(display);
	glutReshapeFunc(reshapeMainWindow);
	glutMotionFunc(mouse_motion);
	glutIdleFunc(idle);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(mouse_button);
	
	// Enter GLUT loop.
	glutMainLoop();

	delete mesh;
}

Here’s my keyboard function:


void keyboard(unsigned char key, int x, int y)
{

	switch (key)
	{
		case(27) :
			exit(0);
			break;
		case('s') :
		{
					  int myFlagCtr = getFlagCtr();
					  cout << "Pressed Before: " << getFlagCtr() << endl;
					  if (myFlagCtr == 0) {
						  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
						 

						  setFlagCtr(1);
					  }
					  else if (myFlagCtr == 1) {
						  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
							
							setFlagCtr(2);
					  } 
					  else if (myFlagCtr == 2) {
							setFlagCtr(0);

						  cout << "Pressed Before: " << getFlagCtr() << endl;
					  }
					  break;
		}
	}
}

Right now I just want to see if there’s a way, ANY way at all, to do both wiremesh+solid.

Thanks.

If you want to display a wireframe on top of a solid render without using a geometry shader you will need to do several passes to avoid z-buffer fighting.

You could try the following steps

  1. enable the stencil buffer, disable the colour buffer and render the wireframe

  2. disable the stencil buffer

  3. clear the depth buffer but not the stencil buffer

  4. render the solid geometry

  5. enable the stencil buffer, disable the depth buffer and render a whole screen quad to show the wireframe

Note that this will show the back faces in wireframe not just outline the front faces

What do you get on screen when you run posted code?

Uh, the forum doesn’t seem to let me post urls so, yeah.

I think I got some sort of mesh after running the code, but I also can’t seem to change the color at all.

[QUOTE=tonyo_au;1257639]If you want to display a wireframe on top of a solid render without using a geometry shader you will need to do several passes to avoid z-buffer fighting.

You could try the following steps

  1. enable the stencil buffer, disable the colour buffer and render the wireframe

  2. disable the stencil buffer

  3. clear the depth buffer but not the stencil buffer

  4. render the solid geometry

  5. enable the stencil buffer, disable the depth buffer and render a whole screen quad to show the wireframe

Note that this will show the back faces in wireframe not just outline the front faces[/QUOTE]

I kinda already have the problem of where the code that should have worked doesn’t for reasons I do not understand, can you be more specific syntaxwise?

I remember having done this a while ago, and I have some questions to your code above:

First, you fill the polygons with glPolygonOffset, and after that, you draw the lines without glPolygonOffset. To my mind, it should be done the other way around: Fill faces without the offset, and draw the lines “on top of” the filled faces (therefore the offset. 1.0 as both parameters should do).

Maybe it could help to move the drawing code to a sub-routine to make it more readable and maybe find your error by that. By the way, what “does not work” with your code? Do you see anything or can’t you get the syntax right?

As for the third code box: What does setFlagCtr do? Maybe you should just set two bools for both filled and wireframe display so that you can decide to draw them separate from each other. Drawing both is not definable in the glPolygonMode, as you already mentioned :wink:

Edit: glClearColor(1, 1, 1, 0) won’t work, you can’t clear with a transparent color (the last value should always be 1)

[QUOTE=Brokenmind;1257653]I remember having done this a while ago, and I have some questions to your code above:

First, you fill the polygons with glPolygonOffset, and after that, you draw the lines without glPolygonOffset. To my mind, it should be done the other way around: Fill faces without the offset, and draw the lines “on top of” the filled faces (therefore the offset. 1.0 as both parameters should do).

Maybe it could help to move the drawing code to a sub-routine to make it more readable and maybe find your error by that. By the way, what “does not work” with your code? Do you see anything or can’t you get the syntax right?

As for the third code box: What does setFlagCtr do? Maybe you should just set two bools for both filled and wireframe display so that you can decide to draw them separate from each other. Drawing both is not definable in the glPolygonMode, as you already mentioned ;)[/QUOTE]

So the problem it turns out is since we were operating using code provided by the professor (which as it isn’t an Opengl class but a computer graphics class that happens to use opengl and thus aren’t taught opengl) it had some funny business going on that I still don’t quite understand but it comes down to being unable to switch color using opengl commands.

I had to use glEnable(GL_COLOR_MATERIAL); (the opengl superbible I have doesn’t mention this for its beginner applications, anyone know why this was needed?) so I could actually see evidence of my mesh (because my wiremesh was the same color as the base material and thus invisible…) and with it everything works now after some fiddling.

Now onto camera movement!

For reference:


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

	// GLUT initialization.
	glutInit(&argc, argv);	
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(width, height);
	glutCreateWindow("CodeBase");
	glEnable(GL_COLOR_MATERIAL); //<---- WASNT HERE BEFORE YOLO!
	
	// Register call backs.
	initialize();
	glutDisplayFunc(display);
	glutReshapeFunc(reshapeMainWindow);
	glutMotionFunc(mouse_motion);
	glutIdleFunc(idle);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(mouse_button);
	
	// Enter GLUT loop.
	glutMainLoop();

	delete mesh;
}

// This function is called to display the scene.
void display()
{	
	//Background color
	glClearColor(1, 1, 1, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
	//glClear(GL_COLOR_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	// Matrix setup   
	glMatrixMode(GL_PROJECTION);
	glViewport(0, 0, width, height);
	glLoadIdentity();
	gluPerspective(40, (float)width / (float)height, 0.1, 1000);

	// Matrix setup
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0, 0, -3);


	int myFlagCtr = getFlagCtr();
	
	if (myFlagCtr == 1) {
		cout << "Set Wireframe" << getFlagCtr() << endl;
		// Set Wireframe
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		// color red
		glColor3f(1.0f, 0.0f, 0.0f);
		blDrawMouseMesh();
	}
	else if (myFlagCtr == 2) {
		cout << "Set Wireframe+Model" << getFlagCtr() << endl;
		// Set Wireframe+Model
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		// color red
		glColor3f(1.0f, 0.0f, 0.0f);
		glEnable(GL_POLYGON_OFFSET_LINE);
		glPolygonOffset(-1.0, -1.0);
		//draw object
		blDrawMouseMesh();

		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		// color red
		//glColor3f(0.53f, 0.12f, 0.47f);
		glColor3f(0.0f, 1.0f, 0.0f);
		//glEnable(GL_POLYGON_OFFSET_LINE);
		//glPolygonOffset(1.0, 0.1);
		//draw object
		blDrawMouseMesh();
	}
	else if (myFlagCtr == 0 || myFlagCtr == -1) {
		cout << "Set Default" << getFlagCtr() << endl;
		// Bring back to Default
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glColor3f(0.53f, 0.12f, 0.47f);
		blDrawMouseMesh();
	}

	glutSwapBuffers();
}

// This function is called when there is nothing else to do.
void idle()
{
	glutPostRedisplay();
}

void blDrawMouseMesh()
{
	glBegin(GL_TRIANGLES);
	for (int i = 0; i<mesh->nfaces.size(); i += 1)
	for (int j = 0; j<3; j += 1){
		glNormal3f(mesh->normal[mesh->nfaces[i][j]][0],
			mesh->normal[mesh->nfaces[i][j]][1],
			mesh->normal[mesh->nfaces[i][j]][2]);

		glVertex3f(mesh->vertex[mesh->faces[i][j]][0],
			mesh->vertex[mesh->faces[i][j]][1],
			mesh->vertex[mesh->faces[i][j]][2]);
	}
	glEnd();
}