-1

I have been trying to write a very simple .obj model loader in c++ but in both of my methods the model doesn't get displayed correctly and I would also like to know which of the 2 methods is faster/better and why. this is my first method:

    //vertices&indices are private members of the class "Model"
    //same with size and indexCount

void Model::loadModel(std::string source)
{
    using namespace std;

    string name = source.substr(0,source.find('.'));
    cout<<"===LOADING: "<<name<<"==="<<endl;

    ifstream file;
    file.open(source);
    string line,v0="",v1="",v2="";
    string v3="",v4="",v5="";
    int indexCount = 0;
    while(file.good())
    {
        getline(file,line);
        if(line[0] =='v') size++;
        if(line[0] =='f') indexCount++;
    }
    file.close();
    size *= 3;
    vertices = new float[size];
    indexSize = indexCount*3;
    indices = new short[indexSize];
    int count = 0;
    int indexCountForFilling =0;
    file.open(source);
    while(file.good())
    {
        getline(file,line);
        if(line[0] == 'v')
        {
            line = line.substr(2,line.length());
            int oldindex =0;

            v0 = line.substr(0,line.find(" "));
            v1 = line.substr(line.find(" "),line.rfind(" ",line.find(" ")));
            v2 = line.substr(line.rfind(" ",line.find(" ")),line.length());
            v2 = v2.substr(line.find(" ")+2,v2.length());

            //1
            float temp = atof(v0.c_str());
            vertices[count] = temp;
            count++;
            //2
            temp = atof(v1.c_str());
            vertices[count] = temp;
            count++;
            //3
            temp = atof(v2.c_str());
            vertices[count] = temp;
            count++;
        }
        else if(line[0] == 'f')
        {
            line = line.substr(2,line.length());

            int firstIndex = line.find(" ");
            v3 = line.substr(0,firstIndex);
            line = line.substr(firstIndex+1,line.length()); //+1 to skip space

            int secondIndex = line.find(" "); 
            v4 = line.substr(0,secondIndex);
            line = line.substr(secondIndex,line.length());

            if(secondIndex+1>=line.length())
                v5 = line.substr(0,line.length()); 
            else
                v5 = line.substr(1,line.length()); //zelfde
            //1
            short temp = atof(v3.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
            //2
            temp = atof(v4.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
            //3
            temp = atof(v5.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
        }
    }
    cout<<"Amount of vertices: "<<size<<endl;
    cout<<"Amount of indexes: "<<indexCountForFilling<<endl;
    cout<<"===ENDED LOADING: "<<name<<"==="<<endl;
    file.close();
}

This is the second method using stringstreams:

void Model::loadModel2(std::string source)
{
    using namespace std;
    string name = source.substr(0,source.find("."));
    cout<<"+++LOADING::"<<name<<"+++"<<endl;

    ifstream file;
    file.open(source);
    string line;
    while(file.good())
    {
        getline(file,line);
        if(line[0]=='v') size++;
        if(line[0]=='f') indexSize++;
    }
    size *= 3;
    vertices = new GLfloat[size];
    indexSize *= 3;
    indices = new GLshort[indexSize];
    cout<<"\tSize: "<<size<<endl;
    cout<<"\tIndexSize:"<<indexSize<<endl;
    file.close();
    file.open(source);
    int count = 0;
    int index = 0;
    while(file.good())
    {
        getline(file,line);
        istringstream in(line);
        string type;
        in>>type;
        if(type=="v")
        { 
            float x,y,z;
            in >> x >> y >> z;
            vertices[count++] = x;
            vertices[count++] = y;
            vertices[count++] = z;
        }
        else if(type == "f")
        {
            float x,y,z;
            in >> x >> y >> z;
            indices[index++] = x;
            indices[index++] = y;
            indices[index++] = z;
        }
    }
    file.close();

    cout<<"+++ENDED LOADING:"<<name<<"+++"<<endl;
}

This is the code where both are initialized:

glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);
    GLfloat model_test[834]; //834
    memset(model_test,0.0f,sizeof(model_test));
    for(unsigned int i=0;i<834;i++) model_test[i] = model.getIndex(i);
    glBufferData(GL_ARRAY_BUFFER,sizeof(model_test),&model_test,GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));
    glEnableVertexAttribArray(0);

    GLuint ibo;
    glGenBuffers(1,&ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
    GLshort indices[1656];//1656
    memset(indices,0,sizeof(indices));
    for(int i=0;i<1656;i++) indices[i] = model.getVertexIndex(i);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),&indices,GL_STATIC_DRAW);

And finally this is the code where it is being rendered:

glBindVertexArray(vao);
    if(rasterize)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    else glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    glDrawElements(GL_TRIANGLES,model.getIndexSize(),GL_UNSIGNED_SHORT,0);

This is the result i should get:

https://i.stack.imgur.com/XhB3Y.jpg

This is the result i get:

https://i.stack.imgur.com/L62el.jpg

As you can see it loads almost perfectly until the last few triangles

So in conclusion my 2 questions are:

- Which of the 2 methods is the best way to load from a txt file?

- Am I doing something wrong with the rendering?

EDIT: My guess is that i'm use the wrong indices, however i've loaded a more simple file with fewer vertices/indices and compared the output of each number and it seems i've correctly copied the data into my application. So my guess is that i did something wrong in my initialization code for openGL, could anyone find the error? Everything compiles fine...

Anton D
  • 1,336
  • 1
  • 12
  • 18

1 Answers1

1

Don't do e.g.

while (file.good()) { ... }

or similar, it will not do what you think it does.

Instead do

while (std::getline(...)) { ... }

It's because the flags (eof/bad/etc.) will not be set until after the input operation fails. This means that you will loop because everything will look good, but then std::getline fails because it's at the end of the file but you still try to parse data that wasn't read.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I changed it but it didn't seem to change anything. – Anton D Aug 08 '13 at 15:31
  • @AntonD Try to load a much simpler model, and then step through the loading code line-by-line in a debugger. Then you can check that the loading code works as it should or not. If it does, then it's something else that's the problem. – Some programmer dude Aug 08 '13 at 15:34
  • That was one of the first things i tried, I've printed out each float and compared each one of them to my file. They all matched exactly(both the indices and the vertices). Do you think something is wrong with my openGL code? – Anton D Aug 08 '13 at 15:40
  • @AntonD I'm not good at OpenGL, so I'm sorry to say I can't help you more. – Some programmer dude Aug 08 '13 at 15:43
  • 1
    @AntonD Where you change it? Are you sure, what you don't forget change in first loop, when you counting indexCount? Your bug looks like your last line in file begins with 'f', and on last iteration (when you reached EOF) you increase indexCount. Then, when you try to output your model, you try render one more index with garbage. – user1837009 Aug 08 '13 at 16:09
  • @user1837009 I changed it so that after the loop it subtracts 1 from indexCount but the supplementary triangles stay there. – Anton D Aug 08 '13 at 16:38