Jump to content

  • Log In with Google      Sign In   
  • Create Account


importing .obj file into OpenGL


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 hikarihe   Members   -  Reputation: 243

Like
0Likes
Like

Posted 15 February 2013 - 01:11 AM

Hi everyone, when I import an .obj file I get a model looking similar to the one I want but some triangles look distorted.

 

this is the model

stick_figure_blender.jpg
 
and this is what i get (ignore rotation)
stick_figure.jpg

 

declarations:

// vertex, normal, and index related declarations
GLfloat vertices[500];
GLfloat normals[540];
int indices[1300];
int vertexIndex = 0, normalIndex = 0, elementIndex = 0;

 

 

my load function:

// extracts object's vertices, indices, and normals from given file
int LoadObject( const char* filename, GLfloat vertices[], GLfloat normals[], int elements[] )
{
	// local variables
	const int MAX_CHARS_PER_LINE = 64;
	char lineBuffer[64];
	char temp[16];
	char tempFloat[16];
	FILE *objFile;
	int count;
	GLfloat coordinate; // stored in vertices
	int index;
	int charCount;
	int isVertex = -1; // -1 for normal, 1 for vertex
	int isFirstNormal = 1; // 1 for first normal, -1 for any other normal

	// open file
	fopen_s( &objFile, filename, "r" );

	// check for errors
	if ( objFile == NULL )
	{
		return 0;
	}

	// while there are lines to read
	while ( fgets( lineBuffer, MAX_CHARS_PER_LINE, objFile ) != NULL )
	{
		
		// if we are reading a vector
		if ( strncmp( lineBuffer, "v ", 2 ) == 0 )
		{

			// initialize charCount
			charCount = 0;

			// loop through each char in the line
			for ( count = 2; count < (int)strlen( lineBuffer ); count++ )
			{
				
				// if we are reading part of a float coordinate
				if ( ( lineBuffer[count] == '-' ) || ( isdigit( lineBuffer[count] ) ) || ( lineBuffer[count] == '.') )
				{
					// store this char into temp
					temp[charCount++] = lineBuffer[count];
				}

				// if we are not reading part of a float and a float exists in temp
				else if ( charCount != 0 )
				{
					// copy the float coordinate to tempFloat
					strncpy( tempFloat, temp, charCount );

					//
					tempFloat[ charCount ] = '\n';

					// store the coordinate in our vertices array
					coordinate = atof( tempFloat );
					vertices[vertexIndex++] = coordinate;

					// re-initialize charCount
					charCount = 0;
				}
			}
		}

		// if we are reading a normal
		if ( strncmp( lineBuffer, "vn ", 3 ) == 0 )
		{

			// initialize charCount
			charCount = 0;

			// loop through each char in the line
			for ( count = 3; count < (int)strlen( lineBuffer ); count++ )
			{
				
				// if we are reading part of a float coordinate
				if ( ( lineBuffer[count] == '-' ) || ( isdigit( lineBuffer[count] ) ) || ( lineBuffer[count] == '.') )
				{
					// store this char into temp
					temp[charCount++] = lineBuffer[count];
				}

				// if we are not reading part of a float and a float exists in temp
				else if ( charCount != 0 )
				{
					// copy the float coordinate to tempFloat
					strncpy( tempFloat, temp, charCount );

					//
					tempFloat[ charCount ] = '\n';

					// store the coordinate in our normals array
					coordinate = atof( tempFloat );
					normals[normalIndex++] = coordinate;

					// re-initialize charCount
					charCount = 0;
				}
			}
		}

		// if we are reading face info
		if ( strncmp( lineBuffer, "f ", 2 ) == 0 )
		{

			// initialize charCount, isVertex and isFirstNormal
			charCount = 0;
			isVertex = 1;
			isFirstNormal = 1;

			// loop through each char in the line
			for ( count = 2; count < (int)strlen( lineBuffer ); count++ )
			{
				
				// if we are reading part of an index
				if ( isdigit( lineBuffer[count] ) )
				{
					// store this char into temp
					temp[charCount++] = lineBuffer[count];
				}

				// if we are not reading part of an index and an index exists in temp
				else if ( charCount != 0 )
				{

					// if the index is a vertex
					if ( isVertex == 1 )
					{

						// copy the float coordinate to tempFloat
						strncpy( tempFloat, temp, charCount );

						//
						tempFloat[ charCount ] = '\n';

						// store the coordinate in our indices array
						index = atof( tempFloat );
						elements[elementIndex++] = (int)index;
					}

					// if the index is a normal
					else
					{

						// if this is the first normal in the line
						if ( isFirstNormal == 1 )
						{
							// copy the float coordinate to tempFloat
							strncpy( tempFloat, temp, charCount );

							//
							tempFloat[ charCount ] = '\n';

							// store the coordinate in our normals array
							index = atof( tempFloat );
							elements[elementIndex++] = (int)index;

							// switch isFirstNormal
							isFirstNormal *= -1;
						}
					}

					// switch isVertex
					isVertex *= -1;

					// re-initialize charCount
					charCount = 0;
				}
			}
		}

	}

	// close file
	fclose( objFile );

	// return ok
	return 1;
}

 

 

