[vtkusers] vtkSmartVolumeMapper doesn't properly handle input changes

Marc Ruiz Altisent marc.ruiz+vtk at gmail.com
Mon May 28 07:55:09 EDT 2018


Should I create a new issue for this in the bug tracker?

Missatge de Marc Ruiz Altisent <marc.ruiz+vtk at gmail.com> del dia dc., 23 de
maig 2018 a les 19:29:

> Hi everyone,
>
> I have found an issue with vtkSmartVolumeMapper. If you create several
> vtkImageData objects, set one of them as the input of the mapper and
> render, then you won't be able to render one of the others at a later time:
> if you set one of the others as input the mapper will keep rendering the
> first one.
>
> The issue is in the method vtkSmartVolumeMapper::ConnectMapperInput. It
> doesn't pass the original input to its internal mapper, but a shallow copy
> of it. The first time it will always perform the shallow copy, but
> afterwards it will only do it if the new input has been modified after
> creating the previous shallow copy, which is not always the case (e.g. if
> you create all the data before the first render).
>
> Possible workarounds are to call Modified() on the input data when setting
> a new one or to create a new mapper each time.
>
> Below is a sample program (adapted from a couple of examples) to proof the
> issue. Pressing 1 or 2 alternates between 2 datasets but only the first one
> is always rendered. Uncommenting the 2 Modified() calls makes it work as
> expected.
>
> #include <vtkSmartPointer.h>
> #include <vtkSphere.h>
> #include <vtkBox.h>
> #include <vtkSampleFunction.h>
> #include <vtkSmartVolumeMapper.h>
> #include <vtkColorTransferFunction.h>
> #include <vtkPiecewiseFunction.h>
> #include <vtkRenderer.h>
> #include <vtkRenderWindow.h>
> #include <vtkRenderWindowInteractor.h>
> #include <vtkVolumeProperty.h>
> #include <vtkCamera.h>
> #include <vtkImageShiftScale.h>
> #include <vtkImageData.h>
> #include <vtkPointData.h>
> #include <vtkDataArray.h>
> #include <vtkInteractorStyleTrackballCamera.h>
> #include <vtkObjectFactory.h>
>
> // Define interaction style
> class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
> {
>   public:
>     static KeyPressInteractorStyle* New();
>     vtkTypeMacro(KeyPressInteractorStyle,
> vtkInteractorStyleTrackballCamera);
>
>     virtual void OnKeyPress()
>     {
>       // Get the keypress
>       vtkRenderWindowInteractor *rwi = this->Interactor;
>       std::string key = rwi->GetKeySym();
>
>       if(key == "1")
>       {
>         mapper->SetInputData(imageData1);
>         //imageData1->Modified();
>         rwi->Render();
>       }
>       else if(key == "2")
>       {
>         mapper->SetInputData(imageData2);
>         //imageData2->Modified();
>         rwi->Render();
>       }
>
>       // Forward events
>       vtkInteractorStyleTrackballCamera::OnKeyPress();
>     }
>     vtkSmartPointer<vtkVolumeMapper> mapper;
>     vtkSmartPointer<vtkImageData> imageData1, imageData2;
> };
> vtkStandardNewMacro(KeyPressInteractorStyle);
>
> static void CreateImageData(vtkImageData* im, bool);
>
> int main(int argc, char *argv[])
> {
>   vtkSmartPointer<vtkImageData> imageData =
>     vtkSmartPointer<vtkImageData>::New();
>   vtkSmartPointer<vtkImageData> imageData2 =
>     vtkSmartPointer<vtkImageData>::New();
>
>   CreateImageData(imageData, true);
>   CreateImageData(imageData2, false);
>
>   vtkSmartPointer<vtkRenderWindow> renWin =
>     vtkSmartPointer<vtkRenderWindow>::New();
>   vtkSmartPointer<vtkRenderer> ren1 =
>     vtkSmartPointer<vtkRenderer>::New();
>   ren1->SetBackground(0.1,0.4,0.2);
>
>   renWin->AddRenderer(ren1);
>
>   renWin->SetSize(301,300); // intentional odd and NPOT  width/height
>
>   vtkSmartPointer<vtkRenderWindowInteractor> iren =
>     vtkSmartPointer<vtkRenderWindowInteractor>::New();
>   iren->SetRenderWindow(renWin);
>
>   vtkSmartPointer<KeyPressInteractorStyle> style =
>     vtkSmartPointer<KeyPressInteractorStyle>::New();
>   iren->SetInteractorStyle(style);
>   style->SetCurrentRenderer(ren1);
>
>   renWin->Render(); // make sure we have an OpenGL context.
>
>   vtkSmartPointer<vtkSmartVolumeMapper> volumeMapper =
>     vtkSmartPointer<vtkSmartVolumeMapper>::New();
>   volumeMapper->SetBlendModeToComposite(); // composite first
>   volumeMapper->SetInputData(imageData);
>   vtkSmartPointer<vtkVolumeProperty> volumeProperty =
>     vtkSmartPointer<vtkVolumeProperty>::New();
>   volumeProperty->ShadeOff();
>   volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
>
>   style->mapper = volumeMapper;
>   style->imageData1 = imageData;
>   style->imageData2 = imageData2;
>
>   vtkSmartPointer<vtkPiecewiseFunction> compositeOpacity =
>     vtkSmartPointer<vtkPiecewiseFunction>::New();
>   compositeOpacity->AddPoint(0.0,0.0);
>   compositeOpacity->AddPoint(80.0,1.0);
>   compositeOpacity->AddPoint(80.1,0.0);
>   compositeOpacity->AddPoint(255.0,0.0);
>   volumeProperty->SetScalarOpacity(compositeOpacity); // composite first.
>
>   vtkSmartPointer<vtkColorTransferFunction> color =
>     vtkSmartPointer<vtkColorTransferFunction>::New();
>   color->AddRGBPoint(0.0  ,0.0,0.0,1.0);
>   color->AddRGBPoint(40.0  ,1.0,0.0,0.0);
>   color->AddRGBPoint(255.0,1.0,1.0,1.0);
>   volumeProperty->SetColor(color);
>
>   vtkSmartPointer<vtkVolume> volume =
>     vtkSmartPointer<vtkVolume>::New();
>   volume->SetMapper(volumeMapper);
>   volume->SetProperty(volumeProperty);
>   ren1->AddViewProp(volume);
>   ren1->ResetCamera();
>
>   // Render composite. In default mode. For coverage.
>   renWin->Render();
>
>   iren->Start();
>
>   return EXIT_SUCCESS;
> }
>
> void CreateImageData(vtkImageData* imageData, bool spherical)
> {
>   vtkSmartPointer<vtkImplicitFunction> implicitFunction;
>
>   if (spherical)
>   {
>     vtkSmartPointer<vtkSphere> sphere =
>       vtkSmartPointer<vtkSphere>::New();
>     sphere->SetRadius(0.1);
>     sphere->SetCenter(0.0,0.0,0.0);
>     implicitFunction = sphere;
>   }
>   else
>   {
>     vtkSmartPointer<vtkBox> box =
>       vtkSmartPointer<vtkBox>::New();
>     box->SetBounds(-0.1, 0.1, -0.1, 0.1, -0.1, 0.1);
>     implicitFunction = box;
>   }
>
>   vtkSmartPointer<vtkSampleFunction> sampleFunction =
>     vtkSmartPointer<vtkSampleFunction>::New();
>   sampleFunction->SetImplicitFunction(implicitFunction);
>   sampleFunction->SetOutputScalarTypeToDouble();
>   sampleFunction->SetSampleDimensions(127,127,127); // intentional NPOT
> dimensions.
>   sampleFunction->SetModelBounds(-1.0,1.0,-1.0,1.0,-1.0,1.0);
>   sampleFunction->SetCapping(false);
>   sampleFunction->SetComputeNormals(false);
>   sampleFunction->SetScalarArrayName("values");
>   sampleFunction->Update();
>
>   vtkDataArray* a =
> sampleFunction->GetOutput()->GetPointData()->GetScalars("values");
>   double range[2];
>   a->GetRange(range);
>
>   vtkSmartPointer<vtkImageShiftScale> t =
>     vtkSmartPointer<vtkImageShiftScale>::New();
>   t->SetInputConnection(sampleFunction->GetOutputPort());
>
>   t->SetShift(-range[0]);
>   double magnitude=range[1]-range[0];
>   if(magnitude==0.0)
>   {
>     magnitude=1.0;
>   }
>   t->SetScale(255.0/magnitude);
>   t->SetOutputScalarTypeToUnsignedChar();
>
>   t->Update();
>
>   imageData->ShallowCopy(t->GetOutput());
> }
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://vtk.org/pipermail/vtkusers/attachments/20180528/ed96be2b/attachment.html>


More information about the vtkusers mailing list