summaryrefslogtreecommitdiff
path: root/src/mbgl/geometry/dem_pyramid.cpp
blob: fb3a9d108e734eceea8fd54a64a172739f64ed16 (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
#include <mbgl/geometry/dem_pyramid.hpp>

namespace mbgl {

void DEMPyramid::buildLevels() {
    while (true) {
        auto& prev = levels.back();
        const int32_t width = std::ceil(prev.width / 2);
        const int32_t height = std::ceil(prev.height / 2);
        const int32_t border = std::max<int32_t>(std::ceil(prev.border / 2), 1);

        if (width == 1 || height == 1) {
            break;
        }
        Level next(width, height, border);
        prev.resample(next);
        levels.emplace_back(std::move(next));
    }

    // Build remaining two levels. They aren't actually used in rendering, but we
    // need them for OpenGL's mipmapping feature.
    levels.emplace_back(2, 2, 0);
    levels.emplace_back(1, 1, 0);
}

DEMPyramid::Level::Level(int32_t width_, int32_t height_, size_t border_)
    : width(width_),
      height(height_),
      border(border_),
      stride(width + 2 * border),
      image({ static_cast<uint32_t>(width + 2 * border),
              static_cast<uint32_t>(height + 2 * border) }) {
    assert(width > 0);
    assert(height > 0);
    std::memset(image.data.get(), 0, image.bytes());
}

void DEMPyramid::Level::resample(Level& target) {
    for (int32_t y = 0; y < target.height; y++) {
        const int32_t fy = y * 2;
        for (int32_t x = 0; x < target.width; x++) {
            const int32_t fx = x * 2;
            target.set(x, y, (get(fx, fy) + get(fx + 1, fy) + get(fx, fy + 1) + get(fx + 1, fy + 1)) / 4);
        }
    }
}

} // namespace mbgl