diff options
Diffstat (limited to 'src')
42 files changed, 1025 insertions, 89 deletions
diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp index d43ec82d38..48c446dae4 100644 --- a/src/mbgl/annotation/annotation_tile.hpp +++ b/src/mbgl/annotation/annotation_tile.hpp @@ -33,6 +33,7 @@ public: optional<Value> getValue(const std::string&) const override; optional<FeatureIdentifier> getID() const override { return { id }; } GeometryCollection getGeometries() const override { return geometries; } + DEMPyramid getDEMPyramid() const override { return {}; } const AnnotationID id; const FeatureType type; diff --git a/src/mbgl/geometry/dem_pyramid.cpp b/src/mbgl/geometry/dem_pyramid.cpp new file mode 100644 index 0000000000..fb3a9d108e --- /dev/null +++ b/src/mbgl/geometry/dem_pyramid.cpp @@ -0,0 +1,48 @@ +#include <mbgl/geometry/dem_pyramid.hpp> + +namespace mbgl { + +void DEMPyramid::buildLevels() { + while (true) { + auto& prev = levels.back(); + const int32_t width = std::ceil(prev.width / 2); + const int32_t height = std::ceil(prev.height / 2); + const int32_t border = std::max<int32_t>(std::ceil(prev.border / 2), 1); + + if (width == 1 || height == 1) { + break; + } + Level next(width, height, border); + prev.resample(next); + levels.emplace_back(std::move(next)); + } + + // Build remaining two levels. They aren't actually used in rendering, but we + // need them for OpenGL's mipmapping feature. + levels.emplace_back(2, 2, 0); + levels.emplace_back(1, 1, 0); +} + +DEMPyramid::Level::Level(int32_t width_, int32_t height_, size_t border_) + : width(width_), + height(height_), + border(border_), + stride(width + 2 * border), + image({ static_cast<uint32_t>(width + 2 * border), + static_cast<uint32_t>(height + 2 * border) }) { + assert(width > 0); + assert(height > 0); + std::memset(image.data.get(), 0, image.bytes()); +} + +void DEMPyramid::Level::resample(Level& target) { + for (int32_t y = 0; y < target.height; y++) { + const int32_t fy = y * 2; + for (int32_t x = 0; x < target.width; x++) { + const int32_t fx = x * 2; + target.set(x, y, (get(fx, fy) + get(fx + 1, fy) + get(fx, fy + 1) + get(fx + 1, fy + 1)) / 4); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/geometry/dem_pyramid.hpp b/src/mbgl/geometry/dem_pyramid.hpp new file mode 100644 index 0000000000..d115f191c0 --- /dev/null +++ b/src/mbgl/geometry/dem_pyramid.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include <mbgl/math/clamp.hpp> +#include <mbgl/util/image.hpp> + +#include <memory> +#include <array> +#include <cassert> +#include <vector> + +namespace mbgl { + +class DEMPyramid { +public: + class Level { + public: + Level(int32_t width, int32_t height, size_t border); + + void set(const int32_t x, const int32_t y, const int32_t value) { + reinterpret_cast<int32_t*>(image.data.get())[idx(x, y)] = value + 65536; + } + + int32_t get(const int32_t x, const int32_t y) const { + return reinterpret_cast<const int32_t*>(image.data.get())[idx(x, y)] - 65536; + } + + void resample(Level& target); + + private: + size_t idx(const int32_t x, const int32_t y) const { + assert(x >= -border); + assert(x < width + border); + assert(y >= -border); + assert(y < height + border); + return (y + border) * stride + (x + border); + } + + public: + const int32_t width; + const int32_t height; + const int32_t border; + const int32_t stride; + PremultipliedImage image; + }; + + + void buildLevels(); + + std::vector<Level> levels; + + +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index ea60f79801..d6065f0674 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -39,6 +39,7 @@ class LineBucket; class CircleBucket; class SymbolBucket; class RasterBucket; +class TerrainBucket; class Shaders; class SymbolSDFShader; @@ -54,6 +55,7 @@ class LineLayer; class CircleLayer; class SymbolLayer; class RasterLayer; +class TerrainLayer; class BackgroundLayer; } // namespace style @@ -84,6 +86,7 @@ public: void renderCircle(PaintParameters&, CircleBucket&, const style::CircleLayer&, const RenderTile&); void renderSymbol(PaintParameters&, SymbolBucket&, const style::SymbolLayer&, const RenderTile&); void renderRaster(PaintParameters&, RasterBucket&, const style::RasterLayer&, const RenderTile&); + void renderTerrain(PaintParameters&, TerrainBucket&, const style::TerrainLayer&, const RenderTile&); void renderBackground(PaintParameters&, const style::BackgroundLayer&); #ifndef NDEBUG diff --git a/src/mbgl/renderer/painter_terrain.cpp b/src/mbgl/renderer/painter_terrain.cpp new file mode 100644 index 0000000000..c59182c2ee --- /dev/null +++ b/src/mbgl/renderer/painter_terrain.cpp @@ -0,0 +1,84 @@ +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/renderer/terrain_bucket.hpp> +#include <mbgl/style/layers/terrain_layer.hpp> +#include <mbgl/style/layers/terrain_layer_impl.hpp> +#include <mbgl/shader/shaders.hpp> +#include <mbgl/util/offscreen_texture.hpp> + +namespace mbgl { + +using namespace style; + +void Painter::renderTerrain(PaintParameters& parameters, + TerrainBucket& bucket, + const TerrainLayer& layer, + const RenderTile& tile) { + if (pass != RenderPass::Translucent) return; + + if (!bucket.prepared) { + OffscreenTexture view(context, { 256, 256 }); + view.bind(); + + context.bindTexture(*bucket.dem, 0, gl::TextureFilter::Linear, gl::TextureMipMap::Yes); + + mat4 mat; + matrix::ortho(mat, 0, util::EXTENT, -util::EXTENT, 0, 0, 1); + matrix::translate(mat, mat, 0, -util::EXTENT, 0); + + context.clear(Color::red(), {}, {}); + context.draw({ + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + gl::ColorMode::unblended(), + parameters.shaders.terrainPrepare, + TerrainPrepareUniforms::Values { + mat, + 0, + { {{ 512, 512 }} }, + tile.id.canonical.z + }, + gl::Unindexed<gl::TriangleStrip>(rasterVertexBuffer) + }); + + bucket.texture = std::move(view.getTexture()); + bucket.prepared = true; + + parameters.view.bind(); + } + + const TerrainPaintProperties& properties = layer.impl->paint; + + double azimuth = (-properties.terrainIlluminationDirection - 90) * util::DEG2RAD; + if (properties.terrainIlluminationAlignment == style::AlignmentType::Viewport) { + azimuth -= state.getAngle(); + } + + context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); + + context.draw({ + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + parameters.shaders.terrain, + TerrainUniforms::Values { + tile.matrix, + 0, // image + 8, // mode + { {{ 256, 256 }} }, + tile.id.canonical.z, + azimuth, + 60 * util::DEG2RAD, // zenith + 0, // mipmap + properties.terrainExaggeration.value, + properties.terrainShadowColor.value, + properties.terrainHighlightColor.value, + properties.terrainAccentColor.value + }, + gl::Unindexed<gl::TriangleStrip>(rasterVertexBuffer) + }); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/terrain_bucket.cpp b/src/mbgl/renderer/terrain_bucket.cpp new file mode 100644 index 0000000000..5dc3ddf364 --- /dev/null +++ b/src/mbgl/renderer/terrain_bucket.cpp @@ -0,0 +1,44 @@ +#include <mbgl/renderer/terrain_bucket.hpp> +#include <mbgl/style/layers/terrain_layer.hpp> +#include <mbgl/shader/terrain_shader.hpp> +#include <mbgl/shader/terrain_prepare_shader.hpp> +#include <mbgl/renderer/painter.hpp> +#include <mbgl/gl/gl.hpp> +#include <mbgl/gl/context.hpp> + +namespace mbgl { + +using namespace style; + +TerrainBucket::TerrainBucket(PremultipliedImage&&) { + // TODO +} + +TerrainBucket::TerrainBucket(DEMPyramid&& pyramid_) : pyramid(std::move(pyramid_)) { +} + +void TerrainBucket::upload(gl::Context& context) { + if (!pyramid.levels.empty()) { + dem = context.createTexture(pyramid.levels.front().image); + for (size_t l = 1; l < pyramid.levels.size(); l++) { + auto& image = pyramid.levels[l].image; + MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, l, GL_RGBA, image.size.width, image.size.height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image.data.get())); + } + } + + uploaded = true; +} + +void TerrainBucket::render(Painter& painter, + PaintParameters& parameters, + const Layer& layer, + const RenderTile& tile) { + painter.renderTerrain(parameters, *this, *layer.as<TerrainLayer>(), tile); +} + +bool TerrainBucket::hasData() const { + return true; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/terrain_bucket.hpp b/src/mbgl/renderer/terrain_bucket.hpp new file mode 100644 index 0000000000..3a96372ff7 --- /dev/null +++ b/src/mbgl/renderer/terrain_bucket.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/renderer/bucket.hpp> +#include <mbgl/util/image.hpp> +#include <mbgl/util/optional.hpp> +#include <mbgl/gl/texture.hpp> +#include <mbgl/geometry/dem_pyramid.hpp> + +namespace mbgl { + +class TerrainPrepareShader; +class TerrainShader; +class RasterShader; +class RasterVertex; + +namespace gl { +class Context; +template <class> class VertexBuffer; +class VertexArrayObject; +} // namespace gl + +class TerrainBucket : public Bucket { +public: + TerrainBucket(PremultipliedImage&&); + TerrainBucket(DEMPyramid&&); + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const style::Layer&, const RenderTile&) override; + bool hasData() const override; + + optional<gl::Texture> dem; + optional<gl::Texture> texture; + bool prepared = false; + +private: + DEMPyramid pyramid; +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/mesh.cpp b/src/mbgl/shader/mesh.cpp new file mode 100644 index 0000000000..6d1578a35c --- /dev/null +++ b/src/mbgl/shader/mesh.cpp @@ -0,0 +1,18 @@ +#include <mbgl/gl/mesh.hpp> + +namespace mbgl { +namespace gl { + +Mesh::Mesh(Size size) { + + +} + +void Mesh::upload(gl::Context&) { + + + +} + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/shader/mesh.hpp b/src/mbgl/shader/mesh.hpp new file mode 100644 index 0000000000..3df0c74632 --- /dev/null +++ b/src/mbgl/shader/mesh.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <mbgl/util/size.hpp> +#include <mbgl/gl/vertex_buffer.hpp> +#include <mbgl/gl/index_buffer.hpp> +#include <mbgl/gl/segment.hpp> +#include <mbgl/shader/fill_vertex.hpp> + +namespace mbgl { +namespace gl { + +namespace gl { +class Context; +} // namespace gl + +class Mesh { +public: + Mesh(Size size); + + void upload(gl::Context&); + + std::vector<FillVertex> vertices; + std::vector<gl::Triangle> triangles; + std::vector<gl::Segment> triangleSegments { { 0, 0 } }; + + optional<gl::VertexBuffer<FillVertex>> vertexBuffer; + optional<gl::IndexBuffer<gl::Triangle>> triangleIndexBuffer; +}; + +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/shader/shaders.hpp b/src/mbgl/shader/shaders.hpp index 56b063ce29..6d5a37ae88 100644 --- a/src/mbgl/shader/shaders.hpp +++ b/src/mbgl/shader/shaders.hpp @@ -9,6 +9,8 @@ #include <mbgl/shader/line_sdf_shader.hpp> #include <mbgl/shader/line_pattern_shader.hpp> #include <mbgl/shader/raster_shader.hpp> +#include <mbgl/shader/terrain_prepare_shader.hpp> +#include <mbgl/shader/terrain_shader.hpp> #include <mbgl/shader/symbol_icon_shader.hpp> #include <mbgl/shader/symbol_sdf_shader.hpp> @@ -28,6 +30,8 @@ public: lineSDF(context, defines), linePattern(context, defines), raster(context, defines), + terrainPrepare(context, defines), + terrain(context, defines), symbolIcon(context, defines), symbolIconSDF(context, defines), symbolGlyph(context, defines), @@ -43,6 +47,8 @@ public: LineSDFShader lineSDF; LinePatternShader linePattern; RasterShader raster; + TerrainPrepareShader terrainPrepare; + TerrainShader terrain; SymbolIconShader symbolIcon; SymbolSDFShader symbolIconSDF; SymbolSDFShader symbolGlyph; diff --git a/src/mbgl/shader/terrain_prepare_shader.cpp b/src/mbgl/shader/terrain_prepare_shader.cpp new file mode 100644 index 0000000000..6bfa1f55f7 --- /dev/null +++ b/src/mbgl/shader/terrain_prepare_shader.cpp @@ -0,0 +1,15 @@ +#include <mbgl/shader/terrain_prepare_shader.hpp> +#include <mbgl/shader/terrain_prepare.vertex.hpp> +#include <mbgl/shader/terrain_prepare.fragment.hpp> + +namespace mbgl { + +TerrainPrepareShader::TerrainPrepareShader(gl::Context& context, Defines defines) + : Shader(shaders::terrain_prepare::name, + shaders::terrain_prepare::vertex, + shaders::terrain_prepare::fragment, + context, defines), + uniformsState(TerrainPrepareUniforms::state(*this)) { +} + +} // namespace mbgl diff --git a/src/mbgl/shader/terrain_prepare_shader.hpp b/src/mbgl/shader/terrain_prepare_shader.hpp new file mode 100644 index 0000000000..dfb5707d6c --- /dev/null +++ b/src/mbgl/shader/terrain_prepare_shader.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/gl/shader.hpp> +#include <mbgl/gl/attribute.hpp> +#include <mbgl/shader/terrain_uniforms.hpp> + +namespace mbgl { + +class RasterVertex; + +class TerrainPrepareShader : public gl::Shader { +public: + TerrainPrepareShader(gl::Context&, Defines defines = None); + + using VertexType = RasterVertex; + using UniformsType = TerrainPrepareUniforms; + + gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; + gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this }; + + typename TerrainPrepareUniforms::State uniformsState; +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/terrain_shader.cpp b/src/mbgl/shader/terrain_shader.cpp new file mode 100644 index 0000000000..e8eedb9515 --- /dev/null +++ b/src/mbgl/shader/terrain_shader.cpp @@ -0,0 +1,16 @@ +#include <mbgl/shader/terrain_shader.hpp> +#include <mbgl/shader/terrain.vertex.hpp> +#include <mbgl/shader/terrain.fragment.hpp> +#include <mbgl/shader/raster_vertex.hpp> + +namespace mbgl { + +TerrainShader::TerrainShader(gl::Context& context, Defines defines) + : Shader(shaders::terrain::name, + shaders::terrain::vertex, + shaders::terrain::fragment, + context, defines), + uniformsState(TerrainUniforms::state(*this)) { +} + +} // namespace mbgl diff --git a/src/mbgl/shader/terrain_shader.hpp b/src/mbgl/shader/terrain_shader.hpp new file mode 100644 index 0000000000..32bdcd16d3 --- /dev/null +++ b/src/mbgl/shader/terrain_shader.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/gl/shader.hpp> +#include <mbgl/gl/attribute.hpp> +#include <mbgl/shader/terrain_uniforms.hpp> + +namespace mbgl { + +class RasterVertex; + +class TerrainShader : public gl::Shader { +public: + TerrainShader(gl::Context&, Defines defines = None); + + using VertexType = RasterVertex; + using UniformsType = TerrainUniforms; + + gl::Attribute<int16_t, 2> a_pos = { "a_pos", *this }; + gl::Attribute<uint16_t, 2> a_texture_pos = { "a_texture_pos", *this }; + + typename TerrainUniforms::State uniformsState; +}; + +} // namespace mbgl diff --git a/src/mbgl/shader/terrain_uniforms.hpp b/src/mbgl/shader/terrain_uniforms.hpp new file mode 100644 index 0000000000..831d419c37 --- /dev/null +++ b/src/mbgl/shader/terrain_uniforms.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/shader/uniforms.hpp> + +namespace mbgl { + +namespace uniforms { +MBGL_DEFINE_UNIFORM_VECTOR(float, 2, u_dimension); +MBGL_DEFINE_UNIFORM_SCALAR(int32_t, u_mode); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_azimuth); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_zenith); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_mipmap); +MBGL_DEFINE_UNIFORM_SCALAR(float, u_exaggeration); +MBGL_DEFINE_UNIFORM_SCALAR(Color, u_shadow); +MBGL_DEFINE_UNIFORM_SCALAR(Color, u_highlight); +MBGL_DEFINE_UNIFORM_SCALAR(Color, u_accent); +} // namespace uniforms + +struct TerrainPrepareUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_image, + uniforms::u_dimension, + uniforms::u_zoom> {}; + +struct TerrainUniforms : gl::Uniforms< + uniforms::u_matrix, + uniforms::u_image, + uniforms::u_mode, + uniforms::u_dimension, + uniforms::u_zoom, + uniforms::u_azimuth, + uniforms::u_zenith, + uniforms::u_mipmap, + uniforms::u_exaggeration, + uniforms::u_shadow, + uniforms::u_highlight, + uniforms::u_accent> {}; + +} // namespace mbgl diff --git a/src/mbgl/style/bucket_parameters.hpp b/src/mbgl/style/bucket_parameters.hpp index 9aad35dcad..f608e000d2 100644 --- a/src/mbgl/style/bucket_parameters.hpp +++ b/src/mbgl/style/bucket_parameters.hpp @@ -1,54 +1,16 @@ #pragma once -#include <mbgl/map/mode.hpp> -#include <mbgl/tile/tile_id.hpp> -#include <mbgl/style/filter.hpp> - -#include <atomic> -#include <functional> +#include <mbgl/util/variant.hpp> +#include <mapbox/recursive_wrapper.hpp> namespace mbgl { - -class TileID; -class GeometryTileLayer; -class GeometryTileFeature; -class GlyphAtlas; -class CollisionTile; -class FeatureIndex; - namespace style { -class BucketParameters { -public: - BucketParameters(const OverscaledTileID& tileID_, - const GeometryTileLayer& layer_, - const std::atomic<bool>& obsolete_, - uintptr_t tileUID_, - GlyphAtlas& glyphAtlas_, - FeatureIndex& featureIndex_, - const MapMode mode_) - : tileID(tileID_), - layer(layer_), - obsolete(obsolete_), - tileUID(tileUID_), - glyphAtlas(glyphAtlas_), - featureIndex(featureIndex_), - mode(mode_) {} - - bool cancelled() const { - return obsolete; - } - - void eachFilteredFeature(const Filter&, std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)>); +class GeometryBucketParameters; +class RasterBucketParameters; - const OverscaledTileID& tileID; - const GeometryTileLayer& layer; - const std::atomic<bool>& obsolete; - uintptr_t tileUID; - GlyphAtlas& glyphAtlas; - FeatureIndex& featureIndex; - const MapMode mode; -}; +using BucketParameters = variant<mapbox::util::recursive_wrapper<GeometryBucketParameters>, + mapbox::util::recursive_wrapper<RasterBucketParameters>>; } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/bucket_parameters.cpp b/src/mbgl/style/geometry_bucket_parameters.cpp index 64f53babcd..acbd20b073 100644 --- a/src/mbgl/style/bucket_parameters.cpp +++ b/src/mbgl/style/geometry_bucket_parameters.cpp @@ -1,11 +1,11 @@ -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/style/filter_evaluator.hpp> #include <mbgl/tile/geometry_tile_data.hpp> namespace mbgl { namespace style { -void BucketParameters::eachFilteredFeature(const Filter& filter, +void GeometryBucketParameters::eachFilteredFeature(const Filter& filter, std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)> function) { auto name = layer.getName(); for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) { diff --git a/src/mbgl/style/geometry_bucket_parameters.hpp b/src/mbgl/style/geometry_bucket_parameters.hpp new file mode 100644 index 0000000000..dce205324d --- /dev/null +++ b/src/mbgl/style/geometry_bucket_parameters.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include <mbgl/map/mode.hpp> +#include <mbgl/tile/tile_id.hpp> +#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/filter.hpp> + +#include <atomic> +#include <functional> + +namespace mbgl { + +class TileID; +class GeometryTileLayer; +class GeometryTileFeature; +class GlyphAtlas; +class CollisionTile; +class FeatureIndex; + +namespace style { + +class GeometryBucketParameters { +public: + GeometryBucketParameters(const OverscaledTileID& tileID_, + const GeometryTileLayer& layer_, + const std::atomic<bool>& obsolete_, + uintptr_t tileUID_, + GlyphAtlas& glyphAtlas_, + FeatureIndex& featureIndex_, + const MapMode mode_) + : tileID(tileID_), + layer(layer_), + obsolete(obsolete_), + tileUID(tileUID_), + glyphAtlas(glyphAtlas_), + featureIndex(featureIndex_), + mode(mode_) {} + + bool cancelled() const { + return obsolete; + } + + void eachFilteredFeature(const Filter&, std::function<void (const GeometryTileFeature&, std::size_t index, const std::string& layerName)>); + + const OverscaledTileID& tileID; + const GeometryTileLayer& layer; + const std::atomic<bool>& obsolete; + uintptr_t tileUID; + GlyphAtlas& glyphAtlas; + FeatureIndex& featureIndex; + const MapMode mode; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index 4bf2956a6d..52ce1e6176 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -3,6 +3,7 @@ #include <mbgl/style/layer.hpp> #include <mbgl/style/types.hpp> #include <mbgl/style/filter.hpp> +#include <mbgl/style/bucket_parameters.hpp> #include <mbgl/style/layer_observer.hpp> #include <mbgl/renderer/render_pass.hpp> #include <mbgl/util/noncopyable.hpp> @@ -20,7 +21,6 @@ namespace style { class CascadeParameters; class CalculationParameters; -class BucketParameters; /** * `Layer::Impl` contains the internal implementation of `Layer`: the details that need to be accessible to other parts diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp index 33699b6665..fd121115a9 100644 --- a/src/mbgl/style/layers/circle_layer_impl.cpp +++ b/src/mbgl/style/layers/circle_layer_impl.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/layers/circle_layer_impl.hpp> -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/renderer/circle_bucket.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/util/math.hpp> @@ -21,7 +21,9 @@ bool CircleLayer::Impl::recalculate(const CalculationParameters& parameters) { return hasTransitions; } -std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& parameters) const { +std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(BucketParameters& params) const { + auto& parameters = params.get<GeometryBucketParameters>(); + auto bucket = std::make_unique<CircleBucket>(parameters.mode); auto& name = bucketName(); diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp index fc439f1cd1..0e4873b3dc 100644 --- a/src/mbgl/style/layers/fill_layer_impl.cpp +++ b/src/mbgl/style/layers/fill_layer_impl.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/layers/fill_layer_impl.hpp> -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/renderer/fill_bucket.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/util/math.hpp> @@ -30,7 +30,8 @@ bool FillLayer::Impl::recalculate(const CalculationParameters& parameters) { return hasTransitions; } -std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& parameters) const { +std::unique_ptr<Bucket> FillLayer::Impl::createBucket(BucketParameters& params) const { + auto& parameters = params.get<GeometryBucketParameters>(); auto bucket = std::make_unique<FillBucket>(); auto& name = bucketName(); diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp index c116af5fc2..4fc0ddef07 100644 --- a/src/mbgl/style/layers/line_layer_impl.cpp +++ b/src/mbgl/style/layers/line_layer_impl.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/layers/line_layer_impl.hpp> -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/renderer/line_bucket.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/util/math.hpp> @@ -27,7 +27,8 @@ bool LineLayer::Impl::recalculate(const CalculationParameters& parameters) { return hasTransitions; } -std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& parameters) const { +std::unique_ptr<Bucket> LineLayer::Impl::createBucket(BucketParameters& params) const { + auto& parameters = params.get<GeometryBucketParameters>(); auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor()); bucket->layout = layout; diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp index 879bfa4559..41370905e7 100644 --- a/src/mbgl/style/layers/raster_layer_impl.cpp +++ b/src/mbgl/style/layers/raster_layer_impl.cpp @@ -1,5 +1,7 @@ #include <mbgl/style/layers/raster_layer_impl.hpp> -#include <mbgl/renderer/bucket.hpp> +#include <mbgl/style/raster_bucket_parameters.hpp> +#include <mbgl/renderer/raster_bucket.hpp> +#include <mbgl/util/image.hpp> namespace mbgl { namespace style { @@ -16,8 +18,9 @@ bool RasterLayer::Impl::recalculate(const CalculationParameters& parameters) { return hasTransitions; } -std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(BucketParameters&) const { - return nullptr; +std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(BucketParameters& params) const { + auto& parameters = params.get<RasterBucketParameters>(); + return std::make_unique<RasterBucket>(decodeImage(*parameters.data)); } } // namespace style diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index 0ac9ff832d..661a635809 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -1,5 +1,5 @@ #include <mbgl/style/layers/symbol_layer_impl.hpp> -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/layout/symbol_layout.hpp> #include <mbgl/renderer/bucket.hpp> @@ -31,7 +31,8 @@ std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters&) const return nullptr; } -std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& parameters) const { +std::unique_ptr<SymbolLayout> SymbolLayer::Impl::createLayout(BucketParameters& params) const { + auto& parameters = params.get<GeometryBucketParameters>(); SymbolLayoutProperties layoutProperties = layout; CalculationParameters p(parameters.tileID.overscaledZ); diff --git a/src/mbgl/style/layers/terrain_layer.cpp b/src/mbgl/style/layers/terrain_layer.cpp new file mode 100644 index 0000000000..3d2a077477 --- /dev/null +++ b/src/mbgl/style/layers/terrain_layer.cpp @@ -0,0 +1,156 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/style/layers/terrain_layer.hpp> +#include <mbgl/style/layers/terrain_layer_impl.hpp> + +namespace mbgl { +namespace style { + +TerrainLayer::TerrainLayer(const std::string& layerID, const std::string& sourceID) + : Layer(Type::Terrain, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; + impl->source = sourceID; +} + +TerrainLayer::TerrainLayer(const Impl& other) + : Layer(Type::Terrain, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +TerrainLayer::~TerrainLayer() = default; + +std::unique_ptr<Layer> TerrainLayer::Impl::clone() const { + return std::make_unique<TerrainLayer>(*this); +} + +std::unique_ptr<Layer> TerrainLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique<TerrainLayer>(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = TerrainPaintProperties(); + return std::move(result); +} + +// Source + +const std::string& TerrainLayer::getSourceID() const { + return impl->source; +} + +void TerrainLayer::setSourceLayer(const std::string& sourceLayer) { + impl->sourceLayer = sourceLayer; +} + +const std::string& TerrainLayer::getSourceLayer() const { + return impl->sourceLayer; +} + +// Filter + +void TerrainLayer::setFilter(const Filter& filter) { + impl->filter = filter; + impl->observer->onLayerFilterChanged(*this); +} + +const Filter& TerrainLayer::getFilter() const { + return impl->filter; +} + +// Layout properties + + +// Paint properties + +PropertyValue<Color> TerrainLayer::getDefaultTerrainShadowColor() { + return { { 0, 0, 1, 1 } }; +} + +PropertyValue<Color> TerrainLayer::getTerrainShadowColor(const optional<std::string>& klass) const { + return impl->paint.terrainShadowColor.get(klass); +} + +void TerrainLayer::setTerrainShadowColor(PropertyValue<Color> value, const optional<std::string>& klass) { + if (value == getTerrainShadowColor(klass)) + return; + impl->paint.terrainShadowColor.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +PropertyValue<Color> TerrainLayer::getDefaultTerrainHighlightColor() { + return { { 1, 1, 0, 1 } }; +} + +PropertyValue<Color> TerrainLayer::getTerrainHighlightColor(const optional<std::string>& klass) const { + return impl->paint.terrainHighlightColor.get(klass); +} + +void TerrainLayer::setTerrainHighlightColor(PropertyValue<Color> value, const optional<std::string>& klass) { + if (value == getTerrainHighlightColor(klass)) + return; + impl->paint.terrainHighlightColor.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +PropertyValue<Color> TerrainLayer::getDefaultTerrainAccentColor() { + return { Color::black() }; +} + +PropertyValue<Color> TerrainLayer::getTerrainAccentColor(const optional<std::string>& klass) const { + return impl->paint.terrainAccentColor.get(klass); +} + +void TerrainLayer::setTerrainAccentColor(PropertyValue<Color> value, const optional<std::string>& klass) { + if (value == getTerrainAccentColor(klass)) + return; + impl->paint.terrainAccentColor.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +PropertyValue<float> TerrainLayer::getDefaultTerrainIlluminationDirection() { + return { 135 }; +} + +PropertyValue<float> TerrainLayer::getTerrainIlluminationDirection(const optional<std::string>& klass) const { + return impl->paint.terrainIlluminationDirection.get(klass); +} + +void TerrainLayer::setTerrainIlluminationDirection(PropertyValue<float> value, const optional<std::string>& klass) { + if (value == getTerrainIlluminationDirection(klass)) + return; + impl->paint.terrainIlluminationDirection.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +PropertyValue<AlignmentType> TerrainLayer::getDefaultTerrainIlluminationAlignment() { + return { AlignmentType::Viewport }; +} + +PropertyValue<AlignmentType> TerrainLayer::getTerrainIlluminationAlignment(const optional<std::string>& klass) const { + return impl->paint.terrainIlluminationAlignment.get(klass); +} + +void TerrainLayer::setTerrainIlluminationAlignment(PropertyValue<AlignmentType> value, const optional<std::string>& klass) { + if (value == getTerrainIlluminationAlignment(klass)) + return; + impl->paint.terrainIlluminationAlignment.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +PropertyValue<float> TerrainLayer::getDefaultTerrainExaggeration() { + return { 1 }; +} + +PropertyValue<float> TerrainLayer::getTerrainExaggeration(const optional<std::string>& klass) const { + return impl->paint.terrainExaggeration.get(klass); +} + +void TerrainLayer::setTerrainExaggeration(PropertyValue<float> value, const optional<std::string>& klass) { + if (value == getTerrainExaggeration(klass)) + return; + impl->paint.terrainExaggeration.set(value, klass); + impl->observer->onLayerPaintPropertyChanged(*this); +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/terrain_layer_impl.cpp b/src/mbgl/style/layers/terrain_layer_impl.cpp new file mode 100644 index 0000000000..79e41fa935 --- /dev/null +++ b/src/mbgl/style/layers/terrain_layer_impl.cpp @@ -0,0 +1,47 @@ +#include <mbgl/style/layers/terrain_layer_impl.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> +#include <mbgl/style/raster_bucket_parameters.hpp> +#include <mbgl/renderer/terrain_bucket.hpp> + +namespace mbgl { +namespace style { + +void TerrainLayer::Impl::cascade(const CascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool TerrainLayer::Impl::recalculate(const CalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + passes = RenderPass::Translucent; + + return hasTransitions; +} + +std::unique_ptr<Bucket> TerrainLayer::Impl::createBucket(BucketParameters& params) const { + if (params.is<mapbox::util::recursive_wrapper<GeometryBucketParameters>>()) { + // DEM data encoded into vector tile + auto& parameters = params.get<GeometryBucketParameters>(); + auto& layer = parameters.layer; + + for (std::size_t i = 0; !parameters.cancelled() && i < layer.featureCount(); i++) { + auto feature = layer.getFeature(i); + if (feature->getType() == FeatureType(4)) { + return std::make_unique<TerrainBucket>(feature->getDEMPyramid()); + } else { + // Trying to create a DEM from another feature type. + } + } + } else if (params.is<mapbox::util::recursive_wrapper<RasterBucketParameters>>()) { + // DEM data from raster tile + auto& parameters = params.get<RasterBucketParameters>(); + if (parameters.data) { + return std::make_unique<TerrainBucket>(decodeImage(*parameters.data)); + } + } + + return nullptr; +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/terrain_layer_impl.hpp b/src/mbgl/style/layers/terrain_layer_impl.hpp new file mode 100644 index 0000000000..ce2c7a7e42 --- /dev/null +++ b/src/mbgl/style/layers/terrain_layer_impl.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/layers/terrain_layer.hpp> +#include <mbgl/style/layers/terrain_layer_properties.hpp> + +namespace mbgl { +namespace style { + +class TerrainLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + std::unique_ptr<Layer> cloneRef(const std::string& id) const override; + + void cascade(const CascadeParameters&) override; + bool recalculate(const CalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(BucketParameters&) const override; + + TerrainPaintProperties paint; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/terrain_layer_properties.cpp b/src/mbgl/style/layers/terrain_layer_properties.cpp new file mode 100644 index 0000000000..7373ef0f00 --- /dev/null +++ b/src/mbgl/style/layers/terrain_layer_properties.cpp @@ -0,0 +1,31 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/style/layers/terrain_layer_properties.hpp> + +namespace mbgl { +namespace style { + +void TerrainPaintProperties::cascade(const CascadeParameters& parameters) { + terrainShadowColor.cascade(parameters); + terrainHighlightColor.cascade(parameters); + terrainAccentColor.cascade(parameters); + terrainIlluminationDirection.cascade(parameters); + terrainIlluminationAlignment.cascade(parameters); + terrainExaggeration.cascade(parameters); +} + +bool TerrainPaintProperties::recalculate(const CalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= terrainShadowColor.calculate(parameters); + hasTransitions |= terrainHighlightColor.calculate(parameters); + hasTransitions |= terrainAccentColor.calculate(parameters); + hasTransitions |= terrainIlluminationDirection.calculate(parameters); + hasTransitions |= terrainIlluminationAlignment.calculate(parameters); + hasTransitions |= terrainExaggeration.calculate(parameters); + + return hasTransitions; +} + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/layers/terrain_layer_properties.hpp b/src/mbgl/style/layers/terrain_layer_properties.hpp new file mode 100644 index 0000000000..ad058b0e35 --- /dev/null +++ b/src/mbgl/style/layers/terrain_layer_properties.hpp @@ -0,0 +1,29 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/types.hpp> +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> + +namespace mbgl { +namespace style { + +class CascadeParameters; +class CalculationParameters; + +class TerrainPaintProperties { +public: + void cascade(const CascadeParameters&); + bool recalculate(const CalculationParameters&); + + PaintProperty<Color> terrainShadowColor { { 0, 0, 1, 1 } }; + PaintProperty<Color> terrainHighlightColor { { 1, 1, 0, 1 } }; + PaintProperty<Color> terrainAccentColor { Color::black() }; + PaintProperty<float> terrainIlluminationDirection { 135 }; + PaintProperty<AlignmentType> terrainIlluminationAlignment { AlignmentType::Viewport }; + PaintProperty<float> terrainExaggeration { 1 }; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/raster_bucket_parameters.hpp b/src/mbgl/style/raster_bucket_parameters.hpp new file mode 100644 index 0000000000..cd2a7c5fd7 --- /dev/null +++ b/src/mbgl/style/raster_bucket_parameters.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/tile/tile_id.hpp> + +#include <memory> +#include <string> + +namespace mbgl { +namespace style { + +class RasterBucketParameters { +public: + RasterBucketParameters(const OverscaledTileID& tileID_, + std::shared_ptr<const std::string> data_) + : tileID(tileID_), data(data_) { + } + + const OverscaledTileID& tileID; + std::shared_ptr<const std::string> data; +}; + +} // namespace style +} // namespace mbgl diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp index afaa94878c..f601796c98 100644 --- a/src/mbgl/style/source_impl.cpp +++ b/src/mbgl/style/source_impl.cpp @@ -55,6 +55,7 @@ void Source::Impl::startRender(algorithm::ClipIDGenerator& generator, const mat4& projMatrix, const TransformState& transform) { if (type == SourceType::Vector || + type == SourceType::Raster || type == SourceType::GeoJSON || type == SourceType::Annotations) { generator.update(renderTiles); diff --git a/src/mbgl/style/sources/raster_source_impl.cpp b/src/mbgl/style/sources/raster_source_impl.cpp index b727651260..91a93c800c 100644 --- a/src/mbgl/style/sources/raster_source_impl.cpp +++ b/src/mbgl/style/sources/raster_source_impl.cpp @@ -12,7 +12,7 @@ RasterSource::Impl::Impl(std::string id_, Source& base_, std::unique_ptr<Tile> RasterSource::Impl::createTile(const OverscaledTileID& tileID, const UpdateParameters& parameters) { - return std::make_unique<RasterTile>(tileID, parameters, tileset); + return std::make_unique<RasterTile>(tileID, base.getID(), parameters, tileset); } } // namespace style diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 3c2b97b65d..7781f6ecdd 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -11,6 +11,7 @@ #include <mbgl/style/layers/line_layer.hpp> #include <mbgl/style/layers/circle_layer.hpp> #include <mbgl/style/layers/raster_layer.hpp> +#include <mbgl/style/layers/terrain_layer.hpp> #include <mbgl/style/layer_impl.hpp> #include <mbgl/style/parser.hpp> #include <mbgl/style/query_parameters.hpp> @@ -542,6 +543,7 @@ struct QueueSourceReloadVisitor { // they don't participate in layout. void operator()(CustomLayer&) {} void operator()(RasterLayer&) {} + void operator()(TerrainLayer&) {} void operator()(BackgroundLayer&) {} template <class VectorLayer> diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp index 61437b79b1..b0d1132178 100644 --- a/src/mbgl/tile/geojson_tile.cpp +++ b/src/mbgl/tile/geojson_tile.cpp @@ -36,6 +36,10 @@ public: return geometry; } + DEMPyramid getDEMPyramid() const override { + return {}; + } + optional<Value> getValue(const std::string& key) const override { auto it = feature.properties.find(key); if (it != feature.properties.end()) { diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 46e2b414fe..edc9094e7c 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -6,6 +6,7 @@ #include <mbgl/style/layer_impl.hpp> #include <mbgl/style/layers/background_layer.hpp> #include <mbgl/style/layers/custom_layer.hpp> +#include <mbgl/style/layers/raster_layer.hpp> #include <mbgl/style/style.hpp> #include <mbgl/storage/file_source.hpp> #include <mbgl/geometry/feature_index.hpp> @@ -78,6 +79,7 @@ void GeometryTile::redoLayout() { // Avoid cloning and including irrelevant layers. if (layer->is<BackgroundLayer>() || layer->is<CustomLayer>() || + layer->is<RasterLayer>() || layer->baseImpl->source != sourceID || id.overscaledZ < std::floor(layer->baseImpl->minZoom) || id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom) || diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp index 8a10ec058a..903af0c892 100644 --- a/src/mbgl/tile/geometry_tile_data.hpp +++ b/src/mbgl/tile/geometry_tile_data.hpp @@ -3,6 +3,7 @@ #include <mbgl/util/geometry.hpp> #include <mbgl/util/feature.hpp> #include <mbgl/util/optional.hpp> +#include <mbgl/geometry/dem_pyramid.hpp> #include <cstdint> #include <string> @@ -38,6 +39,7 @@ public: virtual PropertyMap getProperties() const { return PropertyMap(); } virtual optional<FeatureIdentifier> getID() const { return {}; } virtual GeometryCollection getGeometries() const = 0; + virtual DEMPyramid getDEMPyramid() const = 0; }; class GeometryTileLayer { diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index b6f166be56..f46eab628c 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -4,7 +4,8 @@ #include <mbgl/text/collision_tile.hpp> #include <mbgl/text/glyph_atlas.hpp> #include <mbgl/layout/symbol_layout.hpp> -#include <mbgl/style/bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> +#include <mbgl/style/raster_bucket_parameters.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> #include <mbgl/renderer/symbol_bucket.hpp> @@ -210,19 +211,15 @@ void GeometryTileWorker::redoLayout() { continue; } - BucketParameters parameters(id, - *geometryLayer, - obsolete, - reinterpret_cast<uintptr_t>(this), - glyphAtlas, - *featureIndex, - mode); + BucketParameters parameters = GeometryBucketParameters{id, *geometryLayer, obsolete, + reinterpret_cast<uintptr_t>(this), + glyphAtlas, *featureIndex, mode}; if (layer->is<SymbolLayer>()) { symbolLayouts.push_back(layer->as<SymbolLayer>()->impl->createLayout(parameters)); } else { std::unique_ptr<Bucket> bucket = layer->baseImpl->createBucket(parameters); - if (bucket->hasData()) { + if (bucket && bucket->hasData()) { buckets.emplace(layer->baseImpl->bucketName(), std::move(bucket)); } } diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index c7a051f841..e82b0c1485 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -4,6 +4,10 @@ #include <mbgl/tile/tile_loader_impl.hpp> #include <mbgl/style/source.hpp> #include <mbgl/style/update_parameters.hpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/layers/raster_layer.hpp> +#include <mbgl/style/layers/terrain_layer.hpp> +#include <mbgl/style/style.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/storage/file_source.hpp> @@ -12,14 +16,18 @@ namespace mbgl { +using namespace style; + RasterTile::RasterTile(const OverscaledTileID& id_, + std::string sourceID_, const style::UpdateParameters& parameters, const Tileset& tileset) : Tile(id_), loader(*this, id_, parameters, tileset), + sourceID(std::move(sourceID_)), + style(parameters.style), mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())), - worker(parameters.workerScheduler, - ActorRef<RasterTile>(*this, mailbox)) { + worker(parameters.workerScheduler, ActorRef<RasterTile>(*this, mailbox), id_) { } RasterTile::~RasterTile() = default; @@ -36,23 +44,44 @@ void RasterTile::setData(std::shared_ptr<const std::string> data, optional<Timestamp> expires_) { modified = modified_; expires = expires_; + + std::vector<std::unique_ptr<Layer>> copy; + + for (const Layer* layer : style.getLayers()) { + // Avoid cloning and including irrelevant layers. + if (!(layer->is<RasterLayer>() || layer->is<TerrainLayer>()) || + layer->baseImpl->source != sourceID || + id.overscaledZ < std::floor(layer->baseImpl->minZoom) || + id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom) || + layer->baseImpl->visibility == VisibilityType::None) { + continue; + } + + copy.push_back(layer->baseImpl->clone()); + } + worker.invoke(&RasterTileWorker::setLayers, std::move(copy)); worker.invoke(&RasterTileWorker::parse, data); } -void RasterTile::onParsed(std::unique_ptr<Bucket> result) { - bucket = std::move(result); +void RasterTile::onParsed(ParseResult result) { availableData = DataAvailability::All; + buckets = std::move(result.buckets); observer->onTileChanged(*this); } void RasterTile::onError(std::exception_ptr err) { - bucket.reset(); availableData = DataAvailability::All; observer->onTileError(*this, err); } -Bucket* RasterTile::getBucket(const style::Layer&) { - return bucket.get(); +Bucket* RasterTile::getBucket(const style::Layer& layer) { + const auto it = buckets.find(layer.baseImpl->bucketName()); + if (it == buckets.end()) { + return nullptr; + } + + assert(it->second); + return it->second.get(); } void RasterTile::setNecessity(Necessity necessity) { diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp index 1f6ceef0db..ce13d2cafc 100644 --- a/src/mbgl/tile/raster_tile.hpp +++ b/src/mbgl/tile/raster_tile.hpp @@ -10,6 +10,7 @@ namespace mbgl { class Tileset; namespace style { +class Style; class Layer; class UpdateParameters; } // namespace style @@ -17,8 +18,9 @@ class UpdateParameters; class RasterTile : public Tile { public: RasterTile(const OverscaledTileID&, - const style::UpdateParameters&, - const Tileset&); + std::string sourceID, + const style::UpdateParameters&, + const Tileset&); ~RasterTile() final; void setNecessity(Necessity) final; @@ -29,20 +31,27 @@ public: optional<Timestamp> expires_); void cancel() override; + + class ParseResult { + public: + std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets; + }; + Bucket* getBucket(const style::Layer&) override; - void onParsed(std::unique_ptr<Bucket> result); + void onParsed(ParseResult); void onError(std::exception_ptr); private: TileLoader<RasterTile> loader; + const std::string sourceID; + style::Style& style; + std::shared_ptr<Mailbox> mailbox; Actor<RasterTileWorker> worker; - // Contains the Bucket object for the tile. Buckets are render - // objects and they get added by tile parsing operations. - std::unique_ptr<Bucket> bucket; + std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets; }; } // namespace mbgl diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp index 443ee10400..25cec516cc 100644 --- a/src/mbgl/tile/raster_tile_worker.cpp +++ b/src/mbgl/tile/raster_tile_worker.cpp @@ -1,23 +1,46 @@ #include <mbgl/tile/raster_tile_worker.hpp> #include <mbgl/tile/raster_tile.hpp> -#include <mbgl/renderer/raster_bucket.cpp> +#include <mbgl/style/layer_impl.hpp> +#include <mbgl/style/raster_bucket_parameters.hpp> +#include <mbgl/style/geometry_bucket_parameters.hpp> #include <mbgl/actor/actor.hpp> namespace mbgl { -RasterTileWorker::RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTile> parent_) - : parent(std::move(parent_)) { +using namespace style; + +RasterTileWorker::RasterTileWorker(ActorRef<RasterTileWorker>, + ActorRef<RasterTile> parent_, + OverscaledTileID id_) + : parent(std::move(parent_)), id(std::move(id_)) { +} + +RasterTileWorker::~RasterTileWorker() = default; + +void RasterTileWorker::setLayers(std::vector<std::unique_ptr<Layer>> layers_) { + layers = std::move(layers_); } void RasterTileWorker::parse(std::shared_ptr<const std::string> data) { - if (!data) { - parent.invoke(&RasterTile::onParsed, nullptr); // No data; empty tile. + if (!layers) { return; } try { - auto bucket = std::make_unique<RasterBucket>(decodeImage(*data)); - parent.invoke(&RasterTile::onParsed, std::move(bucket)); + std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets; + + BucketParameters parameters = RasterBucketParameters{id, data}; + + for (auto& layer : *layers) { + std::unique_ptr<Bucket> bucket = layer->baseImpl->createBucket(parameters); + if (bucket && bucket->hasData()) { + buckets.emplace(layer->baseImpl->bucketName(), std::move(bucket)); + } + } + + parent.invoke(&RasterTile::onParsed, RasterTile::ParseResult { + std::move(buckets) + }); } catch (...) { parent.invoke(&RasterTile::onError, std::current_exception()); } diff --git a/src/mbgl/tile/raster_tile_worker.hpp b/src/mbgl/tile/raster_tile_worker.hpp index 44bc37ca5d..c99b6269ec 100644 --- a/src/mbgl/tile/raster_tile_worker.hpp +++ b/src/mbgl/tile/raster_tile_worker.hpp @@ -1,6 +1,8 @@ #pragma once +#include <mbgl/tile/tile_id.hpp> #include <mbgl/actor/actor_ref.hpp> +#include <mbgl/util/optional.hpp> #include <memory> #include <string> @@ -9,14 +11,25 @@ namespace mbgl { class RasterTile; +namespace style { +class Layer; +} // namespace style + class RasterTileWorker { public: - RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTile>); + RasterTileWorker(ActorRef<RasterTileWorker>, ActorRef<RasterTile>, OverscaledTileID); + ~RasterTileWorker(); + void setLayers(std::vector<std::unique_ptr<style::Layer>>); void parse(std::shared_ptr<const std::string> data); private: ActorRef<RasterTile> parent; + + const OverscaledTileID id; + + // Outer optional indicates whether we've received it or not. + optional<std::vector<std::unique_ptr<style::Layer>>> layers; }; } // namespace mbgl diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index a195885415..db4b16da32 100644 --- a/src/mbgl/tile/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -1,6 +1,7 @@ #include <mbgl/tile/vector_tile.hpp> #include <mbgl/tile/tile_loader_impl.hpp> #include <mbgl/tile/geometry_tile_data.hpp> +#include <mbgl/platform/log.hpp> #include <protozero/pbf_reader.hpp> @@ -24,6 +25,7 @@ public: std::unordered_map<std::string,Value> getProperties() const override; optional<FeatureIdentifier> getID() const override; GeometryCollection getGeometries() const override; + DEMPyramid getDEMPyramid() const override; private: const VectorTileLayer& layer; @@ -241,6 +243,76 @@ GeometryCollection VectorTileFeature::getGeometries() const { return fixupPolygons(lines); } +DEMPyramid VectorTileFeature::getDEMPyramid() const { + DEMPyramid pyramid; + if (layer.extent != 256) { + Log::Warning(Event::ParseTile, "DEM extent must be 256"); + return pyramid; + } + + auto decodeSVarint = [](auto& iter) { + if (iter.first == iter.second) { + fprintf(stderr, "reading beyond end\n"); + } + return iter.first != iter.second ? protozero::decode_zigzag32(*iter.first++) : 0; + }; + + auto iter = geometry_iter; + + // Decode main square + pyramid.levels.emplace_back(256, 256, 128); + { + auto& level = pyramid.levels.front(); + for (int32_t y = 0; y < level.height; y++) { + for (int32_t x = 0; x < level.width; x++) { + const auto value = decodeSVarint(iter); + const auto value_left = x ? level.get(x - 1, y) : 0; + const auto value_up = y ? level.get(x, y - 1) : 0; + const auto value_up_left = x && y ? level.get(x - 1, y - 1) : 0; + level.set(x, y, value + value_left + value_up - value_up_left); + } + } + } + + pyramid.buildLevels(); + + // Decode bleed + for (auto& level : pyramid.levels) { + if (level.width <= 2 || level.height <= 2) { + break; + } + + int32_t x = -1; + int32_t y = -1; + int32_t prev = 0; + // Decode left column + while (y < level.height) { + level.set(x, y, (prev = decodeSVarint(iter) + prev)); + y++; + } + + // Decode bottom row + while (x < level.width) { + level.set(x, y, (prev = decodeSVarint(iter) + prev)); + x++; + } + + // Decode right column + while (y > -1) { + level.set(x, y, (prev = decodeSVarint(iter) + prev)); + y--; + } + + // Decode top row + while (x > -1) { + level.set(x, y, (prev = decodeSVarint(iter) + prev)); + x--; + } + } + + return pyramid; +} + VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_) : data(std::move(data_)) { } |