[gelöst] [Newbiefrage] NeHe Tutorial 10 - Eine 3D Welt laden und sich in ihr bewegen.



  • Hi,

    ich sitze jetzt seit heute Morgen um 9 Uhr da dran und musste jetzt abbrechen weil ich langsam aggressiv werde... Ich bekomm's einfach nicht zum laufen. Ich arbeite mich momentan durch die NeHe Tutorials und komme einfach nicht weiter. Stecke jetzt in Tutorial 10 "Eine 3D Welt laden und sich in ihr bewegen" fest. Dieses Tutorial meine ich, bzw. hier auf deutsch.

    Ich hab's jetzt soweit eingegrenzt das ich denke zu wissen wo der Fehler liegt, auch wenn ich ihn nicht finde. 😞 Das ganze soll Daten aus einer Textdatei (world.txt) lesen die momentan so ausschaut:

    /* LEERZEILE (zeigt C++.de sonst nicht an wenn ich hier nix schreib) */
    NUMPOLLIES 2
    
    // Test
    -1.0 -1.0  0.0 0.0 0.0
     1.0 -1.0  0.0 1.0 0.0
    -1.0  1.0  0.0 0.0 1.0
    
     1.0 -1.0  0.0 1.0 0.0
     1.0  1.0  0.0 1.0 1.0
    -1.0  1.0  0.0 0.0 1.0
    

    Der Code der die Textdatei lesen soll ist der hier:

    void ReadLine( FILE* f, char* string)
    {
    	do
    	{
    		fgets( string, 255, f);
    	} while ( (string[0] == '/') || (string[0] == '\n'));
    }
    
    void SetupWorld()
    {
    	GLfloat x, y, z, u, v;
    	int numtriangles;
    	FILE* filein;
    	char oneline[255];
    	filein = fopen( "world.txt", "rt");
    	ReadLine( filein, oneline);
    
    	sscanf( oneline, "NUMPOLLIES %d\n", &numtriangles);
    
    	/* CODE */
    
    	for( int loop = 0; loop < numtriangles; loop++)
    	{
    		for( int vert = 0; vert < 3; vert++)
    		{
    			ReadLine( filein, oneline);
    			sscanf( oneline, "%f %f %f %f %f", &x, &y, &z, &u, &v);
    
    			/* CODE */
    		}
    	}
    
    	fclose( filein);
    }
    

    Ich bekomm's nicht hin. Er liest nur dann den Wert hinter NUMPOLLIES aus (hier also 2), wenn ich die Leerzeile dadrüber entferne. Damit, könnte ich ja sogar leben aber warum ist das so? Normal müsste es doch auch mit der Leerzeile funktionieren? Und beim auslesen der jeweils 5 Werte funktioniert auch was ganz komisch nicht. Ich habe hinterher nur bei x einen Wert. Alle anderen Variablen sind leer. Ich raff's einfach nicht und werd mich jetzt ein wenig an der Wii abreagieren! (Ghost Squad ich komme...)

    Gruß Daniel


  • Mod

    Da ist an sich nichts falsches dran (das ist übrigens C, kein C++).

    Falls du unter Windows arbeitest: Dort ist ein Zeilenumbruch \r\n und nicht einfach nur \n, daher wird es dort zu Problemen kommen.



  • Genau genommen arbeite ich unter Mac und da soll es ja sogar nur "\r" sein. Aber ich hab alles 3 schon ausprobiert und nix davon funktioniert.

    Hmm, wie schreib ich das denn dann richtig in C++? Ich versuch halt momentan C++, SDL und OpenGL alles 3 gleichzeitig durcheinander ohne Vorkenntnisse zu lernen und weil die NeHe Tutorials alle für Windows sind mit C und GLUT komme ich irgendwie manchmal nicht ganz zu rande... 😞


  • Mod

    insanity schrieb:

    Genau genommen arbeite ich unter Mac und da soll es ja sogar nur "\r" sein. Aber ich hab alles 3 schon ausprobiert und nix davon funktioniert.

    Hmm, merkwürdig. Bei mir funktioniert es, habe aber auch keinen Mac. Lass dir zu Debugzwecken doch mal die gelesenen Zeilen in deinem Programm Byte für Byte ausgeben (als Zahlenwert, nicht als Buchstabenwert, sonst siehst du die nicht-druckbaren Zeichen nicht!), damit du siehst, wie der Zeilenumbruch codiert ist.

    Hmm, wie schreib ich das denn dann richtig in C++? Ich versuch halt momentan C++, SDL und OpenGL alles 3 gleichzeitig durcheinander ohne Vorkenntnisse zu lernen und weil die NeHe Tutorials alle für Windows sind mit C und GLUT komme ich irgendwie manchmal nicht ganz zu rande... 😞

    Ganz, ganz anders. Aber dazu liest du dir lieber mal ein C++ Tutorial durch. Je nach gewünschtem Abstraktionsgrad kann man das beliebig kompliziert machen.



  • Einfach reicht mir vollkommen... 😉

    Hast du da eventuell so aus dem Stehgreif nen Tutorial als Empfehlung für mich? 🙂


  • Mod

    insanity schrieb:

    Einfach reicht mir vollkommen... 😉

    Hast du da eventuell so aus dem Stehgreif nen Tutorial als Empfehlung für mich? 🙂

    Ich habe spontan mit Google diese gefunden. Die sind kurz und knapp, sehen aber fachlich kompetent aus.

    Tutorial für C-Umsteiger wie dich:
    http://cplus.about.com/od/learning1/ss/clessontwo.htm

    Überblick über die wichtigsten Klassen die man neben den Streams noch häufig zur Verarbeitung von Eingabedaten benötigt (string und stringstream):
    http://www.cplusplus.com/doc/tutorial/basic_io/

    In beiden Fällen gilt, dass der Inhalt, obwohl für cout und cin geschrieben, auch 1:1 auf Dateistreams übertragbar ist. Ein gesundes Grundverständnis der benutzten C++-Terminologie (Klassen, Objekte,...) ist natürlich Voraussetzung um die Tutorials zu verstehen.



  • Hab ich was verpasst? Seit wann ist cout vs. printf der wichtigste Unterschied zwischen C und C++? 😕


  • Mod

    Michael E. schrieb:

    Hab ich was verpasst? Seit wann ist cout vs. printf der wichtigste Unterschied zwischen C und C++? 😕

    Wer sagt, dass es der wichtigste Unterschied ist? In diesem Thread geht es nun einmal nur um Ein-/Ausgabe, deswegen gehe ich auch nur auf die Unterschiede bei diesem Thema ein.



  • Nagut, ich pack dann wohl mal die ganze SDL OpenGL Geschichte in die Ecke und fang noch mal vorne an. Scheiße 😞

    Aber warum der Code nicht funktioniert weiss jetzt auch keine oder? Na egal, auf geht's, erstmal C++ lernen und dann SDL und OpenGL drauf setzen... 🙂


  • Mod

    insanity schrieb:

    Aber warum der Code nicht funktioniert weiss jetzt auch keine oder?

    Finden wir es gemeinsam heraus!

    Was gibt dieses Programm bei dir aus, wenn die erste Zeile in world.txt eine Leerzeile ist?

    #include<stdio.h>
    int main()
    {
      char oneline[2];
      FILE* filein;
      filein = fopen( "world.txt", "rt");
      fgets( oneline, 2, filein);
      printf("%i\n", oneline[0]);
      printf("%i %i\n", '\n', '\r');
    }
    

    Ich tippe übrigens auf

    32
    10 13
    


  • Da bekomme ich:

    10
    10 13
    

    [EDIT]
    Wer lesen kann ist klar im Vorteil. Bekomme die selbe Ausgabe wie du. Hatte in die Textdatei als erstes nen Zeilenumbruch gemacht und kein Leerzeichen... 🙂


  • Mod

    insanity schrieb:

    Da bekomme ich:

    10
    10 13
    

    [EDIT]
    Wer lesen kann ist klar im Vorteil. Bekomme die selbe Ausgabe wie du. Hatte in die Textdatei als erstes nen Zeilenumbruch gemacht und kein Leerzeichen... 🙂

    Halt, halt, halt! 10 wäre ja richtig! Ich hatte mir gedacht, dass du vielleicht versehentlich ein Leerzeichen in der Datei hattest, dann würde deine Einleseroutine nämlich nicht funktionieren. So sollte sie eigentlich funktionieren, wenn du auf '\n' prüfst.



  • SeppJ schrieb:

    Halt, halt, halt! 10 wäre ja richtig! Ich hatte mir gedacht, dass du vielleicht versehentlich ein Leerzeichen in der Datei hattest, dann würde deine Einleseroutine nämlich nicht funktionieren. So sollte sie eigentlich funktionieren, wenn du auf '\n' prüfst.

    Ne, dann bleib ich bei meinem ersten... 10 war also die Ausgabe.



  • Ok, ich hab mich mal ein wenig eingelesen und bin jetzt soweit, allerdings komme ich jetzt nicht weiter. Wie filter ich denn jetzt am besten die Zeilen raus die Unbrauchbar sind, also alle die mit einem "/" oder "\n" beginnen? Und wie filter ich dann die Werte die ich haben will? Hab's mit sscanf versucht aber irgendwie will das bei mir nicht so wie ich will... 😃

    ifstream f;
    string s;
    f.open( "world.txt", ios::in);
    while(!f.eof())
    {
    	getline(f, s);
    }
    f.close();
    

    Eventuell hat ja jemand einen Tipp für mich mit dem ich dann vielleicht sogar von selbst drauf komme? 🙂

    Achso, und ich hoffe das ich dann diesmal tatsächlich C++ verwende und nicht wieder C und nur glaube das es C++ ist... 😉



  • So, Doppelposts sind zwar schon blöd, also 3fach noch blöder, aber muss grad sein... 😉 Hab noch ein wenig rumgespielt und dabei ist mir folgendes aufgefallen bei der Ausgabe des Codes: FILE und ifstream lesen meine .txt anders aus. Also vom Inhalt her. Aber hier mal mein Code und drunter das Ergebnis. Dabei sollte eigentlich bei beiden das selbe Ergebnis rauskommen?

    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main()
    {
    	cout<<"----------Test1----------ifstream/string"<<endl;
    	ifstream file1;
    	string content1;
    	file1.open("world.txt", ios::in);
    	while(!file1.eof())
    	{
    		getline(file1, content1);
    		printf("%i: ", content1[0]);
    		cout<<content1<<endl;
    	}
    	file1.close();
    
    	cout<<"----------Test2----------ifstream/char"<<endl;
    	ifstream file2;
    	char content2[256];
    	file2.open("world.txt", ios::in);
    	while(!file2.eof())
    	{
    		file2.getline(content2, sizeof(content2));
    		printf("%i: ", content2[0]);
    		cout<<content2<<endl;
    	}
    	file2.close();
    
    	cout<<"----------Test3----------FILE/char"<<endl;
    	FILE *file3;
    	char content3[256];
    	file3=fopen("world.txt", "r");
    	while(!feof(file3))
    	{
    		fgets(content3, 256, file3);
    		printf("%i: ", content3[0]);
    		cout<<content3<<endl;
    	}
    	fclose(file3);
    }
    
    ----------Test1----------ifstream/string
    0: 
    78: NUMPOLLIES 2
    0: 
    47: // Test
    45: -1.0 -1.0 0.0 0.0 0.0
    ----------Test2----------ifstream/char
    0: 
    78: NUMPOLLIES 2
    0: 
    47: // Test
    45: -1.0 -1.0 0.0 0.0 0.0
    ----------Test3----------FILE/char
    10: 
    
    78: NUMPOLLIES 2
    
    10: 
    
    47: // Test
    
    45: -1.0 -1.0 0.0 0.0 0.0
    

    Wieso ergibt denn bei ifstream ein Zeilenumbruch 0 und bei FILE 10? Steckt da ein höherer Sinn hinter?



  • Aus eigener Erfahrung kann das auch am Compiler liegen. Hab selber mal ne Datei im Textmodus geöffnet und mein Auslesealgorithmus funktionierte nur wenn ich z.B. kein fstream::tellg() benutzt habe. War sehr seltsam, aber war tatsächlich so. Ging btw im binarymodus!
    Für C++ statt printf cout benutzen.



  • kingcools schrieb:

    Aus eigener Erfahrung kann das auch am Compiler liegen. Hab selber mal ne Datei im Textmodus geöffnet und mein Auslesealgorithmus funktionierte nur wenn ich z.B. kein fstream::tellg() benutzt habe. War sehr seltsam, aber war tatsächlich so. Ging btw im binarymodus!
    Für C++ statt printf cout benutzen.

    Wollte mit dem printf nur das erste Zeichen einer Zeile als Int ausgeben. Wie ist denn da der richtige Befehl in C++? Ansonsten verwende ich ja cout. Oder wie meintest du das jetzt? 🙂 Und wie ist der richtige Befehl um aus einem String bestimmt Daten als z.B. Int oder Float auszulesen? Z.B. will ich aus der Textzeile "NUMPOLLIES 2\n" nur die 2 Auslesen und das in eine Int Variable speichern. Der Text ist dabei immer derselbe, nur die Zahl kann sich halt ändern.



  • Ok, ich schon wieder... 😉 Ich habe es jetzt soweit am laufen das er mir keine Kommentar und keine Leerzeilen ausgibt. Aber da ich es wohl häufiger in meinem Code brauchen werde das 1 Zeile ausgelesen werden soll ohne Kommentare und Leerzeilen wollte ich das ganze was ich zwischen die beiden Kommentare gesetzt habe in eine eigene Funktion packen. Leider komme ich da jetzt nicht weiter. Wie muss ich es denn der neuen Funktion, ich nenne sie mal "ReadLine()" die Infos übergeben um welchen fstream es sich denn handelt und in welchen String er das Ergebnis speichern soll?

    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main()
    {
    	ifstream file;
    	string content;
    	file.open("world.txt", ios::in);
    	while(!file.eof())
    	{
    		// Ab hier...
    		do
    		{
    			getline(file, content);
    		} while(!file.eof() && (content[0]=='/' || content[0]=='\n'));
    		// ...bis hier
    		cout<<content<<endl;
    	}
    	file.close();
    }
    

    Ich hab's probiert, bitte nicht lachen, mit:

    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    void ReadLine(ifstream *file, string *content)
    {
    	do
    	{
    		getline(file, content);
    	} while(!file.eof() && (content[0]=='/' || content[0]=='\n'));
    }
    
    int main()
    {
    	ifstream file;
    	string content;
    	file.open("world.txt", ios::in);
    	while(!file.eof())
    	{
    		ReadLine(file, content);
    		cout<<content<<endl;
    	}
    	file.close();
    }
    

    Aber da bekomme ich leider diese Fehler:
    line 10: error: no matching function for call to 'getline(std::ifstream*&, std::string*&)
    line 11: error: request for member 'eof' in 'file', which is of non-class type 'std::ifstream*
    line 11: error: no match for 'operator==' in '* content == '/'
    line 11: error: no match for 'operator==' in '* content == '\012'
    line 21: error: invalid conversion from 'void*' to 'std::ifstream*
    line 21: error: cannot convert 'std::string' to 'std::string*' for argument '2' to 'void ReadLine(std::ifstream*, std::string*)



  • void ReadLine(ifstream &file, string &content)
    {
        do
        {
            getline(file, content);
        } while(!file.eof() && (content[0]=='/' || content[0]=='\n'));
    }
    

    Dir ist aber klar, dass am Ende content nur die letzte Zeile enthält? Du willst wahrscheinlich/vielleicht einen std::vectorstd::string& übergeben.



  • Ne möchte nur eine Zeile haben. Danke für den Code. 🙂 Funktioniert auf anhieb. 😃

    Womit ich leider dann doch bei meinem nächsten Problem wäre. Ich würde gerne die Textzeile in "content" filtern. In der Richtung:

    sscanf(content, "NUMPOLLIES %d\n", &zahl);

    DIe Textzeile in "content" ist aktuell "NUMPOLLIES 2\n" und ich hätte halt gerne die 2 als Int in meiner Variable zahl.

    Aber sscanf funktioniert nur mit char und nicht mit string oder sehe ich das falsch? Gibt's eine Möglichkeit auch einen String in der Art zu durchsuchen und Werte in Variablen zu speichern?

    [EDIT]
    So, hab's mir jetzt so gebastellt, gibt's da keinen schöneren Weg in C++?

    sscanf(content.c_str(), "NUMPOLLIES %d\n", &zahl);


Anmelden zum Antworten