From f6e79d70735361438655f279c8699a786d25458c Mon Sep 17 00:00:00 2001 From: Lauren Budorick Date: Thu, 27 Apr 2017 15:56:55 -0700 Subject: [core] Render fill-extrusion layers (#8431) --- cmake/core-files.cmake | 25 +- cmake/test-files.cmake | 2 + include/mbgl/map/map.hpp | 5 + include/mbgl/style/conversion/constant.hpp | 49 +- include/mbgl/style/conversion/layer.hpp | 3 + include/mbgl/style/conversion/light.hpp | 122 ++++ include/mbgl/style/conversion/position.hpp | 29 + include/mbgl/style/layer.hpp | 2 +- include/mbgl/style/light.hpp | 52 ++ include/mbgl/style/position.hpp | 68 ++ include/mbgl/style/types.hpp | 5 + include/mbgl/util/indexed_tuple.hpp | 56 ++ include/mbgl/util/interpolate.hpp | 12 + include/mbgl/util/type_list.hpp | 40 ++ mapbox-gl-js | 2 +- .../mapboxsdk/style/layers/FillExtrusionLayer.java | 339 +++++++++ .../mapbox/mapboxsdk/style/layers/Property.java | 21 + .../mapboxsdk/style/layers/PropertyFactory.java | 164 +++++ .../testapp/style/BackgroundLayerTest.java | 41 +- .../testapp/style/FillExtrusionLayerTest.java | 760 +++++++++++++++++++++ .../src/main/AndroidManifest.xml | 11 + .../activity/style/FillExtrusionActivity.java | 135 ++++ .../res/layout/activity_fill_extrusion_layer.xml | 17 + .../src/main/res/values/strings.xml | 2 + platform/android/config.cmake | 2 + platform/android/scripts/generate-style-code.js | 3 - .../src/style/layers/fill_extrusion_layer.cpp | 200 ++++++ .../src/style/layers/fill_extrusion_layer.hpp | 62 ++ platform/android/src/style/layers/layer.cpp | 4 + platform/android/src/style/layers/layers.cpp | 8 + .../darwin/docs/guides/For Style Authors.md.ejs | 2 +- platform/darwin/scripts/generate-style-code.js | 5 - .../scripts/style-spec-cocoa-conventions-v8.json | 4 + .../darwin/scripts/style-spec-overrides-v8.json | 14 + platform/darwin/src/MGLFillExtrusionStyleLayer.h | 364 ++++++++++ platform/darwin/src/MGLFillExtrusionStyleLayer.mm | 335 +++++++++ platform/darwin/src/MGLStyle.mm | 4 + platform/darwin/src/MGLStyleLayer.h.ejs | 2 +- .../darwin/test/MGLDocumentationExampleTests.swift | 16 + .../darwin/test/MGLFillExtrusionStyleLayerTests.mm | 445 ++++++++++++ platform/darwin/test/MGLStyleLayerTests.mm.ejs | 2 +- platform/glfw/glfw_view.cpp | 10 +- platform/glfw/main.cpp | 2 +- platform/ios/CHANGELOG.md | 1 + platform/ios/docs/guides/For Style Authors.md | 8 + platform/ios/ios.xcodeproj/project.pbxproj | 16 + platform/ios/jazzy.yml | 1 + platform/ios/src/Mapbox.h | 1 + platform/ios/vendor/SMCalloutView | 2 +- platform/macos/CHANGELOG.md | 1 + platform/macos/docs/guides/For Style Authors.md | 8 + platform/macos/jazzy.yml | 1 + platform/macos/macos.xcodeproj/project.pbxproj | 12 + platform/macos/src/Mapbox.h | 1 + scripts/generate-shaders.js | 3 + scripts/style-code.js | 4 + src/mbgl/gl/context.cpp | 12 + src/mbgl/gl/context.hpp | 6 +- src/mbgl/gl/types.hpp | 5 + src/mbgl/map/map.cpp | 17 + src/mbgl/map/transform_state.cpp | 9 +- src/mbgl/map/transform_state.hpp | 2 +- src/mbgl/programs/attributes.hpp | 2 + src/mbgl/programs/extrusion_texture_program.cpp | 7 + src/mbgl/programs/extrusion_texture_program.hpp | 37 + src/mbgl/programs/fill_extrusion_program.cpp | 81 +++ src/mbgl/programs/fill_extrusion_program.hpp | 129 ++++ src/mbgl/programs/fill_program.hpp | 9 - src/mbgl/programs/programs.hpp | 8 + src/mbgl/programs/uniforms.hpp | 7 + src/mbgl/renderer/circle_bucket.hpp | 1 + src/mbgl/renderer/fill_extrusion_bucket.cpp | 177 +++++ src/mbgl/renderer/fill_extrusion_bucket.hpp | 38 ++ src/mbgl/renderer/painter.cpp | 78 ++- src/mbgl/renderer/painter.hpp | 11 +- src/mbgl/renderer/painter_background.cpp | 4 +- src/mbgl/renderer/painter_clipping.cpp | 2 +- src/mbgl/renderer/painter_fill_extrusion.cpp | 87 +++ src/mbgl/renderer/painter_raster.cpp | 2 +- src/mbgl/renderer/render_fill_extrusion_layer.cpp | 41 +- src/mbgl/renderer/render_fill_extrusion_layer.hpp | 9 + src/mbgl/renderer/render_item.hpp | 8 +- src/mbgl/renderer/render_tile.cpp | 48 +- src/mbgl/renderer/render_tile.hpp | 14 + src/mbgl/shaders/extrusion_texture.cpp | 39 ++ src/mbgl/shaders/extrusion_texture.hpp | 16 + src/mbgl/shaders/fill_extrusion.cpp | 98 +++ src/mbgl/shaders/fill_extrusion.hpp | 16 + src/mbgl/shaders/fill_extrusion_pattern.cpp | 111 +++ src/mbgl/shaders/fill_extrusion_pattern.hpp | 16 + src/mbgl/shaders/preludes.cpp | 5 +- .../style/layers/fill_extrusion_layer_impl.hpp | 2 - src/mbgl/style/light_impl.hpp | 74 ++ src/mbgl/style/paint_property.hpp | 75 +- src/mbgl/style/parser.cpp | 16 + src/mbgl/style/parser.hpp | 4 + src/mbgl/style/source_impl.cpp | 8 +- src/mbgl/style/source_impl.hpp | 1 + src/mbgl/style/style.cpp | 22 +- src/mbgl/style/style.hpp | 5 + src/mbgl/style/transitioning_property.hpp | 77 +++ src/mbgl/style/types.cpp | 5 + src/mbgl/util/indexed_tuple.hpp | 56 -- src/mbgl/util/mat3.cpp | 16 +- src/mbgl/util/mat3.hpp | 6 +- src/mbgl/util/offscreen_texture.cpp | 21 +- src/mbgl/util/offscreen_texture.hpp | 1 + src/mbgl/util/type_list.hpp | 40 -- .../fixtures/style_parser/line-translate.info.json | 2 +- test/style/conversion/light.test.cpp | 101 +++ test/style/paint_property.test.cpp | 39 +- test/util/position.test.cpp | 49 ++ test/util/tile_cover.test.cpp | 5 +- 113 files changed, 4951 insertions(+), 331 deletions(-) create mode 100644 include/mbgl/style/conversion/light.hpp create mode 100644 include/mbgl/style/conversion/position.hpp create mode 100644 include/mbgl/style/light.hpp create mode 100644 include/mbgl/style/position.hpp create mode 100644 include/mbgl/util/indexed_tuple.hpp create mode 100644 include/mbgl/util/type_list.hpp create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_fill_extrusion_layer.xml create mode 100644 platform/android/src/style/layers/fill_extrusion_layer.cpp create mode 100644 platform/android/src/style/layers/fill_extrusion_layer.hpp create mode 100644 platform/darwin/src/MGLFillExtrusionStyleLayer.h create mode 100644 platform/darwin/src/MGLFillExtrusionStyleLayer.mm create mode 100644 platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm create mode 100644 src/mbgl/programs/extrusion_texture_program.cpp create mode 100644 src/mbgl/programs/extrusion_texture_program.hpp create mode 100644 src/mbgl/programs/fill_extrusion_program.cpp create mode 100644 src/mbgl/programs/fill_extrusion_program.hpp create mode 100644 src/mbgl/renderer/fill_extrusion_bucket.cpp create mode 100644 src/mbgl/renderer/fill_extrusion_bucket.hpp create mode 100644 src/mbgl/renderer/painter_fill_extrusion.cpp create mode 100644 src/mbgl/shaders/extrusion_texture.cpp create mode 100644 src/mbgl/shaders/extrusion_texture.hpp create mode 100644 src/mbgl/shaders/fill_extrusion.cpp create mode 100644 src/mbgl/shaders/fill_extrusion.hpp create mode 100644 src/mbgl/shaders/fill_extrusion_pattern.cpp create mode 100644 src/mbgl/shaders/fill_extrusion_pattern.hpp create mode 100644 src/mbgl/style/light_impl.hpp create mode 100644 src/mbgl/style/transitioning_property.hpp delete mode 100644 src/mbgl/util/indexed_tuple.hpp delete mode 100644 src/mbgl/util/type_list.hpp create mode 100644 test/style/conversion/light.test.cpp create mode 100644 test/util/position.test.cpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 602cf90dad..d281872102 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -139,6 +139,10 @@ set(MBGL_CORE_FILES src/mbgl/programs/collision_box_program.cpp src/mbgl/programs/collision_box_program.hpp src/mbgl/programs/debug_program.hpp + src/mbgl/programs/extrusion_texture_program.cpp + src/mbgl/programs/extrusion_texture_program.hpp + src/mbgl/programs/fill_extrusion_program.cpp + src/mbgl/programs/fill_extrusion_program.hpp src/mbgl/programs/fill_program.cpp src/mbgl/programs/fill_program.hpp src/mbgl/programs/line_program.cpp @@ -162,6 +166,8 @@ set(MBGL_CORE_FILES src/mbgl/renderer/debug_bucket.hpp src/mbgl/renderer/fill_bucket.cpp src/mbgl/renderer/fill_bucket.hpp + src/mbgl/renderer/fill_extrusion_bucket.cpp + src/mbgl/renderer/fill_extrusion_bucket.hpp src/mbgl/renderer/frame_history.cpp src/mbgl/renderer/frame_history.hpp src/mbgl/renderer/group_by_layout.cpp @@ -176,6 +182,7 @@ set(MBGL_CORE_FILES src/mbgl/renderer/painter_clipping.cpp src/mbgl/renderer/painter_debug.cpp src/mbgl/renderer/painter_fill.cpp + src/mbgl/renderer/painter_fill_extrusion.cpp src/mbgl/renderer/painter_line.cpp src/mbgl/renderer/painter_raster.cpp src/mbgl/renderer/painter_symbol.cpp @@ -213,8 +220,14 @@ set(MBGL_CORE_FILES src/mbgl/shaders/collision_box.hpp src/mbgl/shaders/debug.cpp src/mbgl/shaders/debug.hpp + src/mbgl/shaders/extrusion_texture.cpp + src/mbgl/shaders/extrusion_texture.hpp src/mbgl/shaders/fill.cpp src/mbgl/shaders/fill.hpp + src/mbgl/shaders/fill_extrusion.cpp + src/mbgl/shaders/fill_extrusion.hpp + src/mbgl/shaders/fill_extrusion_pattern.cpp + src/mbgl/shaders/fill_extrusion_pattern.hpp src/mbgl/shaders/fill_outline.cpp src/mbgl/shaders/fill_outline.hpp src/mbgl/shaders/fill_outline_pattern.cpp @@ -270,6 +283,8 @@ set(MBGL_CORE_FILES include/mbgl/style/image.hpp include/mbgl/style/layer.hpp include/mbgl/style/layer_type.hpp + include/mbgl/style/light.hpp + include/mbgl/style/position.hpp include/mbgl/style/property_value.hpp include/mbgl/style/query.hpp include/mbgl/style/source.hpp @@ -288,6 +303,7 @@ set(MBGL_CORE_FILES src/mbgl/style/layer_impl.hpp src/mbgl/style/layer_observer.hpp src/mbgl/style/layout_property.hpp + src/mbgl/style/light_impl.hpp src/mbgl/style/observer.hpp src/mbgl/style/paint_property.hpp src/mbgl/style/paint_property_binder.hpp @@ -304,10 +320,9 @@ set(MBGL_CORE_FILES src/mbgl/style/source_observer.hpp src/mbgl/style/style.cpp src/mbgl/style/style.hpp - src/mbgl/style/style.hpp - src/mbgl/style/style.hpp src/mbgl/style/tile_source_impl.cpp src/mbgl/style/tile_source_impl.hpp + src/mbgl/style/transitioning_property.hpp src/mbgl/style/types.cpp src/mbgl/style/update_batch.hpp src/mbgl/style/update_parameters.hpp @@ -320,7 +335,9 @@ set(MBGL_CORE_FILES include/mbgl/style/conversion/geojson.hpp include/mbgl/style/conversion/geojson_options.hpp include/mbgl/style/conversion/layer.hpp + include/mbgl/style/conversion/light.hpp include/mbgl/style/conversion/make_property_setters.hpp + include/mbgl/style/conversion/position.hpp include/mbgl/style/conversion/property_setter.hpp include/mbgl/style/conversion/property_value.hpp include/mbgl/style/conversion/source.hpp @@ -474,6 +491,7 @@ set(MBGL_CORE_FILES include/mbgl/util/geometry.hpp include/mbgl/util/ignore.hpp include/mbgl/util/image.hpp + include/mbgl/util/indexed_tuple.hpp include/mbgl/util/interpolate.hpp include/mbgl/util/logging.hpp include/mbgl/util/noncopyable.hpp @@ -487,6 +505,7 @@ set(MBGL_CORE_FILES include/mbgl/util/tileset.hpp include/mbgl/util/timer.hpp include/mbgl/util/traits.hpp + include/mbgl/util/type_list.hpp include/mbgl/util/unitbezier.hpp include/mbgl/util/util.hpp include/mbgl/util/variant.hpp @@ -514,7 +533,6 @@ set(MBGL_CORE_FILES src/mbgl/util/http_timeout.hpp src/mbgl/util/i18n.cpp src/mbgl/util/i18n.hpp - src/mbgl/util/indexed_tuple.hpp src/mbgl/util/interpolate.cpp src/mbgl/util/intersection_tests.cpp src/mbgl/util/intersection_tests.hpp @@ -548,7 +566,6 @@ set(MBGL_CORE_FILES src/mbgl/util/tile_cover.cpp src/mbgl/util/tile_cover.hpp src/mbgl/util/token.hpp - src/mbgl/util/type_list.hpp src/mbgl/util/url.cpp src/mbgl/util/url.hpp src/mbgl/util/utf.hpp diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake index 9012ae9616..51dedb0052 100644 --- a/cmake/test-files.cmake +++ b/cmake/test-files.cmake @@ -82,6 +82,7 @@ set(MBGL_TEST_FILES test/style/conversion/function.test.cpp test/style/conversion/geojson_options.test.cpp test/style/conversion/layer.test.cpp + test/style/conversion/light.test.cpp test/style/conversion/stringify.test.cpp # style @@ -125,6 +126,7 @@ set(MBGL_TEST_FILES test/util/merge_lines.test.cpp test/util/number_conversions.test.cpp test/util/offscreen_texture.test.cpp + test/util/position.test.cpp test/util/projection.test.cpp test/util/run_loop.test.cpp test/util/text_conversions.test.cpp diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 0e3cee4e70..84ea3104d8 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -30,6 +30,7 @@ namespace style { class Image; class Source; class Layer; +class Light; } // namespace style class Map : private util::noncopyable { @@ -179,6 +180,10 @@ public: void removeImage(const std::string&); const style::Image* getImage(const std::string&); + // Light + void setLight(std::unique_ptr); + style::Light* getLight(); + // Defaults std::string getStyleName() const; LatLng getDefaultLatLng() const; diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp index 1e1fdc2ee8..07c0a35fae 100644 --- a/include/mbgl/style/conversion/constant.hpp +++ b/include/mbgl/style/conversion/constant.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -92,45 +93,25 @@ struct Converter { } }; -template <> -struct Converter> { +template +struct Converter> { template - optional> operator()(const V& value, Error& error) const { - if (!isArray(value) || arrayLength(value) != 2) { - error = { "value must be an array of two numbers" }; + optional> operator()(const V& value, Error& error) const { + if (!isArray(value) || arrayLength(value) != N) { + error = { "value must be an array of " + util::toString(N) + " numbers" }; return {}; } - optional first = toNumber(arrayMember(value, 0)); - optional second = toNumber(arrayMember(value, 1)); - if (!first || !second) { - error = { "value must be an array of two numbers" }; - return {}; - } - - return std::array {{ *first, *second }}; - } -}; - -template <> -struct Converter> { - template - optional> operator()(const V& value, Error& error) const { - if (!isArray(value) || arrayLength(value) != 4) { - error = { "value must be an array of four numbers" }; - return {}; - } - - optional first = toNumber(arrayMember(value, 0)); - optional second = toNumber(arrayMember(value, 1)); - optional third = toNumber(arrayMember(value, 2)); - optional fourth = toNumber(arrayMember(value, 3)); - if (!first || !second) { - error = { "value must be an array of four numbers" }; - return {}; + std::array result; + for (size_t i = 0; i < N; i++) { + optional n = toNumber(arrayMember(value, i)); + if (!n) { + error = { "value must be an array of " + util::toString(N) + " numbers" }; + return {}; + } + result[i] = *n; } - - return std::array {{ *first, *second, *third, *fourth }}; + return result; } }; diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp index efb1df8fef..3a64c36bf5 100644 --- a/include/mbgl/style/conversion/layer.hpp +++ b/include/mbgl/style/conversion/layer.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,8 @@ public: if (*type == "fill") { converted = convertVectorLayer(*id, value, error); + } else if (*type == "fill-extrusion") { + converted = convertVectorLayer(*id, value, error); } else if (*type == "line") { converted = convertVectorLayer(*id, value, error); } else if (*type == "circle") { diff --git a/include/mbgl/style/conversion/light.hpp b/include/mbgl/style/conversion/light.hpp new file mode 100644 index 0000000000..631ed04ccb --- /dev/null +++ b/include/mbgl/style/conversion/light.hpp @@ -0,0 +1,122 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { +public: + template + optional operator()(const V& value, Error& error) const { + if (!isObject(value)) { + error = { "light must be an object" }; + return {}; + } + + Light light; + + const auto anchor = objectMember(value, "anchor"); + if (anchor) { + optional> convertedAnchor = + convert>(*anchor, error); + + if (convertedAnchor) { + light.get().value = *convertedAnchor; + } else { + return {}; + } + } + + const auto anchorTransition = objectMember(value, "anchor-transition"); + if (anchorTransition) { + optional transition = + convert(*anchorTransition, error); + if (transition) { + light.get().transition = *transition; + } else { + return {}; + } + } + + const auto color = objectMember(value, "color"); + if (color) { + optional> convertedColor = + convert>(*color, error); + + if (convertedColor) { + light.get().value = *convertedColor; + } else { + return {}; + } + } + + const auto colorTransition = objectMember(value, "color-transition"); + if (colorTransition) { + optional transition = + convert(*colorTransition, error); + if (transition) { + light.get().transition = *transition; + } else { + return {}; + } + } + + const auto position = objectMember(value, "position"); + if (position) { + optional> convertedPosition = + convert>(*position, error); + + if (convertedPosition) { + light.get().value = *convertedPosition; + } else { + return {}; + } + } + + const auto positionTransition = objectMember(value, "position-transition"); + if (positionTransition) { + optional transition = + convert(*positionTransition, error); + if (transition) { + light.get().transition = *transition; + } else { + return {}; + } + } + + const auto intensity = objectMember(value, "intensity"); + if (intensity) { + optional> convertedIntensity = + convert>(*intensity, error); + + if (convertedIntensity) { + light.get().value = *convertedIntensity; + } else { + return {}; + } + } + + const auto intensityTransition = objectMember(value, "intensity-transition"); + if (intensityTransition) { + optional transition = + convert(*intensityTransition, error); + if (transition) { + light.get().transition = *transition; + } else { + return {}; + } + } + return { light }; + }; +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/position.hpp b/include/mbgl/style/conversion/position.hpp new file mode 100644 index 0000000000..7036b03822 --- /dev/null +++ b/include/mbgl/style/conversion/position.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { + template + optional operator()(const V& value, Error& error) const { + optional> spherical = convert>(value, error); + + if (!spherical) { + return {}; + } + + return Position(*spherical); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp index f09eb0165a..56f2c48fa7 100644 --- a/include/mbgl/style/layer.hpp +++ b/include/mbgl/style/layer.hpp @@ -66,7 +66,7 @@ public: // Convenience method for dynamic dispatch on the concrete layer type. Using // method overloading, this allows consolidation of logic common to vector-based - // layers (Fill, Line, Circle, or Symbol). For example: + // layers (Fill, FillExtrusion, Line, Circle, or Symbol). For example: // // struct Visitor { // void operator()(CustomLayer&) { ... } diff --git a/include/mbgl/style/light.hpp b/include/mbgl/style/light.hpp new file mode 100644 index 0000000000..bec8e6ddeb --- /dev/null +++ b/include/mbgl/style/light.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { + +template +class LightProperty { +public: + using Type = T; + using ValueType = PropertyValue; + + PropertyValue value; + TransitionOptions transition; +}; + +struct LightAnchor : LightProperty { + static LightAnchorType defaultValue() { + return LightAnchorType::Viewport; + } +}; + +struct LightPosition : LightProperty { + static Position defaultValue() { + std::array default_ = { { 1.15, 210, 30 } }; + return Position{ { default_ } }; + } +}; + +struct LightColor : LightProperty { + static Color defaultValue() { + return Color::white(); + } +}; + +struct LightIntensity : LightProperty { + static float defaultValue() { + return 0.5; + } +}; + +using LightProperties = TypeList; +class Light : public IndexedTuple {}; + +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/position.hpp b/include/mbgl/style/position.hpp new file mode 100644 index 0000000000..3be8d1c55e --- /dev/null +++ b/include/mbgl/style/position.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include + +#include + +namespace mbgl { +namespace style { +class Position { +public: + Position() = default; + Position(std::array& position_) + : radial(position_[0]), azimuthal(position_[1]), polar(position_[2]) { + calculateCartesian(); + }; + + friend bool operator==(const Position& lhs, const Position& rhs) { + return lhs.radial == rhs.radial && lhs.azimuthal == rhs.azimuthal && lhs.polar == rhs.polar; + // TODO this doesn't address wrapping, which would be better addressed by comparing cartesian coordinates but being calculated floats are ont to be trusted. + } + + friend bool operator!=(const Position& lhs, const Position& rhs) { + return !(lhs == rhs); + } + + const std::array getCartesian() const { + return { { x, y, z } }; + }; + + const std::array getSpherical() const { + return { { radial, azimuthal, polar } }; + }; + + void set(std::array& position_) { + radial = position_[0]; + azimuthal = position_[1]; + polar = position_[2]; + calculateCartesian(); + }; + + // Utility function to be used only during interpolation; this leaves spherical coordinates undefined. + void setCartesian(std::array& position_) { + x = position_[0]; + y = position_[1]; + z = position_[2]; + } + +private: + float radial; + float azimuthal; + float polar; + float x; + float y; + float z; + + void calculateCartesian() { + // We abstract "north"/"up" (compass-wise) to be 0° when really this is 90° (π/2): we + // correct for that here + const float _a = (azimuthal + 90) * util::DEG2RAD; + const float _p = polar * util::DEG2RAD; + + x = radial * std::cos(_a) * std::sin(_p); + y = radial * std::sin(_a) * std::sin(_p); + z = radial * std::cos(_p); + }; +}; +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 1f2f5c3105..e0436efb67 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -92,5 +92,10 @@ enum class IconTextFitType : uint8_t { Height }; +enum class LightAnchorType: bool { + Map, + Viewport +}; + } // namespace style } // namespace mbgl diff --git a/include/mbgl/util/indexed_tuple.hpp b/include/mbgl/util/indexed_tuple.hpp new file mode 100644 index 0000000000..a414639530 --- /dev/null +++ b/include/mbgl/util/indexed_tuple.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include +#include + +namespace mbgl { + +template +struct TypeIndex; + +template +struct TypeIndex : std::integral_constant {}; + +template +struct TypeIndex : std::integral_constant::value> {}; + +template class IndexedTuple; + +// A tuple of Ts, where individual members can be accessed via `t.get()` for I ∈ Is. +// +// See https://github.com/mapbox/cpp/blob/master/C%2B%2B%20Structural%20Metaprogramming.md +// for motivation. +// +template +class IndexedTuple, TypeList> : public std::tuple { +public: + static_assert(sizeof...(Is) == sizeof...(Ts), "IndexedTuple size mismatch"); + + using std::tuple::tuple; + + template + static constexpr std::size_t Index = TypeIndex::value; + + template + auto& get() { + return std::get>(*this); + } + + template + const auto& get() const { + return std::get>(*this); + } + + template + IndexedTuple, TypeList> + concat(const IndexedTuple, TypeList>& other) const { + return IndexedTuple, TypeList> { + get()..., + other.template get()... + }; + } +}; + +} // namespace mbgl diff --git a/include/mbgl/util/interpolate.hpp b/include/mbgl/util/interpolate.hpp index d463ffc056..a2103f18b2 100644 --- a/include/mbgl/util/interpolate.hpp +++ b/include/mbgl/util/interpolate.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -46,6 +47,17 @@ public: } }; +template <> +struct Interpolator { +public: + style::Position operator()(const style::Position& a, const style::Position& b, const double t) { + auto pos = style::Position(); + auto interpolated = interpolate(a.getCartesian(), b.getCartesian(), t); + pos.setCartesian(interpolated); + return { pos }; + } +}; + template <> struct Interpolator { public: diff --git a/include/mbgl/util/type_list.hpp b/include/mbgl/util/type_list.hpp new file mode 100644 index 0000000000..4a5e95c8a4 --- /dev/null +++ b/include/mbgl/util/type_list.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +namespace mbgl { + +template +class TypeList {}; + +namespace detail { + +template +struct TypeCons; + +template +struct TypeCons> { + using Type = TypeList; +}; + +template class> +struct TypeFilter; + +template