Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: Trouble loading in .obj

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Newbie Newbie
    Join Date
    Dec 2017
    Posts
    2

    Trouble loading in .obj

    Hi, brand new to the forums and needing a bit of help with loading in an obj for an assignment. My model loader reads the obj file, and assigns the values for the vertices, normals, texture mapping and faces to 4 seperate vertex arrays. It then using the faces as an index to create 3 new sorted arrays for the vertices, normals and texture mapping co-ordinates, and uses these sorted arrays to render.
    Trouble is the model is a complete mess and looks nothing like it should, although when I try and debug it looks as if the file is being read correctly, and the correct values are being sorted when using the appropriate index. Completely stumped.

    The vector3 class contains 3 float values xyz.
    sortedvertex, sortednormals and texCoords are all vector arrays of type float.

    Code :
    bool Model::loadModel(char* filename)
    {
    	vector<Vector3> verts;
    	vector<Vector3> norms;
    	vector<Vector3> texCs;
    	vector<unsigned int> faces;
     
    	FILE* file = fopen(filename, "r");
    	if (file == NULL)
    	{
    		return false;
    	}
    	while (true)
    	{
    		char lineHeader[128];
     
    		// Read first word of the line
    		int res = fscanf(file, "%s ", lineHeader);
    		if (res == EOF)
    		{
    			break; // exit loop
    		}
    		else // Parse
    		{
    			if (strcmp(lineHeader, "v") == 0) // Vertex
    			{
    				Vector3 vertex;
    				fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
    				verts.push_back(vertex);
    			}
    			else if (strcmp(lineHeader, "vt") == 0) // Tex Coord
    			{
    				Vector3 uv;
    				fscanf(file, "%f %f\n", &uv.x, &uv.y);
    				texCs.push_back(uv);
    			}
    			else if (strcmp(lineHeader, "vn") == 0) // Normal
    			{
    				Vector3 normal;
    				fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
    				norms.push_back(normal);
    			}
    			else if (strcmp(lineHeader, "f") == 0) // Face
    			{
    				unsigned int face[9];
    				int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &face[0], &face[1], &face[2],
    															&face[3], &face[4], &face[5],
    															&face[6], &face[7], &face[8]);
    				if (matches != 9)
    				{
    					// Parser error, or not triangle faces
    					return false;
    				}
     
    				for (int i = 0; i < 9; i++)
    				{
    					double value = face[i] - 1;
    					faces.push_back(value);
    				}
     
     
    			}
    		}
    	}
     
    	// "Unroll" the loaded obj information into a list of triangles.
    	for (int f = 0; f < (int)faces.size(); f += 3) {
     
    		int faceIndex = faces[f];
     
    		// first face value (vertex)
    		sortedvertex.push_back(verts[faces[f]].x);
    		sortedvertex.push_back(verts[faces[f]].y);
    		sortedvertex.push_back(verts[faces[f]].z);
    		vertexCount++;
     
    		/*
    		// second face value (texture mapping)
    		texCoords.push_back(texCs[faces[f + 1]].x);
    		texCoords.push_back(texCs[faces[f + 1]].y);
    		*/
     
    		//third face value (normals)
    		sortednormals.push_back(norms[faces[f + 2]].x);
    		sortednormals.push_back(norms[faces[f + 2]].y);
    		sortednormals.push_back(norms[faces[f + 2]].z);
    	}
     
    	verts.clear();
    	norms.clear();
    	texCs.clear();
    	faces.clear();
     
    	return true;
    }
     
    void Model::render()
    {
    	glEnableClientState(GL_VERTEX_ARRAY);
    	glEnableClientState(GL_NORMAL_ARRAY);
    	//glEnableClientState(GL_TEXTURE_COORD_ARRAY); disable texturing for now
     
    	glVertexPointer(3, GL_FLOAT, 0, &sortedvertex);
    	glNormalPointer(GL_FLOAT, 0, &sortednormals);
    	//glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
     
    	glBindTexture(GL_TEXTURE_2D, NULL);
    	glDrawArrays(GL_TRIANGLES, 0, vertexCount);
     
    	glDisableClientState(GL_VERTEX_ARRAY);
    	glDisableClientState(GL_NORMAL_ARRAY);
    	//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

  2. #2
    Junior Member Newbie
    Join Date
    Dec 2017
    Posts
    14
    Code :
    				unsigned int face[9];
    				for (int i = 0; i < 9; i++)
    				{
    					double value = face[i] - 1;
    					faces.push_back(value);
    				}
     
    	for (int f = 0; f < (int)faces.size(); f += 3) {
     
    		int faceIndex = faces[f];
     
    		// first face value (vertex)
    		sortedvertex.push_back(verts[faces[f]].x);
    		sortedvertex.push_back(verts[faces[f]].y);
    		sortedvertex.push_back(verts[faces[f]].z);
    It should be face[8] with the zero bit counter and only calling for 9 variables. You are also pushing 10 times. You should probably make a comparative in the for loop to assure you will not exceed the bounds of the container also , it looks as if you may be exceeding your values stored. 0 , 3 , 6 , 9 but the size is 9
    Code :
    for (; f+3 < faces.size() );
    As far as why your code is looking off I'm not quite sure. And is their a point to subtracting 1 from every face[x].
    Last edited by didydriver; 12-05-2017 at 10:46 PM.

  3. #3
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,526
    Quote Originally Posted by didydriver View Post
    It should be face[8] with the zero bit counter and only calling for 9 variables. You are also pushing 10 times.
    That's incorrect. There's nothing actually wrong with the way the OBJ is being parsed (in the sense that the vectors will end up containing the correct data).

    Quote Originally Posted by didydriver View Post
    And is their a point to subtracting 1 from every face[x].
    The OBJ format uses 1-based indices. C/C++ arrays and vectors use 0-based indices.

  4. #4
    Member Regular Contributor
    Join Date
    May 2016
    Posts
    445
    Code :
    unsigned int face[9];
    int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &face[0], &face[1], &face[2],
    											&face[3], &face[4], &face[5],
    											&face[6], &face[7], &face[8]);
    if (matches != 9)
    {
    	// Parser error, or not triangle faces
    	return false;
    }

    in case the model is made up of quads, this piece of code wont detect it, one way to get around it is to first test for 12 uints (4 x vertexindex/texcoordindex/normalindex) and then:
    Code :
    if (matches == 12)
    /* process quads */
    else if (matches == 9)
    /* process triangles */
    else 
    /* error */

    what do you expect to see ? is it a 3D model ? if so, did you set up a proper 3D camera / view point to be able to look at your model ?

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,526
    Quote Originally Posted by veryamateur View Post
    Code :
    	glVertexPointer(3, GL_FLOAT, 0, &sortedvertex);
    	glNormalPointer(GL_FLOAT, 0, &sortednormals);
    	//glTexCoordPointer(2, GL_FLOAT, 0, &texCoords);
    This won't work. You need to use e.g. &sortedvertex[0] to get a pointer to the vector's data.

  6. #6
    Newbie Newbie
    Join Date
    Dec 2017
    Posts
    2
    Quote Originally Posted by GClements View Post
    This won't work. You need to use e.g. &sortedvertex[0] to get a pointer to the vector's data.

    This is exactly what fixed the problem. Would have never figured this out myself, this was the last thing I had to do so now I can submit the assignment and put my mind at ease
    If anyone has the time, could they help in explaining just what was wrong with "&sortedvertex" compared to "&sortedvertex[0]"? In a different render function I refer to a standard array of floats, without using a pointer address or array index and it works perfectly.

    Thank you very much for all your replies.

  7. #7
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,526
    Quote Originally Posted by veryamateur View Post
    just what was wrong with "&sortedvertex" compared to "&sortedvertex[0]"?
    An array (whether a std::array or a C-style array) is just the data, so a pointer to the array is equivalent to a pointer to the first element.

    A std::vector is a structure which contains (amongst other things) a pointer to the data.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •