|
- //
- // Lol Engine
- //
- // Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the Do What The Fuck You Want To
- // Public License, Version 2, as published by Sam Hocevar. See
- // http://sam.zoy.org/projects/COPYING.WTFPL for more details.
- //
-
- #if defined HAVE_CONFIG_H
- # include "config.h"
- #endif
-
- #include <cstdlib>
- #include <cmath>
-
- #ifdef WIN32
- # define WIN32_LEAN_AND_MEAN
- # include <windows.h>
- #endif
-
- #include "core.h"
- #include "lolgl.h"
-
- namespace lol
- {
-
- struct Tile
- {
- uint32_t prio, code;
- int x, y, z, o;
- };
-
- #if defined HAVE_GL_2X || defined HAVE_GLES_2X
- extern Shader *stdshader;
- #endif
- extern mat4 model_matrix;
-
- /*
- * Scene implementation class
- */
-
- class SceneData
- {
- friend class Scene;
-
- private:
- static int Compare(void const *p1, void const *p2)
- {
- Tile const *t1 = (Tile const *)p1;
- Tile const *t2 = (Tile const *)p2;
-
- return t2->prio - t1->prio;
- }
-
- Tile *tiles;
- int ntiles;
- float angle;
-
- #if defined HAVE_GL_2X
- GLuint vao;
- #endif
- GLuint *bufs;
- int nbufs;
-
- static Scene *scene;
- };
-
- Scene *SceneData::scene = NULL;
-
- /*
- * Public Scene class
- */
-
- Scene::Scene(float angle)
- : data(new SceneData())
- {
- data->tiles = 0;
- data->ntiles = 0;
- data->angle = angle;
-
- data->bufs = 0;
- data->nbufs = 0;
-
- #if defined HAVE_GL_2X
- glGenVertexArrays(1, &data->vao);
- #endif
- }
-
- Scene::~Scene()
- {
- /* FIXME: this must be done while the GL context is still active.
- * Change the architecture to make sure of that. */
- glDeleteBuffers(data->nbufs, data->bufs);
- #if defined HAVE_GL_2X
- glDeleteVertexArrays(1, &data->vao);
- #endif
- free(data->bufs);
- delete data;
- }
-
- Scene *Scene::GetDefault()
- {
- if (!SceneData::scene)
- SceneData::scene = new Scene(0.0f);
- return SceneData::scene;
- }
-
- void Scene::Reset()
- {
- if (SceneData::scene)
- delete SceneData::scene;
- SceneData::scene = NULL;
- }
-
- void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
- {
- if ((data->ntiles % 1024) == 0)
- data->tiles = (Tile *)realloc(data->tiles,
- (data->ntiles + 1024) * sizeof(Tile));
- /* FIXME: this sorting only works for a 45-degree camera */
- data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
- data->tiles[data->ntiles].code = code;
- data->tiles[data->ntiles].x = x;
- data->tiles[data->ntiles].y = y;
- data->tiles[data->ntiles].z = z;
- data->tiles[data->ntiles].o = o;
- data->ntiles++;
- }
-
- void Scene::Render() // XXX: rename to Blit()
- {
- #if 0
- // Randomise, then sort.
- for (int i = 0; i < data->ntiles; i++)
- {
- Tile tmp = data->tiles[i];
- int j = rand() % data->ntiles;
- data->tiles[i] = data->tiles[j];
- data->tiles[j] = tmp;
- }
- #endif
- qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
-
- // XXX: debug stuff
- model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
- model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
- #if 0
- static float f = 0.0f;
- f += 0.01f;
- model_matrix *= mat4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
- model_matrix *= mat4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
- #endif
- model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
- // XXX: end of debug stuff
-
- #if defined HAVE_GL_2X || defined HAVE_GLES_2X
- GLuint uni_mat, uni_tex, attr_pos, attr_tex;
- attr_pos = stdshader->GetAttribLocation("in_Position");
- attr_tex = stdshader->GetAttribLocation("in_TexCoord");
-
- stdshader->Bind();
- uni_mat = stdshader->GetUniformLocation("model_matrix");
- glUniformMatrix4fv(uni_mat, 1, GL_FALSE, &model_matrix[0][0]);
- uni_tex = stdshader->GetUniformLocation("in_Texture");
- glUniform1i(uni_tex, 0);
-
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- # if !defined HAVE_GLES_2X
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GEQUAL, 0.01f);
- # endif
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- #else
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GEQUAL, 0.01f);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glMultMatrixf(&model_matrix[0][0]);
-
- /* Set up state machine */
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnable(GL_TEXTURE_2D);
- glEnableClientState(GL_VERTEX_ARRAY);
- #endif
-
- for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
- {
- /* Generate new vertex / texture coord buffers if necessary */
- if (buf + 2 > data->nbufs)
- {
- data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
- glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
- data->nbufs = buf + 2;
- }
-
- /* Count how many quads will be needed */
- for (n = i + 1; n < data->ntiles; n++)
- if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
- break;
-
- /* Create a vertex array object */
- float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
- float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
-
- for (int j = i; j < n; j++)
- {
- Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
- data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
- vertex + 18 * (j - i), texture + 12 * (j - i));
- }
-
- #if defined HAVE_GL_2X || defined HAVE_GLES_2X
- stdshader->Bind();
- #endif
-
- /* Bind texture */
- Tiler::Bind(data->tiles[i].code);
-
- /* Bind vertex, color and texture coordinate buffers */
- #if defined HAVE_GL_2X || defined HAVE_GLES_2X
- # if !defined HAVE_GLES_2X
- glBindVertexArray(data->vao);
- # endif
- glEnableVertexAttribArray(attr_pos);
- glEnableVertexAttribArray(attr_tex);
-
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
- glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
- vertex, GL_STATIC_DRAW);
- glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
-
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
- glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
- texture, GL_STATIC_DRAW);
- glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
- #elif defined HAVE_GL_1X
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
- glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
- vertex, GL_STATIC_DRAW);
- glVertexPointer(3, GL_FLOAT, 0, NULL);
-
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
- glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
- texture, GL_STATIC_DRAW);
- glTexCoordPointer(2, GL_FLOAT, 0, NULL);
- #else
- glVertexPointer(3, GL_FLOAT, 0, vertex);
- glTexCoordPointer(2, GL_FLOAT, 0, texture);
- #endif
-
- /* Draw arrays */
- glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
-
- #if defined HAVE_GL_2X || defined HAVE_GLES_2X
- # if !defined HAVE_GLES_2X
- glBindVertexArray(0);
- # endif
- glDisableVertexAttribArray(attr_pos);
- glDisableVertexAttribArray(attr_tex);
- #endif
-
- free(vertex);
- free(texture);
- }
-
- #if defined HAVE_GL_1X || defined HAVE_GLES_1X
- /* Disable state machine features */
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- /* Restore matrices */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- #endif
-
- free(data->tiles);
- data->tiles = 0;
- data->ntiles = 0;
- }
-
- } /* namespace lol */
|