From d6db72e8ba8a7c44487392e2cef987d271d5b7d6 Mon Sep 17 00:00:00 2001 From: Stefan Karschti Date: Fri, 16 Feb 2024 17:39:47 +0200 Subject: [PATCH] Custom Drawable Layer: Symbol Icon (#1908) --- CMakeLists.txt | 5 +- bazel/core.bzl | 6 +- {src => include}/mbgl/gfx/context.hpp | 0 .../shaders/custom_drawable_layer_ubo.hpp | 36 ++++ .../gl/drawable_custom_symbol_icon.hpp | 92 ++++++++++ include/mbgl/shaders/gl/shader_info.hpp | 6 + .../mbgl/shaders/mtl/custom_symbol_icon.hpp | 105 +++++++++++ include/mbgl/shaders/shader_defines.hpp | 8 + include/mbgl/shaders/shader_manifest.hpp | 1 + include/mbgl/shaders/shader_source.hpp | 1 + .../style/layers/custom_drawable_layer.hpp | 40 ++++- .../app/ExampleCustomDrawableStyleLayer.mm | 35 +++- .../ios/app/Assets.xcassets/Contents.json | 6 +- .../pin.imageset/Contents.json | 21 +++ .../app/Assets.xcassets/pin.imageset/pin1.png | Bin 0 -> 21574 bytes .../drawable.custom.symbol_icon.fragment.glsl | 7 + .../drawable.custom.symbol_icon.vertex.glsl | 69 ++++++++ shaders/manifest.json | 7 + src/mbgl/gfx/index_vector.hpp | 2 +- src/mbgl/gfx/vertex_vector.hpp | 6 +- src/mbgl/gl/renderer_backend.cpp | 1 + src/mbgl/mtl/renderer_backend.cpp | 2 + src/mbgl/shaders/gl/shader_info.cpp | 9 + src/mbgl/shaders/mtl/custom_symbol_icon.cpp | 22 +++ .../style/layers/custom_drawable_layer.cpp | 164 +++++++++++++++++- test/api/custom_drawable_layer.test.cpp | 143 +++++++++++++-- test/fixtures/api/simple.json | 25 +++ .../custom_drawable_layer/basic/expected.png | Bin 30225 -> 0 bytes .../custom_drawable_layer/fill/expected.png | Bin 0 -> 7742 bytes .../custom_drawable_layer/line/expected.png | Bin 0 -> 35055 bytes .../symbol_icon/expected.png | Bin 0 -> 11379 bytes .../symbol_icon/pin1.png | Bin 0 -> 21574 bytes 32 files changed, 789 insertions(+), 30 deletions(-) rename {src => include}/mbgl/gfx/context.hpp (100%) create mode 100644 include/mbgl/shaders/custom_drawable_layer_ubo.hpp create mode 100644 include/mbgl/shaders/gl/drawable_custom_symbol_icon.hpp create mode 100644 include/mbgl/shaders/mtl/custom_symbol_icon.hpp create mode 100644 platform/ios/app/Assets.xcassets/pin.imageset/Contents.json create mode 100644 platform/ios/app/Assets.xcassets/pin.imageset/pin1.png create mode 100644 shaders/drawable.custom.symbol_icon.fragment.glsl create mode 100644 shaders/drawable.custom.symbol_icon.vertex.glsl create mode 100644 src/mbgl/shaders/mtl/custom_symbol_icon.cpp create mode 100644 test/fixtures/api/simple.json delete mode 100644 test/fixtures/custom_drawable_layer/basic/expected.png create mode 100644 test/fixtures/custom_drawable_layer/fill/expected.png create mode 100644 test/fixtures/custom_drawable_layer/line/expected.png create mode 100644 test/fixtures/custom_drawable_layer/symbol_icon/expected.png create mode 100644 test/fixtures/custom_drawable_layer/symbol_icon/pin1.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bba574fe..eadad1876 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ endif() if(MLN_DRAWABLE_RENDERER) list(APPEND INCLUDE_FILES + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/context.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_data.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_impl.hpp @@ -465,7 +466,6 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/attribute.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/color_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/command_encoder.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/context.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/cull_face_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/debug_group.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/depth_mode.hpp @@ -1142,6 +1142,7 @@ if(MLN_WITH_OPENGL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/hillshade_prepare_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/custom_drawable_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/raster_layer_ubo.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/shader_defines.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/symbol_layer_ubo.hpp @@ -1211,6 +1212,7 @@ if(MBGL_WITH_METAL) ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/common.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_box.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/collision_circle.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/custom_symbol_icon.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/debug.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion.hpp @@ -1256,6 +1258,7 @@ if(MBGL_WITH_METAL) ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_box.cpp ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/collision_circle.cpp ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/clipping_mask.cpp + ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/custom_symbol_icon.cpp ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/debug.cpp ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill.cpp ${PROJECT_SOURCE_DIR}src/mbgl/shaders/mtl/fill_extrusion.cpp diff --git a/bazel/core.bzl b/bazel/core.bzl index b09873d25..6c22564d9 100644 --- a/bazel/core.bzl +++ b/bazel/core.bzl @@ -67,6 +67,7 @@ MLN_GENERATED_OPENGL_SHADER_HEADERS = [ "include/mbgl/shaders/gl/drawable_circle.hpp", "include/mbgl/shaders/gl/drawable_collision_box.hpp", "include/mbgl/shaders/gl/drawable_collision_circle.hpp", + "include/mbgl/shaders/gl/drawable_custom_symbol_icon.hpp", "include/mbgl/shaders/gl/drawable_debug.hpp", "include/mbgl/shaders/gl/drawable_fill.hpp", "include/mbgl/shaders/gl/drawable_fill_outline.hpp", @@ -143,7 +144,6 @@ MLN_CORE_SOURCE = [ "include/mbgl/gfx/backend.hpp", "src/mbgl/gfx/color_mode.hpp", "src/mbgl/gfx/command_encoder.hpp", - "src/mbgl/gfx/context.hpp", "src/mbgl/gfx/cull_face_mode.hpp", "src/mbgl/gfx/debug_group.hpp", "src/mbgl/gfx/depth_mode.hpp", @@ -648,6 +648,7 @@ MLN_CORE_SOURCE = [ ] MLN_CORE_HEADERS = [ + "include/mbgl/gfx/context.hpp", "include/mbgl/actor/actor.hpp", "include/mbgl/actor/actor_ref.hpp", "include/mbgl/actor/aspiring_actor.hpp", @@ -980,6 +981,7 @@ MLN_DRAWABLES_HEADERS = [ "include/mbgl/shaders/background_layer_ubo.hpp", "include/mbgl/shaders/circle_layer_ubo.hpp", "include/mbgl/shaders/collision_layer_ubo.hpp", + "include/mbgl/shaders/custom_drawable_layer_ubo.hpp", "include/mbgl/shaders/debug_layer_ubo.hpp", "include/mbgl/shaders/fill_layer_ubo.hpp", "include/mbgl/shaders/fill_extrusion_layer_ubo.hpp", @@ -1054,6 +1056,7 @@ MLN_DRAWABLES_MTL_SOURCE = [ "src/mbgl/shaders/mtl/collision_box.cpp", "src/mbgl/shaders/mtl/collision_circle.cpp", "src/mbgl/shaders/mtl/clipping_mask.cpp", + "src/mbgl/shaders/mtl/custom_symbol_icon.cpp", "src/mbgl/shaders/mtl/debug.cpp", "src/mbgl/shaders/mtl/fill.cpp", "src/mbgl/shaders/mtl/fill_extrusion.cpp", @@ -1098,6 +1101,7 @@ MLN_DRAWABLES_MTL_HEADERS = [ "include/mbgl/shaders/mtl/collision_box.hpp", "include/mbgl/shaders/mtl/collision_circle.hpp", "include/mbgl/shaders/mtl/common.hpp", + "include/mbgl/shaders/mtl/custom_symbol_icon.hpp", "include/mbgl/shaders/mtl/debug.hpp", "include/mbgl/shaders/mtl/fill.hpp", "include/mbgl/shaders/mtl/fill_extrusion.hpp", diff --git a/src/mbgl/gfx/context.hpp b/include/mbgl/gfx/context.hpp similarity index 100% rename from src/mbgl/gfx/context.hpp rename to include/mbgl/gfx/context.hpp diff --git a/include/mbgl/shaders/custom_drawable_layer_ubo.hpp b/include/mbgl/shaders/custom_drawable_layer_ubo.hpp new file mode 100644 index 000000000..36259ea81 --- /dev/null +++ b/include/mbgl/shaders/custom_drawable_layer_ubo.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace mbgl { +namespace shaders { + +/// Custom Symbol Icon matrix +struct alignas(16) CustomSymbolIconDrawableUBO { + /* 0 */ std::array matrix; + /* 64 */ +}; +static_assert(sizeof(CustomSymbolIconDrawableUBO) == 4 * 16); + +/// Custom Symbol Icon Parameters +struct alignas(16) CustomSymbolIconParametersUBO { + /* 0 */ std::array extrude_scale; + /* 8 */ std::array anchor; + /* 16 */ float angle_degrees; + /* 20 */ uint32_t scale_with_map; + /* 24 */ uint32_t pitch_with_map; + /* 28 */ float camera_to_center_distance; + /* 32 */ float aspect_ratio; + /* 36 */ float pad0, pad1, pad2; + /* 48 */ +}; +static_assert(sizeof(CustomSymbolIconParametersUBO) == 3 * 16); + +enum { + idCustomSymbolIconDrawableUBO, + idCustomSymbolIconParametersUBO, + customDrawableUBOCount +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/drawable_custom_symbol_icon.hpp b/include/mbgl/shaders/gl/drawable_custom_symbol_icon.hpp new file mode 100644 index 000000000..77b4a76b1 --- /dev/null +++ b/include/mbgl/shaders/gl/drawable_custom_symbol_icon.hpp @@ -0,0 +1,92 @@ +// Generated code, do not modify this file! +#pragma once +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr const char* name = "CustomSymbolIconShader"; + static constexpr const char* vertex = R"(layout(location = 0) in vec2 a_pos; +layout(location = 1) in vec2 a_tex; + +layout(std140) uniform CustomSymbolIconDrawableUBO { + highp mat4 u_matrix; +}; + +layout(std140) uniform CustomSymbolIconParametersUBO { + highp vec2 u_extrude_scale; + highp vec2 u_anchor; + highp float u_angle_degrees; + bool u_scale_with_map; + bool u_pitch_with_map; + highp float u_camera_to_center_distance; + highp float u_aspect_ratio; + highp float pad0, pad1, pad3; +}; + +out vec2 v_tex; + +vec2 rotateVec2(vec2 v, float angle) { + float cosA = cos(angle); + float sinA = sin(angle); + return vec2(v.x * cosA - v.y * sinA, v.x * sinA + v.y * cosA); +} + +vec2 ellipseRotateVec2(vec2 v, float angle, float radiusRatio /* A/B */) { + float cosA = cos(angle); + float sinA = sin(angle); + float invRatio = 1.0 / radiusRatio; + return vec2(v.x * cosA - radiusRatio * v.y * sinA, invRatio * v.x * sinA + v.y * cosA); +} + +void main() { + // decode the extrusion vector (-1, -1) to (1, 1) + vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); + + // make anchor relative to (0.5, 0.5) and corners in range (-1, -1) to (1, 1) + vec2 anchor = (u_anchor - vec2(0.5, 0.5)) * 2.0; + + // decode center + vec2 center = floor(a_pos * 0.5); + + // rotate extrusion around anchor + float angle = radians(-u_angle_degrees); + vec2 corner = extrude - anchor; + + // compute + if (u_pitch_with_map) { + if (u_scale_with_map) { + corner *= u_extrude_scale; + } else { + vec4 projected_center = u_matrix * vec4(center, 0, 1); + corner *= u_extrude_scale * (projected_center.w / u_camera_to_center_distance); + } + corner = center + rotateVec2(corner, angle); + gl_Position = u_matrix * vec4(corner, 0, 1); + } else { + gl_Position = u_matrix * vec4(center, 0, 1); + if (u_scale_with_map) { + gl_Position.xy += ellipseRotateVec2(corner * u_extrude_scale * u_camera_to_center_distance, angle, u_aspect_ratio); + } else { + gl_Position.xy += ellipseRotateVec2(corner * u_extrude_scale * gl_Position.w, angle, u_aspect_ratio); + } + } + + // texture coordinates + v_tex = a_tex; +} +)"; + static constexpr const char* fragment = R"(uniform sampler2D u_texture; + +in vec2 v_tex; + +void main() { + fragColor = texture(u_texture, v_tex); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/gl/shader_info.hpp b/include/mbgl/shaders/gl/shader_info.hpp index 7baba27c9..0ce68f3b6 100644 --- a/include/mbgl/shaders/gl/shader_info.hpp +++ b/include/mbgl/shaders/gl/shader_info.hpp @@ -54,6 +54,12 @@ struct ShaderInfo { static const std::vector textures; }; +template <> +struct ShaderInfo { + static const std::vector uniformBlocks; + static const std::vector textures; +}; + template <> struct ShaderInfo { static const std::vector uniformBlocks; diff --git a/include/mbgl/shaders/mtl/custom_symbol_icon.hpp b/include/mbgl/shaders/mtl/custom_symbol_icon.hpp new file mode 100644 index 000000000..229a7b5f2 --- /dev/null +++ b/include/mbgl/shaders/mtl/custom_symbol_icon.hpp @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace shaders { + +template <> +struct ShaderSource { + static constexpr auto name = "CustomSymbolIconShader"; + static constexpr auto vertexMainFunction = "vertexMain"; + static constexpr auto fragmentMainFunction = "fragmentMain"; + + static const std::array attributes; + static const std::array uniforms; + static const std::array textures; + + static constexpr auto source = R"( +struct alignas(16) CustomSymbolIconDrawableUBO { + float4x4 matrix; +}; + +struct alignas(16) CustomSymbolIconParametersUBO { + float2 extrude_scale; + float2 anchor; + float angle_degrees; + int scale_with_map; + int pitch_with_map; + float camera_to_center_distance; + float aspect_ratio; + float pad0, pad1, pad3; +}; + +struct VertexStage { + float2 a_pos [[attribute(0)]]; + float2 a_tex [[attribute(1)]]; +}; + +struct FragmentStage { + float4 position [[position, invariant]]; + half2 tex; +}; + +float2 rotateVec2(float2 v, float angle) { + float cosA = cos(angle); + float sinA = sin(angle); + return float2(v.x * cosA - v.y * sinA, v.x * sinA + v.y * cosA); +} + +float2 ellipseRotateVec2(float2 v, float angle, float radiusRatio /* A/B */) { + float cosA = cos(angle); + float sinA = sin(angle); + float invRatio = 1.0 / radiusRatio; + return float2(v.x * cosA - radiusRatio * v.y * sinA, invRatio * v.x * sinA + v.y * cosA); +} + +FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]], + device const CustomSymbolIconDrawableUBO& drawable [[buffer(2)]], + device const CustomSymbolIconParametersUBO& parameters [[buffer(3)]]) { + + const float2 extrude = glMod(float2(vertx.a_pos), 2.0) * 2.0 - 1.0; + const float2 anchor = (parameters.anchor - float2(0.5, 0.5)) * 2.0; + const float2 center = floor(float2(vertx.a_pos) * 0.5); + const float angle = radians(-parameters.angle_degrees); + float2 corner = extrude - anchor; + + float4 position; + if (parameters.pitch_with_map) { + if (parameters.scale_with_map) { + corner *= parameters.extrude_scale; + } else { + float4 projected_center = drawable.matrix * float4(center, 0, 1); + corner *= parameters.extrude_scale * (projected_center.w / parameters.camera_to_center_distance); + } + corner = center + rotateVec2(corner, angle); + position = drawable.matrix * float4(corner, 0, 1); + } else { + position = drawable.matrix * float4(center, 0, 1); + const float factor = parameters.scale_with_map ? parameters.camera_to_center_distance : position.w; + position.xy += ellipseRotateVec2(corner * parameters.extrude_scale * factor, angle, parameters.aspect_ratio); + } + + return { + .position = position, + .tex = half2(vertx.a_tex) + }; +} + +half4 fragment fragmentMain(FragmentStage in [[stage_in]], + texture2d image [[texture(0)]], + sampler image_sampler [[sampler(0)]]) { +#if defined(OVERDRAW_INSPECTOR) + return half4(1.0); +#endif + + return half4(image.sample(image_sampler, float2(in.tex))); +} +)"; +}; + +} // namespace shaders +} // namespace mbgl diff --git a/include/mbgl/shaders/shader_defines.hpp b/include/mbgl/shaders/shader_defines.hpp index 9ee9fc0a9..36e73c877 100644 --- a/include/mbgl/shaders/shader_defines.hpp +++ b/include/mbgl/shaders/shader_defines.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ namespace shaders { static constexpr auto maxUBOCountPerShader = std::max({static_cast(backgroundUBOCount), static_cast(circleUBOCount), static_cast(collisionUBOCount), + static_cast(customDrawableUBOCount), static_cast(debugUBOCount), static_cast(fillUBOCount), static_cast(fillOutlineUBOCount), @@ -53,6 +55,11 @@ enum { collisionTextureCount }; +enum { + idCustomSymbolIconTexture, + customSymbolIconTextureCount +}; + enum { idDebugOverlayTexture, debugTextureCount @@ -99,6 +106,7 @@ enum { static constexpr auto maxTextureCountPerShader = std::max({static_cast(backgroundTextureCount), static_cast(circleTextureCount), static_cast(collisionTextureCount), + static_cast(customSymbolIconTextureCount), static_cast(debugTextureCount), static_cast(fillTextureCount), static_cast(fillExtrusionTextureCount), diff --git a/include/mbgl/shaders/shader_manifest.hpp b/include/mbgl/shaders/shader_manifest.hpp index d769192e2..44882c401 100644 --- a/include/mbgl/shaders/shader_manifest.hpp +++ b/include/mbgl/shaders/shader_manifest.hpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/include/mbgl/shaders/shader_source.hpp b/include/mbgl/shaders/shader_source.hpp index 8f44c1eec..7facb567c 100644 --- a/include/mbgl/shaders/shader_source.hpp +++ b/include/mbgl/shaders/shader_source.hpp @@ -34,6 +34,7 @@ enum class BuiltIn { SymbolIconShader, SymbolSDFIconShader, SymbolTextAndIconShader, + CustomSymbolIconShader, Prelude, BackgroundProgram, BackgroundPatternProgram, diff --git a/include/mbgl/style/layers/custom_drawable_layer.hpp b/include/mbgl/style/layers/custom_drawable_layer.hpp index 7deb77057..c2ffdea1e 100644 --- a/include/mbgl/style/layers/custom_drawable_layer.hpp +++ b/include/mbgl/style/layers/custom_drawable_layer.hpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -46,6 +48,16 @@ public: float opacity = 1.f; }; + struct SymbolOptions { + Size size; + gfx::Texture2DPtr texture; + std::array anchor{0.5f, 0.5f}; + std::array, 2> textureCoordinates{{{0, 0}, {1, 1}}}; + float angleDegrees{.0f}; + bool scaleWithMap{false}; + bool pitchWithMap{false}; + }; + public: /// @brief Construct a new Interface object (internal core use only) Interface(RenderLayer& layer, @@ -84,6 +96,13 @@ public: */ void setFillOptions(const FillOptions& options); + /** + * @brief Set the Symbol options + * + * @param options + */ + void setSymbolOptions(const SymbolOptions& options); + /** * @brief Add a polyline * @@ -92,8 +111,20 @@ public: */ void addPolyline(const GeometryCoordinates& coordinates); + /** + * @brief Add a multipolygon area fill + * + * @param geometry a collection of rings with optional holes + */ void addFill(const GeometryCollection& geometry); + /** + * @brief Add a symbol + * + * @param point + */ + void addSymbol(const GeometryCoordinate& point); + /** * @brief Finish the current drawable building session * @@ -113,15 +144,20 @@ public: private: gfx::ShaderPtr lineShaderDefault() const; gfx::ShaderPtr fillShaderDefault() const; + gfx::ShaderPtr symbolShaderDefault() const; std::unique_ptr createBuilder(const std::string& name, gfx::ShaderPtr shader) const; - gfx::ShaderPtr lineShader; - gfx::ShaderPtr fillShader; std::unique_ptr builder; std::optional tileID; + + gfx::ShaderPtr lineShader; + gfx::ShaderPtr fillShader; + gfx::ShaderPtr symbolShader; + LineOptions lineOptions; FillOptions fillOptions; + SymbolOptions symbolOptions; }; class CustomDrawableLayer final : public Layer { diff --git a/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm b/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm index dce804d73..49f0e3412 100644 --- a/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm +++ b/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm @@ -2,6 +2,9 @@ #import "MLNStyleLayer.h" #import "MLNCustomDrawableStyleLayer.h" +#import + +#include #include #include #include @@ -81,7 +84,7 @@ public: interface.addPolyline(polyline); } } - + // add fill polygon { using namespace mbgl; @@ -111,6 +114,36 @@ public: // add fill interface.addFill(geometry); } + + // add symbol + { + using namespace mbgl; + GeometryCoordinate position {static_cast(extent* 0.5f), static_cast(extent* 0.5f)}; + + // load image + UIImage *assetImage = [UIImage imageNamed:@"pin"]; + assert(assetImage.CGImage != NULL); + std::shared_ptr image = std::make_shared(MLNPremultipliedImageFromCGImage(assetImage.CGImage)); + + // set symbol options + Interface::SymbolOptions options; + options.texture = interface.context.createTexture2D(); + options.texture->setImage(image); + options.texture->setSamplerConfiguration({gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + options.textureCoordinates = {{{0.0f, 0.08f}, {1.0f, 0.9f}}}; + const float xspan = options.textureCoordinates[1][0] - options.textureCoordinates[0][0]; + const float yspan = options.textureCoordinates[1][1] - options.textureCoordinates[0][1]; + assert(xspan > 0.0f && yspan > 0.0f); + options.size = {static_cast(image->size.width * xspan), static_cast(image->size.height * yspan)}; + options.anchor = {0.5f, 0.95f}; + options.angleDegrees = 45.0f; + options.scaleWithMap = true; + options.pitchWithMap = false; + interface.setSymbolOptions(options); + + // add symbol + interface.addSymbol(position); + } // finish interface.finish(); diff --git a/platform/ios/app/Assets.xcassets/Contents.json b/platform/ios/app/Assets.xcassets/Contents.json index da4a164c9..73c00596a 100644 --- a/platform/ios/app/Assets.xcassets/Contents.json +++ b/platform/ios/app/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/platform/ios/app/Assets.xcassets/pin.imageset/Contents.json b/platform/ios/app/Assets.xcassets/pin.imageset/Contents.json new file mode 100644 index 000000000..102c27746 --- /dev/null +++ b/platform/ios/app/Assets.xcassets/pin.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "pin1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/platform/ios/app/Assets.xcassets/pin.imageset/pin1.png b/platform/ios/app/Assets.xcassets/pin.imageset/pin1.png new file mode 100644 index 0000000000000000000000000000000000000000..c4cc5d2f5f0f7a0ada4ffc4887b957a84f97f72d GIT binary patch literal 21574 zcmeFZWm{a`vMx-J;O-tExHRrgaCfJX00Dx#2Wbc%+}+*X8%b~v!6mo{w}#Vso^{qf z`@{PWUbwjC>^Vo*(5g}6uDgg(Q;|hSAwhwGfkBs-`=9{>^F|8#r-$?w`ecMU2ME2q zan+EOgsGV%JA{5vv(%HfQdWjxg5D#+z`ntOf%{to`U?|o0|WohJq!#T^a=w5m-ps> z-sZvn-?wk1^5Fh^ulKj0>(^LTs1SV{Ej>3qWhFriM|(E2kB;V+Y+m+Ge+$3}dkI2s z?JeER-g()7c5oH+5~2R5gdp_(?_&Vs_@^Zf~qbyme892$`|Dj{-@;sdiI}sgaLmm|9=|uZ%_Yu3hk;W ziZI~6!zPMCY_f$210xP2|3N~_>&>Y@ViunC?Q3FI;)jS}#Ig_A^03rj3*IrvbMznP zd%A?7=2$;JEM5t_io@f*k-&n79}#F|Nw-`YwBohqmAzkVZMN?8_4O>Vw)XJxS%307 znlm=euk5)wa(CD6*8QLq4MWq1#18xaU;ft+v=Ig!uV#wuPa+*qPiqL1H63=AA5ljE&5!Exq$toXS z{o557gha@&%D4p^YGDq~^sWzF2mAgx4+oxoo0N6++r}FC_OcegV`IUA7d`AVX36ia{Iqpk3;aDsvXv>Ng@>0E$O{0I-^yC|n#lvGx-L`-Nmrx8h(RPbvFw=_dD z=~mak5MC`@zS}bQN;>Z6TMF(vRqLabPMVvZ^6nkmMUN4f+4bW}Gyrp_0@ap$LMIlE zsx=&7u3i&6Ddmm+K0AI?+Eb_@{i@8?EXbmP0ono9^k~l`qD%E=LiV+e#`o4^+zVH=Tuo{xiRUpv|&_&W~0qrzUi{-Js)9i z(ykmr;)f!9Fe^6Od^|ka_h;xL;0`2hF9^l`Ko^LQvB*@e8|T68zx^)5Wdnv}9&-iW zKS~90aC(@0|6rfBl#!cyDSp(EFun%|LzfO9^97Vo$d{8{z=yNd2nxX(r07#XcJ*(h z=m;qhamsAESGV~)~@ZtqzQeWQPV7L@*VrioA-S*IHMWWX;~ z$)mk9BEj|bdvn9?Jk+SUZ*kD*csJd_YF*Y=G&{75_NN9D^kl?Olwr!r2%Tf)Wp)gL zV|DCv|E-S0q3^X9SFUFXGQs4_l9{n1+C!F@f9i+^ zs%4KvKGfktLyBSq7(QV9GRrHO>uoLzP-mtA_kbXZrt-UQ$=RwvzgE?@?j-NxSsuJV z^^`y)&my|f!E+}v=&FddunbG9mZoACcr7w9%R7I%Ty?%)6pNi%xLQygm@)>P%Kzxzbo(lt`=<3p*F;)J^S1{(sZ)K#lklMDeWpF(ZfFVg$|V@%&- z+bk3Rs(Uo1FSRe$Ax+lx36JDBQ~N02msyfwv~c6}iGIS5PIklDUj;i+A}xw%O1~Nk z&Mcl!6<~+>ehT^Jr~x0F6P>pYG?d;C*}hgl%KTW1a#!rMcujr5bw>@=*6w@3OketV zr*tQaW@2s!t=#pOl@B(VO4)+VP5mc)0R?ALrHYKzjh zw}7Ef@_=u-?TFBkKI>mdH~PbjhF>FQi)*0{-#ZwmLR^J@Dfqe@suWCsST(S-hp*vd zm7^7&kidDE-Xd9-rP=CWfB5Hyl~glv7#(RUPh{>P3}pk=-evAd*HM@eBBFk@umuaV~J!?4;g9)wyEaeKeCX@kcl&H3^WPdC4`-_#(kRHFpY1utDe`wzFSsFEtJ$p7R7I;nw^3gm;Y>QChW!~1v% z=!}!VkE74fM+)mAElQ^I$%s;R-C}iLT(7yUx$k|Z%aRV34uYDZgK?0ajai?B@0Zbv zj#CO6ITr4jRmsCNsCDlyVC3s7xq1^r&ILg%l!s1VF&=G+k`lZ1J7R0Iu} zM?_jFb!4abT^6O0hCmRea4@t44+v#?&jbPRre94Ed5ron$OYB9eQwGWQ`zS0%%p7R zN@9{^*E-w}!$_G>UPD9SnHV2V>pJG=wU`(f@_zl&V`5_~865mDaK1>_7jC`!WBq#b z{)O8|PZb=blT)(VMeXx=E;hY9QF{v%vKA-Lc*46Y;D6iCNoawi3m<}1ai z+;5R;9u|wmXp7eTc?t&OEcXDu@tz6GW_luEUE9ZCg&Iudh|n%p>H>~_R%gDy7xX-X zu4MNDLH8q~k($xA;^JaFLPFV805ApqqnjHyC@f4vPcLofBb9+AU8MMdvnt6(T*<1? z7wFCvPQrUp7121=yQWy%)oOB{)LU5aOEc6$TU7c<`z{4!=8nysLb3eb5Okcc6xJyH zGw>-(mQRfmi>8k<;5M=8y^9Musher&VyP-63Fk*7bQ12bk2lBk$o4R&p&>|O~scw+5i01TYdQc$VBHin;K%lL;N zVwP}N3{M+-u1UioViY~zh`b6p)~>pEsjFjWi}v(yJ~9^zZWf=vL{7 z(S~j}sz$pVwomz-&-#XmMBwITsHUmTV|}LGHp;}!*gtWHg(|Vim%R@-2ly7Wb>*C_ zbbl88pFYPJrU|$`CwvUVM5J62`qXXQ>A`IVhR@)4rj8*KNFd>9h^6}a{Ol*_ch7FW z)BtL6+)x=A(WZm}m7|d*At-JYhP_BEB{}ql(`MNO8Wgoc4M`W75DrFrHx@zQ8&s(~ zz6<|t{9}-&e0(V-xdf`1m(h6sf=eLsAgNQ?BXk)ZhCB!{ylb;nu8k!Znr*U~I|xFg z$jg@s&+xE|V-6blnezL4+}zJI8X_dN35(&dHHT#6bHV{uqz^H?&tD1gUok~9|^qN-Wx6|UARtW6* z87FE~7X>cVWb((9@q-R&iGHKi%)v~dza)&#+qdw)`$G_I7Amx%t)c@XHE?#68yfoT z0)8Ks6AvJj%-aU9zj$#$dZ(B^3$PHJ2WYjS^QgaN?g;_qKN;W$JH8t3)KvAz?wIIQ#-A=lqhHcy5iWdEDDr_-%WxghYegmySOdHv`k<#F1WTW_3 zLK`Qr%}tyROB)aWly}Ic@P8||P*=%`Dk0o3&^*LW(R=WJ{`38CHx*b?W85j2!uY-7 zi?~uWKmK{+)TiCibYf?Aad%O1~U<-qZ z^3s0+x-V3bP!{HUeuei9wPT_m{OYu1-FO&bBeg5b)+;G{zwrtI^%%N`au>oM8mD3U zJsy@Gf(T9WZckS_pCLUNW*Qne{tvsUO&>>a*1V;gAY6@SMXxVUR4%0|*OBhuZEnZL zn(X7W_ng7m7Ynx>298tbu{;LmSHs`Kjv(N2G&Yv|bBoYq3r}qL%^d;MgC7x2I9D%B z;PVSjRS{ZNcvI&h`9!)3r&}$|H=6<;Cwe~H5%dgve7YH$T|Uizp<%cDr6#EA?`s-eb4L9il!MMa#-5wS|rs>y%Ko#=!s!u(m5FH#O7 z#W?Ng4%C&;^@lpdyOpFUn7o#?I5n5F&Xy>YJ=SJ=km2wdgmLU!T`SNjS8eYX8`4Fb z7Jt)iGA0A4bC1s%E_#6}_WW)FwZ*nr!=oH4m9mZC%_ihx0CO(ebDgmqrlhnI@uPaZ z%{4?-me$P6x3`9Eqv!9jVRoax|F_v_WDxR&9c)lp?@?j&>A)QeTIJ$>nyWEYmco%) z&cWPkrb%~}yM~mQd&RWmm$lAqa~`0D+vQI~NBPR^wNB4P`H47Nls7CY6X{&x8NBui z^eS0uhf;-Wrbio47deK~J!-5PH->m!v4IHVDFFri`k)N{lR}EXuxv;WX7C~UVFP={ zEM-kbt=_PEQ#EwNRTn29@XY@NbuDpWIEGZV_xTbvhEmMr#Q8U!JMG!z9?0X%?IcZ{ zFg1i%Rz{|xA(-_?GU+qu&(b8D*xt=c=aT}MS0nlZ{=DpJ2qPv#&Yx=7H)jGU>}cyM zcz=4aC+TiX-OTnY2+P%_R&FIj^mU?RC+2=}-R}p!$_ca|*^^CV@D!?wL6TmcHePYg z(#OMLmJwjF_r_w$1PYcT;W|NLFWUh9mf^3H+LUTLTo3Cnv%;3Pf&|I-+#0Ld*eW-a z_NX_1NDXCgoynqgC|~nSLmSDJf)|8eS!)&corxx@8t(a7Z1!BEXpd)?`PI@5+nn;} zN1Dt|_~>Ely6;zAr{pUFmT|yGw;3Q;clrHZ#MC9Wt6b&e4=9Lqrk87W6(D*5}_;2!_U~3Z-22}Js#K2=>q+w zCo=hT-~Qe#h^Rv@T>@uCNbk z>=k;Atwi1{^vXPI$-tbx#g~gdG1KG_5;DY~CL`=Hhd6gglS#ugi|S&jpoQiyXCtyP zH6Fhc=0m!xyv(oNfSR!3H*sGNUe)Q+MV+zyFI$dvVhLHq-pyC0M77i2$db0e=i^3I zb1ALI!Nf}R8EvO?Sr^fu?vUU|T@^0ci%3-)@;Ik6ZK&mw5aFdT2t0^v3#zrLZNcJC z`8}q9@_$ck$bVR)CJW$t4>prD3`nEL;MX87i4Q>s0-sC^i*&-fLluIx)6aWfbNE!5 zCF=V`=HHvKGH`KeE~hf+BA@o!*YX#LBgu@@b_6?>puX_Wa=Iih#o*^qf|x0Dn56tq zazObO=&_)Z8}J&F?DzIz-vFNx+VD<`A)?a!2_On>iVJuZ#|;Sd-o>w<)vFZ#a?TP0 zvwXAedrnIuwY^{j7VzT?)N&!!G!;OE3`GRuG*G-2?y+H zV0Wv!0piWP6huG%F`OHew`D5EwX7Ss!wQXiz45h~O6OGnJse|mbF`2k6LKlAVTc>_ z2JWp~xa}4a>~49$KATBN-48q;IWj)AwQ4?lL%!mYZKP%LqX(&z=suLjUY>aOE}gFC zVNsoXRRLx)op@UC@R4yPu&PB6f1FL^G1akHfLg%OXr;xTIX&llkfKr#2nM4nIM!7` zA+ln7j-pL@c^tTAL4AQL`Z5D(vM$GqObuF+)B@aaV4@CGkdobRZn!s*RTrx@^wyo* zAN?}1%#y+IxJQxTmpY+(wiMd=EFh7Lib~73?q%^H)pNxNUrSd zIl$Z4m*A7@wW4p%5KD--SxWCL(p$9Mep;jod<0jmEK4= z&wh0P6P1w&srvhR7X3Y_Ya|_cKC8t4*4Xl!T_r>v7=1wY`983-IUIAOxbmsOE()VG z19E#RoZi~ z^CnI`Xx|eY-ka@2x{KK3W@%Qov3xHXz_#k{a`9BFlK(XHqfRjNipj*wHHIk)dgPD; z1~Odw3gM^h%+%i-&*#e%Rv3@*_yW4g6OU3Tt@_S-Ujs&%u&Zpw+&1-yw$f$;z@yEL zp_sniKF#tLSOkXlwB% z;ISIE6vdG88SFXH^%9x6ck<_gxk9vVKC0ee^%aoZ!#@|izrek(5QOh}8^~M+`^pSv z@gD=%nO{lnI(&U5>L^P4Tr-J6p>!?wJkF<8#QtL$dQ5tJ*v~yoF?5Ir?k+3_&l)jR zYkwH?WGPDO;%8!FzBqbJtG?L8y+FN}p@RxXdER9Ss_ow(G4{L=dkj*=MwN1R{f(7< zmmF8JF7{0Z?JVE#;{nA!aI>!@smY}fHQ@{7(T;?3kj@o-*Jk)ffcn#c)`7Fagi=8w z)prKr5ZUk=2l|V##bC#zU{pVZmsugi?=yEHz5V+nl49b47sT5FQtq0s#$NV1gnxmX zUcc9UTk@;>)!u;lv-?u0LDp`tD-CGAd%TQvW#HwD<|Vt2R~S`b;9!k?yd`-zLH@H` zd(oHK3Y@Uvb6lM;N`W>snv|8I9KopjKBVT7t8h_bTPX!3Mpn?^(rErmE(&n3Ug+&@ z=SL8>%ZfBw!vn6#B91l&D`aCCb?u}i4i9EtRf>g0k2R1U=Bif#om$m^@mc2$v=Qq@179J38JKq5OD7yY!pRxO)$*bi`?#SD1&nQbUA}IOt0ad_t7M< zg3ozE1A<=6yv@z-4ROT)Y>Q*n=#byNFV4{?JbwQBiLCH;Gz#E;WgUHil;dRMG$64e1HY4>iB$hbNUQb zRg@Q~n!`r`VboA&beD-nxQPfpG?Jx650S>3QXY-#GsKRphk^|88McU2KEKvy%OC87RcED`rM*FzrR=J==Ue;e`BhCmy34mS|<2H7^fy9 zfwG(YQ3x-WhFBKH?`?o4&ONr@AzD6Vo)`lX1RgTfuyYK)khUCC$>shk*koVhw{rpM z;?t>Yf-z`yP(JT@su?)!X52n(lXANTo7DGr_%(M`T+*!fyLNiH>EX+jo8XLUiAJs8EYXyr+ommaPa#^`;FwNaE! zp^MyvzT8dC!qAs50r~H)39m^N6KYYUl){AbKhN|E7dM>MqE%c5EE$NQpfPUT#1&GC zJs!|3eDp{r_EI;sb)Zf*VlCn_dr?V#bStB@BrtW;b10iHkLFh|Ml!`lcrFz-Ab3U= zbq{lUM0kv`<(x_Pn@Ahh1#S5ka4e6Z2iwDAZUknYxZg*Tzd8m!S2Ddo-FQj=C!Hyz zDkdph?@2leT-QL~P|m<~&0@(8kC& zFt`!)906tsjk8Tw>4;{v*~0gQZ_1|km2T=5{#E?^{3ViJ+O8f3w0sk8^(CK1YcyRS z@{Vw`i8#WFJLkVA^ZE8h9v)U$oVY0UEtTR3`f#UNnc#@BwbB6m!U5OicekBbZ!W0r z)#W#Ji-XK8^|bE@;M*R@`FZ3# zCrf%+>Z8UeLVmd-^=RST>y)!qpj953l;)N_s%zVH(~d8OQh8{_Y4c7F;J#(*##nP) z_KqzuAM?CjtOe$pcu5p5?5l~cV=;;fWn4zNFtE?^6iT*F5>gKyu=B-mqH6BS`nkiw zZYo}sDs38G)T+-O(jUkksHRW>al_J%%jjDv!d_ahS#+IJb5}YifgM161ZGbik*j<2 zQAWXcGN8p8W6g#34vL-Dt3jEc3gv9yJZ3`x&CFv4FU^S{yy$>}2W=TKjfrldgt+wI z_ZjS3=%=NE_1SMzLNO_Ni)`oib9_~HTO;Y&m=j!38yOh{`&hL*i2O~WF*IqrEnB<3 za3y0+U((+%5=Z?Kgh(&sc9A;(al(EHahWWcV(JQGD-l=uzTPyzRjA{5Jl!46$@0~- zilM0pDI!j`1!yt+4xZV<;1K*+jYo`qXVjmoP>r{VA&E!zd)*5u|1hBr2Dspf>$`kj6aIL=`~L_R~{3R;mRF) zmnX4(rr>PHe8ZX>9M?Z3g9Mc-BXOX5pqugz+R8fy!_Uy5TCz#_S?fu=xc<^EB3ZNj zN(!BF#*UhSV-#Krh4_=|xmrx{nmS^%M$3b}X*Hhbm&zZwekcLS$bM)6e;X>ZP#e8x zUGle;-x-5?t&^P1+RWFSEeW{YkF+Wb7dZowTRNmIL**DB0jHgZ-q_+|$b9_c0*Uxn@WP@{3QP_pnLB`vx4IJwlF@rZE6d7Si? zq0H6Hmcw?>yT;V0d+kZr*E-3@{4}k6_2KaJlIU7%uKdYkfSlN?G*-K5ebJ09*{g0a zPhc}stMxi5bIGM?1jG)bK{#l(+OO5*AyYV3jxU&% zDpEK2VDu@5fb?9kGvR~HgRr0*;l-xzuKw7jb)hfD4AgAkg$96Lc5il=!A@lj#WI*r zA+yKRkiE5|Q`)%_Wmkr5K51|n3pMlC+wAqTcyq@;hV(MwZx$%X36l0^|BML@VHdYk zl!vDSD|QW8fkGM{*)N4hz}OwLVSZ6YwD9$xYifq33-(Y_)~U_*eb864=Dmi3N!MI$htDY!!h5p9ojy&svrDRcsJ~TKJ_oo94mIdO0FoMO z|2!09LF>*tRsVqGx8g@dallPSp{w8<7pi6w5YO6W@jZ6FH!v`B1BFj-A!ZU8zYv^F zQ9YSraeSyzk|u<=>l{Ws*kxh+LjdLZ(Lw=PRMBjtG<#&Y!KSZu6PVt&xamk!G#5DC z+ZABCdxP(khwV(_rzv2v@>99ockyS#Vt%E^7CcaQ;(deELz=*BaT97%8ij2ANIV5A z-Fj|Pyg1{7bJ$qCdYUBiVJgGL3ZS^DU$HlTa9mDdN|iG!RU7w{{}J_fN@;nrKB1Huvoi{{^AwGqIPUs+DefF|W}aYG2yn$W04W01cN zfwq=R&5Y?y`@^+#zR_#LE%t$O<)*MFuSsDIUKTD}Y4{JXX|%;$-(xlo{een;G)F&L zTu>u5J(kFumQ5-5fG!xnHfM`E7auMYsaaSCHd+H0D+bEZgl_@q31npC=3D#b4PrxQ z>yk^@w%yM679KAOZ~n+ubhBH${cNQE_5yIPM|aUW!^$fNkz1JB>FPc_as^M9C1*%| zAJDqe3uO{dm@{Ba=W6s>tOUEJN8jQ4X|{2<)LJ@u6RKlV8=Y ztM7dtWxg0A5@fuRN4<&-E&t1BA%-4k=w7Qd_P6%%`9Qn)%~zYgFK;4m@6J{>cewD< ziDX8IC(n;v>0udkKfB=3?hYUH(7oT~rp*zQw6Rt_46~yw$rV#ZrpK5Wf^Uv(=gk4! zH~XQ9@-<{5Ly#cy5(n19_%HaxUXMSWM>Y==1n&YCW}Q{te=kjNXr#&YCTN;QEfz?l z9xX5Yf{kXaA8~NPkav;DN@HHNY)B}NYTSj+j}?M0e;|UPqlN~U(QUW&2;ReQON_N} zejZ6-G@=D}Zn=Nc;-XP$)Agbgd-hPZ;>GGcfNQY1gI!C$riR>*7;GfOq@^NAI{G6t z9xhR3rnt>iVS@XPLO2N^$QZnh53bDPjsp)G?Y9G76?GLA(DI}1-v9$Yq-so|x_581 zY!Z$3NyaxnSM7TGYA^g#0ib&cT+N22{nN0M2rrBZ+g4(x7AV%(oU6IpPiAD0&)*}S zWxtIM)e&+TAae2^Mtuia+Ky~Isg8O;fot!b9AQrYZFbz1y}JmjnBBt~h2z0By>?(@ z>iXv`9m22*fcB!w@ML%FR~7AM-8c#ntpLXxc)FZ#EPAEJ>WfoVHxdFgxROH$>>4a( zNRY$nD>v_rSX+F)txXCA{0Aci5#4IPE`j=#+~#M8S_eUh{KCdbF`r@E0x17Tv3Sl) zyCvKMqu8+3L3{WvOuVY71fMoSeapcSO8$vnc@D@=V>UDA@*qNBdmO**66BLm+|x9d z;g^V+B9tGSG6-l5k5CEJxZ(3XoFH&;H!CwZo6XuVZDnl&j-IV`t|(jFBJJZs81=Fg zQsXT?H>}RxFtM=~%x+WL^we^1@VNT_pm*9T#e2`r$i{r>hHv)_F$nm1+1U+y_&=jS z5TVCd_g|NjVKeA&(mSliBtGj$Mr129o;HjBe1ANiCD;@>#x+ zbtLfjsT-~Ee6gi$K)r8^nkiU4b?+EGJt#NX)_c?Qq8sX47jftXzk~(sCx5gw`|1zJ zi!g4bOhUA5k(Ls#sEbd6UTx4^;B#~2ZAmi*!oZ@*`|_hPDP8mCt))PZe$9X*x$=ZU zO<~&v>8eK2!Nf6xwBB;;giCdvyP}zK8sj~&A1m%Xx!*a1SuNFLa`5!V=-n{`Y}eM$ zQE**Xvb188?cseH7J6z%PN8k@&+3?Thz2chQ0a~>hb2MjEH;1?e|@@xE2hm74+MD0 zs4?z7B6uI~xEZXD9Oqg3bWmnGkro55P&nz+(&n&2z@2 zlgz|7WGP-0USXFWDCFF^-TJtbPB*E?Y3z)imosp!#oG#!BR(Jkp2FDPla*^hrVhuI zv()|(tLv6sPEQbaD}E*J#kDJB$Zc14z1+R{!uBbB*x@Z*nKlLR*ord7KFjU~Y7 zAeANqJ-b@jN_G?F5(39X&S0V}qn;A|J&MhP!Pwoc)AXTkMSwM+I~`mt%&Db(u~1v8 z!PL6)R-oP1B5xwY+n#i;ebB<~b{2VbWU9r`vGK#f;&0xg*#fwsDt+}rX%s_&6Om>VG@$U}>fYM0OJi0oRr3*)J6Z_-lKNRw?^qqD~3WrkiWE zP0jCW5!7hU{dC(nO+1(d*B;n9*K__jz4HS0J;yPy+@Rs7>~%u?a{_`=YMcEWYyAWv zqe4QFWo5}wWkD_G;QLq`BR_^`P*R^6Bu|}%Pd}86@~5y%@`kKTK2kTIsM&5IVGr4Y zueP+yYbtv3V*M+6C8)i2AS{-mOpO@emG@7RD}(>rWaxa=QRqO(OU);KOp~@Q;3X5N zIoJ@8qY7_&4T+Flods>zRVTSAET8M6r{6<_7Y0ehJler z9lrv0NWMD%=>#x}Ug200_=ID$a((;s(4jYQcY8Vizh+CGi$>^pMtpfIFhW98J;!0E zpaFIiFhSQFg(zZ-7rwsHW@eGW=_d#R=!?^OABp5(SZ;>NF?^SnH$LZ2Hfk>E$oXeP zF?F&7ijO>RXEPaBN5N`5S0+X$Z5h}kazY$NMgzDH3zi9U&fz0~gLn9N>4Dhd8m*+F zi3xFJMa=pA3)LNpbJidP%_=oGG`uJ7YPo;MK=AmQS-Tf%FO{}>Xwc9xUYiZyMn-m7 zfBd37{oFuy+3WR7sY}O3KWvpV!N90e_D^qz>{`t%p%4*PvkhzUP`G+kU4{kE>}7Mx z`RRi0erpCOUu0Sst0uujhCZxWDc_O=bN>65ZVt9Jyv0mWonE)@>=v3WyLtGr(CiPx z??~>QwV@r^^)tT8__(_$dKcKzr3mT{f08qN>|?rQ|J5a=|LM22Oqfh78n-rco~B2O z=V!f1z({^q!{(`6ElMGzW)7a|Ym#NNGvq^G~2Fz42IA?cKS* z?W|OYV$Tj3qLK2=^L}SU+uhJGhUwu_!~%_@s7osIX8&W%(Y7h}p| zcSG5Y5CAu6t~(nTS1?%5w*SV<@>2*~Ij;S87*US?JB&IM#8wPJlRr3Hx{D@m*6Gn) zqZ-S_$MJJeI9|)@RPTb^ETUBKAirHKxzb-mcfyB~vIr!~ACOA`l{5(RC{j?h9Fr;q zmOo~9Ut6Kvk(;I2Xc6&hHz%gpXa&*z$-*blHEnBdn_mrNV$EzRKn|fSQjE%T*f-Wx zVsPwx#$S}h9$36iVQ2f$F>zzt)0!$;Xx?jX_6d_4Gju>F*<)y^oj%djK33Rz_&Qu+j4ySfj z1`I4fHCNcq;IE!CM1Dr=NkM*g*x@6FAVU-+4jk7lXjIglRt>yAdMVEXG;7YGF)}%8 zIRK(=o4GXv{nX%BPHJ-U%9+$PEPMGy^{4It(G+fk zl=SlnMcyQ?tVcW!lCMfjNWSwSwRzAVJHI_DoXgdMOqlpIf((s`Dtff)|Li6X#d3du z($BPKU}0gk0=T>;QJ8-|O`YU%@{yYAWV+FivgwNj~A`C}$@A)@|mrhmCP)I`4V7pz=91|zsGwT!XI6${t5UijVH zXbVj2*eq7i#2j(Ova!A-)G*NPCbioh8(6*EbE^w$YWyt+-PTmVs>NGzp1N`ct9 z8y2xjikpCAuKSbe1@?1SiHxNeD8^Xf;LKz?v}~n^R4~KMAV(v?O!2OQsB==n)RU&( zGBMQoi5+i(dgO?`LJEKJ9TZ71u2cw*^cGn=)I%OD1(>{r-3w!rE++)!g~bPcj;%we!@}UAs8@V%5bW@W|O;H}b(b9k;xjPyWXxC@G0Rr5qumq$V^a zuG!C__ToU6mpF}m^$3jhtuh4wClzy;6ieokSg{mKanrT#Xd6KN7f*>& z-y7Npnq$MTKC8 zQ{U-4idN0}yNxuL4_b-n2-$0W(z$9zG7QFyoFxxCXD+r6x?>x$UBFVx^2c-nOEMAvqbMu66uz_b&UhXwUZ7X4+TxX`^W>x@Vh_UW=-*f(bP8TVUO)kR3p=P_ zEc7A`vIU!QCenHdNQWDgldkRD1k}~eBNav#m`O^>mQ39qZ%wvyI^S~hKc&O#4TvGN zJ%i}WJU_z~zejQJCi|_)T~pJY;@JNm*hC95CTC(5d7KEo$lIVDuxE$H>MOX9e^zTg ztR1$~-NuBMWS2sr?6xZ&mEE-#OGJ{nSBl6l3${@eD*_17)YwkQX|H0DN~n3lW?BP@ zMgIayyxA{ME+Y1(5)L9F(u&(pw$MRMmkJK@*^xVpJRkStUlq6n1Txl>^U)=5WI!Xj zIE)%ZaO}7X<(jD_aXHfQVzouVS{9j06IyW@45$~#hBqPzbQHy$nB}U$!2VXwpxpjN zD5&@rA}evAyY4LBS}^U?+QZ2?IO(<0MMW2XN5*^G8BvY69I=-h@FF|D?iKm)XAzMr};I{iXMn_8v;&ojAeAW5*HXPkpp;yjVCDRU}-TOBIxATFN+u_QC zmX6-$k*%Si*d}fHaWRs6_iV-h#{UOKYGy{I`<8N_FRLAk*_XV-eBpG4F+|&$5MWYu z**S}wNiP5AkOMFCY>Ox;6U{( zo1W9)hwb1Utr=1pFGIaS@5H_BMYUv{>-Dr4Lt{P&m9XNu=3>ywxZoEa2d7euyR-+} zNTFRPsm+D56yv3#PHQDwo?a-D-UY`{Nw|iGx{P~cC1-bvSby)PMPbn#Pzy5hDZnb~ z+zyO2kZ#_NEeTGP`~Db4W_0KdjRRJ&SIyGCC*ndc85RE>w0l&>oL@4_Yok`1uh#0D zM4ckFHi;7zPBL$|j!FgyxC0q3-1Ma`Yky>Y71VIO#=Ry)$fwjly6c06B|bZzYI8H# z|8jWNCH8G}&?2KT(9-$<40tH!T(Mn~wFGHs&C)6;#Z~Hv)+jx1emzWb-g|Fpaxvb5 zrTcS8$=ec1821@N!zt2!KUFabu?Id7Y9@F(TCr^0ACVv9t?idal3ivNpf#ClqMrt? zni^R*sbm{m*Y2Nd^YqUaD>AZ9q`g7Xe%tHo6d-ewtOz#A_tyD_ctfIadc;#YCRRJk z%qdn$2WuwgugWODm6T>T-j&t87);rp3JnJb2gW3*h^gPu6h5SL^f+sc>!Dg$K1zRR z^=IO^z7w+d({{U!-kPuXM_tLhy1F{Nni6Y$$nK69MJc(sS5ugjbK^x#EwP&`AYT*N zG(iDg(;74LoKxMfRlA{Ezcrc)yaA%9iU212Cf%1-`r|eg)B9>S4WYP1{)4p4tAtns z-a`RlL)yV@SxC+pmmV}Ds|2ko zr-Iz}*A{r)0X+EcEBB&SZ&iR3ME7B}`fPicaqT-zQvV5fT~tGt8|8u69_Q?*CJn(q z{^~@qVU`Lkf3su|K*OF$U#5_klpAIkOjrmwp9W97BT zNTteUF-a;AWj!#0LTR2D9=3^5rrI`*-bQL|N?jBx5#a{|V{o7$#_+Hdo9C2^#|rjU zDuXHB`F85t3415=Ol4>;*FkomaG5!L)hgpusv3gM7GtLlQ@R&e;D=S7iLpa*=E_ac z!LH)C8d)ymzz{7^!@NRmk=gAf1nFh2=H1`Gh72+U79u5az_(|rA)RmJd|U~}N(3?| z!LaF_tsYq4Mw`u-dOqY-SL)WzioHIlR&#b?BgeLe--V+pn88B@S4At&4$-+^wIHgEs@G`TspK?lW0-d^rf8K zL<+|FQ<6PG&FvQDWc<|JMHpCh!$oz2&+NtoD^+B)7o_(p@_&PWTt#z~)4*v*7Wp0) zv>9lXhBx~YrHmXy?fykq8@@>-ybOG~u_7jpJr5a@91t9zBDno~W11os=7btWp$8ji;WPI{V7XP_q^%x}p9w;bvfOvpOqH#m0oVMue zZ%nkUNJ!mk?kvyf-+lcB%5OMbZ|3Q~1w$&h#hx$VY~n1nq_HT{t}v0rlyzN1Dz|lj zWh=_$JW*_r3vzr*fu9de?qAYmBMOWF0o9$-xs8i*s+j%j*k4kT9XcC>X=3?4c0zS`4%>@;#|{;C1>*{2`Y zTDWsM(z*SZEOSJZ_4lW|Dv+K{$l+%vqk8dQ2k;UM%zUF*c?075trbw`|1Nkg_!n8R zX{^VH;y^+_W1@oYKLX9HTjr$wgc|~Uo?p3WQ~X5@i_enM(&PePpEmyFpx`laV@!r+ z7o7<22TU-3JlF{d5(!re4_nk+HTX{GpXG;7?+P0Utn`b;N68T z@-N3J1jgf;?}3fkZy{15CvNX)08y^lsmY7RLy*)T_izGNDHEjXNv}`yT{cn=@%hK3 zuPYy3A2g~B(YO@iL~hfVav|!OWwG1e7`08&eQHqL>kQnZ?daxBu^+TygO;~z-Mv~7 zwe+6vf5%-zxvu3o-E0AI8&8WL7r10au!8w8ykj_P%U)tl@DE@2KT)ic#DTUPSrUIY1zs3l@V4 z3lHyu#c;IxAth#8GgtPnTgM8+(iSQ2Pc+?kL%cp$1InY{e{D}I^DiRV0c*}s9UZ2bkBRjug_OI=jQ;iZDtx%!Z&~U zeC@edP{N&tt=Q6p9PXQEbkRku$DrrdBIJgWRFK(_2Si@DL7q|Gskf6hk>#WVSD0{!wmX$Hv!hjevqzB$Ko&e-hXLL zevx`aI-ea*8eYSlTGno%Ie!ON=S)=%+DiIEiO`h5X-`VA^2j$6Z&;w|Sc7Fbjp5j8 z)G#kFxu4Jj|5Csfs4jT!4JGjJf!J1uhB;jGj_Z1V+B%&eyPFoJ)Wt(d1m;pLjq~Rz zDq594-JvwgG}frqRiot||IWb^<;;{YkE&R5^$$O`K5*;W=bX2Vr72{4D0mXKV-hre)vn_X^VB_wS0q>`-I~VGvby!?-`Jgef>A=lkoU zh%uU?+VJpOyRw?HdDSHBD!(ak-Q`aNsUj5XIlGScp=Pxdr{#|4vB{+_?{-A%Jvlge zV_@-m>F*JiJKUL-v-smP_#Dr~*~o@Qkv7HYqmi0}FQAzrHZ!jjmA9e`P(s8k;+5wo zsw{d6Q>@Lz!6PqiKB0>x!0IOflIs+}iLaqMRuY-j4pY!cFANM0*WdpI5E*eyJjGf9 zsSXckK#67e~Z zLDRZ)Zn8vrf?$@(Piyf*H*s~5BrjO+buGUBU4VD`5=dv;8z1x3c#0!T53JVdWd{Ik zGGC<}2S}o>LWh#d?>1!2;u-OX3`9NQy62z(;Ov(-aAm%CN8JMtv(BR#GN#Z}yT9ZM zFj+$aMY?dBjz2`HSvK^?m7;SKXp&0xmq@+#g9@r&SuAbhAyflVA1bh8R<}zxwKbD3{mKMih!{_}>{X{K+X> z?|l^v>hU?pwh_{CuguKU{qUO-5}Yt^{roY~@6UJ58fJqvLT_guXreG51reQ0n~h6C zQ?!vy=ft&q$d2qnM{IXv>;Gxz%-^AG`#&!0FqW|m5yleAU}Ol{#=hl788fnHry3f{ z-e4FaQ6eoGOV;cp#!f^bLZPz7)Fgz+?ap($zsL7)cz$_)nIF#MeZ8;q{2X)5@tNy9 zUvKo-Yy`qWLm^^sD?lgwyXeQLwKmpPip``UQ}XFIxoQcqzrTn$l2Kd_5Ax0F6A?}K zk2*H1O9mHeU#CUKG1emX?Oigo@8k=Q1HOE+oFo$|GS5Ev3J{NFrs`^OS_8j0lsUA+ zBy^vMV>V(LpP*wF_QP_Tn)fEF-Tz8p=P3Z^b%rv2e=COU{{C$#zRJSV%8cNPZFpkIbC-tu=^LNaZlf8l+b5FXIxrw>Qgg>gr((<-nqF~GI&V#=j zg2vPKpVO>d&uCYpRacI?kE?I`KYf3**$Hw%IbBjOk5FY*V*988^ZoP*=8%w(v54aw ze3F%RMmCw1{1={8UHSTO^)=VgR1UR}uW0WDj=K-b^8|Wz=U2PSCY-lUt=IbLo+4It zb=irKqfE5ECS>Kfo3!$Aj9=vAqq1)^baE=>gmz0JS?x`r9;SC2Mi+ZZSOs7zy z&(i(w50$4*bVvUI496ytsfs#Ew4^GYhah-<;N!1;k24FHaLvX!g+`3smRP+7qM~Y3Vx>}za3mYX} zXGR6jB|8`rbh}Jivz~OM#sr2jCbQwVz^P?l$A!g|sPBSgrbI-qJ)d(t+t#BBH#yv? zPz}AmtFs#}Gmc(rGDzWwo6z@;(`KFx8muM!;yts|4@q|PO(BGH#Rl|qCqE=gcouJj zY|Nzner5b8r?j~_`cG?fb1uN=%*9V%F8b6KB}jaDUpJu>K$%6#>ZrFF;r0&W@;vm- zYrYm$mW%9zh@9Due>QygzR&1Q(>$U{A~p@B{`*L7jT>6?WRpEdE!2Zc+DD^W5VZ9u zhE>at7KT6J;PO`Kt}vgFAJ%_4v50570{bir>A%C6%5ZM16MmK5H%BAFAbfl!B5v17 zpCTE`WfBecH5PR-U!aHY*FM$>&MlH#>FEcT#@gY2*fc@g#?*rJ-q^{r;lg~Kvs1S7 zzMKjHrHI9k$?;_|Gt0!NxT%aW5AR==)PKgxjI9Gg*vucCJb^~vy@$jbadL8^33G;l zV?`;aa@SlbhJYDt`!yYezVbGA}G#zwm z0($2j+{LK0x!3;CdK2SA4t!3!j=4qH;S!k}%fV}@2V9_#87nE}>2TGL@(<5m;azUQ z#%`nEM8jrUXU!ExOsxx9I>z@d41Ajsxq2(Zz*e zqU>CP_3O9)=|~q6cr4f97WV91$t`c)tq*?r#r(1!Y00nnSqY!E3rueUz6MqE#C%k8 zZ=~btXwMGcJ81aVdMj3GY_L4^c~7zGCh0X!w51wwyZDO&{k~&Q<=MRM*Ob>2->5~d zj4KP}Q1lk|-T_wo>**`tL~1ar5k~=Fl%4B+d6eB~xebxMgY?|i7|?(Q48NXV;<|ca zkhc9pi9hl7==<|+7*!sF3Ne5~J1(C4Xop(1n%9+q+3zl7Ie^{8{|AECEpj|~{C+OI zLI+JE3eeRTCSjB`UPf`XO@3tE>VgyYvk zHsZM|6jdV1_`DZdkGWq>XM~U_zyoUBHb<@ zmIk}gpCOgQ`vsg0mzei%DTmx6dw2yUp*~{;Wic<1NQjS|OPr4QO}1_QBb+$6@w0iA&(6%>qjK;KN^agaTyc zC%t$7u=7dUfPXyH)*mg_(;XDyz$?;p_QlR(K&g-Z`RDKARg~R>dh;3+)|<;C`f6F1 z{inL!h|d%25kzQZxeZ>le2&oCPh_^QQX3}z#z0Kz4a-aL!Hf#pWQ9{k4U@X}0L)TB zOiWcT>X%SQ`s2^-&RDEGp27)%AaGneJ3BdW!-j7m*^aQlt6G`7;xlVv%Q}C@XSY?C zuOJ~6M*U%)NN(5U;zI5FSVRHysCSpyM*5kNx67_a#(XcED9C17M8#?^jTkwZIXb(ET* zWmxf84k4}?toY%gi7%|+^en-c98I-Vgf{+P=)!GQDYNS-DHEzAZ{p|(o1*P|mE7rY zS;N=RJTeY88Eg&sXFM(Y$|e`76iJA7xaS=fm4Wh#vdO(Ol_zlSr3ORKhRP!~Yh1_A z*~2L@6XnZ0DyffztV%EK5dc!$|IXr;n*uC5duU)#_F-+vLa(>)mEk#*idNdb2deQ}#;L4U#tq^L=s`a^XV zjQ?>j4E@8TwzPVWqfIm#q_{MYT?F8iQv&dg zIt1E@1<;{RQ3J)EBt==zw}&DPBoH;GxXAn~Y6T*{ggO-3uXUi<>rnKslcpRHHKn_p zIuyCZ`e6KjuzP#@|M-<@-Op@q)@@ylguMAo00AtY%|bcxh(U|%AF|n~*U+L+<28SU z7k7~`A353*cnYn>tc326sXGnXE)Iug@`uxkUeV|ojLf$d+A^B$|d1Al^p-vRZ z{fKqg`xOom*^I%#BAbu6tb-m|h3TyvzQ%CN&bS7#1zT5%RfZaiuzZ{UjzdfmSZWZJ zo}C|eb>K;tS*MKg^@f$wb9mS!Y*b@Q44$OHO62KCVk>xX#1BLFy`gto4{FSJ!_Bzb zn?#p?f`_$m;`scAx<`9>=9Z`G4T)-jmo2fJOImu%AAffc3gKR4aC&;6vrd5J3Pg`Y|4c29x6WmaK5vF>Q7iz2;h`a-zKp$FJYWG^F z_5mxg!KJ>fW?b4%H~X0-6KMmAuqD8&7NG{7Ng9b(d0j&VxJMpM&TVc6 zfl{+tZq5y2hih)TYi#2j3{R53B&w=G?unh1;n4n`anVKTjQ(zi$|4?Mlt7h2#($o!p57viX<= literal 0 HcmV?d00001 diff --git a/shaders/drawable.custom.symbol_icon.fragment.glsl b/shaders/drawable.custom.symbol_icon.fragment.glsl new file mode 100644 index 000000000..0f8a298e3 --- /dev/null +++ b/shaders/drawable.custom.symbol_icon.fragment.glsl @@ -0,0 +1,7 @@ +uniform sampler2D u_texture; + +in vec2 v_tex; + +void main() { + fragColor = texture(u_texture, v_tex); +} diff --git a/shaders/drawable.custom.symbol_icon.vertex.glsl b/shaders/drawable.custom.symbol_icon.vertex.glsl new file mode 100644 index 000000000..b912f515e --- /dev/null +++ b/shaders/drawable.custom.symbol_icon.vertex.glsl @@ -0,0 +1,69 @@ +layout(location = 0) in vec2 a_pos; +layout(location = 1) in vec2 a_tex; + +layout(std140) uniform CustomSymbolIconDrawableUBO { + highp mat4 u_matrix; +}; + +layout(std140) uniform CustomSymbolIconParametersUBO { + highp vec2 u_extrude_scale; + highp vec2 u_anchor; + highp float u_angle_degrees; + bool u_scale_with_map; + bool u_pitch_with_map; + highp float u_camera_to_center_distance; + highp float u_aspect_ratio; + highp float pad0, pad1, pad3; +}; + +out vec2 v_tex; + +vec2 rotateVec2(vec2 v, float angle) { + float cosA = cos(angle); + float sinA = sin(angle); + return vec2(v.x * cosA - v.y * sinA, v.x * sinA + v.y * cosA); +} + +vec2 ellipseRotateVec2(vec2 v, float angle, float radiusRatio /* A/B */) { + float cosA = cos(angle); + float sinA = sin(angle); + float invRatio = 1.0 / radiusRatio; + return vec2(v.x * cosA - radiusRatio * v.y * sinA, invRatio * v.x * sinA + v.y * cosA); +} + +void main() { + // decode the extrusion vector (-1, -1) to (1, 1) + vec2 extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0); + + // make anchor relative to (0.5, 0.5) and corners in range (-1, -1) to (1, 1) + vec2 anchor = (u_anchor - vec2(0.5, 0.5)) * 2.0; + + // decode center + vec2 center = floor(a_pos * 0.5); + + // rotate extrusion around anchor + float angle = radians(-u_angle_degrees); + vec2 corner = extrude - anchor; + + // compute + if (u_pitch_with_map) { + if (u_scale_with_map) { + corner *= u_extrude_scale; + } else { + vec4 projected_center = u_matrix * vec4(center, 0, 1); + corner *= u_extrude_scale * (projected_center.w / u_camera_to_center_distance); + } + corner = center + rotateVec2(corner, angle); + gl_Position = u_matrix * vec4(corner, 0, 1); + } else { + gl_Position = u_matrix * vec4(center, 0, 1); + if (u_scale_with_map) { + gl_Position.xy += ellipseRotateVec2(corner * u_extrude_scale * u_camera_to_center_distance, angle, u_aspect_ratio); + } else { + gl_Position.xy += ellipseRotateVec2(corner * u_extrude_scale * gl_Position.w, angle, u_aspect_ratio); + } + } + + // texture coordinates + v_tex = a_tex; +} diff --git a/shaders/manifest.json b/shaders/manifest.json index 331f3eac2..0280508b0 100644 --- a/shaders/manifest.json +++ b/shaders/manifest.json @@ -174,6 +174,13 @@ "glsl_frag": "drawable.symbol_text_and_icon.fragment.glsl", "uses_ubos": true }, + { + "name": "CustomSymbolIconShader", + "header": "drawable_custom_symbol_icon", + "glsl_vert": "drawable.custom.symbol_icon.vertex.glsl", + "glsl_frag": "drawable.custom.symbol_icon.fragment.glsl", + "uses_ubos": true + }, { "name": "Prelude", diff --git a/src/mbgl/gfx/index_vector.hpp b/src/mbgl/gfx/index_vector.hpp index b42b63321..4f67ab053 100644 --- a/src/mbgl/gfx/index_vector.hpp +++ b/src/mbgl/gfx/index_vector.hpp @@ -108,7 +108,7 @@ public: template void emplace_back(Args&&... args) { - static_assert(sizeof...(args) == groupSize, "wrong buffer element count"); + static_assert(sizeof...(args) % groupSize == 0, "wrong buffer element count"); assert(!released); util::ignore({(v.emplace_back(std::forward(args)), 0)...}); } diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index 3be534149..c46069a37 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -63,10 +63,10 @@ public: v(std::move(other.v)) {} ~VertexVector() override = default; - template - void emplace_back(Arg&& vertex) { + template + void emplace_back(Args&&... args) { assert(!released); - v.emplace_back(std::forward(vertex)); + util::ignore({(v.emplace_back(std::forward(args)), 0)...}); dirty = true; } diff --git a/src/mbgl/gl/renderer_backend.cpp b/src/mbgl/gl/renderer_backend.cpp index f84d00212..1e88e1684 100644 --- a/src/mbgl/gl/renderer_backend.cpp +++ b/src/mbgl/gl/renderer_backend.cpp @@ -98,6 +98,7 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::CircleShader, shaders::BuiltIn::CollisionBoxShader, shaders::BuiltIn::CollisionCircleShader, + shaders::BuiltIn::CustomSymbolIconShader, shaders::BuiltIn::DebugShader, shaders::BuiltIn::FillShader, shaders::BuiltIn::FillOutlineShader, diff --git a/src/mbgl/mtl/renderer_backend.cpp b/src/mbgl/mtl/renderer_backend.cpp index e65bcf079..a7351175f 100644 --- a/src/mbgl/mtl/renderer_backend.cpp +++ b/src/mbgl/mtl/renderer_backend.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar shaders::BuiltIn::ClippingMaskProgram, shaders::BuiltIn::CollisionBoxShader, shaders::BuiltIn::CollisionCircleShader, + shaders::BuiltIn::CustomSymbolIconShader, shaders::BuiltIn::DebugShader, shaders::BuiltIn::FillShader, shaders::BuiltIn::FillOutlineShader, diff --git a/src/mbgl/shaders/gl/shader_info.cpp b/src/mbgl/shaders/gl/shader_info.cpp index 637c26db1..704e91585 100644 --- a/src/mbgl/shaders/gl/shader_info.cpp +++ b/src/mbgl/shaders/gl/shader_info.cpp @@ -48,6 +48,15 @@ const std::vector ShaderInfo ShaderInfo::textures = {}; // Collision Circle +const std::vector + ShaderInfo::uniformBlocks = { + UniformBlockInfo{"CustomSymbolIconDrawableUBO", idCustomSymbolIconDrawableUBO}, + UniformBlockInfo{"CustomSymbolIconParametersUBO", idCustomSymbolIconParametersUBO}, +}; +const std::vector ShaderInfo::textures = { + TextureInfo{"u_texture", idSymbolImageTexture}, +}; + const std::vector ShaderInfo::uniformBlocks = { UniformBlockInfo{"CollisionCircleUBO", idCollisionUBO}, diff --git a/src/mbgl/shaders/mtl/custom_symbol_icon.cpp b/src/mbgl/shaders/mtl/custom_symbol_icon.cpp new file mode 100644 index 000000000..4c1afaf79 --- /dev/null +++ b/src/mbgl/shaders/mtl/custom_symbol_icon.cpp @@ -0,0 +1,22 @@ +#include + +namespace mbgl { +namespace shaders { + +const std::array + ShaderSource::attributes = { + // always attributes + AttributeInfo{0, gfx::AttributeDataType::Float2, "a_pos"}, + AttributeInfo{1, gfx::AttributeDataType::Float2, "a_tex"}, +}; +const std::array + ShaderSource::uniforms = { + UniformBlockInfo{2, true, false, sizeof(CustomSymbolIconDrawableUBO), idCustomSymbolIconDrawableUBO}, + UniformBlockInfo{3, true, false, sizeof(CustomSymbolIconParametersUBO), idCustomSymbolIconParametersUBO}, +}; +const std::array ShaderSource::textures = { + TextureInfo{0, idCustomSymbolIconTexture}, +}; + +} // namespace shaders +} // namespace mbgl diff --git a/src/mbgl/style/layers/custom_drawable_layer.cpp b/src/mbgl/style/layers/custom_drawable_layer.cpp index 9b8525ec0..8e3554326 100644 --- a/src/mbgl/style/layers/custom_drawable_layer.cpp +++ b/src/mbgl/style/layers/custom_drawable_layer.cpp @@ -21,8 +21,10 @@ #include #include #include - #include +#include + +#include namespace mbgl { @@ -176,6 +178,59 @@ private: float opacity; }; +class SymbolDrawableTweaker : public gfx::DrawableTweaker { +public: + SymbolDrawableTweaker(const CustomDrawableLayerHost::Interface::SymbolOptions& options_) + : options(options_) {} + ~SymbolDrawableTweaker() override = default; + + void init(gfx::Drawable&) override{}; + + void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override { + if (!drawable.getTileID().has_value()) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + mat4 tileMatrix; + parameters.state.matrixFor(/*out*/ tileMatrix, tileID); + + const auto matrix = LayerTweaker::getTileMatrix( + tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, drawable, false); + + const shaders::CustomSymbolIconDrawableUBO drawableUBO{/*matrix = */ util::cast(matrix)}; + + const auto pixelsToTileUnits = tileID.pixelsToTileUnits( + 1.0f, options.scaleWithMap ? tileID.canonical.z : parameters.state.getZoom()); + const float factor = options.scaleWithMap + ? static_cast(std::pow(2.f, parameters.state.getZoom() - tileID.canonical.z)) + : 1.0f; + const auto extrudeScale = options.pitchWithMap ? std::array{pixelsToTileUnits, pixelsToTileUnits} + : std::array{parameters.pixelsToGLUnits[0] * factor, + parameters.pixelsToGLUnits[1] * factor}; + + const shaders::CustomSymbolIconParametersUBO parametersUBO{ + /*extrude_scale*/ {extrudeScale[0] * options.size.width, extrudeScale[1] * options.size.height}, + /*anchor*/ options.anchor, + /*angle_degrees*/ options.angleDegrees, + /*scale_with_map*/ options.scaleWithMap, + /*pitch_with_map*/ options.pitchWithMap, + /*camera_to_center_distance*/ parameters.state.getCameraToCenterDistance(), + /*aspect_ratio*/ parameters.pixelsToGLUnits[0] / parameters.pixelsToGLUnits[1], + 0, + 0, + 0}; + + // set UBOs + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(idCustomSymbolIconDrawableUBO, &drawableUBO, parameters.context); + uniforms.createOrUpdate(idCustomSymbolIconParametersUBO, ¶metersUBO, parameters.context); + }; + +private: + CustomDrawableLayerHost::Interface::SymbolOptions options; +}; + CustomDrawableLayerHost::Interface::Interface(RenderLayer& layer_, LayerGroupBasePtr& layerGroup_, gfx::ShaderRegistry& shaders_, @@ -220,10 +275,16 @@ void CustomDrawableLayerHost::Interface::setFillOptions(const FillOptions& optio fillOptions = options; } +void CustomDrawableLayerHost::Interface::setSymbolOptions(const SymbolOptions& options) { + finish(); + symbolOptions = options; +} + void CustomDrawableLayerHost::Interface::addPolyline(const GeometryCoordinates& coordinates) { if (!lineShader) lineShader = lineShaderDefault(); assert(lineShader); if (!builder || builder->getShader() != lineShader) { + finish(); builder = createBuilder("lines", lineShader); } assert(builder); @@ -235,6 +296,7 @@ void CustomDrawableLayerHost::Interface::addFill(const GeometryCollection& geome if (!fillShader) fillShader = fillShaderDefault(); assert(fillShader); if (!builder || builder->getShader() != fillShader) { + finish(); builder = createBuilder("fill", fillShader); } assert(builder); @@ -274,15 +336,94 @@ void CustomDrawableLayerHost::Interface::addFill(const GeometryCollection& geome builder->flush(context); } +void CustomDrawableLayerHost::Interface::addSymbol(const GeometryCoordinate& point) { + if (!symbolShader) symbolShader = symbolShaderDefault(); + assert(symbolShader); + if (!builder || builder->getShader() != symbolShader) { + finish(); + builder = createBuilder("symbol", symbolShader); + } + assert(builder); + assert(builder->getShader() == symbolShader); + + // temporary: buffers + struct CustomSymbolIcon { + std::array a_pos; + std::array a_tex; + }; + + // vertices + using VertexVector = gfx::VertexVector; + const std::shared_ptr sharedVertices = std::make_shared(); + VertexVector& vertices = *sharedVertices; + + // encode center and extrude direction into vertices + for (int y = 0; y <= 1; ++y) { + for (int x = 0; x <= 1; ++x) { + vertices.emplace_back( + CustomSymbolIcon{{static_cast(point.x * 2 + x), static_cast(point.y * 2 + y)}, + {symbolOptions.textureCoordinates[x][0], symbolOptions.textureCoordinates[y][1]}}); + } + } + + // indexes + using TriangleIndexVector = gfx::IndexVector; + const std::shared_ptr sharedTriangles = std::make_shared(); + TriangleIndexVector& triangles = *sharedTriangles; + + triangles.emplace_back(0, 1, 2, 1, 2, 3); + + SegmentVector triangleSegments; + triangleSegments.emplace_back(Segment{0, 0, 4, 6}); + + // add to builder + static const StringIdentity idPositionAttribName = stringIndexer().get("a_pos"); + static const StringIdentity idTextureAttribName = stringIndexer().get("a_tex"); + builder->setVertexAttrNameId(idPositionAttribName); + + auto attrs = context.createVertexAttributeArray(); + if (const auto& attr = attrs->add(idPositionAttribName)) { + attr->setSharedRawData(sharedVertices, + offsetof(CustomSymbolIcon, a_pos), + /*vertexOffset=*/0, + sizeof(CustomSymbolIcon), + gfx::AttributeDataType::Float2); + } + if (const auto& attr = attrs->add(idTextureAttribName)) { + attr->setSharedRawData(sharedVertices, + offsetof(CustomSymbolIcon, a_tex), + /*vertexOffset=*/0, + sizeof(CustomSymbolIcon), + gfx::AttributeDataType::Float2); + } + builder->setVertexAttributes(std::move(attrs)); + builder->setRawVertices({}, vertices.elements(), gfx::AttributeDataType::Float2); + builder->setSegments(gfx::Triangles(), sharedTriangles, triangleSegments.data(), triangleSegments.size()); + + // texture + if (symbolOptions.texture) { + builder->setTexture(symbolOptions.texture, idCustomSymbolIconTexture); + } + + // create fill tweaker + auto tweaker = std::make_shared(symbolOptions); + builder->addTweaker(tweaker); + + // flush current builder drawable + builder->flush(context); +} + void CustomDrawableLayerHost::Interface::finish() { if (builder && !builder->empty()) { // finish - const auto finish_ = [this](auto& tweaker) { + const auto finish_ = [this](gfx::DrawableTweakerPtr tweaker) { builder->flush(context); for (auto& drawable : builder->clearDrawables()) { assert(tileID.has_value()); drawable->setTileID(tileID.value()); - drawable->addTweaker(tweaker); + if (tweaker) { + drawable->addTweaker(tweaker); + } TileLayerGroup* tileLayerGroup = static_cast(layerGroup.get()); tileLayerGroup->addDrawable(RenderPass::Translucent, tileID.value(), std::move(drawable)); @@ -314,12 +455,17 @@ void CustomDrawableLayerHost::Interface::finish() { // finish drawables finish_(tweaker); + } else if (builder->getShader() == symbolShader) { + // finish building symbols + + // finish drawables + finish_(nullptr); } } } gfx::ShaderPtr CustomDrawableLayerHost::Interface::lineShaderDefault() const { - gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader"); + gfx::ShaderGroupPtr shaderGroup = shaders.getShaderGroup("LineShader"); const mbgl::unordered_set propertiesAsUniforms{ stringIndexer().get("a_color"), @@ -330,18 +476,22 @@ gfx::ShaderPtr CustomDrawableLayerHost::Interface::lineShaderDefault() const { stringIndexer().get("a_width"), }; - return lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); + return shaderGroup->getOrCreateShader(context, propertiesAsUniforms); } gfx::ShaderPtr CustomDrawableLayerHost::Interface::fillShaderDefault() const { - gfx::ShaderGroupPtr fillShaderGroup = shaders.getShaderGroup("FillShader"); + gfx::ShaderGroupPtr shaderGroup = shaders.getShaderGroup("FillShader"); const mbgl::unordered_set propertiesAsUniforms{ stringIndexer().get("a_color"), stringIndexer().get("a_opacity"), }; - return fillShaderGroup->getOrCreateShader(context, propertiesAsUniforms); + return shaderGroup->getOrCreateShader(context, propertiesAsUniforms); +} + +gfx::ShaderPtr CustomDrawableLayerHost::Interface::symbolShaderDefault() const { + return context.getGenericShader(shaders, "CustomSymbolIconShader"); } std::unique_ptr CustomDrawableLayerHost::Interface::createBuilder(const std::string& name, diff --git a/test/api/custom_drawable_layer.test.cpp b/test/api/custom_drawable_layer.test.cpp index c9a2599af..e3c27f58c 100644 --- a/test/api/custom_drawable_layer.test.cpp +++ b/test/api/custom_drawable_layer.test.cpp @@ -14,11 +14,14 @@ #include #include +#include +#include +#include #include #include -class TestDrawableLayer : public mbgl::style::CustomDrawableLayerHost { +class LineTestDrawableLayer : public mbgl::style::CustomDrawableLayerHost { public: void initialize() override {} @@ -104,6 +107,24 @@ public: } } + // finish + interface.finish(); + } + + void deinitialize() override {} +}; + +class FillTestDrawableLayer : public mbgl::style::CustomDrawableLayerHost { +public: + void initialize() override {} + + void update(Interface& interface) override { + // if we have built our drawable(s) already, either update or skip + if (interface.getDrawableCount()) return; + + // set tile + interface.setTileID({11, 327, 791}); + // add fill polygon { using namespace mbgl; @@ -141,7 +162,65 @@ public: void deinitialize() override {} }; -TEST(CustomDrawableLayer, Basic) { +class SymbolIconTestDrawableLayer : public mbgl::style::CustomDrawableLayerHost { +public: + void initialize() override {} + + void update(Interface& interface) override { + // if we have built our drawable(s) already, either update or skip + if (interface.getDrawableCount()) return; + + // set tile + interface.setTileID({11, 327, 791}); + + // add symbol icon + { + using namespace mbgl; + GeometryCoordinate position{static_cast(util::EXTENT * 0.5f), + static_cast(util::EXTENT * 0.5f)}; + + // load image + std::string imageData; // doh! + constexpr auto imagePath = "test/fixtures/custom_drawable_layer/symbol_icon/pin1.png"; + try { + imageData = util::read_file(imagePath); + } catch (std::exception& ex) { + using namespace std::string_literals; + Log::Error(Event::Setup, "Failed to load expected image "s + imagePath + ": " + ex.what()); + throw; + } + std::shared_ptr image = std::make_shared(decodeImage(imageData)); + + // set symbol options + Interface::SymbolOptions options; + options.texture = interface.context.createTexture2D(); + options.texture->setImage(image); + options.texture->setSamplerConfiguration( + {gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + options.textureCoordinates = {{{0.0f, 0.08f}, {1.0f, 0.9f}}}; + const float xspan = options.textureCoordinates[1][0] - options.textureCoordinates[0][0]; + const float yspan = options.textureCoordinates[1][1] - options.textureCoordinates[0][1]; + assert(xspan > 0.0f && yspan > 0.0f); + options.size = {static_cast(image->size.width * 0.2f * xspan), + static_cast(image->size.height * 0.2f * yspan)}; + options.anchor = {0.5f, 0.95f}; + options.angleDegrees = 45.0f; + options.scaleWithMap = false; + options.pitchWithMap = false; + interface.setSymbolOptions(options); + + // add symbol + interface.addSymbol(position); + } + + // finish + interface.finish(); + } + + void deinitialize() override {} +}; + +TEST(CustomDrawableLayer, Line) { using namespace mbgl; using namespace mbgl::style; @@ -154,21 +233,63 @@ TEST(CustomDrawableLayer, Basic) { ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); // load style - map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json")); + map.getStyle().loadJSON(util::read_file("test/fixtures/api/simple.json")); map.jumpTo(CameraOptions().withCenter(LatLng{37.8, -122.4426032}).withZoom(10.0)); - // add fill layer - auto layer = std::make_unique("landcover", "mapbox"); - layer->setSourceLayer("landcover"); - layer->setFillColor(Color{1.0, 1.0, 0.0, 1.0}); - map.getStyle().addLayer(std::move(layer)); - // add custom drawable layer map.getStyle().addLayer( - std::make_unique("custom-drawable", std::make_unique())); + std::make_unique("custom-drawable", std::make_unique())); // render and test - test::checkImage("test/fixtures/custom_drawable_layer/basic", frontend.render(map).image, 0.000657, 0.1); + test::checkImage("test/fixtures/custom_drawable_layer/line", frontend.render(map).image, 0.000657, 0.1); +} + +TEST(CustomDrawableLayer, Fill) { + using namespace mbgl; + using namespace mbgl::style; + + util::RunLoop loop; + + HeadlessFrontend frontend{1}; + Map map(frontend, + MapObserver::nullObserver(), + MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); + + // load style + map.getStyle().loadJSON(util::read_file("test/fixtures/api/simple.json")); + map.jumpTo(CameraOptions().withCenter(LatLng{37.8, -122.4426032}).withZoom(10.0)); + + // add custom drawable layer + map.getStyle().addLayer( + std::make_unique("custom-drawable", std::make_unique())); + + // render and test + test::checkImage("test/fixtures/custom_drawable_layer/fill", frontend.render(map).image, 0.000657, 0.1); +} + +TEST(CustomDrawableLayer, SymbolIcon) { + using namespace mbgl; + using namespace mbgl::style; + + util::RunLoop loop; + + HeadlessFrontend frontend{1}; + Map map(frontend, + MapObserver::nullObserver(), + MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); + + // load style + map.getStyle().loadJSON(util::read_file("test/fixtures/api/simple.json")); + map.jumpTo(CameraOptions().withCenter(LatLng{37.8, -122.4426032}).withZoom(10.0)); + + // add custom drawable layer + map.getStyle().addLayer( + std::make_unique("custom-drawable", std::make_unique())); + + // render and test + test::checkImage("test/fixtures/custom_drawable_layer/symbol_icon", frontend.render(map).image, 0.000657, 0.1); } #endif // MLN_DRAWABLE_RENDERER diff --git a/test/fixtures/api/simple.json b/test/fixtures/api/simple.json new file mode 100644 index 000000000..d88273816 --- /dev/null +++ b/test/fixtures/api/simple.json @@ -0,0 +1,25 @@ +{ + "version": 8, + "name": "Water", + "sources": { + "mapbox": { + "type": "vector", + "tiles": ["asset://streets/{z}-{x}-{y}.vector.pbf"] + } + }, + "layers": [{ + "id": "background", + "type": "background", + "paint": { + "background-color": "gray" + } + }, { + "id": "water", + "type": "fill", + "source": "mapbox", + "source-layer": "water", + "paint": { + "fill-color": "#3440eb" + } + }] +} diff --git a/test/fixtures/custom_drawable_layer/basic/expected.png b/test/fixtures/custom_drawable_layer/basic/expected.png deleted file mode 100644 index 10572d2719d907ddd59b9b5278bce5d7df403a2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30225 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� 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 diff --git a/test/fixtures/custom_drawable_layer/fill/expected.png b/test/fixtures/custom_drawable_layer/fill/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..26a6fa1c2fee964405695d469965518351e55911 GIT binary patch literal 7742 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 UNaR8>&xHYFgA4kVy2Ob81DX^TL;wH) literal 0 HcmV?d00001 diff --git a/test/fixtures/custom_drawable_layer/line/expected.png b/test/fixtures/custom_drawable_layer/line/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..217b3e170bcea1482b4c2081819e8b2388598659 GIT binary patch literal 35055 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 T%;q8X00000NkvXXu0mjfGppjY literal 0 HcmV?d00001 diff --git a/test/fixtures/custom_drawable_layer/symbol_icon/expected.png b/test/fixtures/custom_drawable_layer/symbol_icon/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..7e2cecc29c1271e29474593c841f8443a36ca842 GIT binary patch literal 11379 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
  • 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 literal 0 HcmV?d00001