1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkCompositePolyDataMapper2.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 "vtkCompositePolyDataMapper2.h"
16 
17 #include "vtk_glew.h"
18 
19 #include "vtkBoundingBox.h"
20 #include "vtkCellData.h"
21 #include "vtkColorTransferFunction.h"
22 #include "vtkCommand.h"
23 #include "vtkCompositeDataDisplayAttributes.h"
24 #include "vtkCompositeDataIterator.h"
25 #include "vtkCompositeDataPipeline.h"
26 #include "vtkCompositeDataSet.h"
27 #include "vtkDataObjectTreeIterator.h"
28 #include "vtkFloatArray.h"
29 #include "vtkHardwareSelector.h"
30 #include "vtkImageData.h"
31 #include "vtkInformation.h"
32 #include "vtkLookupTable.h"
33 #include "vtkMultiBlockDataSet.h"
34 #include "vtkMultiPieceDataSet.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkOpenGLIndexBufferObject.h"
37 #include "vtkOpenGLRenderWindow.h"
38 #include "vtkOpenGLRenderer.h"
39 #include "vtkOpenGLTexture.h"
40 #include "vtkOpenGLVertexBufferObject.h"
41 #include "vtkOpenGLVertexBufferObjectGroup.h"
42 #include "vtkPointData.h"
43 #include "vtkPolyData.h"
44 #include "vtkProperty.h"
45 #include "vtkScalarsToColors.h"
46 #include "vtkShaderProgram.h"
47 #include "vtkTextureObject.h"
48 #include "vtkTransform.h"
49 #include "vtkUnsignedIntArray.h"
50 
51 #include <algorithm>
52 #include <sstream>
53 
54 #include "vtkCompositePolyDataMapper2Internal.h"
55 
56 typedef std::map<vtkPolyData *, vtkCompositeMapperHelperData *>::iterator dataIter;
57 typedef std::map<const std::string, vtkCompositeMapperHelper2 *>::iterator helpIter;
58 
59 vtkStandardNewMacro(vtkCompositeMapperHelper2);
60 
~vtkCompositeMapperHelper2()61 vtkCompositeMapperHelper2::~vtkCompositeMapperHelper2()
62 {
63   for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
64   {
65     delete it->second;
66   }
67   this->Data.clear();
68 }
69 
SetShaderValues(vtkShaderProgram * prog,vtkCompositeMapperHelperData * hdata,size_t primOffset)70 void vtkCompositeMapperHelper2::SetShaderValues(
71   vtkShaderProgram *prog,
72   vtkCompositeMapperHelperData *hdata,
73   size_t primOffset)
74 {
75   if (this->PrimIDUsed)
76   {
77     prog->SetUniformi("PrimitiveIDOffset",
78       static_cast<int>(primOffset));
79   }
80 
81   if (this->CurrentSelector)
82   {
83     if (this->CurrentSelector->GetCurrentPass() ==
84         vtkHardwareSelector::COMPOSITE_INDEX_PASS &&
85         prog->IsUniformUsed("mapperIndex"))
86     {
87       this->CurrentSelector->RenderCompositeIndex(hdata->FlatIndex);
88       prog->SetUniform3f("mapperIndex",
89         this->CurrentSelector->GetPropColorValue());
90     }
91     return;
92   }
93 
94   // If requested, color partial / missing arrays with NaN color.
95   bool useNanColor = false;
96   double nanColor[4] = { -1., -1., -1., -1 };
97   if (this->Parent->GetColorMissingArraysWithNanColor() &&
98       this->GetScalarVisibility())
99   {
100     int cellFlag = 0;
101     vtkAbstractArray *scalars = vtkAbstractMapper::GetAbstractScalars(
102           hdata->Data, this->ScalarMode, this->ArrayAccessMode, this->ArrayId,
103           this->ArrayName, cellFlag);
104     if (scalars == nullptr)
105     {
106       vtkLookupTable *lut = vtkLookupTable::SafeDownCast(this->GetLookupTable());
107       vtkColorTransferFunction *ctf = lut ? nullptr :
108            vtkColorTransferFunction::SafeDownCast(this->GetLookupTable());
109       if (lut)
110       {
111         lut->GetNanColor(nanColor);
112         useNanColor = true;
113       }
114       else if (ctf)
115       {
116         ctf->GetNanColor(nanColor);
117         useNanColor = true;
118       }
119     }
120   }
121 
122   // override the opacity and color
123   prog->SetUniformf("opacityUniform", hdata->Opacity);
124 
125   if (useNanColor)
126   {
127     float fnancolor[3] = {
128       static_cast<float>(nanColor[0]),
129       static_cast<float>(nanColor[1]),
130       static_cast<float>(nanColor[2])
131     };
132     prog->SetUniform3f("ambientColorUniform", fnancolor);
133     prog->SetUniform3f("diffuseColorUniform", fnancolor);
134   }
135   else
136   {
137     vtkColor3d &aColor = hdata->AmbientColor;
138     float ambientColor[3] = {
139       static_cast<float>(aColor[0]),
140       static_cast<float>(aColor[1]),
141       static_cast<float>(aColor[2])
142     };
143     vtkColor3d &dColor = hdata->DiffuseColor;
144     float diffuseColor[3] = {
145       static_cast<float>(dColor[0]),
146       static_cast<float>(dColor[1]),
147       static_cast<float>(dColor[2])
148     };
149     prog->SetUniform3f("ambientColorUniform", ambientColor);
150     prog->SetUniform3f("diffuseColorUniform", diffuseColor);
151     if (this->OverideColorUsed)
152     {
153       prog->SetUniformi("OverridesColor", hdata->OverridesColor);
154     }
155   }
156 }
157 
UpdateShaders(vtkOpenGLHelper & cellBO,vtkRenderer * ren,vtkActor * act)158 void vtkCompositeMapperHelper2::UpdateShaders(
159   vtkOpenGLHelper &cellBO, vtkRenderer *ren, vtkActor *act)
160 {
161   Superclass::UpdateShaders(cellBO, ren, act);
162   if (cellBO.Program && this->Parent)
163   {
164     // allow the program to set what it wants
165     this->Parent->InvokeEvent(vtkCommand::UpdateShaderEvent, cellBO.Program);
166   }
167 }
168 
ReplaceShaderColor(std::map<vtkShader::Type,vtkShader * > shaders,vtkRenderer * ren,vtkActor * actor)169 void vtkCompositeMapperHelper2::ReplaceShaderColor(
170   std::map<vtkShader::Type, vtkShader *> shaders,
171   vtkRenderer *ren, vtkActor *actor)
172 {
173   if (!this->CurrentSelector)
174   {
175     std::string FSSource = shaders[vtkShader::Fragment]->GetSource();
176 
177     vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Dec",
178       "uniform bool OverridesColor;\n"
179       "//VTK::Color::Dec",false);
180 
181     vtkShaderProgram::Substitute(FSSource,"//VTK::Color::Impl",
182       "//VTK::Color::Impl\n"
183       "  if (OverridesColor) {\n"
184       "    ambientColor = ambientColorUniform * ambientIntensity;\n"
185       "    diffuseColor = diffuseColorUniform * diffuseIntensity; }\n",
186       false);
187 
188     shaders[vtkShader::Fragment]->SetSource(FSSource);
189   }
190 
191   this->Superclass::ReplaceShaderColor(shaders,ren,actor);
192 }
193 
ClearMark()194 void vtkCompositeMapperHelper2::ClearMark()
195 {
196   for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
197   {
198     it->second->Marked = false;
199   }
200   this->Marked = false;
201 }
202 
RemoveUnused()203 void vtkCompositeMapperHelper2::RemoveUnused()
204 {
205   for (dataIter it = this->Data.begin(); it != this->Data.end(); )
206   {
207     if (!it->second->Marked)
208     {
209       delete it->second;
210       this->Data.erase(it++);
211       this->Modified();
212     }
213     else
214     {
215       ++it;
216     }
217   }
218 }
219 
220 //-----------------------------------------------------------------------------
221 // Returns if we can use texture maps for scalar coloring. Note this doesn't say
222 // we "will" use scalar coloring. It says, if we do use scalar coloring, we will
223 // use a texture.
224 // When rendering multiblock datasets, if any 2 blocks provide different
225 // lookup tables for the scalars, then also we cannot use textures. This case can
226 // be handled if required.
CanUseTextureMapForColoring(vtkDataObject *)227 int vtkCompositeMapperHelper2::CanUseTextureMapForColoring(vtkDataObject*)
228 {
229   if (!this->InterpolateScalarsBeforeMapping)
230   {
231     return 0; // user doesn't want us to use texture maps at all.
232   }
233 
234   int cellFlag=0;
235   vtkScalarsToColors *scalarsLookupTable = nullptr;
236   for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
237   {
238     vtkPolyData *pd = it->second->Data;
239     vtkDataArray* scalars = vtkAbstractMapper::GetScalars(pd,
240       this->ScalarMode, this->ArrayAccessMode, this->ArrayId,
241       this->ArrayName, cellFlag);
242 
243     if (scalars)
244     {
245       if (cellFlag)
246       {
247         return 0;
248       }
249       if ((this->ColorMode == VTK_COLOR_MODE_DEFAULT &&
250            vtkArrayDownCast<vtkUnsignedCharArray>(scalars)) ||
251           this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS)
252       {
253         // Don't use texture if direct coloring using RGB unsigned chars is
254         // requested.
255         return 0;
256       }
257 
258       if (scalarsLookupTable && scalars->GetLookupTable() &&
259           (scalarsLookupTable != scalars->GetLookupTable()))
260       {
261         // Two datasets are requesting different lookup tables to color with.
262         // We don't handle this case right now for composite datasets.
263         return 0;
264       }
265       if (scalars->GetLookupTable())
266       {
267         scalarsLookupTable = scalars->GetLookupTable();
268       }
269     }
270   }
271 
272   if ((scalarsLookupTable &&
273        scalarsLookupTable->GetIndexedLookup()) ||
274       (!scalarsLookupTable &&
275        this->LookupTable &&
276        this->LookupTable->GetIndexedLookup()))
277   {
278       return 0;
279   }
280 
281   return 1;
282 }
283 
284 //-----------------------------------------------------------------------------
RenderPiece(vtkRenderer * ren,vtkActor * actor)285 void vtkCompositeMapperHelper2::RenderPiece(vtkRenderer* ren, vtkActor *actor)
286 {
287   // Make sure that we have been properly initialized.
288   if (ren->GetRenderWindow()->CheckAbortStatus())
289   {
290     return;
291   }
292 
293   this->CurrentInput = this->Data.begin()->first;
294 
295   this->RenderPieceStart(ren, actor);
296   this->RenderPieceDraw(ren, actor);
297   this->RenderPieceFinish(ren, actor);
298 }
299 
DrawIBO(vtkRenderer * ren,vtkActor * actor,int primType,vtkOpenGLHelper & CellBO,GLenum mode,int pointSize)300 void vtkCompositeMapperHelper2::DrawIBO(
301   vtkRenderer* ren, vtkActor *actor,
302   int primType,
303   vtkOpenGLHelper &CellBO,
304   GLenum mode,
305   int pointSize)
306 {
307   if (CellBO.IBO->IndexCount)
308   {
309     if (pointSize > 0)
310     {
311 #if GL_ES_VERSION_3_0 != 1
312       glPointSize(pointSize); // need to use shader value
313 #endif
314     }
315     // First we do the triangles, update the shader, set uniforms, etc.
316     this->UpdateShaders(CellBO, ren, actor);
317     vtkShaderProgram *prog = CellBO.Program;
318     if (!prog)
319     {
320       return;
321     }
322     this->PrimIDUsed = prog->IsUniformUsed("PrimitiveIDOffset");
323     this->OverideColorUsed = prog->IsUniformUsed("OverridesColor");
324     CellBO.IBO->Bind();
325 
326     if (!this->HaveWideLines(ren,actor) && mode == GL_LINES)
327     {
328       glLineWidth(actor->GetProperty()->GetLineWidth());
329     }
330 
331     // if (this->DrawingEdgesOrVetices && !this->DrawingTubes(CellBO, actor))
332     // {
333     //   vtkProperty *ppty = actor->GetProperty();
334     //   float diffuseColor[3] = {0.0, 0.0, 0.0};
335     //   float ambientColor[3];
336     //   double *acol = ppty->GetEdgeColor();
337     //   ambientColor[0] = acol[0];
338     //   ambientColor[1] = acol[1];
339     //   ambientColor[2] = acol[2];
340     //   prog->SetUniform3f("diffuseColorUniform", diffuseColor);
341     //   prog->SetUniform3f("ambientColorUniform", ambientColor);
342     // }
343 
344     this->RenderedList.clear();
345     bool selecting = (this->CurrentSelector ? true : false);
346     for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
347     {
348       vtkCompositeMapperHelperData *starthdata = it->second;
349       if (starthdata->Visibility &&
350           ((selecting && starthdata->Pickability) || !selecting) &&
351           starthdata->NextIndex[primType] > starthdata->StartIndex[primType])
352       {
353         //compilers think this can exceed the bounds so we also
354         // test against primType even though we should not need to
355         if (primType <= PrimitiveTriStrips)
356         {
357           this->SetShaderValues(prog, starthdata,
358             starthdata->PrimOffsets[primType]);
359         }
360         glDrawRangeElements(mode,
361           static_cast<GLuint>(starthdata->StartVertex),
362           static_cast<GLuint>(starthdata->NextVertex > 0 ? starthdata->NextVertex - 1 : 0),
363           static_cast<GLsizei>(starthdata->NextIndex[primType] - starthdata->StartIndex[primType]),
364           GL_UNSIGNED_INT,
365           reinterpret_cast<const GLvoid *>(starthdata->StartIndex[primType]*sizeof(GLuint)));
366       }
367     }
368     CellBO.IBO->Release();
369   }
370 }
371 
372 //-----------------------------------------------------------------------------
RenderPieceDraw(vtkRenderer * ren,vtkActor * actor)373 void vtkCompositeMapperHelper2::RenderPieceDraw(
374   vtkRenderer* ren, vtkActor *actor)
375 {
376   int representation = actor->GetProperty()->GetRepresentation();
377 
378   // render points for point picking in a special way
379   // all cell types should be rendered as points
380   this->CurrentSelector = ren->GetSelector();
381   bool pointPicking = false;
382   if (this->CurrentSelector && this->PopulateSelectionSettings &&
383       this->CurrentSelector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
384   {
385     representation = VTK_POINTS;
386     pointPicking = true;
387   }
388 
389   this->PrimitiveIDOffset = 0;
390 
391   // draw IBOs
392   for (int i = PrimitiveStart;
393     i < (this->CurrentSelector ? PrimitiveTriStrips + 1 : PrimitiveEnd); i++)
394   {
395     this->DrawingEdgesOrVertices =
396      (i > PrimitiveTriStrips ? true :false);
397     GLenum mode = this->GetOpenGLMode(representation, i);
398     this->DrawIBO(ren, actor, i, this->Primitives[i], mode,
399       pointPicking ? this->GetPointPickingPrimitiveSize(i) : 0);
400   }
401 
402   if (this->CurrentSelector && (
403         this->CurrentSelector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_LOW24 ||
404         this->CurrentSelector->GetCurrentPass() == vtkHardwareSelector::CELL_ID_HIGH24))
405   {
406     this->CurrentSelector->SetPropColorValue(this->PrimitiveIDOffset);
407   }
408 }
409 
AddData(vtkPolyData * pd,unsigned int flatIndex)410 vtkCompositeMapperHelperData *vtkCompositeMapperHelper2::AddData(
411   vtkPolyData *pd, unsigned int flatIndex)
412 {
413   dataIter found = this->Data.find(pd);
414   if (found == this->Data.end())
415   {
416     vtkCompositeMapperHelperData *hdata =
417       new vtkCompositeMapperHelperData();
418     hdata->FlatIndex = flatIndex;
419     hdata->Data = pd;
420     hdata->Marked = true;
421     this->Data.insert(std::make_pair(pd, hdata));
422     this->Modified();
423     return hdata;
424   }
425   found->second->Marked = true;
426   return found->second;
427 }
428 
429 //-------------------------------------------------------------------------
BuildBufferObjects(vtkRenderer * ren,vtkActor * act)430 void vtkCompositeMapperHelper2::BuildBufferObjects(
431   vtkRenderer *ren,
432   vtkActor *act)
433 {
434   // render using the composite data attributes
435 
436   // create the cell scalar array adjusted for ogl Cells
437   std::vector<unsigned char> newColors;
438   std::vector<float> newNorms;
439 
440   // check if this system is subject to the apple/amd primID bug
441   this->HaveAppleBug =
442     static_cast<vtkOpenGLRenderer *>(ren)->HaveApplePrimitiveIdBug();
443   if (this->HaveAppleBugForce == 1)
444   {
445     this->HaveAppleBug = false;
446   }
447   if (this->HaveAppleBugForce == 2)
448   {
449     this->HaveAppleBug = true;
450   }
451   this->AppleBugPrimIDs.resize(0);
452 
453   dataIter iter;
454   this->VBOs->ClearAllVBOs();
455 
456   if (this->Data.begin() == this->Data.end())
457   {
458     this->VBOBuildTime.Modified();
459     return;
460   }
461 
462   vtkBoundingBox bbox;
463   double bounds[6];
464   this->Data.begin()->second->Data->GetPoints()->GetBounds(bounds);
465   bbox.SetBounds(bounds);
466   for (iter = this->Data.begin(); iter != this->Data.end(); ++iter)
467   {
468     vtkCompositeMapperHelperData *hdata = iter->second;
469 
470     hdata->Data->GetPoints()->GetBounds(bounds);
471     bbox.AddBounds(bounds);
472 
473     for (int i = 0; i < PrimitiveEnd; i++)
474     {
475       hdata->StartIndex[i] =
476         static_cast<unsigned int>(this->IndexArray[i].size());
477     }
478 
479     vtkIdType voffset = 0;
480     this->AppendOneBufferObject(ren, act, hdata,
481       voffset, newColors, newNorms);
482     hdata->StartVertex = static_cast<unsigned int>(voffset);
483     hdata->NextVertex = hdata->StartVertex + hdata->Data->GetPoints()->GetNumberOfPoints();
484     for (int i = 0; i < PrimitiveEnd; i++)
485     {
486       hdata->NextIndex[i] =
487         static_cast<unsigned int>(this->IndexArray[i].size());
488     }
489   }
490 
491   // clear color cache
492   for (auto& c : this->ColorArrayMap)
493   {
494     c.second->Delete();
495   }
496   this->ColorArrayMap.clear();
497 
498   vtkOpenGLVertexBufferObject *posVBO = this->VBOs->GetVBO("vertexMC");
499   if (posVBO && this->ShiftScaleMethod ==
500       vtkOpenGLVertexBufferObject::AUTO_SHIFT_SCALE)
501   {
502     posVBO->SetCoordShiftAndScaleMethod(vtkOpenGLVertexBufferObject::MANUAL_SHIFT_SCALE);
503     bbox.GetBounds(bounds);
504     std::vector<double> shift;
505     std::vector<double> scale;
506     for (int i = 0; i < 3; i++)
507     {
508       shift.push_back(0.5*(bounds[i*2] + bounds[i*2+1]));
509       scale.push_back((bounds[i*2+1] - bounds[i*2]) ? 1.0/(bounds[i*2+1] - bounds[i*2]) : 1.0);
510     }
511     posVBO->SetShift(shift);
512     posVBO->SetScale(scale);
513     // If the VBO coordinates were shifted and scaled, prepare the inverse transform
514     // for application to the model->view matrix:
515     if (posVBO->GetCoordShiftAndScaleEnabled())
516     {
517       this->VBOInverseTransform->Identity();
518       this->VBOInverseTransform->Translate(shift[0], shift[1], shift[2]);
519       this->VBOInverseTransform->Scale(1.0/scale[0], 1.0/scale[1], 1.0/scale[2]);
520       this->VBOInverseTransform->GetTranspose(this->VBOShiftScale);
521     }
522   }
523 
524   this->VBOs->BuildAllVBOs(ren);
525 
526   for (int i = PrimitiveStart; i < PrimitiveEnd; i++)
527   {
528     this->Primitives[i].IBO->IndexCount = this->IndexArray[i].size();
529     if (this->Primitives[i].IBO->IndexCount)
530     {
531       this->Primitives[i].IBO->Upload(this->IndexArray[i],
532        vtkOpenGLBufferObject::ElementArrayBuffer);
533       this->IndexArray[i].resize(0);
534     }
535   }
536 
537   // allocate as needed
538   if (this->HaveCellScalars)
539   {
540     if (!this->CellScalarTexture)
541     {
542       this->CellScalarTexture = vtkTextureObject::New();
543       this->CellScalarBuffer = vtkOpenGLBufferObject::New();
544     }
545     this->CellScalarTexture->SetContext(
546       static_cast<vtkOpenGLRenderWindow*>(ren->GetVTKWindow()));
547     this->CellScalarBuffer->Upload(newColors,
548       vtkOpenGLBufferObject::TextureBuffer);
549     this->CellScalarTexture->CreateTextureBuffer(
550       static_cast<unsigned int>(newColors.size()/4),
551       4,
552       VTK_UNSIGNED_CHAR,
553       this->CellScalarBuffer);
554   }
555 
556   if (this->HaveCellNormals)
557   {
558     if (!this->CellNormalTexture)
559     {
560       this->CellNormalTexture = vtkTextureObject::New();
561       this->CellNormalBuffer = vtkOpenGLBufferObject::New();
562       this->CellNormalBuffer->SetType(vtkOpenGLBufferObject::TextureBuffer);
563     }
564     this->CellNormalTexture->SetContext(
565       static_cast<vtkOpenGLRenderWindow*>(ren->GetVTKWindow()));
566 
567     // do we have float texture support ?
568     int ftex =
569       static_cast<vtkOpenGLRenderWindow *>(ren->GetRenderWindow())->
570         GetDefaultTextureInternalFormat(VTK_FLOAT, 4, false, true, false);
571 
572     if (ftex)
573     {
574       this->CellNormalBuffer->Upload(newNorms,
575         vtkOpenGLBufferObject::TextureBuffer);
576       this->CellNormalTexture->CreateTextureBuffer(
577         static_cast<unsigned int>(newNorms.size()/4),
578         4, VTK_FLOAT,
579         this->CellNormalBuffer);
580     }
581     else
582     {
583       // have to convert to unsigned char if no float support
584       std::vector<unsigned char> ucNewNorms;
585       ucNewNorms.resize(newNorms.size());
586       for (size_t i = 0; i < newNorms.size(); i++)
587       {
588         ucNewNorms[i] = 127.0*(newNorms[i] + 1.0);
589       }
590       this->CellNormalBuffer->Upload(ucNewNorms,
591         vtkOpenGLBufferObject::TextureBuffer);
592       this->CellNormalTexture->CreateTextureBuffer(
593         static_cast<unsigned int>(newNorms.size()/4),
594         4, VTK_UNSIGNED_CHAR,
595         this->CellNormalBuffer);
596     }
597   }
598 
599   if (this->HaveAppleBug &&
600       (this->HaveCellNormals || this->HaveCellScalars))
601   {
602     if (!this->AppleBugPrimIDBuffer)
603     {
604       this->AppleBugPrimIDBuffer = vtkOpenGLBufferObject::New();
605     }
606     this->AppleBugPrimIDBuffer->Bind();
607     this->AppleBugPrimIDBuffer->Upload(
608      this->AppleBugPrimIDs, vtkOpenGLBufferObject::ArrayBuffer);
609     this->AppleBugPrimIDBuffer->Release();
610   }
611 
612   this->VBOBuildTime.Modified();
613 }
614 
615 //-------------------------------------------------------------------------
AppendOneBufferObject(vtkRenderer * ren,vtkActor * act,vtkCompositeMapperHelperData * hdata,vtkIdType & voffset,std::vector<unsigned char> & newColors,std::vector<float> & newNorms)616 void vtkCompositeMapperHelper2::AppendOneBufferObject(
617   vtkRenderer *ren,
618   vtkActor *act,
619   vtkCompositeMapperHelperData *hdata,
620   vtkIdType &voffset,
621   std::vector<unsigned char> &newColors,
622   std::vector<float> &newNorms
623   )
624 {
625   vtkPolyData *poly = hdata->Data;
626 
627   // if there are no points then skip this piece
628   if (!poly->GetPoints() || poly->GetPoints()->GetNumberOfPoints() == 0)
629   {
630     return;
631   }
632 
633   // Get rid of old texture color coordinates if any
634   if ( this->ColorCoordinates )
635   {
636     this->ColorCoordinates->UnRegister(this);
637     this->ColorCoordinates = nullptr;
638   }
639   // Get rid of old texture color coordinates if any
640   if ( this->Colors )
641   {
642     this->Colors->UnRegister(this);
643     this->Colors = nullptr;
644   }
645 
646   // For vertex coloring, this sets this->Colors as side effect.
647   // For texture map coloring, this sets ColorCoordinates
648   // and ColorTextureMap as a side effect.
649   // I moved this out of the conditional because it is fast.
650   // Color arrays are cached. If nothing has changed,
651   // then the scalars do not have to be regenerted.
652   this->MapScalars(poly, 1.0);
653 
654   // If we are coloring by texture, then load the texture map.
655   if (this->ColorTextureMap)
656   {
657     if (this->InternalColorTexture == nullptr)
658     {
659       this->InternalColorTexture = vtkOpenGLTexture::New();
660       this->InternalColorTexture->RepeatOff();
661     }
662     this->InternalColorTexture->SetInputData(this->ColorTextureMap);
663   }
664 
665   this->HaveCellScalars = false;
666   vtkDataArray *c = this->Colors;
667   if (this->ScalarVisibility)
668   {
669     // We must figure out how the scalars should be mapped to the polydata.
670     if ( (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA ||
671           this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ||
672           this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ||
673           !poly->GetPointData()->GetScalars() )
674          && this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA
675          && this->Colors)
676     {
677       this->HaveCellScalars = true;
678       c = nullptr;
679     }
680   }
681 
682   this->HaveCellNormals = false;
683   // Do we have cell normals?
684   vtkDataArray *n =
685     (act->GetProperty()->GetInterpolation() != VTK_FLAT) ? poly->GetPointData()->GetNormals() : nullptr;
686   if (n == nullptr && poly->GetCellData()->GetNormals())
687   {
688     this->HaveCellNormals = true;
689     n = nullptr;
690   }
691 
692   int representation = act->GetProperty()->GetRepresentation();
693   vtkHardwareSelector* selector = ren->GetSelector();
694 
695   if (selector && this->PopulateSelectionSettings &&
696       selector->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS)
697   {
698     representation = VTK_POINTS;
699   }
700 
701   // if we have cell scalars then we have to
702   // explode the data
703   vtkCellArray *prims[4];
704   prims[0] =  poly->GetVerts();
705   prims[1] =  poly->GetLines();
706   prims[2] =  poly->GetPolys();
707   prims[3] =  poly->GetStrips();
708 
709   // vert cell offset starts at the end of the last block
710   hdata->PrimOffsets[0] = (!newColors.empty() ? newColors.size()/4 : newNorms.size()/4);
711   hdata->PrimOffsets[1] = hdata->PrimOffsets[0] +
712     prims[0]->GetNumberOfConnectivityEntries() -
713     prims[0]->GetNumberOfCells();
714 
715   this->AppendCellTextures(ren, act, prims, representation,
716     newColors, newNorms, poly);
717 
718   hdata->PrimOffsets[2] = hdata->PrimOffsets[1] +
719     prims[1]->GetNumberOfConnectivityEntries() -
720     2*prims[1]->GetNumberOfCells();
721 
722   hdata->PrimOffsets[4] = (!newColors.empty() ? newColors.size()/4 : newNorms.size()/4);
723 
724   // we back compute the strip number
725   size_t triCount = prims[3]->GetNumberOfConnectivityEntries()
726     - 3*prims[3]->GetNumberOfCells();
727   hdata->PrimOffsets[3] = hdata->PrimOffsets[4] - triCount;
728 
729   // on Apple Macs with the AMD PrimID bug <rdar://20747550>
730   // we use a slow painful approach to work around it (pre 10.11).
731   if (this->HaveAppleBug &&
732       (this->HaveCellNormals || this->HaveCellScalars))
733   {
734     poly = this->HandleAppleBug(poly, this->AppleBugPrimIDs);
735     prims[0] =  poly->GetVerts();
736     prims[1] =  poly->GetLines();
737     prims[2] =  poly->GetPolys();
738     prims[3] =  poly->GetStrips();
739 
740 #ifndef NDEBUG
741     static bool warnedAboutBrokenAppleDriver = false;
742     if (!warnedAboutBrokenAppleDriver)
743     {
744       vtkWarningMacro("VTK is working around a bug in Apple-AMD hardware related to gl_PrimitiveID.  This may cause significant memory and performance impacts. Your hardware has been identified as vendor "
745         << (const char *)glGetString(GL_VENDOR) << " with renderer of "
746         << (const char *)glGetString(GL_RENDERER) << " and version "
747         << (const char *)glGetString(GL_VERSION));
748       warnedAboutBrokenAppleDriver = true;
749     }
750 #endif
751     if (n)
752     {
753       n = (act->GetProperty()->GetInterpolation() != VTK_FLAT) ?
754             poly->GetPointData()->GetNormals() : nullptr;
755     }
756     if (c)
757     {
758       this->Colors->Delete();
759       this->Colors = nullptr;
760       this->MapScalars(poly,1.0);
761       c = this->Colors;
762     }
763   }
764 
765 
766   // do we have texture maps?
767   bool haveTextures = (this->ColorTextureMap || act->GetTexture() || act->GetProperty()->GetNumberOfTextures());
768 
769   // Set the texture if we are going to use texture
770   // for coloring with a point attribute.
771   // fixme ... make the existence of the coordinate array the signal.
772   vtkDataArray *tcoords = nullptr;
773   if (haveTextures)
774   {
775     if (this->InterpolateScalarsBeforeMapping && this->ColorCoordinates)
776     {
777       tcoords = this->ColorCoordinates;
778     }
779     else
780     {
781       tcoords = poly->GetPointData()->GetTCoords();
782     }
783   }
784 
785   // Check if color array is already computed for the current array.
786   // This step is mandatory otherwise the test ArrayExists will fail for "scalarColor" even if
787   // the array used to map the color has already been added.
788   if (c)
789   {
790     int cellFlag = 0; // not used
791     vtkAbstractArray* abstractArray = this->GetAbstractScalars(poly, this->ScalarMode,
792       this->ArrayAccessMode, this->ArrayId, this->ArrayName, cellFlag);
793 
794     auto iter = this->ColorArrayMap.find(abstractArray);
795     if (iter != this->ColorArrayMap.end())
796     {
797       c = iter->second;
798     }
799     else
800     {
801       this->ColorArrayMap[abstractArray] = c;
802       c->Register(this);
803     }
804   }
805 
806   // Build the VBO
807   vtkIdType offsetPos = 0;
808   vtkIdType offsetNorm = 0;
809   vtkIdType offsetColor = 0;
810   vtkIdType offsetTex = 0;
811   vtkIdType totalOffset = 0;
812   vtkIdType dummy = 0;
813   bool exists =
814     this->VBOs->ArrayExists("vertexMC", poly->GetPoints()->GetData(), offsetPos, totalOffset) &&
815     this->VBOs->ArrayExists("normalMC", n, offsetNorm, dummy) &&
816     this->VBOs->ArrayExists("scalarColor", c, offsetColor,dummy) &&
817     this->VBOs->ArrayExists("tcoord", tcoords, offsetTex, dummy);
818 
819   // if all used arrays have the same offset and have already been added,
820   // we can reuse them and save memory
821   if (exists &&
822     (offsetNorm == 0 || offsetPos == offsetNorm) &&
823     (offsetColor == 0 || offsetPos == offsetColor) &&
824     (offsetTex == 0 || offsetPos == offsetTex))
825   {
826     voffset = offsetPos;
827   }
828   else
829   {
830     this->VBOs->AppendDataArray("vertexMC", poly->GetPoints()->GetData(), VTK_FLOAT);
831     this->VBOs->AppendDataArray("normalMC", n, VTK_FLOAT);
832     this->VBOs->AppendDataArray("scalarColor", c, VTK_UNSIGNED_CHAR);
833     this->VBOs->AppendDataArray("tcoord", tcoords, VTK_FLOAT);
834 
835     voffset = totalOffset;
836   }
837 
838   // now create the IBOs
839   vtkOpenGLIndexBufferObject::AppendPointIndexBuffer(
840     this->IndexArray[0], prims[0], voffset);
841 
842   vtkDataArray *ef = poly->GetPointData()->GetAttribute(
843                     vtkDataSetAttributes::EDGEFLAG);
844 
845   if (representation == VTK_POINTS)
846   {
847     vtkOpenGLIndexBufferObject::AppendPointIndexBuffer(
848       this->IndexArray[1], prims[1], voffset);
849 
850     vtkOpenGLIndexBufferObject::AppendPointIndexBuffer(
851       this->IndexArray[2], prims[2], voffset);
852 
853     vtkOpenGLIndexBufferObject::AppendPointIndexBuffer(
854       this->IndexArray[3], prims[3], voffset);
855   }
856   else // WIREFRAME OR SURFACE
857   {
858     vtkOpenGLIndexBufferObject::AppendLineIndexBuffer(
859       this->IndexArray[1], prims[1], voffset);
860 
861     if (representation == VTK_WIREFRAME)
862     {
863       if (ef)
864       {
865         if (ef->GetNumberOfComponents() != 1)
866         {
867           vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
868           ef = nullptr;
869         }
870         if (ef && !ef->IsA("vtkUnsignedCharArray"))
871         {
872           vtkDebugMacro(<< "Currently only unsigned char edge flags are supported.");
873           ef = nullptr;
874         }
875       }
876       if (ef)
877       {
878         vtkOpenGLIndexBufferObject::AppendEdgeFlagIndexBuffer(
879           this->IndexArray[2], prims[2], voffset, ef);
880       }
881       else
882       {
883         vtkOpenGLIndexBufferObject::AppendTriangleLineIndexBuffer(
884           this->IndexArray[2], prims[2], voffset);
885       }
886       vtkOpenGLIndexBufferObject::AppendStripIndexBuffer(
887         this->IndexArray[3], prims[3], voffset, true);
888     }
889     else // SURFACE
890     {
891       vtkOpenGLIndexBufferObject::AppendTriangleIndexBuffer(
892         this->IndexArray[2],
893         prims[2],
894         poly->GetPoints(),
895         voffset);
896       vtkOpenGLIndexBufferObject::AppendStripIndexBuffer(
897         this->IndexArray[3], prims[3], voffset, false);
898     }
899   }
900 
901   // when drawing edges also build the edge IBOs
902   vtkProperty *prop = act->GetProperty();
903   bool draw_surface_with_edges =
904     (prop->GetEdgeVisibility() && prop->GetRepresentation() == VTK_SURFACE);
905   if (draw_surface_with_edges)
906   {
907     if (ef)
908     {
909       if (ef->GetNumberOfComponents() != 1)
910       {
911         vtkDebugMacro(<< "Currently only 1d edge flags are supported.");
912         ef = nullptr;
913       }
914       if (!ef->IsA("vtkUnsignedCharArray"))
915       {
916         vtkDebugMacro(<< "Currently only unsigned char edge flags are supported.");
917         ef = nullptr;
918       }
919     }
920     if (ef)
921     {
922       vtkOpenGLIndexBufferObject::AppendEdgeFlagIndexBuffer(
923         this->IndexArray[4], prims[2], voffset, ef);
924     }
925     else
926     {
927       vtkOpenGLIndexBufferObject::AppendTriangleLineIndexBuffer(
928         this->IndexArray[4], prims[2], voffset);
929     }
930     vtkOpenGLIndexBufferObject::AppendStripIndexBuffer(
931       this->IndexArray[5], prims[3], voffset, false);
932   }
933 
934   if (prop->GetVertexVisibility())
935   {
936     vtkOpenGLIndexBufferObject::AppendVertexIndexBuffer(
937       this->IndexArray[PrimitiveVertices], prims, voffset);
938   }
939 
940   // free up polydata if allocated due to apple bug
941   if (poly != hdata->Data)
942   {
943     poly->Delete();
944   }
945 }
946 
ProcessSelectorPixelBuffers(vtkHardwareSelector * sel,std::vector<unsigned int> & pixeloffsets,vtkProp * prop)947 void vtkCompositeMapperHelper2::ProcessSelectorPixelBuffers(
948   vtkHardwareSelector *sel,
949   std::vector<unsigned int> &pixeloffsets,
950   vtkProp *prop)
951 {
952   if (!this->PopulateSelectionSettings)
953   {
954     return;
955   }
956 
957   if (sel->GetCurrentPass() == vtkHardwareSelector::ACTOR_PASS)
958   {
959     this->PickPixels.clear();
960     return;
961   }
962 
963   if (PickPixels.size() == 0 && pixeloffsets.size())
964   {
965     // preprocess the image to find matching pixels and
966     // store them in a map of vectors based on flat index
967     // this makes the block processing far faster as we just
968     // loop over the pixels for our block
969     unsigned char *compositedata =
970       sel->GetRawPixelBuffer(vtkHardwareSelector::COMPOSITE_INDEX_PASS);
971 
972     if (!compositedata)
973     {
974       return;
975     }
976 
977     size_t maxFlatIndex = 0;
978     for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
979     {
980       maxFlatIndex = (it->second->FlatIndex > maxFlatIndex) ? it->second->FlatIndex : maxFlatIndex;
981     }
982 
983     this->PickPixels.resize(maxFlatIndex + 1);
984 
985     for (auto pos : pixeloffsets)
986     {
987       unsigned int compval = compositedata[pos+2];
988       compval = compval << 8;
989       compval |= compositedata[pos+1];
990       compval = compval << 8;
991       compval |= compositedata[pos];
992       compval -= 1;
993       if (compval <= maxFlatIndex)
994       {
995         this->PickPixels[compval].push_back(pos);
996       }
997     }
998   }
999 
1000   // for each block update the image
1001   for (dataIter it = this->Data.begin(); it != this->Data.end(); ++it)
1002   {
1003     if (this->PickPixels[it->second->FlatIndex].size())
1004     {
1005       this->ProcessCompositePixelBuffers(sel, prop, it->second,
1006         this->PickPixels[it->second->FlatIndex]);
1007     }
1008   }
1009 }
1010 
1011 namespace
1012 {
convertToCells(unsigned int * offset,unsigned int * stride,unsigned int inval)1013   unsigned int convertToCells(
1014     unsigned int *offset,
1015     unsigned int *stride,
1016     unsigned int inval )
1017   {
1018     if (inval < offset[0])
1019     {
1020       return inval;
1021     }
1022     if (inval < offset[1])
1023     {
1024       return offset[0] + (inval - offset[0]) / stride[0];
1025     }
1026     return offset[0] + (offset[1] - offset[0]) / stride[0] + (inval - offset[1]) / stride[1];
1027   }
1028 }
1029 
ProcessCompositePixelBuffers(vtkHardwareSelector * sel,vtkProp * prop,vtkCompositeMapperHelperData * hdata,std::vector<unsigned int> & pixeloffsets)1030 void vtkCompositeMapperHelper2::ProcessCompositePixelBuffers(
1031   vtkHardwareSelector *sel,
1032   vtkProp *prop,
1033   vtkCompositeMapperHelperData *hdata,
1034   std::vector<unsigned int> &pixeloffsets)
1035 {
1036   vtkPolyData *poly = hdata->Data;
1037 
1038   if (!poly)
1039   {
1040     return;
1041   }
1042 
1043   // which pass are we processing ?
1044   int currPass = sel->GetCurrentPass();
1045 
1046   // get some common useful values
1047   bool pointPicking =
1048     sel->GetFieldAssociation() == vtkDataObject::FIELD_ASSOCIATION_POINTS;
1049   vtkPointData *pd = poly->GetPointData();
1050   vtkCellData *cd = poly->GetCellData();
1051 
1052   // get some values
1053   unsigned char *rawplowdata = sel->GetRawPixelBuffer(vtkHardwareSelector::POINT_ID_LOW24);
1054   unsigned char *rawphighdata = sel->GetRawPixelBuffer(vtkHardwareSelector::POINT_ID_HIGH24);
1055 
1056   // do we need to do anything to the process pass data?
1057   if (currPass == vtkHardwareSelector::PROCESS_PASS)
1058   {
1059     unsigned char *processdata = sel->GetPixelBuffer(vtkHardwareSelector::PROCESS_PASS);
1060     vtkUnsignedIntArray* processArray = nullptr;
1061 
1062     if (sel->GetUseProcessIdFromData())
1063     {
1064       processArray = this->ProcessIdArrayName ?
1065         vtkArrayDownCast<vtkUnsignedIntArray>(
1066           pd->GetArray(this->ProcessIdArrayName)) : nullptr;
1067     }
1068 
1069     if (processArray && processdata && rawplowdata)
1070     {
1071       for (auto pos : pixeloffsets)
1072       {
1073         unsigned int inval = 0;
1074         if (rawphighdata)
1075         {
1076           inval = rawphighdata[pos];
1077           inval = inval << 8;
1078         }
1079         inval |= rawplowdata[pos + 2];
1080         inval = inval << 8;
1081         inval |= rawplowdata[pos + 1];
1082         inval = inval << 8;
1083         inval |= rawplowdata[pos];
1084         inval -= 1;
1085         inval -= hdata->StartVertex;
1086         unsigned int outval =  processArray->GetValue(inval) + 1;
1087         processdata[pos] = outval & 0xff;
1088         processdata[pos + 1] = (outval & 0xff00) >> 8;
1089         processdata[pos + 2] = (outval & 0xff0000) >> 16;
1090       }
1091     }
1092   }
1093 
1094   // do we need to do anything to the point id data?
1095   if (currPass == vtkHardwareSelector::POINT_ID_LOW24)
1096   {
1097     vtkIdTypeArray* pointArrayId = this->PointIdArrayName ?
1098       vtkArrayDownCast<vtkIdTypeArray>(
1099         pd->GetArray(this->PointIdArrayName)) : nullptr;
1100 
1101     // do we need to do anything to the point id data?
1102     if (rawplowdata)
1103     {
1104       unsigned char *plowdata = sel->GetPixelBuffer(vtkHardwareSelector::POINT_ID_LOW24);
1105 
1106       for (auto pos : pixeloffsets)
1107       {
1108         unsigned int inval = 0;
1109         if (rawphighdata)
1110         {
1111           inval = rawphighdata[pos];
1112           inval = inval << 8;
1113         }
1114         inval |= rawplowdata[pos + 2];
1115         inval = inval << 8;
1116         inval |= rawplowdata[pos + 1];
1117         inval = inval << 8;
1118         inval |= rawplowdata[pos];
1119         inval -= 1;
1120         inval -= hdata->StartVertex;
1121         vtkIdType outval =  inval + 1;
1122         if (pointArrayId)
1123         {
1124           outval = pointArrayId->GetValue(inval) + 1;
1125         }
1126         plowdata[pos] = outval & 0xff;
1127         plowdata[pos + 1] = (outval & 0xff00) >> 8;
1128         plowdata[pos + 2] = (outval & 0xff0000) >> 16;
1129       }
1130     }
1131   }
1132 
1133   if (currPass == vtkHardwareSelector::POINT_ID_HIGH24)
1134   {
1135     vtkIdTypeArray *pointArrayId = this->PointIdArrayName ?
1136       vtkArrayDownCast<vtkIdTypeArray>(
1137         pd->GetArray(this->PointIdArrayName)) : nullptr;
1138 
1139     // do we need to do anything to the point id data?
1140     if (rawphighdata)
1141     {
1142       unsigned char *phighdata = sel->GetPixelBuffer(vtkHardwareSelector::POINT_ID_HIGH24);
1143 
1144       for (auto pos : pixeloffsets)
1145       {
1146         unsigned int inval = 0;
1147         inval = rawphighdata[pos];
1148         inval = inval << 8;
1149         inval |= rawplowdata[pos + 2];
1150         inval = inval << 8;
1151         inval |= rawplowdata[pos + 1];
1152         inval = inval << 8;
1153         inval |= rawplowdata[pos];
1154         inval -= 1;
1155         inval -= hdata->StartVertex;
1156         vtkIdType outval =  inval + 1;
1157         if (pointArrayId)
1158         {
1159           outval = pointArrayId->GetValue(inval) + 1;
1160         }
1161         phighdata[pos] = (outval & 0xff000000) >> 24;
1162         phighdata[pos + 1] = (outval & 0xff00000000) >> 32;
1163         phighdata[pos + 2] = (outval & 0xff0000000000) >> 40;
1164       }
1165     }
1166   }
1167 
1168   // vars for cell based indexing
1169   vtkCellArray *prims[4];
1170   prims[0] =  poly->GetVerts();
1171   prims[1] =  poly->GetLines();
1172   prims[2] =  poly->GetPolys();
1173   prims[3] =  poly->GetStrips();
1174 
1175   int representation =
1176     static_cast<vtkActor *>(prop)->GetProperty()->GetRepresentation();
1177 
1178   unsigned char *rawclowdata = sel->GetRawPixelBuffer(vtkHardwareSelector::CELL_ID_LOW24);
1179   unsigned char *rawchighdata = sel->GetRawPixelBuffer(vtkHardwareSelector::CELL_ID_HIGH24);
1180 
1181   // build the mapping of point primID to cell primID
1182   // aka when we render triangles in point picking mode
1183   // how do we map primid to what would normally be primid
1184   unsigned int offset[2];
1185   unsigned int stride[2];
1186   offset[0] = static_cast<unsigned int>(this->Primitives[PrimitiveVertices].IBO->IndexCount);
1187   stride[0] = representation == VTK_POINTS ? 1 : 2;
1188   offset[1] = offset[0] + static_cast<unsigned int>(
1189     this->Primitives[PrimitiveLines].IBO->IndexCount);
1190   stride[1] = representation == VTK_POINTS ? 1 : representation == VTK_WIREFRAME ? 2 : 3;
1191 
1192   // do we need to do anything to the composite pass data?
1193   if (currPass == vtkHardwareSelector::COMPOSITE_INDEX_PASS)
1194   {
1195     unsigned char *compositedata =
1196       sel->GetPixelBuffer(vtkHardwareSelector::COMPOSITE_INDEX_PASS);
1197 
1198     vtkUnsignedIntArray *compositeArray = this->CompositeIdArrayName ?
1199       vtkArrayDownCast<vtkUnsignedIntArray>(
1200         cd->GetArray(this->CompositeIdArrayName)) : nullptr;
1201 
1202     if (compositedata && compositeArray && rawclowdata)
1203     {
1204       this->UpdateCellMaps(this->HaveAppleBug,
1205         poly,
1206         prims,
1207         representation,
1208         poly->GetPoints());
1209 
1210       for (auto pos : pixeloffsets)
1211       {
1212         unsigned int inval = 0;
1213         if (rawchighdata)
1214         {
1215           inval = rawchighdata[pos];
1216           inval = inval << 8;
1217         }
1218         inval |= rawclowdata[pos + 2];
1219         inval = inval << 8;
1220         inval |= rawclowdata[pos + 1];
1221         inval = inval << 8;
1222         inval |= rawclowdata[pos];
1223         inval -= 1;
1224         inval -= static_cast<int>(hdata->PrimOffsets[0]);
1225         if (pointPicking)
1226         {
1227           inval = convertToCells(offset, stride, inval);
1228         }
1229         vtkIdType vtkCellId = this->CellCellMap[inval];
1230         unsigned int outval =  compositeArray->GetValue(vtkCellId) + 1;
1231         compositedata[pos] = outval & 0xff;
1232         compositedata[pos + 1] = (outval & 0xff00) >> 8;
1233         compositedata[pos + 2] = (outval & 0xff0000) >> 16;
1234       }
1235     }
1236   }
1237 
1238   if (currPass == vtkHardwareSelector::CELL_ID_LOW24)
1239   {
1240     vtkIdTypeArray *cellArrayId = this->CellIdArrayName ?
1241       vtkArrayDownCast<vtkIdTypeArray>(
1242         cd->GetArray(this->CellIdArrayName)) : nullptr;
1243     unsigned char *clowdata = sel->GetPixelBuffer(vtkHardwareSelector::CELL_ID_LOW24);
1244 
1245     if (rawclowdata)
1246     {
1247       this->UpdateCellMaps(this->HaveAppleBug,
1248         poly,
1249         prims,
1250         representation,
1251         poly->GetPoints());
1252 
1253       for (auto pos : pixeloffsets)
1254       {
1255         unsigned int inval = 0;
1256         if (rawchighdata)
1257         {
1258           inval = rawchighdata[pos];
1259           inval = inval << 8;
1260         }
1261         inval |= rawclowdata[pos + 2];
1262         inval = inval << 8;
1263         inval |= rawclowdata[pos + 1];
1264         inval = inval << 8;
1265         inval |= rawclowdata[pos];
1266         inval -= 1;
1267         inval -= static_cast<int>(hdata->PrimOffsets[0]);
1268         if (pointPicking)
1269         {
1270           inval = convertToCells(offset, stride, inval);
1271         }
1272         vtkIdType outval = this->CellCellMap[inval];
1273         if (cellArrayId)
1274         {
1275           outval = cellArrayId->GetValue(outval);
1276         }
1277         outval++;
1278         clowdata[pos] = outval & 0xff;
1279         clowdata[pos + 1] = (outval & 0xff00) >> 8;
1280         clowdata[pos + 2] = (outval & 0xff0000) >> 16;
1281       }
1282     }
1283   }
1284 
1285   if (currPass == vtkHardwareSelector::CELL_ID_HIGH24)
1286   {
1287     vtkIdTypeArray *cellArrayId = this->CellIdArrayName ?
1288       vtkArrayDownCast<vtkIdTypeArray>(
1289         cd->GetArray(this->CellIdArrayName)) : nullptr;
1290     unsigned char *chighdata = sel->GetPixelBuffer(vtkHardwareSelector::CELL_ID_HIGH24);
1291 
1292     if (rawchighdata)
1293     {
1294       this->UpdateCellMaps(this->HaveAppleBug,
1295         poly,
1296         prims,
1297         representation,
1298         poly->GetPoints());
1299 
1300       for (auto pos : pixeloffsets)
1301       {
1302         unsigned int inval = 0;
1303         inval = rawchighdata[pos];
1304         inval = inval << 8;
1305         inval |= rawclowdata[pos + 2];
1306         inval = inval << 8;
1307         inval |= rawclowdata[pos + 1];
1308         inval = inval << 8;
1309         inval |= rawclowdata[pos];
1310         inval -= 1;
1311         inval -= static_cast<int>(hdata->PrimOffsets[0]);
1312         if (pointPicking)
1313         {
1314           inval = convertToCells(offset, stride, inval);
1315         }
1316         vtkIdType outval = this->CellCellMap[inval];
1317         if (cellArrayId)
1318         {
1319           outval = cellArrayId->GetValue(outval);
1320         }
1321         outval++;
1322         chighdata[pos] = (outval & 0xff000000) >> 24;
1323         chighdata[pos + 1] = (outval & 0xff00000000) >> 32;
1324         chighdata[pos + 2] = (outval & 0xff0000000000) >> 40;
1325       }
1326     }
1327   }
1328 
1329 }
1330 
1331 //===================================================================
1332 // Now the main class methods
1333 
1334 vtkStandardNewMacro(vtkCompositePolyDataMapper2);
1335 //----------------------------------------------------------------------------
vtkCompositePolyDataMapper2()1336 vtkCompositePolyDataMapper2::vtkCompositePolyDataMapper2()
1337 {
1338   this->LastOpaqueCheckTime = 0;
1339   this->CurrentFlatIndex = 0;
1340   this->LastOpaqueCheckValue = true;
1341   this->ColorMissingArraysWithNanColor = false;
1342 }
1343 
1344 //----------------------------------------------------------------------------
~vtkCompositePolyDataMapper2()1345 vtkCompositePolyDataMapper2::~vtkCompositePolyDataMapper2()
1346 {
1347   helpIter miter = this->Helpers.begin();
1348   for (;miter != this->Helpers.end(); ++miter)
1349   {
1350     miter->second->Delete();
1351   }
1352   this->Helpers.clear();
1353 }
1354 
1355 //----------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)1356 int vtkCompositePolyDataMapper2::FillInputPortInformation(
1357   int vtkNotUsed(port), vtkInformation* info)
1358 {
1359   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
1360   info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkCompositeDataSet");
1361   return 1;
1362 }
1363 
1364 //----------------------------------------------------------------------------
CreateDefaultExecutive()1365 vtkExecutive* vtkCompositePolyDataMapper2::CreateDefaultExecutive()
1366 {
1367   return vtkCompositeDataPipeline::New();
1368 }
1369 
1370 //-----------------------------------------------------------------------------
1371 //Looks at each DataSet and finds the union of all the bounds
ComputeBounds()1372 void vtkCompositePolyDataMapper2::ComputeBounds()
1373 {
1374   vtkCompositeDataSet *input = vtkCompositeDataSet::SafeDownCast(
1375     this->GetInputDataObject(0, 0));
1376 
1377   // If we don't have hierarchical data, test to see if we have
1378   // plain old polydata. In this case, the bounds are simply
1379   // the bounds of the input polydata.
1380   if (!input)
1381   {
1382     this->Superclass::ComputeBounds();
1383     return;
1384   }
1385 
1386   if (input->GetMTime() < this->BoundsMTime &&
1387       this->GetMTime() < this->BoundsMTime)
1388   {
1389     return;
1390   }
1391 
1392   // computing bounds with only visible blocks
1393   vtkCompositeDataDisplayAttributes::ComputeVisibleBounds(
1394     this->CompositeAttributes, input, this->Bounds);
1395   this->BoundsMTime.Modified();
1396 }
1397 
1398 //-----------------------------------------------------------------------------
GetIsOpaque()1399 bool vtkCompositePolyDataMapper2::GetIsOpaque()
1400 {
1401   vtkCompositeDataSet *input = vtkCompositeDataSet::SafeDownCast(
1402     this->GetInputDataObject(0, 0));
1403   vtkMTimeType lastMTime = std::max(input ? input->GetMTime() : 0, this->GetMTime());
1404   if (lastMTime <= this->LastOpaqueCheckTime)
1405   {
1406     return this->LastOpaqueCheckValue;
1407   }
1408   this->LastOpaqueCheckTime = lastMTime;
1409   if (this->ScalarVisibility && input &&
1410       (this->ColorMode == VTK_COLOR_MODE_DEFAULT ||
1411        this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS))
1412   {
1413     vtkSmartPointer<vtkCompositeDataIterator> iter;
1414     iter.TakeReference(input->NewIterator());
1415     for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
1416     {
1417       vtkPolyData *pd = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
1418       if (pd)
1419       {
1420         int cellFlag;
1421         vtkDataArray* scalars = this->GetScalars(pd,
1422           this->ScalarMode, this->ArrayAccessMode, this->ArrayId,
1423           this->ArrayName, cellFlag);
1424         if (scalars &&
1425             (scalars->IsA("vtkUnsignedCharArray")  ||
1426              this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS) &&
1427             (scalars->GetNumberOfComponents() ==  4 /*(RGBA)*/ ||
1428              scalars->GetNumberOfComponents() == 2 /*(LuminanceAlpha)*/))
1429         {
1430           int opacityIndex = scalars->GetNumberOfComponents() - 1;
1431           unsigned char opacity = 0;
1432           switch (scalars->GetDataType())
1433           {
1434             vtkTemplateMacro(
1435               vtkScalarsToColors::ColorToUChar(
1436                 static_cast<VTK_TT>(scalars->GetRange(opacityIndex)[0]),
1437                 &opacity));
1438           }
1439           if (opacity < 255)
1440           {
1441             // If the opacity is 255, despite the fact that the user specified
1442             // RGBA, we know that the Alpha is 100% opaque. So treat as opaque.
1443             this->LastOpaqueCheckValue = false;
1444             return false;
1445           }
1446         }
1447       }
1448     }
1449   }
1450   else if(this->CompositeAttributes &&
1451     this->CompositeAttributes->HasBlockOpacities())
1452   {
1453     this->LastOpaqueCheckValue = false;
1454     return false;
1455   }
1456 
1457   this->LastOpaqueCheckValue = this->Superclass::GetIsOpaque();
1458   return this->LastOpaqueCheckValue;
1459 }
1460 
1461 //----------------------------------------------------------------------------
SetBlockVisibility(unsigned int index,bool visible)1462 void vtkCompositePolyDataMapper2::SetBlockVisibility(unsigned int index, bool visible)
1463 {
1464   if(this->CompositeAttributes)
1465   {
1466     unsigned int start_index = 0;
1467     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1468       this->GetInputDataObject(0, 0), start_index);
1469     if (dataObj)
1470     {
1471       this->CompositeAttributes->SetBlockVisibility(dataObj, visible);
1472       this->Modified();
1473     }
1474   }
1475 }
1476 
1477 //----------------------------------------------------------------------------
GetBlockVisibility(unsigned int index)1478 bool vtkCompositePolyDataMapper2::GetBlockVisibility(unsigned int index)
1479 {
1480   if(this->CompositeAttributes)
1481   {
1482     unsigned int start_index = 0;
1483     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1484       this->GetInputDataObject(0, 0), start_index);
1485     if (dataObj)
1486     {
1487       return this->CompositeAttributes->GetBlockVisibility(dataObj);
1488     }
1489   }
1490 
1491   return true;
1492 }
1493 
1494 //----------------------------------------------------------------------------
RemoveBlockVisibility(unsigned int index)1495 void vtkCompositePolyDataMapper2::RemoveBlockVisibility(unsigned int index)
1496 {
1497   if(this->CompositeAttributes)
1498   {
1499     unsigned int start_index = 0;
1500     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1501       this->GetInputDataObject(0, 0), start_index);
1502     if (dataObj)
1503     {
1504       this->CompositeAttributes->RemoveBlockVisibility(dataObj);
1505       this->Modified();
1506     }
1507   }
1508 }
1509 
1510 //----------------------------------------------------------------------------
RemoveBlockVisibilities()1511 void vtkCompositePolyDataMapper2::RemoveBlockVisibilities()
1512 {
1513   if(this->CompositeAttributes)
1514   {
1515     this->CompositeAttributes->RemoveBlockVisibilities();
1516     this->Modified();
1517   }
1518 }
1519 
1520 #ifndef VTK_LEGACY_REMOVE
RemoveBlockVisibilites()1521 void vtkCompositePolyDataMapper2::RemoveBlockVisibilites()
1522 {
1523   this->RemoveBlockVisibilities();
1524 }
1525 #endif
1526 
1527 //----------------------------------------------------------------------------
SetBlockColor(unsigned int index,double color[3])1528 void vtkCompositePolyDataMapper2::SetBlockColor(unsigned int index, double color[3])
1529 {
1530   if(this->CompositeAttributes)
1531   {
1532     unsigned int start_index = 0;
1533     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1534       this->GetInputDataObject(0, 0), start_index);
1535 
1536     if (dataObj)
1537     {
1538       this->CompositeAttributes->SetBlockColor(dataObj, color);
1539       this->Modified();
1540     }
1541   }
1542 }
1543 
1544 //----------------------------------------------------------------------------
GetBlockColor(unsigned int index)1545 double* vtkCompositePolyDataMapper2::GetBlockColor(unsigned int index)
1546 {
1547   static double white[3] = {1.0,1.0,1.0};
1548 
1549   if(this->CompositeAttributes)
1550   {
1551     unsigned int start_index = 0;
1552     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1553       this->GetInputDataObject(0, 0), start_index);
1554     if (dataObj)
1555     {
1556       this->CompositeAttributes->GetBlockColor(dataObj, this->ColorResult);
1557     }
1558 
1559     return this->ColorResult;
1560   }
1561   else
1562   {
1563     return white;
1564   }
1565 }
1566 
1567 //----------------------------------------------------------------------------
RemoveBlockColor(unsigned int index)1568 void vtkCompositePolyDataMapper2::RemoveBlockColor(unsigned int index)
1569 {
1570   if(this->CompositeAttributes)
1571   {
1572     unsigned int start_index = 0;
1573     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1574       this->GetInputDataObject(0, 0), start_index);
1575     if (dataObj)
1576     {
1577       this->CompositeAttributes->RemoveBlockColor(dataObj);
1578       this->Modified();
1579     }
1580   }
1581 }
1582 
1583 //----------------------------------------------------------------------------
RemoveBlockColors()1584 void vtkCompositePolyDataMapper2::RemoveBlockColors()
1585 {
1586   if(this->CompositeAttributes)
1587   {
1588     this->CompositeAttributes->RemoveBlockColors();
1589     this->Modified();
1590   }
1591 }
1592 
1593 //----------------------------------------------------------------------------
SetBlockOpacity(unsigned int index,double opacity)1594 void vtkCompositePolyDataMapper2::SetBlockOpacity(unsigned int index, double opacity)
1595 {
1596   if(this->CompositeAttributes)
1597   {
1598     unsigned int start_index = 0;
1599     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1600       this->GetInputDataObject(0, 0), start_index);
1601     if (dataObj)
1602     {
1603       this->CompositeAttributes->SetBlockOpacity(dataObj, opacity);
1604       this->Modified();
1605     }
1606   }
1607 }
1608 
1609 //----------------------------------------------------------------------------
GetBlockOpacity(unsigned int index)1610 double vtkCompositePolyDataMapper2::GetBlockOpacity(unsigned int index)
1611 {
1612   if(this->CompositeAttributes)
1613   {
1614     unsigned int start_index = 0;
1615     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1616       this->GetInputDataObject(0, 0), start_index);
1617     if (dataObj)
1618     {
1619       return this->CompositeAttributes->GetBlockOpacity(dataObj);
1620     }
1621   }
1622   return 1.;
1623 }
1624 
1625 //----------------------------------------------------------------------------
RemoveBlockOpacity(unsigned int index)1626 void vtkCompositePolyDataMapper2::RemoveBlockOpacity(unsigned int index)
1627 {
1628   if(this->CompositeAttributes)
1629   {
1630     unsigned int start_index = 0;
1631     auto dataObj = vtkCompositeDataDisplayAttributes::DataObjectFromIndex(index,
1632       this->GetInputDataObject(0, 0), start_index);
1633     if (dataObj)
1634     {
1635       this->CompositeAttributes->RemoveBlockOpacity(dataObj);
1636       this->Modified();
1637     }
1638   }
1639 }
1640 
1641 //----------------------------------------------------------------------------
RemoveBlockOpacities()1642 void vtkCompositePolyDataMapper2::RemoveBlockOpacities()
1643 {
1644   if(this->CompositeAttributes)
1645   {
1646     this->CompositeAttributes->RemoveBlockOpacities();
1647     this->Modified();
1648   }
1649 }
1650 
1651 //----------------------------------------------------------------------------
SetCompositeDataDisplayAttributes(vtkCompositeDataDisplayAttributes * attributes)1652 void vtkCompositePolyDataMapper2::SetCompositeDataDisplayAttributes(
1653   vtkCompositeDataDisplayAttributes *attributes)
1654 {
1655   if(this->CompositeAttributes != attributes)
1656   {
1657     this->CompositeAttributes = attributes;
1658     this->Modified();
1659   }
1660 }
1661 
1662 //----------------------------------------------------------------------------
1663 vtkCompositeDataDisplayAttributes*
GetCompositeDataDisplayAttributes()1664 vtkCompositePolyDataMapper2::GetCompositeDataDisplayAttributes()
1665 {
1666   return this->CompositeAttributes;
1667 }
1668 
1669 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1670 void vtkCompositePolyDataMapper2::PrintSelf(ostream& os, vtkIndent indent)
1671 {
1672   this->Superclass::PrintSelf(os, indent);
1673 }
1674 
CopyMapperValuesToHelper(vtkCompositeMapperHelper2 * helper)1675 void vtkCompositePolyDataMapper2::CopyMapperValuesToHelper(vtkCompositeMapperHelper2 *helper)
1676 {
1677   // We avoid PolyDataMapper::ShallowCopy because it copies the input
1678   helper->vtkMapper::ShallowCopy(this);
1679   helper->SetPointIdArrayName(this->GetPointIdArrayName());
1680   helper->SetCompositeIdArrayName(this->GetCompositeIdArrayName());
1681   helper->SetProcessIdArrayName(this->GetProcessIdArrayName());
1682   helper->SetCellIdArrayName(this->GetCellIdArrayName());
1683   helper->ClearAllShaderReplacements();
1684   helper->SetVertexShaderCode(this->GetVertexShaderCode());
1685   helper->SetGeometryShaderCode(this->GetGeometryShaderCode());
1686   helper->SetFragmentShaderCode(this->GetFragmentShaderCode());
1687   helper->SetStatic(1);
1688   for (auto& repl : this->UserShaderReplacements)
1689   {
1690     const vtkShader::ReplacementSpec& spec = repl.first;
1691     const vtkShader::ReplacementValue& values = repl.second;
1692 
1693     helper->AddShaderReplacement(spec.ShaderType, spec.OriginalValue, spec.ReplaceFirst,
1694       values.Replacement, values.ReplaceAll);
1695   }
1696 }
1697 
1698 //-----------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * win)1699 void vtkCompositePolyDataMapper2::ReleaseGraphicsResources(vtkWindow* win)
1700 {
1701   helpIter miter = this->Helpers.begin();
1702   for (;miter != this->Helpers.end(); ++miter)
1703   {
1704     miter->second->ReleaseGraphicsResources(win);
1705   }
1706   miter = this->Helpers.begin();
1707   for (;miter != this->Helpers.end(); ++miter)
1708   {
1709     miter->second->Delete();
1710   }
1711   this->Helpers.clear();
1712   this->Modified();
1713   this->Superclass::ReleaseGraphicsResources(win);
1714 }
1715 
1716 // ---------------------------------------------------------------------------
1717 // Description:
1718 // Method initiates the mapping process. Generally sent by the actor
1719 // as each frame is rendered.
Render(vtkRenderer * ren,vtkActor * actor)1720 void vtkCompositePolyDataMapper2::Render(
1721   vtkRenderer *ren, vtkActor *actor)
1722 {
1723   this->RenderedList.clear();
1724 
1725   // Make sure that we have been properly initialized.
1726   if (ren->GetRenderWindow()->CheckAbortStatus())
1727   {
1728     return;
1729   }
1730 
1731   if (this->GetInputAlgorithm() == nullptr)
1732   {
1733     return;
1734   }
1735 
1736   if (!this->Static)
1737   {
1738     this->InvokeEvent(vtkCommand::StartEvent,nullptr);
1739     this->GetInputAlgorithm()->Update();
1740     this->InvokeEvent(vtkCommand::EndEvent,nullptr);
1741   }
1742 
1743   if (this->GetInputDataObject(0, 0) == nullptr)
1744   {
1745     vtkErrorMacro(<< "No input!");
1746     return;
1747   }
1748 
1749   // the first step is to gather up the polydata based on their
1750   // signatures (aka have normals, have scalars etc)
1751   if (this->HelperMTime < this->GetInputDataObject(0, 0)->GetMTime() ||
1752       this->HelperMTime < this->GetMTime())
1753   {
1754     // clear old helpers
1755     for (helpIter hiter = this->Helpers.begin(); hiter != this->Helpers.end(); ++hiter)
1756     {
1757       hiter->second->ClearMark();
1758     }
1759     this->HelperDataMap.clear();
1760 
1761     vtkCompositeDataSet *input = vtkCompositeDataSet::SafeDownCast(
1762       this->GetInputDataObject(0, 0));
1763 
1764     if (input)
1765     {
1766       vtkSmartPointer<vtkDataObjectTreeIterator> iter =
1767         vtkSmartPointer<vtkDataObjectTreeIterator>::New();
1768       iter->SetDataSet(input);
1769       iter->SkipEmptyNodesOn();
1770       iter->VisitOnlyLeavesOn();
1771       for (iter->InitTraversal(); !iter->IsDoneWithTraversal();
1772           iter->GoToNextItem())
1773       {
1774         unsigned int flatIndex = iter->GetCurrentFlatIndex();
1775         vtkDataObject *dso = iter->GetCurrentDataObject();
1776         vtkPolyData *pd = vtkPolyData::SafeDownCast(dso);
1777 
1778         if (!pd || !pd->GetPoints())
1779         {
1780           continue;
1781         }
1782         int cellFlag = 0;
1783         bool hasScalars = this->ScalarVisibility &&
1784           (vtkAbstractMapper::GetAbstractScalars(
1785             pd, this->ScalarMode, this->ArrayAccessMode,
1786             this->ArrayId, this->ArrayName,
1787             cellFlag) != nullptr);
1788 
1789         bool hasNormals =
1790           (pd->GetPointData()->GetNormals() || pd->GetCellData()->GetNormals());
1791 
1792         bool hasTCoords = (pd->GetPointData()->GetTCoords() != nullptr);
1793 
1794         std::ostringstream toString;
1795         toString.str("");
1796         toString.clear();
1797         toString <<
1798           'A' << (hasScalars ? 1 : 0) <<
1799           'B' << (hasNormals ? 1 : 0) <<
1800           'C' << (hasTCoords ? 1 : 0);
1801 
1802         vtkCompositeMapperHelper2 *helper = nullptr;
1803         helpIter found = this->Helpers.find(toString.str());
1804         if (found == this->Helpers.end())
1805         {
1806           helper = this->CreateHelper();
1807           helper->SetParent(this);
1808           this->Helpers.insert(std::make_pair(toString.str(), helper));
1809         }
1810         else
1811         {
1812           helper = found->second;
1813         }
1814         this->CopyMapperValuesToHelper(helper);
1815         helper->SetMarked(true);
1816         this->HelperDataMap[pd] =
1817           helper->AddData(pd, flatIndex);
1818       }
1819     }
1820     else
1821     {
1822       vtkPolyData *pd = vtkPolyData::SafeDownCast(
1823         this->GetInputDataObject(0, 0));
1824       if (pd && pd->GetPoints())
1825       {
1826         int cellFlag = 0;
1827         bool hasScalars = this->ScalarVisibility &&
1828           (vtkAbstractMapper::GetAbstractScalars(
1829             pd, this->ScalarMode, this->ArrayAccessMode,
1830             this->ArrayId, this->ArrayName,
1831             cellFlag) != nullptr);
1832 
1833         bool hasNormals =
1834           (pd->GetPointData()->GetNormals() || pd->GetCellData()->GetNormals());
1835 
1836         bool hasTCoords = (pd->GetPointData()->GetTCoords() != nullptr);
1837 
1838         std::ostringstream toString;
1839         toString.str("");
1840         toString.clear();
1841         toString <<
1842           'A' << (hasScalars ? 1 : 0) <<
1843           'B' << (hasNormals ? 1 : 0) <<
1844           'C' << (hasTCoords ? 1 : 0);
1845 
1846         vtkCompositeMapperHelper2 *helper = nullptr;
1847         helpIter found = this->Helpers.find(toString.str());
1848         if (found == this->Helpers.end())
1849         {
1850           helper = this->CreateHelper();
1851           helper->SetParent(this);
1852           this->Helpers.insert(std::make_pair(toString.str(), helper));
1853         }
1854         else
1855         {
1856           helper = found->second;
1857         }
1858         this->CopyMapperValuesToHelper(helper);
1859         helper->SetMarked(true);
1860         this->HelperDataMap[pd] =
1861           helper->AddData(pd, 0);
1862       }
1863     }
1864 
1865     // delete unused old helpers/data
1866     for (helpIter hiter = this->Helpers.begin(); hiter != this->Helpers.end(); )
1867     {
1868       hiter->second->RemoveUnused();
1869       if (!hiter->second->GetMarked())
1870       {
1871         hiter->second->ReleaseGraphicsResources(ren->GetVTKWindow());
1872         hiter->second->Delete();
1873         this->Helpers.erase(hiter++);
1874       }
1875       else
1876       {
1877         ++hiter;
1878       }
1879     }
1880     this->HelperMTime.Modified();
1881   }
1882 
1883   // rebuild the render values if needed
1884   if (this->RenderValuesBuildTime < this->GetMTime() ||
1885       this->RenderValuesBuildTime < actor->GetProperty()->GetMTime() ||
1886       this->RenderValuesBuildTime < this->VBOBuildTime ||
1887       this->RenderValuesBuildTime < this->HelperMTime)
1888   {
1889     vtkProperty* prop = actor->GetProperty();
1890 
1891     // Push base-values on the state stack.
1892     this->BlockState.Visibility.push(true);
1893     this->BlockState.Pickability.push(true);
1894     this->BlockState.Opacity.push(prop->GetOpacity());
1895     this->BlockState.AmbientColor.push(vtkColor3d(prop->GetAmbientColor()));
1896     this->BlockState.DiffuseColor.push(vtkColor3d(prop->GetDiffuseColor()));
1897     this->BlockState.SpecularColor.push(vtkColor3d(prop->GetSpecularColor()));
1898 
1899     unsigned int flat_index = 0;
1900     this->BuildRenderValues(ren, actor,
1901       this->GetInputDataObject(0, 0), flat_index);
1902 
1903     this->BlockState.Visibility.pop();
1904     this->BlockState.Pickability.pop();
1905     this->BlockState.Opacity.pop();
1906     this->BlockState.AmbientColor.pop();
1907     this->BlockState.DiffuseColor.pop();
1908     this->BlockState.SpecularColor.pop();
1909 
1910     this->RenderValuesBuildTime.Modified();
1911   }
1912 
1913   this->InitializeHelpersBeforeRendering(ren, actor);
1914 
1915   for (helpIter hiter = this->Helpers.begin(); hiter != this->Helpers.end(); ++hiter)
1916   {
1917     vtkCompositeMapperHelper2 *helper = hiter->second;
1918     helper->RenderPiece(ren,actor);
1919 
1920     std::vector<vtkPolyData *> pdl = helper->GetRenderedList();
1921     for (unsigned int i = 0; i < pdl.size(); ++i)
1922     {
1923       this->RenderedList.push_back(pdl[i]);
1924     }
1925   }
1926 }
1927 
CreateHelper()1928 vtkCompositeMapperHelper2 *vtkCompositePolyDataMapper2::CreateHelper()
1929 {
1930   return vtkCompositeMapperHelper2::New();
1931 }
1932 
1933 //-----------------------------------------------------------------------------
BuildRenderValues(vtkRenderer * renderer,vtkActor * actor,vtkDataObject * dobj,unsigned int & flat_index)1934 void vtkCompositePolyDataMapper2::BuildRenderValues(
1935   vtkRenderer *renderer,
1936   vtkActor *actor,
1937   vtkDataObject *dobj,
1938   unsigned int &flat_index)
1939 {
1940   vtkCompositeDataDisplayAttributes* cda = this->GetCompositeDataDisplayAttributes();
1941   bool overrides_visibility = (cda && cda->HasBlockVisibility(dobj));
1942   if (overrides_visibility)
1943   {
1944     this->BlockState.Visibility.push(cda->GetBlockVisibility(dobj));
1945   }
1946   bool overrides_pickability = (cda && cda->HasBlockPickability(dobj));
1947   if (overrides_pickability)
1948   {
1949     this->BlockState.Pickability.push(cda->GetBlockPickability(dobj));
1950   }
1951 
1952   bool overrides_opacity = (cda && cda->HasBlockOpacity(dobj));
1953   if (overrides_opacity)
1954   {
1955     this->BlockState.Opacity.push(cda->GetBlockOpacity(dobj));
1956   }
1957 
1958   bool overrides_color = (cda && cda->HasBlockColor(dobj));
1959   if (overrides_color)
1960   {
1961     vtkColor3d color = cda->GetBlockColor(dobj);
1962     this->BlockState.AmbientColor.push(color);
1963     this->BlockState.DiffuseColor.push(color);
1964     this->BlockState.SpecularColor.push(color);
1965   }
1966 
1967   // Advance flat-index. After this point, flat_index no longer points to this
1968   // block.
1969   flat_index++;
1970 
1971   vtkMultiBlockDataSet *mbds = vtkMultiBlockDataSet::SafeDownCast(dobj);
1972   vtkMultiPieceDataSet *mpds = vtkMultiPieceDataSet::SafeDownCast(dobj);
1973   if (mbds || mpds)
1974   {
1975     unsigned int numChildren = mbds? mbds->GetNumberOfBlocks() :
1976       mpds->GetNumberOfPieces();
1977     for (unsigned int cc=0 ; cc < numChildren; cc++)
1978     {
1979       vtkDataObject* child = mbds ? mbds->GetBlock(cc) : mpds->GetPiece(cc);
1980       if (child == nullptr)
1981       {
1982         // speeds things up when dealing with nullptr blocks (which is common with
1983         // AMRs).
1984         flat_index++;
1985         continue;
1986       }
1987       this->BuildRenderValues(renderer, actor, child, flat_index);
1988     }
1989   }
1990   else
1991   {
1992     vtkPolyData *pd = vtkPolyData::SafeDownCast(dobj);
1993     dataIter dit = this->HelperDataMap.find(pd);
1994     if (dit != this->HelperDataMap.end())
1995     {
1996       vtkCompositeMapperHelperData *helperData = dit->second;
1997       helperData->Opacity = this->BlockState.Opacity.top();
1998       helperData->Visibility = this->BlockState.Visibility.top();
1999       helperData->Pickability = this->BlockState.Pickability.top();
2000       helperData->AmbientColor = this->BlockState.AmbientColor.top();
2001       helperData->DiffuseColor = this->BlockState.DiffuseColor.top();
2002       helperData->OverridesColor = (this->BlockState.AmbientColor.size() > 1);
2003     }
2004   }
2005   if (overrides_color)
2006   {
2007     this->BlockState.AmbientColor.pop();
2008     this->BlockState.DiffuseColor.pop();
2009     this->BlockState.SpecularColor.pop();
2010   }
2011   if (overrides_opacity)
2012   {
2013     this->BlockState.Opacity.pop();
2014   }
2015   if (overrides_pickability)
2016   {
2017     this->BlockState.Pickability.pop();
2018   }
2019   if (overrides_visibility)
2020   {
2021     this->BlockState.Visibility.pop();
2022   }
2023 }
2024 
2025 //----------------------------------------------------------------------------
SetInputArrayToProcess(int idx,vtkInformation * inInfo)2026 void vtkCompositePolyDataMapper2::SetInputArrayToProcess(int idx, vtkInformation* inInfo)
2027 {
2028   this->Superclass::SetInputArrayToProcess(idx, inInfo);
2029 
2030   // set inputs to helpers
2031   for (auto& helper : this->Helpers)
2032   {
2033     helper.second->SetInputArrayToProcess(idx, inInfo);
2034   }
2035 }
2036 
2037 //----------------------------------------------------------------------------
SetInputArrayToProcess(int idx,int port,int connection,int fieldAssociation,int attributeType)2038 void vtkCompositePolyDataMapper2::SetInputArrayToProcess(
2039   int idx, int port, int connection, int fieldAssociation, int attributeType)
2040 {
2041   this->Superclass::SetInputArrayToProcess(idx, port, connection, fieldAssociation, attributeType);
2042 
2043   // set inputs to helpers
2044   for (auto& helper : this->Helpers)
2045   {
2046     helper.second->SetInputArrayToProcess(idx, port, connection, fieldAssociation, attributeType);
2047   }
2048 }
2049 
2050 //-----------------------------------------------------------------------------
SetInputArrayToProcess(int idx,int port,int connection,int fieldAssociation,const char * name)2051 void vtkCompositePolyDataMapper2::SetInputArrayToProcess(
2052   int idx, int port, int connection, int fieldAssociation, const char* name)
2053 {
2054   this->Superclass::SetInputArrayToProcess(idx, port, connection, fieldAssociation, name);
2055 
2056   // set inputs to helpers
2057   for (auto& helper : this->Helpers)
2058   {
2059     helper.second->SetInputArrayToProcess(idx, port, connection, fieldAssociation, name);
2060   }
2061 }
2062 
ProcessSelectorPixelBuffers(vtkHardwareSelector * sel,std::vector<unsigned int> & pixeloffsets,vtkProp * prop)2063 void vtkCompositePolyDataMapper2::ProcessSelectorPixelBuffers(
2064   vtkHardwareSelector *sel,
2065   std::vector<unsigned int> &pixeloffsets,
2066   vtkProp *prop)
2067 {
2068   // forward to helper
2069   for (auto& helper : this->Helpers)
2070   {
2071     helper.second->ProcessSelectorPixelBuffers(sel, pixeloffsets, prop);
2072   }
2073 }
2074