fixes #70: raster tile rendering as toggleable mode from vector
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
#include <llmr/map/coverage.hpp>
|
||||
#include <llmr/util/constants.hpp>
|
||||
#include <llmr/util/vec.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
|
||||
@@ -64,15 +67,28 @@ void _scanTriangle(const llmr::vec2<double> a, const llmr::vec2<double> b, const
|
||||
if (bc.dy) _scanSpans(ca, bc, ymin, ymax, scanLine);
|
||||
}
|
||||
|
||||
std::forward_list<llmr::Tile::ID> llmr::covering_tiles(int32_t zoom, const box& points) {
|
||||
std::forward_list<llmr::Tile::ID> llmr::covering_tiles(int32_t zoom, const box& points, const bool use_raster, const bool use_retina) {
|
||||
int32_t dim = pow(2, zoom);
|
||||
std::forward_list<llmr::Tile::ID> tiles;
|
||||
|
||||
auto scanLine = [&tiles, zoom](int32_t x0, int32_t x1, int32_t y, int32_t ymax) {
|
||||
auto scanLine = [&tiles, zoom, use_raster, use_retina](int32_t x0, int32_t x1, int32_t y, int32_t ymax) {
|
||||
int32_t x;
|
||||
if (y >= 0 && y <= ymax) {
|
||||
for (x = x0; x < x1; x++) {
|
||||
tiles.emplace_front(zoom, x, y);
|
||||
if (use_raster) {
|
||||
uint32_t search_zoom = zoom;
|
||||
search_zoom += (uint32_t)((llmr::util::tileSize / 256.0f) - 1.0f);
|
||||
if (use_retina) {
|
||||
search_zoom += 1;
|
||||
}
|
||||
Tile::ID id = Tile::ID(zoom, x, y);
|
||||
auto ids = id.children(search_zoom);
|
||||
for (const Tile::ID& child_id : ids) {
|
||||
tiles.emplace_front(child_id.z, child_id.x, child_id.y);
|
||||
}
|
||||
} else {
|
||||
tiles.emplace_front(zoom, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <llmr/style/resources.hpp>
|
||||
#include <llmr/style/sprite.hpp>
|
||||
#include <llmr/map/coverage.hpp>
|
||||
#include <llmr/util/animation.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -14,8 +15,9 @@ Map::Map(Settings& settings)
|
||||
transform(),
|
||||
style(),
|
||||
painter(transform, settings, style),
|
||||
texturepool(),
|
||||
min_zoom(0),
|
||||
max_zoom(14) {
|
||||
max_zoom((use_raster ? kTileRasterMaxZoom : kTileVectorMaxZoom)) {
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
@@ -23,6 +25,7 @@ Map::~Map() {
|
||||
}
|
||||
|
||||
void Map::setup(float pixelRatio) {
|
||||
|
||||
painter.setup();
|
||||
|
||||
pixel_ratio = pixelRatio;
|
||||
@@ -33,10 +36,6 @@ void Map::setup(float pixelRatio) {
|
||||
style.loadJSON(resources::style, resources::style_size);
|
||||
}
|
||||
|
||||
void Map::loadSprite(const std::string& url) {
|
||||
|
||||
}
|
||||
|
||||
void Map::loadStyle(const uint8_t *const data, uint32_t bytes) {
|
||||
style.loadJSON(data, bytes);
|
||||
update();
|
||||
@@ -60,6 +59,13 @@ void Map::resize(uint32_t width, uint32_t height, uint32_t fb_width, uint32_t fb
|
||||
update();
|
||||
}
|
||||
|
||||
void Map::toggleRaster() {
|
||||
use_raster = ! use_raster;
|
||||
max_zoom = (use_raster ? kTileRasterMaxZoom : kTileVectorMaxZoom);
|
||||
tiles.clear();
|
||||
update();
|
||||
}
|
||||
|
||||
void Map::moveBy(double dx, double dy, double duration) {
|
||||
transform.moveBy(dx, dy, duration);
|
||||
update();
|
||||
@@ -278,7 +284,7 @@ TileData::State Map::addTile(const Tile::ID& id) {
|
||||
|
||||
if (!new_tile.data) {
|
||||
// If we don't find working tile data, we're just going to load it.
|
||||
new_tile.data = std::make_shared<TileData>(normalized_id, style);
|
||||
new_tile.data = std::make_shared<TileData>(normalized_id, style, use_raster, (pixel_ratio > 1.0));
|
||||
new_tile.data->request();
|
||||
tile_data.push_front(new_tile.data);
|
||||
}
|
||||
@@ -352,12 +358,14 @@ bool Map::updateTiles() {
|
||||
int32_t min_covering_zoom = zoom - 10;
|
||||
if (min_covering_zoom < min_zoom) min_covering_zoom = min_zoom;
|
||||
|
||||
int32_t max_dim = pow(2, zoom);
|
||||
|
||||
// Map four viewport corners to pixel coordinates
|
||||
box box = transform.mapCornersToBox(zoom);
|
||||
|
||||
// Performs a scanline algorithm search that covers the rectangle of the box
|
||||
// and sorts them by proximity to the center.
|
||||
std::forward_list<Tile::ID> required = llmr::covering_tiles(zoom, box);
|
||||
std::forward_list<Tile::ID> required = llmr::covering_tiles(zoom, box, use_raster, (pixel_ratio > 1.0));
|
||||
|
||||
// Retain is a list of tiles that we shouldn't delete, even if they are not
|
||||
// the most ideal tile for the current viewport. This may include tiles like
|
||||
@@ -369,6 +377,9 @@ bool Map::updateTiles() {
|
||||
const TileData::State state = addTile(id);
|
||||
|
||||
if (state != TileData::State::parsed) {
|
||||
if (use_raster && (transform.rotating || transform.scaling || transform.panning))
|
||||
break;
|
||||
|
||||
// The tile we require is not yet loaded. Try to find a parent or
|
||||
// child tile that we already have.
|
||||
|
||||
@@ -431,6 +442,10 @@ bool Map::render() {
|
||||
transform.updateAnimations();
|
||||
}
|
||||
|
||||
if (*style.sprite->raster && !style.sprite->raster->textured) {
|
||||
style.sprite->raster->setTexturepool(&texturepool);
|
||||
}
|
||||
|
||||
bool changed = updateTiles();
|
||||
|
||||
painter.clear();
|
||||
@@ -447,13 +462,20 @@ bool Map::render() {
|
||||
transform.matrixFor(tile.matrix, tile.id);
|
||||
matrix::multiply(tile.matrix, painter.projMatrix, tile.matrix);
|
||||
tile.clip_id = i++;
|
||||
painter.drawClippingMask(tile.matrix, tile.clip_id);
|
||||
painter.drawClippingMask(tile.matrix, tile.clip_id, !tile.data->use_raster);
|
||||
}
|
||||
}
|
||||
painter.finishClippingMask();
|
||||
|
||||
for (const Tile& tile : tiles) {
|
||||
if (tile.data && tile.data->state == TileData::State::parsed) {
|
||||
if (tile.data->use_raster && *tile.data->raster && !tile.data->raster->textured) {
|
||||
tile.data->raster->setTexturepool(&texturepool);
|
||||
tile.data->raster->beginFadeInAnimation();
|
||||
}
|
||||
if (tile.data->use_raster && tile.data->raster->needsAnimation()) {
|
||||
tile.data->raster->updateAnimations();
|
||||
}
|
||||
painter.render(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,19 @@
|
||||
#include <llmr/renderer/line_bucket.hpp>
|
||||
#include <llmr/renderer/point_bucket.hpp>
|
||||
#include <llmr/util/pbf.hpp>
|
||||
#include <llmr/util/raster.hpp>
|
||||
#include <llmr/util/string.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
TileData::TileData(Tile::ID id, const Style& style)
|
||||
TileData::TileData(Tile::ID id, const Style& style, const bool use_raster, const bool use_retina)
|
||||
: id(id),
|
||||
state(State::initial),
|
||||
use_raster(use_raster),
|
||||
use_retina(use_retina),
|
||||
raster(),
|
||||
fillVertexBuffer(std::make_shared<FillVertexBuffer>()),
|
||||
lineVertexBuffer(std::make_shared<LineVertexBuffer>()),
|
||||
pointVertexBuffer(std::make_shared<PointVertexBuffer>()),
|
||||
@@ -44,9 +48,13 @@ const std::string TileData::toString() const {
|
||||
void TileData::request() {
|
||||
state = State::loading;
|
||||
|
||||
// Create http request
|
||||
std::string url = util::sprintf(kTileURL,
|
||||
id.z, id.x, id.y);
|
||||
std::string url;
|
||||
|
||||
if (use_raster) {
|
||||
url = util::sprintf(kTileRasterURL, id.z, id.x, id.y, (use_retina ? "@2x" : ""));
|
||||
} else {
|
||||
url = util::sprintf(kTileVectorURL, id.z, id.x, id.y);
|
||||
}
|
||||
|
||||
// Note: Somehow this feels slower than the change to request_http()
|
||||
std::weak_ptr<TileData> weak_tile = shared_from_this();
|
||||
@@ -80,6 +88,13 @@ bool TileData::parse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (use_raster) {
|
||||
raster = std::make_shared<Raster>();
|
||||
raster->load(data);
|
||||
state = State::parsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
double parse_time_start = platform::time();
|
||||
VectorTile tile(pbf((const uint8_t *)data.data(), data.size()));
|
||||
|
||||
Reference in New Issue
Block a user