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

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