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