Help! Can't get a cube to draw from OBJ-file. (c++/OpenGL)

Started by
2 comments, last by Aeshma 3 years, 11 months ago

So I decided I should give parsing and loading a simple cube from a OBJ-file a try. The parsing itself seem to work well enough, and right now I only try to make the position element of the vertices work. But I can't seem to get the cube to be drawn like it should, it even looks like it doesn't use all the indices. After staring at this problem for too long and not seeing what's wrong, maybe someone here can help. Anyway, thanks in advance.

	Mesh* OBJFileParser::LoadMeshFromOBJFile(const char* filename)
	{
		std::ifstream in(filename, std::ios::in);
		if (!in)
		{
			std::cout << "Could not open " << filename << std::endl;
			exit(1);
		}

		Mesh* mesh = new Mesh;

		std::string line;
		while (std::getline(in, line))
		{
			if (line.substr(0, 2) == "v ")
			{
				std::istringstream v(line.substr(2));
				glm::vec3 vert;
				double x, y, z;

				v >> x; v >> y; v >> z;

				vert = glm::vec3((float)x,(float)y,(float)z);
				mesh->Data.vertpos.push_back(vert);
			}
			else if (line.substr(0, 2) == "vt")
			{
				std::istringstream vt(line.substr(3));
				glm::vec2 tex;
				double U, V;

				vt >> U; vt >> V;
				
				tex = glm::vec2(U, V);

				mesh->Data.texUV.push_back(tex);
			}
			else if (line.substr(0, 2) == "vn")
			{
				std::istringstream vn(line.substr(3));
				glm::vec3 norm;
				double x, y, z;

				vn >> x; vn >> y; vn >> z;
				norm = glm::vec3(x, y, z);
				mesh->Data.normal.push_back(norm);
			}
			else if (line.substr(0, 2) == "f ")
			{
				GLuint MIa, MIb, MIc; // Mesh index
				GLuint TIa, TIb, TIc; // Texture index
				GLuint NIa, NIb, NIc; // Normal index

				const char* cline = line.c_str();
				sscanf_s(cline, "f %i/%i/%i %i/%i/%i %i/%i/%i", &MIa, &TIa, &NIa, &MIb, &TIb, &NIb, &MIc, &TIc, &NIc);

				MIa--; MIb--; MIc--; 
				TIa--; TIb--; TIc--; 
				NIa--; NIb--; NIc--; 

				mesh->Data.faceIndex.push_back(MIa); mesh->Data.textureIndex.push_back(TIa); mesh->Data.normalIndex.push_back(NIa);
				mesh->Data.faceIndex.push_back(MIb); mesh->Data.textureIndex.push_back(TIb); mesh->Data.normalIndex.push_back(NIb);
				mesh->Data.faceIndex.push_back(MIc); mesh->Data.textureIndex.push_back(TIc); mesh->Data.normalIndex.push_back(NIc);
			}
		}

		for (unsigned int i = 0; i < mesh->Data.faceIndex.size(); i++)
		{
			glm::vec3 meshData;
			glm::vec3 normData;
			glm::vec2 texData;
			meshData = glm::vec3(mesh->Data.vertpos[mesh->Data.faceIndex[i]].x, mesh->Data.vertpos[mesh->Data.faceIndex[i]].y, mesh->Data.vertpos[mesh->Data.faceIndex[i]].z);
			texData = glm::vec2(mesh->Data.texUV[mesh->Data.textureIndex[i]].x, mesh->Data.texUV[mesh->Data.textureIndex[i]].y);
			normData = glm::vec3(mesh->Data.normal[mesh->Data.normalIndex[i]].x, mesh->Data.normal[mesh->Data.normalIndex[i]].y, mesh->Data.normal[mesh->Data.normalIndex[i]].z);
			
			Vertex vertex;
			vertex.Position = meshData;
			//std::cout << "[" << mesh->Data.faceIndex[i] << "] X: " << vertex.Position.x << " Y: " << vertex.Position.y << " Z: " << vertex.Position.z << std::endl;
		    vertex.TexUV = texData;
			vertex.Normal = normData;
			vertex.Color = glm::vec4(0.4f, 1.0f, 0.4f, 1.0f);
			vertex.TexIndex = 1.0f;

			mesh->Data.vertices.push_back(vertex);
			
		}

		return mesh;
	}

	Mesh::Mesh()
	{

	}

	TestLoadMesh::TestLoadMesh() : m_Mesh(nullptr)
	{
		m_FilePath = "res/models/";
		m_FileName = "testbox01";
		m_FileType = ".obj";
		m_Mesh = OBJFileParser::LoadMeshFromOBJFile((m_FilePath + m_FileName + m_FileType).c_str());
		m_Shader = new Shader("res/shaders/Basicv.shader",
			"res/shaders/Basicf.shader");

		m_Shader->Bind();

		glEnable(GL_DEPTH_TEST);
		//glEnable(GL_CULL_FACE);
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		m_Projection = glm::perspective(RecalculateFov(), 1.0f * screen_width / screen_height, 0.1f, 10.0f);
		m_View = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
		m_Model = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));


		m_MVP = m_Projection * m_View * m_Model;

		m_Shader->SetUniformMat4f("u_MVP", m_MVP);
	
		if (m_Mesh != nullptr)
		{
			glCreateVertexArrays(1, &m_VA);
			glBindVertexArray(m_VA);

			glCreateBuffers(1, &m_VB);
			glBindBuffer(GL_ARRAY_BUFFER, m_VB);
			glBufferData(GL_ARRAY_BUFFER, m_Mesh->Data.vertices.size() * sizeof(Vertex), &m_Mesh->Data.vertices[0], GL_STATIC_DRAW);

			glEnableVertexArrayAttrib(m_VA, 0);
			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Position));

			glEnableVertexArrayAttrib(m_VA, 1);
			glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, TexUV));

			glEnableVertexArrayAttrib(m_VA, 2);
			glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Normal));

			glEnableVertexArrayAttrib(m_VA, 3);
			glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Color));

			glEnableVertexArrayAttrib(m_VA, 4);
			glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, TexIndex));

			glCreateBuffers(1, &m_IB);
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IB);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_Mesh->Data.faceIndex.size() * sizeof(GLuint), &m_Mesh->Data.faceIndex[0], GL_STATIC_DRAW);
		}

		m_Shader->Unbind();
	}

	TestLoadMesh::~TestLoadMesh()
	{
		if (m_Mesh != nullptr)
		{
			delete m_Mesh;
			m_Mesh = nullptr;
		}

		if (m_Shader != nullptr)
		{
			delete m_Shader;
			m_Shader = nullptr;
		}
	}

	int TestLoadMesh::OnUpdate(float deltaTime)
	{


		return TEST_MENU_NOCHANGE;
	}

	void TestLoadMesh::OnRender()
	{
		GLCall(glClearColor(0.1f, 0.1f, 0.1f, 1.0f));
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		m_View = glm::lookAt(glm::vec3(0.0f, 3.1f, 0.0f), glm::vec3(0.0f, 0.0f, -5.0f), glm::vec3(0.0f, 1.0f, 0.0f));
		m_Model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -7.0f));

		m_MVP = m_Projection * m_View * m_Model;

		m_Shader->Bind();
		glBindVertexArray(m_VA);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IB);
		
		m_Shader->SetUniformMat4f("u_MVP", m_MVP);
		
		int size;  glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
		glDrawElements(GL_TRIANGLES, size/sizeof(GLuint), GL_UNSIGNED_INT, nullptr);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		m_Shader->Unbind();
	}

