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 = nullptr;
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(nullptr);
104 }
105 }
106
107 return renderedSomething;
108 }
109
110 // Description:
111 // Does this prop have some translucent polygonal geometry?
HasTranslucentPolygonalGeometry()112 vtkTypeBool 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(nullptr);
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
175 // Make sure the paths are up-to-date
176 this->UpdatePaths();
177
178 double numberOfItems = static_cast<double>(this->Parts->GetNumberOfItems());
179 fraction = numberOfItems >= 1.0 ?
180 this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
181
182 // render the Paths
183 vtkCollectionSimpleIterator sit;
184 for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
185 {
186 prop = path->GetLastNode()->GetViewProp();
187 if ( prop->GetVisibility() )
188 {
189 prop->SetAllocatedRenderTime(fraction, ren);
190 prop->PokeMatrix(path->GetLastNode()->GetMatrix());
191 renderedSomething += prop->RenderOpaqueGeometry(ren);
192 prop->PokeMatrix(nullptr);
193 }
194 }
195
196 return renderedSomething;
197 }
198
199 // Render this assembly and all its parts. The rendering process is recursive.
RenderOverlay(vtkViewport * ren)200 int vtkPropAssembly::RenderOverlay(vtkViewport *ren)
201 {
202 vtkProp *prop;
203 vtkAssemblyPath *path;
204 double fraction;
205 int renderedSomething=0;
206
207 // Make sure the paths are up-to-date
208 this->UpdatePaths();
209
210 double numberOfItems = static_cast<double>(this->Parts->GetNumberOfItems());
211 fraction = numberOfItems >= 1.0 ?
212 this->AllocatedRenderTime / numberOfItems : this->AllocatedRenderTime;
213
214 vtkCollectionSimpleIterator sit;
215 for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
216 {
217 prop = path->GetLastNode()->GetViewProp();
218 if ( prop->GetVisibility() )
219 {
220 prop->SetAllocatedRenderTime(fraction, ren);
221 prop->PokeMatrix(path->GetLastNode()->GetMatrix());
222 renderedSomething += prop->RenderOverlay(ren);
223 prop->PokeMatrix(nullptr);
224 }
225 }
226
227 return renderedSomething;
228 }
229
230
ReleaseGraphicsResources(vtkWindow * renWin)231 void vtkPropAssembly::ReleaseGraphicsResources(vtkWindow *renWin)
232 {
233 vtkProp *part;
234
235 vtkProp::ReleaseGraphicsResources(renWin);
236
237 // broadcast the message down the Parts
238 vtkCollectionSimpleIterator pit;
239 for ( this->Parts->InitTraversal(pit);
240 (part=this->Parts->GetNextProp(pit)); )
241 {
242 part->ReleaseGraphicsResources(renWin);
243 }
244 }
245
246 // Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
GetBounds()247 double *vtkPropAssembly::GetBounds()
248 {
249 vtkProp *part;
250 int i, n;
251 double bbox[24];
252 int partVisible=0;
253
254 // carefully compute the bounds
255 vtkCollectionSimpleIterator pit;
256 for ( this->Parts->InitTraversal(pit);
257 (part=this->Parts->GetNextProp(pit)); )
258 {
259 if ( part->GetVisibility() && part->GetUseBounds() )
260 {
261 const double *bounds = part->GetBounds();
262
263 if ( bounds != nullptr )
264 {
265 // For the purposes of GetBounds, an object is visible only if
266 // its visibility is on and it has visible parts.
267 if (!partVisible)
268 {
269 // initialize the bounds
270 this->Bounds[0] =this->Bounds[2] =this->Bounds[4] = VTK_DOUBLE_MAX;
271 this->Bounds[1] =this->Bounds[3] =this->Bounds[5] = -VTK_DOUBLE_MAX;
272 partVisible = 1;
273 }
274
275 // fill out vertices of a bounding box
276 bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
277 bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
278 bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
279 bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
280 bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
281 bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
282 bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
283 bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];
284
285 for (i = 0; i < 8; i++)
286 {
287 for (n = 0; n < 3; n++)
288 {
289 if (bbox[i*3+n] < this->Bounds[n*2])
290 {
291 this->Bounds[n*2] = bbox[i*3+n];
292 }
293 if (bbox[i*3+n] > this->Bounds[n*2+1])
294 {
295 this->Bounds[n*2+1] = bbox[i*3+n];
296 }
297 }
298 }//for each point of box
299 }//if bounds
300 }//for each part
301 }//for each part
302
303 if ( ! partVisible )
304 {
305 return nullptr;
306 }
307 else
308 {
309 return this->Bounds;
310 }
311 }
312
GetMTime()313 vtkMTimeType vtkPropAssembly::GetMTime()
314 {
315 vtkMTimeType mTime=this->vtkProp::GetMTime();
316 vtkMTimeType time;
317 vtkProp *part;
318
319 vtkCollectionSimpleIterator pit;
320 for (this->Parts->InitTraversal(pit);
321 (part=this->Parts->GetNextProp(pit)); )
322 {
323 time = part->GetMTime();
324 mTime = ( time > mTime ? time : mTime );
325 }
326
327 return mTime;
328 }
329
330 // Shallow copy another vtkPropAssembly.
ShallowCopy(vtkProp * prop)331 void vtkPropAssembly::ShallowCopy(vtkProp *prop)
332 {
333 vtkPropAssembly *propAssembly = vtkPropAssembly::SafeDownCast(prop);
334 if ( propAssembly != nullptr && propAssembly != this )
335 {
336 vtkCollectionSimpleIterator pit;
337 vtkProp *part;
338 for ( this->Parts->InitTraversal(pit);
339 (part=this->Parts->GetNextProp(pit)); )
340 {
341 part->RemoveConsumer(this);
342 }
343 this->Parts->RemoveAllItems();
344 for ( propAssembly->Parts->InitTraversal(pit);
345 (part=propAssembly->Parts->GetNextProp(pit)); )
346 {
347 this->AddPart(part);
348 }
349 }
350
351 this->vtkProp::ShallowCopy(prop);
352 }
353
InitPathTraversal()354 void vtkPropAssembly::InitPathTraversal()
355 {
356 this->UpdatePaths();
357 this->Paths->InitTraversal();
358 }
359
GetNextPath()360 vtkAssemblyPath *vtkPropAssembly::GetNextPath()
361 {
362 if ( this->Paths )
363 {
364 return this->Paths->GetNextItem();
365 }
366 return nullptr;
367 }
368
GetNumberOfPaths()369 int vtkPropAssembly::GetNumberOfPaths()
370 {
371 this->UpdatePaths();
372 return this->Paths->GetNumberOfItems();
373 }
374
375
376 // Build the assembly paths if necessary.
UpdatePaths()377 void vtkPropAssembly::UpdatePaths()
378 {
379 if ( this->GetMTime() > this->PathTime )
380 {
381 if ( this->Paths != nullptr )
382 {
383 this->Paths->Delete();
384 this->Paths = nullptr;
385 }
386
387 // Create the list to hold all the paths
388 this->Paths = vtkAssemblyPaths::New();
389 vtkAssemblyPath *path = vtkAssemblyPath::New();
390
391 //add ourselves to the path to start things off
392 path->AddNode(this,nullptr);
393
394 vtkProp *prop;
395 // Add nodes as we proceed down the hierarchy
396 vtkCollectionSimpleIterator pit;
397 for ( this->Parts->InitTraversal(pit);
398 (prop = this->Parts->GetNextProp(pit)); )
399 {
400 // add a matrix, if any
401 path->AddNode(prop,prop->GetMatrix());
402
403 // dive into the hierarchy
404 prop->BuildPaths(this->Paths,path);
405
406 // when returned, pop the last node off of the
407 // current path
408 path->DeleteLastNode();
409 }
410
411 path->Delete();
412 this->PathTime.Modified();
413 }
414 }
415
BuildPaths(vtkAssemblyPaths * paths,vtkAssemblyPath * path)416 void vtkPropAssembly::BuildPaths(vtkAssemblyPaths *paths,
417 vtkAssemblyPath *path)
418 {
419 vtkProp *prop;
420
421 vtkCollectionSimpleIterator pit;
422 for ( this->Parts->InitTraversal(pit);
423 (prop = this->Parts->GetNextProp(pit)); )
424 {
425 path->AddNode(prop,nullptr);
426
427 // dive into the hierarchy
428 prop->BuildPaths(paths,path);
429
430 // when returned, pop the last node off of the
431 // current path
432 path->DeleteLastNode();
433 }
434 }
435
436
PrintSelf(ostream & os,vtkIndent indent)437 void vtkPropAssembly::PrintSelf(ostream& os, vtkIndent indent)
438 {
439 this->Superclass::PrintSelf(os,indent);
440
441 os << indent << "There are: " << this->Parts->GetNumberOfItems()
442 << " parts in this assembly\n";
443 }
444