OpenGl: Wie ist eine Objekt aufgebaut?
-
hallo,
ich bin neu in opengl und hab da eine frage: ich will eine datei auslesen die daten von einem Objekt beinhaltet (also x, y, z, farbe, größe, kopf, körper...) beinhaltet. ich lese die datei nun aus und will jetzt z. b. den körper zeichen (hab ja die daten, wie der körper aussieht), aber wie mache ich das? ich kann ja opengl schlecht sagen, dass er den körper (z. b. kreis) mit 20 cm radius und einer 5 cm einkerbung in der mitte (die daten sind alle aus der datei)... kurz:
ich lese die datei mit den daten des objektes ein -> per funktion übergebe ich werte an opengl -> opengl zeichnet die figur anhand den übergebenen werten
danke schonmal
-
Die Daten, die in einem Dateiformat vor liegen, sind standardisierter Weise Triangles (Dreiecke). Um diese Dreiecke zu strukturieren, gibt es dazugehörige Indices (sing. "Index"), auch face-indices genannt. Sprich:
X-Koordinate = vertex[face-index[n.x]].x
So übergibst du die Koordinaten dann am Besten per loop an die OpenGL-Befehle, wie beispielsweise "glVertex3f( x, y, z );" etc.
Vereinfacht gesagt:
Du lädtst und zeichnest nicht die einzelnen Primitiven, sondern die Vertices, die dann die Primitive ergeben.Darf man noch wissen, um welches Dateiformat es sich handelt?
-
jo klar: .x dateien
mein ziel: eigenes dateiformat, das ich einlese und mit opengl dann zeichne
-
Die (Direct)X-Dateien sind vielleicht noch etwas zu komplex für dich... wie wäre es, wenn du dir mal das OBJ-Format ansiehst? Das ist ASCII-Codiert und ziemlich einfach zu verstehen. Wenn du das verstanden hast, dann kannst du dich an dein eigenes Format machen. Du kannst zu Anfang auch einfach nur die vertices strukturiert untereinander schreiben.... allerdings rate ich dir, dass nur für Testzwecke zu verwenden.
-
ok danke, aber ich versteh das jetzt noch weniger... ich habe eine .obj datei (quader mit farbe) und öffne diese mit wordpad und verseh nich was "f", "vt" und "v" bedeutet
-
Hatte mal einen OBJ-Loader für mein Framework geschrieben, generell benutze ich bei soetwas immer Spezifikationen:
http://www.martinreddy.net/gfx/3d/OBJ.spec
Allerdings ist das etwas viel (Müll). Das wichtigste, um normale Modelle laden zu können:v = vertices (Koordinaten) f = face (Index) vt = weiss ich nicht mehr genau, glaube Texturkoordinaten... (Koordinaten)
Am Besten wohl du siehst dir mal an wie so ein Loader aufgebaut ist, dann kannst du es nachvollziehen.
-
danke, habs probiert und der compiler hat nichts gemeldet, also wollte ich das mal testen aber sobald ich die exe starte beendet sich das programm und es kommt ne fehlemeldung:
Unbehandelte Ausnahme bei 0x00242407 in asd.exe: 0xC00000FD: Stack overflow.
Hier mal mein Code von der Funktion, die ich in der main aufrufe:
glTranslatef(0.0, -0.50, -10.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); Vertex v[50000]; Triangle t[50000]; int vertexCount = 0; int triangleCount = 0; char line[100]; FILE *Datei = fopen("2.obj", "r"); if(Datei != NULL) { while(fgets(line, 99, Datei)) { if(line[0] == 'v') { sscanf(line, "%*c %f %f %f", &v[vertexCount].x, &v[vertexCount].y, &v[vertexCount].z); vertexCount++; } else if(line[0] == 'f') { sscanf(line, "%*c %d %d %d", &t[triangleCount].v1, &t[triangleCount].v2, &t[triangleCount].v3); triangleCount++; } } } fclose(Datei); glBegin(GL_TRIANGLES); for (int i=0; i<triangleCount; i++) { glVertex3f(v[t[i].v1-1].x * 0.25, v[t[i].v1-1].y * 0.25, v[t[i].v1-1].z * 0.25); glVertex3f(v[t[i].v2-1].x * 0.25, v[t[i].v2-1].y * 0.25, v[t[i].v2-1].z * 0.25); glVertex3f(v[t[i].v3-1].x * 0.25, v[t[i].v3-1].y * 0.25, v[t[i].v3-1].z * 0.25); } glEnd(); glFlush();
danke schonmal
-
Hum, das könnte gut ein Bufferoverflow sein... Es ist im Übrigen ziemlich hässlich, auf gut Glück einfach mal 50k Elemte zu reservieren. Der Code sieht mir stark nach C aus, wie siehts aus mit C++? Da gäbe es dann tolle Möglichkeiten wie beispielsweise std::vector und std::ifstream. Mit den std::vectoren kannst du dann dynamisch rumallokieren, ist echt eine tolle Sache. Ich habe damals auch einen OBJ-Loader für mein damaliges Framework geschrieben, ich schreibe ihn bei Zeiten mal neu, da immernoch die MTL-Daten nicht richtig geparst werden. Ich hab ihn mal hochgeladen, der Code sollte (in einer C++-Umgebung) funktionieren:
http://coders-square.de/downloads/Framework.rar
Und wie bereits gesagt, ist es ein altes Ding und sollte nochmal überarbeitet werden. Kann man aber schnell in 2min. machen.
-
ok danke, aber für deine datei brauch ich header dateien die nicht dabei sind:
z.b. vector2.h oder vector3.h
-
Dachte ich mir schon... Sieht natürlich so aus:
#include "Framework.h" #ifndef VECTOR3_HEADER #define VECTOR3_HEADER class Vector3 { public: Vector3(); ~Vector3(); float x; float y; float z; }; #endif VECTOR3_HEADER
Kannste auch direkt in die Headerdatei des Loaders einfügen, dann natürlich ohne Framework-Include und Includeguards. Vector2( ) hingegen sieht genau so aus, halt nur ohne die Z-Koordinate, sollte klar sein... Damit mein Image hier nicht verschmutzt wird: Im Framework gibt es ebenfalls 2 und 3-Dimensionale Vektorklassen mit Operatorenüberladung, in diesem Parser hatte es jedoch so gereicht^^.
-
ok danke, jetzt hab ich nur noch zwei probleme: ich bekomm bei convertToInt und getWord immer "Bezeichner wurde nicht gefunden".
danke schonmal
-
Achso, klar doch. Ich dachte das wäre selbstverständlich: Das ist eine Konvertierung von einem std::string zu einem integer. Also nichts anderes als:
int zahl = ::atoi( zahl.c_str( ) );
und bei der zweiten Konvertierung zum Float natürlich: ::atof( );.
-
ah ok danke, jetzt hab ich nur noch die errors wegen dem getWord
-
#ifndef STRING_HEADER #define STRING_HEADER std::string const getWord(std::string Line, int Pos) { std::vector<std::string> Vec; std::stringstream ss(Line); std::string Word, a; while(ss >> Word) Vec.push_back(Word); return (static_cast<unsigned int> (Pos) + 1 > Vec.size() ? "" : Vec[Pos] ); } float convertToFloat(std::string Num) { if((strlen(Num.c_str())) > 0) { float x = static_cast<float> ( atof( Num.c_str( ) ) ); return x; } else { Num.clear(); return 0; } } int convertToInt(std::string Num) { if((strlen(Num.c_str())) > 0) { int x = atoi(Num.c_str()); return x; } else { Num.clear(); return 0; } } #endif STRING_HEADER
-
vielen dank hat alles fuktioniert
edit: ich bekomme 4 linker fehler (LNK2019) bei den 2 klassen (vector2 und vector3)
-
Schick mir dein Projekt eben per E-Mail...
-
ok
-
Nachdem du mir sehr per E-Mail geholfen hast, habe ich nur noch ein Problem: Meine .Obj Datei wird nicht angezeigt, obwohl ich sie im Code rendere.
Den Link zu meinem Projekt müsstest du noch haben, fals nicht sag bescheid, dann schick ich nochmal den Link.
-
Deine letztendliche Vertexausgabe war an die Erfüllung einer Kondition geknüpft, nämlich:
if( texture->ModelHasUV ) glVertex3f( x, y, z );
Oder so ähnlich, du hast aber eine E-Mail bekommen. Und wie gesagt, wenn du mal alles durchdebuggst, solltest du den/die Fehler leicht finden...
-
danke für deine mail, aber (ich weiß echt nich was ich falsch mache) es geht nicht. immer wenn ich kompiliere und anschließend starte kommt nur das fenster mit dem schwarzen hintergrund und sonst nichts.