Open Source Tomb Raider Engine
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

Texture.cpp 29KB

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