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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*!
  2. * \file src/TextureManager.cpp
  3. * \brief Texture registry
  4. *
  5. * \author Mongoose
  6. * \author xythobuz
  7. */
  8. #include "stb/stb_image.h"
  9. #include "global.h"
  10. #include "Log.h"
  11. #include "RunTime.h"
  12. #include "utils/Folder.h"
  13. #include "utils/pcx.h"
  14. #include "utils/pixel.h"
  15. #include "utils/random.h"
  16. #include "utils/strings.h"
  17. #include "TextureManager.h"
  18. std::vector<unsigned int> TextureManager::mTextureIdsGame;
  19. std::vector<unsigned int> TextureManager::mTextureIdsSystem;
  20. std::vector<TextureTile*> TextureManager::tiles;
  21. std::vector<std::vector<int>> TextureManager::animations;
  22. std::vector<int> TextureManager::gameUnits;
  23. std::vector<int> TextureManager::systemUnits;
  24. unsigned int TextureManager::nextFreeTextureUnit = 0;
  25. std::vector<BufferManager> TextureManager::gameBuffers;
  26. std::vector<BufferManager> TextureManager::systemBuffers;
  27. int TextureManager::initialize() {
  28. assert(mTextureIdsGame.size() == 0);
  29. assert(mTextureIdsSystem.size() == 0);
  30. while (mTextureIdsSystem.size() < 2) {
  31. unsigned int id;
  32. glGenTextures(1, &id);
  33. mTextureIdsSystem.push_back(id);
  34. }
  35. unsigned char* image = generateColorTexture(WHITE, 32, 32, 32);
  36. int res = loadBufferSlot(image, 32, 32, ColorMode::RGBA, 32, TextureStorage::SYSTEM, TEXTURE_WHITE,
  37. false);
  38. delete [] image;
  39. if (res < 0) {
  40. return -1;
  41. }
  42. return 0;
  43. }
  44. int TextureManager::initializeSplash() {
  45. Folder f(RunTime::getPakDir());
  46. std::vector<File> files;
  47. f.findRecursiveFilesEndingWith(files, ".pcx");
  48. if (files.size() == 0) {
  49. if (loadImage(RunTime::getDataDir() + "/splash.tga", TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  50. return -2;
  51. }
  52. } else {
  53. int i = randomInteger(files.size() - 1);
  54. if (loadImage(files.at(i).getPath(), TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  55. if (loadImage(RunTime::getDataDir() + "/splash.tga", TextureStorage::SYSTEM, TEXTURE_SPLASH) < 0) {
  56. return -3;
  57. }
  58. }
  59. }
  60. return 0;
  61. }
  62. void TextureManager::shutdown() {
  63. while (mTextureIdsSystem.size() > 0) {
  64. unsigned int id = mTextureIdsSystem.at(mTextureIdsSystem.size() - 1);
  65. glDeleteTextures(1, &id);
  66. mTextureIdsSystem.pop_back();
  67. }
  68. clear();
  69. systemBuffers.clear();
  70. }
  71. void TextureManager::clear() {
  72. while (mTextureIdsGame.size() > 0) {
  73. unsigned int id = mTextureIdsGame.at(mTextureIdsGame.size() - 1);
  74. glDeleteTextures(1, &id);
  75. mTextureIdsGame.pop_back();
  76. }
  77. while (!tiles.empty()) {
  78. delete tiles.at(tiles.size() - 1);
  79. tiles.pop_back();
  80. }
  81. animations.clear();
  82. gameUnits.clear();
  83. systemUnits.clear();
  84. nextFreeTextureUnit = 0;
  85. gameBuffers.clear();
  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. Log::get(LOG_DEBUG) << "New Texture: " << slot << " - "
  142. << ((s == TextureStorage::GAME) ? "Game" : "System") << Log::endl;
  143. return slot;
  144. }
  145. int TextureManager::numTextures(TextureStorage s) {
  146. return getIds(s).size();
  147. }
  148. void TextureManager::bindTextureId(unsigned int n, TextureStorage s, unsigned int unit) {
  149. assert(n < getIds(s).size());
  150. assert(unit < 80); //! \todo Query GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
  151. glActiveTexture(GL_TEXTURE0 + unit);
  152. glBindTexture(GL_TEXTURE_2D, getIds(s).at(n));
  153. }
  154. int TextureManager::bindTexture(unsigned int n, TextureStorage s) {
  155. if (n >= getIds(s).size()) {
  156. Log::get(LOG_DEBUG) << "Bound Unknown Texture " << n << " in "
  157. << ((s == TextureStorage::GAME) ? "Game" : "System") << Log::endl;
  158. }
  159. assert(n < getIds(s).size());
  160. if ((n < getUnits(s).size()) && (getUnits(s).at(n) >= 0)) {
  161. bindTextureId(n, s, getUnits(s).at(n));
  162. return getUnits(s).at(n);
  163. } else {
  164. while (getUnits(s).size() <= n)
  165. getUnits(s).push_back(-1);
  166. getUnits(s).at(n) = nextFreeTextureUnit;
  167. bindTextureId(n, s, nextFreeTextureUnit);
  168. nextFreeTextureUnit++;
  169. return nextFreeTextureUnit - 1;
  170. }
  171. }
  172. void TextureManager::addTile(TextureTile* t) {
  173. tiles.push_back(t);
  174. }
  175. int TextureManager::numTiles() {
  176. return tiles.size();
  177. }
  178. TextureTile& TextureManager::getTile(int index) {
  179. assert(index >= 0);
  180. assert(index < tiles.size());
  181. return *tiles.at(index);
  182. }
  183. void TextureManager::addAnimatedTile(int index, int tile) {
  184. while (index >= animations.size())
  185. animations.push_back(std::vector<int>());
  186. animations.at(index).push_back(tile);
  187. }
  188. int TextureManager::numAnimatedTiles() {
  189. return animations.size();
  190. }
  191. int TextureManager::getFirstTileAnimation(int index) {
  192. assert(index < animations.size());
  193. assert(animations.at(index).size() > 0);
  194. return animations.at(index).at(0);
  195. }
  196. int TextureManager::getNextTileAnimation(int tile) {
  197. for (int a = 0; a < animations.size(); a++) {
  198. for (int i = 0; i < animations.at(a).size(); i++) {
  199. if (animations.at(a).at(i) == tile) {
  200. if (i < (animations.at(a).size() - 1))
  201. return animations.at(a).at(i + 1);
  202. else
  203. return animations.at(a).at(0);
  204. }
  205. }
  206. }
  207. return -1;
  208. }
  209. BufferManager* TextureManager::getBufferManager(int tex, TextureStorage store) {
  210. auto& v = (store == TextureStorage::GAME) ? gameBuffers : systemBuffers;
  211. while (v.size() <= tex) {
  212. v.emplace_back(v.size(), store);
  213. Log::get(LOG_DEBUG) << "New BufferManager: " << v.size() - 1 << " - "
  214. << ((store == TextureStorage::GAME) ? "Game" : "System") << Log::endl;
  215. }
  216. return &(v.at(tex));
  217. }
  218. int TextureManager::loadImage(std::string filename, TextureStorage s, int slot) {
  219. if (stringEndsWith(filename, ".pcx")) {
  220. return loadPCX(filename, s, slot);
  221. } else {
  222. int x, y, n;
  223. unsigned char* data = stbi_load(filename.c_str(), &x, &y, &n, 0);
  224. if (data) {
  225. if ((n < 3) || (n > 4)) {
  226. Log::get(LOG_ERROR) << "Image \"" << filename << "\" has unsupported format ("
  227. << n << ")!" << Log::endl;
  228. stbi_image_free(data);
  229. return -2;
  230. }
  231. int id = loadBufferSlot(data, x, y, (n == 3) ? ColorMode::RGB : ColorMode::RGBA,
  232. (n == 3) ? 24 : 32, s, slot);
  233. stbi_image_free(data);
  234. return id;
  235. } else {
  236. Log::get(LOG_ERROR) << "Can't load image \"" << filename << "\"!" << Log::endl;
  237. return -1;
  238. }
  239. }
  240. }
  241. int TextureManager::loadPCX(std::string filename, TextureStorage s, int slot) {
  242. int error = pcxCheck(filename.c_str());
  243. if (!error) {
  244. unsigned char* image;
  245. unsigned int w, h, bpp;
  246. ColorMode c;
  247. error = pcxLoad(filename.c_str(), &image, &w, &h, &c, &bpp);
  248. if (!error) {
  249. unsigned char* image2 = scaleBuffer(image, &w, &h, bpp);
  250. if (image2) {
  251. delete [] image;
  252. image = image2;
  253. }
  254. int id = loadBufferSlot(image, w, h, c, bpp, s, slot);
  255. delete [] image;
  256. return id;
  257. }
  258. return -5;
  259. }
  260. return -4;
  261. }
  262. std::vector<unsigned int>& TextureManager::getIds(TextureStorage s) {
  263. if (s == TextureStorage::GAME)
  264. return mTextureIdsGame;
  265. else
  266. return mTextureIdsSystem;
  267. }
  268. std::vector<int>& TextureManager::getUnits(TextureStorage s) {
  269. if (s == TextureStorage::GAME)
  270. return gameUnits;
  271. else
  272. return systemUnits;
  273. }
  274. // ----------------------------------------------------------------------------
  275. glm::vec2 TextureTile::getUV(unsigned int i) {
  276. glm::vec2 uv(vertices.at(i).xPixel,
  277. vertices.at(i).yPixel);
  278. /*! \fixme
  279. * This is my somewhat hacky approach to fixing
  280. * the bad texture-bleeding problems everywhere.
  281. * That's better, but makes the seams between
  282. * each sector much more visible!
  283. */
  284. if (vertices.at(i).xCoordinate == 1) {
  285. uv.x += 0.375f;
  286. }
  287. if (vertices.at(i).yCoordinate == 1) {
  288. uv.y += 0.375f;
  289. }
  290. return uv / 256.0f;
  291. }