goat3dgfx

annotate src/texture.cc @ 33:253542d715f4

default texture
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Mar 2014 06:32:37 +0200
parents dc5918c62a64
children
rev   line source
nuclear@9 1 #include <math.h>
nuclear@0 2 #include "texture.h"
nuclear@0 3 #include "image.h"
nuclear@0 4 #include "opengl.h"
nuclear@0 5 #include "imago2.h"
nuclear@0 6 #include "logger.h"
nuclear@0 7 #include "datapath.h"
nuclear@0 8
nuclear@15 9 using namespace goatgfx;
nuclear@15 10
nuclear@0 11 static int glifmt_from_ifmt(unsigned int ifmt);
nuclear@0 12 static int glfmt_from_ifmt(unsigned int ifmt);
nuclear@0 13 static int gltype_from_ifmt(unsigned int ifmt);
nuclear@0 14
nuclear@0 15 static int glifmt_from_imgfmt(Image::Format fmt);
nuclear@0 16
nuclear@24 17 static unsigned int type_to_target(TextureType type);
nuclear@24 18 static TextureType target_to_type(unsigned int targ);
nuclear@24 19
nuclear@0 20 static unsigned int cur_target[8] = {
nuclear@0 21 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D,
nuclear@0 22 GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D, GL_TEXTURE_2D
nuclear@0 23 };
nuclear@0 24
nuclear@24 25 static unsigned int cube_faces[] = {
nuclear@24 26 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
nuclear@24 27 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
nuclear@24 28 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
nuclear@24 29 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
nuclear@24 30 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
nuclear@24 31 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
nuclear@24 32 };
nuclear@15 33
nuclear@24 34
nuclear@24 35 void goatgfx::bind_texture(Texture *tex, int tunit)
nuclear@0 36 {
nuclear@0 37 if(tex) {
nuclear@0 38 tex->bind(tunit);
nuclear@0 39 } else {
nuclear@0 40 glActiveTexture(GL_TEXTURE0 + tunit);
nuclear@0 41 glBindTexture(cur_target[tunit], 0);
nuclear@0 42 glActiveTexture(GL_TEXTURE0);
nuclear@0 43 }
nuclear@0 44 }
nuclear@0 45
nuclear@33 46
nuclear@33 47 Image *Texture::default_img;
nuclear@33 48
nuclear@0 49 Texture::Texture()
nuclear@0 50 {
nuclear@0 51 target = 0;
nuclear@0 52 sz[0] = sz[1] = sz[2] = 0;
nuclear@0 53 texfmt = 0;
nuclear@0 54
nuclear@24 55 img = 0;
nuclear@0 56 glGenTextures(1, &id);
nuclear@0 57 }
nuclear@0 58
nuclear@0 59 Texture::~Texture()
nuclear@0 60 {
nuclear@0 61 if(id) {
nuclear@0 62 glDeleteTextures(1, &id);
nuclear@0 63 }
nuclear@24 64 if(img) {
nuclear@24 65 delete img;
nuclear@24 66 }
nuclear@0 67 }
nuclear@0 68
nuclear@0 69 void Texture::set_wrapping(unsigned int wrap)
nuclear@0 70 {
nuclear@0 71 if(!target) {
nuclear@0 72 return;
nuclear@0 73 }
nuclear@0 74
nuclear@0 75 glBindTexture(target, id);
nuclear@0 76 glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
nuclear@0 77 glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
nuclear@24 78 glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap);
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 void Texture::set_filtering(unsigned int filt)
nuclear@0 82 {
nuclear@0 83 unsigned int mag_filter;
nuclear@0 84
nuclear@0 85 if(!target) {
nuclear@0 86 return;
nuclear@0 87 }
nuclear@0 88
nuclear@0 89 switch(filt) {
nuclear@0 90 case GL_LINEAR_MIPMAP_NEAREST:
nuclear@0 91 case GL_LINEAR_MIPMAP_LINEAR:
nuclear@0 92 mag_filter = GL_LINEAR;
nuclear@0 93 break;
nuclear@0 94
nuclear@0 95 case GL_NEAREST_MIPMAP_NEAREST:
nuclear@0 96 case GL_NEAREST_MIPMAP_LINEAR:
nuclear@0 97 mag_filter = GL_NEAREST;
nuclear@0 98 break;
nuclear@0 99
nuclear@0 100 default:
nuclear@0 101 mag_filter = filt;
nuclear@0 102 }
nuclear@0 103
nuclear@0 104 set_filtering(filt, mag_filter);
nuclear@0 105 }
nuclear@0 106
nuclear@0 107 void Texture::set_filtering(unsigned int min_filt, unsigned int mag_filt)
nuclear@0 108 {
nuclear@0 109 glBindTexture(target, id);
nuclear@0 110 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filt);
nuclear@0 111 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filt);
nuclear@0 112 }
nuclear@0 113
nuclear@0 114 unsigned int Texture::get_format() const
nuclear@0 115 {
nuclear@0 116 return texfmt;
nuclear@0 117 }
nuclear@0 118
nuclear@0 119 int Texture::get_size(int dim) const
nuclear@0 120 {
nuclear@0 121 if(dim < 0 || dim >= 3) {
nuclear@0 122 return 0;
nuclear@0 123 }
nuclear@0 124 return sz[dim];
nuclear@0 125 }
nuclear@0 126
nuclear@0 127 unsigned int Texture::get_id() const
nuclear@0 128 {
nuclear@0 129 return id;
nuclear@0 130 }
nuclear@0 131
nuclear@24 132 TextureType Texture::get_type() const
nuclear@24 133 {
nuclear@24 134 return target_to_type(target);
nuclear@24 135 }
nuclear@24 136
nuclear@0 137 void Texture::bind(int tex_unit) const
nuclear@0 138 {
nuclear@0 139 glActiveTexture(GL_TEXTURE0 + tex_unit);
nuclear@0 140 glBindTexture(target, id);
nuclear@0 141 glActiveTexture(GL_TEXTURE0);
nuclear@0 142
nuclear@0 143 cur_target[tex_unit] = target;
nuclear@0 144 }
nuclear@0 145
nuclear@0 146
nuclear@24 147 void Texture::create(int xsz, int ysz, TextureType textype, unsigned int ifmt)
nuclear@24 148 {
nuclear@24 149 if(textype == TEX_CUBE && xsz != ysz) {
nuclear@24 150 error_log("trying to create cubemap with different width and height (%dx%d)\n", xsz, ysz);
nuclear@24 151 return;
nuclear@24 152 }
nuclear@0 153
nuclear@0 154 int fmt = glfmt_from_ifmt(ifmt);
nuclear@0 155 int type = gltype_from_ifmt(ifmt);
nuclear@0 156
nuclear@24 157 target = type_to_target(textype);
nuclear@24 158
nuclear@24 159 glBindTexture(target, id);
nuclear@24 160 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@24 161 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@24 162
nuclear@24 163 switch(type) {
nuclear@24 164 case TEX_2D:
nuclear@24 165 glTexImage2D(GL_TEXTURE_2D, 0, glifmt_from_ifmt(ifmt), xsz, ysz, 0, fmt, type, 0);
nuclear@24 166 break;
nuclear@24 167
nuclear@24 168 case TEX_CUBE:
nuclear@24 169 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
nuclear@24 170 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
nuclear@24 171 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
nuclear@24 172 for(int i=0; i<6; i++) {
nuclear@24 173 glTexImage2D(cube_faces[i], 0, ifmt, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
nuclear@24 174 }
nuclear@24 175 break;
nuclear@24 176 }
nuclear@24 177
nuclear@0 178 CHECKGLERR;
nuclear@0 179 sz[0] = xsz;
nuclear@0 180 sz[1] = ysz;
nuclear@0 181 texfmt = ifmt;
nuclear@0 182 }
nuclear@0 183
nuclear@33 184 #define DEF_IMAGE_SIZE 64
nuclear@33 185 void Texture::create_default(TextureType type)
nuclear@33 186 {
nuclear@33 187 if(!default_img) {
nuclear@33 188 default_img = new Image;
nuclear@33 189 default_img->create(DEF_IMAGE_SIZE, DEF_IMAGE_SIZE, Image::FMT_RGBA);
nuclear@33 190
nuclear@33 191 unsigned char *pixels = (unsigned char*)default_img->get_pixels();
nuclear@33 192 for(int i=0; i<DEF_IMAGE_SIZE; i++) {
nuclear@33 193 for(int j=0; j<DEF_IMAGE_SIZE; j++) {
nuclear@33 194 bool chess = ((i >> 3) & 1) == ((j >> 3) & 1);
nuclear@33 195 pixels[0] = chess ? 255 : 32;
nuclear@33 196 pixels[1] = 64;
nuclear@33 197 pixels[2] = chess ? 32 : 255;
nuclear@33 198 pixels[3] = 255;
nuclear@33 199 }
nuclear@33 200 }
nuclear@33 201 }
nuclear@33 202
nuclear@33 203 switch(type) {
nuclear@33 204 case TEX_2D:
nuclear@33 205 set_image(*default_img);
nuclear@33 206 break;
nuclear@33 207
nuclear@33 208 case TEX_CUBE:
nuclear@33 209 for(int i=0; i<6; i++) {
nuclear@33 210 set_image(*default_img, i);
nuclear@33 211 }
nuclear@33 212 break;
nuclear@33 213 }
nuclear@33 214 }
nuclear@33 215
nuclear@24 216 void Texture::set_image(const Image &img, int idx)
nuclear@24 217 {
nuclear@24 218 if(idx >= 0 && idx < 6) {
nuclear@24 219 set_image_cube(img, idx);
nuclear@24 220 } else {
nuclear@24 221 if(!set_image_cube(img)) {
nuclear@24 222 set_image_2d(img);
nuclear@24 223 }
nuclear@24 224 }
nuclear@24 225 }
nuclear@24 226
nuclear@24 227 void Texture::set_image_2d(const Image &img)
nuclear@0 228 {
nuclear@0 229 texfmt = glifmt_from_imgfmt(img.get_format());
nuclear@0 230 unsigned int fmt = glfmt_from_ifmt(texfmt);
nuclear@0 231 unsigned int type = gltype_from_ifmt(texfmt);
nuclear@0 232
nuclear@0 233 sz[0] = img.get_width();
nuclear@0 234 sz[1] = img.get_height();
nuclear@0 235
nuclear@0 236 glBindTexture(GL_TEXTURE_2D, id);
nuclear@0 237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
nuclear@0 238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@0 239 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
nuclear@0 240 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
nuclear@0 241
nuclear@0 242 #ifdef __GLEW_H__
nuclear@0 243 if(GLEW_SGIS_generate_mipmap) {
nuclear@0 244 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
nuclear@0 245 #endif
nuclear@0 246 glTexImage2D(GL_TEXTURE_2D, 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
nuclear@0 247 #ifdef __GLEW_H__
nuclear@0 248 } else {
nuclear@0 249 gluBuild2DMipmaps(GL_TEXTURE_2D, texfmt, sz[0], sz[1], fmt, type, img.get_pixels());
nuclear@0 250 }
nuclear@0 251 #endif
nuclear@0 252
nuclear@0 253 #ifdef GL_ES_VERSION_2_0
nuclear@0 254 glGenerateMipmap(GL_TEXTURE_2D);
nuclear@0 255 #endif
nuclear@0 256 }
nuclear@0 257
nuclear@24 258 bool Texture::set_image_cube(const Image &img, int idx)
nuclear@0 259 {
nuclear@24 260 if(idx < 0 || idx >= 6) {
nuclear@0 261 return false;
nuclear@0 262 }
nuclear@0 263
nuclear@6 264 texfmt = glifmt_from_imgfmt(img.get_format());
nuclear@6 265 unsigned int fmt = glfmt_from_ifmt(texfmt);
nuclear@6 266 unsigned int type = gltype_from_ifmt(texfmt);
nuclear@6 267
nuclear@6 268 sz[0] = img.get_width();
nuclear@6 269 sz[1] = img.get_height();
nuclear@6 270
nuclear@6 271 glBindTexture(GL_TEXTURE_CUBE_MAP, id);
nuclear@6 272 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@6 273 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@6 274 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
nuclear@6 275 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
nuclear@9 276 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
nuclear@6 277
nuclear@6 278 glTexImage2D(cube_faces[idx], 0, texfmt, sz[0], sz[1], 0, fmt, type, img.get_pixels());
nuclear@24 279 return true;
nuclear@0 280 }
nuclear@0 281
nuclear@24 282 bool Texture::set_image_cube(const Image &img)
nuclear@0 283 {
nuclear@6 284 static const float one_third = 1.0 / 3.0;
nuclear@6 285 static const float two_thirds = 2.0 / 3.0;
nuclear@6 286 static const float hcross[2][6] = {
nuclear@6 287 {0.5, 0.0, 0.25, 0.25, 0.25, 0.75}, {one_third, one_third, 0.0, two_thirds, one_third, one_third} };
nuclear@6 288 static const float vcross[2][6] = {
nuclear@6 289 {two_thirds, 0.0, one_third, one_third, one_third, one_third}, {0.25, 0.25, 0.0, 0.5, 0.25, 0.75} };
nuclear@6 290 static const float hsix[2][6] = {
nuclear@6 291 {0.0, 0.0, one_third, one_third, two_thirds, two_thirds}, {0.0, 0.5, 0.0, 0.5, 0.0, 0.5} };
nuclear@6 292
nuclear@6 293 int xsz = img.get_width();
nuclear@6 294 int ysz = img.get_height();
nuclear@6 295
nuclear@6 296 if(xsz / 4 == ysz / 3) {
nuclear@6 297 // horizontal cross, assume the vertical bit is center-left
nuclear@24 298 return set_cube_multi(img, hcross[0], hcross[1], xsz / 4);
nuclear@6 299 }
nuclear@6 300 if(xsz / 3 == ysz / 4) {
nuclear@6 301 // vertical cross, assume the horizontal bit is center-top (180-rotated image 5)
nuclear@24 302 return set_cube_multi(img, vcross[0], vcross[1], ysz / 4, (1 << 5));
nuclear@6 303 }
nuclear@6 304 if(xsz / 3 == ysz / 2) {
nuclear@6 305 // horizontal sixpack
nuclear@24 306 return set_cube_multi(img, hsix[0], hsix[1], ysz / 2);
nuclear@6 307 }
nuclear@6 308
nuclear@6 309 return false;
nuclear@0 310 }
nuclear@0 311
nuclear@24 312
nuclear@24 313 bool Texture::load(const char *fname)
nuclear@0 314 {
nuclear@24 315 Image img;
nuclear@24 316 if(!img.load(fname)) {
nuclear@24 317 error_log("failed to load 2D texture: %s\n", fname);
nuclear@24 318 return false;
nuclear@24 319 }
nuclear@24 320 set_image(img);
nuclear@24 321
nuclear@24 322 info_log("loaded 2D texture: %s\n", fname);
nuclear@24 323 return true;
nuclear@0 324 }
nuclear@0 325
nuclear@24 326 bool Texture::load_cube(const char *fname)
nuclear@24 327 {
nuclear@24 328 Image img;
nuclear@24 329 if(!img.load(fname)) {
nuclear@24 330 return false;
nuclear@24 331 }
nuclear@24 332 return set_image_cube(img);
nuclear@24 333 }
nuclear@24 334
nuclear@24 335 bool Texture::set_cube_multi(const Image &img, const float *xoffsets, const float *yoffsets, float sz,
nuclear@6 336 unsigned int rotmask)
nuclear@6 337 {
nuclear@6 338 for(int i=0; i<6; i++) {
nuclear@6 339 Image face;
nuclear@6 340
nuclear@6 341 int xoffs = xoffsets[i] * img.get_width();
nuclear@6 342 int yoffs = yoffsets[i] * img.get_height();
nuclear@6 343
nuclear@6 344 if(!face.set_pixels(sz, sz, img.get_pixels(), xoffs, yoffs, img.get_width(), img.get_format())) {
nuclear@6 345 return false;
nuclear@6 346 }
nuclear@6 347
nuclear@6 348 if(rotmask & (1 << i)) {
nuclear@6 349 face.rotate_180();
nuclear@6 350 }
nuclear@24 351 set_image_cube(face, i);
nuclear@6 352 }
nuclear@6 353 return true;
nuclear@6 354 }
nuclear@6 355
nuclear@0 356 static int glifmt_from_ifmt(unsigned int ifmt)
nuclear@0 357 {
nuclear@0 358 #ifdef GL_ES_VERSION_2_0
nuclear@0 359 switch(ifmt) {
nuclear@0 360 case GL_LUMINANCE16F:
nuclear@0 361 case GL_LUMINANCE32F:
nuclear@0 362 ifmt = GL_LUMINANCE;
nuclear@0 363 break;
nuclear@0 364
nuclear@0 365 case GL_RGB16F:
nuclear@0 366 case GL_RGB32F:
nuclear@0 367 ifmt = GL_RGB;
nuclear@0 368 break;
nuclear@0 369
nuclear@0 370 case GL_RGBA16F:
nuclear@0 371 case GL_RGBA32F:
nuclear@0 372 ifmt = GL_RGBA;
nuclear@0 373 break;
nuclear@0 374
nuclear@0 375 default:
nuclear@0 376 break;
nuclear@0 377 }
nuclear@0 378 #endif
nuclear@0 379 return ifmt; // by default just pass it through...
nuclear@0 380 }
nuclear@0 381
nuclear@0 382 static int glfmt_from_ifmt(unsigned int ifmt)
nuclear@0 383 {
nuclear@0 384 switch(ifmt) {
nuclear@0 385 case GL_LUMINANCE16F:
nuclear@0 386 case GL_LUMINANCE32F:
nuclear@0 387 return GL_LUMINANCE;
nuclear@0 388
nuclear@0 389 case GL_RGB16F:
nuclear@0 390 case GL_RGB32F:
nuclear@0 391 return GL_RGB;
nuclear@0 392
nuclear@0 393 case GL_RGBA16F:
nuclear@0 394 case GL_RGBA32F:
nuclear@0 395 return GL_RGBA;
nuclear@0 396
nuclear@0 397 default:
nuclear@0 398 break;
nuclear@0 399 }
nuclear@0 400 return ifmt;
nuclear@0 401 }
nuclear@0 402
nuclear@0 403 static int gltype_from_ifmt(unsigned int ifmt)
nuclear@0 404 {
nuclear@0 405 switch(ifmt) {
nuclear@0 406 case GL_RGB16F:
nuclear@0 407 case GL_RGBA16F:
nuclear@0 408 case GL_LUMINANCE16F:
nuclear@0 409 #ifdef GL_ES_VERSION_2_0
nuclear@0 410 return GL_HALF_FLOAT_OES;
nuclear@0 411 #endif
nuclear@0 412 case GL_RGB32F:
nuclear@0 413 case GL_RGBA32F:
nuclear@0 414 case GL_LUMINANCE32F:
nuclear@0 415 return GL_FLOAT;
nuclear@0 416
nuclear@0 417 default:
nuclear@0 418 break;
nuclear@0 419 }
nuclear@0 420 return GL_UNSIGNED_BYTE;
nuclear@0 421 }
nuclear@0 422
nuclear@0 423 static int glifmt_from_imgfmt(Image::Format fmt)
nuclear@0 424 {
nuclear@0 425 switch(fmt) {
nuclear@0 426 case Image::FMT_GREY:
nuclear@0 427 return GL_LUMINANCE;
nuclear@0 428 case Image::FMT_GREY_FLOAT:
nuclear@0 429 return GL_LUMINANCE16F;
nuclear@0 430 case Image::FMT_RGB:
nuclear@0 431 return GL_RGB;
nuclear@0 432 case Image::FMT_RGB_FLOAT:
nuclear@0 433 return GL_RGB16F;
nuclear@0 434 case Image::FMT_RGBA:
nuclear@0 435 return GL_RGBA;
nuclear@0 436 case Image::FMT_RGBA_FLOAT:
nuclear@0 437 return GL_RGBA16F;
nuclear@0 438 default:
nuclear@0 439 break;
nuclear@0 440 }
nuclear@0 441 return 0;
nuclear@0 442 }
nuclear@0 443
nuclear@24 444 static unsigned int type_to_target(TextureType type)
nuclear@24 445 {
nuclear@24 446 return type == TEX_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
nuclear@24 447 }
nuclear@24 448
nuclear@24 449 static TextureType target_to_type(unsigned int targ)
nuclear@24 450 {
nuclear@24 451 return targ == GL_TEXTURE_CUBE_MAP ? TEX_CUBE : TEX_2D;
nuclear@24 452 }
nuclear@24 453
nuclear@0 454 // ---- TextureSet ----
nuclear@24 455 TextureSet::TextureSet()
nuclear@24 456 : DataSet<Texture*>(create_tex, load_tex, done_tex, free_tex)
nuclear@24 457 {
nuclear@24 458 }
nuclear@24 459
nuclear@33 460 Texture *TextureSet::get_texture(const char *name, TextureType type) const
nuclear@33 461 {
nuclear@33 462 typename std::map<std::string, Texture*>::const_iterator iter = data.find(name);
nuclear@33 463 if(iter != data.end()) {
nuclear@33 464 return iter->second;
nuclear@33 465 }
nuclear@33 466
nuclear@33 467 const char *fname, *slash;
nuclear@33 468 if((slash = strrchr(name, '/'))) {
nuclear@33 469 fname = slash + 1;
nuclear@33 470 } else {
nuclear@33 471 fname = name;
nuclear@33 472 }
nuclear@33 473
nuclear@33 474 std::string path = datafile_path(fname);
nuclear@33 475 if(path.empty()) {
nuclear@33 476 fprintf(stderr, "can't find data file: %s\n", name);
nuclear@33 477 return 0;
nuclear@33 478 }
nuclear@33 479
nuclear@33 480 Texture *res = create();
nuclear@33 481 res->create_default(type);
nuclear@33 482 resman_lookup(rman, path.c_str(), res);
nuclear@33 483 return res;
nuclear@33 484 }
nuclear@33 485
nuclear@24 486 // static callbacks
nuclear@24 487
nuclear@24 488 Texture *TextureSet::create_tex()
nuclear@24 489 {
nuclear@24 490 return new Texture;
nuclear@24 491 }
nuclear@24 492
nuclear@24 493 bool TextureSet::load_tex(Texture *tex, const char *fname)
nuclear@24 494 {
nuclear@24 495 Image *img = new Image;
nuclear@24 496 if(!img->load(fname)) {
nuclear@24 497 delete img;
nuclear@24 498 return false;
nuclear@24 499 }
nuclear@24 500
nuclear@24 501 delete tex->img;
nuclear@24 502 tex->img = img;
nuclear@24 503
nuclear@24 504 return true;
nuclear@24 505 }
nuclear@24 506
nuclear@24 507 bool TextureSet::done_tex(Texture *tex)
nuclear@24 508 {
nuclear@24 509 if(!tex->img) {
nuclear@24 510 return false;
nuclear@24 511 }
nuclear@24 512
nuclear@24 513 tex->set_image(*tex->img);
nuclear@24 514 return true;
nuclear@24 515 }
nuclear@24 516
nuclear@24 517 void TextureSet::free_tex(Texture *tex)
nuclear@0 518 {
nuclear@0 519 delete tex;
nuclear@0 520 }