VTK
vtkVolumeMask.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkVolumeMask.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #ifndef vtkVolumeMask_h_
17 #define vtkVolumeMask_h_
18 
19 #include <vtkDataArray.h>
20 #include <vtkImageData.h>
21 
22 #include <map> // STL required
23 
24 //----------------------------------------------------------------------------
25 class vtkVolumeMask
26 {
27 public:
29  {
30  this->TextureId = 0;
31  this->Loaded = false;
32  this->LoadedExtent[0] = VTK_INT_MAX;
33  this->LoadedExtent[1] = VTK_INT_MIN;
34  this->LoadedExtent[2] = VTK_INT_MAX;
35  this->LoadedExtent[3] = VTK_INT_MIN;
36  this->LoadedExtent[4] = VTK_INT_MAX;
37  this->LoadedExtent[5] = VTK_INT_MIN;
38  }
39 
41  {
42  if(this->TextureId != 0)
43  {
44  glDeleteTextures(1, &this->TextureId);
45  this->TextureId = 0;
46  }
47  }
48 
50  {
51  return this->BuildTime;
52  }
53 
54  void Bind()
55  {
56  // Activate texture 6
57  glActiveTexture(GL_TEXTURE6);
58  glBindTexture(GL_TEXTURE_3D, this->TextureId);
59  }
60 
62  int cellFlag,
63  int textureExtent[6],
64  int scalarMode,
65  int arrayAccessMode,
66  int arrayId,
67  const char* arrayName,
68  vtkIdType maxMemoryInBytes)
69  {
70  glActiveTexture(GL_TEXTURE6);
71 
72  bool needUpdate = false;
73  bool modified = false;
74  if(this->TextureId == 0)
75  {
76  glGenTextures(1, &this->TextureId);
77  needUpdate = true;
78  }
79  glBindTexture(GL_TEXTURE_3D,this->TextureId);
80 
81  int obsolete = needUpdate || !this->Loaded ||
82  input->GetMTime()>this->BuildTime;
83  if(!obsolete)
84  {
85  obsolete = cellFlag != this->LoadedCellFlag;
86  int i = 0;
87  while(!obsolete && i<6)
88  {
89  obsolete = obsolete || this->LoadedExtent[i]>textureExtent[i];
90  ++i;
91  obsolete = obsolete || this->LoadedExtent[i]<textureExtent[i];
92  ++i;
93  }
94  }
95 
96  if(obsolete)
97  {
98  this->Loaded = false;
99  int dim[3];
100  input->GetDimensions(dim);
101 
102  vtkDataArray *scalars =
103  vtkAbstractMapper::GetScalars(input,scalarMode,arrayAccessMode,
104  arrayId,arrayName,
105  this->LoadedCellFlag);
106 
107  // DONT USE GetScalarType() or GetNumberOfScalarComponents() on
108  // ImageData as it deals only with point data...
109  int scalarType = scalars->GetDataType();
110  if(scalarType != VTK_UNSIGNED_CHAR)
111  {
112  cout <<"Mask should be VTK_UNSIGNED_CHAR." << endl;
113  }
114  if(scalars->GetNumberOfComponents()!=1)
115  {
116  cout << "Mask should be a one-component scalar field." << endl;
117  }
118 
119  GLint internalFormat = GL_ALPHA8;
120  GLenum format = GL_ALPHA;
121  GLenum type = GL_UNSIGNED_BYTE;
122 
123  // Enough memory?
124  int textureSize[3];
125  int i=0;
126  while(i<3)
127  {
128  textureSize[i] = textureExtent[2*i+1] - textureExtent[2*i] + 1;
129  ++i;
130  }
131 
132  GLint width;
133  glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &width);
134  this->Loaded = textureSize[0] <= width && textureSize[1] <= width &&
135  textureSize[2] <= width;
136  if(this->Loaded)
137  {
138  // So far, so good but some cards always succeed with a proxy texture
139  // let's try to actually allocate..
140  glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, textureSize[0],
141  textureSize[1], textureSize[2], 0, format, type, 0);
142  GLenum errorCode = glGetError();
143  this->Loaded = errorCode!= GL_OUT_OF_MEMORY;
144  if(this->Loaded)
145  {
146  // so far, so good, actual allocation succeeded.
147  if(errorCode != GL_NO_ERROR)
148  {
149  cout << "After try to load the texture";
150  cout << "ERROR (x"<<hex<<errorCode<<") " << dec;
151  cout << endl;
152  }
153  // so far, so good but some cards don't report allocation error
154  this->Loaded = textureSize[0] * textureSize[1]*
155  textureSize[2]*vtkAbstractArray::GetDataTypeSize(scalarType)*
156  scalars->GetNumberOfComponents() <= maxMemoryInBytes;
157  if(this->Loaded)
158  {
159  // OK, we consider the allocation above succeeded...
160  // If it actually didn't the only to fix it for the user
161  // is to decrease the value of this->MaxMemoryInBytes.
162 
163  // enough memory! We can load the scalars!
164 
165  // we don't clamp to edge because for the computation of the
166  // gradient on the border we need some external value.
167  glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
168  glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
169  glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
170 
171  GLfloat borderColor[4]={0.0,0.0,0.0,0.0};
172  glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, borderColor);
173 
174  glPixelTransferf(GL_ALPHA_SCALE, 1.0);
175  glPixelTransferf(GL_ALPHA_BIAS, 0.0);
176  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
177 
178  if(!(textureExtent[1]-textureExtent[0]+cellFlag==dim[0]))
179  {
180  glPixelStorei(GL_UNPACK_ROW_LENGTH,dim[0]-cellFlag);
181  }
182  if(!(textureExtent[3]-textureExtent[2]+cellFlag==dim[1]))
183  {
184  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT_EXT,
185  dim[1]-cellFlag);
186  }
187  void* dataPtr = scalars->GetVoidPointer(
188  ((textureExtent[4]*(dim[1]-cellFlag)+textureExtent[2]) *
189  (dim[0]-cellFlag)+textureExtent[0]) *
190  scalars->GetNumberOfComponents());
191 
192  glTexImage3D(GL_TEXTURE_3D, 0, internalFormat,
193  textureSize[0], textureSize[1], textureSize[2],
194  0, format, type, dataPtr);
195 
196  // Restore the default values.
197  glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
198  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT_EXT,0);
199  glPixelTransferf(GL_ALPHA_SCALE,1.0);
200  glPixelTransferf(GL_ALPHA_BIAS,0.0);
201 
202  this->LoadedCellFlag = cellFlag;
203  i = 0;
204  while(i < 6)
205  {
206  this->LoadedExtent[i] = textureExtent[i];
207  ++i;
208  }
209 
210  double spacing[3];
211  double origin[3];
212  input->GetSpacing(spacing);
213  input->GetOrigin(origin);
214  int swapBounds[3];
215  swapBounds[0] = (spacing[0] < 0);
216  swapBounds[1] = (spacing[1] < 0);
217  swapBounds[2] = (spacing[2] < 0);
218 
219  if(!this->LoadedCellFlag) // loaded extents represent points
220  {
221  // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2];
222  // in general, x=o+i*spacing.
223  // if spacing is positive min extent match the min of the
224  // bounding box
225  // and the max extent match the max of the bounding box
226  // if spacing is negative min extent match the max of the
227  // bounding box
228  // and the max extent match the min of the bounding box
229 
230  // if spacing is negative, we may have to rethink the equation
231  // between real point and texture coordinate...
232  this->LoadedBounds[0]=origin[0]+
233  static_cast<double>(this->LoadedExtent[0+swapBounds[0]])*spacing[0];
234  this->LoadedBounds[2]=origin[1]+
235  static_cast<double>(this->LoadedExtent[2+swapBounds[1]])*spacing[1];
236  this->LoadedBounds[4]=origin[2]+
237  static_cast<double>(this->LoadedExtent[4+swapBounds[2]])*spacing[2];
238  this->LoadedBounds[1]=origin[0]+
239  static_cast<double>(this->LoadedExtent[1-swapBounds[0]])*spacing[0];
240  this->LoadedBounds[3]=origin[1]+
241  static_cast<double>(this->LoadedExtent[3-swapBounds[1]])*spacing[1];
242  this->LoadedBounds[5]=origin[2]+
243  static_cast<double>(this->LoadedExtent[5-swapBounds[2]])*spacing[2];
244 
245  }
246  else // loaded extents represent cells
247  {
248  int wholeTextureExtent[6];
249  input->GetExtent(wholeTextureExtent);
250  i=1;
251  while(i<6)
252  {
253  wholeTextureExtent[i]--;
254  i+=2;
255  }
256 
257  i=0;
258  while(i<3)
259  {
260  if(this->LoadedExtent[2*i]==wholeTextureExtent[2*i])
261  {
262  this->LoadedBounds[2*i+swapBounds[i]]=origin[i];
263  }
264  else
265  {
266  this->LoadedBounds[2*i+swapBounds[i]]=origin[i]+
267  (static_cast<double>(this->LoadedExtent[2*i])+0.5)*spacing[i];
268  }
269 
270  if(this->LoadedExtent[2*i+1]==wholeTextureExtent[2*i+1])
271  {
272  this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+
273  (static_cast<double>(this->LoadedExtent[2*i+1])+1.0)*spacing[i];
274  }
275  else
276  {
277  this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+
278  (static_cast<double>(this->LoadedExtent[2*i+1])+0.5)*spacing[i];
279  }
280  ++i;
281  }
282  }
283  modified=true;
284  } // if enough memory
285  } //load fail with out of memory
286  }
287  }
288 
289  if(this->Loaded && (needUpdate || modified))
290  {
291  glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER,
292  GL_NEAREST );
293  glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER,
294  GL_NEAREST );
295  modified=true;
296  }
297  if(modified)
298  {
299  this->BuildTime.Modified();
300  }
301  glActiveTexture(GL_TEXTURE0);
302  }
303 
304  double* GetLoadedBounds()
305  {
306  return this->LoadedBounds;
307  }
308 
310  {
311  return this->LoadedExtent;
312  }
313 
315  {
316  return this->LoadedCellFlag;
317  }
318 
319  bool IsLoaded()
320  {
321  return this->Loaded;
322  }
323 
324 protected:
327 
328  double LoadedBounds[6];
330 
331  int LoadedCellFlag;
332  bool Loaded;
333 };
334 
335 //----------------------------------------------------------------------------
337 {
338 public:
339  std::map<vtkImageData *,vtkVolumeMask*> Map;
341  {
342  }
343 private:
345  vtkMapMaskTextureId &operator=(const vtkMapMaskTextureId &other);
346 };
347 
348 #endif // vtkVolumeMask_h_
349 // VTK-HeaderTest-Exclude: vtkVolumeMask.h
vtkIdType * GetLoadedExtent()
GLuint GLuint GLsizei GLenum type
Definition: vtkgl.h:11315
vtkTimeStamp GetBuildTime()
Definition: vtkVolumeMask.h:49
GLenum GLenum GLenum input
Definition: vtkgl.h:15941
virtual int GetDataTypeSize()=0
#define VTK_INT_MAX
Definition: vtkType.h:132
typedef GLuint(APIENTRYP PFNGLCREATEPROGRAMPROC)(void)
record modification and/or execution time
Definition: vtkTimeStamp.h:34
static vtkDataArray * GetScalars(vtkDataSet *input, int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, int &cellFlag)
void Modified()
virtual int GetDataType()=0
double * GetLoadedBounds()
int vtkIdType
Definition: vtkType.h:281
vtkTimeStamp BuildTime
unsigned long int GetMTime()
double LoadedBounds[6]
virtual int * GetDimensions()
virtual double * GetOrigin()
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: vtkgl.h:11316
topologically and geometrically regular array of data
Definition: vtkImageData.h:44
GLint GLint GLsizei width
Definition: vtkgl.h:11316
abstract superclass for arrays of numeric data
Definition: vtkDataArray.h:53
virtual double * GetSpacing()
void Update(vtkImageData *input, int cellFlag, int textureExtent[6], int scalarMode, int arrayAccessMode, int arrayId, const char *arrayName, vtkIdType maxMemoryInBytes)
Definition: vtkVolumeMask.h:61
virtual int * GetExtent()
virtual void * GetVoidPointer(vtkIdType id)=0
typedef GLint(APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program
int GetLoadedCellFlag()
#define VTK_UNSIGNED_CHAR
Definition: vtkType.h:28
typedef GLenum(APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target)
GLenum internalFormat
Definition: vtkgl.h:15195
vtkIdType LoadedExtent[6]
#define VTK_INT_MIN
Definition: vtkType.h:131