您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

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