[vtkusers] Setting vtkCamera to custom modelview & volume rendering

Bud Bundy budric at gmail.com
Mon Aug 29 13:45:48 EDT 2016


Sorry to bump my own thread but I still can't get this to work. For 2 
identical cameras in terms of position and projection transform, after 
adjusting the lights (or not) I get 2 different renderings.

The only difference is I apply worldToCamera transform by setting 
camera1->SetModelTransformMatrix(worldToCamera); whereas for camera2 I 
transform the vtkVolume.  In my understanding these should be identical 
in terms of positioning something in camera coordinate system.  But the 
rendering is different (sample attached as volume_vtk_7.0.0.jpg).

Weirdly enough if I render a cube instead of the volume, it works with 
VTK 7.0.0 (attached actor_vtk_7.0.0.jpg).  Same transform, both cameras 
work.  However, then same code rendering the cube doesn't work with 
6.3.0 (attached actor_vtk_6.3.0.jpg).  Not that I need to use 6.3.0.  
But I'm just at my wits end on what to try.

Can someone please have a look at my code and tell me how to get camera1 
to render properly?  Thank you


#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCamera.h>
#include <vtkSphere.h>
#include <vtkSampleFunction.h>
#include <vtkImageShiftScale.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkPiecewiseFunction.h>
#include <vtkVolumeProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkCommand.h>
#include <vtkMatrix4x4.h>
#include <vtkLightCollection.h>
#include <vtkLight.h>
#include <vtkTransform.h>
#include <iostream>

const double objectToWorld[16] = {
     0.976,    0,    0,        -249.511,
     0, -0.976,    0,        249.224,
     0,    0, -2,            -1251.5,
     0,    0,    0,            1 };

const double worldToCamera[16] = {
     -0.965924, 0.00168586, 0.258819,    372.757,
     0.258819, -0.000451724, 0.965926,    1382.12,
     0.00174533, 0.999998, 0,            16.3087,
     0, 0, 0,                            1};

vtkSmartPointer<vtkActor> generateRectangle()
{
     vtkSmartPointer<vtkCubeSource> cubeSource = 
vtkSmartPointer<vtkCubeSource>::New();

     vtkSmartPointer<vtkPolyDataMapper> mapper = 
vtkSmartPointer<vtkPolyDataMapper>::New();
     mapper->SetInputConnection(cubeSource->GetOutputPort());

     vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
     actor->SetMapper(mapper);
     actor->SetScale(512, 512, 160);
     actor->SetPosition(256, 256, 80);
     vtkSmartPointer<vtkTransform> userTransform = 
vtkSmartPointer<vtkTransform>::New();
     userTransform->SetMatrix(objectToWorld);
     actor->SetUserTransform(userTransform);
     return actor;
}

vtkSmartPointer<vtkVolume> generateVolume()
{
     // Create a spherical implicit function.
     vtkSmartPointer<vtkSphere> sphere = vtkSmartPointer<vtkSphere>::New();
     sphere->SetRadius(1);
     sphere->SetCenter(0.0, 0.0, 0.0);

     vtkSmartPointer<vtkSampleFunction> sampleFunction = 
vtkSmartPointer<vtkSampleFunction>::New();
     sampleFunction->SetImplicitFunction(sphere);
     sampleFunction->SetOutputScalarTypeToFloat();
     sampleFunction->SetSampleDimensions(64, 64, 20);
     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();

     vtkSmartPointer<vtkImageData> imageData = 
vtkSmartPointer<vtkImageData>::New();
     imageData->ShallowCopy(t->GetOutput());

     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);

     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);

     volume->SetScale(512, 512, 160);
     volume->SetPosition(256, 256, 80);

     vtkSmartPointer<vtkTransform> userTransform = 
vtkSmartPointer<vtkTransform>::New();
     userTransform->SetMatrix(objectToWorld);
     volume->SetUserTransform(userTransform);
     return volume;
}

void assertArrayEquals(const double * a, const double * b, size_t elements)
{
     for (size_t i = 0; i < elements; ++i)
     {
         assert(a[i] - b[i] <= std::numeric_limits<double>::epsilon());
     }
}

