Advertisement

need help, polygon cutting

Started by January 02, 2003 01:45 PM
50 comments, last by pagal2k2 21 years, 6 months ago
So I am an expert ? I didn't know I was

The renderDepth function assumes that the vertical direction of the walls is the Z axis, since that's how pagal's situation is described in one of his earlier posts in this thread.

But this time, the Z coordinate is not changing. So you have to change slightly the equations.

For instance, if your vertical axis is the Y coordinate, replace :

glTexCoord2dv(lower_left_texcoord);glVertex3dv(lower_left_wall);glTexCoord2d(upper_right_texcoord[0], lower_left_texcoord[1]);glVertex3d(upper_right_wall[0], upper_right_wall[1], lower_left_wall[2]);glTexCoord2dv(upper_right_texcoord);glVertex3dv(upper_right_wall);glTexCoord2d(lower_left_texcoord[0], upper_right_texcoord[1]);glVertex3d(lower_left_wall[0], lower_left_wall[1], upper_right_wall[2]);


with :

glTexCoord2dv(lower_left_texcoord);glVertex3dv(lower_left_wall);glTexCoord2d(upper_right_texcoord[0], lower_left_texcoord[1]);glVertex3d(upper_right_wall[0], lower_left_wall[1], upper_right_wall[2]);glTexCoord2dv(upper_right_texcoord);glVertex3dv(upper_right_wall);glTexCoord2d(lower_left_texcoord[0], upper_right_texcoord[1]);glVertex3d(lower_left_wall[0], upper_right_wall[1], lower_left_wall[2]);


and replace :

{solve_linear(lower_left_wall[2],             upper_right_wall[2],             lower_left_door[2],             upper_right_door[2],             &lower_left_texcoord[1],             &upper_right_texcoord[1]);if (fabs(upper_right_wall[0]-lower_left_wall[0]) > fabs(upper_right_wall[1]-lower_left_wall[1]))  solve_linear(lower_left_wall[0],               upper_right_wall[0],               lower_left_door[0],               upper_right_door[0],               &lower_left_texcoord[0],               &upper_right_texcoord[0]);else  solve_linear(lower_left_wall[1],               upper_right_wall[1],               lower_left_door[1],               upper_right_door[1],               &lower_left_texcoord[0],               &upper_right_texcoord[0]);}


with:

{solve_linear(lower_left_wall[1],             upper_right_wall[1],             lower_left_door[1],             upper_right_door[1],             &lower_left_texcoord[1],             &upper_right_texcoord[1]);if (fabs(upper_right_wall[0]-lower_left_wall[0]) > fabs(upper_right_wall[2]-lower_left_wall[2]))  solve_linear(lower_left_wall[0],               upper_right_wall[0],               lower_left_door[0],               upper_right_door[0],               &lower_left_texcoord[0],               &upper_right_texcoord[0]);else  solve_linear(lower_left_wall[2],               upper_right_wall[2],               lower_left_door[2],               upper_right_door[2],               &lower_left_texcoord[0],               &upper_right_texcoord[0]);}



This should do the trick.
hope this helps, I haven't looked at your code completely but at least what I've written here should be done as long as the Z coordinate of your wall is constant over the wall.

[edited by - vincoof on July 26, 2003 10:57:46 AM]
Hi,

Thx vincoof, I will test that! :-)

Anyway I have tested the technique of Roming22 and it works well! ;-)

I don t know which technique is the best, so don t hesitate to give your opinion

thx all again for your help!

see ya

Khem


We are a Football Tribe!
Advertisement
The problem with Roming22''s technique is that the depth buffer is written where the door is located, so you will not be able to render something "behind" the door (unless you depth-sort your objects to render, which is sometimes hard to setup and always cpu-intensive).

The problem with my technique is that your limited to rectangular doors and walls.

We have also discussed the stencil-buffer technique, which has the good point of leaving the depth buffer unchanged, and allows non-rectangluar walls and doors, but :
- the stencil buffer support is not always accelerated in hardware on consumer-level cards,
- the technique requires three passes at least (instead of two passes at most for the two other approaches),
- curved doors / walls digging is not possible, so does the polygon offset technique, which means that you can''t dig a door or a window into a cylindrical tower for instance.

