296 linhas
7.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2011 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 <cmath>
  15. #ifdef WIN32
  16. # define WIN32_LEAN_AND_MEAN
  17. # include <windows.h>
  18. #endif
  19. #include "core.h"
  20. #include "lolgl.h"
  21. namespace lol
  22. {
  23. struct Tile
  24. {
  25. uint32_t prio, code;
  26. int x, y, z, o;
  27. };
  28. #if defined HAVE_GL_2X || defined HAVE_GLES_2X
  29. extern Shader *stdshader;
  30. #endif
  31. extern mat4 model_matrix;
  32. /*
  33. * Scene implementation class
  34. */
  35. class SceneData
  36. {
  37. friend class Scene;
  38. private:
  39. static int Compare(void const *p1, void const *p2)
  40. {
  41. Tile const *t1 = (Tile const *)p1;
  42. Tile const *t2 = (Tile const *)p2;
  43. return t2->prio - t1->prio;
  44. }
  45. Tile *tiles;
  46. int ntiles;
  47. float angle;
  48. #if defined HAVE_GL_2X
  49. GLuint vao;
  50. #endif
  51. GLuint *bufs;
  52. int nbufs;
  53. static Scene *scene;
  54. };
  55. Scene *SceneData::scene = NULL;
  56. /*
  57. * Public Scene class
  58. */
  59. Scene::Scene(float angle)
  60. : data(new SceneData())
  61. {
  62. data->tiles = 0;
  63. data->ntiles = 0;
  64. data->angle = angle;
  65. data->bufs = 0;
  66. data->nbufs = 0;
  67. #if defined HAVE_GL_2X
  68. glGenVertexArrays(1, &data->vao);
  69. #endif
  70. }
  71. Scene::~Scene()
  72. {
  73. /* FIXME: this must be done while the GL context is still active.
  74. * Change the architecture to make sure of that. */
  75. glDeleteBuffers(data->nbufs, data->bufs);
  76. #if defined HAVE_GL_2X
  77. glDeleteVertexArrays(1, &data->vao);
  78. #endif
  79. free(data->bufs);
  80. delete data;
  81. }
  82. Scene *Scene::GetDefault()
  83. {
  84. if (!SceneData::scene)
  85. SceneData::scene = new Scene(0.0f);
  86. return SceneData::scene;
  87. }
  88. void Scene::Reset()
  89. {
  90. if (SceneData::scene)
  91. delete SceneData::scene;
  92. SceneData::scene = NULL;
  93. }
  94. void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
  95. {
  96. if ((data->ntiles % 1024) == 0)
  97. data->tiles = (Tile *)realloc(data->tiles,
  98. (data->ntiles + 1024) * sizeof(Tile));
  99. /* FIXME: this sorting only works for a 45-degree camera */
  100. data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
  101. data->tiles[data->ntiles].code = code;
  102. data->tiles[data->ntiles].x = x;
  103. data->tiles[data->ntiles].y = y;
  104. data->tiles[data->ntiles].z = z;
  105. data->tiles[data->ntiles].o = o;
  106. data->ntiles++;
  107. }
  108. void Scene::Render() // XXX: rename to Blit()
  109. {
  110. #if 0
  111. // Randomise, then sort.
  112. for (int i = 0; i < data->ntiles; i++)
  113. {
  114. Tile tmp = data->tiles[i];
  115. int j = rand() % data->ntiles;
  116. data->tiles[i] = data->tiles[j];
  117. data->tiles[j] = tmp;
  118. }
  119. #endif
  120. qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
  121. // XXX: debug stuff
  122. model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
  123. model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
  124. #if 0
  125. static float f = 0.0f;
  126. f += 0.01f;
  127. model_matrix *= mat4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
  128. model_matrix *= mat4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
  129. #endif
  130. model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
  131. // XXX: end of debug stuff
  132. #if defined HAVE_GL_2X || defined HAVE_GLES_2X
  133. GLuint uni_mat, uni_tex, attr_pos, attr_tex;
  134. attr_pos = stdshader->GetAttribLocation("in_Position");
  135. attr_tex = stdshader->GetAttribLocation("in_TexCoord");
  136. stdshader->Bind();
  137. uni_mat = stdshader->GetUniformLocation("model_matrix");
  138. glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &model_matrix[0][0]);
  139. uni_tex = stdshader->GetUniformLocation("in_Texture");
  140. glUniform1i(uni_tex, 0);
  141. glEnable(GL_TEXTURE_2D);
  142. glEnable(GL_DEPTH_TEST);
  143. glDepthFunc(GL_LEQUAL);
  144. # if !defined HAVE_GLES_2X
  145. glEnable(GL_ALPHA_TEST);
  146. glAlphaFunc(GL_GEQUAL, 0.01f);
  147. # endif
  148. glEnable(GL_BLEND);
  149. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  150. #else
  151. glEnable(GL_DEPTH_TEST);
  152. glDepthFunc(GL_LEQUAL);
  153. glEnable(GL_ALPHA_TEST);
  154. glAlphaFunc(GL_GEQUAL, 0.01f);
  155. glEnable(GL_BLEND);
  156. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  157. glMatrixMode(GL_MODELVIEW);
  158. glPushMatrix();
  159. glLoadIdentity();
  160. glMultMatrixf(&model_matrix[0][0]);
  161. /* Set up state machine */
  162. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  163. glEnable(GL_TEXTURE_2D);
  164. glEnableClientState(GL_VERTEX_ARRAY);
  165. #endif
  166. for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
  167. {
  168. /* Generate new vertex / texture coord buffers if necessary */
  169. if (buf + 2 > data->nbufs)
  170. {
  171. data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
  172. glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
  173. data->nbufs = buf + 2;
  174. }
  175. /* Count how many quads will be needed */
  176. for (n = i + 1; n < data->ntiles; n++)
  177. if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
  178. break;
  179. /* Create a vertex array object */
  180. float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
  181. float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
  182. for (int j = i; j < n; j++)
  183. {
  184. Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
  185. data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
  186. vertex + 18 * (j - i), texture + 12 * (j - i));
  187. }
  188. #if defined HAVE_GL_2X || defined HAVE_GLES_2X
  189. stdshader->Bind();
  190. #endif
  191. /* Bind texture */
  192. Tiler::Bind(data->tiles[i].code);
  193. /* Bind vertex, color and texture coordinate buffers */
  194. #if defined HAVE_GL_2X || defined HAVE_GLES_2X
  195. # if !defined HAVE_GLES_2X
  196. glBindVertexArray(data->vao);
  197. # endif
  198. glEnableVertexAttribArray(attr_pos);
  199. glEnableVertexAttribArray(attr_tex);
  200. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
  201. glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
  202. vertex, GL_STATIC_DRAW);
  203. glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
  204. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
  205. glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
  206. texture, GL_STATIC_DRAW);
  207. glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
  208. #elif defined HAVE_GL_1X
  209. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
  210. glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
  211. vertex, GL_STATIC_DRAW);
  212. glVertexPointer(3, GL_FLOAT, 0, NULL);
  213. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
  214. glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
  215. texture, GL_STATIC_DRAW);
  216. glTexCoordPointer(2, GL_FLOAT, 0, NULL);
  217. #else
  218. glVertexPointer(3, GL_FLOAT, 0, vertex);
  219. glTexCoordPointer(2, GL_FLOAT, 0, texture);
  220. #endif
  221. /* Draw arrays */
  222. glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
  223. #if defined HAVE_GL_2X || defined HAVE_GLES_2X
  224. # if !defined HAVE_GLES_2X
  225. glBindVertexArray(0);
  226. # endif
  227. glDisableVertexAttribArray(attr_pos);
  228. glDisableVertexAttribArray(attr_tex);
  229. #endif
  230. free(vertex);
  231. free(texture);
  232. }
  233. #if defined HAVE_GL_1X || defined HAVE_GLES_1X
  234. /* Disable state machine features */
  235. glDisableClientState(GL_VERTEX_ARRAY);
  236. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  237. /* Restore matrices */
  238. glMatrixMode(GL_PROJECTION);
  239. glPopMatrix();
  240. glMatrixMode(GL_MODELVIEW);
  241. glPopMatrix();
  242. #endif
  243. free(data->tiles);
  244. data->tiles = 0;
  245. data->ntiles = 0;
  246. }
  247. } /* namespace lol */