my draw routine:

// draw our model
	glBegin( GL_TRIANGLES );

	// go through each element
	for ( i = 0; i < elementIndex; i += 4 )
	{
		// set offsets
		normalOffset  = 3;
		vertexOffset = 3;

		// calculate index of x coordinate of current normal
		currentNormalIndex = normalOffset * ( indices[i + 1] - 1 );

		// calculate index of x coordinates of the three vertices
		firstVertexIndex = vertexOffset * ( indices[ i + 1 ] - 1 );
		secondVertexIndex = vertexOffset * ( indices[ i + 2 ] - 1 );
		thirdVertexIndex = vertexOffset * ( indices[ i + 3 ] - 1 );

		// set the normal for our triangle face
		glNormal3f( normals[ normalOffset ], 
			normals[ normalOffset + 1 ], 
			normals[ normalOffset + 2 ] );

		// set vertex 1
		glVertex3f( vertices[ firstVertexIndex ], 
			vertices[ firstVertexIndex + 1 ],
			vertices[ firstVertexIndex + 2 ]);

		// set vertex 2
		glVertex3f( vertices[ secondVertexIndex ], 
			vertices[ secondVertexIndex + 1 ],
			vertices[ secondVertexIndex + 2 ]);
		
		// set vertex 3
		glVertex3f( vertices[ thirdVertexIndex ], 
			vertices[ thirdVertexIndex + 1 ],
			vertices[ thirdVertexIndex + 2 ]);

	}
	glEnd();

 

 

The object was exported from blender using:

  • selection only (current model)
  • include normals
  • triangulate faces
  • keep vertex order

I understand that there are alternative ways to import and draw an .obj file but this will help me understand OpenGL and 3D objects better since I'm new to both 3D modelling and OpenGL.

 

Can someone help through this?

 

arigatou

 

EDIT: the indices are stored like this: [vector], [vector normal], [vector], [vector] for each line and I use the same vector normal for the 3 vectors to save space

Attached Thumbnails

  • stick_figure.jpg
  • stick_figure_blender.jpg

Edited by hikarihe, 15 February 2013 - 01:15 AM.


Sponsor:

#2 L. Spiro   Crossbones+   -  Reputation: 11938

Like
1Likes
Like

Posted 15 February 2013 - 01:19 AM

The indices in .OBJ files are 1-based.
What is the logic behind “( indices[i + 1] - 1 )”?


L. Spiro

Edited by L. Spiro, 15 February 2013 - 01:20 AM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#3 hikarihe   Members   -  Reputation: 243

Like
0Likes
Like

Posted 15 February 2013 - 01:20 AM

thanks ^^ it works. my mistake. should I delete the post?



#4 L. Spiro   Crossbones+   -  Reputation: 11938

Like
0Likes
Like

Posted 15 February 2013 - 01:25 AM

No. Others may gain insight from it.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#5 Jaey   Members   -  Reputation: 117

Like
0Likes
Like

Posted 17 February 2013 - 12:12 PM

thanks ^^ it works. my mistake. should I delete the post?

hi, how did you fix it pls? I have a similar issue



#6 SimonForsman   Crossbones+   -  Reputation: 5719

Like
0Likes
Like

Posted 17 February 2013 - 12:24 PM


thanks ^^ it works. my mistake. should I delete the post?

hi, how did you fix it pls? I have a similar issue


as lspiro said, the indices are 1 based in obj files, in C and C++ (and quite many other languages aswell) arrays start at 0, so instead of:
glVertex3f( vertices[ firstVertexIndex ],
vertices[ firstVertexIndex + 1 ],
vertices[ firstVertexIndex + 2 ]);