That last point is due to the fact that any buffer based approach (either stencil buffer of depth buffer) uses one layer only, thus it''s not possible to deal with them when pixels come to overlap while the surface is projected onto the screen (this type of overlapping never happens on planar surfaces).
In fact, it IS possible to deal with them when using multipass, but it pretty much goes to CSG techniques anyway.
Hi Vincoof and thx to help me ,

Your technique looks better but I don''t manage to make it work :S

I ve made the change you describe and I ve made the render as pagal2k2 says too...I tried to fix it but I can t see the polygon which has the cutting, I only see the back one.

Here s the entire code, in the case U want to test

int rotateX = 0;int rotateY = 0;GLuint scene;int xold = 0;int yold = 0;GLuint texture[1];#define GL_CLAMP_TO_BORDER 0x812DGLuint init_texture(void){	static GLubyte texture_data[16] =	{		0xFF, 0xFF, 0xFF, 0xFF,		0xFF, 0x00, 0x00, 0xFF,		0xFF, 0x00, 0x00, 0xFF,		0xFF, 0xFF, 0xFF, 0xFF	};	GLuint texture_id;	glGenTextures(1, &texture_id);	glBindTexture(GL_TEXTURE_2D, texture_id);	glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 4, 4, 1, GL_ALPHA, GL_UNSIGNED_BYTE,&texture_data);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	return texture_id;}void solve_linear(GLdouble wall_min,				GLdouble wall_max,				GLdouble door_min,				GLdouble door_max,				GLdouble *texcoord_min,				GLdouble *texcoord_max){	GLdouble a = 1.f / (door_max - door_min);	GLdouble b = -a * door_min;	*texcoord_min = a * wall_min + b;	*texcoord_max = a * wall_max + b;}void compute_texcoord(GLdouble lower_left_wall[3],					GLdouble upper_right_wall[3],					GLdouble lower_left_door[3],					GLdouble upper_right_door[3],					GLdouble lower_left_texcoord[2],					GLdouble upper_right_texcoord[2]){		solve_linear(lower_left_wall[1], 				upper_right_wall[1],				lower_left_door[1],				upper_right_door[1],				&lower_left_texcoord[1],				&upper_right_texcoord[1]);	if (fabs(upper_right_wall[0]-lower_left_wall[0]) > fabs(upper_right_wall[2]-lower_left_wall[2]))  		solve_linear(lower_left_wall[0],					upper_right_wall[0],					lower_left_door[0],					upper_right_door[0],					&lower_left_texcoord[0],					&upper_right_texcoord[0]);	else  		solve_linear(lower_left_wall[2],		upper_right_wall[2],		lower_left_door[2],		upper_right_door[2],		&lower_left_texcoord[0],		&upper_right_texcoord[0]);}void render_depth(GLuint texture_id,				GLdouble lower_left_wall[3],				GLdouble upper_right_wall[3],				GLdouble lower_left_door[3],				GLdouble upper_right_door[3]){	GLdouble lower_left_texcoord[2];	GLdouble upper_right_texcoord[2];	glBindTexture(GL_TEXTURE_2D, texture_id);	glEnable(GL_TEXTURE_2D);	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	glEnable(GL_ALPHA_TEST);	glAlphaFunc(GL_NOTEQUAL, 0);	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);	glColor3d(1.f, 1.f, 1.f);	compute_texcoord(lower_left_wall,						upper_right_wall,						lower_left_door,						upper_right_door,						lower_left_texcoord,						upper_right_texcoord);	glBegin(GL_QUADS);		glTexCoord2dv(lower_left_texcoord);		glVertex3dv(lower_left_wall);		glTexCoord2d(upper_right_texcoord[0], lower_left_texcoord[1]);		glVertex3d(upper_right_wall[0], lower_left_wall[1], upper_right_wall[2]);		glTexCoord2dv(upper_right_texcoord);		glVertex3dv(upper_right_wall);		glTexCoord2d(lower_left_texcoord[0], upper_right_texcoord[1]);		glVertex3d(lower_left_wall[0], upper_right_wall[1], lower_left_wall[2]);	glEnd();	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);	glDisable(GL_ALPHA_TEST);	glDisable(GL_TEXTURE_2D);}void InitGL(){	glBlendFunc(GL_SRC_ALPHA,GL_ONE);	glShadeModel(GL_SMOOTH);								glClearColor(1.0,1.0,1.0, 1.0f);						glClearDepth(1.0f);										glEnable(GL_DEPTH_TEST);	//glDepthFunc(GL_LEQUAL);	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	}void Reshape(int width, int height){	glViewport(0,0,width,height);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	gluPerspective(45,(float)width/(float)height,0.1,10000);	glMatrixMode(GL_MODELVIEW);    glLoadIdentity();}void Draw(void) {	//here I made lower_left_wall = lower_left_door	//and upper_right_wall = upper_right_door.	double lower_left_wall [] = {-0.5,-0.5,0.02};	double upper_right_wall [] = {0.5,0.5,0.02};	double lower_left_door [] = {-0.5,-0.5,0.02};	double upper_right_door [] = {0.5,0.5,0.02};	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glPushMatrix();	glTranslatef(0.0,0.0,-10.0);	glRotated(rotateY,0.0,1.0,0.0);	//here I draw the quad which is visible to the cut	glBegin(GL_QUADS);	glColor4f (0.0,0.0,1.0,1.0);	glVertex3f (-2.0,-2.0,-2.0);	glVertex3f (2.0,-2.0,-2.0);	glVertex3f (2.0,2.0,-2.0);	glVertex3f (-2.0,2.0,-2.0);	glEnd();	//here I draw the alpha textured polygon	static GLuint alpha_id = init_texture();	render_depth(alpha_id, lower_left_wall, upper_right_wall, lower_left_door, upper_right_door);	//here I draw the polygon which has the cutting	glDepthFunc(GL_EQUAL);	glBegin(GL_QUADS);	glColor3f (0.0,1.0,0.0);	glVertex3f (-1.0,-1.0,0.0);	glVertex3f (1.0,-1.0,0.0);	glVertex3f (1.0,1.0,0.0);	glVertex3f (-1.0,1.0,0.0);	glEnd();	glDepthFunc(GL_LESS);	glPopMatrix();	glutSwapBuffers();}void keyboard (unsigned char key,int x,int y){	switch (key) {	case 27:		exit(0);		break;	}}void mousePress (int button,int state,int x,int y) {	if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {		xold = x;		yold = y;	}}void mouseMotion (int x, int y) {	rotateY += x - xold;	rotateX += y - yold;	if (rotateX > 360) {		rotateX -= 360;	}	if (rotateX < 0) {		rotateX += 360;	}	if (rotateY > 360) {		rotateY -= 360;	}	if (rotateY < 0) {		rotateY += 360;	}	xold = x;	yold = y;	glutPostRedisplay();}int APIENTRY WinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){ 	glutInitWindowSize(400,400);	glutInitWindowPosition(300,300);	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);		glutCreateWindow("Methode Vincoof");	InitGL();	glutReshapeFunc(Reshape);	glutDisplayFunc(Draw);	glutKeyboardFunc(keyboard);	glutMouseFunc (mousePress);	glutMotionFunc (mouseMotion);	glutMainLoop();	return 0;}


