summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/circle_bucket.cpp
blob: 1ebe8ffaf38ec1f3452f7fb0af4dd77ddd4433d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <mbgl/renderer/circle_bucket.hpp>
#include <mbgl/renderer/painter.hpp>

#include <mbgl/shader/circle_shader.hpp>
#include <mbgl/layer/circle_layer.hpp>
#include <mbgl/util/constants.hpp>

using namespace mbgl;

CircleBucket::CircleBucket() {
}

CircleBucket::~CircleBucket() {
    // Do not remove. header file only contains forward definitions to unique pointers.
}

void CircleBucket::upload() {
    vertexBuffer_.upload();
    elementsBuffer_.upload();
    uploaded = true;
}

void CircleBucket::render(Painter& painter,
                        const StyleLayer& layer,
                        const TileID& id,
                        const mat4& matrix) {
    painter.renderCircle(*this, *layer.as<CircleLayer>(), id, matrix);
}

bool CircleBucket::hasData() const {
    return !triangleGroups_.empty();
}

void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
    for (auto& circle : geometryCollection) {
        for(auto & geometry : circle) {
            auto x = geometry.x;
            auto y = geometry.y;

            // Do not include points that are outside the tile boundaries.
            if (x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT) continue;

            // this geometry will be of the Point type, and we'll derive
            // two triangles from it.
            //
            // ┌─────────┐
            // │ 4     3 │
            // │         │
            // │ 1     2 │
            // └─────────┘
            //
            vertexBuffer_.add(x, y, -1, -1); // 1
            vertexBuffer_.add(x, y, 1, -1); // 2
            vertexBuffer_.add(x, y, 1, 1); // 3
            vertexBuffer_.add(x, y, -1, 1); // 4

            if (!triangleGroups_.size() || (triangleGroups_.back()->vertex_length + 4 > 65535)) {
                // Move to a new group because the old one can't hold the geometry.
                triangleGroups_.emplace_back(std::make_unique<TriangleGroup>());
            }

            TriangleGroup& group = *triangleGroups_.back();
            auto index = group.vertex_length;

            // 1, 2, 3
            // 1, 4, 3
            elementsBuffer_.add(index, index + 1, index + 2);
            elementsBuffer_.add(index, index + 3, index + 2);

            group.vertex_length += 4;
            group.elements_length += 2;
        }
    }
}

void CircleBucket::drawCircles(CircleShader& shader) {
    GLbyte* vertexIndex = BUFFER_OFFSET(0);
    GLbyte* elementsIndex = BUFFER_OFFSET(0);

    for (auto& group : triangleGroups_) {
        assert(group);

        if (!group->elements_length) continue;

        group->array[0].bind(shader, vertexBuffer_, elementsBuffer_, vertexIndex);

        MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elementsIndex));

        vertexIndex += group->vertex_length * vertexBuffer_.itemSize;
        elementsIndex += group->elements_length * elementsBuffer_.itemSize;
    }
}