Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Texture.cpp 28KB

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