home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / texture.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-01  |  9.6 KB  |  331 lines

  1. // texture.cpp: texture management
  2.  
  3. #include "cube.h"
  4.  
  5. Texture *crosshair = NULL;
  6. hashtable<char *, Texture> textures;
  7.  
  8. VAR(maxtexsize, 0, -1, 4096);
  9.  
  10. void createtexture(int tnum, int w, int h, void *pixels, int clamp, bool mipmap, GLenum format)
  11. {
  12.     glBindTexture(GL_TEXTURE_2D, tnum);
  13.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  14.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp&1 ? GL_CLAMP_TO_EDGE : GL_REPEAT);
  15.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp&2 ? GL_CLAMP_TO_EDGE : GL_REPEAT);
  16.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  17.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
  18.  
  19.     int tw = w, th = h;
  20.     if(maxtexsize<0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&maxtexsize);
  21.     if(maxtexsize) while(tw>maxtexsize || th>maxtexsize) { tw /= 2; th /= 2; }
  22.     if(tw!=w)
  23.     {
  24.         if(gluScaleImage(format, w, h, GL_UNSIGNED_BYTE, pixels, tw, th, GL_UNSIGNED_BYTE, pixels))
  25.         {
  26.             tw = w;
  27.             th = h;
  28.         }
  29.     }
  30.     if(mipmap)
  31.     {
  32.         if(gluBuild2DMipmaps(GL_TEXTURE_2D, format, tw, th, format, GL_UNSIGNED_BYTE, pixels)) fatal("could not build mipmaps");
  33.     }
  34.     else glTexImage2D(GL_TEXTURE_2D, 0, format, tw, th, 0, format, GL_UNSIGNED_BYTE, pixels);
  35. }
  36.  
  37. GLuint loadsurface(const char *texname, int &xs, int &ys, int clamp)
  38. {
  39.     SDL_Surface *s = IMG_Load(texname);
  40.     if(!s) { conoutf("couldn't load texture %s", texname); return 0; }
  41.     if(s->format->BitsPerPixel!=24 && s->format->BitsPerPixel!=32)
  42.     {
  43.         SDL_FreeSurface(s);
  44.         conoutf("texture must be 24bpp or 32bpp: %s", texname);
  45.         return 0;
  46.     }
  47.     GLuint tnum;
  48.     glGenTextures(1, &tnum);
  49.     createtexture(tnum, s->w, s->h, s->pixels, clamp, true, s->format->BitsPerPixel==24 ? GL_RGB : GL_RGBA);
  50.     xs = s->w;
  51.     ys = s->h;
  52.     SDL_FreeSurface(s);
  53.     return tnum;
  54. }
  55.  
  56. // management of texture slots
  57. // each texture slot can have multople texture frames, of which currently only the first is used
  58. // additional frames can be used for various shaders
  59.  
  60. Texture *textureload(const char *name, int clamp)
  61. {   
  62.     string pname;
  63.     s_strcpy(pname, name);
  64.     path(pname); 
  65.     Texture *t = textures.access(pname);
  66.     if(t) return t;
  67.     int xs, ys; 
  68.     GLuint id = loadsurface(pname, xs, ys, clamp);
  69.     if(!id) return crosshair;
  70.     char *key = newstring(pname);
  71.     t = &textures[key];
  72.     t->name = key;
  73.     t->xs = xs;
  74.     t->ys = ys;
  75.     t->id = id;
  76.     return t;
  77. }
  78.  
  79. struct Slot
  80. {   
  81.     string name;
  82.     Texture *tex;
  83.     bool loaded;
  84. };  
  85.  
  86. vector<Slot> slots;
  87.  
  88. void texturereset() { slots.setsizenodelete(0); }
  89.  
  90. void texture(char *aframe, char *name)
  91. {
  92.     Slot &s = slots.add();
  93.     s_strcpy(s.name, name);
  94.     path(s.name);
  95.     s.tex = NULL;
  96.     s.loaded = false;
  97. }
  98.  
  99. COMMAND(texturereset, ARG_NONE);
  100. COMMAND(texture, ARG_2STR);
  101.  
  102. int lookuptexture(int tex, int &xs, int &ys)
  103. {
  104.     Texture *t = crosshair;
  105.     if(slots.inrange(tex))
  106.     {
  107.         Slot &s = slots[tex];
  108.         if(!s.loaded)
  109.         {
  110.             s_sprintfd(pname)("packages/textures/%s", s.name);
  111.             s.tex = textureload(pname);
  112.             s.loaded = true;
  113.         }
  114.         if(s.tex) t = s.tex;
  115.     }
  116.  
  117.     xs = t->xs;
  118.     ys = t->ys;
  119.     return t->id;
  120. }
  121.  
  122. Texture *sky[6] = {NULL, NULL, NULL, NULL, NULL, NULL};
  123.  
  124. void loadsky(char *basename)
  125. {
  126.     char *side[] = { "ft", "bk", "lf", "rt", "dn", "up" };
  127.     loopi(6)
  128.     {
  129.         s_sprintfd(name)("packages/%s_%s.jpg", basename, side[i]);
  130.         sky[i] = textureload(name, 3);
  131.         if(!sky[i]) conoutf("could not load sky texture: %s", name);
  132.     }
  133. }   
  134.  
  135. COMMAND(loadsky, ARG_1STR);
  136.  
  137. void draw_envbox_face(float s0, float t0, int x0, int y0, int z0,
  138.                       float s1, float t1, int x1, int y1, int z1,
  139.                       float s2, float t2, int x2, int y2, int z2,
  140.                       float s3, float t3, int x3, int y3, int z3,
  141.                       Texture *tex)
  142. {
  143.     glBindTexture(GL_TEXTURE_2D, tex->id);
  144.     glBegin(GL_QUADS);
  145.     glTexCoord2f(s3, t3); glVertex3i(x3, y3, z3);
  146.     glTexCoord2f(s2, t2); glVertex3i(x2, y2, z2);
  147.     glTexCoord2f(s1, t1); glVertex3i(x1, y1, z1);
  148.     glTexCoord2f(s0, t0); glVertex3i(x0, y0, z0);
  149.     glEnd();
  150.     xtraverts += 4;
  151. }
  152.  
  153. void draw_envbox(int w)
  154. {
  155.     if(!sky[0]) return;
  156.  
  157.     glDepthMask(GL_FALSE);
  158.  
  159.     draw_envbox_face(1.0f, 1.0f, -w, -w,  w,
  160.                      0.0f, 1.0f,  w, -w,  w,
  161.                      0.0f, 0.0f,  w, -w, -w, 
  162.                      1.0f, 0.0f, -w, -w, -w, sky[0]);
  163.  
  164.     draw_envbox_face(1.0f, 1.0f, +w,  w,  w,
  165.                      0.0f, 1.0f, -w,  w,  w,
  166.                      0.0f, 0.0f, -w,  w, -w, 
  167.                      1.0f, 0.0f, +w,  w, -w, sky[1]);
  168.  
  169.     draw_envbox_face(0.0f, 0.0f, -w, -w, -w,
  170.                      1.0f, 0.0f, -w,  w, -w,
  171.                      1.0f, 1.0f, -w,  w,  w, 
  172.                      0.0f, 1.0f, -w, -w,  w, sky[2]);
  173.  
  174.     draw_envbox_face(1.0f, 1.0f, +w, -w,  w,
  175.                      0.0f, 1.0f, +w,  w,  w,
  176.                      0.0f, 0.0f, +w,  w, -w, 
  177.                      1.0f, 0.0f, +w, -w, -w, sky[3]);
  178.  
  179.     draw_envbox_face(0.0f, 1.0f, -w,  w,  w,
  180.                      0.0f, 0.0f, +w,  w,  w,
  181.                      1.0f, 0.0f, +w, -w,  w, 
  182.                      1.0f, 1.0f, -w, -w,  w, sky[4]);
  183.  
  184.     draw_envbox_face(0.0f, 1.0f, +w,  w, -w,
  185.                      0.0f, 0.0f, -w,  w, -w,
  186.                      1.0f, 0.0f, -w, -w, -w, 
  187.                      1.0f, 1.0f, +w, -w, -w, sky[5]);
  188.  
  189.     glDepthMask(GL_TRUE);
  190. }
  191.  
  192. struct tmufunc
  193. {
  194.     GLenum combine, sources[3], ops[3];
  195.     int scale;
  196. };
  197.  
  198. struct tmu
  199. {
  200.     GLenum mode;
  201.     GLfloat color[4];
  202.     tmufunc rgb, alpha;
  203. };
  204.  
  205. #define INVALIDTMU \
  206. { \
  207.     0, \
  208.     { -1, -1, -1, -1 }, \
  209.     { 0, { 0, 0, 0, }, { 0, 0, 0 }, 0 }, \
  210.     { 0, { 0, 0, 0, }, { 0, 0, 0 }, 0 } \
  211. }
  212.  
  213. #define INITTMU \
  214. { \
  215.     GL_MODULATE, \
  216.     { 0, 0, 0, 0 }, \
  217.     { GL_MODULATE, { GL_TEXTURE, GL_PREVIOUS_ARB, GL_CONSTANT_ARB }, { GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_ALPHA }, 1 }, \
  218.     { GL_MODULATE, { GL_TEXTURE, GL_PREVIOUS_ARB, GL_CONSTANT_ARB }, { GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA }, 1 } \
  219. }
  220.  
  221. tmu tmus[4] =
  222. {
  223.     INVALIDTMU,
  224.     INVALIDTMU,
  225.     INVALIDTMU,
  226.     INVALIDTMU
  227. };
  228.  
  229. VAR(maxtmus, 1, 0, 0);
  230.  
  231. void parsetmufunc(tmufunc &f, const char *s)
  232. {
  233.     int arg = -1;
  234.     while(*s) switch(tolower(*s++))
  235.     {
  236.         case 't': f.sources[++arg] = GL_TEXTURE; f.ops[arg] = GL_SRC_COLOR; break;
  237.         case 'p': f.sources[++arg] = GL_PREVIOUS_ARB; f.ops[arg] = GL_SRC_COLOR; break;
  238.         case 'k': f.sources[++arg] = GL_CONSTANT_ARB; f.ops[arg] = GL_SRC_COLOR; break;
  239.         case 'c': f.sources[++arg] = GL_PRIMARY_COLOR_ARB; f.ops[arg] = GL_SRC_COLOR; break;
  240.         case '~': f.ops[arg] = GL_ONE_MINUS_SRC_COLOR; break;
  241.         case 'a': f.ops[arg] = f.ops[arg]==GL_ONE_MINUS_SRC_COLOR ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA; break;
  242.         case '=': f.combine = GL_REPLACE; break;
  243.         case '*': f.combine = GL_MODULATE; break;
  244.         case '+': f.combine = GL_ADD; break;
  245.         case '-': f.combine = GL_SUBTRACT_ARB; break;
  246.         case ',':
  247.         case '@': f.combine = GL_INTERPOLATE_ARB; break;
  248.         case '.': f.combine = GL_DOT3_RGB_ARB; break;
  249.         case 'x': while(!isdigit(*s)) s++; f.scale = *s++-'0'; break;
  250.     }
  251. }
  252.  
  253. void committmufunc(bool rgb, tmufunc &dst, tmufunc &src)
  254. {
  255.     if(dst.combine!=src.combine) glTexEnvi(GL_TEXTURE_ENV, rgb ? GL_COMBINE_RGB_ARB : GL_COMBINE_ALPHA_ARB, src.combine);
  256.     loopi(3)
  257.     {
  258.         if(dst.sources[i]!=src.sources[i]) glTexEnvi(GL_TEXTURE_ENV, (rgb ? GL_SOURCE0_RGB_ARB : GL_SOURCE0_ALPHA_ARB)+i, src.sources[i]);
  259.         if(dst.ops[i]!=src.ops[i]) glTexEnvi(GL_TEXTURE_ENV, (rgb ? GL_OPERAND0_RGB_ARB : GL_OPERAND0_ALPHA_ARB)+i, src.ops[i]);
  260.     }
  261.     if(dst.scale!=src.scale) glTexEnvi(GL_TEXTURE_ENV, rgb ? GL_RGB_SCALE_ARB : GL_ALPHA_SCALE, src.scale);
  262. }
  263.  
  264. void committmu(int n, tmu &f)
  265. {
  266.     if(n>=maxtmus) return;
  267.     if(tmus[n].mode!=f.mode) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, f.mode);
  268.     if(memcmp(tmus[n].color, f.color, sizeof(f.color))) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, f.color);
  269.     committmufunc(true, tmus[n].rgb, f.rgb);
  270.     committmufunc(false, tmus[n].alpha, f.alpha);
  271.     tmus[n] = f;
  272. }
  273.  
  274. void resettmu(int n)
  275. {
  276.     tmu f = tmus[n];
  277.     f.mode = GL_MODULATE;
  278.     f.rgb.scale = 1;
  279.     f.alpha.scale = 1;
  280.     committmu(n, f);
  281. }
  282.  
  283. void scaletmu(int n, int rgbscale, int alphascale)
  284. {
  285.     tmu f = tmus[n];
  286.     if(rgbscale) f.rgb.scale = rgbscale;
  287.     if(alphascale) f.alpha.scale = alphascale;
  288.     committmu(n, f);
  289. }
  290.  
  291. void colortmu(int n, float r, float g, float b, float a)
  292. {
  293.     tmu f = tmus[n];
  294.     f.color[0] = r;
  295.     f.color[1] = g;
  296.     f.color[2] = b;
  297.     f.color[3] = a;
  298.     committmu(n, f);
  299. }
  300.  
  301. void setuptmu(int n, const char *rgbfunc, const char *alphafunc)
  302. {
  303.     static tmu init = INITTMU;
  304.     tmu f = tmus[n];
  305.  
  306.     f.mode = GL_COMBINE_ARB;
  307.     if(rgbfunc) parsetmufunc(f.rgb, rgbfunc);
  308.     else f.rgb = init.rgb;
  309.     if(alphafunc) parsetmufunc(f.alpha, alphafunc);
  310.     else f.alpha = init.alpha;
  311.  
  312.     committmu(n, f);
  313. }
  314.  
  315. void inittmus()
  316. {
  317.     if(hasTE && !hasMT) maxtmus = 1;
  318.     else if(hasTE && hasMT)
  319.     {
  320.         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint *)&maxtmus);
  321.         maxtmus = max(1, min(4, maxtmus));
  322.         loopi(maxtmus)
  323.         {
  324.             glActiveTexture_(GL_TEXTURE0_ARB+i);
  325.             resettmu(i);
  326.         }
  327.         glActiveTexture_(GL_TEXTURE0_ARB);
  328.     }
  329. }
  330.  
  331.