1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkOpenGLGlyph3DMapper.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 "vtkOpenGLGlyph3DMapper.h"
16
17 #include "vtkActor.h"
18 #include "vtkBitArray.h"
19 #include "vtkCompositeDataDisplayAttributes.h"
20 #include "vtkCompositeDataIterator.h"
21 #include "vtkCompositeDataSet.h"
22 #include "vtkDataObjectTree.h"
23 #include "vtkDataObjectTreeIterator.h"
24 #include "vtkHardwareSelector.h"
25 #include "vtkMath.h"
26 #include "vtkMatrix3x3.h"
27 #include "vtkObjectFactory.h"
28 #include "vtkOpenGLGlyph3DHelper.h"
29 #include "vtkProperty.h"
30 #include "vtkRenderer.h"
31 #include "vtkRenderWindow.h"
32 #include "vtkTransform.h"
33 #include "vtkOpenGLError.h"
34 #include "vtkSmartPointer.h"
35 #include "vtkQuaternion.h"
36
37 #include <map>
38
39 namespace {
getNumberOfChildren(vtkDataObjectTree * tree)40 int getNumberOfChildren(vtkDataObjectTree *tree)
41 {
42 int result = 0;
43 if (tree)
44 {
45 vtkDataObjectTreeIterator *it = tree->NewTreeIterator();
46 it->SetTraverseSubTree(false);
47 it->SetVisitOnlyLeaves(false);
48 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
49 {
50 ++result;
51 }
52 it->Delete();
53 }
54 return result;
55 }
56
getChildDataObject(vtkDataObjectTree * tree,int child)57 vtkDataObject* getChildDataObject(vtkDataObjectTree *tree, int child)
58 {
59 vtkDataObject *result = nullptr;
60 if (tree)
61 {
62 vtkDataObjectTreeIterator *it = tree->NewTreeIterator();
63 it->SetTraverseSubTree(false);
64 it->SetVisitOnlyLeaves(false);
65 it->InitTraversal();
66 for (int i = 0; i < child; ++i)
67 {
68 it->GoToNextItem();
69 }
70 result = it->GetCurrentDataObject();
71 it->Delete();
72 }
73 return result;
74 }
75 }
76
77 class vtkOpenGLGlyph3DMappervtkColorMapper : public vtkMapper
78 {
79 public:
80 vtkTypeMacro(vtkOpenGLGlyph3DMappervtkColorMapper, vtkMapper);
81 static vtkOpenGLGlyph3DMappervtkColorMapper* New();
Render(vtkRenderer *,vtkActor *)82 void Render(vtkRenderer *, vtkActor *) override {}
GetColors()83 vtkUnsignedCharArray* GetColors() { return this->Colors; }
84 };
85
86 vtkStandardNewMacro(vtkOpenGLGlyph3DMappervtkColorMapper)
87
88 class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry
89 {
90 public:
91 std::vector<vtkIdType> PickIds;
92 std::vector<unsigned char> Colors;
93 std::vector<float> Matrices; // transposed
94 std::vector<float> NormalMatrices; // transposed
95 vtkTimeStamp BuildTime;
96 // May be polydata or composite dataset:
97 vtkDataObject *DataObject;
98 // maps composite dataset flat index to polydatamapper. Key = -1 for polydata
99 // DataObject.
100 typedef std::map<int, vtkOpenGLGlyph3DHelper*> MapperMap;
101 MapperMap Mappers;
102 int NumberOfPoints;
103
vtkOpenGLGlyph3DMapperEntry()104 vtkOpenGLGlyph3DMapperEntry()
105 {
106 this->NumberOfPoints = 0;
107 this->DataObject = nullptr;
108 };
~vtkOpenGLGlyph3DMapperEntry()109 ~vtkOpenGLGlyph3DMapperEntry()
110 {
111 this->ClearMappers();
112 if (this->DataObject)
113 {
114 this->DataObject->Delete();
115 }
116 };
ClearMappers()117 void ClearMappers()
118 {
119 for (MapperMap::iterator it = this->Mappers.begin();
120 it != this->Mappers.end(); ++it)
121 {
122 it->second->Delete();
123 }
124 this->Mappers.clear();
125 }
126 };
127
128 class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray
129 {
130 public:
131 std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *> Entries;
132 vtkTimeStamp BuildTime;
133 vtkOpenGLGlyph3DMapperSubArray() = default;
~vtkOpenGLGlyph3DMapperSubArray()134 ~vtkOpenGLGlyph3DMapperSubArray()
135 {
136 this->ClearEntries();
137 };
ClearEntries()138 void ClearEntries()
139 {
140 std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *>::iterator miter = this->Entries.begin();
141 for (;miter != this->Entries.end(); ++miter)
142 {
143 delete *miter;
144 }
145 this->Entries.clear();
146 }
147 };
148
149 class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperArray
150 {
151 public:
152 std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *> Entries;
~vtkOpenGLGlyph3DMapperArray()153 ~vtkOpenGLGlyph3DMapperArray()
154 {
155 std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator miter = this->Entries.begin();
156 for (;miter != this->Entries.end(); ++miter)
157 {
158 delete miter->second;
159 }
160 this->Entries.clear();
161 };
162 };
163
vtkStandardNewMacro(vtkOpenGLGlyph3DMapper)164 vtkStandardNewMacro(vtkOpenGLGlyph3DMapper)
165
166 // ---------------------------------------------------------------------------
167 // Construct object with scaling on, scaling mode is by scalar value,
168 // scale factor = 1.0, the range is (0,1), orient geometry is on, and
169 // orientation is by vector. Clamping and indexing are turned off. No
170 // initial sources are defined.
171 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapper()
172 {
173 this->GlyphValues = new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperArray();
174 this->ColorMapper = vtkOpenGLGlyph3DMappervtkColorMapper::New();
175 }
176
177 // ---------------------------------------------------------------------------
~vtkOpenGLGlyph3DMapper()178 vtkOpenGLGlyph3DMapper::~vtkOpenGLGlyph3DMapper()
179 {
180 this->ColorMapper->Delete();
181
182 delete this->GlyphValues;
183 this->GlyphValues = nullptr;
184 }
185
186 // ---------------------------------------------------------------------------
187 // Description:
188 // Send mapper ivars to sub-mapper.
189 // \pre mapper_exists: mapper!=0
CopyInformationToSubMapper(vtkOpenGLGlyph3DHelper * mapper)190 void vtkOpenGLGlyph3DMapper::CopyInformationToSubMapper(
191 vtkOpenGLGlyph3DHelper *mapper)
192 {
193 assert("pre: mapper_exists" && mapper!=nullptr);
194 mapper->SetStatic(this->Static);
195 mapper->ScalarVisibilityOff();
196 // not used
197 mapper->SetClippingPlanes(this->ClippingPlanes);
198
199 mapper->SetResolveCoincidentTopology(this->GetResolveCoincidentTopology());
200 mapper->SetResolveCoincidentTopologyZShift(
201 this->GetResolveCoincidentTopologyZShift());
202
203 double f, u;
204 this->GetRelativeCoincidentTopologyPolygonOffsetParameters(f, u);
205 mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(f, u);
206 this->GetRelativeCoincidentTopologyLineOffsetParameters(f, u);
207 mapper->SetRelativeCoincidentTopologyLineOffsetParameters(f, u);
208 this->GetRelativeCoincidentTopologyPointOffsetParameter(u);
209 mapper->SetRelativeCoincidentTopologyPointOffsetParameter(u);
210
211 // ResolveCoincidentTopologyPolygonOffsetParameters is static
212 mapper->SetResolveCoincidentTopologyPolygonOffsetFaces(
213 this->GetResolveCoincidentTopologyPolygonOffsetFaces());
214
215 if (static_cast<vtkIdType>(this->LODs.size()) > this->GetMaxNumberOfLOD())
216 {
217 vtkWarningMacro(<< "too many LODs are defined, "
218 << (static_cast<vtkIdType>(this->LODs.size()) - this->GetMaxNumberOfLOD())
219 << " last defined LODs are discarded.");
220 this->LODs.resize(this->GetMaxNumberOfLOD());
221 }
222
223 mapper->SetLODs(this->LODs);
224 mapper->SetLODColoring(this->LODColoring);
225 }
226
SetupColorMapper()227 void vtkOpenGLGlyph3DMapper::SetupColorMapper()
228 {
229 this->ColorMapper->ShallowCopy(this);
230 }
231
232 // ---------------------------------------------------------------------------
233 // Description:
234 // Method initiates the mapping process. Generally sent by the actor
235 // as each frame is rendered.
Render(vtkRenderer * ren,vtkActor * actor)236 void vtkOpenGLGlyph3DMapper::Render(vtkRenderer *ren, vtkActor *actor)
237 {
238 vtkOpenGLClearErrorMacro();
239
240 this->SetupColorMapper();
241
242 vtkHardwareSelector* selector = ren->GetSelector();
243
244 if (selector)
245 {
246 selector->BeginRenderProp();
247 }
248
249 vtkDataObject* inputDO = this->GetInputDataObject(0, 0);
250
251 // Check input for consistency
252 //
253 // Create a default source, if no source is specified.
254 if (!this->UseSourceTableTree && this->GetSource(0) == nullptr)
255 {
256 vtkPolyData *defaultSource = vtkPolyData::New();
257 defaultSource->Allocate();
258 vtkPoints *defaultPoints = vtkPoints::New();
259 defaultPoints->Allocate(6);
260 defaultPoints->InsertNextPoint(0., 0., 0.);
261 defaultPoints->InsertNextPoint(1., 0., 0.);
262 vtkIdType defaultPointIds[2];
263 defaultPointIds[0] = 0;
264 defaultPointIds[1] = 1;
265 defaultSource->SetPoints(defaultPoints);
266 defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
267 this->SetSourceData(defaultSource);
268 defaultSource->Delete();
269 defaultSource = nullptr;
270 defaultPoints->Delete();
271 defaultPoints = nullptr;
272 }
273
274 // Check that source configuration is sane:
275 vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
276 int numSourceDataSets = this->GetNumberOfInputConnections(1);
277 if (this->UseSourceTableTree)
278 {
279 if (numSourceDataSets > 1)
280 {
281 vtkErrorMacro("UseSourceTableTree is true, but multiple source datasets "
282 "are set.");
283 return;
284 }
285 if (!sourceTableTree)
286 {
287 vtkErrorMacro("UseSourceTableTree is true, but the source dataset is "
288 "not a vtkDataObjectTree.");
289 return;
290 }
291 vtkDataObjectTreeIterator *it = sourceTableTree->NewTreeIterator();
292 it->SetTraverseSubTree(false);
293 it->SetVisitOnlyLeaves(false);
294 for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
295 {
296 vtkDataObject *node = it->GetCurrentDataObject();
297 if (!node->IsA("vtkPolyData") && !node->IsA("vtkCompositeDataSet"))
298 {
299 vtkErrorMacro("The source table tree must only contain vtkPolyData "
300 "or vtkCompositeDataSet children, but found a "
301 << node->GetClassName() << ".");
302 it->Delete();
303 return;
304 }
305 }
306 it->Delete();
307 }
308 else
309 {
310 for (int i = 0; i < numSourceDataSets; ++i)
311 {
312 if (!this->GetSource(i))
313 {
314 vtkErrorMacro("Source input at index " << i << " not set, or not "
315 "vtkPolyData.");
316 return;
317 }
318 }
319 }
320
321 // Render the input dataset or every dataset in the input composite dataset.
322 this->BlockMTime = this->BlockAttributes ? this->BlockAttributes->GetMTime() : 0;
323 vtkDataSet* ds = vtkDataSet::SafeDownCast(inputDO);
324 vtkCompositeDataSet* cd = vtkCompositeDataSet::SafeDownCast(inputDO);
325 if (ds)
326 {
327 this->Render(ren, actor, ds);
328 }
329 else if (cd)
330 {
331 vtkNew<vtkActor> blockAct;
332 vtkNew<vtkProperty> blockProp;
333 blockAct->ShallowCopy(actor);
334 blockProp->DeepCopy(blockAct->GetProperty());
335 blockAct->SetProperty(blockProp.GetPointer());
336 double origColor[4];
337 blockProp->GetColor(origColor);
338 vtkCompositeDataIterator* iter = cd->NewIterator();
339 for (iter->InitTraversal(); !iter->IsDoneWithTraversal();
340 iter->GoToNextItem())
341 {
342 auto curIndex = iter->GetCurrentFlatIndex();
343 auto currentObj = iter->GetCurrentDataObject();
344 // Skip invisible blocks and unpickable ones when performing selection:
345 bool blockVis =
346 (this->BlockAttributes && this->BlockAttributes->HasBlockVisibility(currentObj)) ?
347 this->BlockAttributes->GetBlockVisibility(currentObj) : true;
348 bool blockPick =
349 (this->BlockAttributes && this->BlockAttributes->HasBlockPickability(currentObj)) ?
350 this->BlockAttributes->GetBlockPickability(currentObj) : true;
351 if (!blockVis || (selector && !blockPick))
352 {
353 continue;
354 }
355 ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
356 if (ds)
357 {
358 if (selector)
359 {
360 selector->RenderCompositeIndex(curIndex);
361 }
362 else if (this->BlockAttributes && this->BlockAttributes->HasBlockColor(currentObj))
363 {
364 double color[3];
365 this->BlockAttributes->GetBlockColor(currentObj, color);
366 blockProp->SetColor(color);
367 }
368 else
369 {
370 blockProp->SetColor(origColor);
371 }
372 this->Render(ren, blockAct.GetPointer(), ds);
373 }
374 }
375 iter->Delete();
376 }
377
378 if (selector)
379 {
380 selector->EndRenderProp();
381 }
382
383 vtkOpenGLCheckErrorMacro("Failed after Render");
384
385 this->UpdateProgress(1.0);
386 }
387
388 // ---------------------------------------------------------------------------
Render(vtkRenderer * ren,vtkActor * actor,vtkDataSet * dataset)389 void vtkOpenGLGlyph3DMapper::Render(
390 vtkRenderer* ren, vtkActor* actor, vtkDataSet* dataset)
391 {
392 vtkIdType numPts = dataset->GetNumberOfPoints();
393 if (numPts < 1)
394 {
395 vtkDebugMacro(<<"No points to glyph!");
396 return;
397 }
398
399 // make sure we have an entry for this dataset
400 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *subarray;
401 bool rebuild = false;
402 typedef std::map<const vtkDataSet *,vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator GVIter;
403 GVIter found = this->GlyphValues->Entries.find(dataset);
404 if (found == this->GlyphValues->Entries.end())
405 {
406 subarray = new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray();
407 this->GlyphValues->Entries.insert(std::make_pair(dataset, subarray));
408 rebuild = true;
409 }
410 else
411 {
412 subarray = found->second;
413 }
414
415 // make sure we have a subentry for each source
416 vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
417 int sTTSize = getNumberOfChildren(sourceTableTree);
418 int numSourceDataSets = this->GetNumberOfInputConnections(1);
419 size_t numberOfSources = this->UseSourceTableTree ? sTTSize
420 : numSourceDataSets;
421 bool numberOfSourcesChanged = false;
422 if (numberOfSources != subarray->Entries.size())
423 {
424 subarray->ClearEntries();
425 for (size_t cc = 0; cc < numberOfSources; cc++)
426 {
427 subarray->Entries.push_back(
428 new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry());
429 }
430 numberOfSourcesChanged = true;
431 }
432
433 // make sure sources are up to date
434 vtkDataObjectTreeIterator *sTTIter = nullptr;
435 if (sourceTableTree)
436 {
437 sTTIter = sourceTableTree->NewTreeIterator();
438 sTTIter->SetTraverseSubTree(false);
439 sTTIter->SetVisitOnlyLeaves(false);
440 sTTIter->InitTraversal();
441 }
442 for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
443 {
444 vtkDataObject *s = this->UseSourceTableTree
445 ? sTTIter->GetCurrentDataObject()
446 : this->GetSource(static_cast<int>(cc));
447
448 vtkOpenGLGlyph3DMapperEntry *entry = subarray->Entries[cc];
449 vtkDataObject *ss = entry->DataObject;
450 if (ss && !ss->IsA(s->GetClassName()))
451 {
452 ss->Delete();
453 ss = nullptr;
454 }
455 if (!ss)
456 {
457 ss = s->NewInstance();
458 entry->DataObject = ss;
459 }
460 if (numberOfSourcesChanged ||
461 s->GetMTime() > ss->GetMTime() ||
462 this->GetMTime() > entry->BuildTime)
463 {
464 ss->ShallowCopy(s);
465 entry->ClearMappers();
466 }
467
468 // Create/update the helper mappers:
469 vtkCompositeDataIterator *cdsIter = nullptr;
470 if (vtkCompositeDataSet *cds = vtkCompositeDataSet::SafeDownCast(ss))
471 {
472 cdsIter = cds->NewIterator();
473 cdsIter->InitTraversal();
474 }
475
476 for (;;)
477 {
478 vtkOpenGLGlyph3DHelper *mapper = nullptr;
479
480 int mapperIdx = cdsIter ? cdsIter->GetCurrentFlatIndex() : -1;
481 vtkOpenGLGlyph3DMapperEntry::MapperMap::iterator mapIter =
482 entry->Mappers.find(mapperIdx);
483 if (mapIter == entry->Mappers.end())
484 {
485 mapper = vtkOpenGLGlyph3DHelper::New();
486 entry->Mappers.insert(std::make_pair(mapperIdx, mapper));
487 }
488 else
489 {
490 mapper = mapIter->second;
491 }
492 this->CopyInformationToSubMapper(mapper);
493
494 if (cdsIter)
495 {
496 cdsIter->GoToNextItem();
497 }
498
499 if (!cdsIter || cdsIter->IsDoneWithTraversal())
500 {
501 break;
502 }
503 }
504
505 if (cdsIter)
506 {
507 cdsIter->Delete();
508 cdsIter = nullptr;
509 }
510
511 if (sTTIter)
512 {
513 sTTIter->GoToNextItem();
514 }
515 }
516 if (sTTIter)
517 {
518 sTTIter->Delete();
519 sTTIter = nullptr;
520 }
521
522 // rebuild all entries for this DataSet if it
523 // has been modified
524 if (subarray->BuildTime < dataset->GetMTime() ||
525 subarray->BuildTime < this->GetMTime() ||
526 subarray->BuildTime < this->BlockMTime)
527 {
528 rebuild = true;
529 }
530
531 // get the mask array
532 vtkBitArray *maskArray = nullptr;
533 if (this->Masking)
534 {
535 maskArray = vtkArrayDownCast<vtkBitArray>(this->GetMaskArray(dataset));
536 if (maskArray == nullptr)
537 {
538 vtkDebugMacro(<<"masking is enabled but there is no mask array. Ignore masking.");
539 }
540 else
541 {
542 if (maskArray->GetNumberOfComponents() != 1)
543 {
544 vtkErrorMacro(" expecting a mask array with one component, getting "
545 << maskArray->GetNumberOfComponents() << " components.");
546 return;
547 }
548 }
549 }
550
551 // rebuild all sources for this dataset
552 if (rebuild)
553 {
554 this->RebuildStructures(subarray, numPts, actor, dataset, maskArray);
555 }
556
557 // for each subarray
558 for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
559 {
560 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
561 subarray->Entries[cc];
562 if (entry->NumberOfPoints <= 0)
563 {
564 continue;
565 }
566
567 vtkDataObject *dObj = entry->DataObject;
568 vtkPolyData *pd = vtkPolyData::SafeDownCast(dObj);
569 vtkCompositeDataSet *cds = pd ? nullptr
570 : vtkCompositeDataSet::SafeDownCast(dObj);
571
572 vtkCompositeDataIterator *cdsIter = nullptr;
573 if (cds)
574 {
575 cdsIter = cds->NewIterator();
576 cdsIter->InitTraversal();
577 }
578
579 // Either render the polydata, or loop through the composite dataset and
580 // render each polydata leaf:
581 for (;;)
582 {
583 int mapperIdx = -1;
584 if (cdsIter)
585 {
586 pd = vtkPolyData::SafeDownCast(cdsIter->GetCurrentDataObject());
587 mapperIdx = cdsIter->GetCurrentFlatIndex();
588 cdsIter->GoToNextItem();
589 }
590
591 if (pd && pd->GetNumberOfPoints() > 0)
592 {
593 vtkOpenGLGlyph3DHelper *gh = entry->Mappers[mapperIdx];
594 gh->CurrentInput = pd;
595 gh->GlyphRender(ren, actor, entry->NumberOfPoints,
596 entry->Colors, entry->Matrices, entry->NormalMatrices,
597 entry->PickIds, subarray->BuildTime, this->CullingAndLOD);
598 }
599
600 if (!cdsIter || cdsIter->IsDoneWithTraversal())
601 {
602 break;
603 }
604 } // end composite glyph iteration
605
606 if (cdsIter)
607 {
608 cdsIter->Delete();
609 cdsIter = nullptr;
610 }
611 } // end entries
612
613 vtkOpenGLCheckErrorMacro("failed after Render");
614 }
615
616
617
618 // ---------------------------------------------------------------------------
RebuildStructures(vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray * subarray,vtkIdType numPts,vtkActor * actor,vtkDataSet * dataset,vtkBitArray * maskArray)619 void vtkOpenGLGlyph3DMapper::RebuildStructures(
620 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *subarray,
621 vtkIdType numPts,
622 vtkActor* actor,
623 vtkDataSet* dataset,
624 vtkBitArray *maskArray)
625 {
626 double den = this->Range[1] - this->Range[0];
627 if (den == 0.0)
628 {
629 den = 1.0;
630 }
631
632 unsigned char color[4];
633 {
634 const double *actorColor = actor->GetProperty()->GetColor();
635 for (int i = 0; i != 3; ++i)
636 {
637 color[i] = static_cast<unsigned char>(actorColor[i] * 255. + 0.5);
638 }
639 color[3] =
640 static_cast<unsigned char>(actor->GetProperty()->GetOpacity()*255. + 0.5);
641 }
642
643 vtkDataArray* orientArray = this->GetOrientationArray(dataset);
644 if (orientArray != nullptr)
645 {
646 if ((this->OrientationMode == ROTATION || this->OrientationMode == DIRECTION) && orientArray->GetNumberOfComponents() != 3)
647 {
648 vtkErrorMacro(" expecting an orientation array with 3 components, getting "
649 << orientArray->GetNumberOfComponents() << " components.");
650 return;
651 }
652 else if (this->OrientationMode == QUATERNION && orientArray->GetNumberOfComponents() != 4)
653 {
654 vtkErrorMacro(" expecting an orientation array with 4 components, getting "
655 << orientArray->GetNumberOfComponents() << " components.");
656 return;
657 }
658 }
659
660 vtkDataArray* indexArray = this->GetSourceIndexArray(dataset);
661 vtkDataArray* scaleArray = this->GetScaleArray(dataset);
662 vtkDataArray* selectionArray = this->GetSelectionIdArray(dataset);
663
664 /// FIXME: Didn't handle the premultiplycolorswithalpha aspect...
665 this->ColorMapper->SetInputDataObject(dataset);
666 this->ColorMapper->MapScalars(actor->GetProperty()->GetOpacity());
667 vtkUnsignedCharArray* colors = ((vtkOpenGLGlyph3DMappervtkColorMapper *)this->ColorMapper)->GetColors();
668 // Traverse all Input points, transforming Source points
669
670 int numEntries = (int)subarray->Entries.size();
671
672 // how many points for each source
673 int *numPointsPerSource = new int [numEntries];
674 std::fill(numPointsPerSource, numPointsPerSource + numEntries, 0);
675 if (numEntries > 1 && indexArray)
676 {
677 // loop over every point
678 int index = 0;
679 for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
680 {
681 if (maskArray && maskArray->GetValue(inPtId) == 0)
682 {
683 continue;
684 }
685
686 // Compute index into table of glyphs
687 if (indexArray)
688 {
689 double value = vtkMath::Norm(indexArray->GetTuple(inPtId),
690 indexArray->GetNumberOfComponents());
691 index = static_cast<int>((value-this->Range[0])*numEntries/den);
692 index = vtkMath::ClampValue(index, 0, numEntries-1);
693 }
694 numPointsPerSource[index]++;
695 }
696 }
697 else
698 {
699 numPointsPerSource[0] = numPts;
700 }
701
702 // for each entry start with a reasonable allocation
703 for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
704 {
705 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
706 subarray->Entries[cc];
707 entry->PickIds.resize(numPointsPerSource[cc]);
708 entry->Colors.resize(numPointsPerSource[cc]*4);
709 entry->Matrices.resize(numPointsPerSource[cc]*16);
710 entry->NormalMatrices.resize(numPointsPerSource[cc]*9);
711 entry->NumberOfPoints = 0;
712 entry->BuildTime.Modified();
713 }
714 delete [] numPointsPerSource;
715
716 // loop over every point and fill structures
717 int index = 0;
718 vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
719
720 // cache sources to improve performances
721 std::vector<vtkDataObject*> sourceCache(numEntries);
722 for (vtkIdType i = 0; i < numEntries; i++)
723 {
724 sourceCache[i] = this->UseSourceTableTree
725 ? getChildDataObject(sourceTableTree, i)
726 : this->GetSource(i);
727 }
728
729 double trans[16];
730 double normalTrans[9];
731
732 for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
733 {
734 if (!(inPtId % 10000))
735 {
736 this->UpdateProgress (static_cast<double>(inPtId)/
737 static_cast<double>(numPts));
738 if (this->GetAbortExecute())
739 {
740 break;
741 }
742 }
743
744 if (maskArray && maskArray->GetValue(inPtId) == 0)
745 {
746 continue;
747 }
748
749 // Compute index into table of glyphs
750 if (indexArray)
751 {
752 double value = vtkMath::Norm(indexArray->GetTuple(inPtId),
753 indexArray->GetNumberOfComponents());
754 index = static_cast<int>((value-this->Range[0])*numEntries/den);
755 index = vtkMath::ClampValue(index, 0, numEntries-1);
756 }
757
758 // source can be null.
759 vtkDataObject *source = sourceCache[index];
760
761 // Make sure we're not indexing into empty glyph
762 if (source)
763 {
764 vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
765 subarray->Entries[index];
766
767 entry->Colors[entry->NumberOfPoints*4] = color[0];
768 entry->Colors[entry->NumberOfPoints*4+1] = color[1];
769 entry->Colors[entry->NumberOfPoints*4+2] = color[2];
770 entry->Colors[entry->NumberOfPoints*4+3] = color[3];
771
772 double scalex = 1.0;
773 double scaley = 1.0;
774 double scalez = 1.0;
775 // Get the scalar and vector data
776 if (scaleArray)
777 {
778 double* tuple = scaleArray->GetTuple(inPtId);
779 switch (this->ScaleMode)
780 {
781 case SCALE_BY_MAGNITUDE:
782 scalex = scaley = scalez = vtkMath::Norm(tuple,
783 scaleArray->GetNumberOfComponents());
784 break;
785 case SCALE_BY_COMPONENTS:
786 if (scaleArray->GetNumberOfComponents() != 3)
787 {
788 vtkErrorMacro("Cannot scale by components since " <<
789 scaleArray->GetName() << " does not have 3 components.");
790 }
791 else
792 {
793 scalex = tuple[0];
794 scaley = tuple[1];
795 scalez = tuple[2];
796 }
797 break;
798 case NO_DATA_SCALING:
799 default:
800 break;
801 }
802
803 // Clamp data scale if enabled
804 if (this->Clamping && this->ScaleMode != NO_DATA_SCALING)
805 {
806 scalex = (scalex < this->Range[0] ? this->Range[0] :
807 (scalex > this->Range[1] ? this->Range[1] : scalex));
808 scalex = (scalex - this->Range[0]) / den;
809 scaley = (scaley < this->Range[0] ? this->Range[0] :
810 (scaley > this->Range[1] ? this->Range[1] : scaley));
811 scaley = (scaley - this->Range[0]) / den;
812 scalez = (scalez < this->Range[0] ? this->Range[0] :
813 (scalez > this->Range[1] ? this->Range[1] : scalez));
814 scalez = (scalez - this->Range[0]) / den;
815 }
816 }
817 scalex *= this->ScaleFactor;
818 scaley *= this->ScaleFactor;
819 scalez *= this->ScaleFactor;
820
821 // Now begin copying/transforming glyph
822 vtkMatrix4x4::Identity(trans);
823 vtkMatrix3x3::Identity(normalTrans);
824
825 // translate Source to Input point
826 double x[3];
827 dataset->GetPoint(inPtId, x);
828 trans[3] = x[0];
829 trans[7] = x[1];
830 trans[11] = x[2];
831
832 if (orientArray)
833 {
834 double orientation[4];
835 orientArray->GetTuple(inPtId, orientation);
836
837 double rotMatrix[3][3];
838 vtkQuaterniond quaternion;
839
840 switch (this->OrientationMode)
841 {
842 case ROTATION:
843 {
844 double angle = vtkMath::RadiansFromDegrees(orientation[2]);
845 vtkQuaterniond qz(cos(0.5*angle), 0.0, 0.0, sin(0.5*angle));
846
847 angle = vtkMath::RadiansFromDegrees(orientation[0]);
848 vtkQuaterniond qx(cos(0.5*angle), sin(0.5*angle), 0.0, 0.0);
849
850 angle = vtkMath::RadiansFromDegrees(orientation[1]);
851 vtkQuaterniond qy(cos(0.5*angle), 0.0, sin(0.5*angle), 0.0);
852
853 quaternion = qz*qx*qy;
854 }
855 break;
856
857 case DIRECTION:
858 if (orientation[1] == 0.0 && orientation[2] == 0.0)
859 {
860 if (orientation[0] < 0) //just flip x if we need to
861 {
862 quaternion.Set(0.0, 0.0, 1.0, 0.0);
863 }
864 }
865 else
866 {
867 double vMag = vtkMath::Norm(orientation);
868 double vNew[3];
869 vNew[0] = (orientation[0] + vMag) / 2.0;
870 vNew[1] = orientation[1] / 2.0;
871 vNew[2] = orientation[2] / 2.0;
872
873 double f = 1.0/sqrt(vNew[0]*vNew[0]+vNew[1]*vNew[1]+vNew[2]*vNew[2]);
874 vNew[0] *= f;
875 vNew[1] *= f;
876 vNew[2] *= f;
877
878 quaternion.Set(0.0, vNew[0], vNew[1], vNew[2]);
879 }
880 break;
881
882 case QUATERNION:
883 quaternion.Set(orientation);
884 break;
885 }
886
887 quaternion.ToMatrix3x3(rotMatrix);
888
889 for (int i = 0; i < 3; i++)
890 {
891 for (int j = 0; j < 3; j++)
892 {
893 trans[4*i+j] = rotMatrix[i][j];
894 normalTrans[3*i+j] = rotMatrix[j][i]; // transpose
895 }
896 }
897 }
898
899 // Set pickid
900 // Use selectionArray value or glyph point ID.
901 vtkIdType selectionId = inPtId;
902 if (this->UseSelectionIds)
903 {
904 if (selectionArray == nullptr ||
905 selectionArray->GetNumberOfTuples() == 0)
906 {
907 vtkWarningMacro(<<"UseSelectionIds is true, but selection array"
908 " is invalid. Ignoring selection array.");
909 }
910 else
911 {
912 selectionId = static_cast<vtkIdType>(
913 *selectionArray->GetTuple(inPtId));
914 }
915 }
916 entry->PickIds[entry->NumberOfPoints] = selectionId;
917
918 if (colors)
919 {
920 colors->GetTypedTuple(inPtId, &(entry->Colors[entry->NumberOfPoints*4]));
921 }
922
923 // scale data if appropriate
924 if (this->Scaling)
925 {
926 if (scalex == 0.0)
927 {
928 scalex = 1.0e-10;
929 }
930 if (scaley == 0.0)
931 {
932 scaley = 1.0e-10;
933 }
934 if (scalez == 0.0)
935 {
936 scalez = 1.0e-10;
937 }
938
939 for (int i = 0; i < 3; i++)
940 {
941 // inverse of normal matrix is directly computed with inverse scale
942 trans[4*i] *= scalex;
943 normalTrans[i] /= scalex;
944 trans[4*i+1] *= scaley;
945 normalTrans[i+3] /= scaley;
946 trans[4*i+2] *= scalez;
947 normalTrans[i+6] /= scalez;
948 }
949 }
950
951 float* matrices = &entry->Matrices[entry->NumberOfPoints*16];
952 float* normalMatrices = &entry->NormalMatrices[entry->NumberOfPoints*9];
953
954 for (int i = 0; i < 4; i++)
955 {
956 for (int j = 0; j < 4; j++)
957 {
958 matrices[i*4+j] = trans[j*4+i];
959 }
960 }
961
962 for (int i = 0; i < 3; i++)
963 {
964 for (int j = 0; j < 3; j++)
965 {
966 normalMatrices[i*3+j] = normalTrans[i*3+j];
967 }
968 }
969 entry->NumberOfPoints++;
970 }
971 }
972
973 subarray->BuildTime.Modified();
974 }
975
976
977 // ---------------------------------------------------------------------------
978 // Description:
979 // Release any graphics resources that are being consumed by this mapper.
ReleaseGraphicsResources(vtkWindow * window)980 void vtkOpenGLGlyph3DMapper::ReleaseGraphicsResources(vtkWindow *window)
981 {
982 if (this->GlyphValues)
983 {
984 std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator miter = this->GlyphValues->Entries.begin();
985 for (;miter != this->GlyphValues->Entries.end(); ++miter)
986 {
987 std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *>::iterator miter2 = miter->second->Entries.begin();
988 for (;miter2 != miter->second->Entries.end(); ++miter2)
989 {
990 vtkOpenGLGlyph3DMapperEntry::MapperMap::iterator miter3 = (*miter2)->Mappers.begin();
991 for (; miter3 != (*miter2)->Mappers.end(); ++miter3)
992 {
993 miter3->second->ReleaseGraphicsResources(window);
994 }
995 }
996 }
997 }
998 }
999
1000 //---------------------------------------------------------------------------
GetMaxNumberOfLOD()1001 vtkIdType vtkOpenGLGlyph3DMapper::GetMaxNumberOfLOD()
1002 {
1003 #ifndef GL_ES_VERSION_3_0
1004 if (!GLEW_ARB_gpu_shader5 || !GLEW_ARB_transform_feedback3)
1005 {
1006 return 0;
1007 }
1008
1009 GLint streams, maxsize;
1010 glGetIntegerv(GL_MAX_VERTEX_STREAMS, &streams);
1011 glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &maxsize);
1012 maxsize /= 32; // each stream size can be 29 bytes (16 for transform matrix, 9 for normal, 4 for color)
1013
1014 vtkIdType maxstreams = static_cast<vtkIdType>(std::min(streams, maxsize));
1015 return maxstreams - 1;
1016 #else
1017 return 0;
1018 #endif
1019 }
1020
1021 //---------------------------------------------------------------------------
SetNumberOfLOD(vtkIdType nb)1022 void vtkOpenGLGlyph3DMapper::SetNumberOfLOD(vtkIdType nb)
1023 {
1024 this->LODs.resize(nb, {0.f, 0.f});
1025 }
1026
1027 //---------------------------------------------------------------------------
SetLODDistanceAndTargetReduction(vtkIdType index,float distance,float targetReduction)1028 void vtkOpenGLGlyph3DMapper::SetLODDistanceAndTargetReduction(vtkIdType index, float distance, float targetReduction)
1029 {
1030 if (index < static_cast<vtkIdType>(this->LODs.size()))
1031 {
1032 this->LODs[index] = {vtkMath::Max(0.f, distance), vtkMath::ClampValue(targetReduction, 0.f, 1.f)};
1033 }
1034 }
1035
1036 // ----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1037 void vtkOpenGLGlyph3DMapper::PrintSelf(ostream& os, vtkIndent indent)
1038 {
1039 this->Superclass::PrintSelf(os, indent);
1040 }
1041