2

I am using vertex buffers and element buffers.

The following function takes vertex and element data as arrays and creates buffers out of that. My real implementation is more complicated and stores the ids for later use of course, but that does not relate to this question.

void Create(const float Vertices[], const int Elements[])
{
    GLuint VertexBuffer, ElementBuffer; // ids

    glGenBuffers(1, VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, ElementBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Elements), Elements, GL_STATIC_DRAW);
}

In another function I call Create() passing two arrays which represents a cube. But nothing happens. The window opens up and I see the cornflower blue background without any cube.

float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

Create(VERTICES, ELEMENTS);

If I move the vertex and element data inside the Create() function, everything works fine and the cube is rendered correctly.

void Create()
{
    GLuint VertexBuffer, ElementBuffer;

    float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
    int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

    glGenBuffers(1, VertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW);

    glGenBuffers(1, ElementBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ElementBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ELEMENTS), ELEMENTS, GL_STATIC_DRAW);
}

Therefore I assume that the problem occurs when passing the array to the Create() function. I do not get any compiler error or warning. What is wrong here?

2
  • 2
    You are actually passing the arrays as arguments to Create(), right? Your example usage shows it with empty parentheses... Commented Dec 19, 2012 at 10:15
  • Typical copy and paste fault. Commented Dec 19, 2012 at 10:18

2 Answers 2

4

A parameter of type const float Vertices[] is actually the same as const float Vertices*. So sizeof is just returning the size of a pointer.

Use a reference to array using templates instead:

template<std::size_t VerticesN, std::size_t ElementsN>
void Create(const float (&Vertices)[VerticesN], const int (&Elements)[ElementsN])
{
// ...
}

// Usage is the same since template argument deduction

float VERTICES[] = {-1.f,-1.f,1.f,1.f,0.f,0.f,.8f,1.f,-1.f,1.f,0.f,1.f,0.f,.8f,1.f,1.f,1.f,0.f,0.f,1.f,.8f,-1.f,1.f,1.f,1.f,1.f,1.f,.8f,-1.f,-1.f,-1.f,0.f,0.f,1.f,.8f,1.f,-1.f,-1.f,1.f,1.f,1.f,.8f,1.f,1.f,-1.f,1.f,0.f,0.f,.8f,-1.f,1.f,-1.f,0.f,1.f,0.f,.8f};
int   ELEMENTS[] = {0,1,2,2,3,0,1,5,6,6,2,1,7,6,5,5,4,7,4,0,3,3,7,4,4,5,1,1,0,4,3,2,6,6,7,3};

Create(VERTICES, ELEMENTS);
Sign up to request clarification or add additional context in comments.

1 Comment

Could you please extend your example to cover how to call the function?
3

The problem here is sizeof(VERTICES) and sizeof(ELEMENTS). When used in the Create() method the sizes of the arrays are known, but when you pass the arrays as a parameter (like in the Create(const float Vertices[], const int Elements[]) the array degrades to a pointer, and the sizeof is reduced to returning the size of the pointer.

One simple solution is to pass the size along with the arrays. So the function will look like this:

void Create(const float Vertices[], size_t VertSize, const int Elements[], size_t ElemSize) {
  ...
}

but I think I would prefer a solution that uses the new std::array which has a size() function:

void Create(const std::array<float>& vertices, std::array<int>& elements) {
  ...
}

If you do not have the opportunity to work with c++ 11, the boost libraries will provide the boost::array which mirrors the behaviour of c++ 11.

5 Comments

I use C++11 but for performance reasons I will use @Pubby's solution.
@sharethis: this std::array version will be as fast as the raw array version.
Even if some minuscule gain were to be had by the templated version. There are the important question of readability and the problem of keeping the whole code visible for the caller. This might not affect performance, keeps the price of maintenance lower. (compile time, developer time). But this is a matter of requirements and preference. Both solution are quite suited for the problem.
@daramarak. I reconsidered to use std::array but how can I avoid specifying the array size (it is the second template parameter) at compile time?
@sharethis you cannot, that is the point of array. Array are speedy static storage, its size is not dynamic. If you need a dynamic storage use a vector.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.