| @@ -55,6 +55,9 @@ private: | |||||
| int ntiles; | int ntiles; | ||||
| float angle; | float angle; | ||||
| GLuint *bufs; | |||||
| int nbufs; | |||||
| static Scene *scene; | static Scene *scene; | ||||
| }; | }; | ||||
| @@ -70,10 +73,16 @@ Scene::Scene(float angle) | |||||
| data->tiles = 0; | data->tiles = 0; | ||||
| data->ntiles = 0; | data->ntiles = 0; | ||||
| data->angle = angle; | data->angle = angle; | ||||
| data->bufs = 0; | |||||
| data->nbufs = 0; | |||||
| } | } | ||||
| Scene::~Scene() | Scene::~Scene() | ||||
| { | { | ||||
| /* FIXME: this must be done while the GL context is still active. | |||||
| * Change the architecture to make sure of that. */ | |||||
| glDeleteBuffers(data->nbufs, data->bufs); | |||||
| delete data; | delete data; | ||||
| } | } | ||||
| @@ -131,13 +140,58 @@ void Scene::Render() // XXX: rename to Blit() | |||||
| glRotatef(8.0f * cosf(f), 0.0f, 0.0f, 1.0f); | glRotatef(8.0f * cosf(f), 0.0f, 0.0f, 1.0f); | ||||
| #endif | #endif | ||||
| glTranslatef(-320.0f, -240.0f, 0.0f); | glTranslatef(-320.0f, -240.0f, 0.0f); | ||||
| // XXX: end of debug stuff | |||||
| for (int i = 0; i < data->ntiles; i++) | |||||
| Tiler::BlitTile(data->tiles[i].code, data->tiles[i].x, | |||||
| data->tiles[i].y, data->tiles[i].z, data->tiles[i].o); | |||||
| for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2) | |||||
| { | |||||
| /* Generate new vertex / texture coord buffers if necessary */ | |||||
| if (buf + 2 > data->nbufs) | |||||
| { | |||||
| data->bufs = (GLuint *)realloc(data->bufs, (buf + 2) * sizeof(GLuint)); | |||||
| glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs); | |||||
| data->nbufs = buf + 2; | |||||
| } | |||||
| /* Count how many quads will be needed */ | |||||
| for (n = i + 1; n < data->ntiles; n++) | |||||
| if (data->tiles[i].code >> 16 != data->tiles[n].code >> 16) | |||||
| break; | |||||
| /* Create a vertex array object */ | |||||
| float *vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float)); | |||||
| float *texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float)); | |||||
| for (int j = i; j < n; j++) | |||||
| { | |||||
| Tiler::BlitTile(data->tiles[j].code, data->tiles[j].x, | |||||
| data->tiles[j].y, data->tiles[j].z, data->tiles[j].o, | |||||
| vertex + 18 * (j - i), texture + 12 * (j - i)); | |||||
| } | |||||
| glEnableClientState(GL_VERTEX_ARRAY); | |||||
| glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]); | |||||
| glBufferData(GL_ARRAY_BUFFER, 6 * 3 * (n - i) * sizeof(float), | |||||
| vertex, GL_DYNAMIC_DRAW); | |||||
| glVertexPointer(3, GL_FLOAT, 0, NULL); | |||||
| glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]); | |||||
| glBufferData(GL_ARRAY_BUFFER, 6 * 2 * (n - i) * sizeof(float), | |||||
| texture, GL_DYNAMIC_DRAW); | |||||
| glTexCoordPointer(2, GL_FLOAT, 0, NULL); | |||||
| Tiler::Bind(data->tiles[i].code); | |||||
| glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6); | |||||
| glDisableClientState(GL_VERTEX_ARRAY); | |||||
| glDisableClientState(GL_TEXTURE_COORD_ARRAY); | |||||
| free(vertex); | |||||
| free(texture); | |||||
| } | |||||
| glPopMatrix(); | glPopMatrix(); | ||||
| // XXX: end of debug stuff | |||||
| free(data->tiles); | free(data->tiles); | ||||
| data->tiles = 0; | data->tiles = 0; | ||||
| @@ -93,7 +93,25 @@ int2 Tiler::GetCount(int id) | |||||
| return tileset->GetCount(); | return tileset->GetCount(); | ||||
| } | } | ||||
| void Tiler::BlitTile(uint32_t code, int x, int y, int z, int o) | |||||
| void Tiler::Bind(uint32_t code) | |||||
| { | |||||
| int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | |||||
| TileSet *tileset = (TileSet *)data->tilesets.GetEntity(id); | |||||
| #if !FINAL_RELEASE | |||||
| if (!tileset) | |||||
| { | |||||
| if (id != data->lasterror) | |||||
| fprintf(stderr, "ERROR: binding null tiler #%i\n", id); | |||||
| data->lasterror = id; | |||||
| return; | |||||
| } | |||||
| #endif | |||||
| tileset->Bind(); | |||||
| } | |||||
| void Tiler::BlitTile(uint32_t code, int x, int y, int z, int o, | |||||
| float *vertex, float *texture) | |||||
| { | { | ||||
| int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | int id = (code >> 16) - 1; /* ID 0 is for the empty tileset */ | ||||
| @@ -107,6 +125,6 @@ void Tiler::BlitTile(uint32_t code, int x, int y, int z, int o) | |||||
| return; | return; | ||||
| } | } | ||||
| #endif | #endif | ||||
| tileset->BlitTile(code & 0xffff, x, y, z, o); | |||||
| tileset->BlitTile(code & 0xffff, x, y, z, o, vertex, texture); | |||||
| } | } | ||||
| @@ -27,7 +27,9 @@ public: | |||||
| static int2 GetSize(int id); | static int2 GetSize(int id); | ||||
| static int2 GetCount(int id); | static int2 GetCount(int id); | ||||
| static void BlitTile(uint32_t code, int x, int y, int z, int o); | |||||
| static void Bind(uint32_t code); | |||||
| static void BlitTile(uint32_t code, int x, int y, int z, int o, | |||||
| float *vertex, float *texture); | |||||
| }; | }; | ||||
| #endif // __DH_TILER_H__ | #endif // __DH_TILER_H__ | ||||
| @@ -167,7 +167,14 @@ int2 TileSet::GetCount() const | |||||
| return data->count; | return data->count; | ||||
| } | } | ||||
| void TileSet::BlitTile(uint32_t id, int x, int y, int z, int o) | |||||
| void TileSet::Bind() | |||||
| { | |||||
| if (!data->img) | |||||
| glBindTexture(GL_TEXTURE_2D, data->texture); | |||||
| } | |||||
| void TileSet::BlitTile(uint32_t id, int x, int y, int z, int o, | |||||
| float *vertex, float *texture) | |||||
| { | { | ||||
| float tx = data->tx * ((id & 0xffff) % data->count.i); | float tx = data->tx * ((id & 0xffff) % data->count.i); | ||||
| float ty = data->ty * ((id & 0xffff) / data->count.i); | float ty = data->ty * ((id & 0xffff) / data->count.i); | ||||
| @@ -179,17 +186,48 @@ void TileSet::BlitTile(uint32_t id, int x, int y, int z, int o) | |||||
| if (!data->img) | if (!data->img) | ||||
| { | { | ||||
| glBindTexture(GL_TEXTURE_2D, data->texture); | |||||
| glBegin(GL_QUADS); | |||||
| glTexCoord2f(tx, ty); | |||||
| glVertex3f(x, dilate * (y + dy), dilate * (z + dz)); | |||||
| glTexCoord2f(tx + data->tx, ty); | |||||
| glVertex3f(x + dx, dilate * (y + dy), dilate * (z + dz)); | |||||
| glTexCoord2f(tx + data->tx, ty + data->ty); | |||||
| glVertex3f(x + dx, dilate * y, dilate * z); | |||||
| glTexCoord2f(tx, ty + data->ty); | |||||
| glVertex3f(x, dilate * y, dilate * z); | |||||
| glEnd(); | |||||
| float tmp[10]; | |||||
| *vertex++ = tmp[0] = x; | |||||
| *vertex++ = tmp[1] = dilate * (y + dy); | |||||
| *vertex++ = tmp[2] = dilate * (z + dz); | |||||
| *texture++ = tmp[3] = tx; | |||||
| *texture++ = tmp[4] = ty; | |||||
| *vertex++ = x + dx; | |||||
| *vertex++ = dilate * (y + dy); | |||||
| *vertex++ = dilate * (z + dz); | |||||
| *texture++ = tx + data->tx; | |||||
| *texture++ = ty; | |||||
| *vertex++ = tmp[5] = x + dx; | |||||
| *vertex++ = tmp[6] = dilate * y; | |||||
| *vertex++ = tmp[7] = dilate * z; | |||||
| *texture++ = tmp[8] = tx + data->tx; | |||||
| *texture++ = tmp[9] = ty + data->ty; | |||||
| *vertex++ = tmp[0]; | |||||
| *vertex++ = tmp[1]; | |||||
| *vertex++ = tmp[2]; | |||||
| *texture++ = tmp[3]; | |||||
| *texture++ = tmp[4]; | |||||
| *vertex++ = tmp[5]; | |||||
| *vertex++ = tmp[6]; | |||||
| *vertex++ = tmp[7]; | |||||
| *texture++ = tmp[8]; | |||||
| *texture++ = tmp[9]; | |||||
| *vertex++ = x; | |||||
| *vertex++ = dilate * y; | |||||
| *vertex++ = dilate * z; | |||||
| *texture++ = tx; | |||||
| *texture++ = ty + data->ty; | |||||
| } | |||||
| else | |||||
| { | |||||
| memset(vertex, 0, 3 * sizeof(float)); | |||||
| memset(texture, 0, 2 * sizeof(float)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -40,7 +40,9 @@ public: | |||||
| /* New methods */ | /* New methods */ | ||||
| int2 GetSize() const; | int2 GetSize() const; | ||||
| int2 GetCount() const; | int2 GetCount() const; | ||||
| void BlitTile(uint32_t id, int x, int y, int z, int o); | |||||
| void Bind(); | |||||
| void BlitTile(uint32_t id, int x, int y, int z, int o, | |||||
| float *vertex, float *texture); | |||||
| private: | private: | ||||
| TileSetData *data; | TileSetData *data; | ||||