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