1

I'm new to OpenGL and I'm trying to load obj files into my code. I have a code of a simple animating cube. When I declare the vertices and indices as follows it works properly:

GLfloat cube_vertices[] = {
// front
    -1.0, -1.0, 1.0,
    1.0, -1.0, 1.0,
    1.0, 1.0, 1.0,
    -1.0, 1.0, 1.0,
    // back
    -1.0, -1.0, -1.0,
    1.0, -1.0, -1.0,
    1.0, 1.0, -1.0,
    -1.0, 1.0, -1.0,
};
GLushort cube_elements[] = {
    // front
    0, 1, 2,
    2, 3, 0,
    // top
    1, 5, 6,
    6, 2, 1,
    // back
    7, 6, 5,
    5, 4, 7,
    // bottom
    4, 0, 3,
    3, 7, 4,
    // left
    4, 5, 1,
    1, 0, 4,
    // right
    3, 2, 6,
    6, 7, 3,
};

However, when I'm trying to get similar number from a file, the program runs without error but shows nothing in the window. Here is my code for loading the obj file:

vector<GLfloat> vertices;
vector<GLushort> elements;

ifstream in("cube.obj", ios::in);
if (!in)
{
    cerr << "Cannot open " << "sample.obj" << endl; exit(1);
}

string line;
while (getline(in, line))
{
    if (line.substr(0, 2) == "v ")
    {
        istringstream s(line.substr(2));
        GLfloat v;
        s >> v; vertices.push_back(v);
        s >> v; vertices.push_back(v);
        s >> v; vertices.push_back(v);

    }
    else if (line.substr(0, 2) == "f ")
    {
        istringstream s(line.substr(2));
        GLushort a, b, c;
        s >> a; s >> b; s >> c;
        elements.push_back(a); elements.push_back(b); elements.push_back(c);
    }
}

The cube.obj file is saved as follows:

o cube
v -1.0 -1.0 1.0
v 1.0 -1.0 1.0
v 1.0 1.0 1.0
v -1.0 1.0 1.0
v -1.0 -1.0 -1.0
v 1.0 -1.0 -1.0
v 1.0 1.0 -1.0
v -1.0 1.0 -1.0
f 0 1 2
f 2 3 0
f 1 5 6
f 6 2 1
f 7 6 5
f 5 4 7
f 4 0 3
f 3 7 4
f 4 5 1
f 1 0 4
f 3 2 6
f 6 7 3

I'm just getting a blank window in the output. Do you have any idea why the loader doesn't work?

I upload the data thus

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), &elements, GL_STATIC_DRAW);

When I don't put the & operator before vertices and elements it gives compilation error of "no suitable conversion".

legends2k
  • 31,634
  • 25
  • 118
  • 222
mfaieghi
  • 570
  • 2
  • 9
  • 24
  • The loading code seems fine. How do you upload the data from the vector into the video memory? – legends2k Jan 08 '16 at 05:24
  • glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); and glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), &elements, GL_STATIC_DRAW); When I don't put the & operator before "vertices" and "elements" it gives compilation error of "no suitable conversion" – mfaieghi Jan 08 '16 at 05:29

2 Answers2

2
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);

glBufferData expects the raw data and not the vector directly, also the size of this data should be given correctly. What you are doing here is passing the size of the vector itself and not the data it contains.

A vector is a data structure, a container, with metadata like a pointer to the data it's going to hold and a variable to hold the count of element it holds. When you do sizeof(vector) it would always return a constant number, irrespective of the number of elements it houses; this size is the sizeof(pointer-to-data) + sizeof(variable-holding-count). This data is not what you want.

Also, when you pass &vertices, you are passing the address of the vector itself and not the address of the data it contains. vector::data() gives the address of the data contained inside it.

Instead do this:

glBufferData(GL_ARRAY_BUFFER,
             vertices.size() * sizeof(GLfloat),
             vertices.data(),
             GL_STATIC_DRAW);

should do it. The same goes for element array buffer too.

glBufferData(GL_ELEMENT_ARRAY_BUFFER,
             elements.size() * sizeof(GLushort),
             elements.data(),
             GL_STATIC_DRAW);

vector::size() gives the count of the elements it contains, that times the size of one element gives the right size of the data contained.

Aside

line.substr(0, 2) == "v "
line.substr(0, 2) == "f "

This would create two substrings unnecessarily, instead you could do this to check the same thing

line[0] == 'v'
line[0] == 'f'
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Worked perfectly. Thanks a million! I am not clear with "raw data" that you have mentioned. So, considering a vector and an array from the same type with equal entities, vector[i] == array[i] will be FALSE? – mfaieghi Jan 08 '16 at 05:37
  • By _raw data_, I meant just the data of the model and not more or less. A vector usually, internally just has a pointer and a size variable. It's this pointer that points to the data that you insert into it via `push_back`. `v[i] == a[i]` is true, but that doesn't mean arrays and vectors are the same. – legends2k Jan 08 '16 at 05:40
  • Got it!! Thanks again! – mfaieghi Jan 08 '16 at 05:42
  • A minor optimisation is possible in the code, I've put it under the Aside heading. I've added links to the functions used; I'd suggest you to look at them and get into the habit of reading documentation so that you've more clarity when you code things up. Good luck! – legends2k Jan 08 '16 at 05:54
1

The code you've posted loads in the vertices and faces just fine, so you will need to post your rendering code in order to get a specific answer.

From what you have posted though, I have a few suggestions:

  • You've used cube_vertices and cube_elements when specifying the cube, but different variables when loading from a file. Are you trying to render from the empty arrays in your program?
Maglos
  • 88
  • 8
  • On the contrary, the destructor of `ifstream` would automatically call `close`, so [it's recommended](http://en.cppreference.com/w/cpp/io/basic_ifstream/close) that it's not called explicitly. – legends2k Jan 08 '16 at 05:31
  • I was not aware, thanks for the tip. Edited to reflect this. – Maglos Jan 08 '16 at 05:32