summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt7
-rw-r--r--Makefile18
-rw-r--r--emscripten/main.cpp14
-rw-r--r--include/llmr/map/map.hpp9
-rw-r--r--include/llmr/map/tile.hpp7
-rw-r--r--include/llmr/map/transform.hpp10
-rw-r--r--include/llmr/platform/gl.hpp2
-rw-r--r--include/llmr/platform/platform.hpp13
-rw-r--r--include/llmr/renderer/painter.hpp6
-rw-r--r--include/llmr/util/vec2.hpp40
-rw-r--r--macosx/CMakeLists.txt37
-rw-r--r--macosx/main.mm36
-rw-r--r--src/CMakeLists.txt43
-rw-r--r--src/map/map.cpp100
-rw-r--r--src/map/pbf.hpp20
-rw-r--r--src/map/tile.cpp50
-rw-r--r--src/map/transform.cpp56
-rw-r--r--src/renderer/painter.cpp5
18 files changed, 389 insertions, 84 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000..fa5ddfdfab
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
+project(llmr)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
+
+add_subdirectory(src)
+add_subdirectory(macosx)
diff --git a/Makefile b/Makefile
index 3c3269d791..ca26e61495 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-CXXFLAGS = -Wall -Wextra -std=c++11 -stdlib=libc++ -fno-exceptions
-CPPFLAGS = -O3 -DDEBUG
+CXXFLAGS = -O2 -Wall -Wextra -std=c++11 -stdlib=libc++ -fno-exceptions
+CPPFLAGS = -DDEBUG
INCLUDE = -Iinclude
@@ -21,8 +21,9 @@ main: macosx
macosx: SRCS += macosx/main.mm
emscripten: SRCS += emscripten/main.cpp
+emscripten3: SRCS += emscripten/main.cpp
-macosx emscripten: OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
+macosx emscripten emscripten3: OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
@@ -36,13 +37,18 @@ macosx emscripten: OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.
.SECONDEXPANSION:
macosx: $$(OBJS)
- $(CXX) $(OBJS) $(INCLUDE) -lglfw3 -framework OpenGL -framework Foundation -o macosx/main
+ $(CXX) -O3 $(OBJS) $(INCLUDE) -lglfw3 -framework OpenGL -framework Foundation -o macosx/main
emscripten: $$(OBJS)
$(CXX) $(OBJS) $(INCLUDE) -o emscripten/main.js
+emscripten3: $$(OBJS)
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OBJS) $(INCLUDE) -s DOUBLE_MODE=0 -s FORCE_ALIGNED_MEMORY=1 -s PRECISE_I64_MATH=0 --closure 1 -o emscripten/main.js
+ uglifyjs emscripten/main.js -mc > emscripten/main.dist.js
+ gzip -c emscripten/main.dist.js > emscripten/main.dist.js.gz
+
clean:
- rm -rf src/*/*.o
- rm -rf macosx/main
+ rm -rf */*.o */*/*.o
+ rm -rf macosx/main emscripten/main.js emscripten/main.js.map
.PHONY: macosx emscripten
diff --git a/emscripten/main.cpp b/emscripten/main.cpp
index 20e9212baf..4565a67d51 100644
--- a/emscripten/main.cpp
+++ b/emscripten/main.cpp
@@ -3,6 +3,7 @@
#include <cstdio>
#include <cstdlib>
#include <cmath>
+ #include <unistd.h>
#include <llmr/llmr.hpp>
#include <llmr/map/tile.hpp>
@@ -18,8 +19,7 @@ public:
MapView() :
dirty(true),
platform(new llmr::platform(this)),
- painter(new llmr::painter(platform)),
- map(new llmr::map(platform, painter)) {
+ map(new llmr::map(platform)) {
// Initialize GLFW
if (!glfwInit()) {
@@ -42,14 +42,13 @@ public:
exit(1);
}
- painter->setup();
- painter->resize(width, height);
+ map->setup();
+ map->resize(width, height);
}
~MapView() {
delete map;
- delete painter;
delete platform;
glfwTerminate();
}
@@ -65,7 +64,7 @@ public:
static void scroll(float pos) {
double delta = pos;
- bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
+ // bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
double absdelta = delta < 0 ? -delta : delta;
double scale = 2.0 / (1.0 + exp(-absdelta / 100.0));
@@ -86,6 +85,8 @@ public:
static void mouseclick(int button, int action) {
if (button == GLFW_MOUSE_BUTTON_1) {
view->tracking = action == GLFW_PRESS;
+ } else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
+ fprintf(stderr, "right mouse\n");
}
}
@@ -110,7 +111,6 @@ public:
llmr::platform *platform;
- llmr::painter *painter;
llmr::map *map;
};
diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp
index 7f2903a261..745ccce89d 100644
--- a/include/llmr/map/map.hpp
+++ b/include/llmr/map/map.hpp
@@ -11,7 +11,7 @@ class tile;
class map {
public:
- map(class platform *platform);
+ map();
~map();
void setup();
@@ -26,10 +26,15 @@ public:
void tileFailed(tile *tile);
private:
- platform *platform;
+ void updateTiles();
+
+private:
transform *transform;
painter *painter;
+ // int32_t min_zoom;
+ // int32_t max_zoom;
+
std::vector<tile *> tiles;
};
diff --git a/include/llmr/map/tile.hpp b/include/llmr/map/tile.hpp
index 026810ace4..95d0593f72 100644
--- a/include/llmr/map/tile.hpp
+++ b/include/llmr/map/tile.hpp
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <vector>
+#include <llmr/util/vec2.hpp>
namespace llmr {
@@ -18,9 +19,15 @@ public:
void parseFeature(const uint8_t *data, uint32_t bytes);
void loadGeometry(const uint8_t *data, uint32_t bytes);
+ void cancel();
+
+ static uint64_t toID(int32_t z, int32_t x, int32_t y, int32_t w = 0);
+ static vec4<int32_t> fromID(uint64_t id);
+
public:
const int32_t z, x, y;
bool loaded;
+ bool cancelled;
linevertexbuffer lineVertex;
private:
diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp
index 4ff3cc0076..5d81b0c202 100644
--- a/include/llmr/map/transform.hpp
+++ b/include/llmr/map/transform.hpp
@@ -3,8 +3,11 @@
#include <cstdint>
+
namespace llmr {
+struct box;
+
class tile;
class transform {
@@ -24,8 +27,13 @@ public:
// Getters
void matrixFor(float matrix[16], uint32_t z, uint32_t x, uint32_t y) const;
+ int32_t getZoom() const;
void getLonLat(double& lon, double& lat) const;
+
+ // Temporary
+ void mapCornersToBox(uint32_t z, box& b) const;
+
private:
double pixel_x() const;
double pixel_y() const;
@@ -40,6 +48,8 @@ private:
double angle;
double scale;
+ double min_scale, max_scale;
+
// tile size
const int32_t size = 512;
diff --git a/include/llmr/platform/gl.hpp b/include/llmr/platform/gl.hpp
index 58d9099c70..fb36b5b794 100644
--- a/include/llmr/platform/gl.hpp
+++ b/include/llmr/platform/gl.hpp
@@ -12,8 +12,8 @@
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#elif TARGET_OS_MAC
- #include <GLFW/glfw3.h>
#include <OpenGL/OpenGL.h>
+ #include <OpenGL/gl.h>
#else
#error Unsupported Apple platform
#endif
diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp
index e8aa972d7b..69efb68064 100644
--- a/include/llmr/platform/platform.hpp
+++ b/include/llmr/platform/platform.hpp
@@ -5,18 +5,13 @@ namespace llmr {
class tile;
-class platform {
-public:
- platform(void *obj) : obj(obj) {}
- void restart();
- void request(tile *tile);
+namespace platform {
-private:
- void *obj;
-};
+void restart(void *obj);
+void request(void *obj, tile *tile);
}
-
+}
#endif
diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp
index 21dec5e075..e01f6828a1 100644
--- a/include/llmr/renderer/painter.hpp
+++ b/include/llmr/renderer/painter.hpp
@@ -6,13 +6,12 @@
namespace llmr {
-class platform;
class transform;
class tile;
class painter {
public:
- painter(class platform *platform, class transform *tranform);
+ painter(class transform *tranform);
void setup();
void teardown();
@@ -31,7 +30,6 @@ private:
public:
private:
- platform *platform;
transform *transform;
float matrix[16];
@@ -39,7 +37,7 @@ private:
FillShader *fillShader;
LineShader *lineShader;
- uint32_t vertexArray;
+ // uint32_t vertexArray;
uint32_t triangleVertexBuffer;
uint32_t fillVertexBuffer;
};
diff --git a/include/llmr/util/vec2.hpp b/include/llmr/util/vec2.hpp
new file mode 100644
index 0000000000..abc49e54bd
--- /dev/null
+++ b/include/llmr/util/vec2.hpp
@@ -0,0 +1,40 @@
+#ifndef llmr_util_vec2_
+#define llmr_util_vec2_
+
+namespace llmr {
+
+template <typename T = double>
+struct vec2 {
+ T x, y;
+
+ // inline bool operator==(const vec2& rhs) const {
+ // return x == rhs.x && y == rhs.y;
+ // }
+};
+
+template <typename T = double>
+struct vec3 {
+ T x, y, z;
+
+ // inline bool operator==(const vec3& rhs) const {
+ // return x == rhs.x && y == rhs.y && z == rhs.z;
+ // }
+};
+
+template <typename T = double>
+struct vec4 {
+ T x, y, z, w;
+
+ // inline bool operator==(const vec4& rhs) const {
+ // return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w;
+ // }
+};
+
+
+struct box {
+ vec2<double> tl, tr, bl, br;
+};
+
+}
+
+#endif
diff --git a/macosx/CMakeLists.txt b/macosx/CMakeLists.txt
new file mode 100644
index 0000000000..2a839c0c1d
--- /dev/null
+++ b/macosx/CMakeLists.txt
@@ -0,0 +1,37 @@
+FIND_LIBRARY(COCOA_LIBRARY Cocoa)
+FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
+FIND_LIBRARY(IOKIT_LIBRARY IOKit)
+FIND_LIBRARY(COREVIDEO_LIBRARY CoreVidoe)
+
+FIND_PACKAGE(PkgConfig REQUIRED)
+PKG_SEARCH_MODULE(GLFW REQUIRED glfw3)
+
+
+SET(macosx_SOURCES
+ main.mm
+)
+
+SET(macosx_HEADERS
+)
+
+INCLUDE_DIRECTORIES(
+ ../include
+ ${GLFW_INCLUDE_DIRS}
+)
+
+LINK_DIRECTORIES(
+ ${GLFW_LIBRARY_DIRS}
+)
+
+ADD_EXECUTABLE(macosx
+ ${macosx_SOURCES}
+)
+
+TARGET_LINK_LIBRARIES(macosx
+ llmr
+ ${COCOA_LIBRARY}
+ ${OPENGL_LIBRARY}
+ ${IOKIT_LIBRARY}
+ ${COREVIDOE_LIBRARY}
+ ${GLFW_LIBRARIES}
+)
diff --git a/macosx/main.mm b/macosx/main.mm
index 3119d2b869..20b6cc174a 100644
--- a/macosx/main.mm
+++ b/macosx/main.mm
@@ -11,8 +11,10 @@ public:
tracking(false),
rotating(false),
last_click(-1),
- platform(new llmr::platform(this)),
- map(new llmr::map(platform)) {
+ map(new llmr::map()) {
+ }
+
+ void init() {
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize glfw\n");
exit(1);
@@ -143,7 +145,6 @@ public:
~MapView() {
delete map;
- delete platform;
glfwTerminate();
}
@@ -158,19 +159,25 @@ public:
double last_click;
GLFWwindow *window;
- llmr::platform *platform;
llmr::map *map;
};
-void llmr::platform::restart() {
- ((MapView *)obj)->dirty = true;
+
+MapView *view;
+
+namespace llmr {
+namespace platform {
+
+void restart(void *) {
+ view->dirty = true;
}
-void llmr::platform::request(tile *tile) {
+void request(void *, tile *tile) {
fprintf(stderr, "request %d/%d/%d\n", tile->z, tile->x, tile->y);
fprintf(stderr, "requesting tile\n");
- NSString *urlTemplate = @"http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf";
+ // NSString *urlTemplate = @"http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf";
+ NSString *urlTemplate = @"http://localhost:3333/gl/tiles/%d-%d-%d.vector.pbf";
NSString *urlString = [NSString
stringWithFormat:urlTemplate,
tile->z,
@@ -192,20 +199,25 @@ void llmr::platform::request(tile *tile) {
tile->setData((uint8_t *)[data bytes], [data length]);
if (tile->parse()) {
dispatch_async(dispatch_get_main_queue(), ^ {
- ((MapView *)obj)->map->tileLoaded(tile);
+ view->map->tileLoaded(tile);
});
return;
}
}
dispatch_async(dispatch_get_main_queue(), ^ {
- ((MapView *)obj)->map->tileFailed(tile);
+ view->map->tileFailed(tile);
});
}];
}
+}
+}
int main() {
- MapView view;
- return view.run();
+ view = new MapView();
+ view->init();
+ int ret = view->run();
+ delete view;
+ return ret;
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000000..22f140bfac
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,43 @@
+SET(llmr_SOURCES
+ geometry/linevertexbuffer.cpp
+ map/map.cpp
+ map/tile.cpp
+ map/transform.cpp
+ renderer/painter.cpp
+ renderer/shader-fill.cpp
+ renderer/shader-line.cpp
+ renderer/shader.cpp
+ shader/shaders.c
+ util/mat4.c
+)
+
+SET(llmr_HEADERS
+ ../include/llmr/geometry/linevertexbuffer.hpp
+ ../include/llmr/llmr.hpp
+ ../include/llmr/map/map.hpp
+ ../include/llmr/map/tile.hpp
+ ../include/llmr/map/transform.hpp
+ ../include/llmr/platform/gl.hpp
+ ../include/llmr/platform/platform.hpp
+ ../include/llmr/renderer/painter.hpp
+ ../include/llmr/renderer/shader-fill.hpp
+ ../include/llmr/renderer/shader-line.hpp
+ ../include/llmr/renderer/shader.hpp
+ ../include/llmr/util/math.hpp
+ ../include/llmr/util/vec2.hpp
+)
+
+INCLUDE_DIRECTORIES(
+ ../include
+)
+
+ADD_LIBRARY(llmr STATIC
+ ${llmr_SOURCES}
+ ${llmr_HEADERS}
+)
+
+LINK_DIRECTORIES(
+)
+
+TARGET_LINK_LIBRARIES(llmr
+)
diff --git a/src/map/map.cpp b/src/map/map.cpp
index f010fa95af..1fcf5d6636 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -1,31 +1,20 @@
#include <llmr/map/map.hpp>
#include <llmr/map/tile.hpp>
+#include <llmr/util/vec2.hpp>
#include <iostream>
#include <thread>
-using namespace llmr;
-
-map::map(class platform *platform)
- : platform(platform),
- transform(new class transform()),
- painter(new class painter(platform, transform)) {
-
- transform->setLonLat(13, 50);
- transform->setZoom(3);
-
- tiles.push_back(new class tile(1, 0, 0));
- platform->request(tiles.back());
+#include <cmath>
- tiles.push_back(new class tile(1, 1, 0));
- platform->request(tiles.back());
-
- tiles.push_back(new class tile(1, 0, 1));
- platform->request(tiles.back());
+using namespace llmr;
- tiles.push_back(new class tile(1, 1, 1));
- platform->request(tiles.back());
+map::map()
+ : transform(new class transform()),
+ painter(new class painter(transform)) {
+ // transform->setLonLat(13, 50);
+ // transform->setZoom(3);
}
map::~map() {
@@ -39,24 +28,83 @@ void map::setup() {
void map::resize(uint32_t width, uint32_t height) {
transform->width = width;
transform->height = height;
- platform->restart();
+ updateTiles();
+ platform::restart(this);
}
void map::moveBy(double dx, double dy) {
transform->moveBy(dx, dy);
- platform->restart();
+ updateTiles();
+ platform::restart(this);
}
void map::scaleBy(double ds, double cx, double cy) {
transform->scaleBy(ds, cx, cy);
- platform->restart();
+ updateTiles();
+ platform::restart(this);
}
void map::rotateBy(double cx, double cy, double sx, double sy, double ex, double ey) {
transform->rotateBy(cx, cy, sx, sy, ex, ey);
- platform->restart();
+ updateTiles();
+ platform::restart(this);
}
+void map::updateTiles() {
+ // Figure out what tiles we need to load
+ int32_t zoom = transform->getZoom();
+ int32_t max_dim = pow(2, zoom);
+
+ // Map four viewport corners to pixel coordinates
+ box box;
+ transform->mapCornersToBox(zoom, box);
+
+ vec2<int32_t> tl, br;
+ tl.x = fmax(0, floor(fmin(box.tl.x, box.bl.x)));
+ tl.y = fmax(0, floor(fmin(box.tl.y, box.tr.y)));
+ br.x = fmin(max_dim, ceil(fmax(box.tr.x, box.br.x)));
+ br.y = fmin(max_dim, ceil(fmax(box.bl.y, box.br.y)));
+
+ // TODO: Discard tiles that are outside the viewport
+ std::vector<uint64_t> required;
+ for (int32_t y = tl.y; y < br.y; y++) {
+ for (int32_t x = tl.x; x < br.x; x++) {
+ required.push_back(tile::toID(zoom, x, y));
+ }
+ }
+
+ // Add existing child/parent tiles if the actual tile is not yet loaded
+ // TODO
+
+
+ // Remove tiles that we definitely don't need, i.e. tiles that are not on
+ // the required list.
+ for (std::vector<tile *>::iterator it = tiles.begin(); it != tiles.end(); it++) {
+ tile *tile = *it;
+ uint64_t id = tile::toID(tile->z, tile->x, tile->y);
+ std::vector<uint64_t>::const_iterator required_it = std::find(required.begin(), required.end(), id);
+ bool retain = required_it != required.end();
+ if (retain) {
+ // We already have the tile; remove it from the list of required tiles.
+ required.erase(required_it);
+ } else {
+ // We don't need this tile, so we can remove it entirely.
+ std::vector<class tile *>::iterator to_remove = it - 1;
+ tile->cancel();
+ tiles.erase(it);
+ it = to_remove;
+ }
+ }
+
+ // Required now only contains those tiles that are not yet in the list of
+ // tiles, so we should add them all.
+ for (int64_t id : required) {
+ vec4<int32_t> tile_coord = tile::fromID(id);
+ tile *tile = new class tile(tile_coord.z, tile_coord.x, tile_coord.y);
+ tiles.push_back(tile);
+ platform::request(this, tile);
+ }
+}
bool map::render() {
painter->clear();
@@ -72,11 +120,7 @@ bool map::render() {
}
void map::tileLoaded(tile *tile) {
- platform->restart();
- // fprintf(stderr, "[%8zx] tile loaded %d/%d/%d\n",
- // std::hash<std::thread::id>()(std::this_thread::get_id()),
- // tile->z, tile->x, tile->y);
- // schedule rerender
+ platform::restart(this);
}
void map::tileFailed(tile *tile) {
diff --git a/src/map/pbf.hpp b/src/map/pbf.hpp
index 29c252e115..b9ed95a1a0 100644
--- a/src/map/pbf.hpp
+++ b/src/map/pbf.hpp
@@ -22,11 +22,11 @@ struct pbf {
inline bool next();
template <typename T = uint32_t> inline T varint();
- inline int64_t svarint();
+ template <typename T = uint32_t> inline T svarint();
inline std::string string();
inline float float32();
inline double float64();
- inline int64_t int64();
+ // inline int64_t int64();
inline bool boolean();
template <typename T, typename... Args>
@@ -91,10 +91,11 @@ T pbf::varint()
return result;
}
-int64_t pbf::svarint()
+template <typename T>
+T pbf::svarint()
{
- uint64_t n = varint();
- return (n >> 1) ^ -(int64_t)(n & 1);
+ T n = varint<T>();
+ return (n >> 1) ^ -(T)(n & 1);
}
std::string pbf::string()
@@ -112,6 +113,7 @@ float pbf::float32()
memcpy(&result, data - 4, 4);
return result;
}
+
double pbf::float64()
{
skipBytes(8);
@@ -120,10 +122,10 @@ double pbf::float64()
return result;
}
-int64_t pbf::int64()
-{
- return (int64_t)varint();
-}
+// int64_t pbf::int64()
+// {
+// return (int64_t)varint();
+// }
bool pbf::boolean()
{
diff --git a/src/map/tile.cpp b/src/map/tile.cpp
index 6216c55caa..c04392af3a 100644
--- a/src/map/tile.cpp
+++ b/src/map/tile.cpp
@@ -1,18 +1,43 @@
#include <llmr/map/tile.hpp>
#include <stdint.h>
+#include <cassert>
// #include <iostream>
#include <thread>
#include "pbf.hpp"
+#include <llmr/util/vec2.hpp>
+#include <cmath>
using namespace llmr;
+
+uint64_t tile::toID(int32_t z, int32_t x, int32_t y, int32_t w) {
+ w *= 2;
+ if (w < 0) w = w * -1 -1;
+ int32_t dim = 1 << z;
+ return ((dim * dim * w + dim * y + x) * 32) + z;
+}
+
+vec4<int32_t> tile::fromID(uint64_t id) {
+ vec4<int32_t> coord;
+ coord.z = id % 32;
+ int32_t dim = 1 << coord.z;
+ int32_t xy = ((id - coord.z) / 32);
+ coord.x = xy % dim;
+ coord.y = ((xy - coord.x) / dim) % dim;
+ coord.w = floor(xy / (dim * dim));
+ if (coord.w % 2 != 0) coord.w = coord.w * -1 -1;
+ coord.w /= 2;
+ return coord;
+};
+
tile::tile(int32_t z, int32_t x, int32_t y)
: z(z),
x(x),
y(y),
loaded(false),
+ cancelled(false),
data(0),
bytes(0) {
}
@@ -23,8 +48,26 @@ void tile::setData(uint8_t *data, uint32_t bytes) {
memcpy(this->data, data, bytes);
}
+void tile::cancel()
+{
+ // TODO: thread safety
+ if (!cancelled) {
+ cancelled = true;
+ if (loaded) {
+ delete this;
+ }
+ } else {
+ assert((!"logic error? multiple cancelleations"));
+ }
+}
+
bool tile::parse()
{
+ if (cancelled) {
+ delete this;
+ return false;
+ }
+
fprintf(stderr, "[%p] parsing tile...\n", this);
pbf tile(data, bytes);
@@ -40,6 +83,11 @@ bool tile::parse()
fprintf(stderr, "[%p] parsing tile...done\n", this);
+ if (cancelled) {
+ delete this;
+ return false;
+ }
+
loaded = true;
return true;
}
@@ -84,7 +132,7 @@ void tile::parseFeature(const uint8_t *data, uint32_t bytes) {
}
void tile::loadGeometry(const uint8_t *data, uint32_t bytes) {
- pbf geometry(data, bytes);
+ pbf geometry(data, bytes);
uint32_t cmd = 1;
uint32_t length = 0;
diff --git a/src/map/transform.cpp b/src/map/transform.cpp
index e458d663b4..e31fad4233 100644
--- a/src/map/transform.cpp
+++ b/src/map/transform.cpp
@@ -1,6 +1,7 @@
#include <llmr/map/transform.hpp>
#include <llmr/util/mat4.h>
+#include <llmr/util/vec2.hpp>
#include <llmr/util/math.hpp>
#include <cmath>
#include <cstdio>
@@ -22,7 +23,9 @@ transform::transform()
x(0),
y(0),
angle(0.0),
- scale(1.0) {
+ scale(1.0),
+ min_scale(pow(2, 0)),
+ max_scale(pow(2, 20)) {
setScale(scale);
setAngle(angle);
}
@@ -33,6 +36,14 @@ void transform::moveBy(double dx, double dy) {
}
void transform::scaleBy(double ds, double cx, double cy) {
+ // clamp scale to min/max values
+ const double new_scale = scale * ds;
+ if (new_scale < min_scale) {
+ ds = min_scale / scale;
+ } else if (new_scale > max_scale) {
+ ds = max_scale / scale;
+ }
+
const double dx = (cx - width / 2) * (1.0 - ds);
const double dy = (cy - height / 2) * (1.0 - ds);
const double fx = cos(angle) * dx + sin(angle) * dy;
@@ -41,6 +52,8 @@ void transform::scaleBy(double ds, double cx, double cy) {
scale *= ds;
x = (x * ds) + fx;
y = (y * ds) + fy;
+
+ fprintf(stderr, "scale: %f, %f, %f\n", scale, x, y);
}
@@ -78,6 +91,12 @@ void transform::setAngle(double new_angle) {
}
void transform::setScale(double new_scale) {
+ if (new_scale < min_scale) {
+ new_scale = min_scale;
+ } else if (new_scale > max_scale) {
+ new_scale = max_scale;
+ }
+
const double factor = new_scale / scale;
x *= factor;
y *= factor;
@@ -99,7 +118,7 @@ void transform::setLonLat(double lon, double lat) {
y = round(0.5 * Cc * log((1 + f) / (1 - f)));
}
-void transform::getLonLat(double& lon, double& lat) const {
+void transform::getLonLat(double &lon, double &lat) const {
lon = -x / Bc;
lat = R2D * (2 * atan(exp(y / Cc)) - 0.5 * M_PI);
}
@@ -132,7 +151,40 @@ void transform::matrixFor(float matrix[16], uint32_t tile_z, uint32_t tile_x, ui
// Clipping plane
mat4_translate(matrix, matrix, 0, 0, -1);
+}
+int32_t transform::getZoom() const {
+ return floor(log(scale) / M_LN2);
+}
+void transform::mapCornersToBox(uint32_t z, box& b) const {
+ const double ref_scale = pow(2, z);
+
+ // Keep the map as upright as possible.
+ double local_angle = angle;
+ if (local_angle >= M_PI_2) local_angle -= M_PI;
+ if (local_angle < -M_PI_2) local_angle += M_PI;
+
+ const double angle_sin = sin(-local_angle);
+ const double angle_cos = cos(-local_angle);
+
+ const double w_2 = width / 2;
+ const double h_2 = height / 2;
+ const double ss_1 = ref_scale / (scale * size);
+ const double ss_2 = (scale * size) / 2;
+
+ // Calculate the corners of the map view. The resulting coordinates will be
+ // in fractional tile coordinates.
+ b.tl.x = ((-w_2) * angle_cos - (-h_2) * angle_sin + ss_2 - x) * ss_1;
+ b.tl.y = ((-w_2) * angle_sin + (-h_2) * angle_cos + ss_2 - y) * ss_1;
+ b.tr.x = ((+w_2) * angle_cos - (-h_2) * angle_sin + ss_2 - x) * ss_1;
+ b.tr.y = ((+w_2) * angle_sin + (-h_2) * angle_cos + ss_2 - y) * ss_1;
+ b.bl.x = ((-w_2) * angle_cos - (+h_2) * angle_sin + ss_2 - x) * ss_1;
+ b.bl.y = ((-w_2) * angle_sin + (+h_2) * angle_cos + ss_2 - y) * ss_1;
+ b.br.x = ((+w_2) * angle_cos - (+h_2) * angle_sin + ss_2 - x) * ss_1;
+ b.br.y = ((+w_2) * angle_sin + (+h_2) * angle_cos + ss_2 - y) * ss_1;
+
+ // Quick hack: use the entire non-rotated bounding box.
}
+
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index 696e6a8625..656d1fd645 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -25,9 +25,8 @@ GLfloat fill_vertices[] = {
};
-painter::painter(class platform *platform, class transform *transform)
- : platform(platform),
- transform(transform),
+painter::painter(class transform *transform)
+ : transform(transform),
currentShader(NULL),
fillShader(NULL) {