VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkVolumeMask.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 00016 #ifndef vtkVolumeMask_h_ 00017 #define vtkVolumeMask_h_ 00018 00019 #include <vtkDataArray.h> 00020 #include <vtkImageData.h> 00021 00022 #include <map> // STL required 00023 00024 //---------------------------------------------------------------------------- 00025 class vtkVolumeMask 00026 { 00027 public: 00028 vtkVolumeMask() 00029 { 00030 this->TextureId = 0; 00031 this->Loaded = false; 00032 this->LoadedExtent[0] = VTK_INT_MAX; 00033 this->LoadedExtent[1] = VTK_INT_MIN; 00034 this->LoadedExtent[2] = VTK_INT_MAX; 00035 this->LoadedExtent[3] = VTK_INT_MIN; 00036 this->LoadedExtent[4] = VTK_INT_MAX; 00037 this->LoadedExtent[5] = VTK_INT_MIN; 00038 } 00039 00040 ~vtkVolumeMask() 00041 { 00042 if(this->TextureId != 0) 00043 { 00044 glDeleteTextures(1, &this->TextureId); 00045 this->TextureId = 0; 00046 } 00047 } 00048 00049 vtkTimeStamp GetBuildTime() 00050 { 00051 return this->BuildTime; 00052 } 00053 00054 void Bind() 00055 { 00056 // Activate texture 6 00057 glActiveTexture(GL_TEXTURE6); 00058 glBindTexture(GL_TEXTURE_3D, this->TextureId); 00059 } 00060 00061 void Update(vtkImageData *input, 00062 int cellFlag, 00063 int textureExtent[6], 00064 int scalarMode, 00065 int arrayAccessMode, 00066 int arrayId, 00067 const char* arrayName, 00068 vtkIdType maxMemoryInBytes) 00069 { 00070 glActiveTexture(GL_TEXTURE6); 00071 00072 bool needUpdate = false; 00073 bool modified = false; 00074 if(this->TextureId == 0) 00075 { 00076 glGenTextures(1, &this->TextureId); 00077 needUpdate = true; 00078 } 00079 glBindTexture(GL_TEXTURE_3D,this->TextureId); 00080 00081 int obsolete = needUpdate || !this->Loaded || 00082 input->GetMTime()>this->BuildTime; 00083 if(!obsolete) 00084 { 00085 obsolete = cellFlag != this->LoadedCellFlag; 00086 int i = 0; 00087 while(!obsolete && i<6) 00088 { 00089 obsolete = obsolete || this->LoadedExtent[i]>textureExtent[i]; 00090 ++i; 00091 obsolete = obsolete || this->LoadedExtent[i]<textureExtent[i]; 00092 ++i; 00093 } 00094 } 00095 00096 if(obsolete) 00097 { 00098 this->Loaded = false; 00099 int dim[3]; 00100 input->GetDimensions(dim); 00101 00102 vtkDataArray *scalars = 00103 vtkAbstractMapper::GetScalars(input,scalarMode,arrayAccessMode, 00104 arrayId,arrayName, 00105 this->LoadedCellFlag); 00106 00107 // DONT USE GetScalarType() or GetNumberOfScalarComponents() on 00108 // ImageData as it deals only with point data... 00109 int scalarType = scalars->GetDataType(); 00110 if(scalarType != VTK_UNSIGNED_CHAR) 00111 { 00112 cout <<"Mask should be VTK_UNSIGNED_CHAR." << endl; 00113 } 00114 if(scalars->GetNumberOfComponents()!=1) 00115 { 00116 cout << "Mask should be a one-component scalar field." << endl; 00117 } 00118 00119 GLint internalFormat = GL_ALPHA8; 00120 GLenum format = GL_ALPHA; 00121 GLenum type = GL_UNSIGNED_BYTE; 00122 00123 // Enough memory? 00124 int textureSize[3]; 00125 int i=0; 00126 while(i<3) 00127 { 00128 textureSize[i] = textureExtent[2*i+1] - textureExtent[2*i] + 1; 00129 ++i; 00130 } 00131 00132 GLint width; 00133 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &width); 00134 this->Loaded = textureSize[0] <= width && textureSize[1] <= width && 00135 textureSize[2] <= width; 00136 if(this->Loaded) 00137 { 00138 // So far, so good but some cards always succeed with a proxy texture 00139 // let's try to actually allocate.. 00140 glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, textureSize[0], 00141 textureSize[1], textureSize[2], 0, format, type, 0); 00142 GLenum errorCode = glGetError(); 00143 this->Loaded = errorCode!= GL_OUT_OF_MEMORY; 00144 if(this->Loaded) 00145 { 00146 // so far, so good, actual allocation succeeded. 00147 if(errorCode != GL_NO_ERROR) 00148 { 00149 cout << "After try to load the texture"; 00150 cout << "ERROR (x"<<hex<<errorCode<<") " << dec; 00151 cout << endl; 00152 } 00153 // so far, so good but some cards don't report allocation error 00154 this->Loaded = textureSize[0] * textureSize[1]* 00155 textureSize[2]*vtkAbstractArray::GetDataTypeSize(scalarType)* 00156 scalars->GetNumberOfComponents() <= maxMemoryInBytes; 00157 if(this->Loaded) 00158 { 00159 // OK, we consider the allocation above succeeded... 00160 // If it actually didn't the only to fix it for the user 00161 // is to decrease the value of this->MaxMemoryInBytes. 00162 00163 // enough memory! We can load the scalars! 00164 00165 // we don't clamp to edge because for the computation of the 00166 // gradient on the border we need some external value. 00167 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 00168 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00169 glTexParameterf(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00170 00171 GLfloat borderColor[4]={0.0,0.0,0.0,0.0}; 00172 glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, borderColor); 00173 00174 glPixelTransferf(GL_ALPHA_SCALE, 1.0); 00175 glPixelTransferf(GL_ALPHA_BIAS, 0.0); 00176 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 00177 00178 if(!(textureExtent[1]-textureExtent[0]+cellFlag==dim[0])) 00179 { 00180 glPixelStorei(GL_UNPACK_ROW_LENGTH,dim[0]-cellFlag); 00181 } 00182 if(!(textureExtent[3]-textureExtent[2]+cellFlag==dim[1])) 00183 { 00184 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT_EXT, 00185 dim[1]-cellFlag); 00186 } 00187 void* dataPtr = scalars->GetVoidPointer( 00188 ((textureExtent[4]*(dim[1]-cellFlag)+textureExtent[2]) * 00189 (dim[0]-cellFlag)+textureExtent[0]) * 00190 scalars->GetNumberOfComponents()); 00191 00192 glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, 00193 textureSize[0], textureSize[1], textureSize[2], 00194 0, format, type, dataPtr); 00195 00196 // Restore the default values. 00197 glPixelStorei(GL_UNPACK_ROW_LENGTH,0); 00198 glPixelStorei(GL_UNPACK_IMAGE_HEIGHT_EXT,0); 00199 glPixelTransferf(GL_ALPHA_SCALE,1.0); 00200 glPixelTransferf(GL_ALPHA_BIAS,0.0); 00201 00202 this->LoadedCellFlag = cellFlag; 00203 i = 0; 00204 while(i < 6) 00205 { 00206 this->LoadedExtent[i] = textureExtent[i]; 00207 ++i; 00208 } 00209 00210 double spacing[3]; 00211 double origin[3]; 00212 input->GetSpacing(spacing); 00213 input->GetOrigin(origin); 00214 int swapBounds[3]; 00215 swapBounds[0] = (spacing[0] < 0); 00216 swapBounds[1] = (spacing[1] < 0); 00217 swapBounds[2] = (spacing[2] < 0); 00218 00219 if(!this->LoadedCellFlag) // loaded extents represent points 00220 { 00221 // slabsPoints[i]=(slabsDataSet[i] - origin[i/2]) / spacing[i/2]; 00222 // in general, x=o+i*spacing. 00223 // if spacing is positive min extent match the min of the 00224 // bounding box 00225 // and the max extent match the max of the bounding box 00226 // if spacing is negative min extent match the max of the 00227 // bounding box 00228 // and the max extent match the min of the bounding box 00229 00230 // if spacing is negative, we may have to rethink the equation 00231 // between real point and texture coordinate... 00232 this->LoadedBounds[0]=origin[0]+ 00233 static_cast<double>(this->LoadedExtent[0+swapBounds[0]])*spacing[0]; 00234 this->LoadedBounds[2]=origin[1]+ 00235 static_cast<double>(this->LoadedExtent[2+swapBounds[1]])*spacing[1]; 00236 this->LoadedBounds[4]=origin[2]+ 00237 static_cast<double>(this->LoadedExtent[4+swapBounds[2]])*spacing[2]; 00238 this->LoadedBounds[1]=origin[0]+ 00239 static_cast<double>(this->LoadedExtent[1-swapBounds[0]])*spacing[0]; 00240 this->LoadedBounds[3]=origin[1]+ 00241 static_cast<double>(this->LoadedExtent[3-swapBounds[1]])*spacing[1]; 00242 this->LoadedBounds[5]=origin[2]+ 00243 static_cast<double>(this->LoadedExtent[5-swapBounds[2]])*spacing[2]; 00244 00245 } 00246 else // loaded extents represent cells 00247 { 00248 int wholeTextureExtent[6]; 00249 input->GetExtent(wholeTextureExtent); 00250 i=1; 00251 while(i<6) 00252 { 00253 wholeTextureExtent[i]--; 00254 i+=2; 00255 } 00256 00257 i=0; 00258 while(i<3) 00259 { 00260 if(this->LoadedExtent[2*i]==wholeTextureExtent[2*i]) 00261 { 00262 this->LoadedBounds[2*i+swapBounds[i]]=origin[i]; 00263 } 00264 else 00265 { 00266 this->LoadedBounds[2*i+swapBounds[i]]=origin[i]+ 00267 (static_cast<double>(this->LoadedExtent[2*i])+0.5)*spacing[i]; 00268 } 00269 00270 if(this->LoadedExtent[2*i+1]==wholeTextureExtent[2*i+1]) 00271 { 00272 this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ 00273 (static_cast<double>(this->LoadedExtent[2*i+1])+1.0)*spacing[i]; 00274 } 00275 else 00276 { 00277 this->LoadedBounds[2*i+1-swapBounds[i]]=origin[i]+ 00278 (static_cast<double>(this->LoadedExtent[2*i+1])+0.5)*spacing[i]; 00279 } 00280 ++i; 00281 } 00282 } 00283 modified=true; 00284 } // if enough memory 00285 } //load fail with out of memory 00286 } 00287 } 00288 00289 if(this->Loaded && (needUpdate || modified)) 00290 { 00291 glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_MIN_FILTER, 00292 GL_NEAREST ); 00293 glTexParameterf(GL_TEXTURE_3D,GL_TEXTURE_MAG_FILTER, 00294 GL_NEAREST ); 00295 modified=true; 00296 } 00297 if(modified) 00298 { 00299 this->BuildTime.Modified(); 00300 } 00301 glActiveTexture(GL_TEXTURE0); 00302 } 00303 00304 double* GetLoadedBounds() 00305 { 00306 return this->LoadedBounds; 00307 } 00308 00309 vtkIdType* GetLoadedExtent() 00310 { 00311 return this->LoadedExtent; 00312 } 00313 00314 int GetLoadedCellFlag() 00315 { 00316 return this->LoadedCellFlag; 00317 } 00318 00319 bool IsLoaded() 00320 { 00321 return this->Loaded; 00322 } 00323 00324 protected: 00325 GLuint TextureId; 00326 vtkTimeStamp BuildTime; 00327 00328 double LoadedBounds[6]; 00329 vtkIdType LoadedExtent[6]; 00330 00331 int LoadedCellFlag; 00332 bool Loaded; 00333 }; 00334 00335 //---------------------------------------------------------------------------- 00336 class vtkMapMaskTextureId 00337 { 00338 public: 00339 std::map<vtkImageData *,vtkVolumeMask*> Map; 00340 vtkMapMaskTextureId() 00341 { 00342 } 00343 private: 00344 vtkMapMaskTextureId(const vtkMapMaskTextureId &other); 00345 vtkMapMaskTextureId &operator=(const vtkMapMaskTextureId &other); 00346 }; 00347 00348 #endif // vtkVolumeMask_h_ 00349 // VTK-HeaderTest-Exclude: vtkVolumeMask.h