ENGLISH VERSION |
|
Links | | | Forum | | | Kommentare | | | News melden |
Chat | | | Umfragen | | | Newsticker | | | Archiv |
amiga-news.de Forum > Programmierung > Zerlegung nicht konvexer Polygone | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
-1- | [ - Beitrag schreiben - ] |
17.11.2005, 14:22 Uhr Mad_Dog Posts: 1944 Nutzer |
Ich habe gerade folgendes Problem: Ich habe ein Programm, welches ein 3D Objekt von Disk liest und darstellt. Nun ergibt sich das Problem, daß manche Polygone nicht konvex sind, was für OpenGL Grafikprimitiven ein Problem darstellt. Da ja glu eine entsprechende Funktion bietet, hab ich mir mal einige Beispiele angeschaut und versucht, dies in meinen Code einzubauen - hat aber leider nicht vernünftig funktioniert. Die folgende Funktion erzeugt Display Listen aus den Daten der Datei: code:// Liste generieren GLuint buildlist(GeoData* geodat, clut colors) { int layernr, layer; unsigned long i; int j; GLuint display_list; GLUtesselator *tobj; tobj = gluNewTess(); GLdouble v[1][3]; display_list = glGenLists(geodat->num_metal_layers+1); // Display List für die Umrisse der Polygone glNewList(display_list,GL_COMPILE); glColor3f (1.0, 1.0, 1.0); for (i=0; i<geodat->num_polygons; i++) { glBegin (GL_LINE_LOOP); for (j=0;j<geodat->polygon[i].num_vertices;j++) { glVertex3f( geodat->polygon[i].vertex[j].x, geodat->polygon[i].vertex[j].z, geodat->polygon[i].vertex[j].y); } glEnd(); } glEndList(); // Gehe alle Metal Layer durch // Für jeden Metal Layer wird ein eigener Eintrag in // der Display Liste erzeugt. for (layer=0; layer < geodat->num_metal_layers; layer++) { // Display List für die Polygone glNewList(display_list+(layer+1),GL_COMPILE); // Gehe alle Polygone durch for (i=0; i < geodat->num_polygons; i++) { layernr = geodat->polygon[i].layer_num; // Falls Polygon zu diesem Layer gehört if (layernr == layer) { if (geodat->polygon[i].is3d==true) colors.setcolor(0); else colors.setcolor(layernr); switch (geodat->polygon[i].num_vertices) { case 3: // Falls das Polygon 3 Ecken hat, benutze // OpenGL Grafikprimitive GL_TRIANGLES glBegin(GL_TRIANGLES); glVertex3d( geodat->polygon[i].vertex[0].x, geodat->polygon[i].vertex[0].z, geodat->polygon[i].vertex[0].y); glVertex3d( geodat->polygon[i].vertex[1].x, geodat->polygon[i].vertex[1].z, geodat->polygon[i].vertex[1].y); glVertex3d( geodat->polygon[i].vertex[2].x, geodat->polygon[i].vertex[2].z, geodat->polygon[i].vertex[2].y); glEnd(); break; case 4: // Falls das Polygon 4 Ecken hat, benutze // OpenGL Grafikprimitive GL_QUADS glBegin(GL_QUADS); glVertex3d( geodat->polygon[i].vertex[0].x, geodat->polygon[i].vertex[0].z, geodat->polygon[i].vertex[0].y); glVertex3d( geodat->polygon[i].vertex[1].x, geodat->polygon[i].vertex[1].z, geodat->polygon[i].vertex[1].y); glVertex3d( geodat->polygon[i].vertex[2].x, geodat->polygon[i].vertex[2].z, geodat->polygon[i].vertex[2].y); glVertex3d( geodat->polygon[i].vertex[3].x, geodat->polygon[i].vertex[3].z, geodat->polygon[i].vertex[3].y); glEnd(); break; default: // Ansonsten benutze OpenGL Grafikprimitive GL_POLYGONS gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (CALLBACK*) ()) &glVertex3dv); gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid (CALLBACK*) ()) &beginCallback); gluTessCallback(tobj, GLU_TESS_END, (GLvoid (CALLBACK*) ()) &endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ()) &errorCallback); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); // // glBegin (GL_POLYGON); gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); // Gehe alle Punkte des Polygons durch und zeichne es for (j=0;j<geodat->polygon[i].num_vertices;j++) { // glVertex3d( geodat->polygon[i].vertex[j].x, // geodat->polygon[i].vertex[j].z, // geodat->polygon[i].vertex[j].y); v[0][0] = geodat->polygon[i].vertex[j].x; v[0][1] = geodat->polygon[i].vertex[j].z; v[0][2] = geodat->polygon[i].vertex[j].y; // cout << "Polygon " << i << ": " << v[0][0] << " " // << v[0][1] << " " // << v[0][2] << endl; gluTessVertex(tobj, v[0], v[0]); } // for // glEnd(); gluTessEndContour(tobj); gluTessEndPolygon(tobj); break; }// switch } // if } // for glEndList(); cout << "Display list entry " << layer << " ready" << endl; } // for cout << "Display list ready" << endl; gluDeleteTess(tobj); return display_list; } Im falle vom mehr wie 4 Eckpunkten versuche ich hier, das Polygon zu zerlegen. Leider erscheinen die entsprechenden Polygone dann überhaupt nicht. Den ursprünglichen Code habe ich auskommentiert. Die Callback-Funktionen sehen wie folgt aus: code:void CALLBACK beginCallback(GLenum which) { glBegin(which); } void CALLBACK errorCallback(GLenum errorCode) { const GLubyte *estring; estring = gluErrorString(errorCode); fprintf(stderr, "Tessellation Error: %sn", estring); exit(0); } void CALLBACK endCallback(void) { glEnd(); } void CALLBACK vertexCallback(GLvoid *vertex) { const GLdouble *pointer; //pointer = (GLdouble *) vertex; //glColor3dv(pointer+3); glVertex3dv((GLdouble *)vertex); } -- http://www.norman-interactive.com [ Dieser Beitrag wurde von Mad_Dog am 17.11.2005 um 16:33 Uhr editiert. ] [ - Antworten - Zitieren - Direktlink - ] |
24.11.2005, 17:14 Uhr Mad_Dog Posts: 1944 Nutzer |
Ich hab jetzt eine "Notlösung" gebastelt, die zwar nicht sehr elegant ist, aber funktioniert:code:/* displaylists.cpp * Funktionen zum Generieren der OpenGL Display Liste * Autor: Norman Walter */ #include "displaylists.h" #include "tesscallback.h" // Liste generieren GLuint buildlist(GeoFile* file, clut* colors) { int layernr, layer; unsigned long i; int j; GLuint display_list; GLUtesselator *tobj; tobj = gluNewTess(); // Notlösung: Zwischenspeicher zum Triangulieren der Polygone // Platz für maximal 1000 Vertices pro Polygon GLdouble v[1000][3]; display_list = glGenLists(file->num_metal_layers+1); // Display List für die Umrisse der Polygone glNewList(display_list,GL_COMPILE); glColor3f (1.0, 1.0, 1.0); for (i=0; i < file->num_polygons; i++) { glBegin (GL_LINE_LOOP); for (j=0;j < file->polygon[i].num_vertices;j++) { glVertex3f( file->polygon[i].vertex[j].x, file->polygon[i].vertex[j].z, file->polygon[i].vertex[j].y); } glEnd(); } glEndList(); // Gehe alle Metal Layer durch // Für jeden Metal Layer wird ein eigener Eintrag in // der Display Liste erzeugt. for (layer=0; layer < file->num_metal_layers; layer++) { // Display List für die Polygone glNewList(display_list+(layer+1),GL_COMPILE); // Gehe alle Polygone durch for (i=0; i < file->num_polygons; i++) { if (file->polygon[i].num_vertices > 1000) { cout << "Error: Polygon " << i << " has too many vertices." << endl; cout << "Number of vertices is " << file->polygon[i].num_vertices << " but maximum is 1000." << endl; exit(1); } layernr = file->polygon[i].layer_num; // Falls Polygon zu diesem Layer gehört if (layernr == layer) { if (file->polygon[i].is3d==true) colors->setcolor(0); else colors->setcolor(layernr); switch (file->polygon[i].num_vertices) { case 0: case 1: case 2: cout << "Nasty primitive with " << file->polygon[i].num_vertices << " vertices ignored" << endl; break; case 3: // Falls das Polygon 3 Ecken hat, benutze // OpenGL Grafikprimitive GL_TRIANGLES glBegin(GL_TRIANGLES); glVertex3d( file->polygon[i].vertex[0].x, file->polygon[i].vertex[0].z, file->polygon[i].vertex[0].y); glVertex3d( file->polygon[i].vertex[1].x, file->polygon[i].vertex[1].z, file->polygon[i].vertex[1].y); glVertex3d( file->polygon[i].vertex[2].x, file->polygon[i].vertex[2].z, file->polygon[i].vertex[2].y); glEnd(); break; case 4: // Falls das Polygon 4 Ecken hat, benutze // OpenGL Grafikprimitive GL_QUADS glBegin(GL_QUADS); glVertex3d( file->polygon[i].vertex[0].x, file->polygon[i].vertex[0].z, file->polygon[i].vertex[0].y); glVertex3d( file->polygon[i].vertex[1].x, file->polygon[i].vertex[1].z, file->polygon[i].vertex[1].y); glVertex3d( file->polygon[i].vertex[2].x, file->polygon[i].vertex[2].z, file->polygon[i].vertex[2].y); glVertex3d( file->polygon[i].vertex[3].x, file->polygon[i].vertex[3].z, file->polygon[i].vertex[3].y); glEnd(); break; default: // Ansonsten benutze OpenGL Grafikprimitive GL_POLYGONS gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid (CALLBACK*) ()) &glVertex3dv); gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid (CALLBACK*) ()) &beginCallback); gluTessCallback(tobj, GLU_TESS_END, (GLvoid (CALLBACK*) ()) &endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid (CALLBACK*) ()) &errorCallback); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); // glBegin (GL_POLYGON); gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); // Gehe alle Punkte des Polygons durch und zeichne es for (j=0;j < file->polygon[i].num_vertices;j++) { // glVertex3d( file->polygon[i].vertex[j].x, // file->polygon[i].vertex[j].z, // file->polygon[i].vertex[j].y); v[j][0] = file->polygon[i].vertex[j].x; v[j][1] = file->polygon[i].vertex[j].z; v[j][2] = file->polygon[i].vertex[j].y; // cout << "Polygon " << i << ": " << v[j][0] << " " // << v[j][1] << " " // << v[j][2] << endl; gluTessVertex(tobj, v[j], v[j]); } // for // glEnd(); gluTessEndContour(tobj); gluTessEndPolygon(tobj); break; }// switch } // if } // for glEndList(); cout << "Display list entry " << layer << " ready" << endl; } // for cout << "Display list ready" << endl; // gluDeleteTess(tobj); return display_list; } Dabei habe ich 2-dimensionales Array mit 3 Spalten (für x, y und z) und 1000 Zeilen (für maximal 1000 Vertices pro Polygon), welches als Puffer für die Triangulierung dient... -- http://www.norman-interactive.com [ - Antworten - Zitieren - Direktlink - ] |
-1- | [ - Beitrag schreiben - ] |
amiga-news.de Forum > Programmierung > Zerlegung nicht konvexer Polygone | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
Impressum |
Datenschutzerklärung |
Netiquette |
Werbung |
Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten. |