Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Vaikeaa merkkijonojen käsittelyä (.obj loader)

Tumpelo [27.04.2008 15:23:45]

#

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.

os [27.04.2008 16:28:59]

#

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.

Tumpelo [27.04.2008 18:23:21]

#

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).

Mazzimo [27.04.2008 19:45:00]

#

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;
}

Tumpelo [27.04.2008 21:30:24]

#

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.

User137 [28.04.2008 11:27:27]

#

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.

http://www.eg-models.de/formats/Format_Obj.html

Tumpelo [30.04.2008 19:26:30]

#

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;

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta