VTK  9.6.20260228
vtkVolumeMask.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
4#ifndef vtkVolumeMask_h
5#define vtkVolumeMask_h
6
7#include <vtkDataArray.h>
8#include <vtkImageData.h>
10#include <vtkRenderWindow.h>
11#include <vtkRenderer.h>
12#include <vtkTextureObject.h>
13
14#include <iostream> // STL required
15#include <map> // STL required
16
17//----------------------------------------------------------------------------
18VTK_ABI_NAMESPACE_BEGIN
20{
21public:
22 //--------------------------------------------------------------------------
24 {
25 this->Texture = nullptr;
26 this->Loaded = false;
27 this->LoadedExtent[0] = VTK_INT_MAX;
28 this->LoadedExtent[1] = VTK_INT_MIN;
29 this->LoadedExtent[2] = VTK_INT_MAX;
30 this->LoadedExtent[3] = VTK_INT_MIN;
31 this->LoadedExtent[4] = VTK_INT_MAX;
32 this->LoadedExtent[5] = VTK_INT_MIN;
33 }
34
35 //--------------------------------------------------------------------------
37 {
38 if (this->Texture)
39 {
40 this->Texture->Delete();
41 this->Texture = nullptr;
42 }
43 }
44
45 //--------------------------------------------------------------------------
47
48 //--------------------------------------------------------------------------
49 void Activate() { this->Texture->Activate(); }
50
51 //--------------------------------------------------------------------------
52 void Deactivate() { this->Texture->Deactivate(); }
53
54 //--------------------------------------------------------------------------
55 void Update(vtkRenderer* ren, vtkImageData* input, int cellFlag, int textureExtent[6],
56 int scalarMode, int arrayAccessMode, int arrayId, const char* arrayName,
57 vtkIdType maxMemoryInBytes)
58 {
59 bool needUpdate = false;
60 bool modified = false;
61
62 if (!this->Texture)
63 {
65 needUpdate = true;
66 }
67
69 auto ostate = renWin->GetState();
70 this->Texture->SetContext(renWin);
71
72 if (!this->Texture->GetHandle())
73 {
74 needUpdate = true;
75 }
76
77 int obsolete = needUpdate || !this->Loaded || input->GetMTime() > this->BuildTime;
78 if (!obsolete)
79 {
80 obsolete = cellFlag != this->LoadedCellFlag;
81 int i = 0;
82 while (!obsolete && i < 6)
83 {
84 obsolete = obsolete || this->LoadedExtent[i] > textureExtent[i];
85 ++i;
86 obsolete = obsolete || this->LoadedExtent[i] < textureExtent[i];
87 ++i;
88 }
89 }
90
91 if (obsolete)
92 {
93 this->Loaded = false;
94 int dim[3];
95 input->GetDimensions(dim);
96
98 input, scalarMode, arrayAccessMode, arrayId, arrayName, this->LoadedCellFlag);
99
100 // DON'T USE GetScalarType() or GetNumberOfScalarComponents() on
101 // ImageData as it deals only with point data...
102 int scalarType = scalars->GetDataType();
103 if (scalarType != VTK_UNSIGNED_CHAR)
104 {
105 std::cout << "Mask should be VTK_UNSIGNED_CHAR." << std::endl;
106 }
107 if (scalars->GetNumberOfComponents() != 1)
108 {
109 std::cout << "Mask should be a one-component scalar field." << std::endl;
110 }
111
112 GLint internalFormat = GL_R8;
113 GLenum format = GL_RED;
114 GLenum type = GL_UNSIGNED_BYTE;
115
116 // Enough memory?
117 int textureSize[3];
118 int i = 0;
119 while (i < 3)
120 {
121 textureSize[i] = textureExtent[2 * i + 1] - textureExtent[2 * i] + 1;
122 ++i;
123 }
124
125 GLint width;
126 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &width);
127 this->Loaded = textureSize[0] <= width && textureSize[1] <= width && textureSize[2] <= width;
128 if (this->Loaded)
129 {
130 // so far, so good but some cards don't report allocation error
131 this->Loaded = textureSize[0] * textureSize[1] * textureSize[2] *
133 maxMemoryInBytes;
134 if (this->Loaded)
135 {
136 ostate->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
137
138 if (!(textureExtent[1] - textureExtent[0] + cellFlag == dim[0]))
139 {
140 ostate->vtkglPixelStorei(GL_UNPACK_ROW_LENGTH, dim[0] - cellFlag);
141 }
142 if (!(textureExtent[3] - textureExtent[2] + cellFlag == dim[1]))
143 {
144 ostate->vtkglPixelStorei(GL_UNPACK_IMAGE_HEIGHT, dim[1] - cellFlag);
145 }
146 auto scalarsAOS = scalars->ToAOSDataArray();
147 void* dataPtr = scalarsAOS->GetVoidPointer( // NOLINT(bugprone-unsafe-functions)
148 ((textureExtent[4] * (dim[1] - cellFlag) + textureExtent[2]) * (dim[0] - cellFlag) +
149 textureExtent[0]) *
150 scalars->GetNumberOfComponents());
151
152 this->Texture->SetDataType(type);
153 this->Texture->SetFormat(format);
154 this->Texture->SetInternalFormat(internalFormat);
155 this->Texture->Create3DFromRaw(
156 textureSize[0], textureSize[1], textureSize[2], 1, scalarType, dataPtr);
157 this->Texture->SetWrapS(vtkTextureObject::ClampToEdge);
158 this->Texture->SetWrapT(vtkTextureObject::ClampToEdge);
159 this->Texture->SetWrapR(vtkTextureObject::ClampToEdge);
160 this->Texture->SetMagnificationFilter(vtkTextureObject::Nearest);
161 this->Texture->SetMinificationFilter(vtkTextureObject::Nearest);
162 this->Texture->SetBorderColor(0.0f, 0.0f, 0.0f, 0.0f);
163
164 // Restore the default values.
165 ostate->vtkglPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
166 ostate->vtkglPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
167
168 this->LoadedCellFlag = cellFlag;
169 i = 0;
170 while (i < 6)
171 {
172 this->LoadedExtent[i] = textureExtent[i];
173 ++i;
174 }
175
176 double spacing[3];
177 double origin[3];
178 input->GetSpacing(spacing);
179 input->GetOrigin(origin);
180 int swapBounds[3];
181 swapBounds[0] = (spacing[0] < 0);
182 swapBounds[1] = (spacing[1] < 0);
183 swapBounds[2] = (spacing[2] < 0);
184
185 if (!this->LoadedCellFlag) // loaded extents represent points
186 {
187 // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2];
188 // in general, x=o+i*spacing.
189 // if spacing is positive min extent match the min of the
190 // bounding box
191 // and the max extent match the max of the bounding box
192 // if spacing is negative min extent match the max of the
193 // bounding box
194 // and the max extent match the min of the bounding box
195
196 // if spacing is negative, we may have to rethink the equation
197 // between real point and texture coordinate...
198 this->LoadedBounds[0] =
199 origin[0] + static_cast<double>(this->LoadedExtent[0 + swapBounds[0]]) * spacing[0];
200 this->LoadedBounds[2] =
201 origin[1] + static_cast<double>(this->LoadedExtent[2 + swapBounds[1]]) * spacing[1];
202 this->LoadedBounds[4] =
203 origin[2] + static_cast<double>(this->LoadedExtent[4 + swapBounds[2]]) * spacing[2];
204 this->LoadedBounds[1] =
205 origin[0] + static_cast<double>(this->LoadedExtent[1 - swapBounds[0]]) * spacing[0];
206 this->LoadedBounds[3] =
207 origin[1] + static_cast<double>(this->LoadedExtent[3 - swapBounds[1]]) * spacing[1];
208 this->LoadedBounds[5] =
209 origin[2] + static_cast<double>(this->LoadedExtent[5 - swapBounds[2]]) * spacing[2];
210 }
211 else // loaded extents represent cells
212 {
213 int wholeTextureExtent[6];
214 input->GetExtent(wholeTextureExtent);
215 i = 1;
216 while (i < 6)
217 {
218 wholeTextureExtent[i]--;
219 i += 2;
220 }
221
222 i = 0;
223 while (i < 3)
224 {
225 if (this->LoadedExtent[2 * i] == wholeTextureExtent[2 * i])
226 {
227 this->LoadedBounds[2 * i + swapBounds[i]] = origin[i];
228 }
229 else
230 {
231 this->LoadedBounds[2 * i + swapBounds[i]] =
232 origin[i] + (static_cast<double>(this->LoadedExtent[2 * i]) + 0.5) * spacing[i];
233 }
234
235 if (this->LoadedExtent[2 * i + 1] == wholeTextureExtent[2 * i + 1])
236 {
237 this->LoadedBounds[2 * i + 1 - swapBounds[i]] = origin[i] +
238 (static_cast<double>(this->LoadedExtent[2 * i + 1]) + 1.0) * spacing[i];
239 }
240 else
241 {
242 this->LoadedBounds[2 * i + 1 - swapBounds[i]] = origin[i] +
243 (static_cast<double>(this->LoadedExtent[2 * i + 1]) + 0.5) * spacing[i];
244 }
245 ++i;
246 }
247 }
248 modified = true;
249 }
250 }
251 }
252
253 if (modified)
254 {
255 this->BuildTime.Modified();
256 }
257 }
258
259 //--------------------------------------------------------------------------
260 double* GetLoadedBounds() { return this->LoadedBounds; }
261
262 //--------------------------------------------------------------------------
264
265 //--------------------------------------------------------------------------
266 int GetLoadedCellFlag() { return this->LoadedCellFlag; }
267
268 //--------------------------------------------------------------------------
269 bool IsLoaded() { return this->Loaded; }
270
271 // Get the texture unit
272 //--------------------------------------------------------------------------
274 {
275 if (!this->Texture)
276 {
277 return -1;
278 }
279 return this->Texture->GetTextureUnit();
280 }
281
282 //--------------------------------------------------------------------------
284 {
285 if (this->Texture)
286 {
287 this->Texture->ReleaseGraphicsResources(window);
288 this->Texture->Delete();
289 this->Texture = nullptr;
290 }
291 }
292
293protected:
296
297 double LoadedBounds[6];
299
301 bool Loaded;
302};
303
304//----------------------------------------------------------------------------
306{
307public:
308 std::map<vtkImageData*, vtkVolumeMask*> Map;
310
311private:
312 vtkMapMaskTextureId(const vtkMapMaskTextureId& other) = delete;
313 vtkMapMaskTextureId& operator=(const vtkMapMaskTextureId& other) = delete;
314};
315
316VTK_ABI_NAMESPACE_END
317#endif // vtkVolumeMask_h
318// VTK-HeaderTest-Exclude: vtkVolumeMask.h
int GetNumberOfComponents() const
Set/Get the dimension (n) of the components.
virtual int GetDataType() const
Return the underlying data type.
virtual int GetDataTypeSize() const =0
Return the size of the underlying data type.
virtual void * GetVoidPointer(vtkIdType valueIdx)=0
Return a void pointer.
static vtkDataArray * GetScalars(vtkDataSet *input, int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, int &cellFlag)
Internal helper function for getting the active scalars.
int * GetDimensions()
Get dimensions of this structured points dataset.
virtual int * GetExtent()
Set/Get the extent.
vtkSmartPointer< vtkDataArray > ToAOSDataArray()
If the array is not already in AOS format, return a new array that is with the same data.
vtkMTimeType GetMTime() override
Datasets are composite objects and need to check each part for MTime THIS METHOD IS THREAD SAFE.
topologically and geometrically regular array of data
virtual double * GetOrigin()
Set/Get the origin of the dataset.
virtual double * GetSpacing()
Set the spacing (width,height,length) of the cubical cells that compose the data set.
std::map< vtkImageData *, vtkVolumeMask * > Map
vtkMapMaskTextureId()=default
OpenGL rendering window.
static vtkOpenGLRenderWindow * SafeDownCast(vtkObjectBase *o)
virtual vtkOpenGLState * GetState()
abstract specification for renderers
vtkRenderWindow * GetRenderWindow()
Specify the rendering window in which to draw.
abstracts an OpenGL texture object.
static vtkTextureObject * New()
record modification and/or execution time
double LoadedBounds[6]
void Update(vtkRenderer *ren, vtkImageData *input, int cellFlag, int textureExtent[6], int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, vtkIdType maxMemoryInBytes)
vtkTimeStamp BuildTime
vtkTextureObject * Texture
vtkIdType LoadedExtent[6]
vtkTimeStamp GetBuildTime()
vtkIdType * GetLoadedExtent()
void ReleaseGraphicsResources(vtkWindow *window)
double * GetLoadedBounds()
int GetLoadedCellFlag()
window superclass for vtkRenderWindow
Definition vtkWindow.h:61
#define vtkDataArray
#define GL_UNSIGNED_BYTE
int vtkIdType
Definition vtkType.h:363
#define VTK_INT_MIN
Definition vtkType.h:191
#define VTK_UNSIGNED_CHAR
Definition vtkType.h:36
#define VTK_INT_MAX
Definition vtkType.h:192