1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestValuePassFloatingPoint.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
16 // Description:
17 // Tests vtkValuePass in FLOATING_POINT mode. The test generates a 3-component
18 // float array ("elevationVector") using the loaded polygonal data (points and cells).
19 // Polygons are rendered with the ValuePass to its internal floating point frame-buffer.
20 // The rendered float image is then queried from the vtkValuePass and used to
21 // generate a color image using vtkLookupTable, the color image is rendered with
22 // an image actor on-screen. This is repeated for each component.
23
24 #include "vtkActor.h"
25 #include "vtkArrayCalculator.h"
26 #include "vtkCamera.h"
27 #include "vtkCameraPass.h"
28 #include "vtkCellData.h"
29 #include "vtkElevationFilter.h"
30 #include "vtkFloatArray.h"
31 #include "vtkImageActor.h"
32 #include "vtkImageData.h"
33 #include "vtkImageMapper3D.h"
34 #include "vtkInteractorStyleTrackballCamera.h"
35 #include "vtkLookupTable.h"
36 #include "vtkOpenGLRenderer.h"
37 #include "vtkPointData.h"
38 #include "vtkPointDataToCellData.h"
39 #include "vtkPolyData.h"
40 #include "vtkPolyDataMapper.h"
41 #include "vtkRegressionTestImage.h"
42 #include "vtkRenderPassCollection.h"
43 #include "vtkRenderWindow.h"
44 #include "vtkRenderWindowInteractor.h"
45 #include "vtkSequencePass.h"
46 #include "vtkSmartPointer.h"
47 #include "vtkSphereSource.h"
48 #include "vtkTestUtilities.h"
49 #include "vtkValuePass.h"
50
GenerateElevationArray(vtkSmartPointer<vtkPolyDataAlgorithm> source)51 void GenerateElevationArray(vtkSmartPointer<vtkPolyDataAlgorithm> source)
52 {
53 vtkPolyData* data = source->GetOutput();
54 const double* bounds = data->GetBounds();
55
56 vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New();
57 elevation->SetInputConnection(source->GetOutputPort());
58
59 // Use vtkElevation to generate an array per component. vtkElevation generates
60 // a projected distance from each point in the dataset to the line, with respect to
61 // the LowPoint ([0, 1] in this case. This is different from having the actual
62 // coordinates of a given point.
63 for (int c = 0; c < 3; c++)
64 {
65 std::string name;
66 switch (c)
67 {
68 case 0:
69 name = "delta_x";
70 elevation->SetLowPoint(bounds[0], 0.0, 0.0);
71 elevation->SetHighPoint(bounds[1], 0.0, 0.0);
72 break;
73 case 1:
74 name = "delta_y";
75 elevation->SetLowPoint(0.0, bounds[2], 0.0);
76 elevation->SetHighPoint(0.0, bounds[3], 0.0);
77 break;
78 case 2:
79 name = "delta_z";
80 elevation->SetLowPoint(0.0, 0.0, bounds[4]);
81 elevation->SetHighPoint(0.0, 0.0, bounds[5]);
82 break;
83 }
84 elevation->Update();
85
86 vtkPolyData* result = vtkPolyData::SafeDownCast(elevation->GetOutput());
87 int outCellFlag;
88 // Enums defined in vtkAbstractMapper
89 vtkDataArray* elevArray =
90 vtkAbstractMapper::GetScalars(result, VTK_SCALAR_MODE_USE_POINT_FIELD_DATA,
91 VTK_GET_ARRAY_BY_NAME /*acc mode*/, 0 /*arr id*/, "Elevation" /*arr name*/, outCellFlag);
92 if (!elevArray)
93 {
94 std::cout << "->> Error: could not find array!" << std::endl;
95 return;
96 }
97
98 elevArray->SetName(name.c_str());
99 data->GetPointData()->AddArray(elevArray);
100 }
101
102 // Generate a 3-component vector array using the single components
103 // form elevation
104
105 // Point data
106 vtkSmartPointer<vtkArrayCalculator> calc = vtkSmartPointer<vtkArrayCalculator>::New();
107 calc->SetInputConnection(source->GetOutputPort());
108 calc->SetAttributeTypeToPointData();
109 calc->AddScalarArrayName("delta_x");
110 calc->AddScalarArrayName("delta_y");
111 calc->AddScalarArrayName("delta_z");
112 calc->SetFunction("delta_x * iHat + delta_y * jHat + delta_z * kHat");
113 calc->SetResultArrayName("elevationVector");
114 calc->Update();
115
116 // Cell data
117 vtkSmartPointer<vtkPointDataToCellData> p2c = vtkSmartPointer<vtkPointDataToCellData>::New();
118 p2c->SetInputConnection(calc->GetOutputPort());
119 p2c->PassPointDataOn();
120 p2c->Update();
121
122 /// Include the elevation vector (point and cell data) in the original data
123 vtkPolyData* outputP2c = vtkPolyData::SafeDownCast(p2c->GetOutput());
124 data->GetPointData()->AddArray(
125 vtkDataSet::SafeDownCast(calc->GetOutput())->GetPointData()->GetArray("elevationVector"));
126 data->GetCellData()->AddArray(outputP2c->GetCellData()->GetArray("elevationVector"));
127 };
128
129 //------------------------------------------------------------------------------
RenderComponentImages(std::vector<vtkSmartPointer<vtkImageData>> & colorImOut,vtkRenderWindow * window,vtkRenderer * renderer,vtkValuePass * valuePass,int dataMode,char const * name)130 void RenderComponentImages(std::vector<vtkSmartPointer<vtkImageData>>& colorImOut,
131 vtkRenderWindow* window, vtkRenderer* renderer, vtkValuePass* valuePass, int dataMode,
132 char const* name)
133 {
134 valuePass->SetInputArrayToProcess(dataMode, name);
135
136 // Prepare a lut to map the floating point values
137 vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
138 lut->SetAlpha(1.0);
139 lut->Build();
140
141 // Render each component in a separate image
142 for (int c = 0; c < 3; c++)
143 {
144 valuePass->SetInputComponentToProcess(c);
145 window->Render();
146
147 /// Get the resulting values
148 vtkFloatArray* result = valuePass->GetFloatImageDataArray(renderer);
149 int* ext = valuePass->GetFloatImageExtents();
150
151 // Map the resulting float image to a color table
152 vtkUnsignedCharArray* colored =
153 lut->MapScalars(result, VTK_COLOR_MODE_DEFAULT, 0 /* single comp*/);
154
155 // Create an image dataset to render in a quad.
156 vtkSmartPointer<vtkImageData> colorIm = vtkSmartPointer<vtkImageData>::New();
157 colorIm->SetExtent(ext);
158 colorIm->GetPointData()->SetScalars(colored);
159 colorImOut.push_back(colorIm);
160 colored->Delete();
161 }
162 };
163
164 ///////////////////////////////////////////////////////////////////////////////
TestValuePassFloatingPoint(int argc,char * argv[])165 int TestValuePassFloatingPoint(int argc, char* argv[])
166 {
167 // Load data
168 vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
169 sphere->SetThetaResolution(8.0);
170 sphere->SetPhiResolution(8.0);
171 sphere->Update();
172
173 // Prepare a 3-component array (data will be appended to reader's output)
174 GenerateElevationArray(sphere);
175 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
176 mapper->SetInputData(sphere->GetOutput());
177 mapper->ScalarVisibilityOn();
178
179 vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
180 actor->SetMapper(mapper);
181
182 // Setup rendering and interaction
183 vtkSmartPointer<vtkRenderWindowInteractor> interactor =
184 vtkSmartPointer<vtkRenderWindowInteractor>::New();
185
186 vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
187 vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
188 interactor->SetInteractorStyle(style);
189
190 vtkSmartPointer<vtkRenderWindow> window = vtkSmartPointer<vtkRenderWindow>::New();
191 window->SetMultiSamples(0);
192 window->SetSize(640, 640);
193
194 vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
195
196 window->AddRenderer(renderer);
197 interactor->SetRenderWindow(window);
198
199 renderer->AddActor(actor);
200 renderer->SetBackground(0.2, 0.2, 0.5);
201
202 // Setup the value pass
203 int const comp = 0;
204
205 vtkSmartPointer<vtkValuePass> valuePass = vtkSmartPointer<vtkValuePass>::New();
206 valuePass->SetInputComponentToProcess(comp);
207 // Initial data mode
208 valuePass->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, "elevationVector");
209 // valuePass->SetInputArrayToProcess(VTK_SCALAR_MODE_USE_CELL_FIELD_DATA,
210 // "elevationVector");
211
212 // 3. Add it to a sequence of passes
213 vtkSmartPointer<vtkRenderPassCollection> passes = vtkSmartPointer<vtkRenderPassCollection>::New();
214 passes->AddItem(valuePass);
215
216 vtkSmartPointer<vtkSequencePass> sequence = vtkSmartPointer<vtkSequencePass>::New();
217 sequence->SetPasses(passes);
218
219 vtkSmartPointer<vtkCameraPass> cameraPass = vtkSmartPointer<vtkCameraPass>::New();
220 cameraPass->SetDelegatePass(sequence);
221
222 vtkOpenGLRenderer* glRenderer = vtkOpenGLRenderer::SafeDownCast(renderer);
223
224 // Render the value pass
225 glRenderer->SetPass(cameraPass);
226 window->Render();
227
228 // Render point data images
229 std::vector<vtkSmartPointer<vtkImageData>> colorImagesPoint;
230 RenderComponentImages(colorImagesPoint, window, renderer, valuePass,
231 VTK_SCALAR_MODE_USE_POINT_FIELD_DATA, "elevationVector");
232
233 // Render cell data images
234 std::vector<vtkSmartPointer<vtkImageData>> colorImagesCell;
235 RenderComponentImages(colorImagesCell, window, renderer, valuePass,
236 VTK_SCALAR_MODE_USE_CELL_FIELD_DATA, "elevationVector");
237
238 ////// Render results on-screen
239 renderer->RemoveActor(actor);
240
241 // Add image actors to display the point dataArray's components
242 vtkSmartPointer<vtkImageActor> ia_x = vtkSmartPointer<vtkImageActor>::New();
243 ia_x->GetMapper()->SetInputData(colorImagesPoint.at(0));
244 renderer->AddActor(ia_x);
245
246 vtkSmartPointer<vtkImageActor> ia_y = vtkSmartPointer<vtkImageActor>::New();
247 ia_y->RotateX(90);
248 ia_y->GetMapper()->SetInputData(colorImagesPoint.at(1));
249 renderer->AddActor(ia_y);
250
251 vtkSmartPointer<vtkImageActor> ia_z = vtkSmartPointer<vtkImageActor>::New();
252 ia_z->RotateY(-90);
253 ia_z->GetMapper()->SetInputData(colorImagesPoint.at(2));
254 renderer->AddActor(ia_z);
255
256 // Add image actors to display cell dataArray's components
257 vtkSmartPointer<vtkImageActor> iacell_x = vtkSmartPointer<vtkImageActor>::New();
258 iacell_x->SetPosition(-500, 600, 600);
259 iacell_x->GetMapper()->SetInputData(colorImagesCell.at(0));
260 renderer->AddActor(iacell_x);
261
262 vtkSmartPointer<vtkImageActor> iacell_y = vtkSmartPointer<vtkImageActor>::New();
263 iacell_y->RotateX(90);
264 iacell_y->SetPosition(-500, 600, 600);
265 iacell_y->GetMapper()->SetInputData(colorImagesCell.at(1));
266 renderer->AddActor(iacell_y);
267
268 vtkSmartPointer<vtkImageActor> iacell_z = vtkSmartPointer<vtkImageActor>::New();
269 iacell_z->RotateY(-90);
270 iacell_z->SetPosition(-500, 600, 600);
271 iacell_z->GetMapper()->SetInputData(colorImagesCell.at(2));
272 renderer->AddActor(iacell_z);
273
274 // Adjust viewpoint
275 vtkCamera* cam = renderer->GetActiveCamera();
276 cam->SetPosition(2, 2, 2);
277 cam->SetFocalPoint(0, 0, 1);
278 renderer->ResetCamera();
279
280 // Use the default pass to render the colored image.
281 glRenderer->SetPass(nullptr);
282 window->Render();
283
284 // initialize render loop
285 int retVal = vtkRegressionTestImage(window);
286 if (retVal == vtkRegressionTester::DO_INTERACTOR)
287 {
288 interactor->Start();
289 }
290
291 valuePass->ReleaseGraphicsResources(window);
292 return !retVal;
293 }
294