Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

295 řádky
7.2 KiB

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