Blender Wavefront obj-Files -> Python3/PySide/PyOpenGL ?

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Hallo zusammen,

für das Parsen von obj-Files mit Python habe ich mehrere Ansätze gefunden, z.B. mit objloader.py von pygame.org oder mit einer Funktion in OpenGLContext. Diese Packages gibt es aber nur für Python2. Jetzt habe ich aber mein mittlerweile recht umfangreiches Programm in Python3 geschrieben. Wenn ich es unter Python2 laufen lasse, funktioniert einiges verständlicherweise nicht mehr.

Natürlich könnte ich diese Blender-Files auch händisch parsen, weil sie eigentlich nicht sonderlich kompliziert aufgebaut sind. Aber irgendwie gehört das Parsen von Strings nicht so sehr zu meinen Lieblingsbeschäftigungen beim Programmieren :oops:

Gibt es vielleicht eine einfachere Möglichkeit, diese Files mit Python3 in eine glGenList zu bekommen ?

Grüße
m-o
BlackJack

@mephisto-online: Portiere doch einfach den `pygame`-Code zum laden von OBJ-Dateien nach Python 3.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
Du meinst, das geht ? Einfach mit 2to3 ? Warum eigentlich nicht !

Da bin ich überhaupt noch nicht drauf gekommen :oops: ... werde es direkt mal probieren. Danke !

Ich stell mir halt immer alles viel zu kompliziert vor, sollte ich mir bei Python echt mal abgewöhnen (oder C++ programmieren :shock: :mrgreen: )
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Das funzt nicht. Ich habe folgendes gemacht:

Code: Alles auswählen

$ cd ./OBJFileLoader
$ 2to3 objloader.py
RefactoringTool: Refactored objloader.py
--- objloader.py        (original)
+++ objloader.py        (refactored)
@@ -27,7 +27,7 @@
             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, image)
         else:
-            mtl[values[0]] = map(float, values[1:])
+            mtl[values[0]] = list(map(float, values[1:]))
     return contents
  
 class OBJ:
@@ -44,17 +44,17 @@
             values = line.split()
             if not values: continue
             if values[0] == 'v':
-                v = map(float, values[1:4])
+                v = list(map(float, values[1:4]))
                 if swapyz:
                     v = v[0], v[2], v[1]
                 self.vertices.append(v)
             elif values[0] == 'vn':
-                v = map(float, values[1:4])
+                v = list(map(float, values[1:4]))
                 if swapyz:
                     v = v[0], v[2], v[1]
                 self.normals.append(v)
             elif values[0] == 'vt':
-                self.texcoords.append(map(float, values[1:3]))
+                self.texcoords.append(list(map(float, values[1:3])))
             elif values[0] in ('usemtl', 'usemat'):
                 material = values[1]
             elif values[0] == 'mtllib':
RefactoringTool: Files that need to be modified:
RefactoringTool: objloader.py 
Aber nach wie vor bekomme ich diesen Fehler, wenn ich es mit Python3 laufen lasse:

Code: Alles auswählen

  File objloader.py", line 49, in __init__
    v = v[0], v[2], v[1]
TypeError: 'map' object is not subscriptable
Programm-Code:

Code: Alles auswählen

...
            if values[0] == 'v':
                v = map(float, values[1:4])
                if swapyz:
                    v = v[0], v[2], v[1]  # <---- hier !
                self.vertices.append(v)
Mit Python2 geht es ohne Fehler.

Beim näheren Hinschauen ist mir auch aufgefallen, dass in obloader.py auch das zum obj-File gehörige mtl-File geladen wird, und zwar mit einer pygame-Funktion:

Code: Alles auswählen

            surf = pygame.image.load(mtl['map_Kd'])
            image = pygame.image.tostring(surf, 'RGBA', 1)
pygame habe ich dann natürlich auch versucht, per 2to3 umzuwandeln, das funktioniert aber bei den vielen packages nicht.

Hätte ich gewusst, was es für Einschränkungen bezüglich des Paket-Angebots bei Python3 gibt, hätte ich direkt alles in Python2 programmiert.

