amiga-news 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.
.