I keep on trying to fix it

khem
We are a Football Tribe!
quote:
Original post by killerkhem
//here I made lower_left_wall = lower_left_door
//and upper_right_wall = upper_right_door.
double lower_left_wall [] = {-0.5,-0.5,0.02};
double upper_right_wall [] = {0.5,0.5,0.02};
double lower_left_door [] = {-0.5,-0.5,0.02};
double upper_right_door [] = {0.5,0.5,0.02};


First of all, I don''t think it''s a good idea to setup walls and doors to the same coordinates.
You will experience Z-figthting if the rendered wall (the one which is coloured next) does not have exactly the same coordinates as the quad defined by the wall here.

quote:
Original post by killerkhem
//here I draw the alpha textured polygon
static GLuint alpha_id = init_texture();
render_depth(alpha_id, lower_left_wall, upper_right_wall, lower_left_door, upper_right_door);
//here I draw the polygon which has the cutting
glDepthFunc(GL_EQUAL);
glBegin(GL_QUADS);
glColor3f (0.0,1.0,0.0);
glVertex3f (-1.0,-1.0,0.0);
glVertex3f (1.0,-1.0,0.0);
glVertex3f (1.0,1.0,0.0);
glVertex3f (-1.0,1.0,0.0);
glEnd();
glDepthFunc(GL_LESS);


