Rakentelen tässä lataajaa .obj tiedostoille, ja on vähän vaikeuksia saada tuolta tiedot ulos. Tässä koodi tähän mennessä:
int S3D_LoadTerrain(std::string filename) { std::ifstream file(filename.c_str()); char apu[80]; if (file.is_open()) { while (file.peek() != EOF) { file.getline(apu, 80); switch (apu[0]) { case 'v': break; case 'f': break; } } return 0; } else return -1; }
Tuonne case lausekkeiden kohdalle tökkää. Se rivihän on v:n tapauksessa "v -1.000000 -1.000000 -1.000000" tms, ja f:n tapauksessa esim. "f 11 1 26". Sieltä pitäisi saada nuo luvut ulos omiin merkkijonoihin, joista ne voisi sitten muuttaa numeroiksi.
Kelpaisivatko string-getline ja istringstream?
std::string str; std::getline(file,str); std::istringstream iss(str); char c; iss >> c; // ... double v1, v2, v3; iss >> v1 >> v2 >> v3;
Edit: ja voithan varmaan lukea noita myös suoraan tiedostosta, file >> c >> v1 >> v2 ...
, jos noilla riveillä ei ole mitään erityistä virkaa.
Koodista on muotoutunut nyt tällainen:
int S3D_LoadTerrain(std::string filename) { std::ifstream file(filename.c_str()); std::ofstream debug("debug.txt"); char chr; vertex sVertex; triangle sTriangle; if (file.is_open()) { while (file.peek() != EOF) { file.get(chr); switch (chr) { case 'v': file >> sVertex.x >> sVertex.y >> sVertex.z; file.ignore(1); VertexStack.push_back(sVertex); // Print Debug Information debug << 'v' << ' ' << sVertex.x << ' ' << sVertex.y << ' ' << sVertex.z << '\n'; break; case 'f': file >> sTriangle.c1 >> sTriangle.c2 >> sTriangle.c3; file.ignore(1); sTriangle.c1--; sTriangle.c2--; sTriangle.c3--; TriangleStack.push_back(sTriangle); triangleCount++; // Print Debug Information debug << triangleCount << ' ' << sTriangle.c1 << ' ' << sTriangle.c2 << ' ' << sTriangle.c3 << '\n'; break; default: file.ignore('\n'); break; } } file.close(); debug.close(); return 0; } else return -1; }
Jos joku nyt tuota hirviötä edes viitsii katsoa, niin ongelma on että pääosin näyttäisi debug tiedostoon tulevan oikeat luvut, paitsi että muutamat ovat korvautuneet esim. mystisellä "1e-006" merkinnällä ja välistä puuttuu sieltä täältä muutamia rivejä. Aluksi sinne tuli vain n. joka viides rivi, mutta se korjautui kun lisäsin file.ignore(1):n sekä v että f caseen (eliminoi ilmeisesti sen "\n":n sieltä lopusta).
Yksi mahdollinen tapa (ei tosin paras):
std::vector<std::string> GetWords(std::string str, const std::string& separators) { std::vector<std::string> dest; while(1) { size_t pos = str.find_first_of( separators ); if( pos != std::string::npos ) { if( pos > 0 ) dest.push_back( str.substr(0,pos) ); str = str.substr( pos+1 ); } else { if( str.length() ) dest.push_back( str ); return dest; } } return dest; } int S3D_LoadTerrain(const std::string& filename) { std::fstream file(filename.c_str(), std::fstream::in); if (file.is_open()) { while( !file.eof() ) { // haetaan sanat std::string line; std::vector<std::string> elems; getline( file, line ); elems.swap( GetWords( line, " " ) ); switch( elems[0][0] ) { case 'v': VertexStack.push_back( vertex( atof(elems[1].c_str()), atof(elems[2].c_str()), atof(elems[3].c_str()) ) ); break; case 'f': // trianggeleille sama juttu break; } } file.close(); return 0; } else return -1; }
Sain tuon oman toimimaan. Tai oikeastaan en tehnyt koodille mitään, huomasin vain että kommenttirivit ynnä muut tuossa .obj-tiedostossa aiheuttivat ongelmat, vaikka luulin että tuo:
default: file.ignore('\n'); break;
Ohittaisi kaikki muut paitsi tunnetut rivit.
Kuinkas sitten ajattelit ladata normaalit ja tekstuurit :)
Ne kun on muotoa:
f int/int/int int/int/int int/int/int ...
eli
vertexIndex/textureIndex/normalIndex ja sama toistuu niin usein kuin face:lla on verteksejä, ei välttämättä edes kolmio.
User137: Luetaan arvo, skipataan kauttaviiva tai kaksi, luetaan seuraava arvo jne.
Sain ratkaistua tuon aiemman ongelman kokonaan.
default: break;
:) Eli nyt se ohittaa turhat rivit olankohautuksella.
EDIT:
Syön sanani, tässä viimein se toimiva versio:
default: ignore(512, '\n'); break;
Aihe on jo aika vanha, joten et voi enää vastata siihen.