1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkCompositePainter.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 "vtkCompositePainter.h"
16 
17 #include "vtkColor.h"
18 #include "vtkCompositeDataDisplayAttributes.h"
19 #include "vtkCompositeDataIterator.h"
20 #include "vtkCompositeDataSet.h"
21 #include "vtkGarbageCollector.h"
22 #include "vtkHardwareSelector.h"
23 #include "vtkInformation.h"
24 #include "vtkInformationObjectBaseKey.h"
25 #include "vtkMultiBlockDataSet.h"
26 #include "vtkMultiPieceDataSet.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkPolyData.h"
29 #include "vtkProperty.h"
30 #include "vtkRenderer.h"
31 #include "vtkRenderWindow.h"
32 
33 #include <cassert>
34 
35 // Return NULL if no override is supplied.
36 vtkAbstractObjectFactoryNewMacro(vtkCompositePainter)
37 
38 vtkInformationKeyMacro(vtkCompositePainter, DISPLAY_ATTRIBUTES, ObjectBase);
39 vtkCxxSetObjectMacro(vtkCompositePainter, CompositeDataDisplayAttributes, vtkCompositeDataDisplayAttributes);
40 //----------------------------------------------------------------------------
vtkCompositePainter()41 vtkCompositePainter::vtkCompositePainter()
42 {
43   this->OutputData = 0;
44   this->CompositeDataDisplayAttributes = 0;
45 }
46 
47 //----------------------------------------------------------------------------
~vtkCompositePainter()48 vtkCompositePainter::~vtkCompositePainter()
49 {
50   this->SetCompositeDataDisplayAttributes(0);
51 }
52 
53 //----------------------------------------------------------------------------
GetOutput()54 vtkDataObject* vtkCompositePainter::GetOutput()
55 {
56   return this->OutputData? this->OutputData : this->GetInput();
57 }
58 
59 //----------------------------------------------------------------------------
RenderInternal(vtkRenderer * renderer,vtkActor * actor,unsigned long typeflags,bool forceCompileOnly)60 void vtkCompositePainter::RenderInternal(vtkRenderer* renderer,
61                                          vtkActor* actor,
62                                          unsigned long typeflags,
63                                          bool forceCompileOnly)
64 {
65   vtkCompositeDataSet* input = vtkCompositeDataSet::SafeDownCast(this->GetInput());
66   if (!input || !this->DelegatePainter)
67     {
68     this->Superclass::RenderInternal(renderer, actor, typeflags,
69                                      forceCompileOnly);
70     return;
71     }
72 
73   vtkHardwareSelector* selector = renderer->GetSelector();
74 
75   if (this->CompositeDataDisplayAttributes &&
76       (this->CompositeDataDisplayAttributes->HasBlockOpacities() ||
77        this->CompositeDataDisplayAttributes->HasBlockVisibilities() ||
78        this->CompositeDataDisplayAttributes->HasBlockColors()))
79     {
80     vtkProperty* prop = actor->GetProperty();
81     RenderBlockState state;
82 
83     // Push base-values on the state stack.
84     state.Visibility.push(true);
85     state.Opacity.push(prop->GetOpacity());
86     state.AmbientColor.push(vtkColor3d(prop->GetAmbientColor()));
87     state.DiffuseColor.push(vtkColor3d(prop->GetDiffuseColor()));
88     state.SpecularColor.push(vtkColor3d(prop->GetSpecularColor()));
89 
90     // OpenGL currently knows how to render *this* state.
91     state.RenderedOpacity = state.Opacity.top();
92     state.RenderedAmbientColor = state.AmbientColor.top();
93     state.RenderedDiffuseColor = state.DiffuseColor.top();
94     state.RenderedSpecularColor = state.SpecularColor.top();
95 
96     // render using the composite data attributes
97     unsigned int flat_index = 0;
98     this->RenderBlock(renderer,
99                       actor,
100                       typeflags,
101                       forceCompileOnly,
102                       input,
103                       flat_index,
104                       state);
105 
106     // restore OpenGL state, if it was changed.
107     this->UpdateRenderingState(renderer->GetRenderWindow(), actor->GetProperty(), state);
108     }
109   else
110     {
111     // render using the multi-block structure itself
112     vtkCompositeDataIterator* iter = input->NewIterator();
113     for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
114       {
115       vtkDataObject* dobj = iter->GetCurrentDataObject();
116       if (dobj)
117         {
118         if (selector)
119           {
120           selector->BeginRenderProp();
121           // If hardware selection is in progress, we need to pass the composite
122           // index to the selection framework,
123           selector->RenderCompositeIndex(iter->GetCurrentFlatIndex());
124           }
125 
126         this->DelegatePainter->SetInput(dobj);
127         this->OutputData = dobj;
128         this->Superclass::RenderInternal(renderer, actor, typeflags,
129                                          forceCompileOnly);
130         this->OutputData = 0;
131 
132         if (selector)
133           {
134           selector->EndRenderProp();
135           }
136         }
137       }
138     iter->Delete();
139     }
140 }
141 
142 //-----------------------------------------------------------------------------
RenderBlock(vtkRenderer * renderer,vtkActor * actor,unsigned long typeflags,bool forceCompileOnly,vtkDataObject * dobj,unsigned int & flat_index,vtkCompositePainter::RenderBlockState & state)143 void vtkCompositePainter::RenderBlock(vtkRenderer *renderer,
144                                       vtkActor *actor,
145                                       unsigned long typeflags,
146                                       bool forceCompileOnly,
147                                       vtkDataObject *dobj,
148                                       unsigned int &flat_index,
149                                       vtkCompositePainter::RenderBlockState &state)
150 {
151   assert("Sanity Check" &&
152     (state.Visibility.size() > 0) &&
153     (state.Opacity.size() > 0) &&
154     (state.AmbientColor.size() > 0) &&
155     (state.DiffuseColor.size() > 0) &&
156     (state.SpecularColor.size() > 0));
157 
158   vtkHardwareSelector *selector = renderer->GetSelector();
159   vtkProperty *property = actor->GetProperty();
160   vtkCompositeDataDisplayAttributes* cda = this->CompositeDataDisplayAttributes;
161 
162   // A block always *has* a visibility state, either explicitly set or
163   // inherited.
164   state.Visibility.push(
165     cda->HasBlockVisibility(flat_index) ?
166     cda->GetBlockVisibility(flat_index) : state.Visibility.top());
167 
168   bool overrides_opacity = cda->HasBlockOpacity(flat_index);
169   if (overrides_opacity)
170     {
171     state.Opacity.push(cda->GetBlockOpacity(flat_index));
172     }
173 
174   bool overrides_color = cda->HasBlockColor(flat_index);
175   if (overrides_color)
176     {
177     vtkColor3d color = cda->GetBlockColor(flat_index);
178     state.AmbientColor.push(color);
179     state.DiffuseColor.push(color);
180     state.SpecularColor.push(color);
181     }
182 
183   unsigned int my_flat_index = flat_index;
184   // Advance flat-index. After this point, flat_index no longer points to this
185   // block.
186   flat_index++;
187 
188   vtkMultiBlockDataSet *mbds = vtkMultiBlockDataSet::SafeDownCast(dobj);
189   vtkMultiPieceDataSet *mpds = vtkMultiPieceDataSet::SafeDownCast(dobj);
190   if (mbds || mpds)
191     {
192     unsigned int numChildren = mbds? mbds->GetNumberOfBlocks() :
193       mpds->GetNumberOfPieces();
194     for (unsigned int cc=0 ; cc < numChildren; cc++)
195       {
196       vtkDataObject* child = mbds ? mbds->GetBlock(cc) : mpds->GetPiece(cc);
197       if (child == NULL)
198         {
199         // speeds things up when dealing with NULL blocks (which is common with
200         // AMRs).
201         flat_index++;
202         continue;
203         }
204       this->RenderBlock(renderer, actor, typeflags, forceCompileOnly,
205         child, flat_index, state);
206       }
207     }
208   else if (dobj && state.Visibility.top() == true && state.Opacity.top() > 0.0)
209     {
210     // Implies that the block is a non-null leaf node.
211     // The top of the "stacks" have the state that this block must be rendered
212     // with.
213     if (selector)
214       {
215       selector->BeginRenderProp();
216       selector->RenderCompositeIndex(my_flat_index);
217       }
218     else
219       {
220       // Not selecting, render the colors and stuff correctly for this block.
221       // For that.
222       this->UpdateRenderingState(renderer->GetRenderWindow(), property, state);
223       }
224 
225     this->DelegatePainter->SetInput(dobj);
226     this->OutputData = dobj;
227     this->Superclass::RenderInternal(renderer, actor, typeflags, forceCompileOnly);
228     this->OutputData = 0;
229     if (selector)
230       {
231       selector->EndRenderProp();
232       }
233     }
234 
235   if (overrides_color)
236     {
237     state.AmbientColor.pop();
238     state.DiffuseColor.pop();
239     state.SpecularColor.pop();
240     }
241   if (overrides_opacity)
242     {
243     state.Opacity.pop();
244     }
245   state.Visibility.pop();
246 }
247 
248 //-----------------------------------------------------------------------------
ReportReferences(vtkGarbageCollector * collector)249 void vtkCompositePainter::ReportReferences(vtkGarbageCollector *collector)
250 {
251   this->Superclass::ReportReferences(collector);
252 
253   vtkGarbageCollectorReport(collector, this->OutputData, "Output");
254 }
255 
256 //----------------------------------------------------------------------------
ProcessInformation(vtkInformation * info)257 void vtkCompositePainter::ProcessInformation(vtkInformation* info)
258 {
259   this->Superclass::ProcessInformation(info);
260 
261   if (info->Has(DISPLAY_ATTRIBUTES()))
262     {
263     this->SetCompositeDataDisplayAttributes(
264       vtkCompositeDataDisplayAttributes::SafeDownCast(
265         info->Get(DISPLAY_ATTRIBUTES())));
266     }
267 }
268 
269 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)270 void vtkCompositePainter::PrintSelf(ostream& os, vtkIndent indent)
271 {
272   this->Superclass::PrintSelf(os, indent);
273 
274   os << indent << "CompositeDataDisplayAttributes: " ;
275   if (this->CompositeDataDisplayAttributes)
276     {
277     os << endl;
278     this->CompositeDataDisplayAttributes->PrintSelf(os, indent.GetNextIndent());
279     }
280   else
281     {
282     os << "(none)" << endl;
283     }
284 }
285