Announcement

Collapse
No announcement yet.

Assimp

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Assimp

    hej leute,

    kann mir vielleicht jemand erklären, wie ich assimp mit visual studio 2010 "verwende"?
    auf der doku-seite von assimp steht nämlich, dass die pre-compiled libs lediglich für Visual C++ 2005 und 2008 verwendet werden können. wie muss ich nun bei VS 2010 vorgehen?
    die dokumentation von assimp selbst und das PDF auf der CG-wiki-seite sind (für mich) nicht gerade hilfreicht, da ich bisher noch keine erfahrung mit C++ und mit visual studio habe. das ist alles ein bischen viel neues auf einmal

    doku: http://assimp.sourceforge.net/lib_html/index.html
    PDF: https://lva.cg.tuwien.ac.at/cgue/wik...nts:assimp.pdf

    für eine schritt-für-schritt-anleitung wäre ich überaus dankbar
    dominik

  • #2
    Hallo dominik, folgende Schritte sollten dich zum Ziel führen:
    1. Von der offiziellen Homepage den obersten Release assimp 2.0 für Any Platform herunterladen und in den Folder für deine external libs entpacken.
    2. Bei den Project Properties in VS2010 unter "C/C++" > "General" bei "Additional Include Properties" eine Zeile hinzufügen die auf den "include" folder von assimp zeigt, ungefähr so:
    "$(SolutionDir)external\assimp--2.0.863-sdk\include"
    3. Unter "Linker" > "General" bei "Additional Library Directories" die win32 release libraries hinzufügen, ca. so: "$(SolutionDir)external\assimp--2.0.863-sdk\lib\assimp_release-dll_win32". Ich hab das für Debug und Release Konfiguration eingebunden, obs mit Debug library und win64 auch geht weiß ich nicht, einfach probieren.
    4. Unter "Linker" > "Input" bei "Additional Dependencies" die Library "assimp.lib" zusätzlich einbinden.
    5. Nach deinem ersten Build muss noch die Assimp32.dll (von (assimpdir)/bin/assimp_release-dll_win32) in den Ordner kopiert werden, wo VS2010 deine .exe hinspeichert, also typischerweise unter (solutiondir)/Debug.

    lg
    Christian
    Christian Hafner
    [EVC | CGUE | RTR | ARTR | ModCG Tutor]

    Comment


    • #3
      ich hab etwas schwierigkeiten dabei model data einzulesen

      Code:
      void loadModelData(const string file) {
      //Load file
      Assimp::Importer importer;
      const aiScene* scene = importer.ReadFile(file,
          aiProcess_CalcTangentSpace |
          aiProcess_Triangulate |
          aiProcess_JoinIdenticalVertices |
          aiProcess_FlipUVs     );
       if(!scene) {
         std::cerr << "assimp: importer.readfile failed to read the file!" <<endl;
      }
      //......
      Es scheitert schon an ReadFile danach ist die scene nämlich null, aber der filepath sollt eig passen den ich angeb und viel mehr rückmeldung als access violation wo scene dann gebraucht wird bekomm ich nicht =/

      außerdem wollte ich fragen wie man das am besten struktuiert, ich hab daweil das (fail)modelloading in einem eigenn cpp und hpp file und der legt ja vertices und indices laut folien vom wiki am heap an, wie bekomm ich die jetzt von dort wieder in mein main programm nach c++-best-practice (was ich als anfänger nicht beherrsche)? und danach muss mans auch wieder intelligent löschen können, muss ich dann die daten global im model.cpp file speichern und mit ner 2. function explizit löschen? oder muss man das main programm noch länger machen als es eh schon ist damit man alles dort zu verfügung hat. ich hoffe das ergibt gerade irgendeinen sinn

      ah.. und soll man dieses struct wo die normals, positions etc drin sind mit glm vektoren oder mit assimp vektoren machen, daweil speicher ich die geholten assimp auf glm um
      Last edited by Getshi; 08-04-2012, 12:35.

      Comment


      • #4
        Eine Moeglichkeit, wenn du eine Klasse hast, die deine gesamte Szene repraesentiert:
        In dem Konstruktur dieser Klasse laedst du mit Assimp deine Daten und befuellst die Szene.
        Im Destruktur baust du ne Routine, welche deine Daten wieder loescht.
        In der Main erstellst du dann eine Instanz der Klasse und rufst dann (wenn notwendig) den Destruktur auf.

        struct: ich wuerde glm vektoren verwenden

        Hoffe, das hilft.
        Last edited by ClemensRoegner; 08-04-2012, 14:39.
        Clemens Roegner
        Tutor for: CGUE, EVC, ECG, RTR

        Comment


        • #5
          Das Debugging, wenn ReadFile scheitert, ist in der Tat etwas schwer. Verwendest du einen relativen oder absoluten Pfad? Wenn relativ, mach mal einen absoluten Pfad daraus. Es gibt auch einige nicht offensichtliche Bedingungen in ReadFile, auch durch bestimmte Import Flags, z.B. eine maximale Anzahl an einzelnen Meshes oder eine Obergrenze an Vertices pro Mesh (obwohl die irgendwo bei 4 Millionen liegt, das sollte bei dir nicht das Problem sein). In jedem Fall gibt ReadFile einfach NULL zurück. Zwei Sachen kannst du prüfen:
          - ReadFile mit 0 als zweitem Parameter aufrufen, also keine Import Flags verwenden
          - Das Model mit dem AssimpViewer (gibt es separat auf http://assimp.sourceforge.net/main_downloads.html) öffnen. Wenn es da nicht geht, kann Assimp die Datei nicht lesen.

          Allgemein ist es mehr als eine Überlegung wert, Assimp vom SVN (Daten gibts auch unter obigem Link) runterzuladen und zu kompilieren, immerhin ist die letzte Stable Version anderthalb Jahre alt und es hat sich einiges getan seither. Also es kann gut sein, dass irgendwelche Import-Bugs oder so gefixt wurden.
          Former ECG & CGUE Tutor

          Comment


          • #6
            Originally posted by ClemensRoegner View Post
            Eine Moeglichkeit, wenn du eine Klasse hast, die deine gesamte Szene repraesentiert:
            In dem Konstruktur dieser Klasse laedst du mit Assimp deine Daten und befuellst die Szene.
            Im Destruktur baust du ne Routine, welche deine Daten wieder loescht.
            In der Main erstellst du dann eine Instanz der Klasse und rufst dann (wenn notwendig) den Destruktur auf.

            struct: ich wuerde glm vektoren verwenden

            Hoffe, das hilft.
            meinst du mit szene jetzt eine aiScene sprich ein model oder ein spiellevel oder ein ganzes spiel? ich nehm jetzt mal an ein level, wo man beim erstellen/öffnen alle benötigten models lädt. und wie benutze ich die daten dann - eine draw methode machen die alles für die szene übernimmt, also alle benötigten vaos enablen, zeichnen etc?

            @mOfl das mit dem readfile hab ich gerade bemerkt war zum glück nur ein dummer fehler von mir, hab mir modelfile und modelpath als 2 strings gespeichert und dann addiert, aber ich hab statt dem modelpath bei mir den texturepath verwendet. also das einlesen stürzt jetzt nicht mehr ab. msus aber jetzt erst noch schaun ob ichs wirklich anzeigen kann. aber danke!

            Comment


            • #7
              Originally posted by Getshi View Post
              meinst du mit szene jetzt eine aiScene sprich ein model oder ein spiellevel oder ein ganzes spiel?
              Also eigtl solltest du in deinem Spiel fuer ein Level(=Szene) eine eigene "Verwaltung" haben. "Verwaltung" kann dann im Endeffekt vieles sein (Scenegraph,...). Diese "Verwaltung" der Szene und der darin enthaltenen Modelle solltest du dir selbst machen (an deine Anforderungen abgepasst). Assimp liefert dir mit aiScene nur ein Konstrukt welches das File beschreibt, das du geladen hast. Sprich das Assimp-Zeug solltest du eigtl nicht zum Rendern verwenden, sondern dir deine eigenen Klassenstruktur, die dir dein Level beschreibt basteln. (uebrignes die Assimp-Klassenstruktur ist an Collada angelehnt). Also das aiScene ding nur zum Daten auslesen verwenden.



              Originally posted by Getshi View Post
              ich nehm jetzt mal an ein level, wo man beim erstellen/öffnen alle benötigten models lädt. und wie benutze ich die daten dann - eine draw methode machen die alles für die szene übernimmt, also alle benötigten vaos enablen, zeichnen etc?
              Hier gibt es natuerlich auch einige Moeglichkeiten. Du kannst natuerlich eine draw Methode schreiben, die alles fuer dich macht. Ob das sinnvoll ist, haengt davon ab wie Komplex das Spiel im Endeffekt sein wird (weil bei zu Komplexen Spielen die Methode explodiert und du nicht mehr weisst wo vorne und hinten ist.)
              So, was ich dazu bis jetzt geschrieben habe, hilft dir natuerlich noch nicht weiter. Du stehst, wie vielleicht einige andere hier, vor dem grossen und sehr wichtigen Problem der Strukturierung eures Programms. Wie du das am Besten machst, haengt von deinen Anforderungen ab (wie oben bereits erwaehnt - vl kannst du dir schon denken dass deine draw-Routinen in der Klassenstruktur, welche die Szene beschreibt, gut aufgehoben sind. sie muessen aber nicht unbedingt dort sein). Ums kurz zu machen: Sprich bitte mal mit den Tutoren von Angesicht zu Angesicht darueber. Das ist mMn der einzig gute Schritt den du nun machen kannst. Beschreib' ihnen dein Spiel, also deine Anforderungen, und sie werden dir helfen die Klassenstruktur aufzubauen (und mach das bitte schnell - viel Zeit hast du nicht mehr).

              P.S.: ich stehe leider atm nicht zur verfuegung, da ich nicht im Lande bin
              Last edited by ClemensRoegner; 08-04-2012, 22:06.
              Clemens Roegner
              Tutor for: CGUE, EVC, ECG, RTR

              Comment


              • #8
                hmmm hab eine neue frage, ich hab den code wie in den folien versucht nachzubauen und da hat man ein structarray für alle vertexdaten (pos, normals, ....)
                wie benutz ich das jetzt für die VBOs.


                glBufferData(GL_ARRAY_BUFFER, model_vertices_size, model_vertices->pos, GL_STATIC_DRAW);

                Das funktioniert natürlich so nicht, weil er über model_vertices iterieren muss udn von den einzelnen dann pos nehmen und ned über pos vom ersten. meine frage ist jetzt wie ich aus diesem structarray mir alle positionen als einzelnes array herausfilter. wenn das nicht wirklich geht ohne mühsam herumzukopieren dann wäre der code ja nicht wirklich sinnvoll oder?
                ich könnt auch noch viel mehr pointer übergeben als nur 1 für indicesarray und 1 für structarray, halt für alles einzeln, pos normals, tangent, bitangent ,... aber das scheint mir auch ned das wahre zu sein
                --EDIT
                mit manuellem rauskopiern hab ichs mal probiert damit ich herumprobieren kann, aber ich krieg genau 3 buggy dreiecke aus dem model raus =/ und die assimp tutorials die ich finde haben alle extrem langen code und geben mir dadurch wenig einsicht
                Last edited by Getshi; 10-04-2012, 16:07.

                Comment


                • #9
                  Der Code in den Folien erzeugt ein großes Struct-Array "vertices", bei dem alle Attribute zu einem Vertex gespeichert werden, also das ist eine sehr lange Wurst, wo alle Vertices jeweils den Abstand sizeof(Vector4) + 3 * sizeof(Vector3) + sizeof(Vector2) haben. Diese Form von Buffer heißt interleaved. Der Vorteil ist, dass du nur einen einzigen Buffer brauchst, der Nachteil ist, dass es komplizierter zu handhaben ist als separate Buffer. Da du in Assimp in der aiScene ja abfragen kannst, wie viele Vertices dein Mesh hat, kannst du statt eines interleaved VBOs auch gleich zu Beginn separate Arrays für alle Attribute mit der Größe mNumVertices erstellen und einzelne Buffer verwenden - das bleibt dir überlassen.

                  Wenn du den Code so verwenden willst wie in den Folien, dann gibst du als Größe der einzelnen Elemente sizeof(sStdGeomVertex) an und die Position ist das Array selbst, in den Folien vertices. Du musst dich jetzt darum kümmern, dass die einzelnen Attribute auch an der richtigen Stelle im Shader ankommen. Dafür verwendest du glVertexAttribPointer, das erwartet einen Parameter stride, also die Schrittweite von einem Element zum nächsten, was genau der Größe des Structs entspricht. Zusätzlich gibst du noch ein Offset zum ersten Element des jeweiligen Attributs im Buffer als pointer an.

                  Wenn du nach interleaved VBO googlest, werden dir übrigens relativ oft die Funktionen glVertexPointer, glColorPointer, glNormalPointer, glTexCoordPointer u.ä. unterkommen - die dürft ihr für die Übung nicht verwenden, da sie deprecated sind. Also solchen Sample-Code am besten gar nicht anschauen. Es gibt auf der OpenGL-Seite ein paar gute Tutorials, auch eins für Interleaved VBOs ohne Deprecated Calls.
                  Former ECG & CGUE Tutor

                  Comment


                  • #10
                    aahhh. okay nur damit ich das jetzt richtig verstehe:

                    ich benutze nurnoch ein vbo, das ich mal generiere und binde, mit bufferdata buffer ich dann das ganze structarray "model_vertices" und sag im als size nur sizeof(sStdGeomVertex) und danach weise ich die gebufferten datan alle mit mehreren vertexattrib calls zu also mehrmals hintereinander glVertexAttribPointer mit verschiednen offsets aber immer dem gleichen stride.

                    wie zeichne ich dann damit, ganz normal mit (GL_TRIANGLES, 0, numVertices) ? ich nehm an die indices muss man auch noch intelligent verwenden =/
                    ich hoffe ich stelle nicht zu viele unnötige fragen, sollte ich der einzige sein der sich damit schwer tut

                    Comment


                    • #11
                      Originally posted by Getshi View Post
                      ich benutze nurnoch ein vbo, das ich mal generiere und binde, mit bufferdata buffer ich dann das ganze structarray "model_vertices" und sag im als size nur sizeof(sStdGeomVertex) und danach weise ich die gebufferten datan alle mit mehreren vertexattrib calls zu also mehrmals hintereinander glVertexAttribPointer mit verschiednen offsets aber immer dem gleichen stride.
                      Genau.

                      wie zeichne ich dann damit, ganz normal mit (GL_TRIANGLES, 0, numVertices) ? ich nehm an die indices muss man auch noch intelligent verwenden =/
                      ich hoffe ich stelle nicht zu viele unnötige fragen, sollte ich der einzige sein der sich damit schwer tut
                      Das Zeichnen sollte eigentlich gar keinen Unterschied machen zwischen interleaved und normal. Die Indices sind ja von den Attributen unabhängig, also wenn du dir einen Index-Buffer erstellst, dann kannst du zum Zeichnen glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, NULL) verwenden. Den Index-Buffer pro Mesh erstellst du dir, indem du über die Faces des Meshs in der Assimp-Struktur iterierst und einfach die jeweils drei Indices in ein Array rausschreibst. Wenn du ohne Indices auskommst, dann sollte glDrawArrays(GL_TRIANGLES, 0, numVertices) korrekt sein.
                      Former ECG & CGUE Tutor

                      Comment


                      • #12
                        Also ich bekomm zwar keine fehler aber schwarz ist trotzdem alles, und ich vermute dass es was mit stride zu tun hat. in der doku steht etwas von byte offset, aber wie soll ich wissen wieviele byte ein struct mit mehreren glm vectors denn hat?
                        ich versuch gerade nur die position einzulesen und das model anzuzeigen und hab dafür im vertex shader location 0 für position (vec4) , welche ich auch mit glEnableVertexAttribArray(0) aktiviere (wobei ich mir eig noch immer nicht sicher bin trotz google etc. wann ich diese methode genau brauche)
                        im fragment shader sag ich ihm einfach er soll mir mal weiß anzeigen testhalber, aber ich seh nix =/ der array buffer offset macht mich auch etwas stutzig

                        glVertexAttribPointer( 0, // attribute 0 in vertex shader
                        4, // size
                        GL_FLOAT, // type
                        GL_FALSE, // normalized?
                        (4+3+2+3+3), // stride //not 0 because of struct
                        (GLvoid*)0 // array buffer offset
                        );

                        Comment


                        • #13
                          Hallo,

                          Wenn deine Position die ersten 4 floats in deinem Strukt sind sollte der Array-Offset passen.
                          Anmerkung: statt (4+3+...) kannst du sizeof(DEINSTRUCT) verwenden.
                          Bernhard Steiner
                          [CGUE Übungsleitung]

                          Comment


                          • #14
                            Originally posted by Getshi View Post
                            in der doku steht etwas von byte offset, aber wie soll ich wissen wieviele byte ein struct mit mehreren glm vectors denn hat?
                            sizeof(glm::vec4) sizeof sagt dir, wie viele Bytes ein Datentyp hat, das geht auch für Structs. Du musst bei Structs aber aufpassen, weil das afaik immer für 4-Byte-Blöcke optimiert wird, d.h. die Summe der einzelnen Vektoren ist nicht zwingend gleich der Größe des ganzen Structs, dazu hier eine kurze Erklärung: http://stackoverflow.com/questions/1...of-each-member

                            ich versuch gerade nur die position einzulesen und das model anzuzeigen und hab dafür im vertex shader location 0 für position (vec4) , welche ich auch mit glEnableVertexAttribArray(0) aktiviere (wobei ich mir eig noch immer nicht sicher bin trotz google etc. wann ich diese methode genau brauche)
                            Der Buffer hat erstmal überhaupt nichts mit dem Shader zu tun, das sind einfach Daten im Videospeicher. Willst du die im Shader verwenden, musst du dich selbst darum kümmern. Im Vertex Shader kannst du eingehende Attribute bestimmen, die ihre Daten aus dem Buffer nehmen, aber dazu musst du das jeweilige Attribut im Shader mit dem Buffer verknüpfen. Dafür hast du mehrere Möglichkeiten:
                            - Du gibst die Indizierung der Attribute explizit im Shader vor:
                            Code:
                            layout(location = 0) in vec4 inPosition;
                            - Du gibst die Indizierung explizit vor dem Linken des Shaders vor:
                            Code:
                            glBindAttribLocation(shaderHandle, 0, "inPosition");
                            Danach kannst du den Buffer mit dem Attribut verbinden (mit entsprechenden Parametern für deinen interleaved Buffer dann halt):
                            Code:
                            glEnableVertexAttribArray(0);
                            glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
                            So, das Problem ist aber, dass die explizite Indizierung relativ unübersichtlich wird, wenn du mal ein paar Attribute hast, eventuell merkst, dass du ein Attribut nicht mehr brauchst, dafür aber zwei andere, dann noch einen Shader für mehrere Objekte verwenden willst, ... Deshalb empfiehlt es sich grundsätzlich, sich damit nicht rumzuschlagen, sondern nur über den Namen auf Attribute zuzugreifen (ebenfalls wieder eigene Parameter für stride verwenden):

                            Code:
                            int positionIndex = glGetAttribLocation(shaderHandle, "inPosition");
                             
                            glEnableVertexAttribArray(positionIndex);
                            glBindBuffer(GL_ARRAY_BUFFER, positionVboHandle[i]);
                            glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
                            Ich hoffe, so wird das etwas klarer. Der Sinn von glEnableVertexAttribArray ist, Attribute Location im Shader und Buffer zu verbinden.

                            der array buffer offset macht mich auch etwas stutzig
                            glVertexAttribPointer( 0, // attribute 0 in vertex shader
                            4, // size
                            GL_FLOAT, // type
                            GL_FALSE, // normalized?
                            (4+3+2+3+3), // stride //not 0 because of struct
                            (GLvoid*)0 // array buffer offset
                            );
                            Ja, der Stride hier stimmt nicht, weil das ein Wert in Bytes sein sollte, d.h. du müsstest alles noch mit 4 bzw. mit sizeof(float) multiplizieren, da ein Float 4 Bytes hat.
                            Former ECG & CGUE Tutor

                            Comment


                            • #15
                              also ich bekomm immer nur schwarz trotz allen tipps hier. allerdings funktionierts mit nicht ausgelesenen daten...

                              glBufferData(GL_ARRAY_BUFFER, sizeof(sStdGeomVertex),
                              model_vertices, GL_STATIC_DRAW);
                              //....
                              glVertexAttribPointer(
                              0, // attribute 0 in vertex shader
                              4, // size
                              GL_FLOAT, // type
                              GL_FALSE, // normalized?
                              sizeof(sStdGeomVertex), // stride //not 0 because of struct
                              (GLvoid*)0 // array buffer offset
                              );

                              funktioniert nicht, hingegen ein würfel mit manuell getippten vertices funktioniert mit folgendem

                              glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
                              g_vertex_buffer_data, GL_STATIC_DRAW);

                              glVertexAttribPointer( 0, // attribute 0 in vertex shader
                              3, // size
                              GL_FLOAT, // type
                              GL_FALSE, // normalized?
                              0,//sizeof(sStdGeomVertex), // stride //not 0 because of struct
                              (GLvoid*)0 // array buffer offset
                              );

                              ---EDIT

                              huch.. wenn ich die size beim bufferdata ändere bekomm ich wenigstens wilde dreiecke

                              glBufferData(GL_ARRAY_BUFFER, sizeof(sStdGeomVertex)*model_vertices_size,
                              model_vertices, GL_STATIC_DRAW);
                              Last edited by Getshi; 10-04-2012, 19:16.

                              Comment

                              Working...
                              X