source: trunk/src/scene.cpp @ 735

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

core: get rid of now useless <cstdio> includes.

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