Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when mouse panning volume rendering looks weird #5965

Open
ahaldane opened this issue Apr 24, 2024 · 3 comments
Open

when mouse panning volume rendering looks weird #5965

ahaldane opened this issue Apr 24, 2024 · 3 comments
Labels
bug Uh-oh! Something isn't working as expected.

Comments

@ahaldane
Copy link

Describe the bug, what's wrong, and what you expected.

When running the volume rendering examples (for instance, the iron protein example, when I try to pan with the mouse the render looks wrong. When I release the mouse button, it re-renders and looks correct. See screenshots below.

This may be the same bug as #5298, but I can't see the screenshots in that issue so can't verify. Also, that issue was in windows, but I am in linux and I can do debugging if you have any hints/pointers.

As initial debugging, I followed the suggestion in #5298 of looking in paraview. I saved the dataset to data.vtk as in the last line in the code shown in "steps" below, and then opened in in paraview. When I pan the mouse in paraview, in looks "correct" (no panning bug).

Other info:

  • The weird panning happens in both python console (in terminal), and in a jupyter notebook
  • When I use the "interactive scene" link in the iron protein example website above, it looks "correct" even when panning (the bug is gone on the website version).

Steps to reproduce the bug.

from pyvista import examples
dataset = examples.download_iron_protein()
dataset.plot(volume=True, cmap='Blues')

dataset.save('data.vtk')

System Information

--------------------------------------------------------------------------------
  Date: Wed Apr 24 14:36:09 2024 EDT

                  OS : Linux
              CPU(s) : 8
             Machine : x86_64
        Architecture : 64bit
                 RAM : 15.4 GiB
         Environment : IPython
         File system : ext4
         GPU Details : error
    MathText Support : False

  Python 3.11.8 (main, Feb 12 2024, 14:50:05) [GCC 13.2.1 20230801]

             pyvista : 0.43.5
                 vtk : 9.3.0
               numpy : 1.26.4
          matplotlib : 3.8.3
              scooby : 0.9.2
               pooch : 1.8.1
              pillow : 10.2.0
               PyQt5 : 5.15.10
             IPython : 8.22.2
          ipywidgets : 8.1.2
               scipy : 1.13.0
          jupyterlab : 4.1.6
               trame : 3.6.0
        trame_client : 3.0.2
        trame_server : 3.0.0
           trame_vtk : 2.8.6
       trame_vuetify : 2.4.3
jupyter_server_proxy : 4.1.2
        nest_asyncio : 1.6.0
--------------------------------------------------------------------------------

Screenshots

view when not panning:
pyvista_static

view when panning with mouse:
pyvista_interactive

@ahaldane ahaldane added the bug Uh-oh! Something isn't working as expected. label Apr 24, 2024
@ahaldane
Copy link
Author

ahaldane commented Apr 25, 2024

Further debugging:

I found the vtk code in python to do approximately the equivalent as the example (folded below).

When I run the pure-vtk example, overall I don't see the artifact from pyvista from the second screenshot above, at least to anywhere the same degree. However if I look very closely I can see a slight moire effect reminiscent of the artifacts seen in pyvista above, which disappears when I release the mouse.

This makes me think that during mouse panning, VTK is using some rendering approximations causing the artifacts. However in plain vtk the default settings make the approximations very small, but in pyvista the approximations are large.

So my hunch is that solving this problem boils down to finding the setting in pyvista controlling the approximations to volume rendering during panning, and turn it down.

python vtk code for volume rendering
#!/usr/bin/env python

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonDataModel import vtkPiecewiseFunction
from vtkmodules.vtkIOLegacy import vtkStructuredPointsReader
from vtkmodules.vtkRenderingCore import (
    vtkColorTransferFunction,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer,
    vtkVolume,
    vtkVolumeProperty
)
from vtkmodules.vtkRenderingVolume import vtkFixedPointVolumeRayCastMapper
# noinspection PyUnresolvedReferences
from vtkmodules.vtkRenderingVolumeOpenGL2 import vtkOpenGLRayCastImageDisplayHelper
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera

def main():
    fileName = 'ironProt.vtk'
    colors = vtkNamedColors()

    # Create the standard renderer, render window
    # and interactor.
    ren1 = vtkRenderer()

    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren1)

    iren = vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    style = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(style)

    # Create the reader for the data.
    reader = vtkStructuredPointsReader()
    reader.SetFileName(fileName)

    # Create transfer mapping scalar value to opacity.
    opacityTransferFunction = vtkPiecewiseFunction()
    opacityTransferFunction.AddPoint(20, 0.0)
    opacityTransferFunction.AddPoint(255, 0.2)

    # Create transfer mapping scalar value to color.
    colorTransferFunction = vtkColorTransferFunction()
    colorTransferFunction.AddRGBPoint(0.0, 1.0, 1.0, 1.0)
    colorTransferFunction.AddRGBPoint(255.0, 0.0, 0.0, 1.0)

    # The property describes how the data will look.
    volumeProperty = vtkVolumeProperty()
    volumeProperty.SetColor(colorTransferFunction)
    volumeProperty.SetScalarOpacity(opacityTransferFunction)
    volumeProperty.ShadeOn()
    volumeProperty.SetInterpolationTypeToLinear()

    # The mapper / ray cast function know how to render the data.
    volumeMapper = vtkFixedPointVolumeRayCastMapper()
    volumeMapper.SetInputConnection(reader.GetOutputPort())

    # The volume holds the mapper and the property and
    # can be used to position/orient the volume.
    volume = vtkVolume()
    volume.SetMapper(volumeMapper)
    volume.SetProperty(volumeProperty)

    ren1.AddVolume(volume)
    ren1.SetBackground(colors.GetColor3d('white'))
    ren1.GetActiveCamera().Azimuth(45)
    ren1.GetActiveCamera().Elevation(30)
    ren1.ResetCameraClippingRange()
    ren1.ResetCamera()

    renWin.SetSize(600, 600)
    renWin.SetWindowName('SimpleRayCast')
    renWin.Render()

    iren.Start()

