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.

275 lines
7.2 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 SHADER_CRAP
  33. # define ATTRIB_POSITION 42 /* arbitrary id */
  34. extern GLuint prog;
  35. extern GLint uni_mvp, uni_color;
  36. #endif
  37. /*
  38. * Scene implementation class
  39. */
  40. class SceneData
  41. {
  42. friend class Scene;
  43. private:
  44. static int Compare(void const *p1, void const *p2)
  45. {
  46. Tile const *t1 = (Tile const *)p1;
  47. Tile const *t2 = (Tile const *)p2;
  48. return t2->prio - t1->prio;
  49. }
  50. Tile *tiles;
  51. int ntiles;
  52. float angle;
  53. GLuint *bufs;
  54. int nbufs;
  55. static Scene *scene;
  56. };
  57. Scene *SceneData::scene = NULL;
  58. /*
  59. * Public Scene class
  60. */
  61. Scene::Scene(float angle)
  62. : data(new SceneData())
  63. {
  64. data->tiles = 0;
  65. data->ntiles = 0;
  66. data->angle = angle;
  67. data->bufs = 0;
  68. data->nbufs = 0;
  69. }
  70. Scene::~Scene()
  71. {
  72. /* FIXME: this must be done while the GL context is still active.
  73. * Change the architecture to make sure of that. */
  74. glDeleteBuffers(data->nbufs, 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. #if SHADER_CRAP
  117. float *vertices = new float[18];
  118. vertices[0] = -0.5f; vertices[1] = 0.5f; vertices[2] = 0.0f;
  119. vertices[3] = 0.5f; vertices[4] = 0.5f; vertices[5] = 0.0f;
  120. vertices[6] = -0.5f; vertices[7] = -0.5f; vertices[8] = 0.0f;
  121. vertices[9] = 0.5f; vertices[10] = -0.5f; vertices[11] = 0.0f;
  122. vertices[12] = -0.5f; vertices[13] = -0.5f; vertices[14] = 0.0f;
  123. vertices[15] = 0.5f; vertices[16] = 0.5f; vertices[17] = 0.0f;
  124. const GLfloat colors[6][3] = {
  125. { 0.0, 0.0, 1.0 },
  126. { 1.0, 0.0, 0.0 },
  127. { 0.0, 1.0, 0.0 },
  128. { 1.0, 1.0, 0.0 },
  129. { 0.0, 1.0, 0.0 },
  130. { 1.0, 0.0, 0.0 } };
  131. const GLfloat tex[6][2] = {
  132. { 0.0, 0.0 },
  133. { 1.0, 0.0 },
  134. { 0.0, 1.0 },
  135. { 1.0, 1.0 },
  136. { 0.0, 1.0 },
  137. { 1.0, 0.0 } };
  138. GLuint id[4];
  139. glGenVertexArrays(1, &id[0]);
  140. glBindVertexArray(id[0]);
  141. glGenBuffers(3, &id[1]);
  142. glBindBuffer(GL_ARRAY_BUFFER, id[1]);
  143. glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
  144. glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  145. glEnableVertexAttribArray(0);
  146. glBindBuffer(GL_ARRAY_BUFFER, id[2]);
  147. glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
  148. glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
  149. glEnableVertexAttribArray(1);
  150. glBindBuffer(GL_ARRAY_BUFFER, id[3]);
  151. glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), tex, GL_STATIC_DRAW);
  152. glVertexAttribPointer((GLuint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
  153. glEnableVertexAttribArray(2);
  154. delete[] vertices;
  155. glUseProgram(prog);
  156. glBindVertexArray(id[0]);
  157. Tiler::Bind(1 << 16);
  158. glDrawArrays(GL_TRIANGLES, 0, 6);
  159. glBindVertexArray(0);
  160. #else
  161. // XXX: debug stuff
  162. glPushMatrix();
  163. static float f = 0.0f;
  164. f += 0.05f;
  165. glTranslatef(320.0f, 240.0f, 0.0f);
  166. glRotatef(-data->angle, 1.0f, 0.0f, 0.0f);
  167. #if 0
  168. glRotatef(3.0f * sinf(f), 1.0f, 0.0f, 0.0f);
  169. glRotatef(8.0f * cosf(f), 0.0f, 0.0f, 1.0f);
  170. #endif
  171. glTranslatef(-320.0f, -240.0f, 0.0f);
  172. // XXX: end of debug stuff
  173. for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
  174. {
  175. /* Generate new vertex / texture coord buffers if necessary */
  176. if (buf + 2 > data->nbufs)
  177. {
  178. data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
  179. glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
  180. data->nbufs = buf + 2;
  181. }
  182. /* Count how many quads will be needed */
  183. for (n = i + 1; n < data->ntiles; n++)
  184. if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
  185. break;
  186. /* Create a vertex array object */
  187. float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
  188. float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
  189. for (int j = i; j < n; j++)
  190. {
  191. Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
  192. data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
  193. vertex + 18 * (j - i), texture + 12 * (j - i));
  194. }
  195. glEnableClientState(GL_VERTEX_ARRAY);
  196. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  197. #if SHADER_CRAP
  198. glUseProgram(prog);
  199. //float4x4 mvp(1.0f);
  200. //mvp = mvp - mvp;
  201. //glUniformMatrix4fv(uni_mvp, 1, GL_FALSE, (GLfloat *)&mvp[0][0]);
  202. //glUniform4f(uni_color, 1.0f, 0.0f, 1.0f, 1.0f);
  203. #endif
  204. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
  205. glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float),
  206. vertex, GL_DYNAMIC_DRAW);
  207. glVertexPointer(3, GL_FLOAT, 0, NULL);
  208. #if SHADER_CRAP
  209. glVertexAttribPointer(ATTRIB_POSITION, (n - i) * 6, GL_FLOAT, false, 0, vertex);
  210. glEnableVertexAttribArray(ATTRIB_POSITION);
  211. #endif
  212. glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
  213. glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float),
  214. texture, GL_DYNAMIC_DRAW);
  215. glTexCoordPointer(2, GL_FLOAT, 0, NULL);
  216. Tiler::Bind(data->tiles[i].code);
  217. glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
  218. glDisableClientState(GL_VERTEX_ARRAY);
  219. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  220. free(vertex);
  221. free(texture);
  222. }
  223. glPopMatrix();
  224. #endif
  225. free(data->tiles);
  226. data->tiles = 0;
  227. data->ntiles = 0;
  228. }