VTK  9.7.1
vtkOpenGLContextDevice2DPrivate.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 
21 #ifndef vtkOpenGLContextDevice2DPrivate_h
22 #define vtkOpenGLContextDevice2DPrivate_h
23 
25 
26 #include "vtkAbstractMapper.h"
27 #include "vtkCellIterator.h"
28 #include "vtkColor.h"
29 #include "vtkFreeTypeTools.h"
30 #include "vtkGenericCell.h"
32 #include "vtkTextProperty.h"
33 #include "vtkTextRenderer.h"
34 #include "vtkTexture.h"
35 #include "vtkUnsignedCharArray.h"
36 
37 #include <algorithm>
38 #include <iostream>
39 #include <list>
40 #include <utility>
41 
42 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by
43 // a unique key.
44 // .SECTION Description
45 // Creating and initializing a texture can be time consuming,
46 // vtkTextureImageCache offers the ability to reuse them as much as possible.
47 VTK_ABI_NAMESPACE_BEGIN
48 template <class Key>
50 {
51 public:
52  struct CacheData
53  {
56  // Use to generate texture coordinates. Computing this is as expensive as
57  // rendering the texture, so we cache it.
59  };
60 
62 
65  struct CacheElement : public std::pair<Key, CacheData>
66  {
67  // Default constructor
69  : std::pair<Key, CacheData>(Key(), CacheData())
70  {
71  }
72  // Construct a partial CacheElement with no CacheData
73  // This can be used for temporary CacheElement used to search a given
74  // key into the cache list.
75  CacheElement(const Key& key)
76  : std::pair<Key, CacheData>(key, CacheData())
77  {
78  }
79  // Standard constructor of CacheElement
80  CacheElement(const Key& key, const CacheData& cacheData)
81  : std::pair<Key, CacheData>(key, cacheData)
82  {
83  }
84  // Operator tuned to be used when searching into the cache list using
85  // std::find()
86  bool operator==(const CacheElement& other) const
87  {
88  // Here we cheat and make the comparison only on the key, this allows
89  // us to use std::find() to search for a given key.
90  return this->first == other.first;
91  }
92  };
94 
98  vtkTextureImageCache() { this->MaxSize = 50; }
99 
104  bool IsKeyInCache(const Key& key) const
105  {
106  return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
107  }
108 
115  CacheData& GetCacheData(const Key& key);
116 
118 
123  {
124  typename std::list<CacheElement>::iterator it;
125  for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
126  {
127  it->second.Texture->ReleaseGraphicsResources(window);
128  }
129  }
131 
132 protected:
134 
138  CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
139  {
140  assert(!this->IsKeyInCache(key));
141  if (this->Cache.size() >= this->MaxSize)
142  {
143  this->Cache.pop_back();
144  }
145  this->Cache.push_front(CacheElement(key, cacheData));
146  return this->Cache.begin()->second;
147  }
149 
153  std::list<CacheElement> Cache;
155 
158  size_t MaxSize;
160 };
161 
162 template <class Key>
164  const Key& key)
165 {
166  typename std::list<CacheElement>::iterator it =
167  std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
168  if (it != this->Cache.end())
169  {
170  return it->second;
171  }
172  CacheData cacheData;
175  cacheData.Texture->SetInputData(cacheData.ImageData);
176  return this->AddCacheData(key, cacheData);
177 }
178 
179 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text
180 // .SECTION Description
181 // Uniquely describe a pair of vtkTextProperty and text.
182 template <class StringType>
184 {
186 
189  static vtkTypeUInt32 GetIdFromTextProperty(vtkTextProperty* tprop)
190  {
191  size_t id;
192 
194  ftt->MapTextPropertyToId(tprop, &id);
195 
196  // The hash is really a uint32 that gets cast to a size_t in
197  // MapTextPropertyToId, so this possible truncation is safe.
198  // Yay legacy APIs.
199  vtkTypeUInt32 hash = static_cast<vtkTypeUInt32>(id);
200 
201  // Ensure that the above implementation assumption still holds. If it
202  // doesn't we'll need to rework this cache class a bit.
203  assert("Hash is really a uint32" && static_cast<size_t>(hash) == id);
204 
205  // Since we cache the text metrics (which includes orientation and alignment
206  // info), we'll need to store additional options, since MapTextPropertyToId
207  // intentionally ignores them.
208  // These include cell spacing and interior lines for multi cell text, as well
209  // as text justification.
210  int tmp = tprop->GetJustification();
211  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
212  tmp = tprop->GetVerticalJustification();
213  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
214  tmp = tprop->GetCellOffset();
215  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
216  tmp = tprop->GetInteriorLinesVisibility();
217  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
218  tmp = tprop->GetInteriorLinesWidth();
219  hash = vtkFreeTypeTools::HashBuffer(&tmp, sizeof(int), hash);
220  hash = vtkFreeTypeTools::HashBuffer(tprop->GetInteriorLinesColor(), 3 * sizeof(double), hash);
221 
222  return hash;
223  }
225 
227 
230  TextPropertyKey(vtkTextProperty* textProperty, const StringType& text, int dpi)
231  {
232  this->TextPropertyId = GetIdFromTextProperty(textProperty);
233  this->FontSize = textProperty->GetFontSize();
234  double color[3];
235  textProperty->GetColor(color);
236  this->Color.Set(static_cast<unsigned char>(color[0] * 255),
237  static_cast<unsigned char>(color[1] * 255), static_cast<unsigned char>(color[2] * 255),
238  static_cast<unsigned char>(textProperty->GetOpacity() * 255));
239  this->Text = text;
240  this->DPI = dpi;
241  }
243 
248  bool operator==(const TextPropertyKey& other) const
249  {
250  return this->TextPropertyId == other.TextPropertyId && this->FontSize == other.FontSize &&
251  this->Text == other.Text && this->Color[0] == other.Color[0] &&
252  this->Color[1] == other.Color[1] && this->Color[2] == other.Color[2] &&
253  this->Color[3] == other.Color[3] && this->DPI == other.DPI;
254  }
255 
256  unsigned short FontSize;
258  // States in the function not to use more than 32 bits - int works fine here.
259  vtkTypeUInt32 TextPropertyId;
260  StringType Text;
261  int DPI;
262 };
263 
265 
267 {
268 public:
270  {
271  this->Texture = nullptr;
273  this->SpriteTexture = nullptr;
274  this->SavedDepthTest = GL_TRUE;
275  this->SavedStencilTest = GL_TRUE;
276  this->SavedBlend = GL_TRUE;
277  this->SavedDrawBuffer = 0;
278  this->SavedClearColor[0] = this->SavedClearColor[1] = this->SavedClearColor[2] =
279  this->SavedClearColor[3] = 0.0f;
280  this->TextCounter = 0;
281  this->GLExtensionsLoaded = true;
282  this->GLSL = true;
283  this->PowerOfTwoTextures = false;
284  }
285 
287  {
288  if (this->Texture)
289  {
290  this->Texture->Delete();
291  this->Texture = nullptr;
292  }
293  if (this->SpriteTexture)
294  {
295  this->SpriteTexture->Delete();
296  this->SpriteTexture = nullptr;
297  }
298  }
299 
300  void SaveGLState(vtkOpenGLState* ostate, bool colorBuffer = false)
301  {
302  this->SavedDepthTest = ostate->GetEnumState(GL_DEPTH_TEST);
303 
304  if (colorBuffer)
305  {
306  this->SavedStencilTest = ostate->GetEnumState(GL_STENCIL_TEST);
307  this->SavedBlend = ostate->GetEnumState(GL_BLEND);
308  ostate->vtkglGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
309 
310 #ifdef GL_DRAW_BUFFER
311  ostate->vtkglGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
312 #else
313  this->SavedDrawBuffer = GL_BACK_LEFT;
314 #endif
315  }
316  }
317 
318  void RestoreGLState(vtkOpenGLState* ostate, bool colorBuffer = false)
319  {
320  ostate->SetEnumState(GL_DEPTH_TEST, this->SavedDepthTest);
321 
322  if (colorBuffer)
323  {
324  ostate->SetEnumState(GL_STENCIL_TEST, this->SavedStencilTest);
325  ostate->SetEnumState(GL_BLEND, this->SavedBlend);
326 
327  if (this->SavedDrawBuffer != GL_BACK_LEFT)
328  {
329  const GLenum bufs[1] = { static_cast<GLenum>(this->SavedDrawBuffer) };
330  ::glDrawBuffers(1, bufs);
331  }
332 
333  ostate->vtkglClearColor(this->SavedClearColor[0], this->SavedClearColor[1],
334  this->SavedClearColor[2], this->SavedClearColor[3]);
335  }
336  }
337 
338  float* TexCoords(float* f, int n)
339  {
340  float* texCoord = new float[2 * n];
341  float minX = f[0];
342  float minY = f[1];
343  float maxX = f[0];
344  float maxY = f[1];
345  float* fptr = f;
346  for (int i = 0; i < n; ++i)
347  {
348  minX = fptr[0] < minX ? fptr[0] : minX;
349  maxX = fptr[0] > maxX ? fptr[0] : maxX;
350  minY = fptr[1] < minY ? fptr[1] : minY;
351  maxY = fptr[1] > maxY ? fptr[1] : maxY;
352  fptr += 2;
353  }
354  fptr = f;
356  {
357  const double* textureBounds = this->Texture->GetInput()->GetBounds();
358  float rangeX =
359  (textureBounds[1] - textureBounds[0]) ? textureBounds[1] - textureBounds[0] : 1.;
360  float rangeY =
361  (textureBounds[3] - textureBounds[2]) ? textureBounds[3] - textureBounds[2] : 1.;
362  for (int i = 0; i < n; ++i)
363  {
364  texCoord[i * 2] = (fptr[0] - minX) / rangeX;
365  texCoord[i * 2 + 1] = (fptr[1] - minY) / rangeY;
366  fptr += 2;
367  }
368  }
369  else // this->TextureProperties & vtkContextDevice2D::Stretch
370  {
371  float rangeX = (maxX - minX) ? maxX - minX : 1.f;
372  float rangeY = (maxY - minY) ? maxY - minY : 1.f;
373  for (int i = 0; i < n; ++i)
374  {
375  texCoord[i * 2] = (fptr[0] - minX) / rangeX;
376  texCoord[i * 2 + 1] = (fptr[1] - minY) / rangeY;
377  fptr += 2;
378  }
379  }
380  return texCoord;
381  }
382 
384  {
385  vtkVector2i pow2(1, 1);
386  for (int i = 0; i < 2; ++i)
387  {
388  while (pow2[i] < size[i])
389  {
390  pow2[i] *= 2;
391  }
392  }
393  return pow2;
394  }
395 
397  {
398  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
399  {
400  vtkGenericWarningMacro("Invalid image format: expected unsigned char.");
401  return 0;
402  }
403  int bytesPerPixel = image->GetNumberOfScalarComponents();
404  int size[3];
405  image->GetDimensions(size);
406  vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
407 
408  for (int i = 0; i < 2; ++i)
409  {
410  texCoords[i] = size[i] / float(newImg[i]);
411  }
412 
413  unsigned char* dataPtr = new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
414  unsigned char* origPtr = static_cast<unsigned char*>(image->GetScalarPointer());
415 
416  for (int i = 0; i < newImg[0]; ++i)
417  {
418  for (int j = 0; j < newImg[1]; ++j)
419  {
420  for (int k = 0; k < bytesPerPixel; ++k)
421  {
422  if (i < size[0] && j < size[1])
423  {
424  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] =
425  origPtr[i * bytesPerPixel + j * size[0] * bytesPerPixel + k];
426  }
427  else
428  {
429  dataPtr[i * bytesPerPixel + j * newImg[0] * bytesPerPixel + k] = k == 3 ? 0 : 255;
430  }
431  }
432  }
433  }
434 
435  GLuint tmpIndex(0);
436  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
437  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
438 
439  glGenTextures(1, &tmpIndex);
440  glBindTexture(GL_TEXTURE_2D, tmpIndex);
441 
442  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
443  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
444  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
445  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
446 
447  glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, newImg[0], newImg[1], 0, glFormat,
448  GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(dataPtr));
449  delete[] dataPtr;
450  return tmpIndex;
451  }
452 
454  {
455  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
456  {
457  std::cout << "Error = not an unsigned char..." << std::endl;
458  return 0;
459  }
460  int bytesPerPixel = image->GetNumberOfScalarComponents();
461  int size[3];
462  image->GetDimensions(size);
463 
464  unsigned char* dataPtr = static_cast<unsigned char*>(image->GetScalarPointer());
465  GLuint tmpIndex(0);
466  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
467  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
468 
469  glGenTextures(1, &tmpIndex);
470  glBindTexture(GL_TEXTURE_2D, tmpIndex);
471 
472  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
473  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
474  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
475  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
476 
477  glTexImage2D(GL_TEXTURE_2D, 0, glInternalFormat, size[0], size[1], 0, glFormat,
478  GL_UNSIGNED_BYTE, static_cast<const GLvoid*>(dataPtr));
479  return tmpIndex;
480  }
481 
483  unsigned int TextureProperties;
485  // Store the previous GL state so that we can restore it when complete
490  GLfloat SavedClearColor[4];
491 
496  bool GLSL;
498 
500 
507 };
508 
510 
530 {
531 
532 public:
533  enum CellType
534  {
535  LINE = 1,
536  POLYGON
537  // TRIANGLE_STRIPS
538  };
539 
541  : Device(device)
542  , Points(nullptr)
543  , PointIds(nullptr)
544  , Colors(nullptr)
545  , NumPointsCell(0)
546  {
547  this->cache = new PolyDataCache();
548  }
549 
550  ~CellArrayHelper() { delete this->cache; }
551 
555  void Draw(int cellType, vtkPolyData* polyData, vtkPoints* points, float x, float y, float scale,
556  int scalarMode, vtkUnsignedCharArray* colors = nullptr)
557  {
558  this->Points = points;
559  this->Colors = colors;
560  this->CellColors->SetNumberOfComponents(colors->GetNumberOfComponents());
561 
562  switch (cellType)
563  {
564  case LINE:
565  this->DrawLines(polyData, scalarMode, x, y, scale);
566  break;
567 
568  case POLYGON:
569  this->DrawPolygons(polyData, scalarMode, x, y, scale);
570  break;
571  }
572  }
573 
574  void HandleEndFrame() { this->cache->SwapCaches(); }
575 
576 private:
577  CellArrayHelper(const CellArrayHelper&) = delete;
578  void operator=(const CellArrayHelper&) = delete;
579 
580  struct PolyDataCacheItem
581  {
582  // Each polydata may have lines as well as polys which must be cached
583  // separately
584  std::vector<float> PolyTri;
586  vtkTimeStamp PolygonsLoadingTime;
587 
588  std::vector<float> Lines;
590  vtkTimeStamp LinesLoadingTime;
591  };
592 
593  struct PolyDataCache
594  {
595  ~PolyDataCache()
596  {
597  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator itPrev = this->PrevFrameCache.begin();
598  for (; itPrev != this->PrevFrameCache.end(); ++itPrev)
599  {
600  delete itPrev->second;
601  }
602 
603  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator it = this->CurrentFrameCache.begin();
604  for (; it != this->CurrentFrameCache.end(); ++it)
605  {
606  delete it->second;
607  }
608  }
609 
610  PolyDataCacheItem* GetCacheEntry(vtkPolyData* key)
611  {
612  PolyDataCacheItem* cacheItem = this->CurrentFrameCache[key];
613  if (cacheItem == nullptr)
614  {
615  cacheItem = this->PrevFrameCache[key];
616  if (cacheItem == nullptr)
617  {
618  cacheItem = new PolyDataCacheItem();
619  cacheItem->PolyColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
620  cacheItem->LineColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
621  }
622  else
623  {
624  // Move the item to the current frame, since we were asked for it
625  this->PrevFrameCache.erase(key);
626  }
627 
628  // Add the cache item to the current frame's cache
629  this->CurrentFrameCache[key] = cacheItem;
630  }
631 
632  return cacheItem;
633  }
634 
635  void SwapCaches()
636  {
637  // Delete any objects stored in the previous frame's cache, as
638  // if they had been used in this frame, we would have moved them
639  // into the current frame cache already.
640  std::map<vtkPolyData*, PolyDataCacheItem*>::iterator itPrev = this->PrevFrameCache.begin();
641  for (; itPrev != this->PrevFrameCache.end(); ++itPrev)
642  {
643  delete itPrev->second;
644  }
645 
646  // Clear the entries in the previous frame's cache
647  this->PrevFrameCache.clear();
648 
649  // Now swap the caches
650  std::swap(this->PrevFrameCache, this->CurrentFrameCache);
651  }
652 
653  // Last two frames worth of cached polygon/line primitives for each drawn
654  // polydata.
655  std::map<vtkPolyData*, PolyDataCacheItem*> PrevFrameCache;
656  std::map<vtkPolyData*, PolyDataCacheItem*> CurrentFrameCache;
657  };
658 
662  void MapCurrentCell(
663  float const posX, float const posY, float const scale, vtkIdType cellId, int scalarMode)
664  {
665  this->CellPoints.reserve(this->NumPointsCell * 2); /* 2 components */
666  this->CellColors->SetNumberOfTuples(this->NumPointsCell); /* RGBA */
667  for (int i = 0; i < this->NumPointsCell; i++)
668  {
669  double point[3];
670  this->Points->GetPoint(this->PointIds[i], point);
671 
672  // Only 2D meshes are supported
673  float const x = static_cast<float>(point[0]) + posX;
674  float const y = static_cast<float>(point[1]) + posY;
675  this->CellPoints.push_back(x * scale);
676  this->CellPoints.push_back(y * scale);
677 
678  // Grab specific point / cell colors
680  switch (scalarMode)
681  {
683  mappedColorId = this->PointIds[i];
684  break;
686  mappedColorId = cellId;
687  break;
688  default:
689  std::cerr << "Scalar mode not supported!" << std::endl;
690  break;
691  }
692 
693  this->CellColors->SetTuple(i, mappedColorId, this->Colors);
694  }
695  }
696 
702  void DrawLines(
703  vtkPolyData* polyData, int scalarMode, float const x, float const y, float const scale)
704  {
705  PolyDataCacheItem* cacheItem = this->cache->GetCacheEntry(polyData);
706 
707  if (polyData->GetMTime() > cacheItem->LinesLoadingTime)
708  {
709  vtkNew<vtkGenericCell> genericCell;
710  cacheItem->Lines.clear();
711  cacheItem->LineColors->Reset();
712 
713  // Pre-allocate batched array
714  vtkIdType const numVertices = polyData->GetNumberOfCells() * 2; // points/line
715  cacheItem->Lines.reserve(numVertices * 2); // components
716  cacheItem->LineColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
717  cacheItem->LineColors->SetNumberOfTuples(numVertices);
718 
719  vtkIdType cellId = 0;
720  vtkIdType vertOffset = 0;
721  vtkCellIterator* cellIter = nullptr;
722 
723  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
724  cellIter->GoToNextCell(), cellId++)
725  {
726  polyData->GetCell(cellIter->GetCellId(), genericCell);
727  if (genericCell->GetCellType() == VTK_LINE || genericCell->GetCellType() == VTK_POLY_LINE)
728  {
729  vtkIdType actualNumPointsCell = genericCell->GetNumberOfPoints();
730 
731  for (int i = 0; i < actualNumPointsCell - 1; ++i)
732  {
733  this->NumPointsCell = 2;
734  this->PointIds = genericCell->GetPointIds()->GetPointer(i);
735 
736  this->MapCurrentCell(x, y, scale, cellId, scalarMode);
737 
738  // Accumulate the current cell in the batched array
739  for (int j = 0; j < this->NumPointsCell; j++)
740  {
741  cacheItem->Lines.push_back(this->CellPoints[2 * j]);
742  cacheItem->Lines.push_back(this->CellPoints[2 * j + 1]);
743 
744  double* color4 = this->CellColors->GetTuple(j);
745  cacheItem->LineColors->InsertTuple4(
746  vertOffset + j, color4[0], color4[1], color4[2], color4[3]);
747  }
748 
749  vertOffset += this->NumPointsCell;
750  this->CellColors->Reset();
751  this->CellPoints.clear();
752  }
753  }
754  }
755 
756  cacheItem->LinesLoadingTime.Modified();
757  cellIter->Delete();
758  }
759 
760  if (!cacheItem->Lines.empty())
761  {
762  this->Device->DrawLines(cacheItem->Lines.data(),
763  static_cast<int>(cacheItem->Lines.size() / 2), cacheItem->LineColors->GetPointer(0),
764  cacheItem->LineColors->GetNumberOfComponents());
765  }
766  }
767 
772  vtkIdType GetCountTriangleVertices(vtkPolyData* polyData)
773  {
774  vtkIdType numTriVert = 0;
775  vtkNew<vtkGenericCell> genericCell;
776  vtkCellIterator* cellIter = nullptr;
777 
778  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
779  cellIter->GoToNextCell())
780  {
781  polyData->GetCell(cellIter->GetCellId(), genericCell);
782  this->NumPointsCell = genericCell->GetNumberOfPoints();
783  this->PointIds = genericCell->GetPointIds()->GetPointer(0);
784  numTriVert += 3 * (this->NumPointsCell - 2);
785  }
786 
787  cellIter->Delete();
788  return numTriVert;
789  }
790 
796  void DrawPolygons(
797  vtkPolyData* polyData, int scalarMode, float const x, float const y, float const scale)
798  {
799  PolyDataCacheItem* cacheItem = this->cache->GetCacheEntry(polyData);
800 
801  if (polyData->GetMTime() > cacheItem->PolygonsLoadingTime)
802  {
803  cacheItem->PolyTri.clear();
804  cacheItem->PolyColors->Reset();
805 
806  // Pre-allocate batched array
807  vtkIdType const totalTriVert = this->GetCountTriangleVertices(polyData);
808  cacheItem->PolyTri.reserve(totalTriVert * 2); // components
809  cacheItem->PolyColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
810  cacheItem->PolyColors->SetNumberOfTuples(totalTriVert);
811 
812  // Traverse polygons and convert to triangles
813  vtkIdType cellId = 0;
814  vtkIdType vertOffset = 0;
815  cacheItem->PolyColors->SetNumberOfComponents(this->Colors->GetNumberOfComponents());
816 
817  vtkNew<vtkGenericCell> genericCell;
818  vtkCellIterator* cellIter = nullptr;
819 
820  for (cellIter = polyData->NewCellIterator(); !cellIter->IsDoneWithTraversal();
821  cellIter->GoToNextCell(), cellId++)
822  {
823  polyData->GetCell(cellIter->GetCellId(), genericCell);
824  if (genericCell->GetCellType() == VTK_TRIANGLE || genericCell->GetCellType() == VTK_QUAD ||
825  genericCell->GetCellType() == VTK_POLYGON)
826  {
827  this->NumPointsCell = genericCell->GetNumberOfPoints();
828  this->PointIds = genericCell->GetPointIds()->GetPointer(0);
829 
830  this->MapCurrentCell(x, y, scale, cellId, scalarMode);
831 
832  // Convert current cell (polygon) to triangles
833  for (int i = 0; i < this->NumPointsCell - 2; i++)
834  {
835  cacheItem->PolyTri.push_back(this->CellPoints[0]);
836  cacheItem->PolyTri.push_back(this->CellPoints[1]);
837  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 2]);
838  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 3]);
839  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 4]);
840  cacheItem->PolyTri.push_back(this->CellPoints[i * 2 + 5]);
841 
842  // Insert triangle vertex color
843  vtkIdType const triangOffset = vertOffset + 3 * i;
844  double* color4 = this->CellColors->GetTuple(0);
845  cacheItem->PolyColors->InsertTuple4(
846  triangOffset, color4[0], color4[1], color4[2], color4[3]);
847 
848  color4 = this->CellColors->GetTuple(i + 1);
849  cacheItem->PolyColors->InsertTuple4(
850  triangOffset + 1, color4[0], color4[1], color4[2], color4[3]);
851 
852  color4 = this->CellColors->GetTuple(i + 2);
853  cacheItem->PolyColors->InsertTuple4(
854  triangOffset + 2, color4[0], color4[1], color4[2], color4[3]);
855  }
856 
857  vertOffset += 3 * (this->NumPointsCell - 2); // Triangle verts current cell
858  this->CellColors->Reset();
859  this->CellPoints.clear();
860  }
861  }
862 
863  cacheItem->PolygonsLoadingTime.Modified();
864  cellIter->Delete();
865  }
866 
867  if (!cacheItem->PolyTri.empty())
868  {
869  this->Device->CoreDrawTriangles(cacheItem->PolyTri, cacheItem->PolyColors->GetPointer(0), 4);
870  }
871  }
872 
873  vtkOpenGLContextDevice2D* Device;
874 
875  vtkPoints* Points;
876  vtkIdType* PointIds;
877  vtkUnsignedCharArray* Colors;
878 
880 
883  vtkIdType NumPointsCell;
884  std::vector<float> CellPoints;
885  vtkNew<vtkUnsignedCharArray> CellColors;
887 
888  PolyDataCache* cache;
889 };
890 VTK_ABI_NAMESPACE_END
891 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
892 // 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:129
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)
vtkOpenGLContextDeviceBufferObjectBuilder BufferObjectBuilder
record modification and/or execution time
Definition: vtkTimeStamp.h:24
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.
Internal buffer object builder that maintains a cache of VBO groups.
void vtkglGetIntegerv(unsigned int pname, int *params)
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:363
TextPropertyKey(vtkTextProperty *textProperty, const StringType &text, int dpi)
Creates a TextPropertyKey.
concrete dataset represents vertices, lines, polygons, and triangle strips
Definition: vtkPolyData.h:71
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.
int * GetDimensions()
Get dimensions of this structured points dataset.
window superclass for vtkRenderWindow
Definition: vtkWindow.h:41
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.
static int GetScalarType(vtkInformation *meta_data)
Set/Get the scalar data type for the points.
#define VTK_SCALAR_MODE_USE_POINT_DATA
topologically and geometrically regular array of data
Definition: vtkImageData.h:45
vtkImageData * GetInput()
Get the input as a vtkImageData object.
Some derived classes for the different vectors commonly used.
Definition: vtkVector.h:410
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:118
vtkIdType GetNumberOfCells() override
Standard vtkDataSet interface.
Definition: vtkPolyData.h:744
handles properties associated with a texture map
Definition: vtkTexture.h:58
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:36
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.
static int GetNumberOfScalarComponents(vtkInformation *meta_data)
Set/Get the number of scalar components for points.
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:144
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.
TextPropertyKey< std::string > UTF8TextPropertyKey
vtkTextureImageCache< UTF8TextPropertyKey > TextTextureCache
Cache for text images.
represent and manipulate 3D points
Definition: vtkPoints.h:30
#define GL_CLAMP_TO_EDGE
virtual void Delete()
Delete a VTK object.
vtkIdType * GetPointer(vtkIdType i)
Get a pointer to a particular data index.
Definition: vtkIdList.h:150