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.
 
 
 

274 lines
6.6 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. #ifdef WIN32
  15. # define WIN32_LEAN_AND_MEAN
  16. # include <windows.h>
  17. #endif
  18. #include "core.h"
  19. #include "lolgl.h"
  20. extern char const *lolfx_tile;
  21. namespace lol
  22. {
  23. struct Tile
  24. {
  25. TileSet *tileset;
  26. uint32_t prio;
  27. vec3 pos;
  28. vec2 scale;
  29. int id, o;
  30. };
  31. /*
  32. * Scene implementation class
  33. */
  34. class SceneData
  35. {
  36. friend class Scene;
  37. private:
  38. static int Compare(void const *p1, void const *p2)
  39. {
  40. Tile const *t1 = (Tile const *)p1;
  41. Tile const *t2 = (Tile const *)p2;
  42. return t2->prio - t1->prio;
  43. }
  44. mat4 m_model_matrix;
  45. mat4 m_view_matrix;
  46. mat4 m_proj_matrix;
  47. Array<Tile> tiles;
  48. Shader *m_shader;
  49. VertexDeclaration *m_vdecl;
  50. Array<VertexBuffer *> bufs;
  51. static Scene *scene;
  52. };
  53. Scene *SceneData::scene = NULL;
  54. /*
  55. * Public Scene class
  56. */
  57. Scene::Scene()
  58. : data(new SceneData())
  59. {
  60. data->m_model_matrix = mat4(1.f);
  61. data->m_view_matrix = mat4(1.f);
  62. data->m_proj_matrix = mat4::ortho(0, Video::GetSize().x,
  63. 0, Video::GetSize().y, -1000.f, 1000.f);
  64. data->m_shader = 0;
  65. data->m_vdecl = new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
  66. VertexStream<vec2>(VertexUsage::TexCoord));
  67. }
  68. Scene::~Scene()
  69. {
  70. /* FIXME: this must be done while the GL context is still active.
  71. * Change the code architecture to make sure of that. */
  72. /* FIXME: also, make sure we do not add code to Reset() that will
  73. * reallocate stuff */
  74. Reset();
  75. delete data->m_vdecl;
  76. delete data;
  77. }
  78. Scene *Scene::GetDefault()
  79. {
  80. if (!SceneData::scene)
  81. SceneData::scene = new Scene();
  82. return SceneData::scene;
  83. }
  84. void Scene::Reset()
  85. {
  86. for (int i = 0; i < data->bufs.Count(); i++)
  87. delete data->bufs[i];
  88. data->bufs.Empty();
  89. }
  90. void Scene::SetViewMatrix(mat4 const &m)
  91. {
  92. data->m_view_matrix = m;
  93. }
  94. void Scene::SetProjMatrix(mat4 const &m)
  95. {
  96. data->m_proj_matrix = m;
  97. }
  98. mat4 const &Scene::GetViewMatrix(void)
  99. {
  100. return data->m_view_matrix;
  101. }
  102. mat4 const &Scene::GetProjMatrix(void)
  103. {
  104. return data->m_proj_matrix;
  105. }
  106. void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
  107. {
  108. Tile t;
  109. /* FIXME: this sorting only works for a 45-degree camera */
  110. t.prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
  111. t.tileset = tileset;
  112. t.id = id;
  113. t.pos = pos;
  114. t.o = o;
  115. t.scale = scale;
  116. data->tiles.Push(t);
  117. }
  118. void Scene::Render() // XXX: rename to Blit()
  119. {
  120. /* Early exit if nothing needs to be rendered */
  121. if (!data->tiles.Count())
  122. return;
  123. if (!data->m_shader)
  124. data->m_shader = Shader::Create(lolfx_tile);
  125. #if 0
  126. // Randomise, then sort.
  127. for (int i = 0; i < data->tiles.Count(); i++)
  128. {
  129. Tile tmp = data->tiles[i];
  130. int j = rand() % data->tiles.Count();
  131. data->tiles[i] = data->tiles[j];
  132. data->tiles[j] = tmp;
  133. }
  134. #endif
  135. qsort(&data->tiles[0], data->tiles.Count(),
  136. sizeof(Tile), SceneData::Compare);
  137. // XXX: debug stuff
  138. data->m_model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
  139. #if 0
  140. static float f = 0.0f;
  141. f += 0.01f;
  142. data->m_model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
  143. data->m_model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
  144. #endif
  145. data->m_model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
  146. // XXX: end of debug stuff
  147. ShaderUniform uni_mat, uni_tex;
  148. ShaderAttrib attr_pos, attr_tex;
  149. attr_pos = data->m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0);
  150. attr_tex = data->m_shader->GetAttribLocation("in_TexCoord", VertexUsage::TexCoord, 0);
  151. data->m_shader->Bind();
  152. uni_mat = data->m_shader->GetUniformLocation("proj_matrix");
  153. data->m_shader->SetUniform(uni_mat, data->m_proj_matrix);
  154. uni_mat = data->m_shader->GetUniformLocation("view_matrix");
  155. data->m_shader->SetUniform(uni_mat, data->m_view_matrix);
  156. uni_mat = data->m_shader->GetUniformLocation("model_matrix");
  157. data->m_shader->SetUniform(uni_mat, data->m_model_matrix);
  158. #if defined USE_D3D9 || defined _XBOX
  159. #else
  160. uni_tex = data->m_shader->GetUniformLocation("in_Texture");
  161. data->m_shader->SetUniform(uni_tex, 0);
  162. #if !defined HAVE_GLES_2X
  163. glEnable(GL_TEXTURE_2D);
  164. #endif
  165. glEnable(GL_DEPTH_TEST);
  166. glDepthFunc(GL_LEQUAL);
  167. #if defined HAVE_GL_2X && !defined __APPLE__
  168. glEnable(GL_ALPHA_TEST);
  169. glAlphaFunc(GL_GEQUAL, 0.01f);
  170. #endif
  171. glEnable(GL_BLEND);
  172. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  173. #endif
  174. for (int buf = 0, i = 0, n; i < data->tiles.Count(); i = n, buf += 2)
  175. {
  176. /* Count how many quads will be needed */
  177. for (n = i + 1; n < data->tiles.Count(); n++)
  178. if (data->tiles[i].tileset != data->tiles[n].tileset)
  179. break;
  180. /* Create a vertex array object */
  181. VertexBuffer *vb1 = new VertexBuffer(6 * 3 * (n - i) * sizeof(float));
  182. float *vertex = (float *)vb1->Lock(0, 0);
  183. VertexBuffer *vb2 = new VertexBuffer(6 * 2 * (n - i) * sizeof(float));
  184. float *texture = (float *)vb2->Lock(0, 0);
  185. data->bufs.Push(vb1);
  186. data->bufs.Push(vb2);
  187. for (int j = i; j < n; j++)
  188. {
  189. data->tiles[i].tileset->BlitTile(data->tiles[j].id,
  190. data->tiles[j].pos, data->tiles[j].o,
  191. data->tiles[j].scale,
  192. vertex + 18 * (j - i), texture + 12 * (j - i));
  193. }
  194. vb1->Unlock();
  195. vb2->Unlock();
  196. /* Bind texture */
  197. data->tiles[i].tileset->Bind();
  198. /* Bind vertex and texture coordinate buffers */
  199. data->m_vdecl->Bind();
  200. data->m_vdecl->SetStream(vb1, attr_pos);
  201. data->m_vdecl->SetStream(vb2, attr_tex);
  202. /* Draw arrays */
  203. data->m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, (n - i) * 2);
  204. data->m_vdecl->Unbind();
  205. data->tiles[i].tileset->Unbind();
  206. }
  207. data->tiles.Empty();
  208. data->m_shader->Unbind();
  209. #if defined USE_D3D9 || defined _XBOX
  210. /* TODO */
  211. #else
  212. #if !defined HAVE_GLES_2X
  213. glDisable(GL_TEXTURE_2D);
  214. #endif
  215. glDisable(GL_DEPTH_TEST);
  216. #if defined HAVE_GL_2X && !defined __APPLE__
  217. glDisable(GL_ALPHA_TEST);
  218. #endif
  219. glDisable(GL_BLEND);
  220. #endif
  221. }
  222. } /* namespace lol */