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 27KB

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