0

I'm trying to create and element array buffer to draw two different shapes with a different number of vertices. I haven't been able to find any resources on this as they mostly show how to draw a single triangle or square separately.

Let's say i want to draw both at the same time, the square would have 6 indices while the triangle(just an example) would have 3 indices. But I'm not sure how to go about this. I've tried having two element array buffers or just reassigning it.

float vertice[] =
{
    -0.5f, -0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
     0.5f,  0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
     0.5f, -0.5f, 0.0f,     0.5f, 0.3f, 0.0f,
    -0.5f,  0.5f, 0.0f,     0.5f, 0.3f, 0.0f
}; 

float vertices2[] =
{
    -0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f,
     0.0f,  0.0f, 0.0f,     0.0f, 1.0f, 0.0f,
     0.5f, -0.5f, 0.0f,     0.0f, 1.0f, 0.0f
};

int indice[] =
{
    0, 1, 2,
    0, 1, 3
};

int indice2[] =
{
    0, 1, 3
};
VertexArray vao;
vao.Bind();

VertexBuffer vbo(vertice, sizeof(vertice), GL_STATIC_DRAW);
vbo.Bind();

IndexBuffer ibo(indice, sizeof(indice), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

vao.Unbind();
vbo.Unbind();

VertexArray vao2;
vao2.Bind();

VertexBuffer vbo2(vertices2, sizeof(vertices2), GL_STATIC_DRAW);
vbo2.Bind();

IndexBuffer ibo2(indice2, sizeof(indice2), GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

vao2.Unbind();
vbo2.Unbind();
vao.Bind();
ibo.Bind(); 
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
ibo.Unbind();
vao.Unbind();

vao2.Bind();
ibo2.Bind();
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
ibo2.Unbind();
vao2.Unbind();

If anyone has any resources or something where i can work out how to do this properly, that be very much appreciated.

  • Maybe this example code can help: https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/2.4.hello_triangle_exercise2/hello_triangle_exercise2.cpp It draws 2 triangles. – kiner_shah Mar 23 '23 at 08:27
  • When you call glDrawElements OpenGL looks at the current GL_ELEMENT_BUFFER for indices and it looks at the places last set with glVertexPointer for vertices. It seems to me that you are not changing the vertex places in between the glDrawElements calls so it is getting the vertices from the same place (the last one you set) – user253751 Mar 23 '23 at 08:28
  • @user253751, he seems to be binding to a different VAO before second glDrawElements. – kiner_shah Mar 23 '23 at 08:48
  • 1
    Hi, thanks for the responses. But i just realised that in the second element array object I'm trying the get the 4th vertices of the triangle – GlitchInTheAi Mar 23 '23 at 08:51
  • 1
    @kiner_shah oh I misread it as vbo – user253751 Mar 23 '23 at 08:52
  • @GlitchInTheAi, lol somehow I saw it multiple times and couldn't identify the mistake. – kiner_shah Mar 23 '23 at 08:54

1 Answers1

0

The obvious solution is to merge all your arrays together. Summarized:

float vertice[] = {
  // the 4 vertices from vertice
  // the 3 vertices from vertice2
};

int indice[] = {
  // the 6 indices from indice
  0, 1, 2,
  0, 1, 3
  // the 3 indices from indice2, all + 4 to account for the earlier ones.
  4, 5, 6
}

But often it is impractical to do this at compile time. So let's do it at runtime!

struct Merger {
  std::vector<float> vertices;
  std::vector<int> indices;

  void addFromArrays(const float * vs, size_t numvs, const int * is, size_t numis) {
    size_t offsetvs = vertices.size();
    vertices.resize(offsetvs + numvs);
    std::copy(vs, vs + numvs, std::begin(vertices) + offsetvs);

    size_t offsetis = indices.size();
    indices.resize(offsetis + numis);
    std::transform(is, is + numis, std::begin(indices) + offsetis,
       [=](int i) { return i + offsetvs; });
  }
}

Using it is simple:

Merger m;
m.addFromArrays(vertice, 24, indice, 6);
m.addFromArrays(vertice2, 18, indice2, 3);
// now use m.vertices.data() and m.indices.data() as inputs to glBufferData

Of course all these explicit item counts get in the way, but we can add a templated method to Merger to calculate it for you:

  template <size_t Vs, size_t Is>
  void addFromArrays(const float (&vs)[Vs], const int (&is)[Is]) {
    addFromArrays(vs, Vs, is, Is);
  }
Botje
  • 26,269
  • 3
  • 31
  • 41