if __name__ == '__main__':
    main()

@ahaldane
Copy link
Author

ahaldane commented Apr 25, 2024

OK, I've pretty much solved the issue: It is because pyvista sets the default update rate to 30, different from the vtk default of 0.0001. Feel free to close this issue, unless you want to consider changing the default.

I can reset the rate to a lower value in pyvista as follows:

import pyvista as pv

dataset = pv.examples.download_iron_protein()

pl = pv.Plotter()
print(pl.ren_win.GetDesiredUpdateRate())  # prints 0.0001, but somehow this gets reset to 30 by pyvista
pl.ren_win.SetDesiredUpdateRate(0.0)      # this allows full computation per frame
pl.add_volume(dataset, opacity='linear', cmap='Blues')  
pl.show()

Then the plot "looks good" even when panning.

The print statement there says the initial default is 0.0001, same as in my vtk code, which confused me. But actually, pyvista later resets it to 30.

@ahaldane
Copy link
Author

ahaldane commented Apr 26, 2024

Sorry for noise, but an update: The previous comment is not right, the problem still exists.

I got myself confused above, here is the real situation:

  1. When I use dataset.plot(volume=True), then the default update rate is set to 30, making the artifact really big as in my initial screenshot.
  2. When I use pl.add_volume(dataset) with pl = pv.pPlotter() as in my last comment, then the default update rate is left at vtk's default of 0.0001. My command pl.ren_win.SetDesiredUpdateRate(0.0) actually had almost no effect. (0.0001 vs 0.0 gives the same result, I tested). While this greatly reduces the artifact compared to dataset.plot, the artifact is still much larger than in pure vtk.

So in summary, while I found a way to greatly reduce the artifact, it is still much larger than I get in pure vtk. There must be another LOD setting to tweak somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Uh-oh! Something isn't working as expected.
Projects
None yet
Development

No branches or pull requests

1 participant