source: trunk/src/scene.cpp @ 659

Last change on this file since 659 was 659, checked in by sam, 9 years ago

Try to factor all the recent GLSL stuff in the new Shader class.

  • Property svn:keywords set to Id
File size: 6.9 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#if defined __APPLE__ && defined __MACH__
24#   include <OpenGL/gl.h>
25#else
26#   define GL_GLEXT_PROTOTYPES
27#   include <GL/gl.h>
28#endif
29
30#include "core.h"
31
32struct Tile
33{
34    uint32_t prio, code;
35    int x, y, z, o;
36};
37
38#if LOL_EXPERIMENTAL
39extern Shader *stdshader;
40#endif
41
42/*
43 * Scene implementation class
44 */
45
46class SceneData
47{
48    friend class Scene;
49
50private:
51    static int Compare(void const *p1, void const *p2)
52    {
53        Tile const *t1 = (Tile const *)p1;
54        Tile const *t2 = (Tile const *)p2;
55
56        return t2->prio - t1->prio;
57    }
58
59    Tile *tiles;
60    int ntiles;
61    float angle;
62
63    GLuint *bufs;
64    int nbufs;
65
66    static Scene *scene;
67};
68
69Scene *SceneData::scene = NULL;
70
71/*
72 * Public Scene class
73 */
74
75Scene::Scene(float angle)
76  : data(new SceneData())
77{
78    data->tiles = 0;
79    data->ntiles = 0;
80    data->angle = angle;
81
82    data->bufs = 0;
83    data->nbufs = 0;
84}
85
86Scene::~Scene()
87{
88    /* FIXME: this must be done while the GL context is still active.
89     * Change the architecture to make sure of that. */
90    glDeleteBuffers(data->nbufs, data->bufs);
91    delete data;
92}
93
94Scene *Scene::GetDefault()
95{
96    if (!SceneData::scene)
97        SceneData::scene = new Scene(0.0f);
98    return SceneData::scene;
99}
100
101void Scene::Reset()
102{
103    if (SceneData::scene)
104        delete SceneData::scene;
105    SceneData::scene = NULL;
106}
107
108void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
109{
110    if ((data->ntiles % 1024) == 0)
111        data->tiles = (Tile *)realloc(data->tiles,
112                                      (data->ntiles + 1024) * sizeof(Tile));
113    /* FIXME: this sorting only works for a 45-degree camera */
114    data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
115    data->tiles[data->ntiles].code = code;
116    data->tiles[data->ntiles].x = x;
117    data->tiles[data->ntiles].y = y;
118    data->tiles[data->ntiles].z = z;
119    data->tiles[data->ntiles].o = o;
120    data->ntiles++;
121}
122
123void Scene::Render() // XXX: rename to Blit()
124{
125#if 0
126    // Randomise, then sort.
127    for (int i = 0; i < data->ntiles; i++)
128    {
129        Tile tmp = data->tiles[i];
130        int j = rand() % data->ntiles;
131        data->tiles[i] = data->tiles[j];
132        data->tiles[j] = tmp;
133    }
134#endif
135    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
136
137#if LOL_EXPERIMENTAL
138    float *vertices = new float[18];
139    vertices[0] = -0.5f; vertices[1] = 0.5f; vertices[2] = 0.0f;
140    vertices[3] = 0.5f; vertices[4] = 0.5f; vertices[5] = 0.0f;
141    vertices[6] = -0.5f; vertices[7] = -0.5f; vertices[8] = 0.0f;
142
143    vertices[9] = 0.5f; vertices[10] = -0.5f; vertices[11] = 0.0f;
144    vertices[12] = -0.5f; vertices[13] = -0.5f; vertices[14] = 0.0f;
145    vertices[15] = 0.5f; vertices[16] = 0.5f; vertices[17] = 0.0f;
146
147    const GLfloat colors[6][3] = {
148    {  0.0,  0.0,  1.0  },
149    {  1.0,  0.0,  0.0  },
150    {  0.0,  1.0,  0.0  },
151    {  1.0,  1.0,  0.0  },
152    {  0.0,  1.0,  0.0  },
153    {  1.0,  0.0,  0.0  } };
154
155    const GLfloat tex[6][2] = {
156    {  0.0,  0.0  },
157    {  1.0,  0.0  },
158    {  0.0,  1.0  },
159    {  1.0,  1.0  },
160    {  0.0,  1.0  },
161    {  1.0,  0.0  } };
162
163    GLuint vao, vbo[3], attr;
164
165    glGenVertexArrays(1, &vao);
166    glBindVertexArray(vao);
167    glGenBuffers(3, &vbo[0]);
168
169    attr = stdshader->GetAttribLocation("in_Position");
170    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
171    glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
172    glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
173    glEnableVertexAttribArray(attr);
174
175    attr = stdshader->GetAttribLocation("in_Color");
176    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
177    glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
178    glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
179    glEnableVertexAttribArray(attr);
180
181    attr = stdshader->GetAttribLocation("in_TexCoord");
182    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
183    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), tex, GL_STATIC_DRAW);
184    glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
185    glEnableVertexAttribArray(attr);
186
187    delete[] vertices;
188
189    stdshader->Bind();
190    glBindVertexArray(vao);
191    Tiler::Bind(1 << 16);
192    glDrawArrays(GL_TRIANGLES, 0, 6);
193    glBindVertexArray(0);
194
195#else
196    // XXX: debug stuff
197    glPushMatrix();
198    static float f = 0.0f;
199    f += 0.05f;
200    glTranslatef(320.0f, 240.0f, 0.0f);
201    glRotatef(-data->angle, 1.0f, 0.0f, 0.0f);
202#if 0
203    glRotatef(3.0f * sinf(f), 1.0f, 0.0f, 0.0f);
204    glRotatef(8.0f * cosf(f), 0.0f, 0.0f, 1.0f);
205#endif
206    glTranslatef(-320.0f, -240.0f, 0.0f);
207    // XXX: end of debug stuff
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        glEnableClientState(GL_VERTEX_ARRAY);
236        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
237
238        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
239        glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float),
240                     vertex, GL_DYNAMIC_DRAW);
241        glVertexPointer(3, GL_FLOAT, 0, NULL);
242
243        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
244        glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float),
245                     texture, GL_DYNAMIC_DRAW);
246        glTexCoordPointer(2, GL_FLOAT, 0, NULL);
247
248        Tiler::Bind(data->tiles[i].code);
249        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
250
251        glDisableClientState(GL_VERTEX_ARRAY);
252        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
253
254        free(vertex);
255        free(texture);
256    }
257
258    glPopMatrix();
259#endif
260
261    free(data->tiles);
262    data->tiles = 0;
263    data->ntiles = 0;
264}
265
Note: See TracBrowser for help on using the repository browser.