09 May 2013

Reading obj file

The training data contain mesh information of 3D body is stored in .obj file. Here is format of the .obj file:

####
#
# OBJ File Generated by Meshlab
#
####
# Object female01-1532-na.obj
#
# Vertices: 1282
# Faces: 2560
#
####
vn -0.344122 0.249172 -0.905258
v -155.144363 -54.513828 -640.656250
vn 0.046374 -0.339345 -0.939518
v -122.898865 -80.428886 -643.766418
...
vn 0.011051 0.127717 0.991749
v -53.384335 4.810349 852.756348
# 1282 vertices, 1282 vertices normals

f 5//5 1//1 16//16
f 29//29 18//18 6//6
...
f 545//545 501//501 503//503
# 2560 faces, 0 coords texture

# End of File
The lines start with '#' in file can be treated as comments as "//" in C/C++.
The lines begin with vn indicate that the three numbers is unit normal at the point. The next line starting with v indicate the corresponding vertex coordinate.
The lines starting with f indicate the face/mesh information. For example, the first triangle consist of vertex 5, 1 and 16.

Following is snippet for reading obj file and save the data as plain text.
// ObjReader.h
#pragma once

#include 
#include 
#include 
#include 
#include 
#include 

class CObjReader
{
public:
	typedef struct point3fTag
	{
		float x, y, z;
		float normx, normy, normz;
	}point3f;

	int m_iNbofVertex;
	CObjReader(void);
	~CObjReader(void);

	static void ReadObj(const std::string& filename, CObjReader &currObj);
};
// ObjReader.cpp
#include "ObjReader.h"

CObjReader::CObjReader(void):m_iNbofVertex(0){}

CObjReader::~CObjReader(void){}

void CObjReader::ReadObj(const std::string& filename, CObjReader &currObj)
{
	std::fstream fp;
	std::ofstream op(".\\output.txt");
	fp.open(filename.c_str(), std::ios::in);

	std::stringstream ss;
	std::string temp;
	float tempFloat = 0.0f;
	std::vector vertice;
	std::vector face;
	// Skip header
	do 
	{
		getline(fp, temp);
	} while (temp[0] == '#');

	// Process vertex and its normal
	while (temp[0] != '#')
	{
		ss << temp;
		ss >> temp;	// skip "vn"
		point3f tempPoint;
		ss >> tempPoint.normx >> tempPoint.normy >> tempPoint.normz;
		ss.clear();
		// get v
		getline(fp, temp);
		ss << temp;
		ss >> temp;	// skip 'v'
		ss >> tempPoint.x >> tempPoint.y >> tempPoint.z;
		ss.clear();
		vertice.push_back(tempPoint);
		// get vn for next point
		getline(fp, temp);
	}
	ss << temp;
	ss >> temp;	// skip '#'
	unsigned int a;
	ss >> a;
	ss.clear();
	assert(a == vertice.size());
	currObj.m_iNbofVertex = vertice.size();
	// Process face
	getline(fp, temp); // skip empty line
	getline(fp, temp); // Get first line of face data
	do 
	{
		ss.str("");	// Clean previous contents
		ss << temp;
		ss >> temp; // skip 'f'
		for (int i = 0; i < 3; i++)
		{
			ss >> temp; // temp: i//i
			temp.erase(temp.find('/'),temp.size()-temp.find('/'));
			face.push_back(std::stoi(temp));
		}
		ss.clear();
		getline(fp, temp);
	} while (temp[0] == 'f');
	std::cout << temp << std::endl;
	fp.close();
	
	// Save vertice and face info
	for (unsigned int i = 0; i < vertice.size(); i++)
	{
		op << "vn: ";
		op << vertice[i].normx << " " << vertice[i].normy << " " << vertice[i].normz << "\n";
		op << "v: ";
		op << vertice[i].x << " " << vertice[i].y << " " << vertice[i].z << "\n";
	}
	op << "# Face data\n";
	for (int i = 0; i < face.size();)
	{
		op << face[i] << " " << face[i+1] << " " << face[i+2] << "\n";
		i = i + 3;
	}
	op.close();
}

No comments:

Post a Comment