-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Recently I've bumped into issues trying to display a textured mesh in visualizer. The mesh was comping from a .obj
file produced by MVS-Texturing. The visualized geometry was alright, but the textures were messed up. I remembered that we have a bunch of issues related to this. I did a small research and tried some quick fixes, but the problem turned out to be more complex. I don't have time to address it entirely now, but since I've already invested some time, I decided to summarize my findings for future reference. If someone wants to have this issue fixed and has a reasonable spare time budget, welcome! I will be willing to guide and provide assistance.
Reports
GitHub
Specifically this problem:
- TextureMesh struct needs additional texture index buffer public attribute (TextureMesh struct needs additional texture index buffer public attribute #1592)
- loadOBJFile() cannot load texture (loadOBJFile() cannot load texture #1602)
- Problem in loadOBJFile (Problem in loadOBJFile #1169)
- OBJReader() wrong texture from MTL file (OBJReader() wrong texture from MTL file #1615)
(I will close all of them in favor of this umbrella issue.)
Related:
- Exporting textureMesh (Exporting textureMesh #1966)
Elsewhere
Problem
According to my understanding, the problem is two-fold and needs fixes in multiple PCL modules.
Texture coordinate indices
The first part of the problem has been reported in #1592. In a nutshell, the TextureMesh
class lacks texture coordinates indices and the loader ignores such indices (if they are present in an .obj
file). Refer to the original report for more details.
Hidden assumption in PCLVisualizer::addTextureMesh()
The second part of the problem has to do with how TextureMesh
is displayed with PCLVisualizer
. According to my understanding, the hidden assumption in the code is that there should be one-to-one correspondence between vertices (i.e. points in the TextureMesh.cloud
) and UV coordinates in TextureMesh.tex_coordinates
. This means that same vertex can not have different UV coordinates when it appears in different faces.
Quick hack
A quick and dirty solution (proposed in #1169) is to load the geometry and texture coordinates with loadPolygonFileOBJ
(i.e. VTK-based reader) and materials with loadOBJFile
(i.e. PCL's own loader) and then merge them:
pcl::TextureMesh mesh1;
pcl::io::loadPolygonFileOBJ ("mesh.obj", mesh1);
pcl::TextureMesh mesh2;
pcl::io::loadOBJFile ("mesh.obj", mesh2);
mesh1.tex_materials = mesh2.tex_materials;
pcl::visualization::PCLVisualizer visu("Test");
visu.addTextureMesh (mesh1,"texture");
visu.spin ();
This works for a single material case, but I suspect will fail if there are multiple materials. (But I did not test.) The reason why this works is that the VTK reader duplicates vertices and texture coordinates for each face.
Solution plan
- As proposed in TextureMesh struct needs additional texture index buffer public attribute #1592, introduce texture coordinate indices in
TextureMesh
. - Update the OBJ file loader to populate these indices
- If
.obj
file has texture indices read them; - If
.obj
file does not have texture indices generate sequential indices to mimic current behavior.
- If
- Update
PCLVisualizer
to use the texture coordinate indices. This means that every vertex of every face should be added to thevtkPolyData
points array (duplicating as needed), same with texture coordinates. - (?) Update
TextureMapping
class. I haven't looked into that, but since it producesTextureMesh
objects it probably needs to be updated to populate the newly introduced member field. - (?) Double-check that loaders from other formats (e.g. STL) still produce valid
TextureMesh
es.
To verify the results and avoid regressions, we would also need to collect a set of .obj
files for testing. This should include files produced both by PCL and other software; with and without texture indices; with single and multiple materials.
Ideally, the changes in the loader class should be supported by unit tests (which are currently non-existent).
Another approach
VTK 6.3 has a new vtkOBJImporter
class (merge request) that can handle materials. We could piggy-back on it. However:
- Ubuntu 16.04, which will still be around for a while has VTK 6.2;
- Ubuntu 18.04, which will be released next month, is going to have VTK 6.3, whereas the upstream version is 8.1. The inital version of the importer had numerous bugs that were fixed over time (examine the commit history).