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