[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