[vtkusers] Setting vtkCamera to custom modelview & volume rendering

Bud Bundy budric at gmail.com
Tue Aug 30 13:54:13 EDT 2016


Sure Aashish,

Thanks for looking:


#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/30/2016 12:58 PM, Aashish Chaudhary wrote:
> Seems like a bug. Is it possible for you to send us a sample / test code?
>
> - Aashish
>
> On Tue, Aug 30, 2016 at 11:25 AM Bud Bundy <budric at gmail.com 
> <mailto:budric at gmail.com>> wrote:
>
>     Hi Aashish,
>
>     I compiled VTK revision dbae27c5ee61cb7507d893001ae8d93a580f9e72
>     of the master branch and still the same problem with volume
>     rendering. Rectangles render fine.
>
>     The worldToCamera transform applied through
>     SetModelTransformMatrix() seems to deform the volume for volume
>     rendering - yet it does not deform the rectangle geometry.  Does
>     this behavior seem right or should I file a bug report? I'm a new
>     user so it's entirely possible this is intended behavior, but to
>     me at a glance and reading API documentaiton it doesn't seem
>     right.  Yet another screenshot attached.
>
>     Thanks.
>
>
>
>     On 08/29/2016 03:43 PM, Aashish Chaudhary wrote:
>>     Hi Bud,
>>
>>     There was a bug that was fixed recently. Can you try the latest
>>     master and see if it is fixed? If it is, you can always
>>     cherry-pick that commit to 6.3 branch.
>>
>>     - Aashish
>>
>>     On Mon, Aug 29, 2016 at 1:46 PM Bud Bundy <budric at gmail.com
>>     <mailto:budric at gmail.com>> wrote:
>>
>>         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
>>>>
>>>>             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
>>>>
>>>>             Please keep messages on-topic and check the VTK FAQ at:
>>>>             http://www.vtk.org/Wiki/VTK_FAQ
>>>>
>>>>             Search the list archives at:
>>>>             http://markmail.org/search/?q=vtkusers
>>>>
>>>>             Follow this link to subscribe/unsubscribe:
>>>>             http://public.kitware.com/mailman/listinfo/vtkusers
>>>>
>>>
>>
>>         _______________________________________________
>>         Powered by www.kitware.com <http://www.kitware.com>
>>
>>         Visit other Kitware open-source projects at
>>         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
>>
>>         Search the list archives at:
>>         http://markmail.org/search/?q=vtkusers
>>
>>         Follow this link to subscribe/unsubscribe:
>>         http://public.kitware.com/mailman/listinfo/vtkusers
>>
>
>     _______________________________________________
>     Powered by www.kitware.com <http://www.kitware.com>
>
>     Visit other Kitware open-source projects at
>     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
>
>     Search the list archives at: http://markmail.org/search/?q=vtkusers
>
>     Follow this link to subscribe/unsubscribe:
>     http://public.kitware.com/mailman/listinfo/vtkusers
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160830/57bccca3/attachment.html>


More information about the vtkusers mailing list