PDA

View Full Version : Cant figure out what im doing wrong with indexes



lummxx
09-21-2014, 03:21 AM
Hello,

I am having hard time figuring out what I am doing wrong when I draw. I think the problem is when I pass the attributes and indexes.

I am importing an obj file with more than 1 object and I just get weird shapes of missing faces. To load objects I am using tinyobjloader https://github.com/syoyo/tinyobjloadertinyobjloader
To me it seems that I am missing something a small thing the last 2 days. Being new to OpenGl and C++ it not as easy as it looks but I am having fun.:biggrin-new:


After i fix this i am planning to read about map and client states then see if i can include them here.

BTW I am not trying to make efficient code here, just trying to make things work then see how can I improve efficiency.

Thank you for help.

the code that i wrote to copy data to GPU


void initData(){
GLenum errorCode = 0;

// Copy data to GPU
// Vertex
size_t vertex_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {
vertex_buffer_size += sizeof(float)* shapes[i].mesh.positions.size();
}

glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, NULL, GL_STATIC_DRAW);
vertex_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {
glBufferSubData(GL_ARRAY_BUFFER, vertex_buffer_size, sizeof(float)* shapes[i].mesh.positions.size(), &shapes[i].mesh.positions[0]);
vertex_buffer_size += sizeof(float)* shapes[i].mesh.positions.size();
}
glBindBuffer(GL_ARRAY_BUFFER, 0);

// Index
size_t index_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {
index_buffer_size += sizeof(unsigned int)* shapes[i].mesh.indices.size();
}

glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, NULL, GL_STATIC_DRAW);
index_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, sizeof(unsigned int)* shapes[i].mesh.indices.size(), &shapes[i].mesh.indices[0]);
index_buffer_size += sizeof(unsigned int)* shapes[i].mesh.indices.size();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

// draw multiple objects with one draw call
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
//glBindBuffer(GL_ARRAY_BUFFER, 0);
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);

uniform_mvp = glGetUniformLocation(shader_program, "MVP");

errorCode = glGetError();
if (errorCode != 0)
{
fprintf(stderr, "Error data: %s, code %d\n", glewGetErrorString(errorCode), errorCode);
}
}


the draw call code

void display(){

GLenum errorCode = 0;
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Use our shader
glUseProgram(shader_program);

// Send our transformation to the currently bound shader, in the "MVP" uniform
glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(cam.calculateMVP()));

glBindVertexArray(vertex_array_object);
glEnableVertexAttribArray(0);

size_t vertex_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)vertex_buffer_size);
glDrawElements(GL_TRIANGLES, sizeof(int)*shapes[i].mesh.indices.size(), GL_UNSIGNED_INT, (void*)0);

vertex_buffer_size += sizeof(float)* shapes[i].mesh.positions.size();
if (errorCode != 0)
{
fprintf(stderr, "Error rendering shape[%d].name = %s. Error name: %s. Error code code %d\n", i, shapes[i].name.c_str(), glewGetErrorString(errorCode), errorCode);
}
}

glDisableVertexAttribArray(0);
glBindVertexArray(0);

glUseProgram(0);

// Swap buffers
SDL_GL_SwapWindow(window);
}

carsten neumann
09-21-2014, 04:13 AM
Since your indices for the multiple objects are stored in one buffer object you also need an offset as the last argument to glDrawElements. The way you have it set up now means you are using the first shape's indices together with the n'th shape's positions.

lummxx
09-21-2014, 05:39 AM
Since your indices for the multiple objects are stored in one buffer object you also need an offset as the last argument to glDrawElements. The way you have it set up now means you are using the first shape's indices together with the n'th shape's positions.
Yes now i see what i did wrong but still i get weird shapes.

I changed the code to the following


size_t vertex_buffer_size = 0;
size_t index_buffer_size = 0;
for (size_t i = 0; i < shapes.size(); i++) {

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)vertex_buffer_size);
glDrawElements(GL_TRIANGLES, sizeof(unsigned int)*shapes[i].mesh.indices.size(), GL_UNSIGNED_INT, (void*)index_buffer_size);

vertex_buffer_size += sizeof(float)* shapes[i].mesh.positions.size();
index_buffer_size += sizeof(unsigned int)*shapes[i].mesh.indices.size();

I still get some weird connected vertexes. I dont have any lights or color to see the vertexes till i fix this issue.

Thanks for hellp

carsten neumann
09-21-2014, 06:26 AM
Missed that before, it should be:



glDrawElements(GL_TRIANGLES, shapes[i].mesh.indices.size(), GL_UNSIGNED_INT, (void*)index_buffer_size);


That is, the second argument to glDrawElements is the number of indices to use, not the number of bytes those indices take.

lummxx
09-21-2014, 06:46 AM
Ok thanks . it is solved now.

It is funny how frustrating can be when you miss something like this and you spend hours trying to figure out what to do.

Is there anything that i can change to make this template better. If you have any suggestion please let me know. it will make me work and learn a bit more.