Cant figure out what im doing wrong with indexes

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
", 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
", i, shapes[i].name.c_str(), glewGetErrorString(errorCode), errorCode);
		}
	}

	glDisableVertexAttribArray(0);
	glBindVertexArray(0);

	glUseProgram(0);

	// Swap buffers
	SDL_GL_SwapWindow(window);
}

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

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.

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.