void assertVtkMatrixEquals(const vtkMatrix4x4 * a, const vtkMatrix4x4 * b)
{
     for (size_t i = 0; i < 4; ++i)
     {
         for (size_t j = 0; j < 4; ++j)
         {
             assert(fabs(a->GetElement(i, j) - b->GetElement(i, j)) < 
std::numeric_limits<double>::epsilon());
         }
     }
}

int main()
{
     // camera1
     vtkSmartPointer<vtkCamera> camera1 = vtkSmartPointer<vtkCamera>::New();
     camera1->SetPosition(0, 0, 1000);
     camera1->SetFocalPoint(0, 0, 0);
     camera1->SetViewUp(0, 1, 0);
     camera1->SetClippingRange(0.1, 5000);
     camera1->SetViewAngle(60);
     camera1->SetModelTransformMatrix(worldToCamera);

     //camera 2
     vtkSmartPointer<vtkCamera> camera2 = vtkSmartPointer<vtkCamera>::New();
     camera2->SetPosition(0, 0, 1000);
     camera2->SetFocalPoint(0, 0, 0);
     camera2->SetViewUp(0, 1, 0);
     camera2->SetClippingRange(0.1, 5000);
     camera2->SetViewAngle(60);

     // renderer1 using camera1
     vtkSmartPointer<vtkRenderer> renderer1 = 
vtkSmartPointer<vtkRenderer>::New();
     renderer1->SetViewport(0, 0, 0.5, 1);
     renderer1->SetActiveCamera(camera1);
     //renderer1->AddVolume(generateVolume());
     renderer1->AddActor(generateRectangle());

     // renderer2 using camera2
     vtkSmartPointer<vtkRenderer> renderer2 = 
vtkSmartPointer<vtkRenderer>::New();
     renderer2->SetViewport(0.5, 0, 1, 1);
     vtkSmartPointer<vtkVolume> volume2 = generateVolume();
     vtkSmartPointer<vtkActor> rectangle2 = generateRectangle();
     vtkSmartPointer<vtkTransform> objectToCameraTransform = 
vtkSmartPointer<vtkTransform>::New();
     // Generate transform (worldToCamera * objectToWorld) and apply it 
to the model
     objectToCameraTransform->SetMatrix(objectToWorld);
     objectToCameraTransform->PostMultiply();
     objectToCameraTransform->Concatenate(worldToCamera);
     objectToCameraTransform->Update();
     volume2->SetUserTransform(objectToCameraTransform);
     rectangle2->SetUserTransform(objectToCameraTransform);
     renderer2->SetActiveCamera(camera2);
     //renderer2->AddVolume(volume2);
     renderer2->AddActor(rectangle2);

     // window and interactor
     vtkSmartPointer<vtkRenderWindow> renderWindow = 
vtkSmartPointer<vtkRenderWindow>::New();
     renderWindow->SetSize(1024, 512);
     renderWindow->AddRenderer(renderer1);
     renderWindow->AddRenderer(renderer2);
     vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = 
vtkSmartPointer<vtkRenderWindowInteractor>::New();
     renderWindowInteractor->SetRenderWindow(renderWindow);

     // Attempt to Adjust lights
     renderWindow->Render();
     vtkLight * modifiedLight = dynamic_cast<vtkLight 
*>(renderer1->GetLights()->GetItemAsObject(0));
     modifiedLight->SetLightTypeToHeadlight();
     modifiedLight->SetPosition(camera1->GetPosition());
     modifiedLight->SetFocalPoint(camera1->GetFocalPoint());
     // Above Doesn't work, Ok let's try this as well
     renderer1->UpdateLightsGeometryToFollowCamera();

     // Sanity check
     assertArrayEquals(camera1->GetPosition(), camera2->GetPosition(), 3);
     assertArrayEquals(camera1->GetFocalPoint(), 
camera2->GetFocalPoint(), 3);
assertVtkMatrixEquals(camera1->GetProjectionTransformMatrix(renderer1), 
camera2->GetProjectionTransformMatrix(renderer2));
     vtkSmartPointer<vtkLightCollection> lightCollection1 = 
renderer1->GetLights();
     vtkSmartPointer<vtkLightCollection> lightCollection2 = 
renderer2->GetLights();
     assert(lightCollection1->GetNumberOfItems() == 
lightCollection2->GetNumberOfItems());
     lightCollection1->InitTraversal();
     lightCollection2->InitTraversal();
     vtkSmartPointer<vtkLight> light1 = lightCollection1->GetNextItem();
     vtkSmartPointer<vtkLight> light2 = lightCollection2->GetNextItem();
     assertArrayEquals(light1->GetPosition(), light2->GetPosition(), 3);
     assertArrayEquals(light1->GetTransformedPosition(), 
light2->GetTransformedPosition(), 3);
     assertArrayEquals(light1->GetFocalPoint(), light2->GetFocalPoint(), 3);
     assertArrayEquals(light1->GetTransformedFocalPoint(), 
light1->GetTransformedFocalPoint(), 3);
     assertArrayEquals(light1->GetAmbientColor(), 
light2->GetAmbientColor(), 3);
     assertArrayEquals(light1->GetSpecularColor(), 
light2->GetSpecularColor(), 3);
     assertArrayEquals(light1->GetDiffuseColor(), 
light2->GetDiffuseColor(), 3);

     renderWindow->Render();
     renderWindowInteractor->Start();

     return EXIT_SUCCESS;
}


