port collision box debug rendering

This commit is contained in:
Ansis Brammanis
2015-04-01 13:22:16 -07:00
parent 8fd42f371f
commit dda1b770da
13 changed files with 245 additions and 1 deletions

View File

@@ -0,0 +1,27 @@
#include <mbgl/geometry/collision_box_buffer.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/util/math.hpp>
#include <cmath>
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<int16_t *>(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<uint8_t *>(data);
// a_data1
ubytes[8] = maxzoom * 10;
ubytes[9] = placementZoom * 10;
return idx;
}
}

View File

@@ -0,0 +1,23 @@
#ifndef MBGL_GEOMETRY_COLLISIONBOX_BUFFER
#define MBGL_GEOMETRY_COLLISIONBOX_BUFFER
#include <mbgl/geometry/buffer.hpp>
#include <array>
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

View File

@@ -8,6 +8,7 @@
#include <mbgl/geometry/icon_buffer.hpp>
#include <mbgl/geometry/line_buffer.hpp>
#include <mbgl/geometry/text_buffer.hpp>
#include <mbgl/geometry/collision_box_buffer.hpp>
#include <iosfwd>
#include <memory>
@@ -50,6 +51,7 @@ protected:
LineVertexBuffer lineVertexBuffer;
IconVertexBuffer iconVertexBuffer;
TextVertexBuffer textVertexBuffer;
CollisionBoxVertexBuffer collisionBoxVertexBuffer;
TriangleElementsBuffer triangleElementsBuffer;
LineElementsBuffer lineElementsBuffer;

View File

@@ -106,6 +106,7 @@ void Painter::setupShaders() {
if (!sdfIconShader) sdfIconShader = util::make_unique<SDFIconShader>();
if (!dotShader) dotShader = util::make_unique<DotShader>();
if (!gaussianShader) gaussianShader = util::make_unique<GaussianShader>();
if (!collisionBoxShader) collisionBoxShader = util::make_unique<CollisionBoxShader>();
}
void Painter::deleteShaders() {

View File

@@ -21,6 +21,7 @@
#include <mbgl/shader/sdf_shader.hpp>
#include <mbgl/shader/dot_shader.hpp>
#include <mbgl/shader/gaussian_shader.hpp>
#include <mbgl/shader/box_shader.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/ptr.hpp>
@@ -212,6 +213,7 @@ public:
std::unique_ptr<SDFIconShader> sdfIconShader;
std::unique_ptr<DotShader> dotShader;
std::unique_ptr<GaussianShader> gaussianShader;
std::unique_ptr<CollisionBoxShader> collisionBoxShader;
StaticVertexBuffer backgroundBuffer = {
{ -1, -1 }, { 1, -1 },

View File

@@ -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));
}

View File

@@ -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<SymbolFeature> SymbolBucket::processFeatures(const GeometryTileLayer& layer,
const FilterExpression& filter,
GlyphStore &glyphStore,
@@ -317,6 +319,8 @@ void SymbolBucket::placeFeatures() {
addSymbols<IconBuffer, IconElementGroup>(icon, symbolInstance.iconQuads, iconScale);
}
}
addToDebugBuffers();
}
template <typename Buffer, typename GroupType>
@@ -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<float, 4> 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<float> tl{box.x1, box.y1 * yStretch};
vec2<float> tr{box.x2, box.y1 * yStretch};
vec2<float> bl{box.x1, box.y2 * yStretch};
vec2<float> 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<float>(zoom + log(box.maxScale) / log(2))));
const float placementZoom= util::max(0.0f, util::min(25.0f, static_cast<float>(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<CollisionBoxElementGroup>());
}
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));
}
}
}

View File

@@ -7,6 +7,7 @@
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/text_buffer.hpp>
#include <mbgl/geometry/icon_buffer.hpp>
#include <mbgl/geometry/collision_box_buffer.hpp>
#include <mbgl/text/types.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/text/collision_feature.hpp>
@@ -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<const StyleLayoutSymbol> 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<SymbolFeature> processFeatures(const GeometryTileLayer&,
@@ -93,6 +98,7 @@ private:
const GlyphPositions &face);
void placeFeatures();
void addToDebugBuffers();
// Adds placed items to the buffer.
template <typename Buffer, typename GroupType>
@@ -118,6 +124,11 @@ private:
std::vector<std::unique_ptr<IconElementGroup>> groups;
} icon;
struct CollisionBoxBuffer {
CollisionBoxVertexBuffer vertices;
std::vector<std::unique_ptr<CollisionBoxElementGroup>> groups;
} collisionBox;
};
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,32 @@
#include <mbgl/shader/box_shader.hpp>
#include <mbgl/shader/shaders.hpp>
#include <mbgl/platform/gl.hpp>
#include <cstdio>
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));
}

View File

@@ -0,0 +1,28 @@
#ifndef MBGL_SHADER_SHADER_BOX
#define MBGL_SHADER_SHADER_BOX
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
namespace mbgl {
class CollisionBoxShader : public Shader {
public:
CollisionBoxShader();
void bind(char *offset);
UniformMatrix<4> u_matrix = {"u_matrix", *this};
Uniform<float> u_scale = {"u_scale", *this};
Uniform<float> u_zoom = {"u_zoom", *this};
Uniform<float> u_maxzoom = {"u_maxzoom", *this};
protected:
int32_t a_pos = -1;
int32_t a_extrude = -1;
int32_t a_data = -1;
};
}
#endif

View File

@@ -17,7 +17,7 @@ CollisionFeature::CollisionFeature(const std::vector<Coordinate> &line, const An
bboxifyLabel(line, anchor, length, height);
} else {
boxes.emplace_back(anchor, x1, y2, x2, y2, std::numeric_limits<float>::infinity());
boxes.emplace_back(anchor, x1, y1, x2, y2, std::numeric_limits<float>::infinity());
}
}