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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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 "stb/stb_image.h"
  13. #include "global.h"
  14. #include "Log.h"
  15. #include "RunTime.h"
  16. #include "utils/Folder.h"
  17. #include "utils/pcx.h"
  18. #include "utils/pixel.h"
  19. #include "utils/random.h"
  20. #include "utils/strings.h"
  21. #include "TextureManager.h"
  22. std::vector<unsigned int> TextureManager::mTextureIdsGame;
  23. std::vector<unsigned int> TextureManager::mTextureIdsSystem;
  24. std::vector<TextureTile*> TextureManager::tiles;
  25. std::vector<std::vector<int>> TextureManager::animations;
  26. std::vector<int> TextureManager::gameUnits;
  27. std::vector<int> TextureManager::systemUnits;
  28. unsigned int TextureManager::nextFreeTextureUnit = 0;
  29. int TextureManager::initialize() {
  30. assert(mTextureIdsGame.size() == 0);
  31. assert(mTextureIdsSystem.size() == 0);
  32. while (mTextureIdsSystem.size() < 2) {
  33. unsigned int id;
  34. glGenTextures(1, &id);
  35. mTextureIdsSystem.push_back(id);
  36. }
  37. return 0;
  38. }
  39. int TextureManager::initializeSplash() {
  40. unsigned char* image = generateColorTexture(WHITE, 32, 32, 32);
  41. int res = loadBufferSlot(image, 32, 32, ColorMode::RGBA, 32, TextureStorage::SYSTEM, TEXTURE_WHITE,
  42. false);
  43. delete [] image;
  44. if (res < 0) {
  45. return -1;
  46. }
  47. Folder f(RunTime::getPakDir());
  48. std::vector<File> files;
  49. f.findRecursiveFilesEndingWith(files, ".pcx");
  50. if (files.size() == 0) {
  51. if (loadImage(RunTime::getDataDir() + "/splash.tga", TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  52. return -2;
  53. }
  54. } else {
  55. int i = randomInteger(files.size() - 1);
  56. if (loadImage(files.at(i).getPath(), TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  57. if (loadImage(RunTime::getDataDir() + "/splash.tga", TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  58. return -3;
  59. }
  60. }
  61. }
  62. return 0;
  63. }
  64. void TextureManager::shutdown() {
  65. while (mTextureIdsSystem.size() > 0) {
  66. unsigned int id = mTextureIdsSystem.at(mTextureIdsSystem.size() - 1);
  67. glDeleteTextures(1, &id);
  68. mTextureIdsSystem.pop_back();
  69. }
  70. clear();
  71. }
  72. void TextureManager::clear() {
  73. while (mTextureIdsGame.size() > 0) {
  74. unsigned int id = mTextureIdsGame.at(mTextureIdsGame.size() - 1);
  75. glDeleteTextures(1, &id);
  76. mTextureIdsGame.pop_back();
  77. }
  78. while (!tiles.empty()) {
  79. delete tiles.at(tiles.size() - 1);
  80. tiles.pop_back();
  81. }
  82. animations.clear();
  83. gameUnits.clear();
  84. systemUnits.clear();
  85. nextFreeTextureUnit = 0;
  86. }
  87. int TextureManager::loadBufferSlot(unsigned char* image,
  88. unsigned int width, unsigned int height,
  89. ColorMode mode, unsigned int bpp,
  90. TextureStorage s, int slot, bool filter) {
  91. assert(width > 0);
  92. assert(height > 0);
  93. assert((mode == ColorMode::RGB)
  94. || (mode == ColorMode::BGR)
  95. || (mode == ColorMode::ARGB)
  96. || (mode == ColorMode::RGBA)
  97. || (mode == ColorMode::BGRA));
  98. assert((bpp == 8) || (bpp == 24) || (bpp == 32));
  99. if (slot < 0)
  100. slot = getIds(s).size();
  101. while (getIds(s).size() <= slot) {
  102. unsigned int id;
  103. glGenTextures(1, &id);
  104. getIds(s).push_back(id);
  105. }
  106. if (image == nullptr)
  107. return slot;
  108. unsigned int glcMode;
  109. switch (mode) {
  110. case ColorMode::BGR:
  111. glcMode = GL_BGR;
  112. break;
  113. case ColorMode::RGB:
  114. glcMode = GL_RGB;
  115. break;
  116. case ColorMode::ARGB:
  117. argb2rgba32(image, width, height);
  118. glcMode = GL_RGBA;
  119. break;
  120. case ColorMode::BGRA:
  121. glcMode = GL_BGRA;
  122. break;
  123. case ColorMode::RGBA:
  124. glcMode = GL_RGBA;
  125. break;
  126. }
  127. glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  128. bindTexture(slot, s);
  129. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, glcMode, GL_UNSIGNED_BYTE, image);
  130. if (filter) {
  131. // Trilinear filtering
  132. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  133. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  134. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  135. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  136. glGenerateMipmap(GL_TEXTURE_2D);
  137. } else {
  138. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  139. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  140. }
  141. return slot;
  142. }
  143. int TextureManager::numTextures(TextureStorage s) {
  144. return getIds(s).size();
  145. }
  146. void TextureManager::bindTextureId(unsigned int n, TextureStorage s, unsigned int unit) {
  147. assert(n < getIds(s).size());
  148. assert(unit < 80); //! \todo Query GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
  149. glActiveTexture(GL_TEXTURE0 + unit);
  150. glBindTexture(GL_TEXTURE_2D, getIds(s).at(n));
  151. }
  152. int TextureManager::bindTexture(unsigned int n, TextureStorage s) {
  153. assert(n < getIds(s).size());
  154. if ((n < getUnits(s).size()) && (getUnits(s).at(n) >= 0)) {
  155. bindTextureId(n, s, getUnits(s).at(n));
  156. return getUnits(s).at(n);
  157. } else {
  158. while (getUnits(s).size() <= n)
  159. getUnits(s).push_back(-1);
  160. getUnits(s).at(n) = nextFreeTextureUnit;
  161. bindTextureId(n, s, nextFreeTextureUnit);
  162. nextFreeTextureUnit++;
  163. return nextFreeTextureUnit - 1;
  164. }
  165. }
  166. void TextureManager::addTile(TextureTile* t) {
  167. tiles.push_back(t);
  168. }
  169. int TextureManager::numTiles() {
  170. return tiles.size();
  171. }
  172. TextureTile& TextureManager::getTile(int index) {
  173. assert(index >= 0);
  174. assert(index < tiles.size());
  175. return *tiles.at(index);
  176. }
  177. void TextureManager::addAnimatedTile(int index, int tile) {
  178. while (index >= animations.size())
  179. animations.push_back(std::vector<int>());
  180. animations.at(index).push_back(tile);
  181. }
  182. int TextureManager::numAnimatedTiles() {
  183. return animations.size();
  184. }
  185. int TextureManager::getFirstTileAnimation(int index) {
  186. assert(index < animations.size());
  187. assert(animations.at(index).size() > 0);
  188. return animations.at(index).at(0);
  189. }
  190. int TextureManager::getNextTileAnimation(int tile) {
  191. for (int a = 0; a < animations.size(); a++) {
  192. for (int i = 0; i < animations.at(a).size(); i++) {
  193. if (animations.at(a).at(i) == tile) {
  194. if (i < (animations.at(a).size() - 1))
  195. return animations.at(a).at(i + 1);
  196. else
  197. return animations.at(a).at(0);
  198. }
  199. }
  200. }
  201. return -1;
  202. }
  203. int TextureManager::loadImage(std::string filename, TextureStorage s, int slot) {
  204. if (stringEndsWith(filename, ".pcx")) {
  205. return loadPCX(filename, s, slot);
  206. } else {
  207. int x, y, n;
  208. unsigned char* data = stbi_load(filename.c_str(), &x, &y, &n, 0);
  209. if (data) {
  210. if ((n < 3) || (n > 4)) {
  211. getLog() << "Image \"" << filename << "\" has unsupported format ("
  212. << n << ")!" << Log::endl;
  213. stbi_image_free(data);
  214. return -2;
  215. }
  216. int id = loadBufferSlot(data, x, y, (n == 3) ? ColorMode::RGB : ColorMode::RGBA,
  217. (n == 3) ? 24 : 32, s, slot);
  218. stbi_image_free(data);
  219. return id;
  220. } else {
  221. getLog() << "Can't load image \"" << filename << "\"!" << Log::endl;
  222. return -1;
  223. }
  224. }
  225. }
  226. int TextureManager::loadPCX(std::string filename, TextureStorage s, int slot) {
  227. int error = pcxCheck(filename.c_str());
  228. if (!error) {
  229. unsigned char* image;
  230. unsigned int w, h, bpp;
  231. ColorMode c;
  232. error = pcxLoad(filename.c_str(), &image, &w, &h, &c, &bpp);
  233. if (!error) {
  234. unsigned char* image2 = scaleBuffer(image, &w, &h, bpp);
  235. if (image2) {
  236. delete [] image;
  237. image = image2;
  238. }
  239. int id = loadBufferSlot(image, w, h, c, bpp, s, slot);
  240. delete [] image;
  241. return id;
  242. }
  243. return -5;
  244. }
  245. return -4;
  246. }
  247. std::vector<unsigned int>& TextureManager::getIds(TextureStorage s) {
  248. if (s == TextureStorage::GAME)
  249. return mTextureIdsGame;
  250. else
  251. return mTextureIdsSystem;
  252. }
  253. std::vector<int>& TextureManager::getUnits(TextureStorage s) {
  254. if (s == TextureStorage::GAME)
  255. return gameUnits;
  256. else
  257. return systemUnits;
  258. }
  259. // ----------------------------------------------------------------------------
  260. glm::vec2 TextureTile::getUV(unsigned int i) {
  261. glm::vec2 uv(vertices.at(i).xPixel,
  262. vertices.at(i).yPixel);
  263. /*! \fixme
  264. * This is my somewhat hacky approach to fixing
  265. * the bad texture-bleeding problems everywhere.
  266. * That's better, but makes the seams between
  267. * each sector much more visible!
  268. */
  269. if (vertices.at(i).xCoordinate == 1) {
  270. uv.x += 0.375f;
  271. }
  272. if (vertices.at(i).yCoordinate == 1) {
  273. uv.y += 0.375f;
  274. }
  275. return uv / 256.0f;
  276. }