No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

325 líneas
7.6 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstdlib>
  14. #include <cstdio>
  15. #include <cstring>
  16. #if defined WIN32 && !defined _XBOX
  17. # define WIN32_LEAN_AND_MEAN
  18. # include <windows.h>
  19. # if defined USE_D3D9
  20. # define FAR
  21. # define NEAR
  22. # include <d3d9.h>
  23. # endif
  24. #endif
  25. #include "core.h"
  26. #include "lolgl.h"
  27. using namespace std;
  28. #if defined USE_D3D9
  29. extern IDirect3DDevice9 *g_d3ddevice;
  30. #elif defined _XBOX
  31. extern D3DDevice *g_d3ddevice;
  32. #endif
  33. namespace lol
  34. {
  35. /*
  36. * TileSet implementation class
  37. */
  38. class TileSetData
  39. {
  40. friend class TileSet;
  41. private:
  42. char *name, *path;
  43. int *tiles, ntiles;
  44. ivec2 size, isize, count;
  45. vec2 scale;
  46. float tx, ty;
  47. Image *img;
  48. #if defined USE_D3D9
  49. IDirect3DTexture9 *m_tex;
  50. #elif defined _XBOX
  51. D3DTexture *m_tex;
  52. #else
  53. GLuint m_tex;
  54. #endif
  55. };
  56. /*
  57. * Public TileSet class
  58. */
  59. TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
  60. : data(new TileSetData())
  61. {
  62. data->name = (char *)malloc(10 + strlen(path) + 1);
  63. data->path = data->name + 10;
  64. sprintf(data->name, "<tileset> %s", path);
  65. data->tiles = NULL;
  66. data->m_tex = 0;
  67. data->img = new Image(path);
  68. data->isize = data->img->GetSize();
  69. if (count.x > 0 && count.y > 0)
  70. {
  71. data->count = count;
  72. data->size = data->isize / count;
  73. }
  74. else
  75. {
  76. if (size.x <= 0 || size.y <= 0)
  77. size = ivec2(32, 32);
  78. data->count.x = data->isize.x > size.x ? data->isize.x / size.x : 1;
  79. data->count.y = data->isize.y > size.y ? data->isize.y / size.y : 1;
  80. data->size = size;
  81. }
  82. data->tx = (float)data->size.x / PotUp(data->isize.x);
  83. data->ty = (float)data->size.y / PotUp(data->isize.y);
  84. data->ntiles = data->count.x * data->count.y;
  85. m_drawgroup = DRAWGROUP_BEFORE;
  86. }
  87. TileSet::~TileSet()
  88. {
  89. free(data->tiles);
  90. free(data->name);
  91. delete data;
  92. }
  93. void TileSet::TickDraw(float seconds)
  94. {
  95. Entity::TickDraw(seconds);
  96. if (IsDestroying())
  97. {
  98. if (data->img)
  99. delete data->img;
  100. else
  101. #if defined USE_D3D9 || defined _XBOX
  102. /* FIXME: is it really the correct call? */
  103. data->m_tex->Release();
  104. #else
  105. glDeleteTextures(1, &data->m_tex);
  106. #endif
  107. }
  108. else if (data->img)
  109. {
  110. #if defined USE_D3D9 || defined _XBOX
  111. D3DFORMAT format;
  112. #else
  113. GLuint format;
  114. #endif
  115. int planes;
  116. switch (data->img->GetFormat())
  117. {
  118. case Image::FORMAT_RGB:
  119. #if defined USE_D3D9
  120. format = D3DFMT_R8G8B8;
  121. #elif defined _XBOX
  122. format = D3DFMT_LIN_A8R8G8B8; /* FIXME */
  123. #else
  124. format = GL_RGB;
  125. #endif
  126. planes = 3;
  127. break;
  128. case Image::FORMAT_RGBA:
  129. default:
  130. #if defined USE_D3D9
  131. format = D3DFMT_A8R8G8B8;
  132. #elif defined _XBOX
  133. /* By default the X360 will swizzle the texture. Ask for linear. */
  134. format = D3DFMT_LIN_A8R8G8B8;
  135. #else
  136. format = GL_RGBA;
  137. #endif
  138. planes = 4;
  139. break;
  140. }
  141. int w = PotUp(data->isize.x);
  142. int h = PotUp(data->isize.y);
  143. uint8_t *pixels = (uint8_t *)data->img->GetData();
  144. if (w != data->isize.x || h != data->isize.y)
  145. {
  146. uint8_t *tmp = (uint8_t *)malloc(planes * w * h);
  147. for (int line = 0; line < data->isize.y; line++)
  148. memcpy(tmp + planes * w * line,
  149. pixels + planes * data->isize.x * line,
  150. planes * data->isize.x);
  151. pixels = tmp;
  152. }
  153. #if defined USE_D3D9 || defined _XBOX
  154. D3DLOCKED_RECT rect;
  155. HRESULT hr;
  156. # if defined USE_D3D9
  157. hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_DYNAMIC, format,
  158. D3DPOOL_DEFAULT, &data->m_tex, NULL);
  159. # elif defined _XBOX
  160. hr = g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_WRITEONLY, format,
  161. D3DPOOL_DEFAULT, &data->m_tex, NULL);
  162. # endif
  163. if (FAILED(hr))
  164. Abort();
  165. # if defined USE_D3D9
  166. hr = data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
  167. # else
  168. hr = data->m_tex->LockRect(0, &rect, NULL, 0);
  169. # endif
  170. if (FAILED(hr))
  171. Abort();
  172. for (int j = 0; j < h; j++)
  173. memcpy((uint8_t *)rect.pBits + j * rect.Pitch, pixels + w * j * 4, w * 4);
  174. hr = data->m_tex->UnlockRect(0);
  175. if (FAILED(hr))
  176. Abort();
  177. #else
  178. glGenTextures(1, &data->m_tex);
  179. glEnable(GL_TEXTURE_2D);
  180. glBindTexture(GL_TEXTURE_2D, data->m_tex);
  181. glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
  182. format, GL_UNSIGNED_BYTE, pixels);
  183. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  184. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  185. #endif
  186. if (pixels != data->img->GetData())
  187. free(pixels);
  188. delete data->img;
  189. data->img = NULL;
  190. }
  191. }
  192. char const *TileSet::GetName()
  193. {
  194. return data->name;
  195. }
  196. ivec2 TileSet::GetCount() const
  197. {
  198. return data->count;
  199. }
  200. ivec2 TileSet::GetSize(int tileid) const
  201. {
  202. return data->size;
  203. }
  204. void TileSet::Bind()
  205. {
  206. if (!data->img && data->m_tex)
  207. {
  208. #if defined USE_D3D9 || defined _XBOX
  209. HRESULT hr = g_d3ddevice->SetTexture(0, data->m_tex);
  210. if (FAILED(hr))
  211. Abort();
  212. #else
  213. glActiveTexture(GL_TEXTURE0);
  214. glBindTexture(GL_TEXTURE_2D, data->m_tex);
  215. #endif
  216. }
  217. }
  218. void TileSet::Unbind()
  219. {
  220. if (!data->img && data->m_tex)
  221. {
  222. #if defined USE_D3D9 || defined _XBOX
  223. HRESULT hr = g_d3ddevice->SetTexture(0, NULL);
  224. if (FAILED(hr))
  225. Abort();
  226. #else
  227. glActiveTexture(GL_TEXTURE0);
  228. glBindTexture(GL_TEXTURE_2D, 0);
  229. #endif
  230. }
  231. }
  232. void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
  233. float *vertex, float *texture)
  234. {
  235. float tx = data->tx * ((id & 0xffff) % data->count.x);
  236. float ty = data->ty * ((id & 0xffff) / data->count.x);
  237. int dx = data->size.x * scale.x;
  238. int dy = o ? 0 : data->size.y * scale.y;
  239. int dz = o ? data->size.y * scale.y : 0;
  240. if (!data->img && data->m_tex)
  241. {
  242. float tmp[10];
  243. *vertex++ = pos.x + dx;
  244. *vertex++ = pos.y + dy;
  245. *vertex++ = pos.z + dz;
  246. *texture++ = tx + data->tx;
  247. *texture++ = ty;
  248. *vertex++ = tmp[0] = pos.x;
  249. *vertex++ = tmp[1] = pos.y + dy;
  250. *vertex++ = tmp[2] = pos.z + dz;
  251. *texture++ = tmp[3] = tx;
  252. *texture++ = tmp[4] = ty;
  253. *vertex++ = tmp[5] = pos.x + dx;
  254. *vertex++ = tmp[6] = pos.y;
  255. *vertex++ = tmp[7] = pos.z;
  256. *texture++ = tmp[8] = tx + data->tx;
  257. *texture++ = tmp[9] = ty + data->ty;
  258. *vertex++ = tmp[5];
  259. *vertex++ = tmp[6];
  260. *vertex++ = tmp[7];
  261. *texture++ = tmp[8];
  262. *texture++ = tmp[9];
  263. *vertex++ = tmp[0];
  264. *vertex++ = tmp[1];
  265. *vertex++ = tmp[2];
  266. *texture++ = tmp[3];
  267. *texture++ = tmp[4];
  268. *vertex++ = pos.x;
  269. *vertex++ = pos.y;
  270. *vertex++ = pos.z;
  271. *texture++ = tx;
  272. *texture++ = ty + data->ty;
  273. }
  274. else
  275. {
  276. memset(vertex, 0, 3 * sizeof(float));
  277. memset(texture, 0, 2 * sizeof(float));
  278. }
  279. }
  280. } /* namespace lol */