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(vtkInformation*,
60                                     vtkInformationVector**,
61                                     vtkInformationVector* outputVector)
62 {
63   vtkIdType numOutPts;
64   float x1,y1,x2,y2;
65   int dims[3];
66 
67   vtkInformation* info = outputVector->GetInformationObject(0);
68   vtkImageData *output =
69     vtkImageData::SafeDownCast(info->Get(vtkDataObject::DATA_OBJECT()));
70   int uExtent[6];
71   info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), uExtent);
72   output->SetExtent(uExtent);
73 
74   vtkDebugMacro(<<"Extracting image");
75 
76   // Make sure there is proper input
77   if (this->Input == nullptr)
78   {
79     vtkErrorMacro(<<"Please specify a renderer as input!");
80     return;
81   }
82 
83   vtkRenderWindow *renWin = this->Input->GetRenderWindow();
84   if (renWin == nullptr)
85   {
86     vtkErrorMacro(<<"Renderer needs to be associated with renderin window!");
87     return;
88   }
89 
90   // We're okay to go. There are two paths to proceed. Simply a depth image,
91   // or some combination of depth image and color scalars.
92   // calc the pixel range for the renderer
93   if (this->RenderFlag)
94   {
95     renWin->Render();
96   }
97 
98   x1 = this->Input->GetViewport()[0]*(renWin->GetSize()[0] - 1);
99   y1 = this->Input->GetViewport()[1]*(renWin->GetSize()[1] - 1);
100   x2 = this->Input->GetViewport()[2]*(renWin->GetSize()[0] - 1);
101   y2 = this->Input->GetViewport()[3]*(renWin->GetSize()[1] - 1);
102 
103   if (this->WholeWindow)
104   {
105     x1 = 0;
106     y1 = 0;
107     x2 = renWin->GetSize()[0] - 1;
108     y2 = renWin->GetSize()[1] - 1;
109   }
110 
111   // Get origin, aspect ratio and dimensions from the input
112   dims[0] = static_cast<int>(x2 - x1 + 1);
113   dims[1] = static_cast<int>(y2 -y1 + 1);
114   dims[2] = 1;
115   output->SetDimensions(dims);
116   numOutPts = dims[0] * dims[1];
117 
118   // If simply requesting depth values (no colors), do the following
119   // and then return.
120   if ( this->DepthValuesOnly )
121   {
122     float *zBuf, *ptr;
123     output->AllocateScalars(info);
124     vtkFloatArray *outScalars =
125       vtkArrayDownCast<vtkFloatArray>(output->GetPointData()->GetScalars());
126     outScalars->SetName("ZValues");
127     ptr = outScalars->WritePointer(0, numOutPts);
128 
129     zBuf = renWin->GetZbufferData(
130       static_cast<int>(x1),static_cast<int>(y1),static_cast<int>(x2),
131       static_cast<int>(y2));
132 
133     memcpy(ptr, zBuf, numOutPts*sizeof(float));
134 
135     delete [] zBuf;
136     return;
137   }
138 
139   // Okay requesting color scalars plus possibly depth values.
140   unsigned char *pixels, *ptr;
141   output->AllocateScalars(info);
142   vtkUnsignedCharArray *outScalars =
143     vtkArrayDownCast<vtkUnsignedCharArray>(output->GetPointData()->GetScalars());
144 
145   if (this->DepthValuesInScalars)
146   {
147     outScalars->SetName("RGBValues");
148   }
149   else
150   {
151     outScalars->SetName("RGBZValues");
152   }
153 
154   // Allocate data.  Scalar type is FloatScalars.
155   pixels = renWin->GetPixelData(static_cast<int>(x1),
156                                 static_cast<int>(y1),
157                                 static_cast<int>(x2),
158                                 static_cast<int>(y2), 1);
159 
160   // allocate scalars
161   int nb_comp = output->GetNumberOfScalarComponents();
162   ptr = outScalars->WritePointer(0, numOutPts * nb_comp);
163 
164   // copy scalars over (if only RGB is requested, use the pixels directly)
165   if (!this->DepthValuesInScalars)
166   {
167     memcpy(ptr, pixels, numOutPts * nb_comp);
168   }
169 
170   // Lets get the ZBuffer also, if requested.
171   if (this->DepthValues || this->DepthValuesInScalars)
172   {
173     float *zBuf = renWin->GetZbufferData(
174       static_cast<int>(x1),static_cast<int>(y1),static_cast<int>(x2),
175       static_cast<int>(y2));
176 
177     // If RGBZ is requested, intermix RGB with shift/scaled Z
178     if (this->DepthValuesInScalars)
179     {
180       float *zptr = zBuf, *zptr_end = zBuf + numOutPts;
181       float min = *zBuf, max = *zBuf;
182       while (zptr < zptr_end)
183       {
184         if (min < *zptr) { min = *zptr; }
185         if (max > *zptr) { max = *zptr; }
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 
244 //----------------------------------------------------------------------------
GetMTime()245 vtkMTimeType vtkRendererSource::GetMTime()
246 {
247   vtkRenderer *ren = this->GetInput();
248   vtkMTimeType t1 = this->MTime.GetMTime();
249   vtkMTimeType t2;
250 
251   if (!ren)
252   {
253     return t1;
254   }
255 
256   // Update information on the input and
257   // compute information that is general to vtkDataObject.
258   t2 = ren->GetMTime();
259   if (t2 > t1)
260   {
261     t1 = t2;
262   }
263   vtkActorCollection *actors = ren->GetActors();
264   vtkCollectionSimpleIterator ait;
265   actors->InitTraversal(ait);
266   vtkActor *actor;
267   vtkMapper *mapper;
268   vtkDataSet *data;
269   while ( (actor = actors->GetNextActor(ait)) )
270   {
271     t2 = actor->GetMTime();
272     if (t2 > t1)
273     {
274       t1 = t2;
275     }
276     mapper = actor->GetMapper();
277     if (mapper)
278     {
279       t2 = mapper->GetMTime();
280       if (t2 > t1)
281       {
282         t1 = t2;
283       }
284       data = mapper->GetInput();
285       if (data)
286       {
287         mapper->GetInputAlgorithm()->UpdateInformation();
288         t2 = data->GetMTime();
289         if (t2 > t1)
290         {
291           t1 = t2;
292         }
293       }
294       t2 = vtkDemandDrivenPipeline::SafeDownCast(
295         mapper->GetInputExecutive())->GetPipelineMTime();
296       if (t2 > t1)
297       {
298         t1 = t2;
299       }
300     }
301   }
302 
303   return t1;
304 }
305 
306 
307 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)308 void vtkRendererSource::RequestInformation (
309   vtkInformation * vtkNotUsed(request),
310   vtkInformationVector** vtkNotUsed( inputVector ),
311   vtkInformationVector *outputVector)
312 {
313     vtkRenderer *ren = this->GetInput();
314     if (ren == nullptr || ren->GetRenderWindow() == nullptr)
315     {
316       vtkErrorMacro("The input renderer has not been set yet!!!");
317       return;
318     }
319 
320     // calc the pixel range for the renderer
321     float x1,y1,x2,y2;
322     x1 = ren->GetViewport()[0] * ((ren->GetRenderWindow())->GetSize()[0] - 1);
323     y1 = ren->GetViewport()[1] * ((ren->GetRenderWindow())->GetSize()[1] - 1);
324     x2 = ren->GetViewport()[2] * ((ren->GetRenderWindow())->GetSize()[0] - 1);
325     y2 = ren->GetViewport()[3] *((ren->GetRenderWindow())->GetSize()[1] - 1);
326     if (this->WholeWindow)
327     {
328       x1 = 0;
329       y1 = 0;
330       x2 = (this->Input->GetRenderWindow())->GetSize()[0] - 1;
331       y2 = (this->Input->GetRenderWindow())->GetSize()[1] - 1;
332     }
333     int extent[6] = {0, static_cast<int>(x2-x1),
334                      0, static_cast<int>(y2-y1),
335                      0, 0};
336 
337   // get the info objects
338   vtkInformation* outInfo = outputVector->GetInformationObject(0);
339 
340   outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6);
341 
342   if ( this->DepthValuesOnly )
343   {
344     vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
345   }
346   else
347   {
348     vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR,
349                                                 3 + (this->DepthValuesInScalars ? 1:0));
350   }
351 }
352 
353 //----------------------------------------------------------------------------
ProcessRequest(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)354 int vtkRendererSource::ProcessRequest(vtkInformation* request,
355                                       vtkInformationVector** inputVector,
356                                       vtkInformationVector* outputVector)
357 {
358   // generate the data
359   if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
360   {
361     this->RequestData(request, inputVector, outputVector);
362     return 1;
363   }
364 
365   // execute information
366   if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
367   {
368     this->RequestInformation(request, inputVector, outputVector);
369     return 1;
370   }
371 
372   return this->Superclass::ProcessRequest(request, inputVector, outputVector);
373 }
374 
375 //----------------------------------------------------------------------------
GetOutput()376 vtkImageData* vtkRendererSource::GetOutput()
377 {
378   return vtkImageData::SafeDownCast(this->GetOutputDataObject(0));
379 }
380 
381 //----------------------------------------------------------------------------
FillOutputPortInformation(int vtkNotUsed (port),vtkInformation * info)382 int vtkRendererSource::FillOutputPortInformation(
383   int vtkNotUsed(port), vtkInformation* info)
384 {
385   // now add our info
386   info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
387   return 1;
388 }
389