[core] move Painter and dependents to new *TileID classes
This commit is contained in:
@@ -32,9 +32,6 @@ bool ClipIDGenerator::Leaf::operator==(const Leaf& other) const {
|
||||
return children == other.children;
|
||||
}
|
||||
|
||||
// Instantiate the function for Tile& refs.
|
||||
template void ClipIDGenerator::update(std::map<UnwrappedTileID, Tile&>&);
|
||||
|
||||
std::map<UnwrappedTileID, ClipID> ClipIDGenerator::getStencils() const {
|
||||
std::map<UnwrappedTileID, ClipID> stencils;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/map/tile_id.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/interpolate.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
@@ -14,12 +14,14 @@ TransformState::TransformState(ConstrainMode constrainMode_)
|
||||
|
||||
#pragma mark - Matrix
|
||||
|
||||
void TransformState::matrixFor(mat4& matrix, const TileID& id, const int8_t z) const {
|
||||
const double tile_scale = std::pow(2, z);
|
||||
double s = worldSize() / tile_scale;
|
||||
void TransformState::matrixFor(mat4& matrix, const UnwrappedTileID& tileID) const {
|
||||
const uint64_t tileScale = 1ull << tileID.canonical.z;
|
||||
const double s = worldSize() / tileScale;
|
||||
|
||||
matrix::identity(matrix);
|
||||
matrix::translate(matrix, matrix, id.x * s, id.y * s, 0);
|
||||
matrix::translate(matrix, matrix,
|
||||
static_cast<int64_t>(tileID.canonical.x + tileID.wrap * tileScale) * s,
|
||||
static_cast<int64_t>(tileID.canonical.y) * s, 0);
|
||||
matrix::scale(matrix, matrix, s / util::EXTENT, s / util::EXTENT, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class TileID;
|
||||
class UnwrappedTileID;
|
||||
|
||||
class TransformState {
|
||||
friend class Transform;
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
TransformState(ConstrainMode = ConstrainMode::HeightOnly);
|
||||
|
||||
// Matrix
|
||||
void matrixFor(mat4& matrix, const TileID& id, const int8_t z) const;
|
||||
void matrixFor(mat4&, const UnwrappedTileID&) const;
|
||||
void getProjMatrix(mat4& matrix) const;
|
||||
|
||||
// Dimensions
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace mbgl {
|
||||
|
||||
class Painter;
|
||||
class StyleLayer;
|
||||
class TileID;
|
||||
class UnwrappedTileID;
|
||||
class CollisionTile;
|
||||
|
||||
namespace gl {
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
|
||||
// Every time this bucket is getting rendered, this function is called. This happens either
|
||||
// once or twice (for Opaque and Transparent render passes).
|
||||
virtual void render(Painter&, const StyleLayer&, const TileID&, const mat4&) = 0;
|
||||
virtual void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) = 0;
|
||||
|
||||
virtual ~Bucket() = default;
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ void CircleBucket::upload(gl::GLObjectStore& glObjectStore) {
|
||||
|
||||
void CircleBucket::render(Painter& painter,
|
||||
const StyleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
painter.renderCircle(*this, *layer.as<CircleLayer>(), id, matrix);
|
||||
painter.renderCircle(*this, *layer.as<CircleLayer>(), tileID, matrix);
|
||||
}
|
||||
|
||||
bool CircleBucket::hasData() const {
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
~CircleBucket() override;
|
||||
|
||||
void upload(gl::GLObjectStore&) override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override;
|
||||
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
@@ -198,9 +198,9 @@ void FillBucket::upload(gl::GLObjectStore& glObjectStore) {
|
||||
|
||||
void FillBucket::render(Painter& painter,
|
||||
const StyleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
painter.renderFill(*this, *layer.as<FillLayer>(), id, matrix);
|
||||
painter.renderFill(*this, *layer.as<FillLayer>(), tileID, matrix);
|
||||
}
|
||||
|
||||
bool FillBucket::hasData() const {
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
~FillBucket() override;
|
||||
|
||||
void upload(gl::GLObjectStore&) override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
|
||||
@@ -445,9 +445,9 @@ void LineBucket::upload(gl::GLObjectStore& glObjectStore) {
|
||||
|
||||
void LineBucket::render(Painter& painter,
|
||||
const StyleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
painter.renderLine(*this, *layer.as<LineLayer>(), id, matrix);
|
||||
painter.renderLine(*this, *layer.as<LineLayer>(), tileID, matrix);
|
||||
}
|
||||
|
||||
bool LineBucket::hasData() const {
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
~LineBucket() override;
|
||||
|
||||
void upload(gl::GLObjectStore&) override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
#include <mbgl/shader/box_shader.hpp>
|
||||
#include <mbgl/shader/circle_shader.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
#if defined(DEBUG)
|
||||
@@ -144,11 +147,12 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
MBGL_DEBUG_GROUP("clip");
|
||||
|
||||
// Update all clipping IDs.
|
||||
ClipIDGenerator generator;
|
||||
algorithm::ClipIDGenerator generator;
|
||||
for (const auto& source : sources) {
|
||||
if (source->type == SourceType::Vector || source->type == SourceType::GeoJSON ||
|
||||
source->type == SourceType::Annotations) {
|
||||
generator.update(source->getLoadedTiles());
|
||||
auto renderables = source->getRenderables();
|
||||
generator.update(renderables);
|
||||
}
|
||||
source->updateMatrices(projMatrix, state);
|
||||
}
|
||||
@@ -251,7 +255,8 @@ void Painter::renderPass(RenderPass pass_,
|
||||
if (item.bucket->needsClipping()) {
|
||||
setClipping(item.tile->clip);
|
||||
}
|
||||
item.bucket->render(*this, layer, item.tile->id, item.tile->matrix);
|
||||
const UnwrappedTileID tileID{ item.tile->id.sourceZ, item.tile->id.x, item.tile->id.y };
|
||||
item.bucket->render(*this, layer, tileID, item.tile->matrix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,11 +265,13 @@ void Painter::renderPass(RenderPass pass_,
|
||||
}
|
||||
}
|
||||
|
||||
mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor) {
|
||||
mat4 Painter::translatedMatrix(const mat4& matrix,
|
||||
const std::array<float, 2>& translation,
|
||||
const UnwrappedTileID& id,
|
||||
TranslateAnchorType anchor) {
|
||||
if (translation[0] == 0 && translation[1] == 0) {
|
||||
return matrix;
|
||||
} else {
|
||||
|
||||
mat4 vtxMatrix;
|
||||
if (anchor == TranslateAnchorType::Viewport) {
|
||||
const double sin_a = std::sin(-state.getAngle());
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
|
||||
#include <mbgl/renderer/frame_history.hpp>
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
|
||||
@@ -98,23 +100,26 @@ public:
|
||||
void renderDebugFrame(const mat4 &matrix);
|
||||
|
||||
void renderDebugText(TileData&, const mat4&);
|
||||
void renderFill(FillBucket&, const FillLayer&, const TileID&, const mat4&);
|
||||
void renderLine(LineBucket&, const LineLayer&, const TileID&, const mat4&);
|
||||
void renderCircle(CircleBucket&, const CircleLayer&, const TileID&, const mat4&);
|
||||
void renderSymbol(SymbolBucket&, const SymbolLayer&, const TileID&, const mat4&);
|
||||
void renderRaster(RasterBucket&, const RasterLayer&, const TileID&, const mat4&);
|
||||
void renderFill(FillBucket&, const FillLayer&, const UnwrappedTileID&, const mat4&);
|
||||
void renderLine(LineBucket&, const LineLayer&, const UnwrappedTileID&, const mat4&);
|
||||
void renderCircle(CircleBucket&, const CircleLayer&, const UnwrappedTileID&, const mat4&);
|
||||
void renderSymbol(SymbolBucket&, const SymbolLayer&, const UnwrappedTileID&, const mat4&);
|
||||
void renderRaster(RasterBucket&, const RasterLayer&, const UnwrappedTileID&, const mat4&);
|
||||
void renderBackground(const BackgroundLayer&);
|
||||
|
||||
float saturationFactor(float saturation);
|
||||
float contrastFactor(float contrast);
|
||||
std::array<float, 3> spinWeights(float spin_value);
|
||||
|
||||
void drawClippingMasks(const std::map<TileID, ClipID>&);
|
||||
void drawClippingMasks(const std::map<UnwrappedTileID, ClipID>&);
|
||||
|
||||
bool needsAnimation() const;
|
||||
|
||||
private:
|
||||
mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const TileID &id, TranslateAnchorType anchor);
|
||||
mat4 translatedMatrix(const mat4& matrix,
|
||||
const std::array<float, 2>& translation,
|
||||
const UnwrappedTileID& id,
|
||||
TranslateAnchorType anchor);
|
||||
|
||||
std::vector<RenderItem> determineRenderOrder(const Style& style);
|
||||
|
||||
@@ -126,7 +131,7 @@ private:
|
||||
void setClipping(const ClipID&);
|
||||
|
||||
void renderSDF(SymbolBucket &bucket,
|
||||
const TileID &id,
|
||||
const UnwrappedTileID &tileID,
|
||||
const mat4 &matrixSymbol,
|
||||
float scaleDivisor,
|
||||
std::array<float, 2> texsize,
|
||||
|
||||
@@ -59,7 +59,8 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
|
||||
|
||||
for (auto &id: tileIDs) {
|
||||
mat4 vtxMatrix;
|
||||
state.matrixFor(vtxMatrix, id, id.z);
|
||||
const UnwrappedTileID tileID(id.z, id.x, id.y);
|
||||
state.matrixFor(vtxMatrix, tileID);
|
||||
matrix::multiply(vtxMatrix, projMatrix, vtxMatrix);
|
||||
|
||||
if (isPatterned) {
|
||||
|
||||
@@ -11,7 +11,7 @@ using namespace mbgl;
|
||||
|
||||
void Painter::renderCircle(CircleBucket& bucket,
|
||||
const CircleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
// Abort early.
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
@@ -23,7 +23,8 @@ void Painter::renderCircle(CircleBucket& bucket,
|
||||
setDepthSublayer(0);
|
||||
|
||||
const CirclePaintProperties& properties = layer.paint;
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, id, properties.circleTranslateAnchor);
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID,
|
||||
properties.circleTranslateAnchor);
|
||||
|
||||
Color color = properties.circleColor;
|
||||
color[0] *= properties.circleOpacity;
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
#include <mbgl/source/source.hpp>
|
||||
#include <mbgl/shader/plain_shader.hpp>
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/gl/debugging.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
|
||||
void Painter::drawClippingMasks(const std::map<TileID, ClipID>& stencils) {
|
||||
void Painter::drawClippingMasks(const std::map<UnwrappedTileID, ClipID>& stencils) {
|
||||
MBGL_DEBUG_GROUP("clipping masks");
|
||||
|
||||
mat4 matrix;
|
||||
@@ -27,8 +28,8 @@ void Painter::drawClippingMasks(const std::map<TileID, ClipID>& stencils) {
|
||||
const auto& id = stencil.first;
|
||||
const auto& clip = stencil.second;
|
||||
|
||||
MBGL_DEBUG_GROUP(std::string{ "mask: " } + std::string(id));
|
||||
state.matrixFor(matrix, id, id.z);
|
||||
MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(id));
|
||||
state.matrixFor(matrix, id);
|
||||
matrix::multiply(matrix, projMatrix, matrix);
|
||||
plainShader->u_matrix = matrix;
|
||||
|
||||
|
||||
@@ -10,9 +10,13 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileID& id, const mat4& matrix) {
|
||||
void Painter::renderFill(FillBucket& bucket,
|
||||
const FillLayer& layer,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
const FillPaintProperties& properties = layer.paint;
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.fillTranslate, id, properties.fillTranslateAnchor);
|
||||
mat4 vtxMatrix =
|
||||
translatedMatrix(matrix, properties.fillTranslate, tileID, properties.fillTranslateAnchor);
|
||||
|
||||
Color fill_color = properties.fillColor;
|
||||
fill_color[0] *= properties.fillOpacity;
|
||||
@@ -65,7 +69,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI
|
||||
|
||||
// Image fill.
|
||||
if (pass == RenderPass::Translucent && posA && posB) {
|
||||
|
||||
config.program = patternShader->getID();
|
||||
patternShader->u_matrix = vtxMatrix;
|
||||
patternShader->u_pattern_tl_a = (*posA).tl;
|
||||
@@ -85,20 +88,24 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI
|
||||
(int)((*posB).size[1] * properties.fillPattern.value.toScale)
|
||||
}};
|
||||
|
||||
patternShader->u_patternscale_a = {{
|
||||
1.0f / id.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()),
|
||||
1.0f / id.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom())
|
||||
}};
|
||||
patternShader->u_patternscale_b = {{
|
||||
1.0f / id.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()),
|
||||
1.0f / id.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom())
|
||||
}};
|
||||
patternShader->u_patternscale_a = {
|
||||
{ 1.0f / tileID.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()),
|
||||
1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) }
|
||||
};
|
||||
patternShader->u_patternscale_b = {
|
||||
{ 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()),
|
||||
1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) }
|
||||
};
|
||||
|
||||
float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.x) / (float)imageSizeScaledA[0];
|
||||
float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.y) / (float)imageSizeScaledA[1];
|
||||
float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * tileID.canonical.x) /
|
||||
(float)imageSizeScaledA[0];
|
||||
float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * tileID.canonical.y) /
|
||||
(float)imageSizeScaledA[1];
|
||||
|
||||
float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * id.x) / (float)imageSizeScaledB[0];
|
||||
float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * id.y) / (float)imageSizeScaledB[1];
|
||||
float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * tileID.canonical.x) /
|
||||
(float)imageSizeScaledB[0];
|
||||
float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * tileID.canonical.y) /
|
||||
(float)imageSizeScaledB[1];
|
||||
|
||||
patternShader->u_offset_a = std::array<float, 2>{{offsetAx, offsetAy}};
|
||||
patternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}};
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileID& id, const mat4& matrix) {
|
||||
void Painter::renderLine(LineBucket& bucket,
|
||||
const LineLayer& layer,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
// Abort early.
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
|
||||
@@ -50,7 +53,7 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
|
||||
color[2] *= properties.lineOpacity;
|
||||
color[3] *= properties.lineOpacity;
|
||||
|
||||
const float ratio = 1.0 / id.pixelsToTileUnits(1.0, state.getZoom());
|
||||
const float ratio = 1.0 / tileID.pixelsToTileUnits(1.0, state.getZoom());
|
||||
|
||||
mat2 antialiasingMatrix;
|
||||
matrix::identity(antialiasingMatrix);
|
||||
@@ -63,7 +66,8 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
|
||||
float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
|
||||
float extra = (topedgelength + x) / topedgelength - 1;
|
||||
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.lineTranslate, id, properties.lineTranslateAnchor);
|
||||
mat4 vtxMatrix =
|
||||
translatedMatrix(matrix, properties.lineTranslate, tileID, properties.lineTranslateAnchor);
|
||||
|
||||
setDepthSublayer(0);
|
||||
|
||||
@@ -84,9 +88,9 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
|
||||
const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.dashLineWidth;
|
||||
const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.dashLineWidth;
|
||||
|
||||
float scaleXA = 1.0 / id.pixelsToTileUnits(widthA, state.getIntegerZoom());
|
||||
float scaleXA = 1.0 / tileID.pixelsToTileUnits(widthA, state.getIntegerZoom());
|
||||
float scaleYA = -posA.height / 2.0;
|
||||
float scaleXB = 1.0 / id.pixelsToTileUnits(widthB, state.getIntegerZoom());
|
||||
float scaleXB = 1.0 / tileID.pixelsToTileUnits(widthB, state.getIntegerZoom());
|
||||
float scaleYB = -posB.height / 2.0;
|
||||
|
||||
linesdfShader->u_patternscale_a = {{ scaleXA, scaleYA }};
|
||||
@@ -121,14 +125,14 @@ void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileI
|
||||
linepatternShader->u_blur = blur;
|
||||
|
||||
linepatternShader->u_pattern_size_a = {{
|
||||
id.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
|
||||
tileID.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
|
||||
(*imagePosA).size[1]
|
||||
}};
|
||||
linepatternShader->u_pattern_tl_a = (*imagePosA).tl;
|
||||
linepatternShader->u_pattern_br_a = (*imagePosA).br;
|
||||
|
||||
linepatternShader->u_pattern_size_b = {{
|
||||
id.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
|
||||
tileID.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
|
||||
(*imagePosB).size[1]
|
||||
}};
|
||||
linepatternShader->u_pattern_tl_b = (*imagePosB).tl;
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
void Painter::renderRaster(RasterBucket& bucket, const RasterLayer& layer, const TileID&, const mat4& matrix) {
|
||||
void Painter::renderRaster(RasterBucket& bucket,
|
||||
const RasterLayer& layer,
|
||||
const UnwrappedTileID&,
|
||||
const mat4& matrix) {
|
||||
if (pass != RenderPass::Translucent) return;
|
||||
|
||||
const RasterPaintProperties& properties = layer.paint;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
using namespace mbgl;
|
||||
|
||||
void Painter::renderSDF(SymbolBucket &bucket,
|
||||
const TileID &id,
|
||||
const UnwrappedTileID &tileID,
|
||||
const mat4 &matrix,
|
||||
float sdfFontSize,
|
||||
std::array<float, 2> texsize,
|
||||
@@ -35,7 +35,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
TranslateAnchorType translateAnchor,
|
||||
float paintSize)
|
||||
{
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, translate, id, translateAnchor);
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, translate, tileID, translateAnchor);
|
||||
|
||||
bool skewed = rotationAlignment == RotationAlignmentType::Map;
|
||||
mat4 exMatrix;
|
||||
@@ -44,7 +44,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
|
||||
if (skewed) {
|
||||
matrix::identity(exMatrix);
|
||||
s = id.pixelsToTileUnits(1, state.getZoom());
|
||||
s = tileID.pixelsToTileUnits(1, state.getZoom());
|
||||
gammaScale = 1.0f / std::cos(state.getPitch());
|
||||
} else {
|
||||
exMatrix = extrudeMatrix;
|
||||
@@ -130,7 +130,10 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const TileID& id, const mat4& matrix) {
|
||||
void Painter::renderSymbol(SymbolBucket& bucket,
|
||||
const SymbolLayer& layer,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
// Abort early.
|
||||
if (pass == RenderPass::Opaque) {
|
||||
return;
|
||||
@@ -183,7 +186,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
|
||||
if (sdf) {
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
tileID,
|
||||
matrix,
|
||||
1.0f,
|
||||
{{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
|
||||
@@ -200,7 +203,8 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
paint.iconTranslateAnchor,
|
||||
layer.iconSize);
|
||||
} else {
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, paint.iconTranslate, id, paint.iconTranslateAnchor);
|
||||
mat4 vtxMatrix =
|
||||
translatedMatrix(matrix, paint.iconTranslate, tileID, paint.iconTranslateAnchor);
|
||||
|
||||
bool skewed = layout.iconRotationAlignment == RotationAlignmentType::Map;
|
||||
mat4 exMatrix;
|
||||
@@ -208,7 +212,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
|
||||
if (skewed) {
|
||||
matrix::identity(exMatrix);
|
||||
s = id.pixelsToTileUnits(1, state.getZoom());
|
||||
s = tileID.pixelsToTileUnits(1, state.getZoom());
|
||||
} else {
|
||||
exMatrix = extrudeMatrix;
|
||||
matrix::rotate_z(exMatrix, exMatrix, state.getNorthOrientationAngle());
|
||||
@@ -259,7 +263,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
glyphAtlas->bind(glObjectStore);
|
||||
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
tileID,
|
||||
matrix,
|
||||
24.0f,
|
||||
{{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
|
||||
@@ -283,9 +287,10 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
|
||||
config.program = collisionBoxShader->getID();
|
||||
collisionBoxShader->u_matrix = matrix;
|
||||
collisionBoxShader->u_scale = std::pow(2, state.getZoom() - id.z);
|
||||
// TODO: This was the overscaled z instead of the canonical z.
|
||||
collisionBoxShader->u_scale = std::pow(2, state.getZoom() - tileID.canonical.z);
|
||||
collisionBoxShader->u_zoom = state.getZoom() * 10;
|
||||
collisionBoxShader->u_maxzoom = (id.z + 1) * 10;
|
||||
collisionBoxShader->u_maxzoom = (tileID.canonical.z + 1) * 10;
|
||||
config.lineWidth = 1.0f;
|
||||
|
||||
setDepthSublayer(0);
|
||||
|
||||
@@ -18,9 +18,9 @@ void RasterBucket::upload(gl::GLObjectStore& glObjectStore) {
|
||||
|
||||
void RasterBucket::render(Painter& painter,
|
||||
const StyleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
painter.renderRaster(*this, *layer.as<RasterLayer>(), id, matrix);
|
||||
painter.renderRaster(*this, *layer.as<RasterLayer>(), tileID, matrix);
|
||||
}
|
||||
|
||||
void RasterBucket::setImage(PremultipliedImage image) {
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
RasterBucket(gl::TexturePool&);
|
||||
|
||||
void upload(gl::GLObjectStore&) override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool needsClipping() const override;
|
||||
|
||||
|
||||
14
src/mbgl/renderer/renderable.hpp
Normal file
14
src/mbgl/renderer/renderable.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef MBGL_RENDERER_RENDERABLE
|
||||
#define MBGL_RENDERER_RENDERABLE
|
||||
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct Renderable {
|
||||
ClipID& clip;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
@@ -87,9 +87,9 @@ void SymbolBucket::upload(gl::GLObjectStore& glObjectStore) {
|
||||
|
||||
void SymbolBucket::render(Painter& painter,
|
||||
const StyleLayer& layer,
|
||||
const TileID& id,
|
||||
const UnwrappedTileID& tileID,
|
||||
const mat4& matrix) {
|
||||
painter.renderSymbol(*this, *layer.as<SymbolLayer>(), id, matrix);
|
||||
painter.renderSymbol(*this, *layer.as<SymbolLayer>(), tileID, matrix);
|
||||
}
|
||||
|
||||
bool SymbolBucket::hasData() const { return hasTextData() || hasIconData() || !symbolInstances.empty(); }
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
~SymbolBucket() override;
|
||||
|
||||
void upload(gl::GLObjectStore&) override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override;
|
||||
bool hasData() const override;
|
||||
bool hasTextData() const;
|
||||
bool hasIconData() const;
|
||||
|
||||
@@ -162,8 +162,8 @@ void Source::load(FileSource& fileSource) {
|
||||
|
||||
void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) {
|
||||
for (const auto& pair : tiles) {
|
||||
Tile &tile = *pair.second;
|
||||
transform.matrixFor(tile.matrix, tile.id, std::min(static_cast<uint8_t>(info->maxZoom), tile.id.z));
|
||||
auto& tile = *pair.second;
|
||||
transform.matrixFor(tile.matrix, UnwrappedTileID{ tile.id.sourceZ, tile.id.x, tile.id.y });
|
||||
matrix::multiply(tile.matrix, projMatrix, tile.matrix);
|
||||
}
|
||||
}
|
||||
@@ -175,16 +175,16 @@ void Source::finishRender(Painter &painter) {
|
||||
}
|
||||
}
|
||||
|
||||
std::forward_list<Tile*> Source::getLoadedTiles() const {
|
||||
std::forward_list<Tile*> ptrs;
|
||||
auto it = ptrs.before_begin();
|
||||
std::map<UnwrappedTileID, Renderable> Source::getRenderables() const {
|
||||
std::map<UnwrappedTileID, Renderable> renderables;
|
||||
for (const auto& pair : tiles) {
|
||||
auto tile = pair.second.get();
|
||||
if (tile->data->isReady() && tile->data->hasData()) {
|
||||
it = ptrs.insert_after(it, tile);
|
||||
auto& tile = *pair.second;
|
||||
if (tile.data->isReady() && tile.data->hasData()) {
|
||||
renderables.emplace(UnwrappedTileID{ tile.id.sourceZ, tile.id.x, tile.id.y },
|
||||
Renderable{ tile.clip });
|
||||
}
|
||||
}
|
||||
return ptrs;
|
||||
return renderables;
|
||||
}
|
||||
|
||||
const std::vector<Tile*>& Source::getTiles() const {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#ifndef MBGL_MAP_SOURCE
|
||||
#define MBGL_MAP_SOURCE
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/tile/tile_data.hpp>
|
||||
#include <mbgl/tile/tile_cache.hpp>
|
||||
#include <mbgl/source/source_info.hpp>
|
||||
#include <mbgl/renderer/renderable.hpp>
|
||||
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/util/rapidjson.hpp>
|
||||
@@ -70,7 +72,7 @@ public:
|
||||
void updateMatrices(const mat4 &projMatrix, const TransformState &transform);
|
||||
void finishRender(Painter &painter);
|
||||
|
||||
std::forward_list<Tile *> getLoadedTiles() const;
|
||||
std::map<UnwrappedTileID, Renderable> getRenderables() const;
|
||||
const std::vector<Tile*>& getTiles() const;
|
||||
|
||||
std::unordered_map<std::string, std::vector<Feature>> queryRenderedFeatures(
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -19,140 +8,4 @@ namespace mbgl {
|
||||
return os << "mask=" << rhs.mask << ",ref=" << rhs.reference;
|
||||
}
|
||||
|
||||
ClipIDGenerator::Leaf::Leaf(TileID id_, ClipID& clip_) : id(id_), clip(clip_) {}
|
||||
|
||||
void ClipIDGenerator::Leaf::add(const TileID &p) {
|
||||
if (p.isChildOf(id)) {
|
||||
// Ensure that no already present child is a parent of the new p.
|
||||
for (const auto& child : children) {
|
||||
if (p.isChildOf(child))
|
||||
return;
|
||||
}
|
||||
children.push_front(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClipIDGenerator::Leaf::operator==(const Leaf &other) const {
|
||||
return id == other.id && children == other.children;
|
||||
}
|
||||
|
||||
void ClipIDGenerator::update(std::forward_list<Tile *> tiles) {
|
||||
tiles.sort([](const Tile *a, const Tile *b) {
|
||||
return a->id < b->id;
|
||||
});
|
||||
|
||||
std::size_t size = 0;
|
||||
|
||||
const auto end = tiles.end();
|
||||
for (auto it = tiles.begin(); it != end; it++) {
|
||||
if (!*it) {
|
||||
// Handle null pointers.
|
||||
continue;
|
||||
}
|
||||
|
||||
Tile &tile = **it;
|
||||
// Use the actual zoom level for computing the clipping mask.
|
||||
Leaf leaf{ TileID{ tile.id.sourceZ, tile.id.x, tile.id.y, tile.id.sourceZ }, tile.clip };
|
||||
|
||||
// Try to add all remaining ids as children. We sorted the tile list
|
||||
// by z earlier, so all preceding items cannot be children of the current
|
||||
// tile.
|
||||
for (auto child_it = std::next(it); child_it != end; child_it++) {
|
||||
// Use the actual zoom level for computing the clipping mask.
|
||||
const auto& childID = (*child_it)->id;
|
||||
leaf.add(TileID { childID.sourceZ, childID.x, childID.y, childID.sourceZ });
|
||||
}
|
||||
leaf.children.sort();
|
||||
|
||||
// Loop through all existing pools and try to find a matching ClipID.
|
||||
auto existing = std::find(pool.begin(), pool.end(), leaf);
|
||||
if (existing != pool.end()) {
|
||||
leaf.clip = existing->clip;
|
||||
} else {
|
||||
// We haven't found an existing clip ID
|
||||
leaf.clip = {};
|
||||
size++;
|
||||
}
|
||||
|
||||
pool.emplace_back(std::move(leaf));
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
const uint32_t bit_count = util::ceil_log2(size + 1);
|
||||
const std::bitset<8> mask = uint64_t(((1ul << bit_count) - 1) << bit_offset);
|
||||
|
||||
// We are starting our count with 1 since we need at least 1 bit set to distinguish between
|
||||
// areas without any tiles whatsoever and the current area.
|
||||
uint8_t count = 1;
|
||||
for (auto& tile : tiles) {
|
||||
tile->clip.mask |= mask;
|
||||
|
||||
// Assign only to clip IDs that have no value yet.
|
||||
if (tile->clip.reference.none()) {
|
||||
tile->clip.reference = uint32_t(count++) << bit_offset;
|
||||
}
|
||||
}
|
||||
|
||||
bit_offset += bit_count;
|
||||
}
|
||||
|
||||
if (bit_offset > 8) {
|
||||
Log::Error(Event::OpenGL, "stencil mask overflow");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
bool coveredByChildren(const TileID& id, const Container& container) {
|
||||
for (const auto& child : id.children()) {
|
||||
const auto lower = container.lower_bound(child);
|
||||
if (lower == container.end() || lower->first.w != child.w ||
|
||||
(lower->first != child && !coveredByChildren(child, container))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We looked at all four immediate children and verified that they're covered.
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<TileID, ClipID> ClipIDGenerator::getStencils() const {
|
||||
std::map<TileID, ClipID> stencils;
|
||||
|
||||
// Merge everything.
|
||||
for (auto& leaf : pool) {
|
||||
auto res = stencils.emplace(leaf.id, leaf.clip);
|
||||
if (!res.second) {
|
||||
// Merge with the existing ClipID when there was already an element with the
|
||||
// same tile ID.
|
||||
res.first->second |= leaf.clip;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = stencils.begin(); it != stencils.end(); ++it) {
|
||||
auto& childId = it->first;
|
||||
auto& childClip = it->second;
|
||||
|
||||
// Loop through all preceding stencils, and find all parents.
|
||||
|
||||
for (auto parentIt = std::reverse_iterator<std::map<TileID, ClipID>::iterator>(it);
|
||||
parentIt != stencils.rend(); ++parentIt) {
|
||||
auto& parentId = parentIt->first;
|
||||
if (childId.isChildOf(parentId)) {
|
||||
// Once we have a parent, we add the bits that this ID hasn't set yet.
|
||||
const auto& parentClip = parentIt->second;
|
||||
const auto mask = ~(childClip.mask & parentClip.mask);
|
||||
childClip.reference |= mask & parentClip.reference;
|
||||
childClip.mask |= parentClip.mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove tiles that are entirely covered by children.
|
||||
util::erase_if(stencils, [&] (const auto& stencil) {
|
||||
return coveredByChildren(stencil.first, stencils);
|
||||
});
|
||||
|
||||
return stencils;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -36,28 +36,6 @@ struct ClipID {
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const ClipID& rhs);
|
||||
|
||||
class ClipIDGenerator {
|
||||
private:
|
||||
struct Leaf {
|
||||
Leaf(TileID, ClipID&);
|
||||
void add(const TileID &p);
|
||||
bool operator==(const Leaf &other) const;
|
||||
|
||||
const TileID id;
|
||||
std::forward_list<TileID> children;
|
||||
ClipID& clip;
|
||||
};
|
||||
|
||||
uint8_t bit_offset = 0;
|
||||
std::vector<Leaf> pool;
|
||||
|
||||
public:
|
||||
void update(std::forward_list<Tile *> tiles);
|
||||
|
||||
std::map<TileID, ClipID> getStencils() const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
'sources': [
|
||||
'util/assert.cpp',
|
||||
'util/async_task.cpp',
|
||||
'util/clip_ids.cpp',
|
||||
'util/geo.cpp',
|
||||
'util/image.cpp',
|
||||
'util/mapbox.cpp',
|
||||
|
||||
@@ -1,411 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
using Stencil = std::pair<const TileID, ClipID>;
|
||||
|
||||
template <typename T> void generate(ClipIDGenerator& generator, const T &sources) {
|
||||
for (size_t j = 0; j < sources.size(); j++) {
|
||||
std::forward_list<Tile *> tile_ptrs;
|
||||
std::transform(sources[j].begin(), sources[j].end(), std::front_inserter(tile_ptrs), [](const std::shared_ptr<Tile> &tile) { return tile.get(); });
|
||||
generator.update(tile_ptrs);
|
||||
}
|
||||
}
|
||||
|
||||
void print(const std::vector<std::vector<std::shared_ptr<Tile>>> &sources) {
|
||||
for (size_t j = 0; j < sources.size(); j++) {
|
||||
for (size_t i = 0; i < sources[j].size(); i++) {
|
||||
std::cout << " ASSERT_EQ(ClipID(\"" << sources[j][i]->clip.mask << "\", \"" << sources[j][i]->clip.reference << "\"), sources[" << j << "][" << i << "]->clip);\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print(const std::map<TileID, ClipID>& stencils) {
|
||||
std::cout << " auto it = stencils.begin();\n";
|
||||
std::cout << " ASSERT_EQ(" << stencils.size() << ", stencils.size());\n";
|
||||
for (auto& stencil : stencils) {
|
||||
std::cout << " ASSERT_EQ(Stencil(TileID{ " << (int)stencil.first.z << ", "
|
||||
<< stencil.first.x << ", " << stencil.first.y << ", "
|
||||
<< (int)stencil.first.sourceZ << " }, { \"" << stencil.second.mask.to_string()
|
||||
<< "\", \"" << stencil.second.reference.to_string() << "\"}), *it++);\n";
|
||||
}
|
||||
std::cout << " ASSERT_EQ(stencils.end(), it);\n";
|
||||
}
|
||||
|
||||
TEST(ClipIDs, ParentAndFourChildren) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 0, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 1, 1 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 0, 1 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 1, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
|
||||
}
|
||||
|
||||
TEST(ClipIDs, ParentAndFourChildrenNegative) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, -2, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, -2, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, -1, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, -1, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 0, -1, 0, 0 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -2, 0, 1 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -2, 1, 1 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -1, 0, 1 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, -1, 1, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, NegativeParentAndMissingLevel) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, -1, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 2, -1, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, -2, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, -1, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, -2, 0, 2 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(4, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -2, 0, 2 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -2, 1, 2 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -1, 0, 2 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, -1, 1, 2 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
TEST(ClipIDs, SevenOnSameLevel) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 2, 0, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 2, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 2, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 2, 0, 2 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000101"), sources[0][4]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000110"), sources[0][5]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000111"), sources[0][6]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(7, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 0, 2 }, { "00000111", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 1, 2 }, { "00000111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 2, 2 }, { "00000111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 0, 2 }, { "00000111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 1, 2 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 2, 2 }, { "00000111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 0, 2 }, { "00000111", "00000111"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, MultipleLevels) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 2, 0, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 3, 0, 0, 3 }),
|
||||
std::make_shared<Tile>(TileID { 3, 0, 1, 3 }),
|
||||
std::make_shared<Tile>(TileID { 4, 0, 2, 4 }),
|
||||
std::make_shared<Tile>(TileID { 4, 1, 2, 4 }),
|
||||
std::make_shared<Tile>(TileID { 4, 0, 3, 4 }),
|
||||
std::make_shared<Tile>(TileID { 4, 1, 3, 4 }),
|
||||
std::make_shared<Tile>(TileID { 3, 1, 0, 3 }),
|
||||
std::make_shared<Tile>(TileID { 3, 1, 1, 3 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 3, 2, 0, 3 }),
|
||||
std::make_shared<Tile>(TileID { 3, 2, 1, 3 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00001111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000011"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000100"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001001"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001011"), sources[0][4]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001010"), sources[0][5]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001100"), sources[0][6]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000101"), sources[0][7]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000110"), sources[0][8]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000010"), sources[0][9]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000111"), sources[0][10]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001000"), sources[0][11]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(10, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 0, 2 }, { "00001111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 0, 0, 3 }, { "00001111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 1, 0, 3 }, { "00001111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 1, 1, 3 }, { "00001111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 2, 0, 3 }, { "00001111", "00000111"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 3, 2, 1, 3 }, { "00001111", "00001000"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 0, 2, 4 }, { "00001111", "00001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 0, 3, 4 }, { "00001111", "00001010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 1, 2, 4 }, { "00001111", "00001011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 4, 1, 3, 4 }, { "00001111", "00001100"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
TEST(ClipIDs, Bug206) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 10, 162, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 162, 396, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 163, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 11, 326, 791, 11 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1582, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 654, 1583, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1582, 12 }),
|
||||
std::make_shared<Tile>(TileID { 12, 655, 1583, 12 }),
|
||||
std::make_shared<Tile>(TileID { 10, 163, 396, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 164, 395, 10 }),
|
||||
std::make_shared<Tile>(TileID { 10, 164, 396, 10 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00001111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000010"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000111"), sources[0][3]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001000"), sources[0][4]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001001"), sources[0][5]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001010"), sources[0][6]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00001011"), sources[0][7]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000100"), sources[0][8]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000101"), sources[0][9]->clip);
|
||||
ASSERT_EQ(ClipID("00001111", "00000110"), sources[0][10]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(11, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 162, 395, 10 }, { "00001111", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 162, 396, 10 }, { "00001111", "00000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 163, 395, 10 }, { "00001111", "00000011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 163, 396, 10 }, { "00001111", "00000100"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 164, 395, 10 }, { "00001111", "00000101"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 10, 164, 396, 10 }, { "00001111", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 11, 326, 791, 11 }, { "00001111", "00000111"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 654, 1582, 12 }, { "00001111", "00001000"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 654, 1583, 12 }, { "00001111", "00001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 655, 1582, 12 }, { "00001111", "00001010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 12, 655, 1583, 12 }, { "00001111", "00001011"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
TEST(ClipIDs, MultipleSources) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 2, 2, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 2, 2, 2 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 2, 2, 2 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 0, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 0, 1 }),
|
||||
std::make_shared<Tile>(TileID { 1, 1, 1, 1 }),
|
||||
std::make_shared<Tile>(TileID { 2, 1, 1, 2 }),
|
||||
},
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000111", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000010"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000011"), sources[0][2]->clip);
|
||||
ASSERT_EQ(ClipID("00000111", "00000100"), sources[0][3]->clip);
|
||||
|
||||
ASSERT_EQ(ClipID("00011000", "00001000"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00011111", "00000010"), sources[1][1]->clip);
|
||||
ASSERT_EQ(ClipID("00011000", "00010000"), sources[1][2]->clip);
|
||||
ASSERT_EQ(ClipID("00011111", "00000100"), sources[1][3]->clip);
|
||||
|
||||
ASSERT_EQ(ClipID("11100000", "00100000"), sources[2][0]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "01000000"), sources[2][1]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "01100000"), sources[2][2]->clip);
|
||||
ASSERT_EQ(ClipID("11100000", "10000000"), sources[2][3]->clip);
|
||||
ASSERT_EQ(ClipID("11111000", "00010000"), sources[2][4]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(7, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "11111111", "00101001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 1, 1 }, { "11111111", "01001001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 0, 1 }, { "11111111", "01101001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 1, 1, 1 }, { "11111111", "10000010"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 1, 1, 2 }, { "11111111", "00010001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 1, 2 }, { "11111111", "01101011"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 2, 2, 2 }, { "11111111", "10000100"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
|
||||
TEST(ClipIDs, DuplicateIDs) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 2, 0, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 1, 2 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 2, 0, 0, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 1, 2 }),
|
||||
std::make_shared<Tile>(TileID { 2, 0, 1, 2 }),
|
||||
}
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000010"), sources[0][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000010"), sources[1][1]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000010"), sources[1][2]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(2, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 0, 2 }, { "00000011", "00000001"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 2, 0, 1, 2 }, { "00000011", "00000010"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
|
||||
TEST(ClipIDs, SecondSourceHasParentOfFirstSource) {
|
||||
const std::vector<std::vector<std::shared_ptr<Tile>>> sources = {
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
std::make_shared<Tile>(TileID { 1, 0, 0, 1 }),
|
||||
},
|
||||
{
|
||||
std::make_shared<Tile>(TileID { 0, 0, 0, 0 }),
|
||||
}
|
||||
};
|
||||
|
||||
ClipIDGenerator generator;
|
||||
generate(generator, sources);
|
||||
// print(sources);
|
||||
|
||||
ASSERT_EQ(ClipID("00000001", "00000001"), sources[0][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000010", "00000010"), sources[1][0]->clip);
|
||||
ASSERT_EQ(ClipID("00000011", "00000001"), sources[1][1]->clip);
|
||||
|
||||
const auto stencils = generator.getStencils();
|
||||
// print(stencils);
|
||||
|
||||
auto it = stencils.begin();
|
||||
ASSERT_EQ(2, stencils.size());
|
||||
ASSERT_EQ(Stencil(TileID{ 0, 0, 0, 0 }, { "00000110", "00000110"}), *it++);
|
||||
ASSERT_EQ(Stencil(TileID{ 1, 0, 0, 1 }, { "00000111", "00000101"}), *it++);
|
||||
ASSERT_EQ(stencils.end(), it);
|
||||
}
|
||||
Reference in New Issue
Block a user