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
00016 TEXTUREgl::TEXTUREgl(GLenum target,GLenum unit):
00017 TEXTURE(""),
00018 _dl(0),
00019 _dl_valid(0),
00020 _format(GL_RGBA),
00021 _tex_unit(unit),
00022 _save_img(0),
00023 _mipmap(false),
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),
00040 _tex_unit(GL_TEXTURE0),
00041 _save_img(0),
00042 _mipmap(false),
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),
00060 _save_img(0),
00061 _mipmap(false),
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;
00081 _min_filter = _mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST;
00082 _max_filter = _mipmap ? GL_LINEAR : GL_NEAREST;
00083
00084 set_expand_image(!_mipmap);
00085 }
00086 }
00087
00088
00089
00090
00091
00092
00093
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
00106
00107
00108
00109
00110
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
00126
00127
00128
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
00140 free_dl();
00141
00142
00143 _file = filename;
00144 _image_not_available = false;
00145 }
00146
00147
00148
00149
00150
00151
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
00166
00167
00168
00169
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
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 bool
00197 TEXTUREgl::load_texture(unsigned char **copy)
00198 {
00199
00200 if (_dl && _dl_valid)
00201 return 1;
00202
00203
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
00213 if (copy)
00214 *copy = _img.copy();
00215
00216
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,
00237 _img.bpp(),
00238 _img.width(),
00239 _img.height(),
00240 0,
00241 format(),
00242 GL_UNSIGNED_BYTE,
00243 _img.data()
00244 );
00245 }
00246 } else {
00247 glTexImage1D(_target,
00248 0,
00249 _img.bpp(),
00250 _img.width(),
00251 0,
00252 format(),
00253 GL_UNSIGNED_BYTE,
00254 _img.data()
00255 );
00256 }
00257
00258
00259
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
00276
00277
00278
00279
00280 void
00281 TEXTUREgl::apply_texture(CWtransf *xf)
00282 {
00283
00284 load_texture();
00285
00286
00287
00288
00289
00290 declare_texture();
00291 if (!is_valid()) {
00292 cerr << "TEXTUREgl::apply_texture: error: can't generate texture"
00293 << endl;
00294 return;
00295 }
00296
00297
00298 glActiveTexture(_tex_unit);
00299 glBindTexture (_target, _dl);
00300
00301
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
00312 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, _tex_fn);
00313
00314
00315 glPushAttrib(GL_TRANSFORM_BIT);
00316 glMatrixMode(GL_TEXTURE);
00317 glLoadMatrixd((xf ? (_scale * (*xf)) : _scale).transpose().matrix());
00318 glPopAttrib();
00319
00320
00321 glEnable(gltex_enum(this));
00322 }
00323
00324
00325
00326
00327
00328
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);
00349 int y = int((bb.min()[1] + 1.0) * height / 2.0);
00350 cerr << x << " " << y << " " << width << " " << height << "\n";
00351 glCopyTexImage2D(_target,
00352 0,
00353 GL_RGB,
00354 x,
00355 y,
00356 width,
00357 height,
00358 0);
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