Thread: Loading .OBJ Files

  1. #1
    Registered User BradyW's Avatar
    Join Date
    Aug 2011
    Location
    Maryland, USA
    Posts
    5

    Loading .OBJ Files

    After following a Youtube series on OpenGL 3D programming, I came across a simple error:

    The .OBJ file (imported from Blender) is "invalid or corrupt". After some short investigation, I learned that .OBJ files are usually binary files, but since mine is just a 3D model, it is not binary.

    How would I go about it so that my .OBJ file doesn't end up being compiled by the compiler, yet still is accessible by my .OBJ loader in my program? I'm using VC++ Express.

    Here is my .OBJ Loader:
    Code:
    int loadObject(const char* filename)
    {
    	std::vector<std::string*> coord;	//read every single line of the obj file as a string
    	std::vector<coordinate*> vertex;
    	std::vector<face*> faces;
    	std::vector<coordinate*> normals;	//normal vectors for every face
    	std::ifstream in(filename);	//open the .obj file
    	if(!in.is_open())	//if not opened, exit with -1
    	{
    		std::cout << "Not opened" << std::endl;
    		return -1;
    	}
    	char buf[256];
    	//read in every line to coord
    	while(!in.eof())
    	{
    		in.getline(buf,256);
    		coord.push_back(new std::string(buf));
    	}
    	//go through all of the elements of coord, and decide what kind of element is that
    	for(unsigned int i=0;i<coord.size();i++)
    	{
    		if((*coord[i])[0]=='#')	//if it is a comment (the first character is #)
    			continue;	//we don't care about that
    		else if((*coord[i])[0]=='v' && (*coord[i])[1]==' ')	//if vector
    		{
    			float tmpx,tmpy,tmpz;
    			sscanf_s(coord[i]->c_str(),"v %f %f %f",&tmpx,&tmpy,&tmpz);	//read in the 3 float coordinate to tmpx,tmpy,tmpz
    			vertex.push_back(new coordinate(tmpx,tmpy,tmpz));	//and then add it to the end of our vertex list
    		}else if((*coord[i])[0]=='v' && (*coord[i])[1]=='n')	//if normal vector
    		{
    			float tmpx,tmpy,tmpz;	//do the same thing
    			sscanf_s(coord[i]->c_str(),"vn %f %f %f",&tmpx,&tmpy,&tmpz);
    			normals.push_back(new coordinate(tmpx,tmpy,tmpz));	
    		}else if((*coord[i])[0]=='f')	//if face
    		{
    			int a,b,c,d,e;
    			if(count(coord[i]->begin(),coord[i]->end(),' ')==3)	//if it is a triangle (it has 3 space in it)
    			{
    		  sscanf_s(coord[i]->c_str(),"f %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b);
    				faces.push_back(new face(b,a,c,d));	//read in, and add to the end of the face list
    			}else{
    				sscanf_s(coord[i]->c_str(),"f %d//%d %d//%d %d//%d %d//%d",&a,&b,&c,&b,&d,&b,&e,&b);
    				faces.push_back(new face(b,a,c,d,e));	//do the same, except we call another constructor, and we use different pattern
    			}
    		}
    	}
    	//draw
    	int num;	//the id for the list
    	num=glGenLists(1);	//generate a uniqe
    	glNewList(num,GL_COMPILE);	//and create it
    	for(unsigned int i=0;i<faces.size();i++)	
    	{
    		if(faces[i]->four)	//if it's a quad draw a quad
    		{
    			glBegin(GL_QUADS);
    				//basically all I do here, is use the facenum (so the number of the face) as an index for the normal, so the 1st normal owe to the first face
    				//I subtract 1 because the index start from 0 in C++
    				glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
    				//draw the faces
    				glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
    				glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
    				glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
    				glVertex3f(vertex[faces[i]->faces[3]-1]->x,vertex[faces[i]->faces[3]-1]->y,vertex[faces[i]->faces[3]-1]->z);
    			glEnd();
    		}else{
    			glBegin(GL_TRIANGLES);
    				glNormal3f(normals[faces[i]->facenum-1]->x,normals[faces[i]->facenum-1]->y,normals[faces[i]->facenum-1]->z);
    				glVertex3f(vertex[faces[i]->faces[0]-1]->x,vertex[faces[i]->faces[0]-1]->y,vertex[faces[i]->faces[0]-1]->z);
    				glVertex3f(vertex[faces[i]->faces[1]-1]->x,vertex[faces[i]->faces[1]-1]->y,vertex[faces[i]->faces[1]-1]->z);
    				glVertex3f(vertex[faces[i]->faces[2]-1]->x,vertex[faces[i]->faces[2]-1]->y,vertex[faces[i]->faces[2]-1]->z);
    			glEnd();
    		}
    	}
    	glEndList();
    	//delete everything to avoid memory leaks
    	for(unsigned int i=0;i<coord.size();i++)
    		delete coord[i];
    	for(unsigned int i=0;i<faces.size();i++)
    		delete faces[i];
    	for(unsigned int i=0;i<normals.size();i++)
    		delete normals[i];
    	for(unsigned int i=0;i<vertex.size();i++)
    		delete vertex[i];
    	return num;	//return with the id
    }
    Last edited by BradyW; 11-22-2011 at 07:57 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > while(!in.eof())
    SourceForge.net: Feof - cpwiki
    I think you'll find you've got a junk copy of the last line of the file, with the code you have.

    > How would I go about it so that my .OBJ file doesn't end up being compiled by the compiler,
    The compiler doesn't go looking round your project for *.obj files just to link them. It only links the ones named by you in your project.

    Also, all your use of vectors with pointers and DIY memory management is very ugly.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User BradyW's Avatar
    Join Date
    Aug 2011
    Location
    Maryland, USA
    Posts
    5
    Quote Originally Posted by Salem View Post
    > while(!in.eof())
    SourceForge.net: Feof - cpwiki
    I think you'll find you've got a junk copy of the last line of the file, with the code you have.

    > How would I go about it so that my .OBJ file doesn't end up being compiled by the compiler,
    The compiler doesn't go looking round your project for *.obj files just to link them. It only links the ones named by you in your project.

    Also, all your use of vectors with pointers and DIY memory management is very ugly.

    Thanks, I think I'll just look up a new tutorial on .OBJ loaders and attempt to understand it. Do you recommend any?

    EDIT: After looking around, going with the 3DS format is probably better and smoother.
    Last edited by BradyW; 11-23-2011 at 10:55 AM.

  4. #4
    Registered User
    Join Date
    Nov 2011
    Posts
    48
    Very much no to your last comment. The 3DS format, while somewhat simple, is infintely more complex than the OBJ format. For a first importer, obj or ma ( maya ascii ) are probably the two best places to start.


    Refer to this link ( libobj ) for details on implementing an OBJ importer in C++.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. ASM & C++ and loading files
    By RobotGymnast in forum C++ Programming
    Replies: 11
    Last Post: 01-06-2008, 05:02 PM
  2. loading md2 files in opeGL
    By avgprogamerjoe in forum Game Programming
    Replies: 0
    Last Post: 10-01-2007, 08:02 PM
  3. Loading multiple files
    By SanDiego619SDSU in forum C Programming
    Replies: 4
    Last Post: 10-29-2006, 01:37 AM
  4. C++ loading from txt files prob
    By nzad cmaster in forum C++ Programming
    Replies: 6
    Last Post: 08-04-2006, 03:35 PM
  5. Loading large files with c++
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 03-18-2002, 12:26 AM