source: trunk/src/tileset.cpp @ 75

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

Much better resource allocation and release. Scene manager stub.

  • Property svn:keywords set to Id
File size: 4.7 KB
Line 
1
2#ifdef WIN32
3#   define WIN32_LEAN_AND_MEAN
4#   include <windows.h>
5#endif
6#if defined __APPLE__ && defined __MACH__
7#   include <OpenGL/gl.h>
8#else
9#   define GL_GLEXT_PROTOTYPES
10#   include <GL/gl.h>
11#   include <GL/glext.h>
12#endif
13
14#include <SDL.h>
15#include <SDL_image.h>
16
17#include <malloc.h>
18
19#include "tileset.h"
20
21/*
22 * TileSet implementation class
23 */
24
25class TileSetData
26{
27    friend class TileSet;
28
29private:
30    static int Compare(void const *p1, void const *p2)
31    {
32        int const *n1 = (int const *)p1;
33        int const *n2 = (int const *)p2;
34
35        return n1[2] + 32 * n1[3] - (n2[2] + 32 * n2[3]);
36    }
37
38    char *name;
39    int ref;
40    int *tiles;
41    int ntiles;
42
43    GLuint texture[1];
44    GLuint buflist[3];
45};
46
47/*
48 * Public TileSet class
49 */
50
51TileSet::TileSet(char const *path)
52{
53    SDL_Surface *img = NULL;
54
55    data = new TileSetData();
56    data->name = strdup(path);
57    data->ref = 0;
58    data->tiles = NULL;
59    data->ntiles = 0;
60
61    /* One tile texture */
62    for (char const *name = path; *name; name++)
63        if ((img = IMG_Load(name)))
64            break;
65
66    if (!img)
67    {
68        SDL_Quit();
69        exit(1);
70    }
71
72    glGenTextures(1, data->texture);
73    glBindTexture(GL_TEXTURE_2D, data->texture[0]);
74
75    glTexImage2D(GL_TEXTURE_2D, 0, 4, img->w, img->h, 0,
76                 GL_RGBA, GL_UNSIGNED_BYTE, img->pixels);
77
78    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
79    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
80
81    /* Three GPU buffers */
82    glGenBuffers(3, data->buflist);
83}
84
85TileSet::~TileSet()
86{
87    glDeleteTextures(1, data->texture);
88    glDeleteBuffers(3, data->buflist);
89
90    free(data->tiles);
91    free(data->name);
92    delete data;
93}
94
95void TileSet::Ref()
96{
97    data->ref++;
98}
99
100int TileSet::Unref()
101{
102    return --data->ref;
103}
104
105char const *TileSet::GetName()
106{
107    return data->name;
108}
109
110void TileSet::AddTile(int n, int x, int y, int z)
111{
112    if ((data->ntiles % 1024) == 0)
113    {
114        data->tiles = (int *)realloc(data->tiles,
115                                     (data->ntiles + 1024) * 4 * sizeof(int));
116    }
117
118    data->tiles[4 * data->ntiles] = n;
119    data->tiles[4 * data->ntiles + 1] = x;
120    data->tiles[4 * data->ntiles + 2] = y;
121    data->tiles[4 * data->ntiles + 3] = z;
122
123    data->ntiles++;
124}
125
126void TileSet::Render()
127{
128    /* Sort tiles */
129    qsort(data->tiles, data->ntiles, 4 * sizeof(int), TileSetData::Compare);
130
131    /* Texture coord buffer */
132    float uvs[8 * data->ntiles];
133    for (int n = 0; n < data->ntiles; n++)
134    {
135        int tile = data->tiles[4 * n];
136        float ty = .0625f * (tile / 16);
137        float tx = .0625f * (tile % 16);
138        uvs[8 * n + 0] = tx;
139        uvs[8 * n + 1] = ty;
140        uvs[8 * n + 2] = tx + .0625f;
141        uvs[8 * n + 3] = ty;
142        uvs[8 * n + 4] = tx + .0625f;
143        uvs[8 * n + 5] = ty + .0625f;
144        uvs[8 * n + 6] = tx;
145        uvs[8 * n + 7] = ty + .0625f;
146    }
147    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]);
148    glBufferData(GL_ARRAY_BUFFER,
149                 8 * data->ntiles * sizeof(float), uvs, GL_STATIC_DRAW);
150
151    /* Vertex buffer */
152    float vertices[8 * data->ntiles];
153    for (int n = 0; n < data->ntiles; n++)
154    {
155        int x = data->tiles[4 * n + 1];
156        int y = data->tiles[4 * n + 2];
157        vertices[8 * n + 0] = x;
158        vertices[8 * n + 1] = y;
159        vertices[8 * n + 2] = x + 32;
160        vertices[8 * n + 3] = y;
161        vertices[8 * n + 4] = x + 32;
162        vertices[8 * n + 5] = y + 32;
163        vertices[8 * n + 6] = x;
164        vertices[8 * n + 7] = y + 32;
165    }
166    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]);
167    glBufferData(GL_ARRAY_BUFFER, 8 * data->ntiles * sizeof(float),
168                 vertices, GL_STATIC_DRAW);
169
170    /* Index buffer */
171    int indices[4 * data->ntiles];
172    for (int n = 0; n < 4 * data->ntiles; n++)
173        indices[n] = n;
174    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]);
175    glBufferData(GL_ARRAY_BUFFER, 4 * data->ntiles * sizeof(int),
176                 indices, GL_STATIC_DRAW);
177
178    /* Draw everything */
179    glEnableClientState(GL_VERTEX_ARRAY);
180    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
181    glEnableClientState(GL_INDEX_ARRAY);
182
183    glBindTexture(GL_TEXTURE_2D, data->texture[0]);
184
185    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[0]);
186    glVertexPointer(2, GL_FLOAT, 0, NULL);
187    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[1]);
188    glTexCoordPointer(2, GL_FLOAT, 0, NULL);
189    glBindBuffer(GL_ARRAY_BUFFER, data->buflist[2]);
190    glIndexPointer(GL_INT, 0, NULL);
191
192    glDrawArrays(GL_QUADS, 0, 4 * data->ntiles);
193
194    glDisableClientState(GL_VERTEX_ARRAY);
195    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
196    glDisableClientState(GL_INDEX_ARRAY);
197
198    /* Empty our shit */
199    free(data->tiles);
200    data->tiles = NULL;
201    data->ntiles = 0;
202}
203
Note: See TracBrowser for help on using the repository browser.