isl-org / Open3D

Open3D: A Modern Library for 3D Data Processing
http://www.open3d.org
Other
10.82k stars 2.24k forks source link

Copy UV coordinates from a reference mesh. #6625

Open ssheorey opened 5 months ago

ssheorey commented 5 months ago

Checklist

Proposed new feature or change

In many mesh processing workflows, UV coordinates are not preserved (e.g. mesh simplification). UV coordinates are required for many downstream tasks. One way to propagate UV coordinates through mesh processing workflows is by copying them from the original mesh. Here is an outline:

  1. Mesh A is processed to mesh B. Mesh A contains UV coordinates (and textures), but mesh B does not have them.
  2. Call meshB.InterpolateTextureCoordinatesFrom(meshA). This does:
    • Create a ray casting scene with mesh A.
    • For each vertex in mesh B, find nearest point in mesh A.
    • Assign UV coordinates of nearest point in mesh A to the vertex in mesh B.
    • Optionally, copy over any textures from mesh B to mesh A.

References

No response

Additional information

It may be necessary to convert from per-triangle UVs to per-vertex UVs (or vice versa). The following code shows an example of how to make that conversion: https://github.com/isl-org/Open3D/blob/main/cpp/open3d/visualization/rendering/filament/TriangleMeshBuffers.cpp#L614

ssheorey commented 5 months ago

Related: #6615

Amandeep4282 commented 4 months ago

Greeting, I am new to contributing to Open Source. I would like to give it a try and try to resolve this issue if I may.

Could you please provide me some brief info about the issue and location of files/folder in which it need to be fixed.

cdbharath commented 3 months ago

I implemented this feature and was testing it. I noticed the following anomaly that I am not sure how to resolve.

To test the code, I performed the following

  1. Load a sphere mesh
  2. Apply FilterSmoothTaubin filter
  3. Use InterpolateTextureCoordinatesFrom to interpolate the UV coordinates to the filtered mesh
  4. Visualize the original and the filtered mesh

The following images visualizes the textured mesh before and after filtering + UV interpolation Before filtering + UV interpolation:

Screenshot

After filtering + UV interpolation:

Screenshot

After filtering and UV interpolation, a single portion of the sphere doesn't have the same texture as the original.

This happens because per-triangle UVs and per-vertex UVs don't map one to one while converting the former to latter. An example is the following texture image from Open3D documentation. The UVs for same mesh vertex could be at the opposite end of the texture image. This results in the entire portion of the image being compressed and assigned to the single stretch of triangles.

Screenshot

How would you suggest I handle this case?

shanagr commented 3 months ago

Disclaimer: I'm new to Open3D as well, so take this as an idea to explore. Someone more experienced can probably help you better.

Assume we have a way to detect if the vertices of a triangle have "crossed the edge and wrapped around". Let, for example, y1 and y2 be two y coordinates in a triangle, and we know y2 has fallen off the edge. Instead of using y1 we can use 1.0 + y1 in our computations (and take the result "modulo" 1.0 in the end once all computations are done). How do we know if something has fallen off the edge? The simplest heuristic I can think of is check if |y1 - y2| > 0.5. If yes, we use 1.0 + min(y1, y2) instead of min(y1, y2).