1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPropAssembly.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 "vtkPropAssembly.h"
16 
17 #include "vtkAssemblyNode.h"
18 #include "vtkAssemblyPath.h"
19 #include "vtkAssemblyPaths.h"
20 #include "vtkMath.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkProp.h"
23 #include "vtkPropCollection.h"
24 #include "vtkViewport.h"
25 
26 vtkStandardNewMacro(vtkPropAssembly);
27 
28 // Construct object with no children.
vtkPropAssembly()29 vtkPropAssembly::vtkPropAssembly()
30 {
31   this->Parts = vtkPropCollection::New();
32   vtkMath::UninitializeBounds(this->Bounds);
33 }
34 
~vtkPropAssembly()35 vtkPropAssembly::~vtkPropAssembly()
36 {
37   vtkCollectionSimpleIterator pit;
38   vtkProp *part;
39   for ( this->Parts->InitTraversal(pit);
40        (part=this->Parts->GetNextProp(pit)); )
41     {
42     part->RemoveConsumer(this);
43     }
44 
45   this->Parts->Delete();
46   this->Parts = NULL;
47 }
48 
49 // Add a part to the list of Parts.
AddPart(vtkProp * prop)50 void vtkPropAssembly::AddPart(vtkProp *prop)
51 {
52   if ( ! this->Parts->IsItemPresent(prop) )
53     {
54     this->Parts->AddItem(prop);
55     prop->AddConsumer(this);
56     this->Modified();
57     }
58 }
59 
60 // Remove a part from the list of parts,
RemovePart(vtkProp * prop)61 void vtkPropAssembly::RemovePart(vtkProp *prop)
62 {
63   if ( this->Parts->IsItemPresent(prop) )
64     {
65     prop->RemoveConsumer(this);
66     this->Parts->RemoveItem(prop);
67     this->Modified();
68     }
69 }
70 
71 // Get the list of parts for this prop assembly.
GetParts()72 vtkPropCollection *vtkPropAssembly::GetParts()
73 {
74   return this->Parts;
75 }
76 
77 // Render this assembly and all of its Parts. The rendering process is recursive.
RenderTranslucentPolygonalGeometry(vtkViewport * ren)78 int vtkPropAssembly::RenderTranslucentPolygonalGeometry(vtkViewport *ren)
79 {
80   vtkProp *prop;
81   vtkAssemblyPath *path;
82   double fraction;
83   int renderedSomething=0;
84 
85   // Make sure the paths are up-to-date
86   this->UpdatePaths();
87 
88   double numberOfItems =  static_cast<double>(this->Parts->GetNumberOfItems());
89   fraction = numberOfItems >= 1.0 ?
90     this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
91 
92 
93   // render the Paths
94   vtkCollectionSimpleIterator sit;
95   for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
96     {
97     prop = path->GetLastNode()->GetViewProp();
98     if ( prop->GetVisibility() )
99       {
100       prop->SetAllocatedRenderTime(fraction, ren);
101       prop->PokeMatrix(path->GetLastNode()->GetMatrix());
102       renderedSomething += prop->RenderTranslucentPolygonalGeometry(ren);
103       prop->PokeMatrix(NULL);
104       }
105     }
106 
107   return renderedSomething;
108 }
109 
110 // Description:
111 // Does this prop have some translucent polygonal geometry?
HasTranslucentPolygonalGeometry()112 int vtkPropAssembly::HasTranslucentPolygonalGeometry()
113 {
114   vtkProp *prop;
115   vtkAssemblyPath *path;
116   int result=0;
117 
118   // Make sure the paths are up-to-date
119   this->UpdatePaths();
120 
121   // render the Paths
122   vtkCollectionSimpleIterator sit;
123   for ( this->Paths->InitTraversal(sit); !result && (path = this->Paths->GetNextPath(sit)); )
124     {
125     prop = path->GetLastNode()->GetViewProp();
126     if ( prop->GetVisibility() )
127       {
128       result=prop->HasTranslucentPolygonalGeometry();
129       }
130     }
131   return result;
132 }
133 
134 
135 // Render this assembly and all of its Parts. The rendering process is recursive.
RenderVolumetricGeometry(vtkViewport * ren)136 int vtkPropAssembly::RenderVolumetricGeometry(vtkViewport *ren)
137 {
138   vtkProp *prop;
139   vtkAssemblyPath *path;
140   double fraction;
141   int renderedSomething=0;
142 
143    // Make sure the paths are up-to-date
144   this->UpdatePaths();
145 
146   double numberOfItems =  static_cast<double>(this->Parts->GetNumberOfItems());
147   fraction = numberOfItems >= 1.0 ?
148     this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
149 
150   // render the Paths
151   vtkCollectionSimpleIterator sit;
152   for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
153     {
154     prop = path->GetLastNode()->GetViewProp();
155     if ( prop->GetVisibility() )
156       {
157       prop->SetAllocatedRenderTime(fraction, ren);
158       prop->PokeMatrix(path->GetLastNode()->GetMatrix());
159       renderedSomething += prop->RenderVolumetricGeometry(ren);
160       prop->PokeMatrix(NULL);
161       }
162     }
163 
164   return renderedSomething;
165 }
166 
167 // Render this assembly and all its parts. The rendering process is recursive.
RenderOpaqueGeometry(vtkViewport * ren)168 int vtkPropAssembly::RenderOpaqueGeometry(vtkViewport *ren)
169 {
170   vtkProp *prop;
171   vtkAssemblyPath *path;
172   double fraction;
173   int   renderedSomething=0;
174   double numberOfItems = 0.0;
175 
176   // Make sure the paths are up-to-date
177   this->UpdatePaths();
178 
179   numberOfItems =  static_cast<double>(this->Parts->GetNumberOfItems());
180   fraction = numberOfItems >= 1.0 ?
181     this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
182 
183   // render the Paths
184   vtkCollectionSimpleIterator sit;
185   for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
186     {
187     prop = path->GetLastNode()->GetViewProp();
188     if ( prop->GetVisibility() )
189       {
190       prop->SetAllocatedRenderTime(fraction, ren);
191       prop->PokeMatrix(path->GetLastNode()->GetMatrix());
192       renderedSomething += prop->RenderOpaqueGeometry(ren);
193       prop->PokeMatrix(NULL);
194       }
195     }
196 
197   return renderedSomething;
198 }
199 
200 // Render this assembly and all its parts. The rendering process is recursive.
RenderOverlay(vtkViewport * ren)201 int vtkPropAssembly::RenderOverlay(vtkViewport *ren)
202 {
203   vtkProp *prop;
204   vtkAssemblyPath *path;
205   double fraction;
206   int   renderedSomething=0;
207   double numberOfItems = 0.0;
208 
209   // Make sure the paths are up-to-date
210   this->UpdatePaths();
211 
212   numberOfItems =  static_cast<double>(this->Parts->GetNumberOfItems());
213   fraction = numberOfItems >= 1.0 ?
214     this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
215 
216   vtkCollectionSimpleIterator sit;
217   for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
218     {
219     prop = path->GetLastNode()->GetViewProp();
220     if ( prop->GetVisibility() )
221       {
222       prop->SetAllocatedRenderTime(fraction, ren);
223       prop->PokeMatrix(path->GetLastNode()->GetMatrix());
224       renderedSomething += prop->RenderOverlay(ren);
225       prop->PokeMatrix(NULL);
226       }
227     }
228 
229   return renderedSomething;
230 }
231 
232 
ReleaseGraphicsResources(vtkWindow * renWin)233 void vtkPropAssembly::ReleaseGraphicsResources(vtkWindow *renWin)
234 {
235   vtkProp *part;
236 
237   vtkProp::ReleaseGraphicsResources(renWin);
238 
239   // broadcast the message down the Parts
240   vtkCollectionSimpleIterator pit;
241   for ( this->Parts->InitTraversal(pit);
242         (part=this->Parts->GetNextProp(pit)); )
243     {
244     part->ReleaseGraphicsResources(renWin);
245     }
246 }
247 
248 // Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
GetBounds()249 double *vtkPropAssembly::GetBounds()
250 {
251   vtkProp *part;
252   int i, n;
253   double *bounds, bbox[24];
254   int partVisible=0;
255 
256   // carefully compute the bounds
257   vtkCollectionSimpleIterator pit;
258   for ( this->Parts->InitTraversal(pit);
259         (part=this->Parts->GetNextProp(pit)); )
260     {
261     if ( part->GetVisibility() && part->GetUseBounds() )
262       {
263       bounds = part->GetBounds();
264 
265       if ( bounds != NULL )
266         {
267         //  For the purposes of GetBounds, an object is visisble only if
268         //  its visibility is on and it has visible parts.
269         if (!partVisible)
270           {
271           // initialize the bounds
272           this->Bounds[0] =this->Bounds[2] =this->Bounds[4] = VTK_DOUBLE_MAX;
273           this->Bounds[1] =this->Bounds[3] =this->Bounds[5] = -VTK_DOUBLE_MAX;
274           partVisible = 1;
275           }
276 
277         // fill out vertices of a bounding box
278         bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
279         bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
280         bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
281         bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
282         bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
283         bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
284         bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
285         bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];
286 
287         for (i = 0; i < 8; i++)
288           {
289           for (n = 0; n < 3; n++)
290             {
291             if (bbox[i*3+n] < this->Bounds[n*2])
292               {
293               this->Bounds[n*2] = bbox[i*3+n];
294               }
295             if (bbox[i*3+n] > this->Bounds[n*2+1])
296               {
297               this->Bounds[n*2+1] = bbox[i*3+n];
298               }
299             }
300           }//for each point of box
301         }//if bounds
302       }//for each part
303     }//for each part
304 
305   if ( ! partVisible )
306     {
307     return NULL;
308     }
309   else
310     {
311     return this->Bounds;
312     }
313 }
314 
GetMTime()315 unsigned long int vtkPropAssembly::GetMTime()
316 {
317   unsigned long mTime=this->vtkProp::GetMTime();
318   unsigned long time;
319   vtkProp *part;
320 
321   vtkCollectionSimpleIterator pit;
322   for (this->Parts->InitTraversal(pit);
323        (part=this->Parts->GetNextProp(pit)); )
324     {
325     time = part->GetMTime();
326     mTime = ( time > mTime ? time : mTime );
327     }
328 
329   return mTime;
330 }
331 
332 // Shallow copy another vtkPropAssembly.
ShallowCopy(vtkProp * prop)333 void vtkPropAssembly::ShallowCopy(vtkProp *prop)
334 {
335   vtkPropAssembly *propAssembly = vtkPropAssembly::SafeDownCast(prop);
336   if ( propAssembly != NULL && propAssembly != this )
337     {
338     vtkCollectionSimpleIterator pit;
339     vtkProp *part;
340     for ( this->Parts->InitTraversal(pit);
341         (part=this->Parts->GetNextProp(pit)); )
342       {
343       part->RemoveConsumer(this);
344       }
345     this->Parts->RemoveAllItems();
346     for ( propAssembly->Parts->InitTraversal(pit);
347         (part=propAssembly->Parts->GetNextProp(pit)); )
348       {
349       this->AddPart(part);
350       }
351     }
352 
353   this->vtkProp::ShallowCopy(prop);
354 }
355 
InitPathTraversal()356 void vtkPropAssembly::InitPathTraversal()
357 {
358   this->UpdatePaths();
359   this->Paths->InitTraversal();
360 }
361 
GetNextPath()362 vtkAssemblyPath *vtkPropAssembly::GetNextPath()
363 {
364   if ( this->Paths )
365     {
366     return this->Paths->GetNextItem();
367     }
368   return NULL;
369 }
370 
GetNumberOfPaths()371 int vtkPropAssembly::GetNumberOfPaths()
372 {
373   this->UpdatePaths();
374   return this->Paths->GetNumberOfItems();
375 }
376 
377 
378 // Build the assembly paths if necessary.
UpdatePaths()379 void vtkPropAssembly::UpdatePaths()
380 {
381   if ( this->GetMTime() > this->PathTime )
382     {
383     if ( this->Paths != NULL )
384       {
385       this->Paths->Delete();
386       this->Paths = NULL;
387       }
388 
389     // Create the list to hold all the paths
390     this->Paths = vtkAssemblyPaths::New();
391     vtkAssemblyPath *path = vtkAssemblyPath::New();
392 
393     //add ourselves to the path to start things off
394     path->AddNode(this,NULL);
395 
396     vtkProp *prop;
397     // Add nodes as we proceed down the hierarchy
398     vtkCollectionSimpleIterator pit;
399     for ( this->Parts->InitTraversal(pit);
400           (prop = this->Parts->GetNextProp(pit)); )
401       {
402       // add a matrix, if any
403       path->AddNode(prop,prop->GetMatrix());
404 
405       // dive into the hierarchy
406       prop->BuildPaths(this->Paths,path);
407 
408       // when returned, pop the last node off of the
409       // current path
410       path->DeleteLastNode();
411       }
412 
413     path->Delete();
414     this->PathTime.Modified();
415     }
416 }
417 
BuildPaths(vtkAssemblyPaths * paths,vtkAssemblyPath * path)418 void vtkPropAssembly::BuildPaths(vtkAssemblyPaths *paths,
419                                  vtkAssemblyPath *path)
420 {
421   vtkProp *prop;
422 
423   vtkCollectionSimpleIterator pit;
424   for ( this->Parts->InitTraversal(pit);
425         (prop = this->Parts->GetNextProp(pit)); )
426     {
427     path->AddNode(prop,NULL);
428 
429     // dive into the hierarchy
430     prop->BuildPaths(paths,path);
431 
432     // when returned, pop the last node off of the
433     // current path
434     path->DeleteLastNode();
435     }
436 }
437 
438 
PrintSelf(ostream & os,vtkIndent indent)439 void vtkPropAssembly::PrintSelf(ostream& os, vtkIndent indent)
440 {
441   this->Superclass::PrintSelf(os,indent);
442 
443   os << indent << "There are: " << this->Parts->GetNumberOfItems()
444      << " parts in this assembly\n";
445 }
446