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.

TextureManager.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*!
  2. * \file src/TextureManager.cpp
  3. * \brief Texture registry
  4. *
  5. * \author Mongoose
  6. * \author xythobuz
  7. */
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <stdarg.h>
  12. #include "global.h"
  13. #include "Log.h"
  14. #include "RunTime.h"
  15. #include "utils/pcx.h"
  16. #include "utils/pixel.h"
  17. #include "utils/strings.h"
  18. #include "utils/tga.h"
  19. #include "TextureManager.h"
  20. #ifdef USING_PNG
  21. #include "utils/png.h"
  22. #endif
  23. TextureTileVertex::TextureTileVertex(uint8_t xc, uint8_t xp, uint8_t yc, uint8_t yp)
  24. : xCoordinate(xc), xPixel(xp), yCoordinate(yc), yPixel(yp) { }
  25. // ----------------------------------------------------------------------------
  26. TextureTile::~TextureTile() {
  27. while (!vertices.empty()) {
  28. delete vertices.at(vertices.size() - 1);
  29. vertices.pop_back();
  30. }
  31. }
  32. void TextureTile::add(TextureTileVertex* t) {
  33. vertices.push_back(t);
  34. }
  35. void TextureTile::displayRectangle(float a[3], float b[3], float c[3], float d[3]) {
  36. //! \fixme TR Rosetta Stone says this, but looks strange?
  37. /*
  38. if (attribute == 0) {
  39. // Ignore transparency
  40. glDisable(GL_BLEND);
  41. }
  42. */
  43. float xmin = 256.0f, xmax = 0.0f;
  44. float ymin = 256.0f, ymax = 0.0f;
  45. for (int i = 0; i < 4; i++) {
  46. if (vertices.at(i)->xCoordinate == 255) {
  47. if (vertices.at(i)->xPixel > xmax)
  48. xmax = vertices.at(i)->xPixel;
  49. } else {
  50. if (vertices.at(i)->xPixel < xmin)
  51. xmin = vertices.at(i)->xPixel;
  52. }
  53. if (vertices.at(i)->yCoordinate == 255) {
  54. ymax = vertices.at(i)->yPixel;
  55. } else {
  56. ymin = vertices.at(i)->yPixel;
  57. }
  58. }
  59. /*
  60. glBegin(GL_QUADS);
  61. glTexCoord2f(xmin / 256.0f, ymin / 256.0f);
  62. glVertex3f(a.x, a.y, a.z);
  63. glTexCoord2f(xmax / 256.0f, ymin / 256.0f);
  64. glVertex3f(b.x, b.y, b.z);
  65. glTexCoord2f(xmax / 256.0f, ymax / 256.0f);
  66. glVertex3f(c.x, c.y, c.z);
  67. glTexCoord2f(xmin / 256.0f, ymax / 256.0f);
  68. glVertex3f(d.x, d.y, d.z);
  69. glEnd();
  70. */
  71. }
  72. void TextureTile::displayTriangle(float a[3], float b[3], float c[3]) {
  73. }
  74. // ----------------------------------------------------------------------------
  75. TextureManager::~TextureManager() {
  76. while (mTextureIdsSystem.size() > 0) {
  77. unsigned int id = mTextureIdsSystem.at(mTextureIdsSystem.size() - 1);
  78. glDeleteTextures(1, &id);
  79. mTextureIdsSystem.pop_back();
  80. }
  81. clear();
  82. }
  83. void TextureManager::clear() {
  84. while (mTextureIdsGame.size() > 0) {
  85. unsigned int id = mTextureIdsGame.at(mTextureIdsGame.size() - 1);
  86. glDeleteTextures(1, &id);
  87. mTextureIdsGame.pop_back();
  88. }
  89. while (!tiles.empty()) {
  90. delete tiles.at(tiles.size() - 1);
  91. tiles.pop_back();
  92. }
  93. while (!animations.empty())
  94. animations.pop_back();
  95. }
  96. void TextureManager::addTile(TextureTile* t) {
  97. tiles.push_back(t);
  98. }
  99. int TextureManager::numTiles() {
  100. return tiles.size();
  101. }
  102. TextureTile& TextureManager::getTile(int index) {
  103. assert(index >= 0);
  104. assert(index < tiles.size());
  105. return *tiles.at(index);
  106. }
  107. void TextureManager::addAnimatedTile(int index, int tile) {
  108. while (index >= animations.size())
  109. animations.push_back(std::vector<int>());
  110. animations.at(index).push_back(tile);
  111. }
  112. int TextureManager::numAnimatedTiles() {
  113. return animations.size();
  114. }
  115. int TextureManager::getFirstTileAnimation(int index) {
  116. assert(index < animations.size());
  117. assert(animations.at(index).size() > 0);
  118. return animations.at(index).at(0);
  119. }
  120. int TextureManager::getNextTileAnimation(int tile) {
  121. for (int a = 0; a < animations.size(); a++) {
  122. for (int i = 0; i < animations.at(a).size(); i++) {
  123. if (animations.at(a).at(i) == tile) {
  124. if (i < (animations.at(a).size() - 1))
  125. return animations.at(a).at(i + 1);
  126. else
  127. return animations.at(a).at(0);
  128. }
  129. }
  130. }
  131. return -1;
  132. }
  133. std::vector<unsigned int>& TextureManager::getIds(TextureStorage s) {
  134. if (s == TextureStorage::GAME)
  135. return mTextureIdsGame;
  136. else
  137. return mTextureIdsSystem;
  138. }
  139. int TextureManager::initialize() {
  140. assert(mTextureIdsGame.size() == 0);
  141. assert(mTextureIdsSystem.size() == 0);
  142. while (mTextureIdsSystem.size() < 2) {
  143. unsigned int id;
  144. glGenTextures(1, &id);
  145. mTextureIdsSystem.push_back(id);
  146. }
  147. return 0;
  148. }
  149. int TextureManager::initializeSplash() {
  150. unsigned char* image = generateColorTexture(WHITE, 32, 32, 32);
  151. int res = loadBufferSlot(image, 32, 32, ColorMode::RGBA, 32, TextureStorage::SYSTEM, TEXTURE_WHITE, false);
  152. delete [] image;
  153. if (res < 0) {
  154. return -1;
  155. }
  156. //! \fixme Temporary?
  157. std::string filename = getRunTime().getPakDir() + "/tr2/TITLE.PCX";
  158. if (loadPCX(filename.c_str(), TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  159. filename = getRunTime().getDataDir() + "/splash.tga";
  160. if (loadTGA(filename.c_str(), TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  161. return -2;
  162. }
  163. }
  164. return 0;
  165. }
  166. int TextureManager::loadBufferSlot(unsigned char* image,
  167. unsigned int width, unsigned int height,
  168. ColorMode mode, unsigned int bpp,
  169. TextureStorage s, int slot, bool filter) {
  170. assert(width > 0);
  171. assert(height > 0);
  172. assert((mode == ColorMode::RGB)
  173. || (mode == ColorMode::BGR)
  174. || (mode == ColorMode::ARGB)
  175. || (mode == ColorMode::RGBA)
  176. || (mode == ColorMode::BGRA));
  177. assert((bpp == 8) || (bpp == 24) || (bpp == 32));
  178. if (slot == -1)
  179. slot = getIds(s).size();
  180. while (getIds(s).size() <= slot) {
  181. unsigned int id;
  182. glGenTextures(1, &id);
  183. getIds(s).push_back(id);
  184. }
  185. if (image == nullptr)
  186. return slot;
  187. unsigned int glcMode;
  188. switch (mode) {
  189. case ColorMode::BGR:
  190. glcMode = GL_BGR;
  191. break;
  192. case ColorMode::RGB:
  193. glcMode = GL_RGB;
  194. break;
  195. case ColorMode::ARGB:
  196. argb2rgba32(image, width, height);
  197. glcMode = GL_RGBA;
  198. break;
  199. case ColorMode::BGRA:
  200. glcMode = GL_BGRA;
  201. break;
  202. case ColorMode::RGBA:
  203. glcMode = GL_RGBA;
  204. break;
  205. }
  206. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  207. glBindTexture(GL_TEXTURE_2D, getIds(s).at(slot));
  208. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, glcMode, GL_UNSIGNED_BYTE, image);
  209. if (filter) {
  210. // Trilinear filtering
  211. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  212. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  213. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  214. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  215. glGenerateMipmap(GL_TEXTURE_2D);
  216. } else {
  217. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  218. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  219. }
  220. return slot;
  221. }
  222. int TextureManager::numTextures(TextureStorage s) {
  223. return getIds(s).size();
  224. }
  225. void TextureManager::bindTextureId(unsigned int n, TextureStorage s, unsigned int unit) {
  226. assert(n < getIds(s).size());
  227. assert(unit < 80); //! \todo Query GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
  228. glActiveTexture(GL_TEXTURE0 + unit);
  229. glBindTexture(GL_TEXTURE_2D, getIds(s).at(n));
  230. }
  231. int TextureManager::loadImage(const char* filename, TextureStorage s, int slot) {
  232. if (stringEndsWith(filename, ".pcx") || stringEndsWith(filename, ".PCX")) {
  233. return loadPCX(filename, s, slot);
  234. } else if (stringEndsWith(filename, ".png") || stringEndsWith(filename, ".PNG")) {
  235. return loadPNG(filename, s, slot);
  236. } else if (stringEndsWith(filename, ".tga") || stringEndsWith(filename, ".TGA")) {
  237. return loadTGA(filename, s, slot);
  238. } else {
  239. getLog() << "No known image file type? (" << filename << ")" << Log::endl;
  240. }
  241. return -1;
  242. }
  243. int TextureManager::loadPCX(const char* filename, TextureStorage s, int slot) {
  244. assert(filename != nullptr);
  245. assert(filename[0] != '\0');
  246. unsigned char* image;
  247. unsigned int w, h, bpp;
  248. ColorMode c;
  249. int id = -1;
  250. int error = pcxLoad(filename, &image, &w, &h, &c, &bpp);
  251. if (error == 0) {
  252. unsigned char* image2 = scaleBuffer(image, &w, &h, bpp);
  253. if (image2) {
  254. delete [] image;
  255. image = image2;
  256. }
  257. id = loadBufferSlot(image, w, h, c, bpp, s, slot);
  258. delete [] image;
  259. }
  260. return id;
  261. }
  262. int TextureManager::loadPNG(const char* filename, TextureStorage s, int slot) {
  263. #ifdef USING_PNG
  264. assert(filename != nullptr);
  265. assert(filename[0] != '\0');
  266. if (pngCheck(filename) != 0) {
  267. return -1;
  268. }
  269. unsigned char* image;
  270. unsigned int w, h, bpp;
  271. ColorMode c;
  272. int id = -1;
  273. int error = pngLoad(filename, &image, &w, &h, &c, &bpp);
  274. if (error == 0) {
  275. unsigned char* image2 = scaleBuffer(image, &w, &h, bpp);
  276. if (image2) {
  277. delete [] image;
  278. image = image2;
  279. }
  280. id = loadBufferSlot(image, w, h, c, bpp, s, slot);
  281. delete [] image;
  282. }
  283. return id;
  284. #else
  285. getLog() << "No PNG support available (" << filename << ")" << Log::endl;
  286. return -1;
  287. #endif
  288. }
  289. int TextureManager::loadTGA(const char* filename, TextureStorage s, int slot) {
  290. assert(filename != nullptr);
  291. assert(filename[0] != '\0');
  292. unsigned char* image;
  293. unsigned int w, h;
  294. char type;
  295. int id = -1;
  296. if (!tgaCheck(filename)) {
  297. tgaLoad(filename, &image, &w, &h, &type);
  298. unsigned char* image2 = scaleBuffer(image, &w, &h, (type == 2) ? 32 : 24);
  299. if (image2) {
  300. delete [] image;
  301. image = image2;
  302. }
  303. if (image) {
  304. id = loadBufferSlot(image, w, h,
  305. (type == 2) ? ColorMode::RGBA : ColorMode::RGB,
  306. (type == 2) ? 32 : 24,
  307. s, slot);
  308. delete [] image;
  309. }
  310. }
  311. return id;
  312. }