From dda1b770daa2c009abdaaa48d40917abc1571ca3 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Wed, 1 Apr 2015 13:22:16 -0700 Subject: [PATCH] port collision box debug rendering --- src/mbgl/geometry/collision_box_buffer.cpp | 27 ++++++++++ src/mbgl/geometry/collision_box_buffer.hpp | 23 ++++++++ src/mbgl/map/vector_tile_data.hpp | 2 + src/mbgl/renderer/painter.cpp | 1 + src/mbgl/renderer/painter.hpp | 2 + src/mbgl/renderer/painter_symbol.cpp | 15 ++++++ src/mbgl/renderer/symbol_bucket.cpp | 63 ++++++++++++++++++++++ src/mbgl/renderer/symbol_bucket.hpp | 11 ++++ src/mbgl/shader/box.fragment.glsl | 24 +++++++++ src/mbgl/shader/box.vertex.glsl | 16 ++++++ src/mbgl/shader/box_shader.cpp | 32 +++++++++++ src/mbgl/shader/box_shader.hpp | 28 ++++++++++ src/mbgl/text/collision_feature.cpp | 2 +- 13 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 src/mbgl/geometry/collision_box_buffer.cpp create mode 100644 src/mbgl/geometry/collision_box_buffer.hpp create mode 100644 src/mbgl/shader/box.fragment.glsl create mode 100644 src/mbgl/shader/box.vertex.glsl create mode 100644 src/mbgl/shader/box_shader.cpp create mode 100644 src/mbgl/shader/box_shader.hpp diff --git a/src/mbgl/geometry/collision_box_buffer.cpp b/src/mbgl/geometry/collision_box_buffer.cpp new file mode 100644 index 000000000..050a999db --- /dev/null +++ b/src/mbgl/geometry/collision_box_buffer.cpp @@ -0,0 +1,27 @@ +#include +#include +#include + +#include + +namespace mbgl { + +size_t CollisionBoxVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, float maxzoom, float placementZoom) { + const size_t idx = index(); + void *data = addElement(); + + int16_t *shorts = static_cast(data); + shorts[0] /* pos */ = x; + shorts[1] /* pos */ = y; + shorts[2] /* offset */ = std::round(ox); // use 1/64 pixels for placement + shorts[3] /* offset */ = std::round(oy); + + uint8_t *ubytes = static_cast(data); + // a_data1 + ubytes[8] = maxzoom * 10; + ubytes[9] = placementZoom * 10; + + return idx; +} + +} diff --git a/src/mbgl/geometry/collision_box_buffer.hpp b/src/mbgl/geometry/collision_box_buffer.hpp new file mode 100644 index 000000000..098eab13c --- /dev/null +++ b/src/mbgl/geometry/collision_box_buffer.hpp @@ -0,0 +1,23 @@ +#ifndef MBGL_GEOMETRY_COLLISIONBOX_BUFFER +#define MBGL_GEOMETRY_COLLISIONBOX_BUFFER + +#include +#include + +namespace mbgl { + +class CollisionBoxVertexBuffer : public Buffer < + 12, + GL_ARRAY_BUFFER, + 32768 +> { +public: + typedef int16_t vertex_type; + + size_t add(int16_t x, int16_t y, float ex, float ey, float maxzoom, float placementZoom); +}; + + +} + +#endif diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp index 7f43d824a..90b25cd74 100644 --- a/src/mbgl/map/vector_tile_data.hpp +++ b/src/mbgl/map/vector_tile_data.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ protected: LineVertexBuffer lineVertexBuffer; IconVertexBuffer iconVertexBuffer; TextVertexBuffer textVertexBuffer; + CollisionBoxVertexBuffer collisionBoxVertexBuffer; TriangleElementsBuffer triangleElementsBuffer; LineElementsBuffer lineElementsBuffer; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index dae9c766c..9e5335319 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -106,6 +106,7 @@ void Painter::setupShaders() { if (!sdfIconShader) sdfIconShader = util::make_unique(); if (!dotShader) dotShader = util::make_unique(); if (!gaussianShader) gaussianShader = util::make_unique(); + if (!collisionBoxShader) collisionBoxShader = util::make_unique(); } void Painter::deleteShaders() { diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 9c9c6a464..0b2d1b5a7 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -212,6 +213,7 @@ public: std::unique_ptr sdfIconShader; std::unique_ptr dotShader; std::unique_ptr gaussianShader; + std::unique_ptr collisionBoxShader; StaticVertexBuffer backgroundBuffer = { { -1, -1 }, { 1, -1 }, diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 366d33d50..5cf3fd22d 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -189,5 +189,20 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c &SymbolBucket::drawGlyphs); } + if (bucket.hasCollisionBoxData()) { + MBGL_CHECK_ERROR(glEnable(GL_STENCIL_TEST)); + + useProgram(collisionBoxShader->program); + collisionBoxShader->u_matrix = matrix; + collisionBoxShader->u_scale = std::pow(2, state.getNormalizedZoom() - id.z); + collisionBoxShader->u_zoom = state.getNormalizedZoom() * 10; + collisionBoxShader->u_maxzoom = (id.z + 1) * 10; + lineWidth(3.0f); + + depthRange(strata, 1.0f); + bucket.drawCollisionBoxes(*collisionBoxShader); + + } + MBGL_CHECK_ERROR(glEnable(GL_STENCIL_TEST)); } diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index bcf02b432..45e8819b0 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -59,6 +59,8 @@ bool SymbolBucket::hasTextData() const { return !text.groups.empty(); } bool SymbolBucket::hasIconData() const { return !icon.groups.empty(); } +bool SymbolBucket::hasCollisionBoxData() const { return !collisionBox.groups.empty(); } + std::vector SymbolBucket::processFeatures(const GeometryTileLayer& layer, const FilterExpression& filter, GlyphStore &glyphStore, @@ -317,6 +319,8 @@ void SymbolBucket::placeFeatures() { addSymbols(icon, symbolInstance.iconQuads, iconScale); } } + + addToDebugBuffers(); } template @@ -379,6 +383,57 @@ void SymbolBucket::addSymbols(Buffer &buffer, const PlacedGlyphs &symbols, float } } +void SymbolBucket::addToDebugBuffers() { + + const float yStretch = 1.0f; + const float angle = 0.0f; + const float zoom = collision.zoom; + float angle_sin = std::sin(-angle); + float angle_cos = std::cos(-angle); + std::array matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}}; + + for (const SymbolInstance &symbolInstance : symbolInstances) { + for (int i = 0; i < 2; i++) { + auto& feature = i == 0 ? + symbolInstance.textCollisionFeature : + symbolInstance.iconCollisionFeature; + + for (const CollisionBox &box : feature.boxes) { + auto& anchor = box.anchor; + + vec2 tl{box.x1, box.y1 * yStretch}; + vec2 tr{box.x2, box.y1 * yStretch}; + vec2 bl{box.x1, box.y2 * yStretch}; + vec2 br{box.x2, box.y2 * yStretch}; + tl = tl.matMul(matrix); + tr = tr.matMul(matrix); + bl = bl.matMul(matrix); + br = br.matMul(matrix); + + const float maxZoom = util::max(0.0f, util::min(25.0f, static_cast(zoom + log(box.maxScale) / log(2)))); + const float placementZoom= util::max(0.0f, util::min(25.0f, static_cast(zoom + log(box.placementScale) / log(2)))); + + if (!collisionBox.groups.size()) { + // Move to a new group because the old one can't hold the geometry. + collisionBox.groups.emplace_back(util::make_unique()); + } + + collisionBox.vertices.add(anchor.x, anchor.y, tl.x, tl.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, tr.x, tr.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, tr.x, tr.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, br.x, br.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, br.x, br.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, bl.x, bl.y, maxZoom, placementZoom); + collisionBox.vertices.add(anchor.x, anchor.y, tl.x, tl.y, maxZoom, placementZoom); + + auto &group= *collisionBox.groups.back(); + group.vertex_length += 8; + } + } + } +} + void SymbolBucket::drawGlyphs(SDFShader &shader) { char *vertex_index = BUFFER_OFFSET(0); char *elements_index = BUFFER_OFFSET(0); @@ -414,4 +469,12 @@ void SymbolBucket::drawIcons(IconShader &shader) { elements_index += group->elements_length * icon.triangles.itemSize; } } + +void SymbolBucket::drawCollisionBoxes(CollisionBoxShader &shader) { + char *vertex_index = BUFFER_OFFSET(0); + for (auto &group : collisionBox.groups) { + group->array[0].bind(shader, collisionBox.vertices, vertex_index); + MBGL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, group->vertex_length)); + } +} } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index d11417311..0b506021a 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ class Style; class StyleLayoutSymbol; class SDFShader; class IconShader; +class CollisionBoxShader; class DotShader; class Collision; class SpriteAtlas; @@ -60,6 +62,7 @@ class SymbolInstance { class SymbolBucket : public Bucket { typedef ElementGroup<1> TextElementGroup; typedef ElementGroup<2> IconElementGroup; + typedef ElementGroup<1> CollisionBoxElementGroup; public: SymbolBucket(std::unique_ptr styleLayout, Collision &collision); @@ -70,6 +73,7 @@ public: bool hasData() const override; bool hasTextData() const; bool hasIconData() const; + bool hasCollisionBoxData() const; void addFeatures(const GeometryTileLayer&, const FilterExpression&, @@ -82,6 +86,7 @@ public: void drawGlyphs(SDFShader& shader); void drawIcons(SDFShader& shader); void drawIcons(IconShader& shader); + void drawCollisionBoxes(CollisionBoxShader& shader); private: std::vector processFeatures(const GeometryTileLayer&, @@ -93,6 +98,7 @@ private: const GlyphPositions &face); void placeFeatures(); + void addToDebugBuffers(); // Adds placed items to the buffer. template @@ -118,6 +124,11 @@ private: std::vector> groups; } icon; + struct CollisionBoxBuffer { + CollisionBoxVertexBuffer vertices; + std::vector> groups; + } collisionBox; + }; } diff --git a/src/mbgl/shader/box.fragment.glsl b/src/mbgl/shader/box.fragment.glsl new file mode 100644 index 000000000..030f1219f --- /dev/null +++ b/src/mbgl/shader/box.fragment.glsl @@ -0,0 +1,24 @@ +uniform float u_zoom; +uniform float u_maxzoom; + +varying float v_max_zoom; +varying float v_placement_zoom; + +void main() { + + float alpha = 0.5; + + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0) * alpha; + + if (v_placement_zoom > u_zoom) { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * alpha; + } + + if (u_zoom >= v_max_zoom) { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) * alpha * 0.25; + } + + if (v_placement_zoom >= u_maxzoom) { + gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0) * alpha * 0.2; + } +} diff --git a/src/mbgl/shader/box.vertex.glsl b/src/mbgl/shader/box.vertex.glsl new file mode 100644 index 000000000..d141b1387 --- /dev/null +++ b/src/mbgl/shader/box.vertex.glsl @@ -0,0 +1,16 @@ +attribute vec2 a_pos; +attribute vec2 a_extrude; +attribute vec2 a_data; + +uniform mat4 u_matrix; +uniform float u_scale; + +varying float v_max_zoom; +varying float v_placement_zoom; + +void main() { + gl_Position = u_matrix * vec4(a_pos + a_extrude / u_scale, 0.0, 1.0); + + v_max_zoom = a_data.x; + v_placement_zoom = a_data.y; +} diff --git a/src/mbgl/shader/box_shader.cpp b/src/mbgl/shader/box_shader.cpp new file mode 100644 index 000000000..2676223a9 --- /dev/null +++ b/src/mbgl/shader/box_shader.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +#include + +using namespace mbgl; + +CollisionBoxShader::CollisionBoxShader() + : Shader( + "collisionbox", + shaders[BOX_SHADER].vertex, + shaders[BOX_SHADER].fragment + ) { + a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos")); + a_extrude = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_extrude")); + a_data = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_data")); +} + +void CollisionBoxShader::bind(char *offset) { + const int stride = 12; + + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0)); + + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_extrude)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_extrude, 2, GL_SHORT, false, stride, offset + 4)); + + MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data)); + MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 2, GL_UNSIGNED_BYTE, false, stride, offset + 8)); + +} diff --git a/src/mbgl/shader/box_shader.hpp b/src/mbgl/shader/box_shader.hpp new file mode 100644 index 000000000..5c84d8906 --- /dev/null +++ b/src/mbgl/shader/box_shader.hpp @@ -0,0 +1,28 @@ +#ifndef MBGL_SHADER_SHADER_BOX +#define MBGL_SHADER_SHADER_BOX + +#include +#include + +namespace mbgl { + +class CollisionBoxShader : public Shader { +public: + CollisionBoxShader(); + + void bind(char *offset); + + UniformMatrix<4> u_matrix = {"u_matrix", *this}; + Uniform u_scale = {"u_scale", *this}; + Uniform u_zoom = {"u_zoom", *this}; + Uniform u_maxzoom = {"u_maxzoom", *this}; + +protected: + int32_t a_pos = -1; + int32_t a_extrude = -1; + int32_t a_data = -1; +}; + +} + +#endif diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp index e68774600..f2205da09 100644 --- a/src/mbgl/text/collision_feature.cpp +++ b/src/mbgl/text/collision_feature.cpp @@ -17,7 +17,7 @@ CollisionFeature::CollisionFeature(const std::vector &line, const An bboxifyLabel(line, anchor, length, height); } else { - boxes.emplace_back(anchor, x1, y2, x2, y2, std::numeric_limits::infinity()); + boxes.emplace_back(anchor, x1, y1, x2, y2, std::numeric_limits::infinity()); } }