|
- //
- // 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 <cstdio>
- #include <cmath>
-
- #ifdef WIN32
- # define WIN32_LEAN_AND_MEAN
- # include <windows.h>
- #endif
- #if defined __APPLE__ && defined __MACH__
- # include <OpenGL/gl.h>
- #else
- # define GL_GLEXT_PROTOTYPES
- # include <GL/gl.h>
- #endif
-
- #include "core.h"
-
- struct Tile
- {
- uint32_t prio, code;
- int x, y, z, o;
- };
-
- #if LOL_EXPERIMENTAL
- 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;
-
- 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;
- }
-
- 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);
- 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 LOL_EXPERIMENTAL
- GLuint uni;
- uni = stdshader->GetUniformLocation("model_matrix");
- glUniformMatrix4fv(uni, 1, GL_FALSE, &model_matrix[0][0]);
-
- float *vertices = new float[18];
- vertices[0] = 0.0f; vertices[1] = 480.0f; vertices[2] = 0.0f;
- vertices[3] = 640.0f; vertices[4] = 480.0f; vertices[5] = 0.0f;
- vertices[6] = 0.0f; vertices[7] = 0.0f; vertices[8] = 0.0f;
-
- vertices[9] = 640.0f; vertices[10] = 0.0f; vertices[11] = 0.0f;
- vertices[12] = 0.0f; vertices[13] = 0.0f; vertices[14] = 0.0f;
- vertices[15] = 640.0f; vertices[16] = 480.0f; vertices[17] = 0.0f;
-
- const GLfloat colors[6][3] = {
- { 0.0, 0.0, 1.0 },
- { 1.0, 0.0, 0.0 },
- { 0.0, 1.0, 0.0 },
- { 1.0, 1.0, 0.0 },
- { 0.0, 1.0, 0.0 },
- { 1.0, 0.0, 0.0 } };
-
- const GLfloat tex[6][2] = {
- { 0.0, 0.0 },
- { 1.0, 0.0 },
- { 0.0, 1.0 },
- { 1.0, 1.0 },
- { 0.0, 1.0 },
- { 1.0, 0.0 } };
-
- GLuint vao, vbo[3], attr;
-
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
- glGenBuffers(3, &vbo[0]);
-
- attr = stdshader->GetAttribLocation("in_Position");
- glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
- glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
- glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
- glEnableVertexAttribArray(attr);
-
- attr = stdshader->GetAttribLocation("in_Color");
- glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
- glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
- glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
- glEnableVertexAttribArray(attr);
-
- attr = stdshader->GetAttribLocation("in_TexCoord");
- glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
- glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), tex, GL_STATIC_DRAW);
- glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
- glEnableVertexAttribArray(attr);
-
- delete[] vertices;
-
- stdshader->Bind();
- glBindVertexArray(vao);
- Tiler::Bind(1 << 16);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- glBindVertexArray(0);
-
- #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);
-
- glLoadIdentity();
- glMultMatrixf(&model_matrix[0][0]);
-
- 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));
- }
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
- glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float),
- vertex, GL_DYNAMIC_DRAW);
- glVertexPointer(3, GL_FLOAT, 0, NULL);
-
- glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
- glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float),
- texture, GL_DYNAMIC_DRAW);
- glTexCoordPointer(2, GL_FLOAT, 0, NULL);
-
- Tiler::Bind(data->tiles[i].code);
- glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- free(vertex);
- free(texture);
- }
- #endif
-
- free(data->tiles);
- data->tiles = 0;
- data->ntiles = 0;
- }
|