Single Azimuthal Segment Texture Distortion for Earth TextureMaptoSphere

Background & Issue

High-resolution images of the Earth are readily available [1,2]. If these are reversed horizontally, they can be directly used with the TextureMaptoSphere filter applied to a sphere source.

When mapping the texture to a sphere source, the texture maps very well; however, one of the azimuthal segments contains a reversed and distorted version of the image. The effect can be minimized, but not eliminated, by increasing the theta resolution of the sphere that the texture is applied to. Please see the figures below for varying theta resolutions demonstrating the distortion and mitigation.

Questions

  1. Is there a way to overcome this distortion? Using the “prevent seam” option in the TextureMaptoSphere filter prevents a seam but distorts the remainder of the texture by mirroring it.

  2. Alternatively, could there be an off-by-one error in the mapping algorithm? The 720-segment theta resolution case is nearly perfect except for this one segment. If it were eliminated, the fitment would be virtually seamless.

  3. As an aside: is there a reason for the need to horizontally reverse the texture before it is applied? Can/should an obvious GUI control be added to perform this transformation for the texture? Note that modifying the “Transforming” settings permit this type of manipulation, but the correct parameters are non-obvious without a good understanding of coordinate transform techniques.

Figures

theta resolution = 4

theta resolution = 12

theta resolution = 24

theta resolution = 720

References

  1. https://www.solarsystemscope.com/textures/
  2. https://www.solarsystemscope.com/textures/download/2k_earth_daymap.jpg

What is happening is that the sphere texture coordinates increase monotonically from 0.0 to 1.0 longitudinally as you circle around the sphere until that last segment where the texture coordinates go from 1.0 to 0.0 from the last meridian to the first meridian. To handle the texture mapping properly for this use case, the sphere should be be split where the texture coordinate is 0.0 and the points should be duplicated there with texture coordinate 1.0. This would prevent the mirroring you see.

For most cases, we probably don’t want the sphere to have this split. Rather than add an option to the sphere source, though, it might be better to provide a new “Globe” source that generates geometry this way, perhaps with the new Python Algorithm plugin capability coming to ParaView 5.6.

The reason you have to flip the texture is just a mismatch in conventions of how the image is stored and how the texture coordinates are applied to the sphere source. Of course it would be possible to add basic transforms for texture images, but it might be better to instead allow pipeline objects to be used as texture images. Then you could transform the images in arbitrary ways using the ParaView image filters.

@cory.quammen, This sounds like something I could implement in PVGeo! Could you give me some more details on how exactly we want to split the sphere?

By the way, the texture map being reversed was written up in gitlab here: https://gitlab.kitware.com/paraview/paraview/issues/10404

2 Likes

Quick Fix

FYI, a quick fix to the seam issue: just set the Start Theta to a small nonzero value such as 0.0001:

Note: my texture is inverted but the seam looks pretty good

vs.

Python Plugin

This would be incredibly easy/simple to implement as a Python plugin that would handle this by default. Not sure if this is the solution you are looking for though.

FYI, a quick fix to the seam issue: just set the Start Theta to a small nonzero value such as 0.0001

For my purposes, that is a perfectly acceptable solution. Thanks!

1 Like

@banesullivan Here’s a little graphic to show what I mean using a circle in place of a sphere. The current situation is on the left, where you have four points defining the sphere and each has a unique texture coordinate. The texture flipping occurs between 0.75 and 0.0 because the texture coordinate is linearly interpolated from 0.75 to 0.0 in this section.

What you need to do to get the texturing right in all cases is shown on the right. Add a duplicate point at the bottom, and assign its texture coordinate to 1.0. On a sphere, you would need to duplicate the points on a meridian in the same way (hopefully I am using the right term) with texture coordinates set to 1.0. This adds a seam to the mesh, so it is no longer water tight, but it will texture correctly.

Ahh, I okay! I will see if I can manually create a sphere in this manner (Python/NumPy), go ahead and add the texture coordinates in the proper/transposed mode, and make a vtkPolyData object which I will wrap up in a Python Algorithm plugin.

Just to be clear, the duplicated points do indeed have the same coordinates?

Yes, they will have the same XYZ coordinates, just different texture coordinates.

1 Like

Made a rather simple implementation of the GlobeSource in PVGeo which goes ahead and adds texture coordinates that make sense for the outside surface of a sphere and can be easily tweaked to provide desired effects. The code can be found here and the wrappings for ParaView can be found here.

Here is an interactive example of the sphere it produces.

And below is a screenshot of what this looks like in ParaView. Note that I added some sliders to control the resolution of the parallels and meridians. I gave it default values that make sense for the Earth. The texture applied is the same JPEG that @jkulesza posted above and was loaded with no transformations.

Nice job, @banesullivan!

1 Like

Bane, your plugin looks great. However I get an error when I try to load it through the plugin manager. I am able to load the sample Python plugin ( “PythonAlgorithmExamples.py”), but when I try to load “PVGeo_Model_Builder.py”, I get this error message in the Output messages (ParaView 5.7.0 on MacOS 10.15.1):

Generic Warning: In /Users/kitware/dashboards/buildbot-slave/a64f5607/build/superbuild/paraview/src/ParaViewCore/PythonAlgorithm/vtkPVPythonAlgorithmPlugin.cxx, line 185
Failed to load Python plugin:
Failed to call `paraview.detail.pythonalgorithm.load_plugin`.

Traceback (most recent call last):
  File "/Applications/ParaView-5.7.0.app/Contents/Python/paraview/detail/pythonalgorithm.py", line 513, in load_plugin
    module = imp.load_source(modulename, filepath)
  File "/Users/shermanw/Work/Geology/PVGeo_Model_Builder.py", line 7, in <module>
    from PVGeo.model_build import (CreateEvenRectilinearGrid, CreateTensorMesh,
ImportError: No module named PVGeo.model_build
ERROR: In /Users/kitware/dashboards/buildbot-slave/a64f5607/build/superbuild/paraview/src/ParaViewCore/ClientServerCore/Core/vtkPVPluginLoader.cxx, line 417
vtkPVPluginLoader (0x60000ae99080): dlopen(/Users/shermanw/Work/Geology/PVGeo_Model_Builder.py, 1): no suitable image found.  Did find:
	/Users/shermanw/Work/Geology/PVGeo_Model_Builder.py: unknown file type, first eight bytes: 0x70 0x61 0x72 0x61 0x76 0x69 0x65 0x77
	/Users/shermanw/Work/Geology/PVGeo_Model_Builder.py: unknown file type, first eight bytes: 0x70 0x61 0x72 0x61 0x76 0x69 0x65 0x77

And I get a similar message when I try to load “earth.py” as a plugin. (Also, I’m a bit confused as to how the two files should be loaded as a single plugin.)

I know this thread is from a year ago, but I hope it might catch someone’s eye.

Thanks,
Bill