Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

remove Level class #10964

Merged
merged 1 commit into from
Jan 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 35 additions & 41 deletions src/mbgl/geometry/dem_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@

namespace mbgl {

DEMData::DEMData(const PremultipliedImage& image):
level(image.size.height, std::max<int32_t>(std::ceil(image.size.height / 2), 1)){
if (image.size.height != image.size.width){
DEMData::DEMData(const PremultipliedImage& _image):
dim(_image.size.height),
border(std::max<int32_t>(std::ceil(_image.size.height / 2), 1)),
stride(dim + 2 * border),
image({ static_cast<uint32_t>(stride), static_cast<uint32_t>(stride) }) {

if (_image.size.height != _image.size.width){
throw std::runtime_error("raster-dem tiles must be square.");
}

for (int32_t y = 0; y < level.dim; y++) {
for (int32_t x = 0; x < level.dim; x++) {
const int32_t i = y * level.dim + x;
std::memset(image.data.get(), 0, image.bytes());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed if all bits are being set in the for loop below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the loop doesn't set all bits bc there is an empty 254px border around the image (need 1px border, but also need texture to be power of 2)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

homer-disappear


for (int32_t y = 0; y < dim; y++) {
for (int32_t x = 0; x < dim; x++) {
const int32_t i = y * dim + x;
const int32_t j = i * 4;
level.set(x, y, (image.data[j] * 256 * 256 + image.data[j+1] * 256 + image.data[j+2])/10 - 10000);
set(x, y, (_image.data[j] * 256 * 256 + _image.data[j+1] * 256 + _image.data[j+2])/10 - 10000);
}
}

Expand All @@ -22,26 +28,25 @@ DEMData::DEMData(const PremultipliedImage& image):
// replaced when the tile's neighboring tiles are loaded and the accurate data can be backfilled using
// DEMData#backfillBorder

for (int32_t x = 0; x < level.dim; x++) {
for (int32_t x = 0; x < dim; x++) {
// left vertical border
level.set(-1, x, level.get(0, x));
set(-1, x, get(0, x));

// right vertical border
level.set(level.dim, x, level.get(level.dim - 1, x));
set(dim, x, get(dim - 1, x));

//left horizontal border
level.set(x, -1, level.get(x, 0));
set(x, -1, get(x, 0));

// right horizontal border
level.set(x, level.dim, level.get(x, level.dim - 1));
set(x, dim, get(x, dim - 1));
}

// corners
level.set(-1, -1, level.get(0, 0));
level.set(level.dim, -1, level.get(level.dim - 1, 0));
level.set( -1, level.dim, level.get(0, level.dim - 1));
level.set(level.dim, level.dim, level.get(level.dim - 1, level.dim - 1));
loaded = true;
set(-1, -1, get(0, 0));
set(dim, -1, get(dim - 1, 0));
set( -1, dim, get(0, dim - 1));
set(dim, dim, get(dim - 1, dim - 1));
}

// This function takes the DEMData from a neighboring tile and backfills the edge/corner
Expand All @@ -50,51 +55,40 @@ DEMData::DEMData(const PremultipliedImage& image):
// pixel of the tile by querying the 8 surrounding pixels, and if we don't have the pixel
// buffer we get seams at tile boundaries.
void DEMData::backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy) {
auto& t = level;
auto& o = borderTileData.level;
auto& o = borderTileData;

// Tiles from the same source should always be of the same dimensions.
assert(t.dim == o.dim);
assert(dim == o.dim);

// We determine the pixel range to backfill based which corner/edge `borderTileData`
// represents. For example, dx = -1, dy = -1 represents the upper left corner of the
// base tile, so we only need to backfill one pixel at coordinates (-1, -1) of the tile
// image.
int32_t _xMin = dx * t.dim;
int32_t _xMax = dx * t.dim + t.dim;
int32_t _yMin = dy * t.dim;
int32_t _yMax = dy * t.dim + t.dim;
int32_t _xMin = dx * dim;
int32_t _xMax = dx * dim + dim;
int32_t _yMin = dy * dim;
int32_t _yMax = dy * dim + dim;

if (dx == -1) _xMin = _xMax - 1;
else if (dx == 1) _xMax = _xMin + 1;

if (dy == -1) _yMin = _yMax - 1;
else if (dy == 1) _yMax = _yMin + 1;

int32_t xMin = util::clamp(_xMin, -t.border, t.dim + t.border);
int32_t xMax = util::clamp(_xMax, -t.border, t.dim + t.border);
int32_t xMin = util::clamp(_xMin, -border, dim + border);
int32_t xMax = util::clamp(_xMax, -border, dim + border);

int32_t yMin = util::clamp(_yMin, -t.border, t.dim + t.border);
int32_t yMax = util::clamp(_yMax, -t.border, t.dim + t.border);
int32_t yMin = util::clamp(_yMin, -border, dim + border);
int32_t yMax = util::clamp(_yMax, -border, dim + border);

int32_t ox = -dx * t.dim;
int32_t oy = -dy * t.dim;
int32_t ox = -dx * dim;
int32_t oy = -dy * dim;

for (int32_t y = yMin; y < yMax; y++) {
for (int32_t x = xMin; x < xMax; x++) {
t.set(x, y, o.get(x + ox, y + oy));
set(x, y, o.get(x + ox, y + oy));
}
}
}

DEMData::Level::Level(int32_t dim_, int32_t border_)
: dim(dim_),
border(border_),
stride(dim + 2 * border),
image({ static_cast<uint32_t>(stride),
static_cast<uint32_t>(stride) }) {
assert(dim > 0);
std::memset(image.data.get(), 0, image.bytes());
}

} // namespace mbgl
45 changes: 17 additions & 28 deletions src/mbgl/geometry/dem_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,29 @@ namespace mbgl {

class DEMData {
public:
class Level {
public:
Level(int32_t dim, int32_t border);
DEMData(const PremultipliedImage& image);
void backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy);

void set(const int32_t x, const int32_t y, const int32_t value) {
reinterpret_cast<int32_t*>(image.data.get())[idx(x, y)] = value + 65536;
}
void set(const int32_t x, const int32_t y, const int32_t value) {
reinterpret_cast<int32_t*>(image.data.get())[idx(x, y)] = value + 65536;
}

int32_t get(const int32_t x, const int32_t y) const {
return reinterpret_cast<const int32_t*>(image.data.get())[idx(x, y)] - 65536;
}
int32_t get(const int32_t x, const int32_t y) const {
return reinterpret_cast<const int32_t*>(image.data.get())[idx(x, y)] - 65536;
}

const PremultipliedImage* getImage() {
return &image;
}
const PremultipliedImage* getImage() const {
return &image;
}

const int32_t dim;
const int32_t border;
const int32_t stride;


private:
PremultipliedImage image;

size_t idx(const int32_t x, const int32_t y) const {
assert(x >= -border);
assert(x < dim + border);
Expand All @@ -38,22 +43,6 @@ class DEMData {
return (y + border) * stride + (x + border);
}

public:
const int32_t dim;
const int32_t border;
const int32_t stride;
PremultipliedImage image;
};

DEMData(const PremultipliedImage& image);
void backfillBorder(const DEMData& borderTileData, int8_t dx, int8_t dy);
bool isLoaded() const {
return loaded;
}
Level level;
private:
bool loaded = false;

};

} // namespace mbgl
4 changes: 2 additions & 2 deletions src/mbgl/renderer/buckets/hillshade_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void HillshadeBucket::upload(gl::Context& context) {
}


const PremultipliedImage* image = demdata.level.getImage();
const PremultipliedImage* image = demdata.getImage();
dem = context.createTexture(*image);

if (!segments.empty()) {
Expand Down Expand Up @@ -107,7 +107,7 @@ void HillshadeBucket::setMask(TileMask&& mask_) {
}

bool HillshadeBucket::hasData() const {
return demdata.level.image.valid();
return demdata.getImage()->valid();
}

} // namespace mbgl
2 changes: 1 addition & 1 deletion src/mbgl/renderer/layers/render_hillshade_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource*) {
}

if (!bucket.isPrepared() && parameters.pass == RenderPass::Pass3D) {
const uint16_t tilesize = bucket.getDEMData().level.dim;
const uint16_t tilesize = bucket.getDEMData().dim;
OffscreenTexture view(parameters.context, { tilesize, tilesize });
view.bind();

Expand Down
15 changes: 7 additions & 8 deletions src/mbgl/tile/raster_dem_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,13 @@ void RasterDEMTile::backfillBorder(const RasterDEMTile& borderTile, const DEMTil
const DEMData& borderDEM = borderBucket->getDEMData();
DEMData& tileDEM = bucket->getDEMData();

if (tileDEM.isLoaded() && borderDEM.isLoaded()){
tileDEM.backfillBorder(borderDEM, dx, dy);
// update the bitmask to indicate that this tiles have been backfilled by flipping the relevant bit
this->neighboringTiles = this->neighboringTiles | mask;
// mark HillshadeBucket.prepared as false so it runs through the prepare render pass
// with the new texture data we just backfilled
bucket->setPrepared(false);
}
tileDEM.backfillBorder(borderDEM, dx, dy);
// update the bitmask to indicate that this tiles have been backfilled by flipping the relevant bit
this->neighboringTiles = this->neighboringTiles | mask;
// mark HillshadeBucket.prepared as false so it runs through the prepare render pass
// with the new texture data we just backfilled
bucket->setPrepared(false);

}

void RasterDEMTile::setMask(TileMask&& mask) {
Expand Down
63 changes: 30 additions & 33 deletions test/geometry/dem_data.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,26 @@ auto fakeImage = [](Size s) {
return img;
};

TEST(Level, Constructor) {
DEMData::Level level(4, 2);
EXPECT_EQ(level.dim, 4);
EXPECT_EQ(level.border, 2);
EXPECT_EQ(level.stride, 8);
EXPECT_EQ(level.image.bytes(), size_t(8*8*4));
}

TEST(Level, RoundTrip) {
DEMData::Level level(4, 2);
level.set(0, 0, 255);
EXPECT_EQ(level.get(0,0), 255);
}

TEST(DEMData, Constructor) {
PremultipliedImage image = fakeImage({16, 16});
DEMData pyramid(image);

EXPECT_TRUE(pyramid.isLoaded());
EXPECT_EQ(pyramid.level.dim, 16);
EXPECT_EQ(pyramid.level.border, 8);
EXPECT_EQ(pyramid.dim, 16);
EXPECT_EQ(pyramid.border, 8);
EXPECT_EQ(pyramid.stride, 32);
EXPECT_EQ(pyramid.getImage()->bytes(), size_t(32*32*4));
EXPECT_EQ(pyramid.dim, 16);
EXPECT_EQ(pyramid.border, 8);
};

TEST(DEMData, RoundTrip) {
PremultipliedImage image = fakeImage({16, 16});
DEMData pyramid(image);

pyramid.set(4, 6, 255);
EXPECT_EQ(pyramid.get(4, 6), 255);
}

TEST(DEMData, InitialBackfill) {

PremultipliedImage image1 = fakeImage({4, 4});
Expand All @@ -47,7 +44,7 @@ TEST(DEMData, InitialBackfill) {
// with a non-empty pixel value
for (int x = -1; x < 5; x++){
for (int y = -1; y < 5; y ++) {
if (dem1.level.get(x, y) == -65536) {
if (dem1.get(x, y) == -65536) {
nonempty = false;
break;
}
Expand All @@ -59,7 +56,7 @@ TEST(DEMData, InitialBackfill) {
int vertx[] = {-1, 4};
for (int x : vertx) {
for (int y = 0; y < 4; y++) {
if (dem1.level.get(x, y) != dem1.level.get(x < 0 ? x + 1 : x - 1, y)) {
if (dem1.get(x, y) != dem1.get(x < 0 ? x + 1 : x - 1, y)) {
verticalBorderMatch = false;
break;
}
Expand All @@ -73,7 +70,7 @@ TEST(DEMData, InitialBackfill) {
int horiz[] = {-1, 4};
for (int y : horiz) {
for (int x = 0; x < 4; x++) {
if (dem1.level.get(x, y) != dem1.level.get(x, y < 0 ? y + 1 : y - 1)) {
if (dem1.get(x, y) != dem1.get(x, y < 0 ? y + 1 : y - 1)) {
horizontalBorderMatch = false;
break;
}
Expand All @@ -83,13 +80,13 @@ TEST(DEMData, InitialBackfill) {

EXPECT_TRUE(horizontalBorderMatch);
// -1, 1 corner initially equal to closest corner data
EXPECT_TRUE(dem1.level.get(-1, 4) == dem1.level.get(0, 3));
EXPECT_TRUE(dem1.get(-1, 4) == dem1.get(0, 3));
// 1, 1 corner initially equal to closest corner data
EXPECT_TRUE(dem1.level.get(4, 4) == dem1.level.get(3, 3));
EXPECT_TRUE(dem1.get(4, 4) == dem1.get(3, 3));
// -1, -1 corner initially equal to closest corner data
EXPECT_TRUE(dem1.level.get(-1, -1) == dem1.level.get(0, 0));
EXPECT_TRUE(dem1.get(-1, -1) == dem1.get(0, 0));
// -1, 1 corner initially equal to closest corner data
EXPECT_TRUE(dem1.level.get(4, -1) == dem1.level.get(3, 0));
EXPECT_TRUE(dem1.get(4, -1) == dem1.get(3, 0));
};

TEST(DEMData, BackfillNeighbor) {
Expand All @@ -103,41 +100,41 @@ TEST(DEMData, BackfillNeighbor) {
for (int y = 0; y < 4; y++) {
// dx = -1, dy = 0, so the left edge of dem1 should equal the right edge of dem0
// backfills Left neighbor
EXPECT_TRUE(dem0.level.get(-1, y) == dem1.level.get(3, y));
EXPECT_TRUE(dem0.get(-1, y) == dem1.get(3, y));

}

dem0.backfillBorder(dem1, 0, -1);
// backfills TopCenter neighbor
for (int x = 0; x < 4; x++) {
EXPECT_TRUE(dem0.level.get(x, -1) == dem1.level.get(x, 3));
EXPECT_TRUE(dem0.get(x, -1) == dem1.get(x, 3));
}

dem0.backfillBorder(dem1, 1, 0);
// backfills Right neighb// backfulls TopRight neighboror
// backfills Right neighbor
for (int y = 0; y < 4; y++) {
EXPECT_TRUE(dem0.level.get(4, y) == dem1.level.get(0, y));
EXPECT_TRUE(dem0.get(4, y) == dem1.get(0, y));
}

dem0.backfillBorder(dem1, 0, 1);
// backfills BottomCenter neighbor
for (int x = 0; x < 4; x++) {
EXPECT_TRUE(dem0.level.get(x, 4) == dem1.level.get(x, 0));
EXPECT_TRUE(dem0.get(x, 4) == dem1.get(x, 0));
}

dem0.backfillBorder(dem1, -1, 1);
// backfulls TopRight neighbor
EXPECT_TRUE(dem0.level.get(-1, 4) == dem1.level.get(3, 0));
EXPECT_TRUE(dem0.get(-1, 4) == dem1.get(3, 0));

dem0.backfillBorder(dem1, 1, 1);
// backfulls BottomRight neighbor
EXPECT_TRUE(dem0.level.get(4, 4) == dem1.level.get(0, 0));
EXPECT_TRUE(dem0.get(4, 4) == dem1.get(0, 0));

dem0.backfillBorder(dem1, -1, -1);
// backfulls TopLeft neighbor
EXPECT_TRUE(dem0.level.get(-1, -1) == dem1.level.get(3, 3));
EXPECT_TRUE(dem0.get(-1, -1) == dem1.get(3, 3));

dem0.backfillBorder(dem1, 1, -1);
// backfulls BottomLeft neighbor
EXPECT_TRUE(dem0.level.get(4, -1) == dem1.level.get(0, 3));
EXPECT_TRUE(dem0.get(4, -1) == dem1.get(0, 3));
};