TextureNode.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 //=============================================================================
00047 //
00048 //  CLASS TextureNode - IMPLEMENTATION
00049 //
00050 //=============================================================================
00051 
00052 
00053 //== INCLUDES =================================================================
00054 
00055 
00056 #include "TextureNode.hh"
00057 #include "DrawModes.hh"
00058 #include <QGLWidget>
00059 
00060 
00061 //== NAMESPACES ===============================================================
00062 
00063 
00064 namespace ACG {
00065 namespace SceneGraph {
00066 
00067 
00068 //== IMPLEMENTATION ==========================================================
00069 
00070 
00071 TextureNode::TextureNode( BaseNode*            _parent,
00072                           const std::string&   _name,
00073                           bool                 _texture_repeat,
00074                           GLint                _texture_filter )
00075       : BaseNode( _parent, _name ),
00076         textures_(),
00077         alpha_( 0 ),
00078         texture_repeat_( _texture_repeat ),
00079         tex_mode_( GL_MODULATE ),
00080         texture_filter_( _texture_filter ),
00081         activeTexture_(-1)
00082 {
00083 }
00084 
00085 
00086 //----------------------------------------------------------------------------
00087 
00088 
00089 TextureNode::~TextureNode()
00090 {
00091   for (std::vector<TextureInfo>::iterator texturesIt = textures_.begin(); texturesIt != textures_.end(); texturesIt++) {
00092     if ( glIsTexture( texturesIt->id ) ) {
00093       glDeleteTextures( 1, &(texturesIt->id) );
00094     }
00095   }
00096   textures_.clear();
00097 }
00098 
00099 
00100 
00101 //----------------------------------------------------------------------------
00102 
00103 
00104 bool
00105 TextureNode::read(const char* _filename)
00106 {
00107    // load to image
00108    QImage image;
00109    if ( !image.load( _filename ) )
00110    {
00111       std::cerr << "Cannot load texture " << _filename << "\n";
00112       return false;
00113    }
00114 
00115    set_texture( image );
00116 
00117    return true;
00118 }
00119 
00120 
00121 //----------------------------------------------------------------------------
00122 
00123 
00124 void
00125 TextureNode::applyGLSettings(  )
00126 {
00127   // GL settings
00128   glPixelStorei( GL_UNPACK_ROW_LENGTH,  0 );
00129   glPixelStorei( GL_UNPACK_SKIP_ROWS,   0 );
00130   glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 );
00131   glPixelStorei( GL_UNPACK_ALIGNMENT,   1 );
00132   glPixelStorei( GL_PACK_ROW_LENGTH,    0 );
00133   glPixelStorei( GL_PACK_SKIP_ROWS,     0 );
00134   glPixelStorei( GL_PACK_SKIP_PIXELS,   0 );
00135   glPixelStorei( GL_PACK_ALIGNMENT,     1 );
00136 }
00137 
00138 void
00139 TextureNode::applyTextureParameters( int _id )
00140 {
00141   if ( texture_repeat_ ) {
00142     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
00143     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
00144   } else {
00145     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
00146     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
00147 
00148     // Set BorderColor for Clamping
00149     const float borderColor[4] = {1.0, 1.0, 1.0, 1.0};
00150     glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor );
00151   }
00152 
00153 
00154   switch(texture_filter_) {
00155     case GL_LINEAR:
00156       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00157       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00158       break;
00159     case GL_LINEAR_MIPMAP_LINEAR:
00160       if (textures_[_id].mipmapAvailable) {
00161         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00162         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
00163         break;
00164       }
00165     default:
00166     case GL_NEAREST:
00167       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
00168       glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
00169       break;
00170 
00171   }
00172 }
00173 
00174 
00175 
00176 
00177 //----------------------------------------------------------------------------
00178 
00179 void TextureNode::setTextureDataGL (  GLuint _textureId,
00180                                       GLenum _target,
00181                                       GLint _width ,
00182                                       GLint _height,
00183                                       GLenum _format ,
00184                                       GLenum _type,
00185                                       const void * _data)
00186 {
00187   applyGLSettings();
00188 
00189   // copy texture to GL
00190   glBindTexture( GL_TEXTURE_2D, textures_[_textureId].id );
00191 
00192   if ( texture_filter_ == GL_LINEAR_MIPMAP_LINEAR )
00193     textures_[_textureId].mipmapAvailable = true;
00194   else
00195     textures_[_textureId].mipmapAvailable = false;
00196 
00197   applyTextureParameters(_textureId);
00198 
00199   // Load the image
00200   if (texture_filter_ == GL_LINEAR_MIPMAP_LINEAR  ) {
00201     gluBuild2DMipmaps( _target ,
00202                        3 ,
00203                        _width ,
00204                        _height ,
00205                        _format ,
00206                        _type,
00207                        _data);
00208 
00209   } else {
00210     glTexImage2D(_target,        // target
00211                   0,                   // level
00212                   GL_RGBA,             // internal format
00213                   _width,              // width  (2^n)
00214                   _height,             // height (2^m)
00215                   0,                   // border
00216                   _format,             // format
00217                   _type,    // type
00218                   _data );    // pointer to pixels
00219   }
00220 
00221 
00222 }
00223 
00224 
00225 
00226 //----------------------------------------------------------------------------
00227 
00228 
00229 void
00230 TextureNode::set_texture(const unsigned char * _image, int _width, int _height)
00231 {
00232   checkEmpty();
00233 
00234   // enough texture mem?
00235   glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
00236   GLint width;
00237   glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width );
00238   if ( width == 0 ) {
00239     std::cerr << "Can't load texture";
00240     return;
00241   }
00242 
00243   setTextureDataGL(activeTexture_,GL_TEXTURE_2D,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,_image);
00244 
00245 }
00246 
00247 
00248 //----------------------------------------------------------------------------
00249 
00250 
00251 void
00252 TextureNode::set_texture(const QImage& _image)
00253 {
00254   checkEmpty();
00255 
00256   int w=_image.width(), h=_image.height();
00257 
00258   // adjust texture size: 2^k * 2^l
00259   GLint tex_w, tex_h;
00260   for ( tex_w=1; tex_w <= w; tex_w <<= 1 ){};
00261   for ( tex_h=1; tex_h <= h; tex_h <<= 1 ){};
00262   tex_w >>= 1;
00263   tex_h >>= 1;
00264 
00265   // enough texture mem?
00266   glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
00267   GLint width;
00268   glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width );
00269   if ( width == 0 ) {
00270     std::cerr << "Can't load texture TextureNode::set_texture" << std::endl;
00271     return;
00272   }
00273 
00274   // Convert Image
00275   QImage texture( QGLWidget::convertToGLFormat ( _image.scaled( tex_w, tex_h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ) );
00276 
00277   // Set the image
00278   setTextureDataGL(activeTexture_,GL_TEXTURE_2D,tex_w,tex_h,GL_RGBA,GL_UNSIGNED_BYTE,texture.bits());
00279 
00280 }
00281 
00282 //----------------------------------------------------------------------------
00283 
00284 
00285 void
00286 TextureNode::set_texture(const float * _image, int _width, int _height )
00287 {
00288   checkEmpty();
00289 
00290   // enough texture mem?
00291   glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_FLOAT, 0 );
00292   GLint width;
00293   glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width );
00294   if ( width == 0 ) {
00295     std::cerr << "Can't load texture TextureNode::set_texture" << std::endl;
00296     return;
00297   }
00298 
00299   // Set the image
00300   setTextureDataGL(activeTexture_,GL_TEXTURE_2D,_width,_height,GL_RGBA,GL_FLOAT,_image);
00301 
00302 }
00303 
00304 //----------------------------------------------------------------------------
00305 
00306 void TextureNode::checkEmpty() {
00307 
00308   // No texture generated yet!
00309   if ( textures_.empty() ) {
00310     textures_.resize(1);
00311     activeTexture_ = 0;
00312 //     textures_[activeTexture_].id = 0;
00313     glGenTextures( 1, &(textures_[activeTexture_].id ) );
00314   }
00315 
00316 }
00317 
00318 //----------------------------------------------------------------------------
00319 
00320 int TextureNode::available( GLuint _id  ) {
00321   // If the texture is found in the array return its id otherwise -1
00322   for ( uint i = 0 ; i < textures_.size(); ++i )
00323     if ( textures_[i].id == _id )
00324       return i;
00325 
00326   return -1;
00327 }
00328 
00329 //----------------------------------------------------------------------------
00330 
00331 bool TextureNode::read(const char* _filename, GLuint _id ) {
00332   if ( available(_id) != -1 ) {
00333     activeTexture_ = available(_id);
00334     return read(_filename);
00335   } else
00336     std::cerr << "Texture with id " << _id << " not handled by this Node!!!" << std::endl;
00337 
00338   return false;
00339 
00340 }
00341 
00342 
00343 //----------------------------------------------------------------------------
00344 
00345 
00346 
00347 void TextureNode::set_texture(const QImage& _image, GLuint _id) {
00348 
00349   checkEmpty();
00350 
00351   if ( available(_id) != -1 ) {
00352     activeTexture_ = available(_id);
00353     set_texture(_image);
00354   } else
00355     std::cerr << "Texture with id " << _id << " not handled by this Node!!!" << std::endl;
00356 
00357 }
00358 
00359 
00360 //----------------------------------------------------------------------------
00361 
00362 
00363 
00364 void TextureNode::set_texture(const float * _image, int _width, int _height, GLuint _id) {
00365 
00366   checkEmpty();
00367 
00368   if ( available(_id) != -1 ) {
00369     activeTexture_ = available(_id);
00370     set_texture(_image,_width,_height);
00371   } else
00372     std::cerr << "Texture with id " << _id << " not handled by this Node!!!" << std::endl;
00373 }
00374 
00375 
00376 
00377 //----------------------------------------------------------------------------
00378 
00379 
00380 void TextureNode::set_texture(const unsigned char * _image, int _width, int _height, GLuint _id) {
00381 
00382   checkEmpty();
00383 
00384   if ( available(_id) != -1 ) {
00385     activeTexture_ = available(_id);
00386     set_texture(_image,_width,_height);
00387 
00388   } else
00389     std::cerr << "Texture with id " << _id << " not handled by this Node!!!" << std::endl;
00390 
00391 }
00392 
00393 
00394 //----------------------------------------------------------------------------
00395 
00396 
00397 // add QImage _image as additional texture, using face_texture_index
00398 GLuint
00399 TextureNode::add_texture(const QImage& _image)
00400 {
00401   checkEmpty();
00402 
00403   // adjust texture size: 2^k * 2^l
00404   int tex_w, w( _image.width()  );
00405   int tex_h, h( _image.height() );
00406 
00407   for (tex_w=1; tex_w < w; tex_w <<= 1) {};
00408   for (tex_h=1; tex_h < h; tex_h <<= 1) {};
00409   if (5 * tex_w > 7 *w)   // tex_w longer than sqrt(2)*w means too much waste of storage space (7/5 = sqrt(2)-1%)
00410     tex_w >>= 1;
00411   if (5 * tex_h > 7 *h)   // tex_h longer than sqrt(2)*h means too much waste of storage space (7/5 = sqrt(2)-1%)
00412     tex_h >>= 1;
00413 
00414   // enough texture mem?
00415   glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
00416   GLint testWidth;
00417   glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &testWidth );
00418   if ( testWidth == 0 ) {
00419     std::cerr << "Can't load texture TextureNode::add_texture" << std::endl;
00420     return 0;  // does not really help
00421   }
00422 
00423   // because texture will only be accessed proportionally by texture coordinates, aspect ratio is of no concern
00424   QImage texture( QGLWidget::convertToGLFormat ( _image.scaled( tex_w, tex_h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ) );
00425 
00426   textures_.resize(textures_.size()+1);  // can't push_back, because glGenTextures needs a pointer
00427 
00428   // Generate new texture
00429   glGenTextures(1, &( textures_.back().id ) );
00430 
00431   activeTexture_ = textures_.size() - 1;
00432 
00433   // Set the image
00434   setTextureDataGL(activeTexture_ ,GL_TEXTURE_2D,tex_w,tex_h,GL_RGBA,GL_UNSIGNED_BYTE,texture.bits());
00435 
00436   // return the id of the new texture
00437   return textures_.back().id;
00438 }
00439 
00440 
00441 //----------------------------------------------------------------------------
00442 
00443 
00444 void TextureNode::enter(GLState& /* _state */ , unsigned int _drawmode)
00445 {
00446    if ( _drawmode & ( DrawModes::SOLID_TEXTURED |
00447                       DrawModes::SOLID_TEXTURED_SHADED |
00448                       DrawModes::SOLID_ENV_MAPPED |
00449                       DrawModes::SOLID_2DTEXTURED_FACE |
00450                       DrawModes::SOLID_2DTEXTURED_FACE_SHADED |
00451                       DrawModes::SOLID_SHADER))
00452    {
00453       glEnable( GL_TEXTURE_2D );
00454       if ( !textures_.empty() ) {
00455         glBindTexture( GL_TEXTURE_2D, textures_[activeTexture_].id );
00456       }
00457       glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_ );
00458    }
00459 }
00460 
00461 
00462 //----------------------------------------------------------------------------
00463 
00464 
00465 void TextureNode::leave(GLState& /* _state */ , unsigned int _drawmode)
00466 {
00467    if ( _drawmode & ( DrawModes::SOLID_TEXTURED |
00468                       DrawModes::SOLID_TEXTURED_SHADED |
00469                       DrawModes::SOLID_ENV_MAPPED |
00470                       DrawModes::SOLID_2DTEXTURED_FACE |
00471                       DrawModes::SOLID_2DTEXTURED_FACE_SHADED |
00472                       DrawModes::SOLID_SHADER))
00473    {
00474       glBindTexture( GL_TEXTURE_2D, 0 );
00475       glDisable( GL_TEXTURE_2D );
00476    }
00477 }
00478 
00479 void TextureNode::enterPick(GLState& /*_state*/ ,
00480                             PickTarget /*_target*/,
00481                             unsigned int /*_drawMode*/ ) {
00482 
00483 }
00484 
00485 void TextureNode::leavePick(GLState& /*_state*/,
00486                             PickTarget /*_target*/,
00487                             unsigned int /*_drawMode*/ ) {
00488 }
00489 
00490 //----------------------------------------------------------------------------
00491 
00492 
00493 GLuint TextureNode::activeTexture()
00494 {
00495   return textures_[activeTexture_].id;
00496 }
00497 
00498 //----------------------------------------------------------------------------
00499 
00500 bool TextureNode::activateTexture(GLuint _id)
00501 {
00502   int search = available(_id);
00503 
00504   //==========================================================================
00505   // If zero is given, unbind all textures
00506   //==========================================================================
00507   if ( _id == 0 ) {
00508     search = 0;
00509   }
00510 
00511   //==========================================================================
00512   // Index has not been found ... No corresponding Texture in this node
00513   //==========================================================================
00514   if ( search == -1 ) {
00515     std::cerr << "Texture to activate not found!" << std::endl;
00516     return false;
00517   }
00518 
00519   activeTexture_ = search;
00520 
00521   return true;
00522 }
00523 
00524 //=============================================================================
00525 } // namespace SceneGraph
00526 } // namespace ACG
00527 //=============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .