Skip to content

Commit d309ca8

Browse files
committed
Consider whether volume transform preserves orientation
This commit changes the OpenGL2 GPU volume renderer to consider whether the volume transform preserves orientation when orienting polygons. Before, nothing was rendered when the transform didn't preserve orientation, presumably due to backface culling. The legacy OpenGL volume renderer handles this case.
1 parent 1cb5a96 commit d309ca8

File tree

4 files changed

+142
-1
lines changed

4 files changed

+142
-1
lines changed

Rendering/Volume/Testing/Cxx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ set (GenericVolumeCxxTests
2222
TestGPURayCastMIPToComposite.cxx
2323
TestGPURayCastNearestDataTypesMIP.cxx
2424
TestGPURayCastPerspectiveParallel.cxx
25+
TestGPURayCastVolumeOrientation.cxx
2526
TestGPURayCastVolumeUpdate.cxx
2627
TestGPUVolumeRayCastMapper.cxx
2728
TestMinIntensityRendering.cxx
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*=========================================================================
2+
3+
Program: Visualization Toolkit
4+
Module: TestGPURayCastVolumeOrientation.cxx
5+
6+
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7+
All rights reserved.
8+
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9+
10+
This software is distributed WITHOUT ANY WARRANTY; without even
11+
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12+
PURPOSE. See the above copyright notice for more information.
13+
14+
=========================================================================*/
15+
// This test volume renders a dataset that has a transform that
16+
// doesn't preserve orientation.
17+
18+
#include <vtkColorTransferFunction.h>
19+
#include <vtkGPUVolumeRayCastMapper.h>
20+
#include <vtkImageData.h>
21+
#include <vtkInteractorStyleTrackballCamera.h>
22+
#include <vtkNew.h>
23+
#include <vtkOutlineFilter.h>
24+
#include <vtkPiecewiseFunction.h>
25+
#include <vtkPolyDataMapper.h>
26+
#include <vtkRegressionTestImage.h>
27+
#include <vtkRenderWindow.h>
28+
#include <vtkRenderWindowInteractor.h>
29+
#include <vtkRenderer.h>
30+
#include <vtkSmartPointer.h>
31+
#include <vtkTestUtilities.h>
32+
#include <vtkVolumeProperty.h>
33+
#include <vtkXMLImageDataReader.h>
34+
35+
int TestGPURayCastVolumeOrientation(int argc, char *argv[])
36+
{
37+
cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << endl;
38+
double scalarRange[2];
39+
40+
vtkNew<vtkActor> outlineActor;
41+
vtkNew<vtkPolyDataMapper> outlineMapper;
42+
vtkNew<vtkGPUVolumeRayCastMapper> volumeMapper;
43+
44+
vtkNew<vtkXMLImageDataReader> reader;
45+
const char* volumeFile = vtkTestUtilities::ExpandDataFileName(
46+
argc, argv, "Data/vase_1comp.vti");
47+
reader->SetFileName(volumeFile);
48+
volumeMapper->SetInputConnection(reader->GetOutputPort());
49+
delete[] volumeFile;
50+
51+
// Add outline filter
52+
vtkNew<vtkOutlineFilter> outlineFilter;
53+
outlineFilter->SetInputConnection(reader->GetOutputPort());
54+
outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());
55+
outlineActor->SetMapper(outlineMapper.GetPointer());
56+
57+
volumeMapper->GetInput()->GetScalarRange(scalarRange);
58+
volumeMapper->SetSampleDistance(0.1);
59+
volumeMapper->SetAutoAdjustSampleDistances(0);
60+
volumeMapper->SetBlendModeToComposite();
61+
62+
vtkNew<vtkRenderWindow> renWin;
63+
renWin->SetMultiSamples(0);
64+
renWin->SetSize(400, 400);
65+
66+
vtkNew<vtkRenderWindowInteractor> iren;
67+
iren->SetRenderWindow(renWin.GetPointer());
68+
vtkNew<vtkInteractorStyleTrackballCamera> style;
69+
iren->SetInteractorStyle(style.GetPointer());
70+
71+
renWin->Render(); // make sure we have an OpenGL context.
72+
73+
vtkNew<vtkRenderer> ren;
74+
ren->SetBackground(0.2, 0.2, 0.5);
75+
renWin->AddRenderer(ren.GetPointer());
76+
77+
vtkNew<vtkPiecewiseFunction> scalarOpacity;
78+
scalarOpacity->AddPoint(50, 0.0);
79+
scalarOpacity->AddPoint(75, 1.0);
80+
81+
vtkNew<vtkVolumeProperty> volumeProperty;
82+
volumeProperty->ShadeOn();
83+
volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
84+
volumeProperty->SetScalarOpacity(scalarOpacity.GetPointer());
85+
86+
vtkNew<vtkColorTransferFunction> colorTransferFunction;
87+
colorTransferFunction->RemoveAllPoints();
88+
colorTransferFunction->AddRGBPoint(scalarRange[0], 0.6, 0.4, 0.1);
89+
volumeProperty->SetColor(colorTransferFunction.GetPointer());
90+
91+
vtkNew<vtkVolume> volume;
92+
volume->SetMapper(volumeMapper.GetPointer());
93+
volume->SetProperty(volumeProperty.GetPointer());
94+
95+
// Set a transform that doesn't preserve orientation
96+
volume->SetScale(1.0, -1.0, 1.0);
97+
outlineActor->SetScale(1.0, -1.0, 1.0);
98+
99+
ren->AddViewProp(volume.GetPointer());
100+
ren->AddActor(outlineActor.GetPointer());
101+
ren->ResetCamera();
102+
103+
int valid = volumeMapper->IsRenderSupported(renWin.GetPointer(),
104+
volumeProperty.GetPointer());
105+
int retVal;
106+
if (valid)
107+
{
108+
renWin->Render();
109+
110+
iren->Initialize();
111+
retVal = vtkRegressionTestImage(renWin.GetPointer());
112+
if (retVal == vtkRegressionTester::DO_INTERACTOR)
113+
{
114+
iren->Start();
115+
}
116+
}
117+
else
118+
{
119+
retVal = vtkTesting::PASSED;
120+
cout << "Required extensions not supported" << endl;
121+
}
122+
123+
return !retVal;
124+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
f5e91acd4a0226e3bff27b0636aaf7d2

Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1803,9 +1803,24 @@ void vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::RenderVolumeGeometry(
18031803
vtkIdType npts;
18041804
vtkIdType *pts;
18051805

1806+
// See if the volume transform is orientation-preserving
1807+
// and orient polygons accordingly
1808+
vtkMatrix4x4* volMat = vol->GetMatrix();
1809+
double det = vtkMath::Determinant3x3(
1810+
volMat->GetElement(0, 0), volMat->GetElement(0, 1), volMat->GetElement(0, 2),
1811+
volMat->GetElement(1, 0), volMat->GetElement(1, 1), volMat->GetElement(1, 2),
1812+
volMat->GetElement(2, 0), volMat->GetElement(2, 1), volMat->GetElement(2, 2));
1813+
bool preservesOrientation = det > 0.0;
1814+
1815+
const vtkIdType indexMap[3] = {
1816+
preservesOrientation ? 0 : 2,
1817+
1,
1818+
preservesOrientation ? 2 : 0
1819+
};
1820+
18061821
while(cells->GetNextCell(npts, pts))
18071822
{
1808-
polys->InsertNextTuple3(pts[0], pts[1], pts[2]);
1823+
polys->InsertNextTuple3(pts[indexMap[0]], pts[indexMap[1]], pts[indexMap[2]]);
18091824
}
18101825

18111826
// Dispose any previously created buffers

0 commit comments

Comments
 (0)