OBJ-file:

# Blender v2.81 (sub 16) OBJ File: 'untitled.blend'
# www.blender.org
o Cube_Cube.001
v 1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 1.000000
vt 0.875000 0.750000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/2/2
f 8/6/3 5/7/3 7/5/3
f 6/8/4 1/9/4 5/7/4
f 7/5/5 1/10/5 3/11/5
f 4/12/6 6/8/6 8/6/6
f 2/1/1 4/4/1 3/2/1
f 4/4/2 8/6/2 7/5/2
f 8/6/3 6/8/3 5/7/3
f 6/8/4 2/13/4 1/9/4
f 7/5/5 5/7/5 1/10/5
f 4/12/6 2/14/6 6/8/6

vertex shader:

#version 330 core

layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec2 a_TexCoord;
layout(location = 2) in vec3 a_Normal;
layout(location = 3) in vec4 a_Color;
layout(location = 4) in float a_TexIndex;

out vec2 v_TexCoord;
out float v_TexIndex;
out vec4 v_Color;

uniform mat4 u_MVP;

void main()
{
	gl_Position = u_MVP * a_Position;
	v_TexCoord = a_TexCoord;
	v_Color = a_Color;
	v_TexIndex = a_TexIndex;
};
Advertisement

I just solved it, hard to believe it took me so much time. my indices order was all messed up.

@fleabay I don't know, first time doing this and not got that far yet, but every index for the "vn" is the same per triangle face. Those 6 normals are indexed 36 times.

This topic is closed to new replies.

Advertisement