vtkOpenGLGlyph3DMapper.cxx 30.2 KB
Newer Older
1 2 3
/*=========================================================================

  Program:   Visualization Toolkit
4
  Module:    vtkOpenGLGlyph3DMapper.cxx
5 6 7 8 9 10 11 12 13 14

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
#include "vtkOpenGLGlyph3DMapper.h"
16 17 18

#include "vtkActor.h"
#include "vtkBitArray.h"
19
#include "vtkCompositeDataDisplayAttributes.h"
20 21
#include "vtkCompositeDataIterator.h"
#include "vtkCompositeDataSet.h"
22
#include "vtkCompositeDataSetRange.h"
23 24
#include "vtkDataObjectTree.h"
#include "vtkDataObjectTreeIterator.h"
25 26
#include "vtkHardwareSelector.h"
#include "vtkMath.h"
27
#include "vtkMatrix3x3.h"
28
#include "vtkObjectFactory.h"
Ken Martin's avatar
Ken Martin committed
29
#include "vtkOpenGLGlyph3DHelper.h"
30 31 32 33 34
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkTransform.h"
#include "vtkOpenGLError.h"
Ken Martin's avatar
Ken Martin committed
35
#include "vtkSmartPointer.h"
36
#include "vtkQuaternion.h"
37

38 39
#include <map>

40 41 42 43 44 45 46 47
namespace {
int getNumberOfChildren(vtkDataObjectTree *tree)
{
  int result = 0;
  if (tree)
  {
    vtkDataObjectTreeIterator *it = tree->NewTreeIterator();
    it->SetTraverseSubTree(false);
48
    it->SetVisitOnlyLeaves(false);
49 50 51 52 53 54 55 56 57 58 59
    for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
    {
      ++result;
    }
    it->Delete();
  }
  return result;
}

vtkDataObject* getChildDataObject(vtkDataObjectTree *tree, int child)
{
60
  vtkDataObject *result = nullptr;
61 62 63 64
  if (tree)
  {
    vtkDataObjectTreeIterator *it = tree->NewTreeIterator();
    it->SetTraverseSubTree(false);
65
    it->SetVisitOnlyLeaves(false);
66 67 68 69 70 71 72 73 74 75 76 77
    it->InitTraversal();
    for (int i = 0; i < child; ++i)
    {
      it->GoToNextItem();
    }
    result = it->GetCurrentDataObject();
    it->Delete();
  }
  return result;
}
}

Ken Martin's avatar
Ken Martin committed
78
class vtkOpenGLGlyph3DMappervtkColorMapper : public vtkMapper
79 80
{
public:
Ken Martin's avatar
Ken Martin committed
81 82
  vtkTypeMacro(vtkOpenGLGlyph3DMappervtkColorMapper, vtkMapper);
  static vtkOpenGLGlyph3DMappervtkColorMapper* New();
83
  void Render(vtkRenderer *, vtkActor *) override {}
84 85 86
  vtkUnsignedCharArray* GetColors() { return this->Colors; }
};

Ken Martin's avatar
Ken Martin committed
87 88
vtkStandardNewMacro(vtkOpenGLGlyph3DMappervtkColorMapper)

89
class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry
90 91
{
public:
92
  std::vector<vtkIdType> PickIds;
93
  std::vector<unsigned char> Colors;
94 95
  std::vector<float> Matrices;  // transposed
  std::vector<float> NormalMatrices; // transposed
96
  vtkTimeStamp BuildTime;
97 98 99 100 101 102
  // May be polydata or composite dataset:
  vtkDataObject *DataObject;
  // maps composite dataset flat index to polydatamapper. Key = -1 for polydata
  // DataObject.
  typedef std::map<int, vtkOpenGLGlyph3DHelper*> MapperMap;
  MapperMap Mappers;
Ken Martin's avatar
Ken Martin committed
103
  int NumberOfPoints;
104

Ken Martin's avatar
Ken Martin committed
105 106
  vtkOpenGLGlyph3DMapperEntry()
  {
Ken Martin's avatar
Ken Martin committed
107
    this->NumberOfPoints = 0;
108
    this->DataObject = nullptr;
Ken Martin's avatar
Ken Martin committed
109
  };
110 111
  ~vtkOpenGLGlyph3DMapperEntry()
  {
112 113 114 115 116
    this->ClearMappers();
    if (this->DataObject)
    {
      this->DataObject->Delete();
    }
Ken Martin's avatar
Ken Martin committed
117
  };
118 119 120 121 122 123 124 125 126
  void ClearMappers()
  {
    for (MapperMap::iterator it = this->Mappers.begin();
         it != this->Mappers.end(); ++it)
    {
      it->second->Delete();
    }
    this->Mappers.clear();
  }
Ken Martin's avatar
Ken Martin committed
127 128 129 130 131
};

class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray
{
public:
132
  std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *>  Entries;
Ken Martin's avatar
Ken Martin committed
133
  vtkTimeStamp BuildTime;
134
  vtkOpenGLGlyph3DMapperSubArray() = default;
Ken Martin's avatar
Ken Martin committed
135
  ~vtkOpenGLGlyph3DMapperSubArray()
136 137 138 139
  {
    this->ClearEntries();
  };
  void ClearEntries()
Ken Martin's avatar
Ken Martin committed
140
  {
141
    std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *>::iterator miter = this->Entries.begin();
142
    for (;miter != this->Entries.end(); ++miter)
143
    {
144
      delete *miter;
145
    }
146 147
    this->Entries.clear();
  }
148 149
};

150
class vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperArray
151 152
{
public:
Ken Martin's avatar
Ken Martin committed
153
  std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *> Entries;
154 155
  ~vtkOpenGLGlyph3DMapperArray()
  {
Ken Martin's avatar
Ken Martin committed
156
    std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator miter = this->Entries.begin();
157
    for (;miter != this->Entries.end(); ++miter)
158
    {
159
      delete miter->second;
160
    }
Ken Martin's avatar
Ken Martin committed
161
    this->Entries.clear();
162
  };
163 164
};

165
vtkStandardNewMacro(vtkOpenGLGlyph3DMapper)
166

167 168 169 170 171
// ---------------------------------------------------------------------------
// Construct object with scaling on, scaling mode is by scalar value,
// scale factor = 1.0, the range is (0,1), orient geometry is on, and
// orientation is by vector. Clamping and indexing are turned off. No
// initial sources are defined.
172
vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapper()
173
{
174
  this->GlyphValues = new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperArray();
Ken Martin's avatar
Ken Martin committed
175
  this->ColorMapper = vtkOpenGLGlyph3DMappervtkColorMapper::New();
176 177 178
}

// ---------------------------------------------------------------------------
179
vtkOpenGLGlyph3DMapper::~vtkOpenGLGlyph3DMapper()
180
{
Ken Martin's avatar
Ken Martin committed
181
  this->ColorMapper->Delete();
182

Ken Martin's avatar
Ken Martin committed
183
  delete this->GlyphValues;
184
  this->GlyphValues = nullptr;
185 186 187 188 189 190
}

// ---------------------------------------------------------------------------
// Description:
// Send mapper ivars to sub-mapper.
// \pre mapper_exists: mapper!=0
191
void vtkOpenGLGlyph3DMapper::CopyInformationToSubMapper(
Ken Martin's avatar
Ken Martin committed
192
    vtkOpenGLGlyph3DHelper *mapper)
193
{
194
  assert("pre: mapper_exists" && mapper!=nullptr);
195 196 197 198 199 200 201 202 203
  mapper->SetStatic(this->Static);
  mapper->ScalarVisibilityOff();
  // not used
  mapper->SetClippingPlanes(this->ClippingPlanes);

  mapper->SetResolveCoincidentTopology(this->GetResolveCoincidentTopology());
  mapper->SetResolveCoincidentTopologyZShift(
    this->GetResolveCoincidentTopologyZShift());

204 205 206 207 208 209 210 211
  double f, u;
  this->GetRelativeCoincidentTopologyPolygonOffsetParameters(f, u);
  mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(f, u);
  this->GetRelativeCoincidentTopologyLineOffsetParameters(f, u);
  mapper->SetRelativeCoincidentTopologyLineOffsetParameters(f, u);
  this->GetRelativeCoincidentTopologyPointOffsetParameter(u);
  mapper->SetRelativeCoincidentTopologyPointOffsetParameter(u);

212 213 214
  // ResolveCoincidentTopologyPolygonOffsetParameters is static
  mapper->SetResolveCoincidentTopologyPolygonOffsetFaces(
    this->GetResolveCoincidentTopologyPolygonOffsetFaces());
215 216 217 218 219 220 221 222 223 224 225

  if (static_cast<vtkIdType>(this->LODs.size()) > this->GetMaxNumberOfLOD())
  {
    vtkWarningMacro(<< "too many LODs are defined, "
                    << (static_cast<vtkIdType>(this->LODs.size()) - this->GetMaxNumberOfLOD())
                    << " last defined LODs are discarded.");
    this->LODs.resize(this->GetMaxNumberOfLOD());
  }

  mapper->SetLODs(this->LODs);
  mapper->SetLODColoring(this->LODColoring);
226 227
}

228
void vtkOpenGLGlyph3DMapper::SetupColorMapper()
229 230 231 232
{
  this->ColorMapper->ShallowCopy(this);
}

233 234 235 236
// ---------------------------------------------------------------------------
// Description:
// Method initiates the mapping process. Generally sent by the actor
// as each frame is rendered.
237
void vtkOpenGLGlyph3DMapper::Render(vtkRenderer *ren, vtkActor *actor)
238 239 240
{
  vtkOpenGLClearErrorMacro();

241 242
  this->SetupColorMapper();

243
  vtkHardwareSelector* selector = ren->GetSelector();
244 245

  if (selector)
246
  {
247
    selector->BeginRenderProp();
248
  }
249 250 251

  vtkDataObject* inputDO = this->GetInputDataObject(0, 0);

Ken Martin's avatar
Ken Martin committed
252 253 254
  // Check input for consistency
  //
  // Create a default source, if no source is specified.
255
  if (!this->UseSourceTableTree && this->GetSource(0) == nullptr)
256
  {
Ken Martin's avatar
Ken Martin committed
257 258 259 260 261 262 263 264 265 266 267 268 269
    vtkPolyData *defaultSource = vtkPolyData::New();
    defaultSource->Allocate();
    vtkPoints *defaultPoints = vtkPoints::New();
    defaultPoints->Allocate(6);
    defaultPoints->InsertNextPoint(0., 0., 0.);
    defaultPoints->InsertNextPoint(1., 0., 0.);
    vtkIdType defaultPointIds[2];
    defaultPointIds[0] = 0;
    defaultPointIds[1] = 1;
    defaultSource->SetPoints(defaultPoints);
    defaultSource->InsertNextCell(VTK_LINE, 2, defaultPointIds);
    this->SetSourceData(defaultSource);
    defaultSource->Delete();
270
    defaultSource = nullptr;
Ken Martin's avatar
Ken Martin committed
271
    defaultPoints->Delete();
272
    defaultPoints = nullptr;
273
  }
274

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
  // Check that source configuration is sane:
  vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
  int numSourceDataSets = this->GetNumberOfInputConnections(1);
  if (this->UseSourceTableTree)
  {
    if (numSourceDataSets > 1)
    {
      vtkErrorMacro("UseSourceTableTree is true, but multiple source datasets "
                    "are set.");
      return;
    }
    if (!sourceTableTree)
    {
      vtkErrorMacro("UseSourceTableTree is true, but the source dataset is "
                    "not a vtkDataObjectTree.");
      return;
    }
    vtkDataObjectTreeIterator *it = sourceTableTree->NewTreeIterator();
    it->SetTraverseSubTree(false);
294
    it->SetVisitOnlyLeaves(false);
295 296 297
    for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
    {
      vtkDataObject *node = it->GetCurrentDataObject();
298
      if (!node->IsA("vtkPolyData") && !node->IsA("vtkCompositeDataSet"))
299 300
      {
        vtkErrorMacro("The source table tree must only contain vtkPolyData "
301 302 303
                      "or vtkCompositeDataSet children, but found a "
                      << node->GetClassName() << ".");
        it->Delete();
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
        return;
      }
    }
    it->Delete();
  }
  else
  {
    for (int i = 0; i < numSourceDataSets; ++i)
    {
      if (!this->GetSource(i))
      {
        vtkErrorMacro("Source input at index " << i << " not set, or not "
                      "vtkPolyData.");
        return;
      }
    }
  }

322
  // Render the input dataset or every dataset in the input composite dataset.
323
  this->BlockMTime = this->BlockAttributes ? this->BlockAttributes->GetMTime() : 0;
324 325 326
  vtkDataSet* ds = vtkDataSet::SafeDownCast(inputDO);
  vtkCompositeDataSet* cd = vtkCompositeDataSet::SafeDownCast(inputDO);
  if (ds)
327
  {
328
    this->Render(ren, actor, ds);
329
  }
330
  else if (cd)
331
  {
332 333 334 335 336 337 338
    vtkNew<vtkActor> blockAct;
    vtkNew<vtkProperty> blockProp;
    blockAct->ShallowCopy(actor);
    blockProp->DeepCopy(blockAct->GetProperty());
    blockAct->SetProperty(blockProp.GetPointer());
    double origColor[4];
    blockProp->GetColor(origColor);
339 340 341

    using Opts = vtk::CompositeDataSetOptions;
    for (auto node : vtk::Range(cd, Opts::SkipEmptyNodes))
342
    {
343 344 345
      auto curIndex = node.GetFlatIndex();
      auto currentObj = node.GetDataObject();

346 347
      // Skip invisible blocks and unpickable ones when performing selection:
      bool blockVis =
348 349
        (this->BlockAttributes && this->BlockAttributes->HasBlockVisibility(currentObj)) ?
        this->BlockAttributes->GetBlockVisibility(currentObj) : true;
350
      bool blockPick =
351 352
        (this->BlockAttributes && this->BlockAttributes->HasBlockPickability(currentObj)) ?
        this->BlockAttributes->GetBlockPickability(currentObj) : true;
353 354 355 356
      if (!blockVis || (selector && !blockPick))
      {
        continue;
      }
357
      ds = vtkDataSet::SafeDownCast(currentObj);
358
      if (ds)
359
      {
360
        if (selector)
361
        {
362 363
          selector->RenderCompositeIndex(curIndex);
        }
364
        else if (this->BlockAttributes && this->BlockAttributes->HasBlockColor(currentObj))
365 366
        {
          double color[3];
367
          this->BlockAttributes->GetBlockColor(currentObj, color);
368 369 370 371 372
          blockProp->SetColor(color);
        }
        else
        {
          blockProp->SetColor(origColor);
373
        }
374
        this->Render(ren, blockAct.GetPointer(), ds);
375
      }
376
    }
377
  }
378 379

  if (selector)
380
  {
381
    selector->EndRenderProp();
382
  }
383 384 385 386 387 388 389

  vtkOpenGLCheckErrorMacro("Failed after Render");

  this->UpdateProgress(1.0);
}

// ---------------------------------------------------------------------------
390
void vtkOpenGLGlyph3DMapper::Render(
391 392 393 394
  vtkRenderer* ren, vtkActor* actor, vtkDataSet* dataset)
{
  vtkIdType numPts = dataset->GetNumberOfPoints();
  if (numPts < 1)
395
  {
396 397
    vtkDebugMacro(<<"No points to glyph!");
    return;
398
  }
399

Ken Martin's avatar
Ken Martin committed
400 401 402 403
  // make sure we have an entry for this dataset
  vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *subarray;
  bool rebuild = false;
  typedef std::map<const vtkDataSet *,vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator GVIter;
404 405
  GVIter found = this->GlyphValues->Entries.find(dataset);
  if (found == this->GlyphValues->Entries.end())
406
  {
Ken Martin's avatar
Ken Martin committed
407 408 409
    subarray = new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray();
    this->GlyphValues->Entries.insert(std::make_pair(dataset, subarray));
    rebuild = true;
410
  }
411
  else
412
  {
Ken Martin's avatar
Ken Martin committed
413
    subarray = found->second;
414
  }
415

Ken Martin's avatar
Ken Martin committed
416
  // make sure we have a subentry for each source
417 418 419 420 421
  vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
  int sTTSize = getNumberOfChildren(sourceTableTree);
  int numSourceDataSets = this->GetNumberOfInputConnections(1);
  size_t numberOfSources = this->UseSourceTableTree ? sTTSize
                                                    : numSourceDataSets;
Ken Martin's avatar
Ken Martin committed
422 423
  bool numberOfSourcesChanged = false;
  if (numberOfSources != subarray->Entries.size())
424
  {
425
    subarray->ClearEntries();
Ken Martin's avatar
Ken Martin committed
426
    for (size_t cc = 0; cc < numberOfSources; cc++)
427
    {
428 429
      subarray->Entries.push_back(
        new vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry());
Ken Martin's avatar
Ken Martin committed
430
    }
431 432
    numberOfSourcesChanged = true;
  }
Ken Martin's avatar
Ken Martin committed
433 434

  // make sure sources are up to date
435
  vtkDataObjectTreeIterator *sTTIter = nullptr;
436 437 438 439
  if (sourceTableTree)
  {
    sTTIter = sourceTableTree->NewTreeIterator();
    sTTIter->SetTraverseSubTree(false);
440
    sTTIter->SetVisitOnlyLeaves(false);
441 442
    sTTIter->InitTraversal();
  }
Ken Martin's avatar
Ken Martin committed
443
  for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
444
  {
445 446
    vtkDataObject *s = this->UseSourceTableTree
        ? sTTIter->GetCurrentDataObject()
447
        : this->GetSource(static_cast<int>(cc));
448 449 450 451 452 453

    vtkOpenGLGlyph3DMapperEntry *entry = subarray->Entries[cc];
    vtkDataObject *ss = entry->DataObject;
    if (ss && !ss->IsA(s->GetClassName()))
    {
      ss->Delete();
454
      ss = nullptr;
455 456 457 458 459 460
    }
    if (!ss)
    {
      ss = s->NewInstance();
      entry->DataObject = ss;
    }
461 462 463
    if (numberOfSourcesChanged ||
      s->GetMTime() > ss->GetMTime() ||
      this->GetMTime() > entry->BuildTime)
464
    {
Ken Martin's avatar
Ken Martin committed
465
      ss->ShallowCopy(s);
466
      entry->ClearMappers();
Ken Martin's avatar
Ken Martin committed
467
    }
468 469

    // Create/update the helper mappers:
470
    vtkCompositeDataIterator *cdsIter = nullptr;
471 472 473 474
    if (vtkCompositeDataSet *cds = vtkCompositeDataSet::SafeDownCast(ss))
    {
      cdsIter = cds->NewIterator();
      cdsIter->InitTraversal();
Ken Martin's avatar
Ken Martin committed
475
    }
476 477 478

    for (;;)
    {
479
      vtkOpenGLGlyph3DHelper *mapper = nullptr;
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508

      int mapperIdx = cdsIter ? cdsIter->GetCurrentFlatIndex() : -1;
      vtkOpenGLGlyph3DMapperEntry::MapperMap::iterator mapIter =
          entry->Mappers.find(mapperIdx);
      if (mapIter == entry->Mappers.end())
      {
        mapper = vtkOpenGLGlyph3DHelper::New();
        entry->Mappers.insert(std::make_pair(mapperIdx, mapper));
      }
      else
      {
        mapper = mapIter->second;
      }
      this->CopyInformationToSubMapper(mapper);

      if (cdsIter)
      {
        cdsIter->GoToNextItem();
      }

      if (!cdsIter || cdsIter->IsDoneWithTraversal())
      {
        break;
      }
    }

    if (cdsIter)
    {
      cdsIter->Delete();
509
      cdsIter = nullptr;
510 511
    }

512 513 514 515 516 517 518 519
    if (sTTIter)
    {
      sTTIter->GoToNextItem();
    }
  }
  if (sTTIter)
  {
    sTTIter->Delete();
520
    sTTIter = nullptr;
521
  }
522

Ken Martin's avatar
Ken Martin committed
523 524
  // rebuild all entries for this DataSet if it
  // has been modified
525
  if (subarray->BuildTime < dataset->GetMTime() ||
526 527
      subarray->BuildTime < this->GetMTime() ||
      subarray->BuildTime < this->BlockMTime)
528
  {
Ken Martin's avatar
Ken Martin committed
529
    rebuild = true;
530
  }
531

Ken Martin's avatar
Ken Martin committed
532
  // get the mask array
533
  vtkBitArray *maskArray = nullptr;
534
  if (this->Masking)
535
  {
536
    maskArray = vtkArrayDownCast<vtkBitArray>(this->GetMaskArray(dataset));
537
    if (maskArray == nullptr)
538
    {
539
      vtkDebugMacro(<<"masking is enabled but there is no mask array. Ignore masking.");
540
    }
541
    else
542
    {
543
      if (maskArray->GetNumberOfComponents() != 1)
544
      {
545 546 547 548 549
        vtkErrorMacro(" expecting a mask array with one component, getting "
          << maskArray->GetNumberOfComponents() << " components.");
        return;
      }
    }
550
  }
551

Ken Martin's avatar
Ken Martin committed
552 553
  // rebuild all sources for this dataset
  if (rebuild)
554
  {
555
    this->RebuildStructures(subarray, numPts, actor, dataset, maskArray);
556
  }
Ken Martin's avatar
Ken Martin committed
557 558 559

  // for each subarray
  for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
560
  {
Ken Martin's avatar
Ken Martin committed
561 562
    vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
      subarray->Entries[cc];
563
    if (entry->NumberOfPoints <= 0)
564
    {
565
      continue;
566
    }
Ken Martin's avatar
Ken Martin committed
567

568 569
    vtkDataObject *dObj = entry->DataObject;
    vtkPolyData *pd = vtkPolyData::SafeDownCast(dObj);
570
    vtkCompositeDataSet *cds = pd ? nullptr
571
                                  : vtkCompositeDataSet::SafeDownCast(dObj);
Ken Martin's avatar
Ken Martin committed
572

573
    vtkCompositeDataIterator *cdsIter = nullptr;
574
    if (cds)
575
    {
576 577
      cdsIter = cds->NewIterator();
      cdsIter->InitTraversal();
578
    }
579 580 581 582

    // Either render the polydata, or loop through the composite dataset and
    // render each polydata leaf:
    for (;;)
583
    {
584 585
      int mapperIdx = -1;
      if (cdsIter)
586
      {
587 588 589 590 591
        pd = vtkPolyData::SafeDownCast(cdsIter->GetCurrentDataObject());
        mapperIdx = cdsIter->GetCurrentFlatIndex();
        cdsIter->GoToNextItem();
      }

592
      if (pd && pd->GetNumberOfPoints() > 0)
593 594 595
      {
        vtkOpenGLGlyph3DHelper *gh = entry->Mappers[mapperIdx];
        gh->CurrentInput = pd;
596 597
        gh->GlyphRender(ren, actor, entry->NumberOfPoints,
                        entry->Colors, entry->Matrices, entry->NormalMatrices,
598
                        entry->PickIds, subarray->BuildTime, this->CullingAndLOD);
599
      }
600 601

      if (!cdsIter || cdsIter->IsDoneWithTraversal())
602
      {
603
        break;
Ken Martin's avatar
Ken Martin committed
604
      }
605 606 607 608 609
    } // end composite glyph iteration

    if (cdsIter)
    {
      cdsIter->Delete();
610
      cdsIter = nullptr;
Ken Martin's avatar
Ken Martin committed
611
    }
612
  } // end entries
Ken Martin's avatar
Ken Martin committed
613 614 615 616

  vtkOpenGLCheckErrorMacro("failed after Render");
}

617

Ken Martin's avatar
Ken Martin committed
618 619 620 621 622 623 624

// ---------------------------------------------------------------------------
void vtkOpenGLGlyph3DMapper::RebuildStructures(
  vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *subarray,
  vtkIdType numPts,
  vtkActor* actor,
  vtkDataSet* dataset,
625
  vtkBitArray *maskArray)
Ken Martin's avatar
Ken Martin committed
626 627 628
{
  double den = this->Range[1] - this->Range[0];
  if (den == 0.0)
629
  {
Ken Martin's avatar
Ken Martin committed
630
    den = 1.0;
631
  }
Ken Martin's avatar
Ken Martin committed
632

633
  unsigned char color[4];
634
  {
635 636
    const double *actorColor = actor->GetProperty()->GetColor();
    for (int i = 0; i != 3; ++i)
637
    {
638
      color[i] = static_cast<unsigned char>(actorColor[i] * 255. + 0.5);
639
    }
640 641
    color[3] =
      static_cast<unsigned char>(actor->GetProperty()->GetOpacity()*255. + 0.5);
642
  }
643

Ken Martin's avatar
Ken Martin committed
644
  vtkDataArray* orientArray = this->GetOrientationArray(dataset);
645
  if (orientArray != nullptr)
646
  {
647 648 649 650 651 652 653 654 655 656 657 658
    if ((this->OrientationMode == ROTATION || this->OrientationMode == DIRECTION) && orientArray->GetNumberOfComponents() != 3)
    {
      vtkErrorMacro(" expecting an orientation array with 3 components, getting "
        << orientArray->GetNumberOfComponents() << " components.");
      return;
    }
    else if (this->OrientationMode == QUATERNION && orientArray->GetNumberOfComponents() != 4)
    {
      vtkErrorMacro(" expecting an orientation array with 4 components, getting "
        << orientArray->GetNumberOfComponents() << " components.");
      return;
    }
659
  }
Ken Martin's avatar
Ken Martin committed
660

661 662 663 664
  vtkDataArray* indexArray = this->GetSourceIndexArray(dataset);
  vtkDataArray* scaleArray = this->GetScaleArray(dataset);
  vtkDataArray* selectionArray = this->GetSelectionIdArray(dataset);

Ken Martin's avatar
Ken Martin committed
665 666 667
  /// FIXME: Didn't handle the premultiplycolorswithalpha aspect...
  this->ColorMapper->SetInputDataObject(dataset);
  this->ColorMapper->MapScalars(actor->GetProperty()->GetOpacity());
668
  vtkUnsignedCharArray* colors = ((vtkOpenGLGlyph3DMappervtkColorMapper *)this->ColorMapper)->GetColors();
Ken Martin's avatar
Ken Martin committed
669 670 671 672 673 674
  // Traverse all Input points, transforming Source points

  int numEntries = (int)subarray->Entries.size();

  // how many points for each source
  int *numPointsPerSource = new int [numEntries];
675
  std::fill(numPointsPerSource, numPointsPerSource + numEntries, 0);
Ken Martin's avatar
Ken Martin committed
676
  if (numEntries > 1 && indexArray)
677
  {
Ken Martin's avatar
Ken Martin committed
678 679
    // loop over every point
    int index = 0;
680
    for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
681
    {
Ken Martin's avatar
Ken Martin committed
682
      if (maskArray && maskArray->GetValue(inPtId) == 0)
683
      {
Ken Martin's avatar
Ken Martin committed
684
        continue;
685
      }
686

Ken Martin's avatar
Ken Martin committed
687
      // Compute index into table of glyphs
688 689 690 691
      double value = vtkMath::Norm(indexArray->GetTuple(inPtId),
        indexArray->GetNumberOfComponents());
      index = static_cast<int>(value);
      index = vtkMath::ClampValue(index, 0, numEntries-1);
692
      numPointsPerSource[index]++;
Ken Martin's avatar
Ken Martin committed
693
    }
694
  }
Ken Martin's avatar
Ken Martin committed
695
  else
696
  {
Ken Martin's avatar
Ken Martin committed
697
    numPointsPerSource[0] = numPts;
698
  }
699

Ken Martin's avatar
Ken Martin committed
700 701
  // for each entry start with a reasonable allocation
  for (size_t cc = 0; cc < subarray->Entries.size(); cc++)
702
  {
Ken Martin's avatar
Ken Martin committed
703 704
    vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
      subarray->Entries[cc];
705
    entry->PickIds.resize(numPointsPerSource[cc]);
Ken Martin's avatar
Ken Martin committed
706 707
    entry->Colors.resize(numPointsPerSource[cc]*4);
    entry->Matrices.resize(numPointsPerSource[cc]*16);
708
    entry->NormalMatrices.resize(numPointsPerSource[cc]*9);
Ken Martin's avatar
Ken Martin committed
709 710
    entry->NumberOfPoints = 0;
    entry->BuildTime.Modified();
711
  }
Ken Martin's avatar
Ken Martin committed
712 713 714 715
  delete [] numPointsPerSource;

  // loop over every point and fill structures
  int index = 0;
716
  vtkDataObjectTree *sourceTableTree = this->GetSourceTableTree();
717 718 719 720 721 722 723 724 725 726 727 728 729

  // cache sources to improve performances
  std::vector<vtkDataObject*> sourceCache(numEntries);
  for (vtkIdType i = 0; i < numEntries; i++)
  {
    sourceCache[i] = this->UseSourceTableTree
        ? getChildDataObject(sourceTableTree, i)
        : this->GetSource(i);
  }

  double trans[16];
  double normalTrans[9];

Ken Martin's avatar
Ken Martin committed
730
  for (vtkIdType inPtId = 0; inPtId < numPts; inPtId++)
731
  {
Ken Martin's avatar
Ken Martin committed
732
    if (!(inPtId % 10000))
733
    {
Ken Martin's avatar
Ken Martin committed
734 735 736
      this->UpdateProgress (static_cast<double>(inPtId)/
        static_cast<double>(numPts));
      if (this->GetAbortExecute())
737
      {
Ken Martin's avatar
Ken Martin committed
738 739
        break;
      }
740
    }
Ken Martin's avatar
Ken Martin committed
741 742

    if (maskArray && maskArray->GetValue(inPtId) == 0)
743
    {
Ken Martin's avatar
Ken Martin committed
744
      continue;
745
    }
Ken Martin's avatar
Ken Martin committed
746 747 748

    // Compute index into table of glyphs
    if (indexArray)
749
    {
Ken Martin's avatar
Ken Martin committed
750 751
      double value = vtkMath::Norm(indexArray->GetTuple(inPtId),
        indexArray->GetNumberOfComponents());
752
      index = static_cast<int>(value);
753
      index = vtkMath::ClampValue(index, 0, numEntries-1);
754
    }
Ken Martin's avatar
Ken Martin committed
755 756

    // source can be null.
757
    vtkDataObject *source = sourceCache[index];
Ken Martin's avatar
Ken Martin committed
758 759 760

    // Make sure we're not indexing into empty glyph
    if (source)
761
    {
Ken Martin's avatar
Ken Martin committed
762 763 764
      vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *entry =
        subarray->Entries[index];

765 766 767 768
      entry->Colors[entry->NumberOfPoints*4] = color[0];
      entry->Colors[entry->NumberOfPoints*4+1] = color[1];
      entry->Colors[entry->NumberOfPoints*4+2] = color[2];
      entry->Colors[entry->NumberOfPoints*4+3] = color[3];
Ken Martin's avatar
Ken Martin committed
769

770 771 772 773 774
      double scalex = 1.0;
      double scaley = 1.0;
      double scalez = 1.0;
      // Get the scalar and vector data
      if (scaleArray)
775
      {
776 777
        double* tuple = scaleArray->GetTuple(inPtId);
        switch (this->ScaleMode)
778
        {
779 780 781 782 783 784
        case SCALE_BY_MAGNITUDE:
          scalex = scaley = scalez = vtkMath::Norm(tuple,
            scaleArray->GetNumberOfComponents());
          break;
        case SCALE_BY_COMPONENTS:
          if (scaleArray->GetNumberOfComponents() != 3)
785
          {
786 787
            vtkErrorMacro("Cannot scale by components since " <<
              scaleArray->GetName() << " does not have 3 components.");
788
          }
789
          else
790
          {
791 792 793
            scalex = tuple[0];
            scaley = tuple[1];
            scalez = tuple[2];
794
          }
795 796 797 798
          break;
        case NO_DATA_SCALING:
        default:
          break;
799
        }
800

801 802
        // Clamp data scale if enabled
        if (this->Clamping && this->ScaleMode != NO_DATA_SCALING)
803
        {
804 805 806 807 808 809 810 811 812 813
          scalex = (scalex < this->Range[0] ? this->Range[0] :
            (scalex > this->Range[1] ? this->Range[1] : scalex));
          scalex = (scalex - this->Range[0]) / den;
          scaley = (scaley < this->Range[0] ? this->Range[0] :
            (scaley > this->Range[1] ? this->Range[1] : scaley));
          scaley = (scaley - this->Range[0]) / den;
          scalez = (scalez < this->Range[0] ? this->Range[0] :
            (scalez > this->Range[1] ? this->Range[1] : scalez));
          scalez = (scalez - this->Range[0]) / den;
        }
814
      }
815 816 817
      scalex *= this->ScaleFactor;
      scaley *= this->ScaleFactor;
      scalez *= this->ScaleFactor;
818 819

      // Now begin copying/transforming glyph
820 821
      vtkMatrix4x4::Identity(trans);
      vtkMatrix3x3::Identity(normalTrans);
822 823 824 825

      // translate Source to Input point
      double x[3];
      dataset->GetPoint(inPtId, x);
826 827 828
      trans[3] = x[0];
      trans[7] = x[1];
      trans[11] = x[2];
829 830

      if (orientArray)
831
      {
832
        double orientation[4];
833
        orientArray->GetTuple(inPtId, orientation);
834 835 836 837

        double rotMatrix[3][3];
        vtkQuaterniond quaternion;

838
        switch (this->OrientationMode)
839
        {
840
        case ROTATION:
841 842 843 844 845 846 847 848 849 850 851 852
          {
            double angle = vtkMath::RadiansFromDegrees(orientation[2]);
            vtkQuaterniond qz(cos(0.5*angle), 0.0, 0.0, sin(0.5*angle));

            angle = vtkMath::RadiansFromDegrees(orientation[0]);
            vtkQuaterniond qx(cos(0.5*angle), sin(0.5*angle), 0.0, 0.0);

            angle = vtkMath::RadiansFromDegrees(orientation[1]);
            vtkQuaterniond qy(cos(0.5*angle), 0.0, sin(0.5*angle), 0.0);

            quaternion = qz*qx*qy;
          }
853 854 855 856
          break;

        case DIRECTION:
          if (orientation[1] == 0.0 && orientation[2] == 0.0)
857
          {
858
            if (orientation[0] < 0) //just flip x if we need to
859
            {
860
              quaternion.Set(0.0, 0.0, 1.0, 0.0);
861
            }
862
          }
863
          else
864
          {
865 866 867 868 869
            double vMag = vtkMath::Norm(orientation);
            double vNew[3];
            vNew[0] = (orientation[0] + vMag) / 2.0;
            vNew[1] = orientation[1] / 2.0;
            vNew[2] = orientation[2] / 2.0;
870 871 872 873 874 875 876

            double f = 1.0/sqrt(vNew[0]*vNew[0]+vNew[1]*vNew[1]+vNew[2]*vNew[2]);
            vNew[0] *= f;
            vNew[1] *= f;
            vNew[2] *= f;

            quaternion.Set(0.0, vNew[0], vNew[1], vNew[2]);
877
          }
878
          break;
879 880

        case QUATERNION:
881
          quaternion.Set(orientation);
882
          break;
883
        }
884 885 886 887 888 889 890 891 892 893 894

        quaternion.ToMatrix3x3(rotMatrix);

        for (int i = 0; i < 3; i++)
        {
          for (int j = 0; j < 3; j++)
          {
            trans[4*i+j] = rotMatrix[i][j];
            normalTrans[3*i+j] = rotMatrix[j][i]; // transpose
          }
        }
895
      }
896

897 898 899 900
      // Set pickid
      // Use selectionArray value or glyph point ID.
      vtkIdType selectionId = inPtId;
      if (this->UseSelectionIds)
901
      {
902
        if (selectionArray == nullptr ||
903
            selectionArray->GetNumberOfTuples() == 0)
904
        {
905 906
          vtkWarningMacro(<<"UseSelectionIds is true, but selection array"
                          " is invalid. Ignoring selection array.");
907
        }
908
        else
909
        {
910 911
          selectionId = static_cast<vtkIdType>(
              *selectionArray->GetTuple(inPtId));
912
        }
913
      }
914 915 916
      entry->PickIds[entry->NumberOfPoints] = selectionId;

      if (colors)
917
      {
918
        colors->GetTypedTuple(inPtId, &(entry->Colors[entry->NumberOfPoints*4]));
919
      }
920 921 922

      // scale data if appropriate
      if (this->Scaling)
923
      {
924
        if (scalex == 0.0)
925
        {
926
          scalex = 1.0e-10;
927
        }
928
        if (scaley == 0.0)
929
        {
930
          scaley = 1.0e-10;
931
        }
932
        if (scalez == 0.0)
933
        {
934
          scalez = 1.0e-10;
935
        }
936 937 938 939 940 941 942 943 944 945 946

        for (int i = 0; i < 3; i++)
        {
          // inverse of normal matrix is directly computed with inverse scale
          trans[4*i] *= scalex;
          normalTrans[i] /= scalex;
          trans[4*i+1] *= scaley;
          normalTrans[i+3] /= scaley;
          trans[4*i+2] *= scalez;
          normalTrans[i+6] /= scalez;
        }
947
      }
948

949 950 951
      float* matrices = &entry->Matrices[entry->NumberOfPoints*16];
      float* normalMatrices = &entry->NormalMatrices[entry->NumberOfPoints*9];

952
      for (int i = 0; i < 4; i++)
953
      {
954
        for (int j = 0; j < 4; j++)
955
        {
956
          matrices[i*4+j] = trans[j*4+i];
957
        }
958
      }
959

960
      for (int i = 0; i < 3; i++)
961
      {
962
        for (int j = 0; j < 3; j++)
963
        {
964
          normalMatrices[i*3+j] = normalTrans[i*3+j];
965 966
        }
      }
967
      entry->NumberOfPoints++;
968
    }
969
  }
970

Ken Martin's avatar
Ken Martin committed
971
  subarray->BuildTime.Modified();
972 973
}

Ken Martin's avatar
Ken Martin committed
974

975 976 977
// ---------------------------------------------------------------------------
// Description:
// Release any graphics resources that are being consumed by this mapper.
978
void vtkOpenGLGlyph3DMapper::ReleaseGraphicsResources(vtkWindow *window)
979
{
Ken Martin's avatar
Ken Martin committed
980
  if (this->GlyphValues)
981
  {
Ken Martin's avatar
Ken Martin committed
982
    std::map<const vtkDataSet *, vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperSubArray *>::iterator miter = this->GlyphValues->Entries.begin();
983
    for (;miter != this->GlyphValues->Entries.end(); ++miter)
984
    {
985
      std::vector<vtkOpenGLGlyph3DMapper::vtkOpenGLGlyph3DMapperEntry *>::iterator miter2 = miter->second->Entries.begin();
986
      for (;miter2 != miter->second->Entries.end(); ++miter2)
987
      {
988 989
        vtkOpenGLGlyph3DMapperEntry::MapperMap::iterator miter3 = (*miter2)->Mappers.begin();
        for (; miter3 != (*miter2)->Mappers.end(); ++miter3)
990 991 992
        {
          miter3->second->ReleaseGraphicsResources(window);
        }
993 994
      }
    }
995
  }
996 997
}

998 999 1000
//---------------------------------------------------------------------------
vtkIdType vtkOpenGLGlyph3DMapper::GetMaxNumberOfLOD()
{
1001
#ifndef GL_ES_VERSION_3_0
1002
  if (!GLEW_ARB_gpu_shader5 || !GLEW_ARB_transform_feedback3)
1003 1004 1005 1006
  {
    return 0;
  }

1007
  GLint streams, maxsize;
1008
  glGetIntegerv(GL_MAX_VERTEX_STREAMS, &streams);
1009 1010 1011 1012 1013
  glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &maxsize);
  maxsize /= 32; // each stream size can be 29 bytes (16 for transform matrix, 9 for normal, 4 for color)

  vtkIdType maxstreams = static_cast<vtkIdType>(std::min(streams, maxsize));
  return maxstreams - 1;
1014 1015 1016
#else
  return 0;
#endif
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
}

//---------------------------------------------------------------------------
void vtkOpenGLGlyph3DMapper::SetNumberOfLOD(vtkIdType nb)
{
  this->LODs.resize(nb, {0.f, 0.f});
}

//---------------------------------------------------------------------------
void vtkOpenGLGlyph3DMapper::SetLODDistanceAndTargetReduction(vtkIdType index, float distance, float targetReduction)
{
  if (index < static_cast<vtkIdType>(this->LODs.size()))
  {
    this->LODs[index] = {vtkMath::Max(0.f, distance), vtkMath::ClampValue(targetReduction, 0.f, 1.f)};
  }
}

1034
// ----------------------------------------------------------------------------
1035
void vtkOpenGLGlyph3DMapper::PrintSelf(ostream& os, vtkIndent indent)
1036 1037 1038
{
  this->Superclass::PrintSelf(os, indent);
}