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.