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