OpenGL using std::vector with glm::vec3

14,459

Solution 1

In your glBufferData() &vertices[0] should probably have been, &vertices[0].x.
That's because &vertices[0] points to a glm::vec3 but you want it to point to a float
because that's what OpenGL expects.

Solution 2

I don't think you are allowed to pass complex types to the shader. I have always created a struct with a float array for the positions:

struct vertex{
    GLfloat positions[3];
};

Then to use in your code:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertex) * vertices.size(),
             &vertices[0],  GL_DYNAMIC_DRAW);  

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

glBindVertexArray(buffer);  
Share:
14,459
a_learner
Author by

a_learner

Updated on June 07, 2022

Comments

  • a_learner
    a_learner almost 2 years

    I'm having the following issue.

    I've loaded 8 glm::vec3 into a std::vector, such that:

    std::vector <glm::vec3> vertices;
    

    returns:

    0.250000 -0.250000 -0.250000
    0.250000 -0.250000 0.250000
    -0.250000 -0.250000 0.250000
    -0.250000 -0.250000 -0.250000
    0.250000 0.250000 -0.250000
    0.250000 0.250000 0.250000
    -0.250000 0.250000 0.250000
    -0.250000 0.250000 -0.250000

    if:

    for(int i{0}; i<8; i++){
        std::cout<<"\n";
        for(int j{0}; j<3; j++){
        std::cout<<vertices[i][j]<<" ";
        }
    }
    

    When I pass the following code into OpenGL,

    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * vertices.size(), &vertices[0],  GL_DYNAMIC_DRAW);  
    
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
    
    glBindVertexArray(buffer);  
    

    my shader program loads and the window opens, however there is no cube.

    A slight alteration to the first line,

    glBufferData(GL_ARRAY_BUFFER, sizeof(vert), &vert, GL_DYNAMIC_DRAW); //Here
    
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    
    glBindVertexArray(buffer); 
    

    while taking vectors from,

    const GLfloat vert[9] =
    {-0.5,-0.5, 0.0,
      0.0, 0.5, 0.0,
      0.5,-0.5, 0.0};
    

    and a pretty red triangle is drawn onto the screen.

    My question: Is it possible to use a vector container in combination with glm? If so, how can it be implemented?
    My hypothesis:The glVertexAttribPointer function is reading sequentially from the starting address of the vertices container. The elements of the vertices container are fragmented throughout my memory.

  • a_learner
    a_learner over 9 years
    It does point to a glm::vec3. I tried your method and I've also tried &vertices[0][0]. Still, it does not render.
  • Axalo
    Axalo over 9 years
    @a_learner is it possible that vertices gets destructed after calling glBufferData?
  • a_learner
    a_learner over 9 years
    This is an interesting alternative, but surely OpenGL would allow you to send a glm::vec3 to the shader. First of all, they are essentially small arrays of floats, and secondly, GLM is the OpenGL math library, so why would they design it not to be compatible with their shaders?
  • a_learner
    a_learner over 9 years
    No, vertices is a public: vector container from an object that I'm calling from main(). I checked the vertices with a for loop from main, after calling glBufferDatafrom a function that is public under the same class as vertices.
  • Axalo
    Axalo over 9 years
    @a_learner what are the values of std::vector<float> vv(&vertices[0].x, &vertices[0].x + sizeof(vertex) * vertices.size());?
  • a_learner
    a_learner over 9 years
    I see what you did there. std::vector<GLfloat> vv(&vertices[0].x, &vertices[0].x + sizeof(glm::vec3) * vertices.size()); gave me an exact copy of vertices. I then made a copy std::vector <GLfloat> v under the public of that class so it wouldn't be destroyed once I left the function call. I glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertices.size(), &v, GL_DYNAMIC_DRAW); AND BAM IT DREW SOMETHING! It's not exactly a cube, but damn it's something!
  • a_learner
    a_learner over 9 years
    Cube accomplished. This was my first time loading vertex data from a .obj file. I know your code worked, I'm going to study the details tomorrow, but likely I'm going change my approach since copying the container is going to kill performance. I may just throw it all into a std::vector <GLfloat> and forget 'std::vector <glm::vec3>` altogether. I might also forget about std::vector and store it some other way. I've heard of performance issues with std::vector for things greater than a cube.
  • Axalo
    Axalo over 9 years
    @a_learner yes, using an array of floats is usually the way it's done. std::vectors are fine though.
  • eklukovich
    eklukovich over 9 years
    This method allows for all the data for each vertex to be packaged nicely, ie. texture coordinates and normal vectors.
  • a_learner
    a_learner over 9 years
    Yes, I know your way is one of the more popular methods.
  • Mars
    Mars over 8 years
    You are allowed to pass complex types, as long as they are designed to do so. And GLM library was designed just to support this type of usage. So there is really no point in re-inventing the wheel with own classes for vectors and matrices. And GLM is NOT part of OpenGL nor it comes from any corner of Khronos group. It is external tool based on the GLSL specs. There could be bugs or some undefined behaviour, but it's here for years and proved to be really stable and reliable.