You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

299 rivejä
7.1 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 <cmath>
  16. #include <cstring>
  17. #if defined WIN32 && !defined _XBOX
  18. # define WIN32_LEAN_AND_MEAN
  19. # include <windows.h>
  20. # if defined USE_D3D9
  21. # define FAR
  22. # define NEAR
  23. # include <d3d9.h>
  24. # endif
  25. #endif
  26. #include "core.h"
  27. #include "lolgl.h"
  28. using namespace std;
  29. #if defined USE_D3D9
  30. extern IDirect3DDevice9 *g_d3ddevice;
  31. #elif defined _XBOX
  32. extern D3DDevice *g_d3ddevice;
  33. #endif
  34. namespace lol
  35. {
  36. /*
  37. * TileSet implementation class
  38. */
  39. class TileSetData
  40. {
  41. friend class TileSet;
  42. private:
  43. char *name, *path;
  44. int *tiles, ntiles;
  45. ivec2 size, isize, count;
  46. vec2 scale;
  47. float tx, ty;
  48. Image *img;
  49. #if defined USE_D3D9
  50. IDirect3DTexture9 *m_tex;
  51. #elif defined _XBOX
  52. D3DTexture *m_tex;
  53. #else
  54. GLuint m_tex;
  55. #endif
  56. };
  57. /*
  58. * Public TileSet class
  59. */
  60. TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
  61. : data(new TileSetData())
  62. {
  63. data->name = (char *)malloc(10 + strlen(path) + 1);
  64. data->path = data->name + 10;
  65. sprintf(data->name, "<tileset> %s", path);
  66. data->tiles = NULL;
  67. data->m_tex = 0;
  68. data->img = new Image(path);
  69. data->isize = data->img->GetSize();
  70. if (count.x > 0 && count.y > 0)
  71. {
  72. data->count = count;
  73. data->size = data->isize / count;
  74. }
  75. else
  76. {
  77. if (size.x <= 0 || size.y <= 0)
  78. size = ivec2(32, 32);
  79. data->count.x = data->isize.x > size.x ? data->isize.x / size.x : 1;
  80. data->count.y = data->isize.y > size.y ? data->isize.y / size.y : 1;
  81. data->size = size;
  82. }
  83. data->tx = (float)data->size.x / PotUp(data->isize.x);
  84. data->ty = (float)data->size.y / PotUp(data->isize.y);
  85. data->ntiles = data->count.x * data->count.y;
  86. m_drawgroup = DRAWGROUP_BEFORE;
  87. }
  88. TileSet::~TileSet()
  89. {
  90. free(data->tiles);
  91. free(data->name);
  92. delete data;
  93. }
  94. void TileSet::TickDraw(float deltams)
  95. {
  96. Entity::TickDraw(deltams);
  97. if (IsDestroying())
  98. {
  99. if (data->img)
  100. delete data->img;
  101. else
  102. #if defined USE_D3D9 || defined _XBOX
  103. /* FIXME: is it really the correct call? */
  104. data->m_tex->Release();
  105. #else
  106. glDeleteTextures(1, &data->m_tex);
  107. #endif
  108. }
  109. else if (data->img)
  110. {
  111. #if defined USE_D3D9 || defined _XBOX
  112. D3DFORMAT format;
  113. #else
  114. GLuint format;
  115. #endif
  116. int planes;
  117. switch (data->img->GetFormat())
  118. {
  119. case Image::FORMAT_RGB:
  120. #if defined USE_D3D9
  121. format = D3DFMT_R8G8B8;
  122. #elif defined _XBOX
  123. format = D3DFMT_LIN_R8G8B8; /* FIXME */
  124. #else
  125. format = GL_RGB;
  126. #endif
  127. planes = 3;
  128. break;
  129. case Image::FORMAT_RGBA:
  130. default:
  131. #if defined USE_D3D9
  132. format = D3DFMT_A8R8G8B8;
  133. #elif defined _XBOX
  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. # if defined USE_D3D9
  156. g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_DYNAMIC, format,
  157. D3DPOOL_SYSTEMMEM, &data->m_tex, NULL);
  158. data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
  159. # elif defined _XBOX
  160. /* By default the X360 will swizzle the texture. Ask for linear. */
  161. g_d3ddevice->CreateTexture(w, h, 1, D3DUSAGE_WRITEONLY, format,
  162. D3DPOOL_DEFAULT, &data->m_tex, NULL);
  163. data->m_tex->LockRect(0, &rect, NULL, D3DLOCK_NOOVERWRITE);
  164. # endif
  165. for (int j = 0; j < h; j++)
  166. memcpy((uint8_t *)rect.pBits + j * rect.Pitch, pixels + w * j * 4, w * 4);
  167. data->m_tex->UnlockRect(0);
  168. #else
  169. glGenTextures(1, &data->m_tex);
  170. glEnable(GL_TEXTURE_2D);
  171. glBindTexture(GL_TEXTURE_2D, data->m_tex);
  172. glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
  173. format, GL_UNSIGNED_BYTE, pixels);
  174. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  175. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  176. #endif
  177. if (pixels != data->img->GetData())
  178. free(pixels);
  179. delete data->img;
  180. data->img = NULL;
  181. }
  182. }
  183. char const *TileSet::GetName()
  184. {
  185. return data->name;
  186. }
  187. ivec2 TileSet::GetCount() const
  188. {
  189. return data->count;
  190. }
  191. ivec2 TileSet::GetSize(int tileid) const
  192. {
  193. return data->size;
  194. }
  195. void TileSet::Bind()
  196. {
  197. if (!data->img && data->m_tex)
  198. {
  199. #if defined USE_D3D9 || defined _XBOX
  200. g_d3ddevice->SetTexture(0, data->m_tex);
  201. #else
  202. glActiveTexture(GL_TEXTURE0);
  203. glBindTexture(GL_TEXTURE_2D, data->m_tex);
  204. #endif
  205. }
  206. }
  207. void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
  208. float *vertex, float *texture)
  209. {
  210. float tx = data->tx * ((id & 0xffff) % data->count.x);
  211. float ty = data->ty * ((id & 0xffff) / data->count.x);
  212. int dx = data->size.x * scale.x;
  213. int dy = o ? 0 : data->size.y * scale.y;
  214. int dz = o ? data->size.y * scale.y : 0;
  215. if (!data->img && data->m_tex)
  216. {
  217. float tmp[10];
  218. *vertex++ = tmp[0] = pos.x;
  219. *vertex++ = tmp[1] = pos.y + dy;
  220. *vertex++ = tmp[2] = pos.z + dz;
  221. *texture++ = tmp[3] = tx;
  222. *texture++ = tmp[4] = ty;
  223. *vertex++ = pos.x + dx;
  224. *vertex++ = pos.y + dy;
  225. *vertex++ = pos.z + dz;
  226. *texture++ = tx + data->tx;
  227. *texture++ = ty;
  228. *vertex++ = tmp[5] = pos.x + dx;
  229. *vertex++ = tmp[6] = pos.y;
  230. *vertex++ = tmp[7] = pos.z;
  231. *texture++ = tmp[8] = tx + data->tx;
  232. *texture++ = tmp[9] = ty + data->ty;
  233. *vertex++ = tmp[0];
  234. *vertex++ = tmp[1];
  235. *vertex++ = tmp[2];
  236. *texture++ = tmp[3];
  237. *texture++ = tmp[4];
  238. *vertex++ = tmp[5];
  239. *vertex++ = tmp[6];
  240. *vertex++ = tmp[7];
  241. *texture++ = tmp[8];
  242. *texture++ = tmp[9];
  243. *vertex++ = pos.x;
  244. *vertex++ = pos.y;
  245. *vertex++ = pos.z;
  246. *texture++ = tx;
  247. *texture++ = ty + data->ty;
  248. }
  249. else
  250. {
  251. memset(vertex, 0, 3 * sizeof(float));
  252. memset(texture, 0, 2 * sizeof(float));
  253. }
  254. }
  255. } /* namespace lol */