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.
 
 
 

204 líneas
4.7 KiB

  1. #ifdef WIN32
  2. # define WIN32_LEAN_AND_MEAN
  3. # include <windows.h>
  4. #endif
  5. #if defined __APPLE__ && defined __MACH__
  6. # include <OpenGL/gl.h>
  7. #else
  8. # define GL_GLEXT_PROTOTYPES
  9. # include <GL/gl.h>
  10. # include <GL/glext.h>
  11. #endif
  12. #include <SDL.h>
  13. #include <SDL_image.h>
  14. #include <malloc.h>
  15. #include "tileset.h"
  16. /*
  17. * TileSet implementation class
  18. */
  19. class TileSetData
  20. {
  21. friend class TileSet;
  22. private:
  23. static int Compare(void const *p1, void const *p2)
  24. {
  25. int const *n1 = (int const *)p1;
  26. int const *n2 = (int const *)p2;
  27. return n1[2] + 32 * n1[3] - (n2[2] + 32 * n2[3]);
  28. }
  29. char *name;
  30. int ref;
  31. int *tiles;
  32. int ntiles;
  33. GLuint texture[1];
  34. GLuint buflist[3];
  35. };
  36. /*
  37. * Public TileSet class
  38. */
  39. TileSet::TileSet(char const *path)
  40. {
  41. SDL_Surface *img = NULL;
  42. data = new TileSetData();
  43. data->name = strdup(path);
  44. data->ref = 0;
  45. data->tiles = NULL;
  46. data->ntiles = 0;
  47. /* One tile texture */
  48. for (char const *name = path; *name; name++)
  49. if ((img = IMG_Load(name)))
  50. break;
  51. if (!img)
  52. {
  53. SDL_Quit();
  54. exit(1);
  55. }
  56. glGenTextures(1, data->texture);
  57. glBindTexture(GL_TEXTURE_2D, data->texture[0]);
  58. glTexImage2D(GL_TEXTURE_2D, 0, 4, img->w, img->h, 0,
  59. GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);
  60. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  61. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  62. /* Three GPU buffers */
  63. glGenBuffers(3, data->buflist);
  64. }
  65. TileSet::~TileSet()
  66. {
  67. glDeleteTextures(1, data->texture);
  68. glDeleteBuffers(3, data->buflist);
  69. free(data->tiles);
  70. free(data->name);
  71. delete data;
  72. }
  73. void TileSet::Ref()
  74. {
  75. data->ref++;
  76. }
  77. int TileSet::Unref()
  78. {
  79. return --data->ref;
  80. }
  81. char const *TileSet::GetName()
  82. {
  83. return data->name;
  84. }
  85. void TileSet::AddTile(int n, int x, int y, int z)
  86. {
  87. if ((data->ntiles % 1024) == 0)
  88. {
  89. data->tiles = (int *)realloc(data->tiles,
  90. (data->ntiles + 1024) * 4 * sizeof(int));
  91. }
  92. data->tiles[4 * data->ntiles] = n;
  93. data->tiles[4 * data->ntiles + 1] = x;
  94. data->tiles[4 * data->ntiles + 2] = y;
  95. data->tiles[4 * data->ntiles + 3] = z;
  96. data->ntiles++;
  97. }
  98. void TileSet::Render()
  99. {
  100. /* Sort tiles */
  101. qsort(data->tiles, data->ntiles, 4 * sizeof(int), TileSetData::Compare);
  102. /* Texture coord buffer */
  103. float uvs[8 * data->ntiles];
  104. for (int n = 0; n < data->ntiles; n++)
  105. {
  106. int tile = data->tiles[4 * n];
  107. float ty = .0625f * (tile / 16);
  108. float tx = .0625f * (tile % 16);
  109. uvs[8 * n + 0] = tx;
  110. uvs[8 * n + 1] = ty;
  111. uvs[8 * n + 2] = tx + .0625f;
  112. uvs[8 * n + 3] = ty;
  113. uvs[8 * n + 4] = tx + .0625f;
  114. uvs[8 * n + 5] = ty + .0625f;
  115. uvs[8 * n + 6] = tx;
  116. uvs[8 * n + 7] = ty + .0625f;
  117. }
  118. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]);
  119. glBufferData(GL_ARRAY_BUFFER,
  120. 8 * data->ntiles * sizeof(float), uvs, GL_STATIC_DRAW);
  121. /* Vertex buffer */
  122. float vertices[8 * data->ntiles];
  123. for (int n = 0; n < data->ntiles; n++)
  124. {
  125. int x = data->tiles[4 * n + 1];
  126. int y = data->tiles[4 * n + 2];
  127. vertices[8 * n + 0] = x;
  128. vertices[8 * n + 1] = y;
  129. vertices[8 * n + 2] = x + 32;
  130. vertices[8 * n + 3] = y;
  131. vertices[8 * n + 4] = x + 32;
  132. vertices[8 * n + 5] = y + 32;
  133. vertices[8 * n + 6] = x;
  134. vertices[8 * n + 7] = y + 32;
  135. }
  136. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]);
  137. glBufferData(GL_ARRAY_BUFFER, 8 * data->ntiles * sizeof(float),
  138. vertices, GL_STATIC_DRAW);
  139. /* Index buffer */
  140. int indices[4 * data->ntiles];
  141. for (int n = 0; n < 4 * data->ntiles; n++)
  142. indices[n] = n;
  143. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]);
  144. glBufferData(GL_ARRAY_BUFFER, 4 * data->ntiles * sizeof(int),
  145. indices, GL_STATIC_DRAW);
  146. /* Draw everything */
  147. glEnableClientState(GL_VERTEX_ARRAY);
  148. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  149. glEnableClientState(GL_INDEX_ARRAY);
  150. glBindTexture(GL_TEXTURE_2D, data->texture[0]);
  151. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]);
  152. glVertexPointer(2, GL_FLOAT, 0, NULL);
  153. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]);
  154. glTexCoordPointer(2, GL_FLOAT, 0, NULL);
  155. glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]);
  156. glIndexPointer(GL_INT, 0, NULL);
  157. glDrawArrays(GL_QUADS, 0, 4 * data->ntiles);
  158. glDisableClientState(GL_VERTEX_ARRAY);
  159. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  160. glDisableClientState(GL_INDEX_ARRAY);
  161. /* Empty our shit */
  162. free(data->tiles);
  163. data->tiles = NULL;
  164. data->ntiles = 0;
  165. }