[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
This commit is contained in:
@@ -10,6 +10,9 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
|
||||
### Performance improvements
|
||||
- Mark used offline region resources in batches. [#15521](https://github.com/mapbox/mapbox-gl-native/pull/15521)
|
||||
|
||||
### Bug fixes
|
||||
- Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. [#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467)
|
||||
|
||||
## 8.3.0 - August 28, 2019
|
||||
[Changes](https://github.com/mapbox/mapbox-gl-native/compare/android-v8.3.0-beta.1...android-v8.3.0) since [Mapbox Maps SDK for Android v8.3.0-beta.1](https://github.com/mapbox/mapbox-gl-native/releases/tag/android-v8.3.0-beta.1):
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
|
||||
|
||||
* Fixed an issue that caused the tilt gesture to trigger too easily and conflict with pinch or pan gestures. ([#15349](https://github.com/mapbox/mapbox-gl-native/pull/15349))
|
||||
* Fixed a bug with annotation view positions after camera transitions. ([#15122](https://github.com/mapbox/mapbox-gl-native/pull/15122/))
|
||||
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
|
||||
|
||||
### Performance improvements
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* Fixed rendering and collision detection issues with using `text-variable-anchor` and `icon-text-fit` properties on the same layer. ([#15367](https://github.com/mapbox/mapbox-gl-native/pull/15367))
|
||||
* Fixed symbol overlap when zooming out quickly. ([15416](https://github.com/mapbox/mapbox-gl-native/pull/15416))
|
||||
* Fixed a rendering issue that non-SDF icon would be treated as SDF icon if they are in the same layer. ([#15456](https://github.com/mapbox/mapbox-gl-native/pull/15456))
|
||||
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
|
||||
|
||||
### Styles and rendering
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Introduce `text-writing-mode` layout property for symbol layer ([#14932](https://github.com/mapbox/mapbox-gl-native/pull/14932)). The `text-writing-mode` layout property allows control over symbol's preferred writing mode. The new property value is an array, whose values are enumeration values from a ( `horizontal` | `vertical` ) set.
|
||||
* Fixed rendering and collision detection issues with using `text-variable-anchor` and `icon-text-fit` properties on the same layer ([#15367](https://github.com/mapbox/mapbox-gl-native/pull/15367)).
|
||||
* Fixed a rendering issue that non-SDF icon would be treated as SDF icon if they are in the same layer. ([#15456](https://github.com/mapbox/mapbox-gl-native/pull/15456))
|
||||
* Fixed a rendering issue of `collisionBox` when `text-translate` or `icon-translate` is enabled. ([#15467](https://github.com/mapbox/mapbox-gl-native/pull/15467))
|
||||
|
||||
# 4.2.0
|
||||
- Add an option to set whether or not an image should be treated as a SDF ([#15054](https://github.com/mapbox/mapbox-gl-native/issues/15054))
|
||||
|
||||
@@ -812,12 +812,15 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const SymbolInstance &symbolInstance : symbolInstances) {
|
||||
auto populateCollisionBox = [&](const auto& feature) {
|
||||
SymbolBucket::CollisionBuffer& collisionBuffer = feature.alongLine ?
|
||||
static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateCollisionCircleBuffer()) :
|
||||
static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateCollisionBox());
|
||||
for (const CollisionBox &box : feature.boxes) {
|
||||
for (const SymbolInstance& symbolInstance : symbolInstances) {
|
||||
auto populateCollisionBox = [&](const auto& feature, bool isText) {
|
||||
SymbolBucket::CollisionBuffer& collisionBuffer =
|
||||
feature.alongLine ? (isText ? static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateTextCollisionCircleBuffer())
|
||||
: static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateIconCollisionCircleBuffer()))
|
||||
: (isText ? static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateTextCollisionBox())
|
||||
: static_cast<SymbolBucket::CollisionBuffer&>(bucket.getOrCreateIconCollisionBox()));
|
||||
|
||||
for (const CollisionBox& box : feature.boxes) {
|
||||
auto& anchor = box.anchor;
|
||||
|
||||
Point<float> tl{box.x1, box.y1};
|
||||
@@ -829,8 +832,11 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
|
||||
const std::size_t indexLength = feature.alongLine ? 6 : 8;
|
||||
|
||||
if (collisionBuffer.segments.empty() || collisionBuffer.segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
|
||||
collisionBuffer.segments.emplace_back(collisionBuffer.vertices.elements(),
|
||||
feature.alongLine ? bucket.collisionCircle->triangles.elements() : bucket.collisionBox->lines.elements());
|
||||
collisionBuffer.segments.emplace_back(
|
||||
collisionBuffer.vertices.elements(),
|
||||
feature.alongLine
|
||||
? (isText ? bucket.textCollisionCircle->triangles.elements() : bucket.iconCollisionCircle->triangles.elements())
|
||||
: (isText ? bucket.textCollisionBox->lines.elements() : bucket.iconCollisionBox->lines.elements()));
|
||||
}
|
||||
|
||||
auto& segment = collisionBuffer.segments.back();
|
||||
@@ -850,27 +856,29 @@ void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) {
|
||||
collisionBuffer.dynamicVertices.emplace_back(dynamicVertex);
|
||||
|
||||
if (feature.alongLine) {
|
||||
bucket.collisionCircle->triangles.emplace_back(index, index + 1, index + 2);
|
||||
bucket.collisionCircle->triangles.emplace_back(index, index + 2, index + 3);
|
||||
auto& collisionCircle = (isText ? bucket.textCollisionCircle : bucket.iconCollisionCircle);
|
||||
collisionCircle->triangles.emplace_back(index, index + 1, index + 2);
|
||||
collisionCircle->triangles.emplace_back(index, index + 2, index + 3);
|
||||
} else {
|
||||
bucket.collisionBox->lines.emplace_back(index + 0, index + 1);
|
||||
bucket.collisionBox->lines.emplace_back(index + 1, index + 2);
|
||||
bucket.collisionBox->lines.emplace_back(index + 2, index + 3);
|
||||
bucket.collisionBox->lines.emplace_back(index + 3, index + 0);
|
||||
auto& collisionBox = (isText ? bucket.textCollisionBox : bucket.iconCollisionBox);
|
||||
collisionBox->lines.emplace_back(index + 0, index + 1);
|
||||
collisionBox->lines.emplace_back(index + 1, index + 2);
|
||||
collisionBox->lines.emplace_back(index + 2, index + 3);
|
||||
collisionBox->lines.emplace_back(index + 3, index + 0);
|
||||
}
|
||||
|
||||
segment.vertexLength += vertexLength;
|
||||
segment.indexLength += indexLength;
|
||||
}
|
||||
};
|
||||
populateCollisionBox(symbolInstance.textCollisionFeature);
|
||||
populateCollisionBox(symbolInstance.textCollisionFeature, true /*isText*/);
|
||||
if (symbolInstance.verticalTextCollisionFeature) {
|
||||
populateCollisionBox(*symbolInstance.verticalTextCollisionFeature);
|
||||
populateCollisionBox(*symbolInstance.verticalTextCollisionFeature, true /*isText*/);
|
||||
}
|
||||
if (symbolInstance.verticalIconCollisionFeature) {
|
||||
populateCollisionBox(*symbolInstance.verticalIconCollisionFeature);
|
||||
populateCollisionBox(*symbolInstance.verticalIconCollisionFeature, false /*isText*/);
|
||||
}
|
||||
populateCollisionBox(symbolInstance.iconCollisionFeature);
|
||||
populateCollisionBox(symbolInstance.iconCollisionFeature, false /*isText*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 (hasCollisionCircleData()) {
|
||||
if (hasTextCollisionBoxData()) {
|
||||
updateCollisionBox(*textCollisionBox);
|
||||
}
|
||||
|
||||
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::hasCollisionCircleData() const {
|
||||
return collisionCircle && !collisionCircle->segments.empty();
|
||||
bool SymbolBucket::hasIconCollisionCircleData() const {
|
||||
return iconCollisionCircle && !iconCollisionCircle->segments.empty();
|
||||
}
|
||||
|
||||
bool SymbolBucket::hasTextCollisionBoxData() const {
|
||||
return textCollisionBox && !textCollisionBox->segments.empty();
|
||||
}
|
||||
|
||||
bool SymbolBucket::hasTextCollisionCircleData() const {
|
||||
return textCollisionCircle && !textCollisionCircle->segments.empty();
|
||||
}
|
||||
|
||||
void addPlacedSymbol(gfx::IndexVector<gfx::Triangles>& triangles, const PlacedSymbol& placedSymbol) {
|
||||
|
||||
@@ -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& getOrCreateCollisionCircleBuffer() {
|
||||
if (!collisionCircle) collisionCircle = std::make_unique<CollisionCircleBuffer>();
|
||||
return *collisionCircle;
|
||||
CollisionCircleBuffer& getOrCreateIconCollisionCircleBuffer() {
|
||||
if (!iconCollisionCircle) iconCollisionCircle = std::make_unique<CollisionCircleBuffer>();
|
||||
return *iconCollisionCircle;
|
||||
}
|
||||
|
||||
CollisionCircleBuffer& getOrCreateTextCollisionCircleBuffer() {
|
||||
if (!textCollisionCircle) textCollisionCircle = std::make_unique<CollisionCircleBuffer>();
|
||||
return *textCollisionCircle;
|
||||
}
|
||||
|
||||
const float tilePixelRatio;
|
||||
|
||||
@@ -392,10 +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;
|
||||
|
||||
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 =
|
||||
@@ -403,68 +404,69 @@ void RenderSymbolLayer::render(PaintParameters& parameters) {
|
||||
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()
|
||||
);
|
||||
}
|
||||
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 (bucket.hasCollisionCircleData()) {
|
||||
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 =
|
||||
{{
|
||||
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()
|
||||
);
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -159,7 +159,6 @@ void Placement::placeBucket(
|
||||
const bool rotateWithMap = layout.get<style::TextRotationAlignment>() == style::AlignmentType::Map;
|
||||
const bool pitchWithMap = layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map;
|
||||
const bool hasIconTextFit = layout.get<style::IconTextFit>() != style::IconTextFitType::None;
|
||||
const bool hasCollisionCircleData = bucket.hasCollisionCircleData();
|
||||
|
||||
const bool zOrderByViewportY = layout.get<style::SymbolZOrder>() == style::SymbolZOrderType::ViewportY;
|
||||
std::vector<ProjectedCollisionBox> textBoxes;
|
||||
@@ -418,13 +417,14 @@ void Placement::placeBucket(
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCollisionCircleData) {
|
||||
if (symbolInstance.iconCollisionFeature.alongLine && !iconBoxes.empty()) {
|
||||
collisionCircles[&symbolInstance.iconCollisionFeature] = iconBoxes;
|
||||
}
|
||||
if (symbolInstance.textCollisionFeature.alongLine && !textBoxes.empty()) {
|
||||
collisionCircles[&symbolInstance.textCollisionFeature] = textBoxes;
|
||||
}
|
||||
const bool hasIconCollisionCircleData = bucket.hasIconCollisionCircleData();
|
||||
const bool hasTextCollisionCircleData = bucket.hasTextCollisionCircleData();
|
||||
|
||||
if (hasIconCollisionCircleData && symbolInstance.iconCollisionFeature.alongLine && !iconBoxes.empty()) {
|
||||
collisionCircles[&symbolInstance.iconCollisionFeature] = iconBoxes;
|
||||
}
|
||||
if (hasTextCollisionCircleData && symbolInstance.textCollisionFeature.alongLine && !textBoxes.empty()) {
|
||||
collisionCircles[&symbolInstance.textCollisionFeature] = textBoxes;
|
||||
}
|
||||
|
||||
assert(symbolInstance.crossTileID != 0);
|
||||
@@ -696,8 +696,10 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
|
||||
if (bucket.hasTextData()) bucket.text.opacityVertices.clear();
|
||||
if (bucket.hasIconData()) bucket.icon.opacityVertices.clear();
|
||||
if (bucket.hasSdfIconData()) bucket.sdfIcon.opacityVertices.clear();
|
||||
if (bucket.hasCollisionBoxData()) bucket.collisionBox->dynamicVertices.clear();
|
||||
if (bucket.hasCollisionCircleData()) bucket.collisionCircle->dynamicVertices.clear();
|
||||
if (bucket.hasIconCollisionBoxData()) bucket.iconCollisionBox->dynamicVertices.clear();
|
||||
if (bucket.hasIconCollisionCircleData()) bucket.iconCollisionCircle->dynamicVertices.clear();
|
||||
if (bucket.hasTextCollisionBoxData()) bucket.textCollisionBox->dynamicVertices.clear();
|
||||
if (bucket.hasTextCollisionCircleData()) bucket.textCollisionCircle->dynamicVertices.clear();
|
||||
|
||||
JointOpacityState duplicateOpacityState(false, false, true);
|
||||
|
||||
@@ -788,15 +790,15 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
|
||||
}
|
||||
}
|
||||
|
||||
auto updateCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
|
||||
auto updateIconCollisionBox = [&](const auto& feature, const bool placed, const Point<float>& shift) {
|
||||
if (feature.alongLine) {
|
||||
return;
|
||||
}
|
||||
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false, shift);
|
||||
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
|
||||
bucket.iconCollisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
|
||||
};
|
||||
|
||||
auto updateCollisionTextBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
|
||||
auto updateTextCollisionBox = [this, &bucket, &symbolInstance, &state, variablePlacement, rotateWithMap, pitchWithMap](const auto& feature, const bool placed) {
|
||||
Point<float> shift{0.0f, 0.0f};
|
||||
if (feature.alongLine) {
|
||||
return shift;
|
||||
@@ -826,11 +828,11 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
|
||||
}
|
||||
}
|
||||
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !used, shift);
|
||||
bucket.collisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
|
||||
bucket.textCollisionBox->dynamicVertices.extend(feature.boxes.size() * 4, dynamicVertex);
|
||||
return shift;
|
||||
};
|
||||
|
||||
auto updateCollisionCircles = [&](const auto& feature, const bool placed) {
|
||||
auto updateCollisionCircles = [&](const auto& feature, const bool placed, bool isText) {
|
||||
if (!feature.alongLine) {
|
||||
return;
|
||||
}
|
||||
@@ -838,31 +840,36 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, const TransformState
|
||||
if (circles != collisionCircles.end()) {
|
||||
for (const auto& circle : circles->second) {
|
||||
const auto& dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, !circle.isCircle(), {});
|
||||
bucket.collisionCircle->dynamicVertices.extend(4, dynamicVertex);
|
||||
isText ? bucket.textCollisionCircle->dynamicVertices.extend(4, dynamicVertex):
|
||||
bucket.iconCollisionCircle->dynamicVertices.extend(4, dynamicVertex);
|
||||
}
|
||||
} else {
|
||||
// This feature was not placed, because it was not loaded or from a fading tile. Apply default values.
|
||||
static const auto dynamicVertex = CollisionBoxProgram::dynamicVertex(placed, false /*not used*/, {});
|
||||
bucket.collisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex);
|
||||
isText ? bucket.textCollisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex):
|
||||
bucket.iconCollisionCircle->dynamicVertices.extend(4 * feature.boxes.size(), dynamicVertex);
|
||||
}
|
||||
};
|
||||
|
||||
if (bucket.hasCollisionBoxData()) {
|
||||
const auto& textShift = updateCollisionTextBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
|
||||
if (bucket.allowVerticalPlacement) {
|
||||
Point<float> verticalTextShift{0.0f, 0.0f};
|
||||
if (symbolInstance.verticalTextCollisionFeature) {
|
||||
verticalTextShift = updateCollisionTextBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
|
||||
}
|
||||
if (symbolInstance.verticalIconCollisionFeature) {
|
||||
updateCollisionBox(*symbolInstance.verticalIconCollisionFeature, opacityState.text.placed, hasIconTextFit ? verticalTextShift : Point<float>{0.0f, 0.0f});
|
||||
}
|
||||
Point<float> textShift{0.0f, 0.0f};
|
||||
Point<float> verticalTextShift{0.0f, 0.0f};
|
||||
if (bucket.hasTextCollisionBoxData()) {
|
||||
textShift = updateTextCollisionBox(symbolInstance.textCollisionFeature, opacityState.text.placed);
|
||||
if (bucket.allowVerticalPlacement && symbolInstance.verticalTextCollisionFeature) {
|
||||
verticalTextShift = updateTextCollisionBox(*symbolInstance.verticalTextCollisionFeature, opacityState.text.placed);
|
||||
}
|
||||
updateCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed, hasIconTextFit ? textShift : Point<float>{0.0f, 0.0f});
|
||||
}
|
||||
if (bucket.hasCollisionCircleData()) {
|
||||
updateCollisionCircles(symbolInstance.textCollisionFeature, opacityState.text.placed);
|
||||
updateCollisionCircles(symbolInstance.iconCollisionFeature, opacityState.icon.placed);
|
||||
if (bucket.hasIconCollisionBoxData()) {
|
||||
updateIconCollisionBox(symbolInstance.iconCollisionFeature, opacityState.icon.placed, hasIconTextFit ? textShift : Point<float>{0.0f, 0.0f});
|
||||
if (bucket.allowVerticalPlacement && symbolInstance.verticalIconCollisionFeature) {
|
||||
updateIconCollisionBox(*symbolInstance.verticalIconCollisionFeature, opacityState.text.placed, hasIconTextFit ? verticalTextShift : Point<float>{0.0f, 0.0f});
|
||||
}
|
||||
}
|
||||
|
||||
if (bucket.hasIconCollisionCircleData()) {
|
||||
updateCollisionCircles(symbolInstance.iconCollisionFeature, opacityState.icon.placed, false);
|
||||
}
|
||||
if (bucket.hasTextCollisionCircleData()) {
|
||||
updateCollisionCircles(symbolInstance.textCollisionFeature, opacityState.text.placed, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,10 @@ TEST(Buckets, SymbolBucket) {
|
||||
ASSERT_FALSE(bucket.hasIconData());
|
||||
ASSERT_FALSE(bucket.hasSdfIconData());
|
||||
ASSERT_FALSE(bucket.hasTextData());
|
||||
ASSERT_FALSE(bucket.hasCollisionBoxData());
|
||||
ASSERT_FALSE(bucket.hasIconCollisionBoxData());
|
||||
ASSERT_FALSE(bucket.hasTextCollisionBoxData());
|
||||
ASSERT_FALSE(bucket.hasIconCollisionCircleData());
|
||||
ASSERT_FALSE(bucket.hasTextCollisionCircleData());
|
||||
ASSERT_FALSE(bucket.hasData());
|
||||
ASSERT_FALSE(bucket.needsUpload());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user