diff options
author | zmiao <miao.zhao@mapbox.com> | 2019-08-30 08:24:03 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-30 08:24:03 +0300 |
commit | 6ef2710e5cfb5ee4258583a20d55320e90faa8a5 (patch) | |
tree | 1c840291ea93ec38c2745348678879f10217bf7c /src/mbgl/renderer | |
parent | 29b11a503766efb469036b38f010400cea57967e (diff) | |
download | qtlocation-mapboxgl-6ef2710e5cfb5ee4258583a20d55320e90faa8a5.tar.gz |
[core] fix collisionBox alignment when Icon/text translation is enabled (#15467)
* add initial fix
* fix bug for collision circle
* refind code structure
* fix indentation
* update test
* refind code structure
* Add changelog
* Add comment for boolean
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.cpp | 58 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.hpp | 34 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.cpp | 130 |
3 files changed, 130 insertions, 92 deletions
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index a46c25a13b..ff201e9c2c 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -113,37 +113,50 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) { if (hasIconData()) { updateIconBuffer(icon); } - if (hasSdfIconData()) { updateIconBuffer(sdfIcon); } - if (hasCollisionBoxData()) { + const auto updateCollisionBox = [&](CollisionBoxBuffer& collisionBox) { if (!staticUploaded) { - collisionBox->indexBuffer = uploadPass.createIndexBuffer(std::move(collisionBox->lines)); - collisionBox->vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox->vertices)); + collisionBox.indexBuffer = uploadPass.createIndexBuffer(std::move(collisionBox.lines)); + collisionBox.vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox.vertices)); } if (!placementChangesUploaded) { - if (!collisionBox->dynamicVertexBuffer) { - collisionBox->dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox->dynamicVertices), gfx::BufferUsageType::StreamDraw); + if (!collisionBox.dynamicVertexBuffer) { + collisionBox.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionBox.dynamicVertices), gfx::BufferUsageType::StreamDraw); } else { - uploadPass.updateVertexBuffer(*collisionBox->dynamicVertexBuffer, std::move(collisionBox->dynamicVertices)); + uploadPass.updateVertexBuffer(*collisionBox.dynamicVertexBuffer, std::move(collisionBox.dynamicVertices)); } } + }; + if (hasIconCollisionBoxData()) { + updateCollisionBox(*iconCollisionBox); + } + + if (hasTextCollisionBoxData()) { + updateCollisionBox(*textCollisionBox); } - if (hasCollisionCircleData()) { + const auto updateCollisionCircle = [&](CollisionCircleBuffer& collisionCircle) { if (!staticUploaded) { - collisionCircle->indexBuffer = uploadPass.createIndexBuffer(std::move(collisionCircle->triangles)); - collisionCircle->vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle->vertices)); + collisionCircle.indexBuffer = uploadPass.createIndexBuffer(std::move(collisionCircle.triangles)); + collisionCircle.vertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle.vertices)); } if (!placementChangesUploaded) { - if (!collisionCircle->dynamicVertexBuffer) { - collisionCircle->dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle->dynamicVertices), gfx::BufferUsageType::StreamDraw); + if (!collisionCircle.dynamicVertexBuffer) { + collisionCircle.dynamicVertexBuffer = uploadPass.createVertexBuffer(std::move(collisionCircle.dynamicVertices), gfx::BufferUsageType::StreamDraw); } else { - uploadPass.updateVertexBuffer(*collisionCircle->dynamicVertexBuffer, std::move(collisionCircle->dynamicVertices)); + uploadPass.updateVertexBuffer(*collisionCircle.dynamicVertexBuffer, std::move(collisionCircle.dynamicVertices)); } } + }; + if (hasIconCollisionCircleData()) { + updateCollisionCircle(*iconCollisionCircle); + } + + if (hasTextCollisionCircleData()) { + updateCollisionCircle(*textCollisionCircle); } uploaded = true; @@ -154,7 +167,8 @@ void SymbolBucket::upload(gfx::UploadPass& uploadPass) { } bool SymbolBucket::hasData() const { - return hasTextData() || hasIconData() || hasSdfIconData() || hasCollisionBoxData(); + return hasTextData() || hasIconData() || hasSdfIconData() || hasIconCollisionBoxData() || + hasTextCollisionBoxData() || hasIconCollisionCircleData() || hasTextCollisionCircleData(); } bool SymbolBucket::hasTextData() const { @@ -169,12 +183,20 @@ bool SymbolBucket::hasSdfIconData() const { return !sdfIcon.segments.empty(); } -bool SymbolBucket::hasCollisionBoxData() const { - return collisionBox && !collisionBox->segments.empty(); +bool SymbolBucket::hasIconCollisionBoxData() const { + return iconCollisionBox && !iconCollisionBox->segments.empty(); +} + +bool SymbolBucket::hasIconCollisionCircleData() const { + return iconCollisionCircle && !iconCollisionCircle->segments.empty(); +} + +bool SymbolBucket::hasTextCollisionBoxData() const { + return textCollisionBox && !textCollisionBox->segments.empty(); } -bool SymbolBucket::hasCollisionCircleData() const { - return collisionCircle && !collisionCircle->segments.empty(); +bool SymbolBucket::hasTextCollisionCircleData() const { + return textCollisionCircle && !textCollisionCircle->segments.empty(); } void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSymbol& placedSymbol) { diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index d813707c2f..020190b81f 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -72,8 +72,10 @@ public: bool hasTextData() const; bool hasIconData() const; bool hasSdfIconData() const; - bool hasCollisionBoxData() const; - bool hasCollisionCircleData() const; + bool hasIconCollisionBoxData() const; + bool hasIconCollisionCircleData() const; + bool hasTextCollisionBoxData() const; + bool hasTextCollisionCircleData() const; bool hasFormatSectionOverrides() const; @@ -138,22 +140,34 @@ public: gfx::IndexVector<gfx::Lines> lines; optional<gfx::IndexBuffer> indexBuffer; }; - std::unique_ptr<CollisionBoxBuffer> collisionBox; + std::unique_ptr<CollisionBoxBuffer> iconCollisionBox; + std::unique_ptr<CollisionBoxBuffer> textCollisionBox; - CollisionBoxBuffer& getOrCreateCollisionBox() { - if (!collisionBox) collisionBox = std::make_unique<CollisionBoxBuffer>(); - return *collisionBox; + CollisionBoxBuffer& getOrCreateIconCollisionBox() { + if (!iconCollisionBox) iconCollisionBox = std::make_unique<CollisionBoxBuffer>(); + return *iconCollisionBox; + } + + CollisionBoxBuffer& getOrCreateTextCollisionBox() { + if (!textCollisionBox) textCollisionBox = std::make_unique<CollisionBoxBuffer>(); + return *textCollisionBox; } struct CollisionCircleBuffer : public CollisionBuffer { gfx::IndexVector<gfx::Triangles> triangles; optional<gfx::IndexBuffer> indexBuffer; }; - std::unique_ptr<CollisionCircleBuffer> collisionCircle; + std::unique_ptr<CollisionCircleBuffer> iconCollisionCircle; + std::unique_ptr<CollisionCircleBuffer> textCollisionCircle; + + CollisionCircleBuffer& getOrCreateIconCollisionCircleBuffer() { + if (!iconCollisionCircle) iconCollisionCircle = std::make_unique<CollisionCircleBuffer>(); + return *iconCollisionCircle; + } - CollisionCircleBuffer& getOrCreateCollisionCircleBuffer() { - if (!collisionCircle) collisionCircle = std::make_unique<CollisionCircleBuffer>(); - return *collisionCircle; + CollisionCircleBuffer& getOrCreateTextCollisionCircleBuffer() { + if (!textCollisionCircle) textCollisionCircle = std::make_unique<CollisionCircleBuffer>(); + return *textCollisionCircle; } const float tilePixelRatio; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index d0c038222a..06eacc041b 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -392,46 +392,11 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { } } - if (bucket.hasCollisionBoxData()) { - static const style::Properties<>::PossiblyEvaluated properties {}; - static const CollisionBoxProgram::Binders paintAttributeData(properties, 0); + const auto drawCollisonData = [&](const bool isText, const bool hasCollisionBox, const bool hasCollisionCircle) { + if (!hasCollisionBox && !hasCollisionCircle) return; - auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); - const float scale = std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ); - std::array<float,2> extrudeScale = - {{ - parameters.pixelsToGLUnits[0] / (pixelRatio * scale), - parameters.pixelsToGLUnits[1] / (pixelRatio * scale) - }}; - parameters.programs.getSymbolLayerPrograms().collisionBox.draw( - parameters.context, - *parameters.renderPass, - gfx::Lines { 1.0f }, - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - CollisionBoxProgram::LayoutUniformValues { - uniforms::matrix::Value( tile.matrix ), - uniforms::extrude_scale::Value( extrudeScale ), - uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() ) - }, - *bucket.collisionBox->vertexBuffer, - *bucket.collisionBox->dynamicVertexBuffer, - *bucket.collisionBox->indexBuffer, - bucket.collisionBox->segments, - paintAttributeData, - properties, - CollisionBoxProgram::TextureBindings{}, - parameters.state.getZoom(), - getID() - ); - } - - if (bucket.hasCollisionCircleData()) { - static const style::Properties<>::PossiblyEvaluated properties {}; + static const style::Properties<>::PossiblyEvaluated properties{}; static const CollisionBoxProgram::Binders paintAttributeData(properties, 0); - auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); const float scale = std::pow(2, parameters.state.getZoom() - tile.getOverscaledTileID().overscaledZ); std::array<float,2> extrudeScale = @@ -439,32 +404,69 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { parameters.pixelsToGLUnits[0] / (pixelRatio * scale), parameters.pixelsToGLUnits[1] / (pixelRatio * scale) }}; - - parameters.programs.getSymbolLayerPrograms().collisionCircle.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - CollisionCircleProgram::LayoutUniformValues { - uniforms::matrix::Value( tile.matrix ), - uniforms::extrude_scale::Value( extrudeScale ), - uniforms::overscale_factor::Value( float(tile.getOverscaledTileID().overscaleFactor()) ), - uniforms::camera_to_center_distance::Value( parameters.state.getCameraToCenterDistance() ) - }, - *bucket.collisionCircle->vertexBuffer, - *bucket.collisionCircle->dynamicVertexBuffer, - *bucket.collisionCircle->indexBuffer, - bucket.collisionCircle->segments, - paintAttributeData, - properties, - CollisionCircleProgram::TextureBindings{}, - parameters.state.getZoom(), - getID() - ); - } + const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData->layerProperties); + const auto& layout = *bucket.layout; + const auto values = isText ? textPropertyValues(evaluated, layout): iconPropertyValues(evaluated, layout); + const bool needTranslate = values.translate[0] != 0 || values.translate[1] != 0; + + if (hasCollisionBox) { + const auto& collisionBox = isText ? bucket.textCollisionBox : bucket.iconCollisionBox; + parameters.programs.getSymbolLayerPrograms().collisionBox.draw( + parameters.context, + *parameters.renderPass, + gfx::Lines{ 1.0f }, + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + CollisionBoxProgram::LayoutUniformValues { + uniforms::matrix::Value((needTranslate + ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) + : tile.matrix)), + uniforms::extrude_scale::Value(extrudeScale), + uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance()) + }, + *collisionBox->vertexBuffer, + *collisionBox->dynamicVertexBuffer, + *collisionBox->indexBuffer, + collisionBox->segments, + paintAttributeData, + properties, + CollisionBoxProgram::TextureBindings{}, + parameters.state.getZoom(), + getID()); + } + if (hasCollisionCircle) { + const auto& collisionCircle = isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle; + parameters.programs.getSymbolLayerPrograms().collisionCircle.draw( + parameters.context, + *parameters.renderPass, + gfx::Triangles(), + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + CollisionCircleProgram::LayoutUniformValues { + uniforms::matrix::Value((needTranslate + ? tile.translatedMatrix(values.translate, values.translateAnchor, parameters.state) + : tile.matrix)), + uniforms::extrude_scale::Value(extrudeScale), + uniforms::overscale_factor::Value(float(tile.getOverscaledTileID().overscaleFactor())), + uniforms::camera_to_center_distance::Value(parameters.state.getCameraToCenterDistance()) + }, + *collisionCircle->vertexBuffer, + *collisionCircle->dynamicVertexBuffer, + *collisionCircle->indexBuffer, + collisionCircle->segments, + paintAttributeData, + properties, + CollisionCircleProgram::TextureBindings{}, + parameters.state.getZoom(), + getID()); + } + }; + drawCollisonData(false /*isText*/, bucket.hasIconCollisionBoxData(), bucket.hasIconCollisionCircleData()); + drawCollisonData(true /*isText*/, bucket.hasTextCollisionBoxData(), bucket.hasTextCollisionCircleData()); } if (sortFeaturesByKey) { |