On 08/05/2016 03:10 PM, Bud Bundy wrote:
>
> Thanks,
>
> The light positions were indeed different, but making them the same 
> didn't fix it for me.  Perhaps my fix is wrong?
>
> void assertArrayEquals(const double * a, const double * b, size_t 
> elements)
> {
>     for (size_t i = 0; i < elements; ++i)
>     {
>         assert(a[i] - b[i] <= std::numeric_limits<double>::epsilon());
>     }
> }
>
>     //previous int main() code ...
>
>     //setting lights before first call to Render() crashes program, 
> also describedh http://www.vtk.org/Wiki/VTK/Examples/Cxx/Lighting/Light
>
>     renderWindow->Render();
>
>     renderer2->RemoveAllLights();
>     vtkSmartPointer<vtkLight> newLight = vtkSmartPointer<vtkLight>::New();
>     newLight->SetPosition(0, 0, 1000);
>     renderer2->AddLight(newLight);
>
>     //assert lighting is the same
>     vtkSmartPointer<vtkLightCollection> lightCollection1 = 
> renderer1->GetLights();
>     vtkSmartPointer<vtkLightCollection> lightCollection2 = 
> renderer2->GetLights();
>     assert(lightCollection1->GetNumberOfItems() == 
> lightCollection2->GetNumberOfItems());
>     lightCollection1->InitTraversal();
>     lightCollection2->InitTraversal();
>     vtkSmartPointer<vtkLight> light1 = lightCollection1->GetNextItem();
>     vtkSmartPointer<vtkLight> light2 = lightCollection2->GetNextItem();
>     assertArrayEquals(light1->GetPosition(), light2->GetPosition(), 3);
>     assertArrayEquals(light1->GetTransformedPosition(), 
> light2->GetTransformedPosition(), 3);
>     assertArrayEquals(light1->GetFocalPoint(), 
> light2->GetFocalPoint(), 3);
>     assertArrayEquals(light1->GetTransformedFocalPoint(), 
> light1->GetTransformedFocalPoint(), 3);
>     assertArrayEquals(light1->GetAmbientColor(), 
> light2->GetAmbientColor(), 3);
>     assertArrayEquals(light1->GetSpecularColor(), 
> light2->GetSpecularColor(), 3);
>     assertArrayEquals(light1->GetDiffuseColor(), 
> light2->GetDiffuseColor(), 3);
>
>     renderWindow->Render();
>
>     renderWindowInteractor->Start();
>
>
> On 08/05/16 14:10, David E DeMarle wrote:
>>
>> I was just doing a very similar thing and noticed that light 
>> positions are only updated with the set origin, focal point and up. I 
>> ended up computing those for my intended matrix and lighting then 
>> worked as expected.
>>
>>
>> On Aug 5, 2016 1:12 PM, "Bud Bundy" <budric at gmail.com 
>> <mailto:budric at gmail.com>> wrote:
>>
>>     Hi,
>>
>>     I need to setup the camera to an arbitrary modelview matrix I
>>     have in memory.  I managed to get some code working such that
>>     GetModelViewTransformMatrix() returns the modelview I have/want.
>>     However the volume rendering is sometimes blank, and I don't
>>     understand why because the volume is in front of the camera.  I
>>     managed to boil down the problem to the following code below.
>>     camera1 and camera2 have the same modelview transform, however
>>     the rendering look very different (I've attached a screen shot) -
>>     though not blank it's a lot dimmer.
>>
>>     The code is loosely based on:
>>     http://www.vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/SmartVolumeMapper
>>     <http://www.vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/SmartVolumeMapper>
>>
>>     I'm using VTK 7.0
>>
>>     #include <vtkActor.h>
>>     #include <vtkSmartPointer.h>
>>     #include <vtkCubeSource.h>
>>     #include <vtkPolyDataMapper.h>
>>     #include <vtkRenderWindow.h>
>>     #include <vtkRenderer.h>
>>     #include <vtkRenderWindowInteractor.h>
>>     #include <vtkCamera.h>
>>     #include <vtkSphere.h>
>>     #include <vtkSampleFunction.h>
>>     #include <vtkImageShiftScale.h>
>>     #include <vtkImageData.h>
>>     #include <vtkPointData.h>
>>     #include <vtkSmartVolumeMapper.h>
>>     #include <vtkPiecewiseFunction.h>
>>     #include <vtkVolumeProperty.h>
>>     #include <vtkColorTransferFunction.h>
>>     #include <vtkCommand.h>
>>     #include <vtkMatrix4x4.h>
>>
>>     vtkSmartPointer<vtkVolume> generateVolume()
>>     {
>>         // Create a spherical implicit function.
>>         vtkSmartPointer<vtkSphere> sphere =
>>     vtkSmartPointer<vtkSphere>::New();
>>         sphere->SetRadius(0.1);
>>         sphere->SetCenter(0.0, 0.0, 0.0);
>>
>>         vtkSmartPointer<vtkSampleFunction> sampleFunction =
>>     vtkSmartPointer<vtkSampleFunction>::New();
>>         sampleFunction->SetImplicitFunction(sphere);
>>         sampleFunction->SetOutputScalarTypeToFloat();
>>         sampleFunction->SetSampleDimensions(64, 64, 20);
>>         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();
>>
>>         vtkSmartPointer<vtkImageData> imageData =
>>     vtkSmartPointer<vtkImageData>::New();
>>         imageData->ShallowCopy(t->GetOutput());
>>
>>         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);
>>
>>         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);
>>
>>         vtkSmartPointer<vtkMatrix4x4> volumeScaleTransform =
>>     vtkSmartPointer<vtkMatrix4x4>::New();
>>         volumeScaleTransform->Identity();
>>         volumeScaleTransform->SetElement(0, 0, 512);
>>         volumeScaleTransform->SetElement(1, 1, 512);
>>         volumeScaleTransform->SetElement(2, 2, 160);
>>         volume->SetUserMatrix(volumeScaleTransform);
>>         return volume;
>>     }
>>
>>     int main()
>>     {
>>         // camera1
>>         vtkSmartPointer<vtkCamera> camera1 =
>>     vtkSmartPointer<vtkCamera>::New();
>>         camera1->SetPosition(0, 0, 1000);
>>         camera1->SetFocalPoint(0, 0, 0);
>>         camera1->SetClippingRange(0.1, 5000);
>>         camera1->SetViewAngle(60);
>>
>>         //camera 2
>>         vtkSmartPointer<vtkCamera> camera2 =
>>     vtkSmartPointer<vtkCamera>::New();
>>         camera2->SetPosition(0, 0, 0);            //I do not want any
>>     additional translation that comes with default (0,0,1) setting.
>>         camera2->SetFocalPoint(0, 0, -1);       //setting this to
>>     (0,0,0) causes whole modelview matrix to be 0, regardless of what
>>     SetModelTransformMatrix() sets
>>         camera2->SetViewAngle(60);
>>         camera2->SetClippingRange(0.1, 5000);
>>         double modelViewTransform[16] = { 1, 0, 0, 0,
>>             0, 1, 0, 0,
>>             0, 0, 1, -1000,
>>             0, 0, 0, 1 };
>>         camera2->SetModelTransformMatrix(modelViewTransform);
>>
>>         // renderer1 using camera1
>>         vtkSmartPointer<vtkRenderer> renderer1 =
>>     vtkSmartPointer<vtkRenderer>::New();
>>         renderer1->SetViewport(0, 0, 0.5, 1);
>>         renderer1->AddVolume(generateVolume());
>>         renderer1->SetActiveCamera(camera1);
>>
>>         // renderer2 using camera2
>>         vtkSmartPointer<vtkRenderer> renderer2 =
>>     vtkSmartPointer<vtkRenderer>::New();
>>         renderer2->SetViewport(0.5, 0, 1, 1);
>>         renderer2->AddVolume(generateVolume());
>>         renderer2->SetActiveCamera(camera2);
>>
>>         // assert model view matrices are the same
>>         vtkSmartPointer<vtkMatrix4x4> vtkModelViewMatrix1 =
>>     renderer1->GetActiveCamera()->GetModelViewTransformMatrix();
>>         vtkSmartPointer<vtkMatrix4x4> vtkModelViewMatrix2 =
>>     renderer2->GetActiveCamera()->GetModelViewTransformMatrix();
>>         for (int i = 0; i < 4; ++i)
>>             for (int j = 0; j < 4; ++j)
>>                 assert(vtkModelViewMatrix1->GetElement(i, j) ==
>>     vtkModelViewMatrix2->GetElement(i, j));
>>
>>         // window and interactor
>>         vtkSmartPointer<vtkRenderWindow> renderWindow =
>>     vtkSmartPointer<vtkRenderWindow>::New();
>>         renderWindow->SetSize(1024, 512);
>>         renderWindow->AddRenderer(renderer1);
>>         renderWindow->AddRenderer(renderer2);
>>         vtkSmartPointer<vtkRenderWindowInteractor>
>>     renderWindowInteractor =
>>     vtkSmartPointer<vtkRenderWindowInteractor>::New();
>>         renderWindowInteractor->SetRenderWindow(renderWindow);
>>
>>         renderWindow->Render();
>>         renderWindowInteractor->Start();
>>
>>         return EXIT_SUCCESS;
>>     }
>>
>>
>>     Thank you very much.
>>
>>
>>     _______________________________________________
>>     Powered by www.kitware.com <http://www.kitware.com>
>>
>>     Visit other Kitware open-source projects at
>>     http://www.kitware.com/opensource/opensource.html
>>     <http://www.kitware.com/opensource/opensource.html>
>>
>>     Please keep messages on-topic and check the VTK FAQ at:
>>     http://www.vtk.org/Wiki/VTK_FAQ <http://www.vtk.org/Wiki/VTK_FAQ>
>>
>>     Search the list archives at:
>>     http://markmail.org/search/?q=vtkusers
>>     <http://markmail.org/search/?q=vtkusers>
>>
>>     Follow this link to subscribe/unsubscribe:
>>     http://public.kitware.com/mailman/listinfo/vtkusers
>>     <http://public.kitware.com/mailman/listinfo/vtkusers>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160829/7e32ae59/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: actor_vtk_6.3.0.jpg
Type: image/jpeg
Size: 16768 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160829/7e32ae59/attachment.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: actor_vtk_7.0.0.jpg
Type: image/jpeg
Size: 20036 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160829/7e32ae59/attachment-0001.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: volume_vtk_7.0.0.jpg
Type: image/jpeg
Size: 20428 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160829/7e32ae59/attachment-0002.jpg>


More information about the vtkusers mailing list