you do:
glVertex3f( vertices[ firstVertexIndex -1 ],
vertices[ firstVertexIndex ],
vertices[ firstVertexIndex + 1 ]);

(if you use vertex arrays or VBOs you do the equivalent operation where you initialize your array/vbo instead)
I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#7 hikarihe   Members   -  Reputation: 243

Like
0Likes
Like

Posted 17 February 2013 - 12:41 PM

thanks ^^ it works. my mistake. should I delete the post?

hi, how did you fix it pls? I have a similar issue

 

 

       // calculate index of x coordinate of current normal
        currentNormalIndex = normalOffset * ( indices[i + 1] - 1 ); 

        // calculate index of x coordinates of the three vertices
        firstVertexIndex = vertexOffset * ( indices[ i + 1 ] - 1 ); <<<<< here, replace with ( indices[ i ] - 1 )
        secondVertexIndex = vertexOffset * ( indices[ i + 2 ] - 1 );
        thirdVertexIndex = vertexOffset * ( indices[ i + 3 ] - 1 );

 

that's it. rest of the code is fine, but could be cleaned up ^ ^'



#8 hikarihe   Members   -  Reputation: 243

Like
0Likes
Like

Posted 17 February 2013 - 12:59 PM

 

thanks ^^ it works. my mistake. should I delete the post?

hi, how did you fix it pls? I have a similar issue

 

as lspiro said, the indices are 1 based in obj files, in C and C++ (and quite many other languages aswell) arrays start at 0, so instead of:
glVertex3f( vertices[ firstVertexIndex ],
vertices[ firstVertexIndex + 1 ],
vertices[ firstVertexIndex + 2 ]);

you do:
glVertex3f( vertices[ firstVertexIndex -1 ],
vertices[ firstVertexIndex ],
vertices[ firstVertexIndex + 1 ]);

(if you use vertex arrays or VBOs you do the equivalent operation where you initialize your array/vbo instead)

 

You can go to the root of the problem instead and do -1 when storing:

 

Store indices:

// if the index is a normal
else
{

	// increment currentNormal
	currentNormal++;

	// if this is the third normal in the line
	if ( currentNormal == 3 )
	{
		// copy the float coordinate to tempFloat
		strncpy_s( tempFloat, 16, temp, charCount );

		//
		tempFloat[ charCount ] = '\n';

		// store the coordinate in indices array
		index = atoi( tempFloat );
		elements[(*elementIndex)++] = index - 1;

		// set current normal to 0
		currentNormal = 0;
	}
} 

 

 

Draw:

// calculate index of x coordinate of current normal
currentNormalIndex = normalOffset * ( indices[i + 3] );

// calculate index of x coordinates of the three vertices
firstVertexIndex = vertexOffset * ( indices[ i ] );
secondVertexIndex = vertexOffset * ( indices[ i + 1 ] );
thirdVertexIndex = vertexOffset * ( indices[ i + 2 ] );

 

looks much cleaner! ^w^



#9 Jaey   Members   -  Reputation: 117

Like
0Likes
Like

Posted 17 February 2013 - 01:30 PM

Hi,

I am trying to import chess pieces from 3dsmax to opengl.

However, I am quite new to opengl and it has been a big challenge so far.

Any help will be appreciated?



#10 blueshogun96   Crossbones+   -  Reputation: 797

Like
0Likes
Like

Posted 18 February 2013 - 12:59 AM

Hi,

I am trying to import chess pieces from 3dsmax to opengl.

However, I am quite new to opengl and it has been a big challenge so far.

Any help will be appreciated?

 

I recommend starting a new thread for this question, then it can get more specific attention.

 

I think the proper word you want to use is "export".  Export your 3D model to a 3D format that's well documented such as collada (.dae), object (.obj), .3ds, etc.  I don't have 3dsmax so I don't know what types of exports it supports; I use Blender.  Depending on the format you choose to export, you may have to write your own loader for the file and parse it manually, then format the vertex data into a compatible format that OpenGL can use.

 

The answer to your question is not a simple one.  Do you have a specific export format in mind?  And how far with OpenGL have you gotten already?  You may be biting off more than you can chew; I'm asking because I don't quite understand what is so difficult for you.

 

Shogun.


Follow Shogun3D on the official website: http://shogun3d.net

 

blogger.png twitter.png tumblr_32.png facebook.png





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS