VTK  9.5.20251214
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
20
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"
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.
47VTK_ABI_NAMESPACE_BEGIN
48template <class Key>
50{
51public:
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 };
93
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 }
130
131
132protected:
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 }
148
149
153 std::list<CacheElement> Cache;
155
158 size_t MaxSize;
160};
161
162template <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.
182template <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 }
224
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 }
242
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{
268public:
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
396 GLuint TextureFromImage(vtkImageData* image, vtkVector2f& texCoords)
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
532public:
534 {
535 LINE = 1,
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
576private:
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 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, cacheItem->PolyColors->GetPointer(0), 4);
871 }
872 }
873
875
876 vtkPoints* Points;
877 vtkIdType* PointIds;
878 vtkUnsignedCharArray* Colors;
879
881
884 vtkIdType NumPointsCell;
885 std::vector<float> CellPoints;
886 vtkNew<vtkUnsignedCharArray> CellColors;
888
889 PolyDataCache* cache;
890};
891VTK_ABI_NAMESPACE_END
892#endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
893// VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h
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.
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.
void SetInputData(vtkDataObject *)
Assign a data object as input.
topologically and geometrically regular array of data
T * GetPointer() const noexcept
Get a raw pointer to the contained object.
Definition vtkNew.h:256
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.
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
concrete dataset represents vertices, lines, polygons, and triangle strips
vtkCell * GetCell(vtkIdType cellId) override
Standard vtkDataSet interface.
vtkMTimeType GetMTime() override
Get MTime which also considers its cell array MTime.
vtkIdType GetNumberOfCells() override
Standard vtkDataSet interface.
Hold a reference to a vtkObjectBase instance.
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 double * GetColor()
Set the color of the text.
virtual double * GetInteriorLinesColor()
Set the color of the interior lines between cells.
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 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.
CacheData & AddCacheData(const Key &key, const CacheData &cacheData)
Add a new cache entry into the cache list.
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 & GetCacheData(const Key &key)
Return the cache associated to a key.
handles properties associated with a texture map
Definition vtkTexture.h:168
record modification and/or execution time
dynamic, self-adjusting array of unsigned char
Some derived classes for the different vectors commonly used.
Definition vtkVector.h:450
window superclass for vtkRenderWindow
Definition vtkWindow.h:48
@ point
Definition vtkX3D.h:237
@ key
Definition vtkX3D.h:258
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:40
@ VTK_TRIANGLE
Definition vtkCellType.h:41
@ VTK_POLYGON
Definition vtkCellType.h:43
@ VTK_LINE
Definition vtkCellType.h:39
@ VTK_QUAD
Definition vtkCellType.h:45
#define GL_NEAREST
#define GL_UNSIGNED_BYTE
#define GL_CLAMP_TO_EDGE
TextPropertyKey< std::string > UTF8TextPropertyKey
int vtkIdType
Definition vtkType.h:367
#define VTK_UNSIGNED_CHAR
Definition vtkType.h:36