VTK
/Users/kitware/Dashboards/MyTests/VTK_BLD_Release_docs/Utilities/Doxygen/dox/Rendering/VolumeOpenGLNew/vtkVolumeMask.h
Go to the documentation of this file.
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