diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp index 56db250de..d2a23cc5b 100644 --- a/include/mbgl/util/feature.hpp +++ b/include/mbgl/util/feature.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include @@ -32,4 +33,27 @@ optional numericValue(const Value& value) { }); } +inline optional featureIDtoString(const FeatureIdentifier& id) { + if (id.is()) { + return nullopt; + } + + return id.match( + [] (const std::string& value_) { + return value_; + }, + [] (uint64_t value_) { + return util::toString(value_); + }, + [] (int64_t value_) { + return util::toString(value_); + }, + [] (double value_) { + return util::toString(value_); + }, + [] (const auto&) -> optional { + return nullopt; + }); +} + } // namespace mbgl diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp index 59fe67586..091ecb912 100644 --- a/src/mbgl/gfx/vertex_vector.hpp +++ b/src/mbgl/gfx/vertex_vector.hpp @@ -20,6 +20,11 @@ public: v.resize(v.size() + n, val); } + Vertex& at(std::size_t n) { + assert(n < v.size()); + return v.at(n); + } + std::size_t elements() const { return v.size(); } diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp index 858d51534..d6d878955 100644 --- a/src/mbgl/layout/pattern_layout.hpp +++ b/src/mbgl/layout/pattern_layout.hpp @@ -108,7 +108,7 @@ public: const PatternLayerMap& patterns = patternFeature.patterns; const GeometryCollection& geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, patternPositions, patterns); + bucket->addFeature(*feature, geometries, patternPositions, patterns, i); featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID); } if (bucket->hasData()) { diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 1dbb5d91d..71724cad5 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -713,7 +713,7 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptrpaintProperties) { - pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), {}, {}); + pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), symbolInstance.dataFeatureIndex, {}, {}); } } @@ -765,7 +765,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket, std::size_t sectionIndex) { const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex)); for (auto& pair : bucket.paintProperties) { - pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), {}, {}, formattedSection); + pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), feature.index, {}, {}, formattedSection); } } diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index a978c06d6..98c2200ce 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -35,7 +35,11 @@ public: virtual void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, - const PatternLayerMap&) {}; + const PatternLayerMap&, + std::size_t) {}; + + virtual void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) {} + // As long as this bucket has a Prepare render pass, this function is getting called. Typically, // this only happens once when the bucket is being rendered for the first time. diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index 7ba130da6..ffa6f5912 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -25,8 +25,10 @@ CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector CircleBucket::~CircleBucket() = default; void CircleBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -42,7 +44,8 @@ bool CircleBucket::hasData() const { void CircleBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, const ImagePositions&, - const PatternLayerMap&) { + const PatternLayerMap&, + std::size_t featureIndex) { constexpr const uint16_t vertexLength = 4; for (auto& circle : geometry) { @@ -90,7 +93,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.elements(), {}, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}); } } @@ -112,4 +115,12 @@ float CircleBucket::getQueryRadius(const RenderLayer& layer) const { return radius + stroke + util::length(translate[0], translate[1]); } +void CircleBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp index 27423bc56..9fee45ad7 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.hpp +++ b/src/mbgl/renderer/buckets/circle_bucket.hpp @@ -21,7 +21,8 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, - const PatternLayerMap&) override; + const PatternLayerMap&, + std::size_t) override; bool hasData() const override; @@ -29,6 +30,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector vertices; gfx::IndexVector triangles; SegmentVector segments; diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp index 8a089c679..ea79a1e68 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -47,7 +47,8 @@ FillBucket::~FillBucket() = default; void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { + const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); @@ -114,17 +115,19 @@ void FillBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } void FillBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines)); - triangleIndexBuffer = triangles.empty() ? optional {} : uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines)); + triangleIndexBuffer = triangles.empty() ? optional {} : uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -143,4 +146,12 @@ float FillBucket::getQueryRadius(const RenderLayer& layer) const { return util::length(translate[0], translate[1]); } +void FillBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp index 6747c1083..eee421f93 100644 --- a/src/mbgl/renderer/buckets/fill_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_bucket.hpp @@ -29,7 +29,8 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&, - const PatternLayerMap&) override; + const PatternLayerMap&, + std::size_t) override; bool hasData() const override; @@ -37,6 +38,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector vertices; gfx::IndexVector lines; gfx::IndexVector triangles; diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index be13850e5..6a25349c2 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -53,7 +53,8 @@ FillExtrusionBucket::~FillExtrusionBucket() = default; void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { + const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& polygon : classifyRings(geometry)) { // Optimize polygons with many interior rings for earcut tesselation. limitHoles(polygon, 500); @@ -158,16 +159,18 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -186,4 +189,12 @@ float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const { return util::length(translate[0], translate[1]); } +void FillExtrusionBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp index 4c97618a7..582480bf4 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp @@ -27,7 +27,8 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&, - const PatternLayerMap&) override; + const PatternLayerMap&, + std::size_t) override; bool hasData() const override; @@ -35,6 +36,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + gfx::VertexVector vertices; gfx::IndexVector triangles; SegmentVector triangleSegments; diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp index fad78f6ce..0ea645a9a 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp @@ -42,7 +42,8 @@ bool HeatmapBucket::hasData() const { void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry, const ImagePositions&, - const PatternLayerMap&) { + const PatternLayerMap&, + std::size_t featureIndex) { constexpr const uint16_t vertexLength = 4; for (auto& points : geometry) { @@ -89,7 +90,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature, } for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.elements(), {}, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {}); } } diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp index 68790bf5b..3f9d1cb5c 100644 --- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp +++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp @@ -21,7 +21,8 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&, - const PatternLayerMap&) override; + const PatternLayerMap&, + std::size_t) override; bool hasData() const override; void upload(gfx::UploadPass&) override; diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 9019e76d3..318af99b0 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -33,7 +33,8 @@ LineBucket::~LineBucket() = default; void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection, const ImagePositions& patternPositions, - const PatternLayerMap& patternDependencies) { + const PatternLayerMap& patternDependencies, + std::size_t index) { for (auto& line : geometryCollection) { addGeometry(line, feature); } @@ -41,9 +42,9 @@ void LineBucket::addFeature(const GeometryTileFeature& feature, for (auto& pair : paintPropertyBinders) { const auto it = patternDependencies.find(pair.first); if (it != patternDependencies.end()){ - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second); } else { - pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {}); + pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {}); } } } @@ -517,8 +518,10 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, } void LineBucket::upload(gfx::UploadPass& uploadPass) { - vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); - indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + if (!uploaded) { + vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + indexBuffer = uploadPass.createIndexBuffer(std::move(triangles)); + } for (auto& pair : paintPropertyBinders) { pair.second.upload(uploadPass); @@ -554,4 +557,12 @@ float LineBucket::getQueryRadius(const RenderLayer& layer) const { return lineWidth / 2.0f + std::abs(offset) + util::length(translate[0], translate[1]); } +void LineBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) { + auto it = paintPropertyBinders.find(layerID); + if (it != paintPropertyBinders.end()) { + it->second.updateVertexVectors(states, layer, imagePositions); + uploaded = false; + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp index eac9e14e4..6be35593d 100644 --- a/src/mbgl/renderer/buckets/line_bucket.hpp +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -29,7 +29,8 @@ public: void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions& patternPositions, - const PatternLayerMap&) override; + const PatternLayerMap&, + std::size_t) override; bool hasData() const override; @@ -37,6 +38,8 @@ public: float getQueryRadius(const RenderLayer&) const override; + void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override; + PossiblyEvaluatedLayoutProperties layout; gfx::VertexVector vertices; diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index cd6b259e8..fdfbc9964 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -19,6 +19,15 @@ namespace mbgl { +// Maps vertex range to feature index +struct FeatureVertexRange { + std::size_t featureIndex; + std::size_t start; + std::size_t end; +}; + +using FeatureVertexRangeMap = std::map>; + /* ZoomInterpolatedAttribute is a 'compound' attribute, representing two values of the the base attribute Attr. These two values are provided to the shader to allow interpolation @@ -97,9 +106,17 @@ public: virtual ~PaintPropertyBinder() = default; virtual void populateVertexVector(const GeometryTileFeature& feature, - std::size_t length, const ImagePositions&, + std::size_t length, std::size_t index, + const ImagePositions&, const optional&, const style::expression::Value&) = 0; + + virtual void updateVertexVectors(const FeatureStates&, + const GeometryTileLayer&, + const ImagePositions&) {} + + virtual void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) = 0; + virtual void upload(gfx::UploadPass&) = 0; virtual void setPatternParameters(const optional&, const optional&, const CrossfadeParameters&) = 0; virtual std::tuple>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0; @@ -118,7 +135,8 @@ public: : constant(std::move(constant_)) { } - void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional&, const style::expression::Value&) override {} + void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, const optional&, const style::expression::Value&) override {} + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} void upload(gfx::UploadPass&) override {} void setPatternParameters(const optional&, const optional&, const CrossfadeParameters&) override {}; @@ -145,7 +163,8 @@ public: : constant(std::move(constant_)), constantPatternPositions({}) { } - void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional&, const style::expression::Value&) override {} + void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, const optional&, const style::expression::Value&) override {} + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} void upload(gfx::UploadPass&) override {} void setPatternParameters(const optional& posA, const optional& posB, const CrossfadeParameters&) override { @@ -187,14 +206,46 @@ public: defaultValue(std::move(defaultValue_)) { } void setPatternParameters(const optional&, const optional&, const CrossfadeParameters&) override {}; - void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional&, const style::expression::Value& formattedSection) override { + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions&, const optional&, const style::expression::Value& formattedSection) override { using style::expression::EvaluationContext; auto evaluated = expression.evaluate(EvaluationContext(&feature).withFormattedSection(&formattedSection), defaultValue); this->statistics.add(evaluated); auto value = attributeValue(evaluated); - for (std::size_t i = vertexVector.elements(); i < length; ++i) { + auto elements = vertexVector.elements(); + for (std::size_t i = elements; i < length; ++i) { vertexVector.emplace_back(BaseVertex { value }); } + optional idStr = featureIDtoString(feature.getID()); + if (idStr) { + featureMap[*idStr].emplace_back(FeatureVertexRange { index, elements, length }); + } + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions&) override { + for (const auto& it : states) { + const auto positions = featureMap.find(it.first); + if (positions == featureMap.end()) { + continue; + } + + for (const auto& pos : positions->second) { + std::unique_ptr feature = layer.getFeature(pos.featureIndex); + if (feature) { + updateVertexVector(pos.start, pos.end, *feature, it.second); + } + } + } + } + + void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, const FeatureState& state) override { + using style::expression::EvaluationContext; + + auto evaluated = expression.evaluate(EvaluationContext(&feature).withFeatureState(&state), defaultValue); + this->statistics.add(evaluated); + auto value = attributeValue(evaluated); + for (std::size_t i = start; i < end; ++i) { + vertexVector.at(i) = BaseVertex { value }; + } } void upload(gfx::UploadPass& uploadPass) override { @@ -229,6 +280,7 @@ private: T defaultValue; gfx::VertexVector vertexVector; optional> vertexBuffer; + FeatureVertexRangeMap featureMap; }; template @@ -245,7 +297,7 @@ public: zoomRange({zoom, zoom + 1}) { } void setPatternParameters(const optional&, const optional&, const CrossfadeParameters&) override {}; - void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional&, const style::expression::Value& formattedSection) override { + void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions&, const optional&, const style::expression::Value& formattedSection) override { using style::expression::EvaluationContext; Range range = { expression.evaluate(EvaluationContext(zoomRange.min, &feature).withFormattedSection(&formattedSection), defaultValue), @@ -256,9 +308,47 @@ public: AttributeValue value = zoomInterpolatedAttributeValue( attributeValue(range.min), attributeValue(range.max)); - for (std::size_t i = vertexVector.elements(); i < length; ++i) { + auto elements = vertexVector.elements(); + for (std::size_t i = elements; i < length; ++i) { vertexVector.emplace_back(Vertex { value }); } + optional idStr = featureIDtoString(feature.getID()); + if (idStr) { + featureMap[*idStr].emplace_back(FeatureVertexRange { index, elements, length }); + } + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions&) override { + for (const auto& it : states) { + const auto positions = featureMap.find(it.first); + if (positions == featureMap.end()) { + continue; + } + + for (const auto& pos : positions->second) { + std::unique_ptr feature = layer.getFeature(pos.featureIndex); + if (feature) { + updateVertexVector(pos.start, pos.end, *feature, it.second); + } + } + } + } + + void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, const FeatureState& state) override { + using style::expression::EvaluationContext; + Range range = { + expression.evaluate(EvaluationContext(zoomRange.min, &feature, &state), defaultValue), + expression.evaluate(EvaluationContext(zoomRange.max, &feature, &state), defaultValue), + }; + this->statistics.add(range.min); + this->statistics.add(range.max); + AttributeValue value = zoomInterpolatedAttributeValue( + attributeValue(range.min), + attributeValue(range.max)); + + for (std::size_t i = start; i < end; ++i) { + vertexVector.at(i) = Vertex { value }; + } } void upload(gfx::UploadPass& uploadPass) override { @@ -298,6 +388,7 @@ private: Range zoomRange; gfx::VertexVector vertexVector; optional> vertexBuffer; + FeatureVertexRangeMap featureMap; }; template @@ -322,7 +413,7 @@ public: crossfade = crossfade_; }; - void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional& patternDependencies, const style::expression::Value&) override { + void populateVertexVector(const GeometryTileFeature&, std::size_t length, std::size_t /* index */, const ImagePositions& patternPositions, const optional& patternDependencies, const style::expression::Value&) override { if (!patternDependencies || patternDependencies->mid.empty()) { // Unlike other propperties with expressions that evaluate to null, the default value for `*-pattern` properties is an empty @@ -353,6 +444,8 @@ public: } } + void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {} + void upload(gfx::UploadPass& uploadPass) override { if (!patternToVertexVector.empty()) { assert(!zoomInVertexVector.empty()); @@ -491,9 +584,15 @@ public: PaintPropertyBinders(PaintPropertyBinders&&) = default; PaintPropertyBinders(const PaintPropertyBinders&) = delete; - void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional& patternDependencies, const style::expression::Value& formattedSection = {}) { + void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions& patternPositions, const optional& patternDependencies, const style::expression::Value& formattedSection = {}) { util::ignore({ - (binders.template get()->populateVertexVector(feature, length, patternPositions, patternDependencies, formattedSection), 0)... + (binders.template get()->populateVertexVector(feature, length, index, patternPositions, patternDependencies, formattedSection), 0)... + }); + } + + void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions& imagePositions) { + util::ignore({ + (binders.template get()->updateVertexVectors(states, layer, imagePositions), 0)... }); } diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 428a5b0d5..ce883ad93 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -384,7 +384,7 @@ void GeometryTileWorker::parse() { continue; const GeometryCollection& geometries = feature->getGeometries(); - bucket->addFeature(*feature, geometries, {}, PatternLayerMap ()); + bucket->addFeature(*feature, geometries, {}, PatternLayerMap (), i); featureIndex->insert(geometries, i, sourceLayerID, leaderImpl.id); }