Back to index

salome-gui  6.5.0
VTKViewer_Texture.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 #include "VTKViewer_Texture.h"
00023 
00024 #include "vtkHomogeneousTransform.h"
00025 #include "vtkImageData.h"
00026 #include "vtkLookupTable.h"
00027 #include "vtkObjectFactory.h"
00028 #include "vtkOpenGLRenderer.h"
00029 #include "vtkPointData.h"
00030 #include "vtkRenderWindow.h"
00031 #include "vtkOpenGLExtensionManager.h"
00032 #include "vtkOpenGLRenderWindow.h"
00033 #include "vtkTransform.h"
00034 #include "vtkPixelBufferObject.h"
00035 #include "vtkOpenGL.h"
00036 #include "vtkgl.h" // vtkgl namespace
00037 #include <vtkObjectFactory.h>
00038 
00039 vtkStandardNewMacro(VTKViewer_Texture);
00040 
00041 
00042 // ----------------------------------------------------------------------------
00043 VTKViewer_Texture::VTKViewer_Texture()
00044 {
00045   myWidth = 0;
00046   myHeight = 0;
00047   myPosition = VTKViewer_Texture::Centered;
00048 }
00049 
00050 // ----------------------------------------------------------------------------
00051 VTKViewer_Texture::~VTKViewer_Texture()
00052 {
00053 }
00054 
00055 // ----------------------------------------------------------------------------
00056 // Implement base class method.
00057 void VTKViewer_Texture::Load(vtkRenderer *ren)
00058 {
00059   GLenum format = GL_LUMINANCE;
00060   vtkImageData *input = this->GetInput();
00061 
00062   this->Initialize(ren);
00063 
00064   // Need to reload the texture.
00065   // There used to be a check on the render window's mtime, but
00066   // this is too broad of a check (e.g. it would cause all textures
00067   // to load when only the desired update rate changed).
00068   // If a better check is required, check something more specific,
00069   // like the graphics context.
00070   vtkOpenGLRenderWindow* renWin = 
00071     static_cast<vtkOpenGLRenderWindow*>(ren->GetRenderWindow());
00072 
00073   if(this->BlendingMode != VTK_TEXTURE_BLENDING_MODE_NONE
00074      && vtkgl::ActiveTexture)
00075     {
00076     glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, vtkgl::COMBINE);
00077 
00078     switch(this->BlendingMode)
00079       {
00080       case VTK_TEXTURE_BLENDING_MODE_REPLACE:
00081         {
00082         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
00083         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
00084         break;
00085         }
00086       case VTK_TEXTURE_BLENDING_MODE_MODULATE:
00087         {
00088         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_MODULATE);
00089         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_MODULATE);
00090         break;
00091         }
00092       case VTK_TEXTURE_BLENDING_MODE_ADD:
00093         {
00094         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD);
00095         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD);
00096         break;
00097         }
00098       case VTK_TEXTURE_BLENDING_MODE_ADD_SIGNED:
00099         {
00100         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::ADD_SIGNED);
00101         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::ADD_SIGNED);
00102         break;
00103         }
00104       case VTK_TEXTURE_BLENDING_MODE_INTERPOLATE:
00105         {
00106         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::INTERPOLATE);
00107         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::INTERPOLATE);
00108         break;
00109         }
00110       case VTK_TEXTURE_BLENDING_MODE_SUBTRACT:
00111         {
00112         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::SUBTRACT);
00113         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::SUBTRACT);
00114         break;
00115         }
00116       default:
00117         {
00118         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD);
00119         glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD);
00120         }
00121       }
00122     }
00123 
00124   if (this->GetMTime() > this->LoadTime.GetMTime() ||
00125       input->GetMTime() > this->LoadTime.GetMTime() ||
00126       (this->GetLookupTable() && this->GetLookupTable()->GetMTime () >  
00127        this->LoadTime.GetMTime()) || 
00128        renWin != this->RenderWindow.GetPointer() ||
00129        renWin->GetContextCreationTime() > this->LoadTime)
00130     {
00131     int bytesPerPixel;
00132     int size[3];
00133     vtkDataArray *scalars;
00134     unsigned char *dataPtr;
00135     unsigned char *resultData=NULL;
00136     int xsize, ysize;
00137     unsigned int xs,ys;
00138     GLuint tempIndex=0;
00139 
00140     // Get the scalars the user choose to color with.
00141     scalars = this->GetInputArrayToProcess(0, input);
00142 
00143     // make sure scalars are non null
00144     if (!scalars) 
00145       {
00146       vtkErrorMacro(<< "No scalar values found for texture input!");
00147       return;
00148       }
00149 
00150     // get some info
00151     input->GetDimensions(size);
00152 
00153     if (input->GetNumberOfCells() == scalars->GetNumberOfTuples())
00154       {
00155       // we are using cell scalars. Adjust image size for cells.
00156       for (int kk=0; kk < 3; kk++)
00157         {
00158         if (size[kk]>1)
00159           {
00160           size[kk]--;
00161           }
00162         }
00163       }
00164 
00165     bytesPerPixel = scalars->GetNumberOfComponents();
00166 
00167     // make sure using unsigned char data of color scalars type
00168     if (this->MapColorScalarsThroughLookupTable ||
00169        scalars->GetDataType() != VTK_UNSIGNED_CHAR )
00170       {
00171       dataPtr = this->MapScalarsToColors (scalars);
00172       bytesPerPixel = 4;
00173       }
00174     else
00175       {
00176       dataPtr = static_cast<vtkUnsignedCharArray *>(scalars)->GetPointer(0);
00177       }
00178 
00179     // we only support 2d texture maps right now
00180     // so one of the three sizes must be 1, but it 
00181     // could be any of them, so lets find it
00182     if (size[0] == 1)
00183       {
00184       xsize = size[1]; ysize = size[2];
00185       }
00186     else
00187       {
00188       xsize = size[0];
00189       if (size[1] == 1)
00190         {
00191         ysize = size[2];
00192         }
00193       else
00194         {
00195         ysize = size[1];
00196         if (size[2] != 1)
00197           {
00198           vtkErrorMacro(<< "3D texture maps currently are not supported!");
00199           return;
00200           }
00201         }
00202       }
00203     
00204     
00205     if(!this->CheckedHardwareSupport)
00206       {
00207       vtkOpenGLExtensionManager *m=renWin->GetExtensionManager();
00208       this->CheckedHardwareSupport=true;
00209       this->SupportsNonPowerOfTwoTextures=
00210         m->ExtensionSupported("GL_VERSION_2_0")
00211         || m->ExtensionSupported("GL_ARB_texture_non_power_of_two");
00212       this->SupportsPBO=vtkPixelBufferObject::IsSupported(renWin);
00213       }
00214     
00215     // -- decide whether the texture needs to be resampled --
00216     
00217     GLint maxDimGL;
00218     glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL);
00219     // if larger than permitted by the graphics library then must resample
00220     bool resampleNeeded=xsize > maxDimGL || ysize > maxDimGL;
00221     if(resampleNeeded)
00222       {
00223       vtkDebugMacro( "Texture too big for gl, maximum is " << maxDimGL);
00224       }
00225     
00226     if(!resampleNeeded && !this->SupportsNonPowerOfTwoTextures)
00227       {
00228       // xsize and ysize must be a power of 2 in OpenGL
00229       xs = static_cast<unsigned int>(xsize);
00230       ys = static_cast<unsigned int>(ysize);
00231       while (!(xs & 0x01))
00232         {
00233         xs = xs >> 1;
00234         }
00235       while (!(ys & 0x01))
00236         {
00237         ys = ys >> 1;
00238         }
00239       // if not a power of two then resampling is required
00240       resampleNeeded= (xs>1) || (ys>1);
00241       }
00242 
00243     if(resampleNeeded)
00244       {
00245       vtkDebugMacro(<< "Resampling texture to power of two for OpenGL");
00246       resultData = this->ResampleToPowerOfTwo(xsize, ysize, dataPtr, 
00247                                               bytesPerPixel);
00248       }
00249 
00250     if ( resultData == NULL )
00251         {
00252         resultData = dataPtr;
00253         }
00254 
00255     // free any old display lists (from the old context)
00256     if (this->RenderWindow)
00257       {
00258       this->ReleaseGraphicsResources(this->RenderWindow);
00259       }
00260     
00261      this->RenderWindow = ren->GetRenderWindow();
00262      
00263     // make the new context current before we mess with opengl
00264     this->RenderWindow->MakeCurrent();
00265  
00266     // define a display list for this texture
00267     // get a unique display list id
00268 
00269 #ifdef GL_VERSION_1_1
00270     glGenTextures(1, &tempIndex);
00271     this->Index = static_cast<long>(tempIndex);
00272     glBindTexture(GL_TEXTURE_2D, this->Index);
00273 #else
00274     this->Index = glGenLists(1);
00275     glDeleteLists (static_cast<GLuint>(this->Index), static_cast<GLsizei>(0));
00276     glNewList (static_cast<GLuint>(this->Index), GL_COMPILE);
00277 #endif
00278     //seg fault protection for those wackos that don't use an
00279     //opengl render window
00280     if(this->RenderWindow->IsA("vtkOpenGLRenderWindow"))
00281       {
00282       static_cast<vtkOpenGLRenderWindow *>(ren->GetRenderWindow())->
00283         RegisterTextureResource( this->Index );
00284       }
00285 
00286     if (this->Interpolate)
00287       {
00288       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
00289                        GL_LINEAR);
00290       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
00291                        GL_LINEAR );
00292       }
00293     else
00294       {
00295       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
00296       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00297       }
00298     if (this->Repeat)
00299       {
00300       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_REPEAT );
00301       glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_REPEAT );
00302       }
00303     else
00304       {
00305       vtkOpenGLExtensionManager* manager = renWin->GetExtensionManager();
00306       if (this->EdgeClamp &&
00307            (manager->ExtensionSupported("GL_VERSION_1_2") ||
00308             manager->ExtensionSupported("GL_EXT_texture_edge_clamp")))
00309         {
00310         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
00311                          vtkgl::CLAMP_TO_EDGE );
00312         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
00313                          vtkgl::CLAMP_TO_EDGE );
00314         }
00315       else
00316         {
00317         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     GL_CLAMP );
00318         glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     GL_CLAMP );
00319         }
00320       }
00321     int internalFormat = bytesPerPixel;
00322     switch (bytesPerPixel)
00323       {
00324       case 1: format = GL_LUMINANCE; break;
00325       case 2: format = GL_LUMINANCE_ALPHA; break;
00326       case 3: format = GL_RGB; break;
00327       case 4: format = GL_RGBA; break;
00328       }
00329     // if we are using OpenGL 1.1, you can force 32 or16 bit textures
00330 #ifdef GL_VERSION_1_1
00331     if (this->Quality == VTK_TEXTURE_QUALITY_32BIT)
00332       {
00333       switch (bytesPerPixel)
00334         {
00335         case 1: internalFormat = GL_LUMINANCE8; break;
00336         case 2: internalFormat = GL_LUMINANCE8_ALPHA8; break;
00337         case 3: internalFormat = GL_RGB8; break;
00338         case 4: internalFormat = GL_RGBA8; break;
00339         }
00340       }
00341     else if (this->Quality == VTK_TEXTURE_QUALITY_16BIT)
00342       {
00343       switch (bytesPerPixel)
00344         {
00345         case 1: internalFormat = GL_LUMINANCE4; break;
00346         case 2: internalFormat = GL_LUMINANCE4_ALPHA4; break;
00347         case 3: internalFormat = GL_RGB4; break;
00348         case 4: internalFormat = GL_RGBA4; break;
00349         }
00350       }
00351 #endif
00352     if(this->SupportsPBO)
00353       {
00354       if(this->PBO==0)
00355         {
00356         this->PBO=vtkPixelBufferObject::New();
00357         this->PBO->SetContext(renWin);
00358         }
00359       unsigned int dims[2];
00360       vtkIdType increments[2];
00361       dims[0]=static_cast<unsigned int>(xsize);
00362       dims[1]=static_cast<unsigned int>(ysize);
00363       increments[0]=0;
00364       increments[1]=0;
00365       this->PBO->Upload2D(VTK_UNSIGNED_CHAR,resultData,dims,bytesPerPixel,
00366         increments);
00367       // non-blocking call
00368       this->PBO->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
00369       glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat,
00370                     xsize, ysize, 0, format, 
00371                     GL_UNSIGNED_BYTE,0);
00372       myWidth = xsize;
00373       myHeight = ysize;
00374       this->PBO->UnBind();
00375       }
00376     else
00377       {
00378       // blocking call
00379       glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat,
00380                     xsize, ysize, 0, format, 
00381                     GL_UNSIGNED_BYTE,
00382                     static_cast<const GLvoid *>(resultData) );
00383         myWidth = xsize;
00384         myHeight = ysize;
00385       }
00386 #ifndef GL_VERSION_1_1
00387     glEndList ();
00388 #endif
00389     // modify the load time to the current time
00390     this->LoadTime.Modified();
00391     
00392     // free memory
00393     if (resultData != dataPtr)
00394       {
00395       delete [] resultData;
00396       }
00397     }
00398 
00399   // execute the display list that uses creates the texture
00400 #ifdef GL_VERSION_1_1
00401   glBindTexture(GL_TEXTURE_2D, this->Index);
00402 #else
00403   glCallList(this->Index);
00404 #endif
00405   
00406   // don't accept fragments if they have zero opacity. this will stop the
00407   // zbuffer from be blocked by totally transparent texture fragments.
00408   glAlphaFunc (GL_GREATER, static_cast<GLclampf>(0));
00409   glEnable (GL_ALPHA_TEST);
00410 
00411   if (this->PremultipliedAlpha)
00412     {
00413     // save the blend function.
00414     glPushAttrib(GL_COLOR_BUFFER_BIT);
00415 
00416     // make the blend function correct for textures premultiplied by alpha.
00417     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
00418     }
00419 
00420   // now bind it
00421   glEnable(GL_TEXTURE_2D);
00422 
00423   // clear any texture transform
00424   glMatrixMode(GL_TEXTURE);
00425   glLoadIdentity();
00426 
00427   // build transformation 
00428   if (this->Transform)
00429     {
00430     double *mat = this->Transform->GetMatrix()->Element[0];
00431     double mat2[16];
00432     mat2[0] = mat[0];
00433     mat2[1] = mat[4];
00434     mat2[2] = mat[8];
00435     mat2[3] = mat[12];
00436     mat2[4] = mat[1];
00437     mat2[5] = mat[5];
00438     mat2[6] = mat[9];
00439     mat2[7] = mat[13];
00440     mat2[8] = mat[2];
00441     mat2[9] = mat[6];
00442     mat2[10] = mat[10];
00443     mat2[11] = mat[14];
00444     mat2[12] = mat[3];
00445     mat2[13] = mat[7];
00446     mat2[14] = mat[11];
00447     mat2[15] = mat[15];
00448     
00449     // insert texture transformation 
00450     glMultMatrixd(mat2);
00451     }
00452   glMatrixMode(GL_MODELVIEW);
00453   
00454   GLint uUseTexture=-1;
00455   GLint uTexture=-1;
00456   
00457   vtkOpenGLRenderer *oRenderer=static_cast<vtkOpenGLRenderer *>(ren);
00458  
00459 /*  if(oRenderer->GetDepthPeelingHigherLayer())
00460     {
00461     uUseTexture=oRenderer->GetUseTextureUniformVariable();
00462     uTexture=oRenderer->GetTextureUniformVariable();
00463     vtkgl::Uniform1i(uUseTexture,1);
00464     vtkgl::Uniform1i(uTexture,0); // active texture 0
00465     }
00466     */
00467 }
00468 
00469 void VTKViewer_Texture::Initialize(vtkRenderer * vtkNotUsed(ren))
00470 {
00471 }
00472 
00473 int VTKViewer_Texture::GetWidth() const
00474 {
00475   return myWidth;
00476 }
00477 
00478 int VTKViewer_Texture::GetHeight() const
00479 {
00480   return myHeight;
00481 }
00482 
00483 void VTKViewer_Texture::SetPosition(int pos)
00484 {
00485   myPosition = pos;
00486 }
00487 
00488 int VTKViewer_Texture::GetPosition() const
00489 {
00490   return myPosition;
00491 }