Werde mir mal OpenGLContext (Python2) anschauen. Vielleicht kann man ja dort die obj-import-Funktion extrahieren und umwandeln. Grosse Hoffnungen habe ich da aber nicht.
BlackJack

@mephisto-online: Der Fehler tritt beim ausführen des Python 2-Codes auf. Du hast den Patch den 2to3.py ausgibt, offenbar nicht angewendet.

Ausserdem kann 2to3.py nicht alles vollautomatisch konvertieren, man sollte den konvertierten Quelltext durchgehen ob auch alles plausibel geändert wurde, oder ob man noch von Hand Änderungen vornehmen muss, oder sollte.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@BlackJack
Da hast Du recht, ich hatte die Ausgabe von 2to3 nicht angewendet und auch kein -w angehängt. Da bleibt aber immer noch das Problem mit pygame.

Gerade habe ich mit den import-Paketen aus OpenGLContext versucht, erst mal die Abhängigkeiten (logging und urllib) zu installieren. Mit sudo pip install logging bekomme ich einen Syntax-Fehler:

Code: Alles auswählen

  File "/tmp/pycharm-packaging8769514940256449775.tmp/logging/logging/__init__.py", line 618
    raise NotImplementedError, 'emit must be implemented '\
                             ^
SyntaxError: invalid syntax
Wenn ich emit installiere, geht das zwar, aber der gleiche Fehler kommt bei der Installation von logging immer noch.

Bei urllib weiss ich nicht, welches Py3-Paket denn da das Richtige ist - es gibt da mehrere.

Wenn ich mir den objectloader von pygame anschaue, wird da ein pygame.image.load(mtl['map_Kd']) und ein pygame.image.tostring(surf, 'RGBA', 1) gebraucht. in /usr/lib/python27 und in in den Unterverzeichnissen kann ich aber kein image.irgendwas finden und in pygame.h gibt es auch kein image.

Ich denke, an der Stelle wird mir das mit Python doch zu kompliziert. Da ich meine "alten" 2D-Grafiken sowieso schon in Java per Socket benutze, könnte ich den 3D-Teil ja nun auch noch in dem Java-Programm machen. Vielleicht komme ich damit ja besser klar. Dann dient der Python-Teil halt nur der Bedienung und Datenhaltung. Ein weitere Vorteil bei der Benutzung des Java-Programms für die Grafiken ist die Tatsache, dass ich beliebig viele Grafiken auf dem Desktop erzeugen und stehenlassen kann, was ich in Python noch nicht hinbekommen habe. Nach vielen Fehlversuchen hatte ich auch schon hier nachgefragt, da konnte mir auch niemand helfen (oder ich habe mich missverständlich ausgedrückt). Eigentlich hatte ich vor, nach und nach die Java-Grafiken mit Pyside/PyOpengl neu zu programmieren.
BlackJack

@mephisto-online: Das Problem mit dem laden der Texturen musst Du ja sowieso irgendwie lösen in Python 3.x. Halt anders als mit Pygame. Ich nehme mal an mit PySide wenn das die GUI-Bibliothek ist, die Du verwendest.

`logging` und `urllib` gehören zur Standardbibliothek von Python, da muss man nichts installieren.

`emit` kenne ich nicht und da deutet auch nichts darauf hin, dass man so etwas braucht.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Ok, emit habe ich installiert wegen der Fehlermeldung:

Code: Alles auswählen

raise NotImplementedError, 'emit must be implemented '
Das hatte ich so interpretiert, dass 'emit' ein Paket ist. Ein Paket mit diesem Namen ließ sich ja auch problemlos installieren.

Dass Python Standard-Bibliotheken hat, hatte ich nicht mehr auf dem Schirm oder ist bei der Durcharbeitung des Tutorials nicht hängengeblieben. Offensichtlich habe ich bislang auch noch keine gebraucht außer sys und os.

