sscanf and MD5

Started by
5 comments, last by GavRobbs 15 years, 8 months ago
I've finally gotten OBJ and MD2 to work, so now I'm going to try my hand at skeletal animation. I've written some code to simply read and output the data into a console window. No rendering yet, I just want to make sure the file is being read properly. The header reads fine, and the required number of meshes and joints too, but the data INSIDE the meshes and joints don't read properly. I've found my issue to be with sscanf I think. MD5Version 10 ------>(indent here)numverts 494 The difference between those 2 lines up there is that one is indented and one isn't. Thats why the version info is being properly read, but the vertex count isn't. I'm trying to read the vertex count using the following line: sscanf(tmpline,"numverts %d",&temp_mesh.numVertices); Can someone please suggest a modification to my formatting string so that it will read the number of vertices properly? Thanks in advance.
Advertisement
Not sure about MD5. But when i download .md5 file i saw TABs before "numverts",
probably thats why not interpreting this?

maybe you can try like this ?:

char *line = readline();
char *s = strstr(line,"numverts");
if(s) {
if(sscaf(s,"numverts %d",&num_vert) == 1) {
printf("num vertices are now %d\n",num_vert);
};
};

you can skip the leading spaces/tabs and go to the first character:
char *ptr = str;while(*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++;

something like that...
@ferdekk: Thanks for the advice, but I can already accurately identify which line belongs to which element of the file. The problem is that numVerts, in fact, most subdata chunks, won't load properly.

$Tobio: I've tried. It ain't workin. lol. Any other suggestions people? Please and thank you.
Here is some more code, so you can have an idea of whats going on.

[source lang = "cpp"]struct MD5HeaderInfo{	int version;	int numJoints;	int numMeshes;};struct MD5Vec2{	float x,y;};struct MD5Vec3{	float x,y,z;};struct MD5Vec4{	float x,y,z,w;};struct MD5MeshVertex{	int index;	MD5Vec2 texcoords;	int start_weight;	int count_weight;};struct MD5MeshTriangle{	int triangle_index;	int vertex_indices[3];};struct MD5MeshVertexWeight{	int index;	int joint;	float bias;	MD5Vec3 weight_position;};struct MD5JointInfo{	char * name;	int parent;	MD5Vec3 joint_position;	MD5Vec4 joint_orientation;};struct MD5Mesh{	int numVertices;	int numTriangles;	int numWeights;	std::vector<MD5MeshVertex> mesh_vertices;	std::vector<MD5MeshTriangle> mesh_triangles;	std::vector<MD5MeshVertexWeight> mesh_vertex_weights;};struct MD5Model{	MD5HeaderInfo header;	std::vector<MD5Mesh> meshes;	std::vector<MD5JointInfo> joints;};MD5Mesh ProcessMesh(FILE * mfile){	MD5Mesh temp_mesh;	MD5MeshVertex temp_vert;	MD5MeshTriangle temp_tri;	MD5MeshVertexWeight temp_weight;	char tmpline[256];	while(fgets(tmpline,256,mfile) != NULL)	{		if(feof(mfile))		{			break;		};		if(strncmp(tmpline,"}",1) == 0)		{			break;		}		else if(strncmp(tmpline,"numverts",8) == 0)		{			sscanf(tmpline,"numverts %d",&temp_mesh.numVertices);		}		else if(strncmp(tmpline,"numtris",7) == 0)		{			sscanf(tmpline,"numtris %d",&temp_mesh.numTriangles);		}		else if(strncmp(tmpline,"numweights",10) == 0)		{			sscanf(tmpline,"numweights %d",&temp_mesh.numWeights);		}		else if(strncmp(tmpline,"vert",4) == 0)		{			sscanf(tmpline,"vert %d ( %f %f ) %d %d",&temp_vert.index,&temp_vert.texcoords.x,&temp_vert.texcoords.y,&temp_vert.start_weight,&temp_vert.count_weight);temp_mesh.mesh_vertices.push_back(temp_vert);		}		else if(strncmp(tmpline,"tri",3) == 0)		{			sscanf(tmpline,"tri %d %d %d %d",&temp_tri.triangle_index,temp_tri.vertex_indices[0],temp_tri.vertex_indices[1],temp_tri.vertex_indices[2]);			temp_mesh.mesh_triangles.push_back(temp_tri);		}		else if(strncmp(tmpline,"weight",6) == 0)		{			sscanf(tmpline,"weight %d %d %f ( %f %f %f )",&temp_weight.index,&temp_weight.joint,&temp_weight.bias,&temp_weight.weight_position.x,&temp_weight.weight_position.y,&temp_weight.weight_position.z);			temp_mesh.mesh_vertex_weights.push_back(temp_weight);		};		memset(tmpline,0,256);	};	return temp_mesh;};std::vector<MD5JointInfo> ProcessJoints(FILE * file){	char tmpline[256];	MD5JointInfo temp;	MD5Vec3 orient;	std::vector<MD5JointInfo> mdji;	while(fgets(tmpline,256,file) != NULL)	{		if(feof(file))		{			break;		};		if(strncmp("}",tmpline,1) == 0)		{			break;		}		else		{			sscanf(tmpline,"%s %d ( %f %f %f ) ( %f %f %f)",&temp.name,&temp.parent,&temp.joint_position.x,&temp.joint_position.y,&temp.joint_position.z,&orient.x,&orient.y,&orient.z);	temp.joint_orientation = calculate_quat_w(orient);			mdji.push_back(temp);		};	};	return mdji;};
Here is some source code of a modified md5 loader.
I found a great one on the net, but it didn't make use of classes, so I rewrote it:

if (!ifs.is_open())	throw_exception( "Input stream not opened!", LIB_EXCEPTION );std::string token, buffer, shader;int _numVerts, _numTris, _numWeights;m_fBumpheight = 1.0f;do{	// Read first token line from file	ifs >> token;	if( token == "shader" )	{		ifs >> shader;		// Remove quote marks from the shader string		m_strTexture = shader.substr(shader.find_first_of('\"') + 1, shader.find_last_of('\"') - 1);		// Get mesh name from shader string		m_strMesh = m_strTexture.c_str() + m_strTexture.find_last_of ('/') + 1;	}	else if( token == "bumpheight" )	{		ifs >> m_fBumpheight;	}	else if( token == "numverts" )	{		ifs >> _numVerts;		m_Vertices.reserve( _numVerts );	}	else if( token == "numtris" )	{		ifs >> _numTris;		m_Triangles.reserve( _numTris );	}	else if( token == "numweights" )	{		ifs >> _numWeights;		m_Weights.reserve( _numWeights );	}	else if( token == "vert" )	{		static int index = 0;		CMD5Vertex vert;		if( numVerts() >= _numVerts )			throw_exception( "model is damaged", LIB_ERROR );		// Read vertex data		ifs >> token; // index		ifs >> token; // "("		ifs >> vert.tu;		ifs >> vert.tv;		ifs >> token; // ")"		ifs >> vert.WeightIndex;		ifs >> vert.Weightcount;		vert.Index = index;		vert.tv    = 1 - vert.tv;		m_Vertices.push_back( vert );		index++;	}	// Eat up rest of the line	std::getline( ifs, buffer );}while((token != "}") && !ifs.eof ());


If you use c++ to open the md5 mesh, you don't have to worry about the possbile tabs. std::ifstream just doesn't read them and continues at the next character.
A big plus of using the c++ filestream classes is, that reading and writing strings becomes quite easy.

If you want the source code of my loader, write me a pm, I'm happy to share it :)
Thanks for the offer shadowman, but I solved my problem at about 1 am this morning. Thanks anyway.

This topic is closed to new replies.

Advertisement