source: trunk/src/scene.cpp @ 705

Last change on this file since 705 was 705, checked in by sam, 10 years ago

Various changes to the Scene class. Not sure what's useful.

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