GeometryCollective / boundary-first-flattening

MIT License
768 stars 96 forks source link

Need ability to map UV faces to the corresponding input faces #60

Closed dnjiang closed 1 year ago

dnjiang commented 4 years ago

There is one to one mapping between an original triangle and an output UV triangle. Either no API is currently provided for this mapping or I do not where to find it.

rohan-sawhney commented 4 years ago

@dnjiang the uvs are stored in the "vt" flag in the obj file

dnjiang commented 4 years ago

Yes, but the vt field is in the UV coordinate space, not in the original XYZ coordinate space. Given a face in the UV space, I need to find the corresponding face in the original XYZ space of the input data. -Thanks

rohan-sawhney commented 4 years ago

Oh, the connectivity of the mesh (i.e., the face indices) is the same in both UV & XYZ space. More concretely, the face indices given by the "f" flag are shared by meshes defined by the "v" flag in XYZ space and "vt" flag in UV space. Let me know if I'm being confusing...

dnjiang commented 4 years ago

Hmm, it seems that is not the case. If that is the case, then the area of the 1st face in the original 3D mesh should be same as the area of the 1st face in the UV mesh. The positions of the two faces are different, but the areas should be the same, correct?

I modified the export function to export UV mesh only. # of "vt" lines in the UV file is NOT same as # of "v" lines in the input .obj file. Yet, # of faces in the original .obj mesh file is same as the # of faces in the UV mesh file. I am confused.

rohan-sawhney commented 4 years ago

This library flattens triangles in XYZ space into UV space by deforming them. The deformation is kind of special - the triangle areas change but the angles/aspect ratios of the triangles remain the same.

dnjiang commented 4 years ago

That is good to know. Are the following true?

Thanks for your help. Excellent piece of software.

rohan-sawhney commented 4 years ago

Hi, sorry for the slow response. Yes, the first point is true. The second one is almost true, due to the numerical nature of the algorithm, some error can creep in which causes the aspect ratios to differ slightly.

keenancrane commented 4 years ago

Hi dnjiang,

Let me clear up some confusion. You can definitely use the output of BFF as you desire. But there are a couple basic things to know.

First, the file does not work the way you think it does. See especially the Wikipedia page on the OBJ file format: https://en.m.wikipedia.org/wiki/Wavefront_.obj_file#File_format

In particular, there is:

The number of vertex and UV coordinates does NOT have to be equal, because multiple triangles can choose to reference the same coordinates. For instance, you could have a mesh

v 0 0 1 v 1 0 1 v 1 1 2 v 0 1 2 vt 0 0 vt 1 0 vt 1 1 vt 2 0 vt 3 0 vt 3 1 f 1/1 2/2 3/3 f 1/4 3/5 4/6

This mesh has two triangles that are connected in 3D, but are disconnected in UV. I would make sure you understand this example (and the OBJ format) before trying to use the output of BFF.

Also, to map a point in a 3D triangle to a point in a UV triangle, you can use a standard idea from computer graphics called “barycentric coordinates”: https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates

This will work perfectly, even of the 3D and UV triangles have different shape/area.

Let’s say your 3D triangle has vertices a,b,c, and your UV triangle has corresponding vertices p,q,r. To map a point x in the 3D triangle to the corresponding point y in the UV triangle, you should first compute the barycentric coordinates

wa = area(b,c,x)/area(a,b,c) wb = area(c,a,x)/area(a,b,c) wc = area(a,b,x)/area(a,b,c)

The point in UV space is then

y = wa p + wb q + wc * r.

(Note by the way that you will have to do this computation for a UV map produced by any library; it is not specific to BFF.)

keenancrane commented 4 years ago

Also, you should NOT be using both the input OBJ file and the output OBJ file simultaneously. Just the output file contains both the 3D and UV coordinates you will need.

JuergenNeubauer commented 3 years ago

So what happens if there is a texture in the original XYZ space of the input file.

It seems the XYZ coordinates of the output file are different from the XYZ coordinates of the input file. I want to map the input texture to the flattened UV coordinates.

Do I have to recalculate the UV texture coordinates of the input file by first calculating the relative position of the input vertices with respect to the output vertices (barycentric coordinates)? Then I would use these relative barycentric coordinates and calculate the coordinate of the input texture?

Thanks.

coreqode commented 2 years ago

@keenancrane @rohan-sawhney After exporing the UV mesh it's vertex correspondences with the input mesh gets changed. Is there any way to find the correspondences between the input mesh and the output uv mesh? I want to use the texture map from the bff while 3D coordinates from the input mesh.

keenancrane commented 2 years ago

Export an ordinary mesh (not a UV mesh) and open it in a text editor. You should see some lines starting with v and others starting with vt. The v lines give the 3D coordinates and the vt lines give the UV coordinates. Now look for lines starting with f. These lines define triangles, and say, for each triangle, which three 3D positions are used, and which three UVs are used. It’s impossible in general to put 3D and UV coordinates in 1:1 correspondence because the mesh needs to be cut open to flatten it. Along the cut you will have only one unique 3D position, but multiple UVs (since the two sides of the cut must show up in different places in the UV domain).

For more information see https://en.m.wikipedia.org/wiki/Wavefront_.obj_file