VTK  9.2.6
vtkOpenGLContextDevice2DPrivate.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkOpenGLContextDevice2DPrivate.h
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 
33 #ifndef vtkOpenGLContextDevice2DPrivate_h
34 #define vtkOpenGLContextDevice2DPrivate_h
35 
37 
38 #include "vtkAbstractMapper.h"
39 #include "vtkCellIterator.h"
40 #include "vtkColor.h"
41 #include "vtkFreeTypeTools.h"
42 #include "vtkGenericCell.h"
43 #include "vtkStdString.h"
44 #include "vtkTextProperty.h"
45 #include "vtkTextRenderer.h"
46 #include "vtkTexture.h"
47 #include "vtkUnsignedCharArray.h"
48 
49 #include <algorithm>
50 #include <list>
51 #include <utility>
52 
53 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by
54 // a unique key.
55 // .SECTION Description
56 // Creating and initializing a texture can be time consuming,
57 // vtkTextureImageCache offers the ability to reuse them as much as possible.
58 template <class Key>
60 {
61 public:
62  struct CacheData
63  {
66  // Use to generate texture coordinates. Computing this is as expensive as
67  // rendering the texture, so we cache it.
69  };
70 
72 
75  struct CacheElement : public std::pair<Key, CacheData>
76  {
77  // Default constructor
79  : std::pair<Key, CacheData>(Key(), CacheData())
80  {
81  }
82  // Construct a partial CacheElement with no CacheData
83  // This can be used for temporary CacheElement used to search a given
84  // key into the cache list.
85  CacheElement(const Key& key)
86  : std::pair<Key, CacheData>(key, CacheData())
87  {
88  }
89  // Standard constructor of CacheElement
90  CacheElement(const Key& key, const CacheData& cacheData)
91  : std::pair<Key, CacheData>(key, cacheData)
92  {
93  }
94  // Operator tuned to be used when searching into the cache list using
95  // std::find()
96  bool operator==(const CacheElement& other) const
97  {
98  // Here we cheat and make the comparison only on the key, this allows
99  // us to use std::find() to search for a given key.
100  return this->first == other.first;
101  }
102  };
104 
108  vtkTextureImageCache() { this->MaxSize = 50; }
109 
114  bool IsKeyInCache(const Key& key) const
115  {
116  return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
117  }
118 
125  CacheData& GetCacheData(const Key& key);
126 
128 
133  {
134  typename std::list<CacheElement>::iterator it;
135  for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
136  {
137  it->second.Texture->ReleaseGraphicsResources(window);
138  }
139  }
141 
142 protected:
144 
148  CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
149  {
150  assert(!this->IsKeyInCache(key));
151  if (this->Cache.size() >= this->MaxSize)
152  {
153  this->Cache.pop_back();
154  }
155  this->Cache.push_front(CacheElement(key, cacheData));
156  return this->Cache.begin()->second;
157  }
159 
163  std::list<CacheElement> Cache;
165 
168  size_t MaxSize;
170 };
171 
172 template <class Key>
174  const Key& key)
175 {
176  typename std::list<CacheElement>::iterator it =
177  std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
178  if (it != this->Cache.end())
179  {
180  return it->second;
181  }
182  CacheData cacheData;
185  cacheData.Texture->SetInputData(cacheData.ImageData);
186  return this->AddCacheData(key, cacheData);
187 }
188 
189 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text
190 // .SECTION Description
191 // Uniquely describe a pair of vtkTextProperty and text.
192 template <class StringType>
194 {
196 
199  static vtkTypeUInt32 GetIdFromTextProperty(vtkTextProperty* tprop)
200  {
201  size_t id;
202 
204  ftt->MapTextPropertyToId(tprop, &id);
205 
206  // The hash is really a uint32 that gets cast to a size_t in
207  // MapTextPropertyToId, so this possible truncation is safe.
208  // Yay legacy APIs.
209  vtkTypeUInt32 hash = static_cast<vtkTypeUInt32>(id);
210 
211  // Ensure that the above implementation assumption still holds. If it
212  // doesn't we'll need to rework this cache class a bit.
213  assert("Hash is really a uint32" && static_cast<size_t>(hash) == id);
214 
215  // Since we cache the text metrics (which includes orientation and alignment
216  // info), we'll need to store additional options, since MapTextPropertyToId
217  // intentionally ignores them.
218  // These include cell spacing and interior lines for multi cell text, as well
219  // as text justification.
220  int tmp = tprop->GetJustification();
221  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
222  tmp = tprop->GetVerticalJustification();
223  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
224  tmp = tprop->GetCellOffset();
225  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
226  tmp = tprop->GetInteriorLinesVisibility();
227  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
228  tmp = tprop->GetInteriorLinesWidth();
229  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
230  hash = vtkFreeTypeTools::HashBuffer(tprop->GetInteriorLinesColor(), 3 * sizeof(double), hash);
231 
232  return hash;
233  }
235 
237 
240  TextPropertyKey(vtkTextProperty* textProperty, const StringType& text, int dpi)
241  {
242  this->TextPropertyId = GetIdFromTextProperty(textProperty);
243  this->FontSize = textProperty->GetFontSize();
244  double color[3];
245  textProperty->GetColor(color);
246  this->Color.Set(static_cast<unsigned char>(color[0] * 255),
247  static_cast<unsigned char>(color[1] * 255), static_cast<unsigned char>(color[2] * 255),
248  static_cast<unsigned char>(textProperty->GetOpacity() * 255));
249  this->Text = text;
250  this->DPI = dpi;
251  }
253 
258  bool operator==(const TextPropertyKey& other) const
259  {
260  return this->TextPropertyId == other.TextPropertyId && this->FontSize == other.FontSize &&
261  this->Text == other.Text && this->Color[0] == other.Color[0] &&
262  this->Color[1] == other.Color[1] && this->Color[2] == other.Color[2] &&
263  this->Color[3] == other.Color[3] && this->DPI == other.DPI;
264  }
265 
266  unsigned short FontSize;
268  // States in the function not to use more than 32 bits - int works fine here.
269  vtkTypeUInt32 TextPropertyId;
270  StringType Text;
271  int DPI;
272 };
273 
275 
277 {
278 public:
280  {
281  this->Texture = nullptr;
283  this->SpriteTexture = nullptr;
284  this->SavedDepthTest = GL_TRUE;
285  this->SavedStencilTest = GL_TRUE;
286  this->SavedBlend = GL_TRUE;
287  this->SavedDrawBuffer = 0;
288  this->SavedClearColor[0] = this->SavedClearColor[1] = this->SavedClearColor[2] =
289  this->SavedClearColor[3] = 0.0f;
290  this->TextCounter = 0;
291  this->GLExtensionsLoaded = true;
292  this->GLSL = true;
293  this->PowerOfTwoTextures = false;
294  }
295 
297  {
298  if (this->Texture)
299  {
300  this->Texture->Delete();
301  this->Texture = nullptr;
302  }
303  if (this->SpriteTexture)
304  {
305  this->SpriteTexture->Delete();
306  this->SpriteTexture = nullptr;
307  }
308  }
309 
310  void SaveGLState(vtkOpenGLState* ostate, bool colorBuffer = false)
311  {
312  this->SavedDepthTest = ostate->GetEnumState(GL_DEPTH_TEST);
313 
314  if (colorBuffer)
315  {
316  this->SavedStencilTest = ostate->GetEnumState(GL_STENCIL_TEST);
317  this->SavedBlend = ostate->GetEnumState(GL_BLEND);
318  ostate->vtkglGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
319  ostate->vtkglGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
320  }
321  }
322 
323  void RestoreGLState(vtkOpenGLState* ostate, bool colorBuffer = false)
324  {
325  ostate->SetEnumState(GL_DEPTH_TEST, this->SavedDepthTest);
326 
327  if (colorBuffer)
328  {
329  ostate->SetEnumState(GL_STENCIL_TEST, this->SavedStencilTest);
330  ostate->SetEnumState(GL_BLEND, this->SavedBlend);
331 
332  if (this->SavedDrawBuffer != GL_BACK_LEFT)
333  {
334  const GLenum bufs[1] = { static_cast<GLenum>(this->SavedDrawBuffer) };
335  ::glDrawBuffers(1, bufs);
336  }
337 
338  ostate->vtkglClearColor(this->SavedClearColor[0], this->SavedClearColor[1],
339  this->SavedClearColor[2], this->SavedClearColor[3]);
340  }
341  }
342 
343  float* TexCoords(float* f, int n)
344  {
345  float* texCoord = new float[2 * n];
346  float minX = f[0];
347  float minY = f[1];
348  float maxX = f[0];
349  float maxY = f[1];
350  float* fptr = f;
351  for (int i = 0; i < n; ++i)
352  {
353  minX = fptr[0] < minX ? fptr[0] : minX;
354  maxX = fptr[0] > maxX ? fptr[0] : maxX;
355  minY = fptr[1] < minY ? fptr[1] : minY;
356  maxY = fptr[1] > maxY ? fptr[1] : maxY;
357  fptr += 2;
358  }
359  fptr = f;
361  {
362  const double* textureBounds = this->Texture->GetInput()->GetBounds();
363  float rangeX =
364  (textureBounds[1] - textureBounds[0]) ? textureBounds[1] - textureBounds[0] : 1.;
365  float rangeY =
366  (textureBounds[3] - textureBounds[2]) ? textureBounds[3] - textureBounds[2] : 1.;
367  for (int i = 0; i < n; ++i)
368  {
369  texCoord[i * 2] = (fptr[0] - minX) / rangeX;
370  texCoord[i * 2 + 1] = (fptr[1] - minY) / rangeY;
371  fptr += 2;
372  }
373  }
374  else // this->TextureProperties & vtkContextDevice2D::Stretch
375  {
376  float rangeX = (maxX - minX) ? maxX - minX : 1.f;
377  float rangeY = (maxY - minY) ? maxY - minY : 1.f;
378  for (int i = 0; i < n; ++i)
379  {
380  texCoord[i * 2] = (fptr[0] - minX) / rangeX;
381  texCoord[i * 2 + 1] = (fptr[1] - minY) / rangeY;
382  fptr += 2;
383  }
384  }
385  return texCoord;
386  }
387 
389  {
390  vtkVector2i pow2(1, 1);
391  for (int i = 0; i < 2; ++i)
392  {
393  while (pow2[i] < size[i])
394  {
395  pow2[i] *= 2;
396  }
397  }
398  return pow2;
399  }
400 
402  {
403  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
404  {
405  vtkGenericWarningMacro("Invalid image format: expected unsigned char.");
406  return 0;
407  }
408  int bytesPerPixel = image->GetNumberOfScalarComponents();
409  int size[3];
410  image->GetDimensions(size);
411  vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
412 
413  for (int i = 0; i < 2; ++i)
414  {
415  texCoords[i] = size[i] / float(newImg[i]);
416  }
417 
418  unsigned char* dataPtr = new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
419  unsigned char* origPtr = static_cast<unsigned char*>(image->GetScalarPointer());
420 
421  for (int i = 0; i < newImg[0]; ++i)
422  {
423  for (int j = 0; j < newImg[1]; ++j)
424  {
425  for (int k = 0; k < bytesPerPixel; ++k)
426  {
427  if (i < size[0] && j < size[1])
428  {
429  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
430  origPtr[i * bytesPerPixel + j * size[0] * bytesPerPixel + k];
431  }
432  else
433  {
434  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] = k == 3 ? 0 : 255;
435  }
436  }
437  }
438  }
439 
440  GLuint tmpIndex(0);
441  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
442  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
443 
444  glGenTextures(1, &tmpIndex);
445  glBindTexture(GL_TEXTURE_2D, tmpIndex);
446 
447  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
448  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
449  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
450  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
451 
452  glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, newImg[0], newImg[1], 0, glFormat,
453  GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(dataPtr));
454  delete[] dataPtr;
455  return tmpIndex;
456  }
457 
459  {
460  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
461  {
462  cout << "Error = not an unsigned char..." << endl;
463  return 0;
464  }
465  int bytesPerPixel = image->GetNumberOfScalarComponents();
466  int size[3];
467  image->GetDimensions(size);
468 
469  unsigned char* dataPtr = static_cast<unsigned char*>(image->GetScalarPointer());
470  GLuint tmpIndex(0);
471  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
472  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
473 
474  glGenTextures(1, &tmpIndex);
475  glBindTexture(GL_TEXTURE_2D, tmpIndex);
476 
477  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
478  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
479  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
480  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
481 
482  glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, size[0], size[1], 0, glFormat,
483  GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(dataPtr));
484  return tmpIndex;
485  }
486 
488  unsigned int TextureProperties;
490  // Store the previous GL state so that we can restore it when complete
495  GLfloat SavedClearColor[4];
496 
501  bool GLSL;
503 
505 
511 };
512 
514 
534 {
535 
536 public:
537  enum CellType
538  {
539  LINE = 1,
540  POLYGON
541  // TRIANGLE_STRIPS
542  };
543 
545  : Device(device)
546  , Points(nullptr)
547  , PointIds(nullptr)
548  , Colors(nullptr)
549  , NumPointsCell(0)
550  {
551  this->cache = new PolyDataCache();
552  };
553 
554  ~CellArrayHelper() { delete this->cache; }
555 
559  void Draw(int cellType, vtkPolyData* polyData, vtkPoints* points, float x, float y, float scale,
560  int scalarMode, vtkUnsignedCharArray* colors = nullptr)
561  {
562  this->Points = points;
563  this->Colors = colors;
564  this->CellColors->SetNumberOfComponents(colors->GetNumberOfComponents());
565 
566  switch (cellType)
567  {
568  case LINE:
569  this->DrawLines(polyData, scalarMode, x, y, scale);
570  break;
571 
572  case POLYGON:
573  this->DrawPolygons(polyData, scalarMode, x, y, scale);
574  break;
575  }
576  };
577 
578  void HandleEndFrame() { this->cache->SwapCaches(); }
579 
580 private:
581  CellArrayHelper(const CellArrayHelper&) = delete;
582  void operator=(const CellArrayHelper&) = delete;
583 
584  struct PolyDataCacheItem
585  {
586  // Each polydata may have lines as well as polys which must be cached
587  // separately
588  std::vector<float> PolyTri;
590  vtkTimeStamp PolygonsLoadingTime;
591 
592  std::vector<float> Lines;
594  vtkTimeStamp LinesLoadingTime;
595  };
596 
597  struct PolyDataCache
598  {
599  ~PolyDataCache()
600  {
601  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator itPrev = this->PrevFrameCache.begin();
602  for (; itPrev != this->PrevFrameCache.end(); ++itPrev)
603  {
604  delete itPrev->second;
605  }
606 
607  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator it = this->CurrentFrameCache.begin();
608  for (; it != this->CurrentFrameCache.end(); ++it)
609  {
610  delete it->second;
611  }
612  }
613 
614  PolyDataCacheItem* GetCacheEntry(vtkPolyData* key)
615  {
616  PolyDataCacheItem* cacheItem = this->CurrentFrameCache[key];
617  if (cacheItem == nullptr)
618  {
619  cacheItem = this->PrevFrameCache[key];
620  if (cacheItem == nullptr)
621  {
622  cacheItem = new PolyDataCacheItem();
623  cacheItem->PolyColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
624  cacheItem->LineColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
625  }
626  else
627  {
628  // Move the item to the current frame, since we were asked for it
629  this->PrevFrameCache.erase(key);
630  }
631 
632  // Add the cache item to the current frame's cache
633  this->CurrentFrameCache[key] = cacheItem;
634  }
635 
636  return cacheItem;
637  }
638 
639  void SwapCaches()
640  {
641  // Delete any objects stored in the previous frame's cache, as
642  // if they had been used in this frame, we would have moved them
643  // into the current frame cache already.
644  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator itPrev = this->PrevFrameCache.begin();
645  for (; itPrev != this->PrevFrameCache.end(); ++itPrev)
646  {
647  delete itPrev->second;
648  }
649 
650  // Clear the entries in the previous frame's cache
651  this->PrevFrameCache.clear();
652 
653  // Now swap the caches
654  std::swap(this->PrevFrameCache, this->CurrentFrameCache);
655  }
656 
657  // Last two frames worth of cached polygon/line primitives for each drawn
658  // polydata.
659  std::map<vtkPolyData*, PolyDataCacheItem*> PrevFrameCache;
660  std::map<vtkPolyData*, PolyDataCacheItem*> CurrentFrameCache;
661  };
662 
666  void MapCurrentCell(
667  float const posX, float const posY, float const scale, vtkIdType cellId, int scalarMode)
668  {
669  this->CellPoints.reserve(this->NumPointsCell * 2); /* 2 components */
670  this->CellColors->SetNumberOfTuples(this->NumPointsCell); /* RGBA */
671  for (int i = 0; i < this->NumPointsCell; i++)
672  {
673  double point[3];
674  this->Points->GetPoint(this->PointIds[i], point);
675 
676  // Only 2D meshes are supported
677  float const x = static_cast<float>(point[0]) + posX;
678  float const y = static_cast<float>(point[1]) + posY;
679  this->CellPoints.push_back(x * scale);
680  this->CellPoints.push_back(y * scale);
681 
682  // Grab specific point / cell colors
684  switch (scalarMode)
685  {
687  mappedColorId = this->PointIds[i];
688  break;
690  mappedColorId = cellId;
691  break;
692  default:
693  std::cerr << "Scalar mode not supported!" << std::endl;
694  break;
695  }
696 
697  this->CellColors->SetTuple(i, mappedColorId, this->Colors);
698  }
699  };
700 
706  void DrawLines(
707  vtkPolyData* polyData, int scalarMode, float const x, float const y, float const scale)
708  {
709  PolyDataCacheItem* cacheItem = this->cache->GetCacheEntry(polyData);
710 
711  if (polyData->GetMTime() > cacheItem->LinesLoadingTime)
712  {
713  vtkNew<vtkGenericCell> genericCell;
714  cacheItem->Lines.clear();
715  cacheItem->LineColors->Reset();
716 
717  // Pre-allocate batched array
718  vtkIdType const numVertices = polyData->GetNumberOfCells() * 2; // points/line
719  cacheItem->Lines.reserve(numVertices * 2); // components
720  cacheItem->LineColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
721  cacheItem->LineColors->SetNumberOfTuples(numVertices);
722 
723  vtkIdType cellId = 0;
724  vtkIdType vertOffset = 0;
725  vtkCellIterator* cellIter = nullptr;
726 
727  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
728  cellIter->GoToNextCell(), cellId++)
729  {
730  polyData->GetCell(cellIter->GetCellId(), genericCell);
731  if (genericCell->GetCellType() == VTK_LINE || genericCell->GetCellType() == VTK_POLY_LINE)
732  {
733  vtkIdType actualNumPointsCell = genericCell->GetNumberOfPoints();
734 
735  for (int i = 0; i < actualNumPointsCell - 1; ++i)
736  {
737  this->NumPointsCell = 2;
738  this->PointIds = genericCell->GetPointIds()->GetPointer(i);
739 
740  this->MapCurrentCell(x, y, scale, cellId, scalarMode);
741 
742  // Accumulate the current cell in the batched array
743  for (int j = 0; j < this->NumPointsCell; j++)
744  {
745  cacheItem->Lines.push_back(this->CellPoints[2 * j]);
746  cacheItem->Lines.push_back(this->CellPoints[2 * j + 1]);
747 
748  double* color4 = this->CellColors->GetTuple(j);
749  cacheItem->LineColors->InsertTuple4(
750  vertOffset + j, color4[0], color4[1], color4[2], color4[3]);
751  }
752 
753  vertOffset += this->NumPointsCell;
754  this->CellColors->Reset();
755  this->CellPoints.clear();
756  }
757  }
758  }
759 
760  cacheItem->LinesLoadingTime.Modified();
761  cellIter->Delete();
762  }
763 
764  if (!cacheItem->Lines.empty())
765  {
766  this->Device->DrawLines(&cacheItem->Lines[0], static_cast<int>(cacheItem->Lines.size() / 2),
767  static_cast<unsigned char*>(cacheItem->LineColors->GetVoidPointer(0)),
768  cacheItem->LineColors->GetNumberOfComponents());
769  }
770  };
771 
776  vtkIdType GetCountTriangleVertices(vtkPolyData* polyData)
777  {
778  vtkIdType cellId = 0;
779  vtkIdType numTriVert = 0;
780  vtkNew<vtkGenericCell> genericCell;
781  vtkCellIterator* cellIter = nullptr;
782 
783  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
784  cellIter->GoToNextCell(), cellId++)
785  {
786  polyData->GetCell(cellIter->GetCellId(), genericCell);
787  this->NumPointsCell = genericCell->GetNumberOfPoints();
788  this->PointIds = genericCell->GetPointIds()->GetPointer(0);
789  numTriVert += 3 * (this->NumPointsCell - 2);
790  }
791 
792  cellIter->Delete();
793  return numTriVert;
794  };
795 
801  void DrawPolygons(
802  vtkPolyData* polyData, int scalarMode, float const x, float const y, float const scale)
803  {
804  PolyDataCacheItem* cacheItem = this->cache->GetCacheEntry(polyData);
805 
806  if (polyData->GetMTime() > cacheItem->PolygonsLoadingTime)
807  {
808  cacheItem->PolyTri.clear();
809  cacheItem->PolyColors->Reset();
810 
811  // Pre-allocate batched array
812  vtkIdType const totalTriVert = this->GetCountTriangleVertices(polyData);
813  cacheItem->PolyTri.reserve(totalTriVert * 2); // components
814  cacheItem->PolyColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
815  cacheItem->PolyColors->SetNumberOfTuples(totalTriVert);
816 
817  // Traverse polygons and convert to triangles
818  vtkIdType cellId = 0;
819  vtkIdType vertOffset = 0;
820  cacheItem->PolyColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
821 
822  vtkNew<vtkGenericCell> genericCell;
823  vtkCellIterator* cellIter = nullptr;
824 
825  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
826  cellIter->GoToNextCell(), cellId++)
827  {
828  polyData->GetCell(cellIter->GetCellId(), genericCell);
829  if (genericCell->GetCellType() == VTK_TRIANGLE || genericCell->GetCellType() == VTK_QUAD ||
830  genericCell->GetCellType() == VTK_POLYGON)
831  {
832  this->NumPointsCell = genericCell->GetNumberOfPoints();
833  this->PointIds = genericCell->GetPointIds()->GetPointer(0);
834 
835  this->MapCurrentCell(x, y, scale, cellId, scalarMode);
836 
837  // Convert current cell (polygon) to triangles
838  for (int i = 0; i < this->NumPointsCell - 2; i++)
839  {
840  cacheItem->PolyTri.push_back(this->CellPoints[0]);
841  cacheItem->PolyTri.push_back(this->CellPoints[1]);
842  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 2]);
843  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 3]);
844  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 4]);
845  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 5]);
846 
847  // Insert triangle vertex color
848  vtkIdType const triangOffset = vertOffset + 3 * i;
849  double* color4 = this->CellColors->GetTuple(0);
850  cacheItem->PolyColors->InsertTuple4(
851  triangOffset, color4[0], color4[1], color4[2], color4[3]);
852 
853  color4 = this->CellColors->GetTuple(i + 1);
854  cacheItem->PolyColors->InsertTuple4(
855  triangOffset + 1, color4[0], color4[1], color4[2], color4[3]);
856 
857  color4 = this->CellColors->GetTuple(i + 2);
858  cacheItem->PolyColors->InsertTuple4(
859  triangOffset + 2, color4[0], color4[1], color4[2], color4[3]);
860  }
861 
862  vertOffset += 3 * (this->NumPointsCell - 2); // Triangle verts current cell
863  this->CellColors->Reset();
864  this->CellPoints.clear();
865  }
866  }
867 
868  cacheItem->PolygonsLoadingTime.Modified();
869  cellIter->Delete();
870  }
871 
872  if (!cacheItem->PolyTri.empty())
873  {
874  this->Device->CoreDrawTriangles(cacheItem->PolyTri,
875  static_cast<unsigned char*>(cacheItem->PolyColors->GetVoidPointer(0)), 4);
876  }
877  };
878 
879  vtkOpenGLContextDevice2D* Device;
880 
881  vtkPoints* Points;
882  vtkIdType* PointIds;
883  vtkUnsignedCharArray* Colors;
884 
886 
889  vtkIdType NumPointsCell;
890  std::vector<float> CellPoints;
891  vtkNew<vtkUnsignedCharArray> CellColors;
893 
894  PolyDataCache* cache;
895 };
896 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
897 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h
virtual double * GetInteriorLinesColor()
Set the color of the interior lines between cells.
bool operator==(const CacheElement &other) const
static vtkTypeUInt32 HashBuffer(const void *buffer, size_t n, vtkTypeUInt32 hash=0)
Hash a buffer of a given length.
void DrawLines(float *f, int n, unsigned char *colors=nullptr, int nc_comps=0) override
Draw lines using the points - memory layout is as follows: l1p1,l1p2,l2p1,l2p2... ...
std::list< CacheElement > Cache
List of a pair of key and cache data.
virtual int GetJustification()
Set/Get the horizontal justification to left (default), centered, or right.
vtkIdType GetNumberOfPoints() const
Return the number of points in the cell.
Definition: vtkCell.h:141
double * GetBounds()
Return a pointer to the geometry bounding box in the form (xmin,xmax, ymin,ymax, zmin,zmax).
void SetEnumState(unsigned int name, bool value)
record modification and/or execution time
Definition: vtkTimeStamp.h:35
Class for drawing 2D primitives using OpenGL 1.1+.
void Draw(int cellType, vtkPolyData *polyData, vtkPoints *points, float x, float y, float scale, int scalarMode, vtkUnsignedCharArray *colors=nullptr)
Draw primitives as specified by cellType.
void vtkglGetIntegerv(unsigned int pname, int *params)
static int GetNumberOfScalarComponents(vtkInformation *meta_data)
Set/Get the number of scalar components for points.
GLuint TextureFromImage(vtkImageData *image, vtkVector2f &texCoords)
bool IsKeyInCache(const Key &key) const
Search the cache list to see if a given key already exists.
#define GL_UNSIGNED_BYTE
void SaveGLState(vtkOpenGLState *ostate, bool colorBuffer=false)
int vtkIdType
Definition: vtkType.h:332
TextPropertyKey(vtkTextProperty *textProperty, const StringType &text, int dpi)
Creates a TextPropertyKey.
concrete dataset represents vertices, lines, polygons, and triangle strips
Definition: vtkPolyData.h:90
bool GetEnumState(unsigned int name)
static vtkSmartPointer< T > New()
Create an instance of a VTK object.
CacheElement(const Key &key, const CacheData &cacheData)
void SetInputData(vtkDataObject *)
Assign a data object as input.
void ReleaseGraphicsResources(vtkWindow *window)
Release all the OpenGL Pixel Buffer Object(PBO) associated with the textures of the cache list...
bool operator==(const TextPropertyKey &other) const
Compares two TextPropertyKeys with each other.
TextPropertyKey< vtkStdString > UTF8TextPropertyKey
window superclass for vtkRenderWindow
Definition: vtkWindow.h:38
size_t MaxSize
Maximum size the cache list can be.
virtual vtkIdType GetCellId()=0
Get the id of the current cell.
void vtkglGetFloatv(unsigned int pname, float *params)
void GoToNextCell()
Increment to next cell.
OpenGL state storage.
vtkCell * GetCell(vtkIdType cellId) override
Standard vtkDataSet interface.
#define VTK_SCALAR_MODE_USE_POINT_DATA
virtual int * GetDimensions()
Get dimensions of this structured points dataset.
static int GetScalarType(vtkInformation *meta_data)
topologically and geometrically regular array of data
Definition: vtkImageData.h:53
vtkImageData * GetInput()
Get the input as a vtkImageData object.
Some derived classes for the different vectors commonly used.
Definition: vtkVector.h:421
int GetCellType() override
See the vtkCell API for descriptions of these methods.
virtual int GetVerticalJustification()
Set/Get the vertical justification to bottom (default), middle, or top.
CacheData & GetCacheData(const Key &key)
Return the cache associated to a key.
void Set(const T &red, const T &green, const T &blue)
Set the red, green and blue components of the color.
Definition: vtkColor.h:129
vtkIdType GetNumberOfCells() override
Standard vtkDataSet interface.
Definition: vtkPolyData.h:764
handles properties associated with a texture map
Definition: vtkTexture.h:68
vtkTextureImageCache()
Construct a texture image cache with a maximum number of texture of 50.
virtual double GetOpacity()
Set/Get the text's opacity.
vtkMTimeType GetMTime() override
Get MTime which also considers its cell array MTime.
represent text properties.
static vtkFreeTypeTools * GetInstance()
Return the singleton instance with no reference counting.
dynamic, self-adjusting array of unsigned char
virtual bool GetInteriorLinesVisibility()
Set/Get the visibility of the interior lines between cells.
virtual double * GetColor()
Set the color of the text.
#define VTK_UNSIGNED_CHAR
Definition: vtkType.h:47
vtkCellIterator * NewCellIterator() override
Return an iterator that traverses the cells in this data set.
virtual void * GetScalarPointer(int coordinates[3])
Access the native pointer for the scalar data.
void MapTextPropertyToId(vtkTextProperty *tprop, size_t *tprop_cache_id)
Given a text property 'tprop', get its unique ID in our cache framework.
void RestoreGLState(vtkOpenGLState *ostate, bool colorBuffer=false)
void vtkglClearColor(float red, float green, float blue, float alpha)
#define GL_NEAREST
Efficient cell iterator for vtkDataSet topologies.
vtkIdList * GetPointIds()
Return the list of point ids defining the cell.
Definition: vtkCell.h:156
CacheElement associates a unique key to some cache.
vtkVector2i FindPowerOfTwo(const vtkVector2i &size)
virtual int GetFontSize()
Set/Get the font size (in points).
static vtkTypeUInt32 GetIdFromTextProperty(vtkTextProperty *tprop)
Transform a text property into an unsigned long.
#define VTK_SCALAR_MODE_USE_CELL_DATA
FreeType library support.
virtual double GetCellOffset()
Set/Get the horizontal offset between cells.
CacheData & AddCacheData(const Key &key, const CacheData &cacheData)
Add a new cache entry into the cache list.
virtual bool IsDoneWithTraversal()=0
Returns false while the iterator is valid.
vtkSmartPointer< vtkImageData > ImageData
virtual int GetInteriorLinesWidth()
Set the width (in pixels) of the interior lines between cells.
vtkTextureImageCache< UTF8TextPropertyKey > TextTextureCache
Cache for text images.
vtkIdType * GetPointer(const vtkIdType i)
Get a pointer to a particular data index.
Definition: vtkIdList.h:129
represent and manipulate 3D points
Definition: vtkPoints.h:39
#define GL_CLAMP_TO_EDGE
virtual void Delete()
Delete a VTK object.