Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

texturegl.C

Go to the documentation of this file.
00001 #include "gtex/gl_extensions.H"
00002 #include "texturegl.H"
00003 #include "appear.H"
00004 #include "gl_view.H"
00005 
00006 #include <GL/glu.h>
00007 
00008 using mlib::Wvec;
00009 using mlib::Wtransf;
00010 using mlib::CWtransf;
00011 
00012 static bool debug = Config::get_var_bool("DEBUG_TEXTURE",false);
00013 
00014 
00015 //can be 2D or 3D
00016 TEXTUREgl::TEXTUREgl(GLenum target,GLenum unit):
00017   TEXTURE(""),
00018    _dl(0),
00019    _dl_valid(0),
00020    _format(GL_RGBA),            // reset in load file
00021    _tex_unit(unit),
00022    _save_img(0),
00023    _mipmap(false),              // set to true below
00024    _min_filter(GL_LINEAR_MIPMAP_LINEAR),
00025    _max_filter(GL_LINEAR),
00026    _wrap_r(GL_REPEAT),
00027    _wrap_s(GL_REPEAT),
00028    _wrap_t(GL_REPEAT),
00029    _tex_fn(GL_MODULATE),
00030    _target(target)
00031 {
00032     init_settings();
00033 }
00034 
00035 TEXTUREgl::TEXTUREgl(Cstr_ptr& file, GLenum target) :
00036    TEXTURE(file),
00037    _dl(0),
00038    _dl_valid(0),
00039    _format(GL_RGBA),            // reset in load file
00040    _tex_unit(GL_TEXTURE0),
00041    _save_img(0),
00042    _mipmap(false),              // set to true below
00043    _min_filter(GL_LINEAR_MIPMAP_LINEAR),
00044    _max_filter(GL_LINEAR),
00045    _wrap_r(GL_REPEAT),
00046    _wrap_s(GL_REPEAT),
00047    _wrap_t(GL_REPEAT),
00048    _tex_fn(GL_MODULATE),
00049    _target(target)
00050 {
00051    init_settings();
00052    set_mipmap(true); 
00053 }
00054 
00055 TEXTUREgl::TEXTUREgl(CBBOX2D& bb, CVIEWptr& v) :
00056    TEXTURE(""),
00057    _dl(0),
00058    _dl_valid(0),
00059    _format(GL_RGBA),    // reset in load file
00060    _save_img(0),
00061    _mipmap(false),      // set to true below
00062    _min_filter(GL_LINEAR_MIPMAP_LINEAR),
00063    _max_filter(GL_LINEAR),
00064    _wrap_r(GL_REPEAT),
00065    _wrap_s(GL_REPEAT),
00066    _wrap_t(GL_REPEAT),
00067    _tex_fn(GL_MODULATE),
00068    _target(GL_TEXTURE_2D) 
00069 {
00070    set_mipmap(true);
00071    copy_texture(bb, v);
00072    init_settings();
00073 }
00074 
00075 void
00076 TEXTUREgl::set_mipmap(bool mipmap)   
00077 {
00078    if (mipmap != _mipmap) {
00079       _mipmap = mipmap;
00080       _dl_valid = false; // Invalidate texture object/display list
00081       _min_filter = _mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST;
00082       _max_filter = _mipmap ? GL_LINEAR : GL_NEAREST;
00083       // Only expand image to power of 2 dimensions when not mipmapping
00084       set_expand_image(!_mipmap);
00085    }
00086 }
00087 
00088 /***********************************************************************P5
00089  * Method : TEXTUREgl::load_image
00090  * Params : 
00091  * Returns: int (success/failure)
00092  * Effects: clear the texture object
00093  *          set image from data (not from file)
00094  ***********************************************************************/
00095 int
00096 TEXTUREgl::load_image()
00097 {
00098    err_adv(debug, "TEXTUREgl::load_image (%s)", **_file);
00099    free_dl();
00100    const int retval = TEXTURE::load_image();
00101    _format = bpp_to_format();
00102    return retval;
00103 }
00104 
00105 /***********************************************************************P5
00106  * Method : TEXTUREgl::set_image
00107  * Params : unsigned char *data, int w, int h, uint bpp
00108  * Returns: int (success/failure)
00109  * Effects: clear the texture object
00110  *          set image from data (not from file)
00111  ***********************************************************************/
00112 int
00113 TEXTUREgl::set_image(unsigned char *data, int w, int h, uint bpp)
00114 {
00115    err_adv(debug, "TEXTUREgl::set_image (%s)", **_file);
00116    free_dl();
00117    const int retval = TEXTURE::set_image(data,w,h,bpp);
00118    _format = bpp_to_format();
00119    return retval;
00120 }
00121 
00122 void 
00123 TEXTUREgl::set_texture(Cstr_ptr& filename)
00124 {
00125    // delete current texture (if any) and store the given filename
00126    // as the texture file to load next time we need the data:
00127 
00128    // do nothing if it's the same filename as before
00129    if (filename == _file)
00130       return;
00131 
00132    if (debug) {
00133       cerr << "TEXTUREgl::set_texture: old name: "
00134            << _file
00135            << ", new name: "
00136            << filename << endl;
00137    }
00138 
00139    // free the old texture
00140    free_dl();
00141 
00142    // store the filename to load when needed:
00143    _file = filename;
00144    _image_not_available = false; // becomes true if attempt to load fails
00145 }
00146 
00147 /***********************************************************************
00148  * Method : TEXTUREgl::free_dl
00149  * Params : 
00150  * Returns: void
00151  * Effects: frees the texture object or display list
00152  ***********************************************************************/
00153 void
00154 TEXTUREgl::free_dl()
00155 {
00156    if (_dl) {
00157       err_adv(debug, "TEXTUREgl::free_dl (%s)", **_file);
00158       glDeleteTextures(1, &_dl);
00159       _dl = 0;
00160       _dl_valid = false;
00161    }
00162 }
00163 
00164 /***********************************************************************
00165  * Method : TEXTUREgl::declare_texture
00166  * Params : 
00167  * Returns: void
00168  * Effects: frees the old texture object (if any)
00169  *          creates and binds a texture object (or display list)
00170  ***********************************************************************/
00171 void
00172 TEXTUREgl::declare_texture() 
00173 {
00174    if (!_dl) {
00175       glGenTextures (1, &_dl);
00176       glActiveTexture(_tex_unit);
00177       glBindTexture (_target, _dl);
00178       _dl_valid = (_dl > 0);
00179       err_adv(debug, "TEXTUREgl::declare_texture (%s) %s",
00180               **_file,
00181               _dl_valid ? "succeeded" : "failed");
00182    }
00183 }
00184 
00185 /***********************************************************************
00186  * Method : TEXTUREgl::load_texture
00187  * Params : unsigned char **copy = 0
00188  * Returns: bool (success/failure)
00189  * Effects: if texture object has not been initialized:
00190  *              loads the image from file
00191  *              (makes a copy of the data on request)
00192  *              creates and binds texture object
00193  *              assigns image data to texture object
00194  *              frees the image data.
00195  ***********************************************************************/
00196 bool
00197 TEXTUREgl::load_texture(unsigned char **copy) 
00198 {
00199    // If _dl is set and valid, do nothing
00200    if (_dl && _dl_valid)
00201       return 1;
00202 
00203    // if image is empty and we can't load it, give up:
00204    if (_img.empty() && !load_image()) {
00205       err_adv(debug, "TEXTUREgl::load_texture: error: can't load image (%)",
00206               **_file);
00207       return 0;
00208    }
00209 
00210    err_adv(debug, "TEXTUREgl::load_texture: loading (%s)...", **_file);
00211 
00212    // copy the image data on request:
00213    if (copy)
00214       *copy = _img.copy();
00215 
00216    // create and bind texture object:
00217    declare_texture();
00218 
00219    if (!is_valid()) {
00220       cerr << "TEXTUREgl::load_texture: error: can't generate texture" << endl;
00221       return false;
00222    }
00223 
00224    if (_target == GL_TEXTURE_2D) {
00225       if (_mipmap) {
00226          gluBuild2DMipmaps(_target,
00227                            _img.bpp(),
00228                            _img.width(),
00229                            _img.height(),
00230                            format(),
00231                            GL_UNSIGNED_BYTE,
00232                            _img.data()
00233                           );
00234       } else {
00235          glTexImage2D(_target,
00236                       0,                // mipmap level
00237                       _img.bpp(),
00238                       _img.width(),     // width
00239                       _img.height(),    // height
00240                       0,                // no border
00241                       format(),         // GL_RGB, GL_RGBA, etc.
00242                       GL_UNSIGNED_BYTE, // type of each color component
00243                       _img.data()       // image data
00244                      );
00245       }
00246    } else {
00247       glTexImage1D(_target,
00248                    0,                // mipmap level
00249                    _img.bpp(),
00250                    _img.width(),     // width
00251                    0,                // no border
00252                    format(),         // GL_RGB, GL_RGBA, etc.
00253                    GL_UNSIGNED_BYTE, // type of each color component
00254                    _img.data()       // image data
00255                   );
00256    }
00257 
00258    // the image is now saved in the texture object (or display list)
00259    // we can free the image data
00260    if (!_save_img)
00261       _img.freedata();
00262  
00263    return is_valid();
00264 }
00265 
00266 inline GLenum
00267 gltex_enum(CTEXTUREptr &t) 
00268 {
00269    return (t->dimension() == 2 ? GL_TEXTURE_2D :
00270            t->dimension() == 3 ? GL_TEXTURE_3D :
00271            GL_TEXTURE_1D);
00272 }
00273 
00274 /***********************************************************************
00275  * Method : TEXTUREgl::apply_texture
00276  * Params : 
00277  * Returns: void
00278  * Effects: Make my texture the current texture
00279  ***********************************************************************/
00280 void
00281 TEXTUREgl::apply_texture(CWtransf *xf)
00282 {
00283    // load image data into texture if needed:
00284    load_texture();
00285 
00286    // press on even if that failed
00287    // (some textures don't load from file...)
00288 
00289    // ensure we get a texture object:
00290    declare_texture(); // no-op if load texture worked; otherwise create one
00291    if (!is_valid()) { // ensure texture object is valid
00292       cerr << "TEXTUREgl::apply_texture: error: can't generate texture"
00293            << endl;
00294       return;
00295    }
00296 
00297    // Make the texture the current texture
00298    glActiveTexture(_tex_unit);
00299    glBindTexture (_target, _dl);
00300 
00301    // set texture parameters
00302    glTexParameteri(_target, GL_TEXTURE_MIN_FILTER, _min_filter);
00303    glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, _max_filter);
00304    glTexParameteri(_target, GL_TEXTURE_WRAP_R, _wrap_r);
00305    glTexParameteri(_target, GL_TEXTURE_WRAP_S, _wrap_s);
00306    glTexParameteri(_target, GL_TEXTURE_WRAP_T, _wrap_t);
00307 
00308    static GLfloat color[4] = {1,1,1,0};
00309    glTexParameterfv(_target, GL_TEXTURE_BORDER_COLOR, color);
00310 
00311    // set texture function (GL_REPLACE, GL_DECAL, etc.)cd 
00312    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, _tex_fn);
00313 
00314    // Set up the texture matrix
00315    glPushAttrib(GL_TRANSFORM_BIT); // save current matrix mode
00316    glMatrixMode(GL_TEXTURE);
00317    glLoadMatrixd((xf ? (_scale * (*xf)) : _scale).transpose().matrix());
00318    glPopAttrib();                  // restore previous matrix mode
00319 
00320    // enable the texture:
00321    glEnable(gltex_enum(this));  // GL_ENABLE_BIT
00322 }
00323 
00324 /***********************************************************************
00325  * Method : TEXTUREgl::copy_texture
00326  * Params : CBBOX2D& bb, CVIEWptr &v
00327  * Returns: void
00328  * Effects: Copies part of the framebuffer as a texture
00329  ***********************************************************************/
00330 void
00331 TEXTUREgl::copy_texture(CBBOX2D& bb, CVIEWptr &v) 
00332 {
00333    int width, height;
00334    assert(_target == GL_TEXTURE_2D);
00335    v->get_size(width, height);
00336    int orig_width = (int) (bb.dim()[0] * width  / 2.0);
00337    int orig_height= (int) (bb.dim()[1] * height / 2.0);
00338    width  = getPower2Size(orig_width);
00339    height = getPower2Size(orig_height);
00340    
00341    _scale = Wtransf::scaling(Wvec((double)width/orig_width,
00342                                     (double)height/orig_height,
00343                                     1));
00344    glReadBuffer(GL_BACK);
00345 
00346    declare_texture();
00347 
00348    int x = int((bb.min()[0] + 1.0) * width  / 2.0); // X start
00349    int y = int((bb.min()[1] + 1.0) * height / 2.0); // Y start
00350    cerr << x << " " << y << " " << width << " " << height << "\n";
00351    glCopyTexImage2D(_target,
00352                     0,                                  // mip map level
00353                     GL_RGB,
00354                     x,
00355                     y,
00356                     width,
00357                     height,
00358                     0);                                 // no border
00359 
00360    _save_img = false;
00361    _img.clear();
00362 }
00363 
00364 void
00365 TEXTUREgl::init_settings()
00366 {
00367    _min_filter = GL_LINEAR_MIPMAP_LINEAR;
00368    _max_filter = GL_LINEAR;
00369    _wrap_r = GL_REPEAT;
00370    _wrap_s = GL_REPEAT;
00371    _wrap_t = GL_REPEAT;
00372    _tex_fn = GL_MODULATE;
00373 }
00374 
00375 /* end of file texturegl.C */

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4