PDA

View Full Version : How draw fill non convex polygon in OpenGl?



Sergei
10-10-2000, 12:16 AM
I have coordinates of all points, but may polygon is not convex. If i use glDrawArrays() opengl draw many triangles from first point to others, and polygon is incorret.


(Sorry, I don't know good english)

Nicolas Lelong
10-10-2000, 03:15 AM
Hi,

OpenGL alone can't handle non-convex polygons. So, you have to split up your polygon in a set of convex polygons.

I never looked, but I believe GLUT has some functions that can help you.

Hope this helps

Kilam Malik
10-10-2000, 06:30 AM
Originally posted by Nicolas Lelong:
Hi,

OpenGL alone can't handle non-convex polygons. So, you have to split up your polygon in a set of convex polygons.

I never looked, but I believe GLUT has some functions that can help you.

Hope this helps

It's the gluTess... functions. They are rather complicated to use (with several callbacks) but they work fine. But use display lists here, so that the tesselation is only done once.

Kilam.

Pauly
10-10-2000, 09:50 AM
Here's a code fragment to get you going. Lord knows it took me ages to find the proper casting for the callbacks...

(BTW, can we have the old UBB forum code back please? This sucks as you see below in the code section).




list[0] = glGenLists ( 1 );
tess = gluNewTess ( );

/* Nice casting here -- NOT!! */
gluTessCallback ( tess, GLU_BEGIN, ( void ( __stdcall *) ( void ))glBegin );
gluTessCallback ( tess, GLU_VERTEX, ( void ( __stdcall *) ( void ))glVertex3dv );
gluTessCallback ( tess, GLU_END, ( void ( __stdcall *) ( void ))glEnd );

glNewList ( list[0], GL_COMPILE );

gluBeginPolygon ( tess );
for ( int i = 0; i < 4; i++ )
gluTessVertex ( tess, outside[i], outside[i] );

gluNextContour ( tess, GLU_INTERIOR );
for ( int i = 0; i < 48; i++ )
gluTessVertex ( tess, inside[i], inside[i] );
gluEndPolygon ( tess );

glEndList ( );

It puts a rectangle with a circular hole cut into the middle of it. The 'outside' contour is the rectangle, 'inside' is a pregenerated circle.

Paul.

[This message has been edited by Pauly (edited 10-10-2000).]

Kilam Malik
10-10-2000, 10:46 PM
Yes, the callbacks really sucks... if you need to get your own functions called (e.g., you need to set the normals too), you can use like the following, as the gluTessVertex accepts a void * which is then passed to the callback you install:



WINGDIAPI void APIENTRY CALLBACK myVertex3dv(class PntNorm *p)
// Passing my own PntNorm class here.
{
glNormal3dv(p->normal);
glVertex3dv(p->pnt);
}

typedef void (CALLBACK *MYCALLBACK)(void);

void InstallCallbacks(GLUtriangulatorObj *tess)
// Sets the callbacks.
{
gluTessCallback(tess,(GLenum)GLU_BEGIN,(MYCALLBACK )glBegin);
gluTessCallback(tess,(GLenum)GLU_VERTEX,(MYCALLBAC K)myVertex3dv);
gluTessCallback(tess,(GLenum)GLU_END,(MYCALLBACK)g lEnd);
}


Kilam.

Eric
10-10-2000, 11:04 PM
Just a remark : the tesselators are part of the GLU library ; you do not need GLUT to use them...

And by the way, the callbacks are not that awful ; they work in the same way than all Windows callbacks !

Regards.

Eric

Sergei
10-15-2000, 12:42 AM
Hello. Thanks for your reply. I break my polygon on many triangles, then draw it. But now i have other problem. I can't enable smooth for any filled polygons. I think it's a problem with graphics card, but not shure. I have riva tnt2.

10-15-2000, 07:54 AM
Smooth being what? Texture filtering? You
have to make sure that the texture
coordinates are the same for the vertexes in
the same position. Lighting? If there are
normals in the original polygon, you need to
tween the normals in your new, tesselated
polygon.

However, the special case of a concave
polygon can be easily tesselated yourself;
perhaps not with the ideal number of
triangles, but it's worth a try.

Look in Foley, van Dam, or another good
graphics reference, for some tessellation
algorithms to try out.

Sergei
10-16-2000, 03:58 AM
What also i must enable?

#include <main.h>
#include <windows.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>

#include <qfile.h>
#include <qstring.h>

int Lists[65536]; // list's number
int Listscount=0;

int Load_GL_objects (QString & filename1,QString &filename2)
{
QFile f(filename1);
QFile o(filename2);

float (*vertex)[2]; // array of points
int (*triangl)[3]; // array of index for triangles;
int *object; // array start pointov triangles;
int vertexcount=0;
int trianglcount=0;
int objectcount=0;

int r,i,j,k;
const char *str;
char temp = 0;


// Read objects from file.

o.open(IO_ReadOnly);
o.readBlock((char *)&vertexcount, sizeof (int));
o.readBlock((char *)&trianglcount, sizeof (int));
o.readBlock((char *)&objectcount, sizeof (int));

o.readBlock((char *)vertex, (sizeof (float))*vertexcount*2);
o.readBlock((char *)triangl, (sizeof (int))*trianglcount*3);
o.readBlock((char *)object, (sizeof (int))*objectcount*2);

o.close();
int h=0;
for (i=0;i<objectcount-1;i++)
{
Lists[Listscount++]=glGenLists(1);h++;
glNewList(Lists[Listscount-1], GL_COMPILE);
glBegin (GL_TRIANGLES);
for(j=object[i];j<object[i+1];j++)
for(k=0;k<3;k++)
{
int vi=triangl[j][k];
glVertex2f (vertex[vi][0],vertex[vi][1]);
}
glEnd ();
glEndList();
}

Lists[Listscount++]=glGenLists(1);
glNewList(Lists[Listscount-1], GL_COMPILE);h++;
glBegin (GL_TRIANGLES);

for(j=object[objectcount-1];j<trianglcount;j++)
for(k=0;k<3;k++)
{
int vi=triangl[j][k];
glVertex2f (vertex[vi][0],vertex[vi][1]);
}
glEnd ();
glEndList();

delete []triangl;
delete []vertex;
delete []object;
return h;


}

void CALLBACK resize(int width,int height)
{
if (width<=height) height=width;
else width=height;
glViewport(0,0,width,height);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(-5,5, -5,5, 2,12);
gluLookAt( 0,0,5, 0,0,0, 0,1,0 );
glMatrixMode( GL_MODELVIEW );
}


void CALLBACK display(void)
{

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

int s,f;
QString sr;
s=GetTickCount();
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_POLYGON_SMOOTH);
glColor3f(1,1,1);
glCallLists(1,GL_INT,&(Lists[0]));


glColor3f(0.7,0.7,0.7);
glCallLists(24,GL_INT,&(Lists[1]));

glColor3f(0,0,0);
glCallLists(32,GL_INT,&(Lists[25]));

glColor3f(0,0,0);
glCallLists(47,GL_INT,&(Lists[57]));


glDisable(GL_POLYGON_SMOOTH);
auxSwapBuffers();
f=GetTickCount();
sr.setNum(f-s);
::MessageBox(0,"Time",sr.ascii(),MB_OK);


}

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

// init OpenGL
auxInitPosition(1, 1, 300, 300);
auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE );
auxInitWindow( "OpenGL Window" );
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glEnable(GL_FOG);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;

Load_GL_objects(QString("cell_rect.txt"),QString("cell_rect1.txt"));
Load_GL_objects(QString("cell_fills.txt"),QString("cell_fills1.txt"));
Load_GL_objects(QString("cell_outlines.txt"),QString("cell_outlines1.txt"));
Load_GL_objects(QString("cell_names.txt"),QString("cell_names1.txt"));

auxReshapeFunc(resize);
auxMainLoop(display);
auxQuit();

glDeleteLists(Lists[0],Listscount);


return 0;
}