1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkRendererSource.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 #include "vtkRendererSource.h"
16
17 #include "vtkCommand.h"
18 #include "vtkFloatArray.h"
19 #include "vtkImageData.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkMapper.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 #include "vtkRenderWindow.h"
26 #include "vtkRenderer.h"
27 #include "vtkStreamingDemandDrivenPipeline.h"
28 #include "vtkUnsignedCharArray.h"
29
30 vtkStandardNewMacro(vtkRendererSource);
31
32 vtkCxxSetObjectMacro(vtkRendererSource, Input, vtkRenderer);
33
34 //------------------------------------------------------------------------------
vtkRendererSource()35 vtkRendererSource::vtkRendererSource()
36 {
37 this->Input = nullptr;
38 this->WholeWindow = 0;
39 this->RenderFlag = 0;
40 this->DepthValues = 0;
41 this->DepthValuesInScalars = 0;
42 this->DepthValuesOnly = 0;
43
44 this->SetNumberOfInputPorts(0);
45 this->SetNumberOfOutputPorts(1);
46 }
47
48 //------------------------------------------------------------------------------
~vtkRendererSource()49 vtkRendererSource::~vtkRendererSource()
50 {
51 if (this->Input)
52 {
53 this->Input->UnRegister(this);
54 this->Input = nullptr;
55 }
56 }
57
58 //------------------------------------------------------------------------------
RequestData(vtkInformation *,vtkInformationVector **,vtkInformationVector * outputVector)59 void vtkRendererSource::RequestData(
60 vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector)
61 {
62 vtkIdType numOutPts;
63 float x1, y1, x2, y2;
64 int dims[3];
65
66 vtkInformation* info = outputVector->GetInformationObject(0);
67 vtkImageData* output = vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
68 int uExtent[6];
69 info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
70 output->SetExtent(uExtent);
71
72 vtkDebugMacro(<< "Extracting image");
73
74 // Make sure there is proper input
75 if (this->Input == nullptr)
76 {
77 vtkErrorMacro(<< "Please specify a renderer as input!");
78 return;
79 }
80
81 vtkRenderWindow* renWin = this->Input->GetRenderWindow();
82 if (renWin == nullptr)
83 {
84 vtkErrorMacro(<< "Renderer needs to be associated with renderin window!");
85 return;
86 }
87
88 // We're okay to go. There are two paths to proceed. Simply a depth image,
89 // or some combination of depth image and color scalars.
90 // calc the pixel range for the renderer
91 if (this->RenderFlag)
92 {
93 renWin->Render();
94 }
95
96 x1 = this->Input->GetViewport()[0] * (renWin->GetSize()[0] - 1);
97 y1 = this->Input->GetViewport()[1] * (renWin->GetSize()[1] - 1);
98 x2 = this->Input->GetViewport()[2] * (renWin->GetSize()[0] - 1);
99 y2 = this->Input->GetViewport()[3] * (renWin->GetSize()[1] - 1);
100
101 if (this->WholeWindow)
102 {
103 x1 = 0;
104 y1 = 0;
105 x2 = renWin->GetSize()[0] - 1;
106 y2 = renWin->GetSize()[1] - 1;
107 }
108
109 // Get origin, aspect ratio and dimensions from the input
110 dims[0] = static_cast<int>(x2 - x1 + 1);
111 dims[1] = static_cast<int>(y2 - y1 + 1);
112 dims[2] = 1;
113 output->SetDimensions(dims);
114 numOutPts = dims[0] * dims[1];
115
116 // If simply requesting depth values (no colors), do the following
117 // and then return.
118 if (this->DepthValuesOnly)
119 {
120 float *zBuf, *ptr;
121 output->AllocateScalars(info);
122 vtkFloatArray* outScalars =
123 vtkArrayDownCast<vtkFloatArray>(output->GetPointData()->GetScalars());
124 outScalars->SetName("ZValues");
125 ptr = outScalars->WritePointer(0, numOutPts);
126
127 zBuf = renWin->GetZbufferData(
128 static_cast<int>(x1), static_cast<int>(y1), static_cast<int>(x2), static_cast<int>(y2));
129
130 memcpy(ptr, zBuf, numOutPts * sizeof(float));
131
132 delete[] zBuf;
133 return;
134 }
135
136 // Okay requesting color scalars plus possibly depth values.
137 unsigned char *pixels, *ptr;
138 output->AllocateScalars(info);
139 vtkUnsignedCharArray* outScalars =
140 vtkArrayDownCast<vtkUnsignedCharArray>(output->GetPointData()->GetScalars());
141
142 if (this->DepthValuesInScalars)
143 {
144 outScalars->SetName("RGBValues");
145 }
146 else
147 {
148 outScalars->SetName("RGBZValues");
149 }
150
151 // Allocate data. Scalar type is FloatScalars.
152 pixels = renWin->GetPixelData(
153 static_cast<int>(x1), static_cast<int>(y1), static_cast<int>(x2), static_cast<int>(y2), 1);
154
155 // allocate scalars
156 int nb_comp = output->GetNumberOfScalarComponents();
157 ptr = outScalars->WritePointer(0, numOutPts * nb_comp);
158
159 // copy scalars over (if only RGB is requested, use the pixels directly)
160 if (!this->DepthValuesInScalars)
161 {
162 memcpy(ptr, pixels, numOutPts * nb_comp);
163 }
164
165 // Lets get the ZBuffer also, if requested.
166 if (this->DepthValues || this->DepthValuesInScalars)
167 {
168 float* zBuf = renWin->GetZbufferData(
169 static_cast<int>(x1), static_cast<int>(y1), static_cast<int>(x2), static_cast<int>(y2));
170
171 // If RGBZ is requested, intermix RGB with shift/scaled Z
172 if (this->DepthValuesInScalars)
173 {
174 float *zptr = zBuf, *zptr_end = zBuf + numOutPts;
175 float min = *zBuf, max = *zBuf;
176 while (zptr < zptr_end)
177 {
178 if (min < *zptr)
179 {
180 min = *zptr;
181 }
182 if (max > *zptr)
183 {
184 max = *zptr;
185 }
186 zptr++;
187 }
188 float scale = 255.0 / (max - min);
189
190 zptr = zBuf;
191 unsigned char* ppixels = pixels;
192 while (zptr < zptr_end)
193 {
194 *ptr++ = *ppixels++;
195 *ptr++ = *ppixels++;
196 *ptr++ = *ppixels++;
197 *ptr++ = static_cast<unsigned char>((*zptr++ - min) * scale);
198 }
199 }
200
201 // If Z is requested as independent array, create it
202 if (this->DepthValues)
203 {
204 vtkFloatArray* zArray = vtkFloatArray::New();
205 zArray->Allocate(numOutPts);
206 zArray->SetNumberOfTuples(numOutPts);
207 float* zPtr = zArray->WritePointer(0, numOutPts);
208 memcpy(zPtr, zBuf, numOutPts * sizeof(float));
209 zArray->SetName("ZBuffer");
210 output->GetPointData()->AddArray(zArray);
211 zArray->Delete();
212 }
213
214 delete[] zBuf;
215 }
216
217 delete[] pixels;
218 }
219
220 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)221 void vtkRendererSource::PrintSelf(ostream& os, vtkIndent indent)
222 {
223 this->Superclass::PrintSelf(os, indent);
224
225 os << indent << "RenderFlag: " << (this->RenderFlag ? "On\n" : "Off\n");
226
227 if (this->Input)
228 {
229 os << indent << "Input:\n";
230 this->Input->PrintSelf(os, indent.GetNextIndent());
231 }
232 else
233 {
234 os << indent << "Input: (none)\n";
235 }
236
237 os << indent << "Whole Window: " << (this->WholeWindow ? "On\n" : "Off\n");
238 os << indent << "Depth Values: " << (this->DepthValues ? "On\n" : "Off\n");
239 os << indent << "Depth Values In Scalars: " << (this->DepthValuesInScalars ? "On\n" : "Off\n");
240 os << indent << "Depth Values Only: " << (this->DepthValuesOnly ? "On\n" : "Off\n");
241 }
242
243 //------------------------------------------------------------------------------
GetMTime()244 vtkMTimeType vtkRendererSource::GetMTime()
245 {
246 vtkRenderer* ren = this->GetInput();
247 vtkMTimeType t1 = this->MTime.GetMTime();
248 vtkMTimeType t2;
249
250 if (!ren)
251 {
252 return t1;
253 }
254
255 // Update information on the input and
256 // compute information that is general to vtkDataObject.
257 t2 = ren->GetMTime();
258 if (t2 > t1)
259 {
260 t1 = t2;
261 }
262 vtkActorCollection* actors = ren->GetActors();
263 vtkCollectionSimpleIterator ait;
264 actors->InitTraversal(ait);
265 vtkActor* actor;
266 vtkMapper* mapper;
267 vtkDataSet* data;
268 while ((actor = actors->GetNextActor(ait)))
269 {
270 t2 = actor->GetMTime();
271 if (t2 > t1)
272 {
273 t1 = t2;
274 }
275 mapper = actor->GetMapper();
276 if (mapper)
277 {
278 t2 = mapper->GetMTime();
279 if (t2 > t1)
280 {
281 t1 = t2;
282 }
283 data = mapper->GetInput();
284 if (data)
285 {
286 mapper->GetInputAlgorithm()->UpdateInformation();
287 t2 = data->GetMTime();
288 if (t2 > t1)
289 {
290 t1 = t2;
291 }
292 }
293 t2 = vtkDemandDrivenPipeline::SafeDownCast(mapper->GetInputExecutive())->GetPipelineMTime();
294 if (t2 > t1)
295 {
296 t1 = t2;
297 }
298 }
299 }
300
301 return t1;
302 }
303
304 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)305 void vtkRendererSource::RequestInformation(vtkInformation* vtkNotUsed(request),
306 vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
307 {
308 vtkRenderer* ren = this->GetInput();
309 if (ren == nullptr || ren->GetRenderWindow() == nullptr)
310 {
311 vtkErrorMacro("The input renderer has not been set yet!!!");
312 return;
313 }
314
315 // calc the pixel range for the renderer
316 float x1, y1, x2, y2;
317 x1 = ren->GetViewport()[0] * ((ren->GetRenderWindow())->GetSize()[0] - 1);
318 y1 = ren->GetViewport()[1] * ((ren->GetRenderWindow())->GetSize()[1] - 1);
319 x2 = ren->GetViewport()[2] * ((ren->GetRenderWindow())->GetSize()[0] - 1);
320 y2 = ren->GetViewport()[3] * ((ren->GetRenderWindow())->GetSize()[1] - 1);
321 if (this->WholeWindow)
322 {
323 x1 = 0;
324 y1 = 0;
325 x2 = (this->Input->GetRenderWindow())->GetSize()[0] - 1;
326 y2 = (this->Input->GetRenderWindow())->GetSize()[1] - 1;
327 }
328 int extent[6] = { 0, static_cast<int>(x2 - x1), 0, static_cast<int>(y2 - y1), 0, 0 };
329
330 // get the info objects
331 vtkInformation* outInfo = outputVector->GetInformationObject(0);
332
333 outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6);
334
335 if (this->DepthValuesOnly)
336 {
337 vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
338 }
339 else
340 {
341 vtkDataObject::SetPointDataActiveScalarInfo(
342 outInfo, VTK_UNSIGNED_CHAR, 3 + (this->DepthValuesInScalars ? 1 : 0));
343 }
344 }
345
346 //------------------------------------------------------------------------------
ProcessRequest(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)347 vtkTypeBool vtkRendererSource::ProcessRequest(
348 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
349 {
350 // generate the data
351 if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
352 {
353 this->RequestData(request, inputVector, outputVector);
354 return 1;
355 }
356
357 // execute information
358 if (request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
359 {
360 this->RequestInformation(request, inputVector, outputVector);
361 return 1;
362 }
363
364 return this->Superclass::ProcessRequest(request, inputVector, outputVector);
365 }
366
367 //------------------------------------------------------------------------------
GetOutput()368 vtkImageData* vtkRendererSource::GetOutput()
369 {
370 return vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
371 }
372
373 //------------------------------------------------------------------------------
FillOutputPortInformation(int vtkNotUsed (port),vtkInformation * info)374 int vtkRendererSource::FillOutputPortInformation(int vtkNotUsed(port), vtkInformation* info)
375 {
376 // now add our info
377 info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
378 return 1;
379 }
380