OBJ-Loader



  • Hi,
    gerade bin ich dabei einen Wavefront OBJ Loader zu schreiben. Richten tu ich mich nach dem Wikipedia-Artikel: http://en.wikipedia.org/wiki/Wavefront_.obj_file.

    Klappt auch bisher alles ganz gut, aber nur, wenn ich weiß, wie die OBJ Datei genau aufgebaut ist. Wenn ich zum Beispiel einen Würfel in Blender exportiere hat der Faces mit 4 Vertices. Wenn ich aber einen Kegel exportiere, habe die Faces 3 Vertices. Das bedeutet, dass das Face in der OBJ Datei z.B. als

    v 1 2 3 4

    in der Würfel Datei und als

    v 1 2 3

    in der Kegel Datei definiert ist. Wie kann ich jetzt ressourcensparend Prüfen, wie viele Vertices das bestimmte Face hat?
    Ich habe mich schonmal nach OBJ Loadern umgeschaut, aber die benutzen alle fsacnf. Ich würde gerne streams benutzen.

    Grüße,
    Raz



  • Indem du sie zählst? 😕



  • Später möchte ich aber jede mögliche Datei einlesen und nicht alle 2k faces durchlesen.



  • Also wenn ich das gerade richtig überflogen habe, definierst du mit

    v 1 2 3
    v 3 4 5
    v 5 6 7
    

    ohnehin erstmal nur 3 vertices.

    Die Face-Definition würde ja dann

    f 1 2 3
    

    lauten und die dort verwendeten Werte sind die Vertex-Indices.

    Du musst ja ohnehin alle Face-Definitionen einlesen, um eben zu wissen aus welchen Vertices die facec bestehen. Dann ist es doch ein leichtes eben mitzuzählen, aus wievielen Vertices jedes face besteht.

    Verstehe deine Aussage nicht, dass du nicht alle faces durchlesen möchtest.



  • Okay, vielleicht nochmal ein Beispiel.

    Das ist eine Datei, in der ein Dreieck definiert ist:

    v 0.0 1.0 0.0
    v 1.0 -1.0 0.0
    v -1.0 -1.0 0.0

    f 1 2 3

    Und das ist die von einem Quadrat:

    v -1.0 1.0 0.0
    v 1.0 1.0 0.0
    v 1.0 -1.0 0.0
    v -1.0 -1.0 0.0

    f 1 2 3 4

    Mal angenommen, ich suche erst nach den Face-Definitionen, die mit 'f' beginnen.
    Bei dem Dreieck wäre das so:
    - 'f' in der 5. Zeile gefunden.
    - lese 3 mal einen int ein
    - suche nach dem nächsten 'f'

    Und bei dem Quadrat gibts dann aber Probleme:
    - 'f' in der 6. Zeile gefunden
    - lese 3 mal einen int ein
    - suche nach dem nächsten 'f'

    Aber bei dem Quadrat würde es ein fehlerhaften Mesh ergeben, denn ich habe nur 3 Vertices pro Face eingelesen, obwohl 4 definiert waren.

    Jetzt die Frage: Woher soll ich wissen, wieviel Vertices pro Face definiert sind, bzw. wie oft soll ich einen int pro Face einlesen?
    Ein Beispiel wäre schön.



  • Du musst solange ints einlesen, bis etwas kommt, das kein int ist (also ein 'f' für face oder 'v' für vertex).



  • Ja, da könnte man z.B. isdigit() benutzen, aber das ist nur für einen int und nicht für einen string, bzw. const char*.



  • Okay, das wäre mal ein Ansatz:

    char c;
    
            while(stream.get(c)) {
    
                switch(c) {
                    case 'f':
                    int i;
                    while(stream >> i)
                        std::cout << i << std::endl;
                    break;
    
                    default:
                    break;
                }
            }
    

    Das Problem ist, dass nach dem ersten f der stream nicht mehr good() ist und deshalb die Schleife beendet wird.



  • Ja, weil es f Zahl und nicht fZahl heißt. Dazwischen ist ein Leerzeichen und das versuchst du als Zahl einzulesen. Das haut natürlich nicht hin und der Stream geht in einen Fehlerzustand.

    char c;
    
            while(stream.get(c)) {
    
                switch(c) {
                    case 'f':
                   { // Scope für Var-Deklaration!
                    int i;
                    stream.get(c); // Leerzeichen überlesen
                    while(stream >> i)
                        std::cout << i << std::endl;
                  }
                    break;
    
                    default:
                    break;
                }
            }
    

    Die Lösung ist aber alles andere als schön. Nimm doch einen std::stringstream. Der ignoriert für dich sogar die Leerräume...



  • Danke, hat geklappt :).


Anmelden zum Antworten