source: trunk/src/scene.cpp @ 663

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

Implement +=, -= and *= for matrices and vectors.
Add new types, closer to the GLSL ones.

  • Property svn:keywords set to Id
File size: 7.3 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
41extern float4x4 projection_matrix, view_matrix, model_matrix;
42
43/*
44 * Scene implementation class
45 */
46
47class SceneData
48{
49    friend class Scene;
50
51private:
52    static int Compare(void const *p1, void const *p2)
53    {
54        Tile const *t1 = (Tile const *)p1;
55        Tile const *t2 = (Tile const *)p2;
56
57        return t2->prio - t1->prio;
58    }
59
60    Tile *tiles;
61    int ntiles;
62    float angle;
63
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
87Scene::~Scene()
88{
89    /* FIXME: this must be done while the GL context is still active.
90     * Change the architecture to make sure of that. */
91    glDeleteBuffers(data->nbufs, data->bufs);
92    delete data;
93}
94
95Scene *Scene::GetDefault()
96{
97    if (!SceneData::scene)
98        SceneData::scene = new Scene(0.0f);
99    return SceneData::scene;
100}
101
102void Scene::Reset()
103{
104    if (SceneData::scene)
105        delete SceneData::scene;
106    SceneData::scene = NULL;
107}
108
109void Scene::AddTile(uint32_t code, int x, int y, int z, int o)
110{
111    if ((data->ntiles % 1024) == 0)
112        data->tiles = (Tile *)realloc(data->tiles,
113                                      (data->ntiles + 1024) * sizeof(Tile));
114    /* FIXME: this sorting only works for a 45-degree camera */
115    data->tiles[data->ntiles].prio = -y - 2 * 32 * z + (o ? 0 : 32);
116    data->tiles[data->ntiles].code = code;
117    data->tiles[data->ntiles].x = x;
118    data->tiles[data->ntiles].y = y;
119    data->tiles[data->ntiles].z = z;
120    data->tiles[data->ntiles].o = o;
121    data->ntiles++;
122}
123
124void Scene::Render() // XXX: rename to Blit()
125{
126#if 0
127    // Randomise, then sort.
128    for (int i = 0; i < data->ntiles; i++)
129    {
130        Tile tmp = data->tiles[i];
131        int j = rand() % data->ntiles;
132        data->tiles[i] = data->tiles[j];
133        data->tiles[j] = tmp;
134    }
135#endif
136    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
137
138    // XXX: debug stuff
139    model_matrix = float4x4::translate(320.0f, 240.0f, 0.0f);
140    model_matrix *= float4x4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
141#if 0
142    static float f = 0.0f;
143    f += 0.01f;
144    model_matrix *= float4x4::rotate(0.1f * sinf(f), 1.0f, 0.0f, 0.0f);
145    model_matrix *= float4x4::rotate(0.3f * cosf(f), 0.0f, 0.0f, 1.0f);
146#endif
147    model_matrix *= float4x4::translate(-320.0f, -240.0f, 0.0f);
148    // XXX: end of debug stuff
149
150#if LOL_EXPERIMENTAL
151    GLuint uni;
152    uni = stdshader->GetUniformLocation("model_matrix");
153    glUniformMatrix4fv(uni, 1, GL_FALSE, &model_matrix[0][0]);
154
155    float *vertices = new float[18];
156    vertices[0] = 0.0f; vertices[1] = 480.0f; vertices[2] = 0.0f;
157    vertices[3] = 640.0f; vertices[4] = 480.0f; vertices[5] = 0.0f;
158    vertices[6] = 0.0f; vertices[7] = 0.0f; vertices[8] = 0.0f;
159
160    vertices[9] = 640.0f; vertices[10] = 0.0f; vertices[11] = 0.0f;
161    vertices[12] = 0.0f; vertices[13] = 0.0f; vertices[14] = 0.0f;
162    vertices[15] = 640.0f; vertices[16] = 480.0f; vertices[17] = 0.0f;
163
164    const GLfloat colors[6][3] = {
165    {  0.0,  0.0,  1.0  },
166    {  1.0,  0.0,  0.0  },
167    {  0.0,  1.0,  0.0  },
168    {  1.0,  1.0,  0.0  },
169    {  0.0,  1.0,  0.0  },
170    {  1.0,  0.0,  0.0  } };
171
172    const GLfloat tex[6][2] = {
173    {  0.0,  0.0  },
174    {  1.0,  0.0  },
175    {  0.0,  1.0  },
176    {  1.0,  1.0  },
177    {  0.0,  1.0  },
178    {  1.0,  0.0  } };
179
180    GLuint vao, vbo[3], attr;
181
182    glGenVertexArrays(1, &vao);
183    glBindVertexArray(vao);
184    glGenBuffers(3, &vbo[0]);
185
186    attr = stdshader->GetAttribLocation("in_Position");
187    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
188    glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
189    glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
190    glEnableVertexAttribArray(attr);
191
192    attr = stdshader->GetAttribLocation("in_Color");
193    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
194    glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), colors, GL_STATIC_DRAW);
195    glVertexAttribPointer(attr, 3, GL_FLOAT, GL_FALSE, 0, 0);
196    glEnableVertexAttribArray(attr);
197
198    attr = stdshader->GetAttribLocation("in_TexCoord");
199    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
200    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), tex, GL_STATIC_DRAW);
201    glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
202    glEnableVertexAttribArray(attr);
203
204    delete[] vertices;
205
206    stdshader->Bind();
207    glBindVertexArray(vao);
208    Tiler::Bind(1 << 16);
209    glDrawArrays(GL_TRIANGLES, 0, 6);
210    glBindVertexArray(0);
211
212#else
213    glLoadIdentity();
214    glMultMatrixf(&model_matrix[0][0]);
215
216    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
217    {
218        /* Generate new vertex / texture coord buffers if necessary */
219        if (buf + 2 > data->nbufs)
220        {
221            data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint));
222            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
223            data->nbufs = buf + 2;
224        }
225
226        /* Count how many quads will be needed */
227        for (n = i + 1; n < data->ntiles; n++)
228            if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16)
229                break;
230
231        /* Create a vertex array object */
232        float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
233        float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
234
235        for (int j = i; j < n; j++)
236        {
237            Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x,
238                            data->tiles[j].y, data->tiles[j].z, data->tiles[j].o,
239                            vertex + 18 * (j - i), texture + 12 * (j - i));
240        }
241
242        glEnableClientState(GL_VERTEX_ARRAY);
243        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
244
245        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
246        glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float),
247                     vertex, GL_DYNAMIC_DRAW);
248        glVertexPointer(3, GL_FLOAT, 0, NULL);
249
250        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
251        glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float),
252                     texture, GL_DYNAMIC_DRAW);
253        glTexCoordPointer(2, GL_FLOAT, 0, NULL);
254
255        Tiler::Bind(data->tiles[i].code);
256        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
257
258        glDisableClientState(GL_VERTEX_ARRAY);
259        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
260
261        free(vertex);
262        free(texture);
263    }
264#endif
265
266    free(data->tiles);
267    data->tiles = 0;
268    data->ntiles = 0;
269}
270
Note: See TracBrowser for help on using the repository browser.