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