The .obj mesh file format allows corners of triangles to pull attributes from different sources. The triangle:
v 0 0 0
v 1 0 0
v 0 0 0
vn 1 0 0
vn 0 1 0
vt 0 0 0
f 1/1/1 2/1/1 3/1/2
pulls vertex positions from entries (1,2,3) in the v ...
vertex position list, texture coordinates from entries (1,1,1) in the vt ...
list, and normals from entries (1,2,2) in the vn normals
list.
If we think of corners being described by all attributes there are potentially #F*3 distinct corners. Often information is shared, and in the best case the position/texture/normal indices are all the same, so #V distinct corners. Usually it's some mixture in between.
I added igl::unzip_corners
to libigl which “unzips” an OBJ-style mesh into per-vertex attribute mesh: each new vertex is a distinct corner, so the new face list indexes all attributes in lock step (ideal for OpenGL). I was careful to determine uniqueness combinatorially so, for example, combinatorially distinct input vertices happening to share the same attributes (two vertices at the same position, etc.) don't get merged (you could always use igl::remove_duplicate_vertices
if you wanted to do that).
Here’s a little demo program:
Eigen::MatrixXd V, TC, N;
Eigen::MatrixXi F,FTC,FN;
igl::readOBJ(argv[1],V,TC,N,F,FTC,FN);
if(FTC.size() == 0)
{
FTC = F;
}
Eigen::MatrixXi U,G,J;
igl::unzip_corners<Eigen::MatrixXi>({F,FTC},U,G,J);
// New mesh vertices and texture coordinates indexed by G
GV = igl::slice(Eigen::MatrixXd(V),U.col(0),1);
GTC = igl::slice(Eigen::MatrixXd(TC),U.col(1),1);