source: trunk/src/scene.cpp @ 674

Last change on this file since 674 was 674, checked in by sam, 11 years ago

The engine now builds for GL and GL ES 1.x and 2.x, and runs for each
one except GL ES 2.x for now.

  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
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
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cstdio>
17#include <cmath>
18
19#ifdef WIN32
20#   define WIN32_LEAN_AND_MEAN
21#   include <windows.h>
22#endif
23
24#include "core.h"
25#include "lolgl.h"
26
27struct Tile
28{
29    uint32_t prio, code;
30    int x, y, z, o;
31};
32
33#if defined HAVE_GL_2X || defined HAVE_GLES_2X
34extern Shader *stdshader;
35#endif
36extern mat4 model_matrix;
37
38/*
39 * Scene implementation class
40 */
41
42class SceneData
43{
44    friend class Scene;
45
46private:
47    static int Compare(void const *p1, void const *p2)
48    {
49        Tile const *t1 = (Tile const *)p1;
50        Tile const *t2 = (Tile const *)p2;
51
52        return t2->prio - t1->prio;
53    }
54
55    Tile *tiles;
56    int ntiles;
57    float angle;
58
59#if defined HAVE_GL_2X
60    GLuint vao;
61#endif
62    GLuint *bufs;
63    int nbufs;
64
65    static Scene *scene;
66};
67
68Scene *SceneData::scene = NULL;
69
70/*
71 * Public Scene class
72 */
73
74Scene::Scene(float angle)
75  : data(new SceneData())
76{
77    data->tiles = 0;
78    data->ntiles = 0;
79    data->angle = angle;
80
81    data->bufs = 0;
82    data->nbufs = 0;
83
84#if defined HAVE_GL_2X
85    glGenVertexArrays(1, &data->vao);
86#endif
87}
88
89Scene::~Scene()
90{
91    /* FIXME: this must be done while the GL context is still active.
92     * Change the architecture to make sure of that. */
93    glDeleteBuffers(data->nbufs, data->bufs);
94#if defined HAVE_GL_2X
95    glDeleteVertexArrays(1, &data->vao);
96#endif
97    free(data->bufs);
98    delete data;
99}
100
101Scene *Scene::GetDefault()
102{
103    if (!SceneData::scene)
104        SceneData::scene = new Scene(0.0f);
105    return SceneData::scene;
106}
107
108void Scene::Reset()
109{
110    if (SceneData::scene)
111        delete SceneData::scene;
112    SceneData::scene = NULL;
113}
114
115void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
116{
117    if ((data->ntiles % 1024) == 0)
118        data->tiles = (Tile *)realloc(data->tiles,
119                                      (data->ntiles + 1024) * sizeof(Tile));
120    /* FIXME: this sorting only works for a 45-degree camera */
121    data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
122    data->tiles[data->ntiles].code = code;
123    data->tiles[data->ntiles].x = x;
124    data->tiles[data->ntiles].y = y;
125    data->tiles[data->ntiles].z = z;
126    data->tiles[data->ntiles].o = o;
127    data->ntiles++;
128}
129
130void Scene::Render() // XXX: rename to Blit()
131{
132#if 0
133    // Randomise, then sort.
134    for (int i = 0; i < data->ntiles; i++)
135    {
136        Tile tmp = data->tiles[i];
137        int j = rand() % data->ntiles;
138        data->tiles[i] = data->tiles[j];
139        data->tiles[j] = tmp;
140    }
141#endif
142    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
143
144    // XXX: debug stuff
145    model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
146    model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
147#if 0
148    static float f = 0.0f;
149    f += 0.01f;
150    model_matrix *= mat4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
151    model_matrix *= mat4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
152#endif
153    model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
154    // XXX: end of debug stuff
155
156#if defined HAVE_GL_2X || defined HAVE_GLES_2X
157    GLuint uni, attr_pos, attr_tex;
158    uni = stdshader->GetUniformLocation("model_matrix");
159    attr_pos = stdshader->GetAttribLocation("in_Position");
160    attr_tex = stdshader->GetAttribLocation("in_TexCoord");
161
162    stdshader->Bind();
163    glUniformMatrix4fv(uni, 1, GL_FALSE, &model_matrix[0][0]);
164
165    glEnable(GL_DEPTH_TEST);
166    glDepthFunc(GL_LEQUAL);
167#   if !defined HAVE_GLES_2X
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#else
174    glEnable(GL_DEPTH_TEST);
175    glDepthFunc(GL_LEQUAL);
176    glEnable(GL_ALPHA_TEST);
177    glAlphaFunc(GL_GEQUAL, 0.01f);
178    glEnable(GL_BLEND);
179    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
180
181    glLoadIdentity();
182    glMultMatrixf(&model_matrix[0][0]);
183#endif
184
185    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
186    {
187        /* Generate new vertex / texture coord buffers if necessary */
188        if (buf + 2 > data->nbufs)
189        {
190            data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
191            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
192            data->nbufs = buf + 2;
193        }
194
195        /* Count how many quads will be needed */
196        for (n = i + 1; n < data->ntiles; n++)
197            if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
198                break;
199
200        /* Create a vertex array object */
201        float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
202        float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
203
204        for (int j = i; j < n; j++)
205        {
206            Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
207                            data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
208                            vertex + 18 * (j - i), texture + 12 * (j - i));
209        }
210
211#if defined HAVE_GL_2X
212        glBindVertexArray(data->vao);
213        glEnableVertexAttribArray(attr_pos);
214        glEnableVertexAttribArray(attr_tex);
215#elif defined HAVE_GLES_2X
216        glEnableVertexAttribArray(attr_pos);
217        glEnableVertexAttribArray(attr_tex);
218#else
219        glEnableClientState(GL_VERTEX_ARRAY);
220        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
221#endif
222
223#if defined HAVE_GL_2X
224        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
225        glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
226                     vertex, GL_STATIC_DRAW);
227        glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
228#elif defined HAVE_GLES_2X
229        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
230        glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, vertex);
231#elif defined HAVE_GL_1X
232        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
233        glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
234                     vertex, GL_STATIC_DRAW);
235        glVertexPointer(3, GL_FLOAT, 0, NULL);
236#else
237        glVertexPointer(3, GL_FLOAT, 0, vertex);
238#endif
239
240#if defined HAVE_GL_2X
241        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
242        glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
243                     texture, GL_STATIC_DRAW);
244        glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
245#elif defined HAVE_GLES_2X
246        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
247        glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texture);
248#elif defined HAVE_GL_1X
249        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
250        glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
251                     texture, GL_STATIC_DRAW);
252        glTexCoordPointer(2, GL_FLOAT, 0, NULL);
253#else
254        glTexCoordPointer(2, GL_FLOAT, 0, texture);
255#endif
256
257#if defined HAVE_GL_2X || defined HAVE_GLES_2X
258        stdshader->Bind();
259#endif
260
261        Tiler::Bind(data->tiles[i].code);
262        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
263
264#if defined HAVE_GL_2X
265        glBindVertexArray(0);
266        glDisableVertexAttribArray(attr_pos);
267        glDisableVertexAttribArray(attr_tex);
268#elif defined HAVE_GLES_2X
269        glDisableVertexAttribArray(attr_pos);
270        glDisableVertexAttribArray(attr_tex);
271#else
272        glDisableClientState(GL_VERTEX_ARRAY);
273        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
274#endif
275
276        free(vertex);
277        free(texture);
278    }
279
280    free(data->tiles);
281    data->tiles = 0;
282    data->ntiles = 0;
283}
284
Note: See TracBrowser for help on using the repository browser.