As I''ve written above, you should render this quad using the coordinates defined by wall (especially the Z value, but not only that one).

For instance, you may copy''n''paste the quad rendering code called into the render_depth function (except that you don''t need texture coordinates) :
glBegin(GL_QUADS);	glVertex3dv(lower_left_wall);	glVertex3d(upper_right_wall[0], lower_left_wall[1], upper_right_wall[2]);	glVertex3dv(upper_right_wall);	glVertex3d(lower_left_wall[0], upper_right_wall[1], lower_left_wall[2]);glEnd();
Thx vincoof, it works! :D

The cut is rendered perfectly but there s still one problem :
the wall,all around the cutting,is "clipping" when I rotate it

That looks like this :

[img]http://parisaku.free.fr/hole.JPG[/img]

Is there a way to fix it?

Thx

Khem

[edited by - killerkhem on July 31, 2003 9:01:15 AM]
We are a Football Tribe!
Advertisement
That''s weird. It looks like Z-fighting without actually being it !

Well, I see two issues.

First, try eliminating Z-fighting (or at least reduce it) by replacing the far clipping plane position. For instance, replace :
gluPerspective(45,(float)width/(float)height,1,10000);
with :
gluPerspective(45,(float)width/(float)height,1,100);

Secondly, I expect the clamp-to-border feature not to be correctly supported on some graphics cards that claim to be OpenGL-compliant without being really. Try replacing :
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 4, 4, 1, GL_ALPHA, GL_UNSIGNED_BYTE,&texture_data);
with :
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE,&texture_data);
... which, as I''ve written in one of the earlier posts, will not give the expected results in terms of the door/window size (the hole should be smaller) but may be relevant in terms of OpenGL compatibility.
Hi Vincoof,

When I set zNear to 0.01 and zFar to 100, the result is nearly perfect but it isn t perfect (there is still a cutting at the left of the polygone)! :S I tried many value but this one seems to be the best.

With your 2nd idea, it doesn t work too : the result is as before and it cause size''s problem too...


Thx for your help, I hope we are close to the solution and we can make it! :D

Khem
We are a Football Tribe!
Finally I've got my hands back on a PC that I can use for compiling and executing programs !

It's a shame. As far as I've been able to test, it seems that texture borders are badly supported.
That is, when I 'try' the technique with the null border technique, it works fine (the solution #2 of my previous post). And when I enable texture borders, depth testing fails randomly. My guess is that texture borders are supported in software, and thus does not compute the same depth components.
It's a shame because I think that OpenGL mandates the invariance, but oh well.

[edited by - vincoof on August 4, 2003 5:29:23 PM]
Finally here''s the solution I propose : discard texture borders but use roughly the same technique.
Instead of considering the "square-hole" texture as a 2x2 texture with 2 border pixels, consider that texture as a 4x4 standard texture (no border involved).
So, to clamp the hole, we define the hole in the range [0.25,0.75]. Logical, isn''t it ?

Then, we just have to change few lines of code.
First of all, setup the texture WITHOUT borders, as previously described :
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 4, 4, 0, GL_ALPHA, GL_UNSIGNED_BYTE,&texture_data);

And clamp to the edge, instead of clamping to the border :
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

You will probably need the corresponding token :
#define GL_CLAMP_TO_EDGE 0x812F

Then, re-map the texture coordinates of the hole to the range [0.25,0.75] instead of the [0,1] range :
void solve_linear(GLdouble wall_min,				GLdouble wall_max,				GLdouble door_min,				GLdouble door_max,				GLdouble *texcoord_min,				GLdouble *texcoord_max){	const GLdouble texlimit_min = 0.25f; // new	const GLdouble texlimit_max = 0.75f; // new	GLdouble a = (texlimit_max - texlimit_min) / (door_max - door_min); // changed	GLdouble b = texlimit_min - (a * door_min); // changed	*texcoord_min = a * wall_min + b;	*texcoord_max = a * wall_max + b;}


And this will do the trick.
This time, no doubt about the correctness on most graphics cards. This should work on TNT2 and Rage128 at least !
OpenGL1.2 is required because of GL_CLAMP_TO_EDGE, but if you want you can deal with GL_CLAMP and then only OpenGL1.1 is required. A little error could be seen in that case, though.

Hope this helps.

This topic is closed to new replies.

Advertisement