summaryrefslogtreecommitdiff
path: root/src/render.cpp
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-12-19 19:27:06 +0100
committerPaweł Redman <pawel.redman@gmail.com>2017-12-19 19:27:06 +0100
commit297524c8ec41b585c4812494791772406653e479 (patch)
tree40e91994daeb073051e7b3f40465f76b9f54ed36 /src/render.cpp
parentbbed2cb38638e51bc19a50464ec818ea96524c2c (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.cpp221
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){