diff options
author | Paweł Redman <pawel.redman@gmail.com> | 2017-12-19 19:27:06 +0100 |
---|---|---|
committer | Paweł Redman <pawel.redman@gmail.com> | 2017-12-19 19:27:06 +0100 |
commit | 297524c8ec41b585c4812494791772406653e479 (patch) | |
tree | 40e91994daeb073051e7b3f40465f76b9f54ed36 /src/render.cpp | |
parent | bbed2cb38638e51bc19a50464ec818ea96524c2c (diff) |
Introduce tall tiles.
Some features are still missing but the commit is large enough as it is. TODO: render layers and fix minor artifacts.
Diffstat (limited to 'src/render.cpp')
-rw-r--r-- | src/render.cpp | 221 |
1 files changed, 160 insertions, 61 deletions
diff --git a/src/render.cpp b/src/render.cpp index 76701b6..6c47ab7 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -1,4 +1,5 @@ #include "common.hpp" +#include <iomanip> static sf::RectangleShape wot_rect; static sf::Font font; @@ -12,17 +13,31 @@ state_t::state_t(sf::RenderWindow *window_) font.loadFromFile("assets/FanwoodText.otf"); } -// FIXME: rename -static sf::Texture *tiles[256] = {0}; +typedef struct { + sf::Texture *top, *side; + float height; +} tiledata_t; +static tiledata_t tiledata[256] = {0}; -void register_tile(uint8_t type, const char *path) +void register_tile(uint8_t type, const char *top, const char *side, float height) { - printf("load %s\n", path); - tiles[type] = new sf::Texture; - tiles[type]->loadFromFile(path); - tiles[type]->setRepeated(true); + tiledata_t *tile = tiledata + type; + + printf("load %s\n", top); + tile->top = new sf::Texture; + tile->top->loadFromFile(top); + tile->top->setRepeated(true); + + if (height > 0.0f) { + tile->height = height; + printf("load %s\n", side); + tile->side = new sf::Texture; + tile->side->loadFromFile(side); + tile->side->setRepeated(true); + } } + void state_t::begin_frame(double now_, double dt_) { now = now_; @@ -71,17 +86,17 @@ void state_t::drender_entity(world::entity_t *ent) drender_text(ent->render_bounds, ss.str()); } -static const v2f_t tile_base[8] ={ - {1.0f, 0.5f}, {1.0f, 1.0f}, {0.5f, 1.0f}, {0.0f, 1.0f}, - {0.0f, 0.5f}, {0.0f, 0.0f}, {0.5f, 0.0f}, {1.0f, 0.0f} -}; - static void generate_tile_verts(sf::Vertex *verts, v2f_t tx, procgen::perlin_noise_t *perlin) { + static const v2f_t local_base[8] ={ + {1.0f, 0.5f}, {1.0f, 1.0f}, {0.5f, 1.0f}, {0.0f, 1.0f}, + {0.0f, 0.5f}, {0.0f, 0.0f}, {0.5f, 0.0f}, {1.0f, 0.0f} + }; + for (size_t i = 0; i < 8; i++) { v2f_t base, turb; - base = tile_base[i] + tx; + base = local_base[i] + tx; turb[0] = perlin->get(base, 1.0f) * 0.5f; turb[1] = perlin->get(base, 2.0f) * 0.5f; @@ -92,89 +107,173 @@ static void generate_tile_verts(sf::Vertex *verts, v2f_t tx, procgen::perlin_noi } } -void state_t::render_sector(world::world_t *world, world::sector_t *sector) +void state_t::render_tile(world::world_t *world, v2f_t tx, world::tile_t *tile) { - for (ssize_t y = 0; y < SECTOR_SIZE; y++) - for (ssize_t x = 0; x < SECTOR_SIZE; x++) { - sf::Vertex verts[8]; - sf::Texture *texture; - v2f_t tx; - world::tile_t *tile; - - tx = sector->bounds.v[0] + v2f_t(x, y); - tile = sector->tiles + y * SECTOR_SIZE + x; - - texture = tiles[tile->type]; - if (!texture) { - printf("draw_tile: tile %i not registered\n", tile->type); - abort(); - } + static const size_t side_order[6] = {4, 0, 7, 3, 2, 1}; + static const size_t side_tests[8] = {1, 4, 4, 16, 16, 64, 64, 1}; - sf::RenderStates states(texture); - generate_tile_verts(verts, tx, &world->perlin); - window->draw(verts, 8, sf::TrianglesFan, states); + sf::Vertex verts[8]; + tiledata_t *data; - if (debug_draw_tile_coords) { - world::tile_index_t local(x, y); - std::stringstream ss; + data = tiledata + tile->type; - ss << "L=" << local; - sf::Text text(ss.str(), font, 20); - text.setPosition(tx); - text.setScale(0.005, 0.005); - window->draw(text); + generate_tile_verts(verts, tx, &world->perlin); + + if (data->height) { + sf::RenderStates states(data->side); + + for (size_t i = 0; i < 6; i++) { + size_t j = side_order[i]; + size_t k = (j + 1) % 8; + sf::Vertex quad[4]; + + if (tile->neighbors & side_tests[j]) + continue; + + quad[0] = verts[j]; + quad[0].texCoords.y = 0; + quad[1] = verts[k]; + quad[1].texCoords.y = 0; + quad[2] = quad[1]; + quad[3] = quad[0]; + + quad[2].position.y -= data->height; + quad[2].texCoords.y -= data->height * 32; + quad[3].position.y -= data->height; + quad[3].texCoords.y -= data->height * 32; + + window->draw(quad, 4, sf::TrianglesFan, states); } - stats.tiles++; + for (size_t i = 0; i < 8; i++) + verts[i].position.y -= data->height; } - stats.sectors++; + sf::RenderStates states(data->top); + window->draw(verts, 8, sf::TrianglesFan, states); + stats.tiles++; } -void state_t::render(game::state_t *game) +static rectf_t window_bounds(sf::RenderWindow *window) { + const v2f_t margin(1.5f, 1.5f); + sf::Vector2u size = window->getSize(); v2f_t A, B, C, D; - const v2f_t margin(1.0f, 1.0f); - rectf_t bbox; - std::list<world::entity_t*> ents; + rectf_t bounds; A = window->mapPixelToCoords(sf::Vector2i(0, 0)); B = window->mapPixelToCoords(sf::Vector2i(size.x, 0)); C = window->mapPixelToCoords(sf::Vector2i(0, size.y)); D = window->mapPixelToCoords(sf::Vector2i(size.x, size.y)); - bbox[0][0] = std::min({A[0], B[0], C[0], D[0]}); - bbox[0][1] = std::min({A[1], B[1], C[1], D[1]}); - bbox[1][0] = std::max({A[0], B[0], C[0], D[0]}); - bbox[1][1] = std::max({A[1], B[1], C[1], D[1]}); + bounds[0][0] = std::min({A[0], B[0], C[0], D[0]}); + bounds[0][1] = std::min({A[1], B[1], C[1], D[1]}); + bounds[1][0] = std::max({A[0], B[0], C[0], D[0]}); + bounds[1][1] = std::max({A[1], B[1], C[1], D[1]}); + bounds[0] -= margin; + bounds[1] += margin; + + return bounds; +} - bbox[0] -= margin; - bbox[1] += margin; +void state_t::render(game::state_t *game) +{ + rectf_t bounds; + std::list<world::entity_t*> ents; + std::list<world::entity_t*>::iterator ent; + rect_t<world::coord_t, 2> sectors; - for (world::sector_t *sector : game->world.get_sectors(bbox)) - render_sector(&game->world, sector); + bounds = window_bounds(window); + sectors[0] = world::sector_index_at(bounds[0]); + sectors[1] = world::sector_index_at(bounds[1]); - ents = game->world.get_render_entities(bbox); + ents = game->world.get_render_entities(bounds); ents.sort( [](const world::entity_t *x, const world::entity_t *y) -> bool { + return x->render_bounds[1][1] < y->render_bounds[1][1]; + // FIXME: bring render layers back + /* if (x->render_layer < y->render_layer) return true; else if (x->render_layer > y->render_layer) return false; else - return x->render_bounds[1][1] < y->render_bounds[1][1]; + return x->render_bounds[1][1] < y->render_bounds[1][1];*/ }); - for (world::entity_t *ent : ents) { - ent->render_to(this); + ent = ents.begin(); - if (debug_draw_cmodels) - drender_entity(ent); + for (world::coord_t sy = sectors[0][1]; sy <= sectors[1][1]; sy++) + for (world::coord_t ty = 0; ty < SECTOR_SIZE; ty++) + for (world::coord_t sx = sectors[0][0]; sx <= sectors[1][0]; sx++) { + world::sector_index_t sector_index(sx, sy); + world::sector_t *sector; + + sector = game->world.get_sector(sector_index, world::SECTOR_FULL); + + while (ent != ents.end() && + (*ent)->render_bounds[1][1] < sy * SECTOR_SIZE + ty) { + (*ent)->render_to(this); + stats.entities++; + ent++; + } + + for (world::coord_t tx = 0; tx < SECTOR_SIZE; tx++) { + world::tile_index_t index; + world::tile_t *tile; - stats.entities++; + index = sector_index * SECTOR_SIZE + + world::tile_index_t(tx, ty); + tile = sector->tiles + ty * SECTOR_SIZE + tx; + + render_tile(&game->world, index, tile); + } + + stats.sectors++; } + + // Every sector is iterated SECTOR_SIZE times. + stats.sectors /= SECTOR_SIZE; + + if (debug_draw_tile_coords) { + for (world::sector_t *sector : game->world.get_sectors(bounds, world::SECTOR_FULL)) + for (world::coord_t ty = 0; ty < SECTOR_SIZE; ty++) + for (world::coord_t tx = 0; tx < SECTOR_SIZE; tx++) { + std::stringstream ss; + world::tile_index_t local, index; + world::tile_t *tile; + int neighbors; + + local = world::tile_index_t(tx, ty); + index = sector->index * SECTOR_SIZE + local; + tile = sector->tiles + ty * SECTOR_SIZE + tx; + + ss << "SI: " << sector->index << "\n"; + ss << "GI: " << index << "\n"; + ss << "LI: " << local << "\n"; + ss << "T: " << tile->type << "\n"; + ss << "N: "; + + neighbors = tile->neighbors; + for (size_t i = 0; i < 8; i++) { + ss << ((neighbors & 1) ? 'P' : 'A'); + neighbors >>= 1; + } + + ss << " (" << tile->neighbors << ")"; + + sf::Text text(ss.str(), font, 20); + text.setPosition(index); + text.setScale(0.005, 0.005); + window->draw(text); + } + } + + if (debug_draw_cmodels) + for (world::entity_t *ent : ents) + drender_entity(ent); } void state_t::render(double phase, animated_texture_t *anim, rectf_t bounds, sf::Color color, bool mirror){ |