Werde das Ganze jetzt nochmal mit "obj.py", "base.py" und "basenodes.py" und aus der OpenGLContext-Bibliothek und "2to3" versuchen. Vielleicht klappt das ja.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Ein blindes Huhn findet auch mal ein Korn: es existiert ein pygame 1.9.2a0, welches auch mit Python3 funktioniert. Es lässt sich unter Manjaro-Linux aus dem AUR installieren und funktioniert auch. Mit pip geht das nicht.

Für Python selbst braucht man eigentlich kaum Unterstützung, weil es, bis auf ein paar "Seiteneffekte", die man kennen muss, recht unkompliziert ist. Aber für die Python-Umgebung braucht man echt einen Lotsen. Warum bekommt man diese Version von pygame eigentlich nicht ganz regulär mit z.B. "sudo pip install pygame --allow-external pygame" oder mit "...--allow-unverified pygame" installiert ??? Da fängt Python an, einem richtig an die Nerven zu gehen.
BlackJack

@mephisto-online: Die Version bekommt man nicht regulär weil es keine reguläre Version ist. Normalerweise wollen die Leute stabile Releaseversionen wenn sie etwas installieren und keine experimentellen Alpha-Versionen. Die sollte sich installieren lassen wenn man noch ``--pre`` als Option hinzufügt, allerdings weiss ich nicht ob Du Dir damit einen gefallen tust, denn dann musst Du Dich als nächstes mit den Abhängigkeiten von Pygame herum schlagen. Und wozu überhaupt? Denn ich gehe doch mal stark davon aus, dass Du den OpenGL-Kontext von Qt verwendest, und Qt sollte selbst Möglichkeiten bieten Bilder für die Texturen zu laden, da muss man nicht auf Pygame zurück greifen.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

@Blackjack
Die ``--pre``-Option wurde mir nicht angeboten, die anderen schon. Ausserdem wurde der Text immer auf einmal braun - sehr gut zu sehen auf schwarzem Hintergrund ... Aber Danke !

Ich arbeite übrigens auch nicht gerne mit Alphas oder Betas als "Versuchskaninchen". Nur, wenn mir nichts anderes übrig bleibt ...

Mit den Abhängigkeiten von pygame hatte ich keine Probleme. Die Vertices und Materialien aus der obj-Datei werden auch ohne Fehlermeldung geladen. Die erzeugte glList scheint aber nicht OK zu sein, weil nichts angezeigt wird.

OpenGLContext_qt habe ich mir gerde mal runtergeladen und angeschaut. Es scheint aber nur der besseren Integration von OpenGLContext selbst (lässt sich nur unter Python 2.7 installieren) in Qt zu dienen (z.B. Signals und Slots). Die Installation schlägt aber schon unter Python 2.7 fehl.

Habe da noch etwas anderes gefunden: Open Asset Import Library, natürlich alles in C++ geschrieben :evil: , hat aber Python-Bindings :mrgreen: ! Damit kann man sämtliche 3D-File-Formate händeln. Vielleicht komme ich ja damit weiter (auch in Python3 !?)
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Mit der Open Asset Import Library und den Python-Bindings klappt das tatsächlich mit dem Import von einer ganzen Latte von 3D-Formaten - mit Python3. Das Paket habe ich aus den Repos meiner Linux-Distri installiert bekommen und es funktioniert bislang ohne Probleme mit den obj-, sogar auch mit .blend-Dateien.

Für Python2 kann man es auch installieren, wenn man in der PKBUILD-Datei (unter Arch-Linux, wie das in anderen Distris geht, weiss ich nicht) den Eintrag "python setup.py" gegen "python2 setup.py" ändert. Der Hinweisende auf der AUR-Paket-Seite https://aur.archlinux.org/packages/pyassimp-git/ war sich aber nicht 100%ig sicher, dass es auch zu 100% funktioniert. Bei mir klappt es jedenfalls jetzt auch mit Python2, Blender-Files zu importieren :) .

Der Import mit dem obj-Loader von PyGame ist insofern depricated, da er obj-Dateien in eine (depricated) glList lädt.
Antworten