Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Texture.cpp 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. /*!
  2. * \file src/Texture.cpp
  3. * \brief Texture registry
  4. *
  5. * \author Mongoose
  6. */
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <stdarg.h>
  11. #include "SDL_ttf.h"
  12. #ifdef __APPLE__
  13. #include <OpenGL/gl.h>
  14. #include <OpenGL/glu.h>
  15. #else
  16. #include <GL/gl.h>
  17. #include <GL/glu.h>
  18. #endif
  19. #include "utils/tga.h"
  20. #include "Texture.h"
  21. //Texture *gTextureManager = 0x0;
  22. gl_font_t *gFontTest = 0x0;
  23. ////////////////////////////////////////////////////////////
  24. // Constructors
  25. ////////////////////////////////////////////////////////////
  26. Texture::Texture()
  27. {
  28. mTextureIds = NULL;
  29. mFlags = 0;
  30. mTextureId = -1;
  31. mTextureId2 = -1;
  32. mTextureCount = 0;
  33. mTextureLimit = 0;
  34. //gTextureManager = this;
  35. initSDL_TTF();
  36. textureDebug = -1;
  37. }
  38. Texture::~Texture()
  39. {
  40. if (gFontTest)
  41. {
  42. glDeleteLists(gFontTest->drawListBase, gFontTest->count);
  43. delete gFontTest;
  44. }
  45. reset();
  46. }
  47. ////////////////////////////////////////////////////////////
  48. // Public Accessors
  49. ////////////////////////////////////////////////////////////
  50. unsigned char *Texture::generateColorTexture(unsigned char rgba[4],
  51. unsigned int width,
  52. unsigned int height)
  53. {
  54. unsigned char *image;
  55. unsigned int i, size;
  56. image = new unsigned char[height*width*4];
  57. for (i = 0, size = width*height; i < size; ++i)
  58. {
  59. /* RBGA */
  60. image[i*4] = rgba[0];
  61. image[i*4+1] = rgba[1];
  62. image[i*4+2] = rgba[2];
  63. image[i*4+3] = rgba[3];
  64. }
  65. return image;
  66. }
  67. void glEnterMode2d(unsigned int width, unsigned int height)
  68. {
  69. glPushAttrib(GL_ENABLE_BIT);
  70. glDisable(GL_DEPTH_TEST);
  71. glDisable(GL_CULL_FACE);
  72. glEnable(GL_TEXTURE_2D);
  73. /* This allows alpha blending of 2D textures with the scene */
  74. glEnable(GL_BLEND);
  75. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  76. glViewport(0, 0, width, height);
  77. glMatrixMode(GL_PROJECTION);
  78. glPushMatrix();
  79. glLoadIdentity();
  80. glOrtho(0.0, (GLdouble)width, (GLdouble)height, 0.0, 0.0, 1.0);
  81. glMatrixMode(GL_MODELVIEW);
  82. glPushMatrix();
  83. glLoadIdentity();
  84. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  85. }
  86. void glExitMode2d()
  87. {
  88. glMatrixMode(GL_MODELVIEW);
  89. glPopMatrix();
  90. glMatrixMode(GL_PROJECTION);
  91. glPopMatrix();
  92. glPopAttrib();
  93. glMatrixMode(GL_MODELVIEW);
  94. }
  95. void bufferedPrintf(char *string, unsigned int len, char *s, ...)
  96. {
  97. va_list args;
  98. if (s && s[0])
  99. {
  100. va_start(args, s);
  101. vsnprintf(string, len-1, s, args);
  102. string[len-1] = 0;
  103. va_end(args);
  104. }
  105. }
  106. void glPrint2d(float x, float y, float scale, char *string)
  107. {
  108. gl_font_t *font = gFontTest;
  109. if (!font)
  110. {
  111. static int errors = 0;
  112. if (errors < 10)
  113. printf("ERROR: glPrint2d failed, %i\n", ++errors);
  114. return;
  115. }
  116. glPushMatrix();
  117. glBindTexture(GL_TEXTURE_2D, font->textureId);
  118. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  119. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  120. glTranslatef(x, y, 0);
  121. glScalef(scale, scale, 1);
  122. /*! \fixme
  123. * Add utf-8 dencoding of char* string
  124. *
  125. * Also this string must be preprocessed to have glyph offsets
  126. * instead of ASCII text in it and support counts over 256 */
  127. glListBase(font->drawListBase - font->utf8Offset);
  128. glCallLists(strlen(string), GL_BYTE, string);
  129. glPopMatrix();
  130. }
  131. void glPrint3d(float x, float y, float z,
  132. float pitch, float yaw, float roll,
  133. float scale,
  134. char *string)
  135. {
  136. gl_font_t *font = gFontTest;
  137. if (!font)
  138. {
  139. static int errors = 0;
  140. if (errors < 10)
  141. printf("ERROR: glPrint3d failed, %i\n", ++errors);
  142. return;
  143. }
  144. glPushMatrix();
  145. glBindTexture(GL_TEXTURE_2D, font->textureId);
  146. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  147. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  148. glTranslatef(x, y, z);
  149. glRotatef(roll, 1, 0, 0);
  150. glRotatef(yaw, 0, 1, 0);
  151. glRotatef(pitch, 0, 0, 1);
  152. glScalef(scale, scale, scale);
  153. /*! \fixme
  154. * Add utf-8 dencoding of char* string
  155. *
  156. * Also this string must be preprocessed to have glyph offsets
  157. * instead of ASCII text in it and support counts over 256 */
  158. glListBase(font->drawListBase - font->utf8Offset);
  159. glCallLists(strlen(string), GL_BYTE, string);
  160. glPopMatrix();
  161. }
  162. int Texture::showTextureDebug(int textureId) {
  163. if (textureId >= getTextureCount())
  164. return -1;
  165. textureDebug = textureId;
  166. textureDebugFrames = 100;
  167. return mTextureIds[textureId];
  168. }
  169. void Texture::debugTextureRender(int width, int height) {
  170. int xMin, xMax, yMin, yMax;
  171. xMin = yMin = 0;
  172. xMax = width;
  173. yMax = height;
  174. if ((textureDebug >= 0) && (textureDebugFrames > 0)) {
  175. glColor3f(1, 1, 1);
  176. bindTextureId(textureDebug);
  177. // Draw a textured quad
  178. glBegin(GL_QUADS);
  179. glTexCoord2f(0, 0); glVertex3f(xMin, yMin, 0);
  180. glTexCoord2f(0, 1); glVertex3f(xMin, yMax, 0);
  181. glTexCoord2f(1, 1); glVertex3f(xMax, yMax, 0);
  182. glTexCoord2f(1, 0); glVertex3f(xMax, yMin, 0);
  183. glEnd();
  184. textureDebugFrames--;
  185. }
  186. }
  187. int Texture::loadFontTTF(const char *filename,
  188. unsigned int utf8Offset, unsigned int count)
  189. {
  190. ttf_texture_t *texture;
  191. unsigned char rgb[3] = {0xff, 0xff, 0xff};
  192. if (!filename || !filename[0])
  193. {
  194. printf("fontTest> Passed bad filename\n");
  195. return -1;
  196. }
  197. texture = generateFontTexture(filename, 24, 256, rgb,
  198. //0x303f, 0x3093-0x303f, // hiragana
  199. //32, 126 - 32, // english
  200. utf8Offset, count,
  201. false);
  202. if (texture)
  203. {
  204. #ifdef DUMP_TTF_TGA
  205. tgaSaveFilename(texture->texture, 256, 256, 4, "ttf_font.tga");
  206. #endif
  207. gFontTest = generateFont(texture);
  208. /*! \fixme Until UTF8 decoder is working, we map from
  209. ASCII when rendering */
  210. gFontTest->utf8Offset = 32; // hack to use ASCII strings to test unicode
  211. delete [] texture->texture;
  212. delete [] texture->glyphs;
  213. delete texture;
  214. return gFontTest->textureId;
  215. }
  216. else
  217. {
  218. return -2;
  219. }
  220. }
  221. gl_font_t *Texture::generateFont(ttf_texture_t *texture)
  222. {
  223. const float spacing = 4.0;
  224. unsigned int i;
  225. float u, v, u2, v2;
  226. int h;
  227. gl_font_t *font;
  228. if (!texture)
  229. return NULL;
  230. printf("Generating gl font from texture...\n");
  231. font = new gl_font_t;
  232. font->utf8Offset = texture->utf8Offset;
  233. font->count = texture->count;
  234. font->textureId = loadBuffer(texture->texture,
  235. texture->width, texture->width, RGBA, 32);
  236. glColor3f(1.0, 1.0, 1.0);
  237. font->drawListBase = glGenLists(texture->count);
  238. glBindTexture(GL_TEXTURE_2D, font->textureId);
  239. for (i = 0; i < texture->count; i++)
  240. {
  241. /* Generate texture coordinates for this TTF glyph */
  242. u = (float)texture->glyphs[i].x / (float)texture->width;
  243. v = (float)texture->glyphs[i].y / (float)texture->width;
  244. u2 = (((float)texture->glyphs[i].x + (float)texture->glyphs[i].w) /
  245. (float)texture->width);
  246. v2 = (((float)texture->glyphs[i].y + (float)texture->glyphs[i].h) /
  247. (float)texture->width);
  248. #ifdef DEBUG_TTF_OFFSET
  249. if (i+texture->utf8Offset == 'y' || i+texture->utf8Offset == 'x')
  250. {
  251. printf("%c: %i %i %i\n",
  252. i+texture->utf8Offset,
  253. texture->fontDescent,
  254. texture->glyphs[i].miny, texture->glyphs[i].maxy);
  255. }
  256. #endif
  257. if (texture->glyphs[i].h < texture->fontHeight)
  258. {
  259. h = texture->fontHeight - texture->glyphs[i].h;
  260. }
  261. else
  262. {
  263. h = 0;
  264. }
  265. // After migrating to SDL2_TTF, some characters where rendered slightly
  266. // vertically offset. However, dumping the font texture as TGA did not show
  267. // this offset. It turns out, this fixes the issue...? O.o --xythobuz
  268. // h += -texture->fontHeight/2-(texture->fontDescent + texture->glyphs[i].miny);
  269. h -= texture->fontHeight/2 + texture->fontDescent;
  270. /* Make a list for this TTF glyph, one nonuniform Quad per glyph */
  271. glNewList(font->drawListBase + i, GL_COMPILE);
  272. glBegin(GL_QUADS);
  273. glTexCoord2f(u2, v); /* Top, right */
  274. glVertex3i(texture->glyphs[i].w, h, 0);
  275. glTexCoord2f(u, v); /* Top, left */
  276. glVertex3i(0, h, 0);
  277. glTexCoord2f(u, v2); /* Bottom, left */
  278. glVertex3i(0, h+texture->glyphs[i].h, 0);
  279. glTexCoord2f(u2, v2); /* Bottom, right */
  280. glVertex3i(texture->glyphs[i].w, h+texture->glyphs[i].h, 0);
  281. glEnd();
  282. /* Move To The Left Of The Character */
  283. glTranslated(texture->glyphs[i].w + spacing, 0, 0);
  284. glEndList();
  285. }
  286. return font;
  287. }
  288. ttf_texture_t *Texture::generateFontTexture(const char *filename, int pointSize,
  289. unsigned int textureWidth,
  290. unsigned char color[3],
  291. unsigned int utf8Offset,
  292. unsigned int count,
  293. char verbose)
  294. {
  295. unsigned int i;
  296. int xx = 0, yy = 0, hh = 0, k, h, w, offset;
  297. unsigned char b;
  298. unsigned char *image;
  299. SDL_Surface* glyph;
  300. SDL_Color sdlColor;
  301. TTF_Font *font;
  302. ttf_texture_t *texture;
  303. FILE *f;
  304. sdlColor.r = color[0];
  305. sdlColor.g = color[1];
  306. sdlColor.b = color[2];
  307. if (!(mFlags & fUseSDL_TTF))
  308. {
  309. printf("SDL_TTF couldn't be used... exiting\n");
  310. return NULL;
  311. }
  312. if (pointSize < 8)
  313. {
  314. pointSize = 8;
  315. }
  316. /* Work around for TTF_OpenFont for file not found segfault */
  317. f = fopen(filename, "rb");
  318. if (!f)
  319. {
  320. printf("generateFontTexture> Couldn't load '%s'\n", filename);
  321. perror(filename);
  322. return NULL;
  323. }
  324. fclose(f);
  325. // Open the font file at the requested point size
  326. font = TTF_OpenFont(filename, pointSize);
  327. if (font == NULL)
  328. {
  329. fprintf(stderr, "generateFontTexture> Couldn't load %d pt font from %s: %s\n",
  330. pointSize, filename, SDL_GetError());
  331. return NULL;
  332. }
  333. // TTF_STYLE_NORMAL, TTF_STYLE_BOLD, TTF_STYLE_ITALIC, TTF_STYLE_UNDERLINE
  334. int renderStyle = TTF_STYLE_NORMAL;
  335. TTF_SetFontStyle(font, renderStyle);
  336. TTF_SetFontHinting(font, TTF_HINTING_LIGHT);
  337. /* Allocate a new TTF font texture */
  338. printf("Creating font texture from '%s'...\n", filename);
  339. texture = new ttf_texture_t;
  340. texture->width = textureWidth;
  341. texture->utf8Offset = utf8Offset;
  342. texture->count = count;
  343. texture->glyphs = new ttf_glyph_t[count];
  344. texture->texture = new unsigned char[textureWidth*textureWidth*4];
  345. memset(texture->texture, 0, textureWidth*textureWidth*4);
  346. texture->fontHeight = TTF_FontHeight(font);
  347. texture->fontAscent = TTF_FontAscent(font);
  348. texture->fontDescent = TTF_FontDescent(font);
  349. texture->fontSpacing = TTF_FontLineSkip(font);
  350. for (i = 0; i < count; ++i)
  351. {
  352. glyph = TTF_RenderGlyph_Blended(font, (Uint16)(i + utf8Offset), sdlColor);
  353. if (glyph)
  354. {
  355. image = (unsigned char*)glyph->pixels;
  356. TTF_GlyphMetrics(font, (Uint16)(i + utf8Offset),
  357. &texture->glyphs[i].minx, &texture->glyphs[i].maxx,
  358. &texture->glyphs[i].miny, &texture->glyphs[i].maxy,
  359. &texture->glyphs[i].advance);
  360. texture->glyphs[i].w = glyph->w;
  361. texture->glyphs[i].h = glyph->h;
  362. if (xx + texture->glyphs[i].w > ((int)textureWidth - 1))
  363. {
  364. yy += hh;
  365. hh = 2;
  366. xx = 2;
  367. texture->glyphs[i].x = 0;
  368. texture->glyphs[i].y = yy;
  369. }
  370. else
  371. {
  372. (texture->glyphs[i].h > hh) ? hh = texture->glyphs[i].h: 0;
  373. texture->glyphs[i].x = xx;
  374. texture->glyphs[i].y = yy;
  375. }
  376. xx += glyph->w;
  377. if (verbose)
  378. {
  379. printf("0x%x : %ix%i @ %i, %i\n", i + utf8Offset,
  380. texture->glyphs[i].w, texture->glyphs[i].h,
  381. texture->glyphs[i].x, texture->glyphs[i].y);
  382. }
  383. /* Blit @ xx, yy - in pixels */
  384. for (k = 0; k < glyph->w*glyph->h; ++k)
  385. {
  386. w = texture->glyphs[i].x + k%glyph->w;
  387. h = texture->glyphs[i].y + k/glyph->w;
  388. offset = (w + h*textureWidth);
  389. if (verbose)
  390. {
  391. printf("Offset: %i; Pixel: %i,%i; Data: 0x%08x\n",
  392. offset, w, h, *((unsigned int *)(void *)&image[k*4]));
  393. }
  394. /* 32-bit ARGB to RGBA */
  395. b = image[k*4+3];
  396. texture->texture[offset*4] = image[k*4] = image[k*4+1];
  397. texture->texture[offset*4+1] = image[k*4+1] = image[k*4+2];
  398. texture->texture[offset*4+2] = image[k*4+2] = image[k*4+3];
  399. texture->texture[offset*4+3] = image[k*4+3] = b;
  400. }
  401. }
  402. }
  403. TTF_CloseFont(font);
  404. return texture;
  405. }
  406. ////////////////////////////////////////////////////////////
  407. // Public Mutators
  408. ////////////////////////////////////////////////////////////
  409. int Texture::loadColorTexture(unsigned char rgba[4],
  410. unsigned int width, unsigned int height)
  411. {
  412. unsigned char *image;
  413. int id;
  414. image = generateColorTexture(rgba, width, height);
  415. id = loadBuffer(image, width, height, RGBA, 32);
  416. delete [] image;
  417. return id;
  418. }
  419. void Texture::initSDL_TTF()
  420. {
  421. // Initialize the TTF library
  422. if (TTF_Init() < 0)
  423. {
  424. fprintf(stderr, "initSDL_TTF> TTF_Init() failed!\n");
  425. fprintf(stderr, "initSDL_TTF> Error is [%s].\n", SDL_GetError());
  426. }
  427. else
  428. {
  429. mFlags |= fUseSDL_TTF;
  430. printf("Started SDL_TTF subsystem!\n");
  431. atexit(TTF_Quit);
  432. }
  433. }
  434. void Texture::setFlag(TextureFlag flag)
  435. {
  436. mFlags |= flag;
  437. }
  438. void Texture::clearFlag(TextureFlag flag)
  439. {
  440. mFlags |= flag;
  441. mFlags ^= flag;
  442. }
  443. void Texture::reset()
  444. {
  445. if (mTextureIds)
  446. {
  447. glDeleteTextures(mTextureLimit, mTextureIds);
  448. delete [] mTextureIds;
  449. }
  450. mTextureIds = 0x0;
  451. mTextureCount = 0;
  452. mTextureLimit = 0;
  453. }
  454. void Texture::disableMultiTexture()
  455. {
  456. mFlags ^= fUseMultiTexture;
  457. mTextureId = -1;
  458. mTextureId2 = -1;
  459. glDisable(GL_TEXTURE_2D);
  460. glActiveTextureARB(GL_TEXTURE0_ARB);
  461. }
  462. void Texture::useMultiTexture(float aU, float aV, float bU, float bV)
  463. {
  464. if (!(mFlags & fUseMultiTexture))
  465. return;
  466. glMultiTexCoord2fARB(GL_TEXTURE0_ARB, aU, aV);
  467. glMultiTexCoord2fARB(GL_TEXTURE1_ARB, bU, bV);
  468. }
  469. void Texture::useMultiTexture(float u, float v)
  470. {
  471. if (!(mFlags & fUseMultiTexture))
  472. return;
  473. glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
  474. glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
  475. }
  476. void Texture::bindMultiTexture(int texture0, int texture1)
  477. {
  478. if (//(int)a == mTextureId && (int)b == mTextureId2 ||
  479. !mTextureIds ||
  480. texture0 < 0 || texture0 > (int)mTextureCount ||
  481. texture1 < 0 || texture1 > (int)mTextureCount)
  482. {
  483. return;
  484. }
  485. mFlags |= fUseMultiTexture;
  486. mTextureId = texture0;
  487. mTextureId2 = texture1;
  488. glActiveTextureARB(GL_TEXTURE0_ARB);
  489. glEnable(GL_TEXTURE_2D);
  490. glBindTexture(GL_TEXTURE_2D, mTextureIds[texture0]);
  491. glActiveTextureARB(GL_TEXTURE1_ARB);
  492. glEnable(GL_TEXTURE_2D);
  493. glBindTexture(GL_TEXTURE_2D, mTextureIds[texture1]);
  494. }
  495. void Texture::setMaxTextureCount(unsigned int n)
  496. {
  497. mTextureLimit = n;
  498. mTextureIds = new unsigned int[n];
  499. glGenTextures(n, mTextureIds);
  500. }
  501. int Texture::getTextureCount()
  502. {
  503. return (mTextureCount-1);
  504. }
  505. int Texture::loadBuffer(unsigned char *image,
  506. unsigned int width, unsigned int height,
  507. ColorMode mode, unsigned int bpp)
  508. {
  509. int id;
  510. id = loadBufferSlot(image, width, height, mode, bpp, mTextureCount++);
  511. if (id < 0)
  512. {
  513. return id;
  514. }
  515. return ++id;
  516. }
  517. void convertARGB32bppToRGBA32bpp(unsigned char *image,
  518. unsigned int w, unsigned int h)
  519. {
  520. unsigned int i, size = w*h;
  521. unsigned char swap;
  522. for (i = 0; i < size; ++i)
  523. {
  524. /* 32-bit ARGB to RGBA */
  525. swap = image[i*4+3];
  526. image[i*4] = image[i*4+1];
  527. image[i*4+1] = image[i*4+2];
  528. image[i*4+2] = image[i*4+3];
  529. image[i*4+3] = swap;
  530. }
  531. }
  532. // http://mmmovania.blogspot.de/2011/01/opengl-30-and-above-deprecated-func-and.html
  533. // http://www.g-truc.net/post-0256.html
  534. GLint deprecated_gluBuild2DMipmaps(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data) {
  535. glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
  536. glTexImage2D(target, 0, internalFormat, width, height, 0, format, type, data);
  537. return 0;
  538. }
  539. int Texture::loadBufferSlot(unsigned char *image,
  540. unsigned int width, unsigned int height,
  541. ColorMode mode, unsigned int bpp,
  542. unsigned int slot)
  543. {
  544. unsigned char bytes;
  545. unsigned int glcMode;
  546. if (!mTextureIds || slot >= mTextureLimit)
  547. {
  548. printf("Texture::Load> ERROR Not initialized or out of free slots\n");
  549. return -1000;
  550. }
  551. if (!width || !height || !image)
  552. {
  553. printf("Texture::Load> ERROR Assertion 'image is valid' failed\n");
  554. return -1;
  555. }
  556. switch (mode)
  557. {
  558. case GREYSCALE:
  559. if (bpp != 8)
  560. {
  561. printf("Texture::Load> ERROR Unsupported GREYSCALE, %i bpp\n", bpp);
  562. return -2;
  563. }
  564. bytes = 1;
  565. glcMode = GL_LUMINANCE;
  566. break;
  567. case RGB:
  568. if (bpp != 24)
  569. {
  570. printf("Texture::Load> ERROR Unsupported RGB, %i bpp\n", bpp);
  571. return -2;
  572. }
  573. bytes = 3;
  574. glcMode = GL_RGB;
  575. break;
  576. case ARGB:
  577. if (bpp == 32)
  578. {
  579. convertARGB32bppToRGBA32bpp(image, width, height);
  580. }
  581. else
  582. {
  583. printf("Texture::Load> ERROR Unsupported ARGB, %i bpp\n", bpp);
  584. return -2;
  585. }
  586. bytes = 4;
  587. glcMode = GL_RGBA;
  588. break;
  589. case RGBA:
  590. if (bpp != 32)
  591. {
  592. printf("Texture::Load> ERROR Unsupported RGBA, %i bpp\n", bpp);
  593. return -2;
  594. }
  595. bytes = 4;
  596. glcMode = GL_RGBA;
  597. break;
  598. }
  599. glClearColor(0.0, 0.0, 0.0, 0.0);
  600. glEnable(GL_DEPTH_TEST);
  601. glShadeModel(GL_SMOOTH);
  602. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  603. glBindTexture(GL_TEXTURE_2D, mTextureIds[slot]);
  604. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  605. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  606. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  607. if (mFlags & fUseMipmaps)
  608. {
  609. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  610. GL_NEAREST_MIPMAP_LINEAR);
  611. //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  612. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  613. GL_LINEAR_MIPMAP_LINEAR);
  614. //gluBuild2DMipmaps(GL_TEXTURE_2D, bytes, width, height, glcMode, GL_UNSIGNED_BYTE, image);
  615. // gluBuild2DMipmaps is deprecated. Replacement by xythobuz
  616. deprecated_gluBuild2DMipmaps(GL_TEXTURE_2D, bytes, width, height, glcMode, GL_UNSIGNED_BYTE, image);
  617. }
  618. else
  619. {
  620. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  621. glTexImage2D(GL_TEXTURE_2D, 0, glcMode, width, height, 0,
  622. glcMode, GL_UNSIGNED_BYTE, image);
  623. }
  624. //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  625. return slot;
  626. }
  627. void Texture::bindTextureId(unsigned int n)
  628. {
  629. if ((int)n == mTextureId || !mTextureIds || n > mTextureCount)
  630. {
  631. return;
  632. }
  633. mTextureId = n;
  634. glEnable(GL_TEXTURE_2D);
  635. //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  636. glBindTexture(GL_TEXTURE_2D, mTextureIds[n]);
  637. }
  638. void Texture::glScreenShot(char *base, unsigned int width, unsigned int height) {
  639. FILE *f;
  640. int sz = width * height;
  641. unsigned char *image = new unsigned char[sz * 3];
  642. char filename[1024];
  643. static int count = 0;
  644. bool done = false;
  645. if (!image || !width || !height) {
  646. if (image)
  647. delete [] image;
  648. printf("glScreenShot> ERROR: Couldn't allocate image!\n");
  649. return;
  650. }
  651. // Don't overwrite files
  652. while (!done)
  653. {
  654. snprintf(filename, 1024, "%s-%04i.tga", base, count++);
  655. f = fopen(filename, "rb");
  656. if (f)
  657. fclose(f);
  658. else
  659. done = true;
  660. }
  661. // Capture frame buffer
  662. glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, image);
  663. tgaSaveFilename(image, width, height, 0, "%s", filename);
  664. printf("Took screenshot '%s'.\n", filename);
  665. delete [] image;
  666. }
  667. int Texture::loadTGA(const char *filename)
  668. {
  669. FILE *f;
  670. unsigned char *image = NULL;
  671. unsigned char *image2 = NULL;
  672. unsigned int w, h;
  673. char type;
  674. int id = -1;
  675. f = fopen(filename, "rb");
  676. if (!f)
  677. {
  678. perror("Couldn't load file");
  679. }
  680. else if (!tgaCheck(f))
  681. {
  682. tgaLoad(f, &image, &w, &h, &type);
  683. type += 2;
  684. image2 = scaleBuffer(image, w, h, (type == 4) ? 4 : 3);
  685. if (image2)
  686. {
  687. image = image2;
  688. w = h = 256;
  689. }
  690. if (image)
  691. {
  692. id = loadBuffer(image, w, h,
  693. (type == 4) ? RGBA : RGB,
  694. (type == 4) ? 32 : 24);
  695. delete [] image;
  696. }
  697. fclose(f);
  698. }
  699. if (id == -1)
  700. {
  701. printf("Texture::loadTGA> ERROR: Failed to load '%s'\n", filename);
  702. }
  703. return id;
  704. }
  705. ////////////////////////////////////////////////////////////
  706. // Private Accessors
  707. ////////////////////////////////////////////////////////////
  708. int Texture::nextPower(int seed)
  709. {
  710. int i;
  711. for(i = 1; i < seed; i *= 2)
  712. ;
  713. return i;
  714. }
  715. /* This code based off on gluScaleImage() */
  716. unsigned char *Texture::scaleBuffer(unsigned char *image,
  717. int width, int height,
  718. int components)
  719. {
  720. int i, j, k;
  721. float* tempin;
  722. float* tempout;
  723. float sx, sy;
  724. // int components = 3;
  725. unsigned char *timage;
  726. int original_height = height;
  727. int original_width = width;
  728. if (!image || !width || !height)
  729. {
  730. return NULL;
  731. }
  732. height = nextPower(height);
  733. width = nextPower(width);
  734. if (height > 256)
  735. height = 256;
  736. if (width > 256)
  737. width = 256;
  738. // Check to see if scaling is needed
  739. if (height == original_height && width == original_width)
  740. return NULL;
  741. //printf("%i\n", components);
  742. timage = new unsigned char[height * width * components];
  743. tempin = new float[original_width * original_height * components * sizeof(float)];
  744. tempout = new float[width * height * components * sizeof(float)];
  745. if (!tempout || !tempin || !timage)
  746. {
  747. if (tempout)
  748. delete [] tempout;
  749. if (tempin)
  750. delete [] tempin;
  751. if (timage)
  752. delete [] timage;
  753. printf("Oh shit out of memory!\n");
  754. return NULL;
  755. }
  756. // Copy user data to float format.
  757. for (i = 0; i < original_height * original_width * components; ++i)
  758. {
  759. tempin[i] = (float)image[i];
  760. }
  761. // Determine which filter to use by checking ratios.
  762. if (width > 1)
  763. {
  764. sx = (float)(original_width - 1) / (float)(width - 1);
  765. }
  766. else
  767. {
  768. sx = (float)(original_width - 1);
  769. }
  770. if (height > 1)
  771. {
  772. sy = (float)(original_height - 1) / (float) (height - 1);
  773. }
  774. else
  775. {
  776. sy = (float)(original_height - 1);
  777. }
  778. if (sx < 1.0 && sy < 1.0)
  779. {
  780. /* Magnify both width and height: use weighted sample of 4 pixels */
  781. int i0, i1, j0, j1;
  782. float alpha, beta;
  783. float* src00;
  784. float* src01;
  785. float* src10;
  786. float* src11;
  787. float s1, s2;
  788. float* dst;
  789. for(i = 0; i < height; ++i)
  790. {
  791. i0 = (int)(i * sy);
  792. i1 = i0 + 1;
  793. if (i1 >= original_height)
  794. {
  795. i1 = original_height - 1;
  796. }
  797. alpha = i * sy - i0;
  798. for (j = 0; j < width; ++j)
  799. {
  800. j0 = (int) (j * sx);
  801. j1 = j0 + 1;
  802. if (j1 >= original_width)
  803. {
  804. j1 = original_width - 1;
  805. }
  806. beta = j * sx - j0;
  807. /* Compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
  808. src00 = tempin + (i0 * original_width + j0) * components;
  809. src01 = tempin + (i0 * original_width + j1) * components;
  810. src10 = tempin + (i1 * original_width + j0) * components;
  811. src11 = tempin + (i1 * original_width + j1) * components;
  812. dst = tempout + (i * width + j) * components;
  813. for (k = 0; k < components; ++k)
  814. {
  815. s1 = *src00++ * (1.0f - beta) + *src01++ * beta;
  816. s2 = *src10++ * (1.0f - beta) + *src11++ * beta;
  817. *dst++ = s1 * (1.0f - alpha) + s2 * alpha;
  818. }
  819. }
  820. }
  821. }
  822. else
  823. {
  824. /* Shrink width and/or height: use an unweighted box filter */
  825. int i0, i1;
  826. int j0, j1;
  827. int ii, jj;
  828. float sum;
  829. float* dst;
  830. for (i = 0; i < height; ++i)
  831. {
  832. i0 = (int) (i * sy);
  833. i1 = i0 + 1;
  834. if (i1 >= original_height)
  835. {
  836. i1 = original_height - 1;
  837. }
  838. for (j = 0; j < width; ++j)
  839. {
  840. j0 = (int) (j * sx);
  841. j1 = j0 + 1;
  842. if (j1 >= original_width)
  843. {
  844. j1 = original_width - 1;
  845. }
  846. dst = tempout + (i * width + j) * components;
  847. /* Compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
  848. for (k = 0; k < components; ++k)
  849. {
  850. sum = 0.0;
  851. for (ii = i0; ii <= i1; ++ii)
  852. {
  853. for (jj = j0; jj <= j1; ++jj)
  854. {
  855. sum += *(tempin + (ii * original_width + jj)
  856. * components + k);
  857. }
  858. }
  859. sum /= ( j1 - j0 + 1 ) * ( i1 - i0 + 1 );
  860. *dst++ = sum;
  861. }
  862. }
  863. }
  864. }
  865. // Copy to our results.
  866. for( i = 0; i < height * width * components; ++i)
  867. {
  868. timage[i] = (unsigned char)tempout[i];
  869. }
  870. // Delete our temp buffers.
  871. delete[] tempin;
  872. delete[] tempout;
  873. delete[] image;
  874. return timage;
  875. }
  876. ////////////////////////////////////////////////////////////
  877. // Private Mutators
  878. ////////////////////////////////////////////////////////////