[core] change approach to stencil clipping to (almost) match JS
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
"src/csscolorparser/csscolorparser.cpp",
|
||||
"src/mbgl/actor/mailbox.cpp",
|
||||
"src/mbgl/actor/scheduler.cpp",
|
||||
"src/mbgl/algorithm/generate_clip_ids.cpp",
|
||||
"src/mbgl/annotation/annotation_manager.cpp",
|
||||
"src/mbgl/annotation/annotation_source.cpp",
|
||||
"src/mbgl/annotation/annotation_tile.cpp",
|
||||
@@ -280,7 +279,6 @@
|
||||
"src/mbgl/tile/vector_tile.cpp",
|
||||
"src/mbgl/tile/vector_tile_data.cpp",
|
||||
"src/mbgl/util/chrono.cpp",
|
||||
"src/mbgl/util/clip_id.cpp",
|
||||
"src/mbgl/util/color.cpp",
|
||||
"src/mbgl/util/compression.cpp",
|
||||
"src/mbgl/util/constants.cpp",
|
||||
@@ -495,9 +493,6 @@
|
||||
},
|
||||
"private_headers": {
|
||||
"csscolorparser/csscolorparser.hpp": "src/csscolorparser/csscolorparser.hpp",
|
||||
"mbgl/algorithm/covered_by_children.hpp": "src/mbgl/algorithm/covered_by_children.hpp",
|
||||
"mbgl/algorithm/generate_clip_ids.hpp": "src/mbgl/algorithm/generate_clip_ids.hpp",
|
||||
"mbgl/algorithm/generate_clip_ids_impl.hpp": "src/mbgl/algorithm/generate_clip_ids_impl.hpp",
|
||||
"mbgl/algorithm/update_renderables.hpp": "src/mbgl/algorithm/update_renderables.hpp",
|
||||
"mbgl/algorithm/update_tile_masks.hpp": "src/mbgl/algorithm/update_tile_masks.hpp",
|
||||
"mbgl/annotation/annotation_manager.hpp": "src/mbgl/annotation/annotation_manager.hpp",
|
||||
@@ -750,7 +745,6 @@
|
||||
"mbgl/tile/tile_observer.hpp": "src/mbgl/tile/tile_observer.hpp",
|
||||
"mbgl/tile/vector_tile.hpp": "src/mbgl/tile/vector_tile.hpp",
|
||||
"mbgl/tile/vector_tile_data.hpp": "src/mbgl/tile/vector_tile_data.hpp",
|
||||
"mbgl/util/clip_id.hpp": "src/mbgl/util/clip_id.hpp",
|
||||
"mbgl/util/dtoa.hpp": "src/mbgl/util/dtoa.hpp",
|
||||
"mbgl/util/grid_index.hpp": "src/mbgl/util/grid_index.hpp",
|
||||
"mbgl/util/hash.hpp": "src/mbgl/util/hash.hpp",
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace algorithm {
|
||||
|
||||
template <typename Iterator>
|
||||
bool coveredByChildren(const UnwrappedTileID& id, Iterator it, const Iterator& end) {
|
||||
for (const auto& child : id.children()) {
|
||||
it = std::lower_bound(it, end, child, [](const auto& a, const auto& b) { return std::get<0>(a) < b; });
|
||||
|
||||
// Child is not present, neither its grandchildren.
|
||||
if (it == end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Child is not present, but its grandchildren are.
|
||||
if (std::get<0>(*it) != child) {
|
||||
// This child is not covered by its grandchildren.
|
||||
if (!coveredByChildren(child, it, end)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We looked at all four children (recursively) and verified that they're covered.
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
bool coveredByChildren(const UnwrappedTileID& id, const Container& container) {
|
||||
return coveredByChildren(
|
||||
id, container.upper_bound(id),
|
||||
container.lower_bound(UnwrappedTileID{ static_cast<int16_t>(id.wrap + 1), { 0, 0, 0 } }));
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace mbgl
|
||||
@@ -1,76 +0,0 @@
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
#include <mbgl/algorithm/covered_by_children.hpp>
|
||||
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace mbgl {
|
||||
namespace algorithm {
|
||||
|
||||
ClipIDGenerator::Leaf::Leaf(ClipID& clip_) : clip(clip_) {
|
||||
}
|
||||
|
||||
void ClipIDGenerator::Leaf::add(const CanonicalTileID& p) {
|
||||
// Ensure that no already present child is a parent of the new p.
|
||||
for (const auto& child : children) {
|
||||
if (p.isChildOf(child)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
children.emplace(p);
|
||||
}
|
||||
|
||||
bool ClipIDGenerator::Leaf::operator==(const Leaf& other) const {
|
||||
return children == other.children;
|
||||
}
|
||||
|
||||
std::map<UnwrappedTileID, ClipID> ClipIDGenerator::getClipIDs() const {
|
||||
std::map<UnwrappedTileID, ClipID> clipIDs;
|
||||
|
||||
// Merge everything.
|
||||
for (auto& pair : pool) {
|
||||
auto& id = pair.first;
|
||||
auto& leaf = pair.second;
|
||||
auto res = clipIDs.emplace(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 = clipIDs.begin(); it != clipIDs.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<decltype(it)>(it);
|
||||
parentIt != clipIDs.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(clipIDs, [&](const auto& stencil) {
|
||||
return algorithm::coveredByChildren(stencil.first, clipIDs);
|
||||
});
|
||||
|
||||
return clipIDs;
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace mbgl
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace mbgl {
|
||||
namespace algorithm {
|
||||
|
||||
class ClipIDGenerator {
|
||||
private:
|
||||
struct Leaf {
|
||||
Leaf(ClipID&);
|
||||
void add(const CanonicalTileID &p);
|
||||
bool operator==(const Leaf &other) const;
|
||||
|
||||
std::set<CanonicalTileID> children;
|
||||
ClipID& clip;
|
||||
};
|
||||
|
||||
uint8_t bit_offset = 0;
|
||||
std::multimap<UnwrappedTileID, Leaf> pool;
|
||||
|
||||
public:
|
||||
// The given vector must be sorted by id.
|
||||
template <typename Renderable>
|
||||
void update(std::vector<std::reference_wrapper<Renderable>> sortedRenderables);
|
||||
|
||||
std::map<UnwrappedTileID, ClipID> getClipIDs() const;
|
||||
};
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace mbgl
|
||||
@@ -1,91 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/math/log2.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace algorithm {
|
||||
|
||||
template <typename Renderable>
|
||||
void ClipIDGenerator::update(std::vector<std::reference_wrapper<Renderable>> renderables) {
|
||||
std::size_t size = 0;
|
||||
assert(std::is_sorted(renderables.begin(), renderables.end(),
|
||||
[](const Renderable& a, const Renderable& b) { return a.id < b.id; }));
|
||||
|
||||
const auto end = renderables.end();
|
||||
for (auto it = renderables.begin(); it != end; ++it) {
|
||||
auto& renderable = it->get();
|
||||
if (!renderable.used || !renderable.needsClipping) {
|
||||
continue;
|
||||
}
|
||||
|
||||
renderable.clip = {};
|
||||
Leaf leaf{ renderable.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. We also compute the lower bound of the next wrap, because items of the next wrap
|
||||
// can never be children of the current wrap.
|
||||
auto child_it = std::next(it);
|
||||
const auto children_end = std::lower_bound(
|
||||
child_it, end, UnwrappedTileID{ static_cast<int16_t>(renderable.id.wrap + 1), { 0, 0, 0 } },
|
||||
[](auto& a, auto& b) { return a.get().id < b; });
|
||||
for (; child_it != children_end; ++child_it) {
|
||||
auto& childTileID = child_it->get().id;
|
||||
if (childTileID.isChildOf(it->get().id)) {
|
||||
leaf.add(childTileID.canonical);
|
||||
}
|
||||
}
|
||||
|
||||
// Find a leaf with matching children.
|
||||
for (auto its = pool.equal_range(renderable.id); its.first != its.second; ++its.first) {
|
||||
auto& existing = its.first->second;
|
||||
if (existing == leaf) {
|
||||
leaf.clip = existing.clip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (leaf.clip.reference.none()) {
|
||||
// We haven't found an existing clip ID
|
||||
size++;
|
||||
}
|
||||
|
||||
pool.emplace(renderable.id, 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& it : renderables) {
|
||||
auto& renderable = it.get();
|
||||
if (!renderable.used || !renderable.needsClipping) {
|
||||
continue;
|
||||
}
|
||||
renderable.clip.mask |= mask;
|
||||
|
||||
// Assign only to clip IDs that have no value yet.
|
||||
if (renderable.clip.reference.none()) {
|
||||
renderable.clip.reference = uint32_t(count++) << bit_offset;
|
||||
}
|
||||
}
|
||||
|
||||
bit_offset += bit_count;
|
||||
}
|
||||
|
||||
// Prevent this warning from firing on every frame,
|
||||
// which can be expensive in some platforms.
|
||||
static bool warned = false;
|
||||
|
||||
if (!warned && bit_offset > 8) {
|
||||
Log::Error(Event::OpenGL, "stencil mask overflow");
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace mbgl
|
||||
@@ -3,9 +3,6 @@
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
#include <mbgl/layermanager/layer_manager.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -51,7 +48,6 @@ void RenderAnnotationSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
}
|
||||
|
||||
void RenderAnnotationSource::startRender(PaintParameters& parameters) {
|
||||
parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
|
||||
tilePyramid.startRender(parameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,8 @@ public:
|
||||
virtual void visualizeStencilBuffer() = 0;
|
||||
virtual void visualizeDepthBuffer(float depthRangeSize) = 0;
|
||||
#endif
|
||||
|
||||
virtual void clearStencilBuffer(int32_t) = 0;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
@@ -870,5 +870,10 @@ void Context::visualizeDepthBuffer(const float depthRangeSize) {
|
||||
|
||||
#endif
|
||||
|
||||
void Context::clearStencilBuffer(const int32_t bits) {
|
||||
MBGL_CHECK_ERROR(glClearStencil(bits));
|
||||
MBGL_CHECK_ERROR(glClear(GL_STENCIL_BUFFER_BIT));
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -247,6 +247,8 @@ public:
|
||||
void visualizeStencilBuffer() override;
|
||||
void visualizeDepthBuffer(float depthRangeSize) override;
|
||||
#endif
|
||||
|
||||
void clearStencilBuffer(int32_t) override;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -103,9 +103,7 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
*parameters.renderPass,
|
||||
gfx::Triangles(),
|
||||
parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly),
|
||||
parameters.mapMode != MapMode::Continuous
|
||||
? parameters.stencilModeForClipping(tile.clip)
|
||||
: gfx::StencilMode::disabled(),
|
||||
gfx::StencilMode::disabled(),
|
||||
parameters.colorModeForRenderPass(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
*bucket.indexBuffer,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/renderer/layers/render_fill_layer.hpp>
|
||||
#include <mbgl/renderer/buckets/fill_bucket.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/render_source.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/image_manager.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
@@ -73,6 +74,7 @@ bool RenderFillLayer::hasCrossfade() const {
|
||||
|
||||
void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
if (unevaluated.get<FillPattern>().isUndefined()) {
|
||||
parameters.renderTileClippingMasks(renderTiles);
|
||||
for (const RenderTile& tile : renderTiles) {
|
||||
const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl);
|
||||
if (!renderData) {
|
||||
@@ -115,7 +117,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
*parameters.renderPass,
|
||||
drawMode,
|
||||
depthMode,
|
||||
parameters.stencilModeForClipping(tile.clip),
|
||||
parameters.stencilModeForClipping(tile.id),
|
||||
parameters.colorModeForRenderPass(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
indexBuffer,
|
||||
@@ -157,6 +159,8 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.renderTileClippingMasks(renderTiles);
|
||||
|
||||
for (const RenderTile& tile : renderTiles) {
|
||||
const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl);
|
||||
if (!renderData) {
|
||||
@@ -209,7 +213,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
*parameters.renderPass,
|
||||
drawMode,
|
||||
depthMode,
|
||||
parameters.stencilModeForClipping(tile.clip),
|
||||
parameters.stencilModeForClipping(tile.id),
|
||||
parameters.colorModeForRenderPass(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
indexBuffer,
|
||||
|
||||
@@ -98,10 +98,6 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
|
||||
const auto extrudeScale = tile.id.pixelsToTileUnits(1, parameters.state.getZoom());
|
||||
|
||||
const auto stencilMode = parameters.mapMode != MapMode::Continuous
|
||||
? parameters.stencilModeForClipping(tile.clip)
|
||||
: gfx::StencilMode::disabled();
|
||||
|
||||
const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID());
|
||||
|
||||
auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap;
|
||||
@@ -129,7 +125,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
*renderPass,
|
||||
gfx::Triangles(),
|
||||
parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly),
|
||||
stencilMode,
|
||||
gfx::StencilMode::disabled(),
|
||||
gfx::ColorMode::additive(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
*bucket.indexBuffer,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/renderer/layers/render_line_layer.hpp>
|
||||
#include <mbgl/renderer/buckets/line_bucket.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/render_source.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/image_manager.hpp>
|
||||
#include <mbgl/programs/programs.hpp>
|
||||
@@ -62,6 +63,8 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
return;
|
||||
}
|
||||
|
||||
parameters.renderTileClippingMasks(renderTiles);
|
||||
|
||||
for (const RenderTile& tile : renderTiles) {
|
||||
const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl);
|
||||
if (!renderData) {
|
||||
@@ -98,7 +101,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
|
||||
*parameters.renderPass,
|
||||
gfx::Triangles(),
|
||||
parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly),
|
||||
parameters.stencilModeForClipping(tile.clip),
|
||||
parameters.stencilModeForClipping(tile.id),
|
||||
parameters.colorModeForRenderPass(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
*bucket.indexBuffer,
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
#include <mbgl/renderer/render_static_data.hpp>
|
||||
#include <mbgl/renderer/render_source.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/gfx/command_encoder.hpp>
|
||||
#include <mbgl/gfx/render_pass.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -73,15 +76,94 @@ gfx::DepthMode PaintParameters::depthModeFor3D(gfx::DepthMaskType mask) const {
|
||||
return gfx::DepthMode { gfx::DepthFunctionType::LessEqual, mask, { 0.0, 1.0 } };
|
||||
}
|
||||
|
||||
gfx::StencilMode PaintParameters::stencilModeForClipping(const ClipID& id) const {
|
||||
return gfx::StencilMode {
|
||||
gfx::StencilMode::Equal { static_cast<uint32_t>(id.mask.to_ulong()) },
|
||||
static_cast<int32_t>(id.reference.to_ulong()),
|
||||
0,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Replace
|
||||
};
|
||||
void PaintParameters::clearStencil() {
|
||||
nextStencilID = 1;
|
||||
context.clearStencilBuffer(0b00000000);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Detects a difference in keys of renderTiles and tileClippingMaskIDs
|
||||
bool tileIDsIdentical(const std::vector<std::reference_wrapper<RenderTile>>& renderTiles,
|
||||
const std::map<UnwrappedTileID, int32_t>& tileClippingMaskIDs) {
|
||||
assert(std::is_sorted(renderTiles.begin(), renderTiles.end(),
|
||||
[](const RenderTile& a, const RenderTile& b) { return a.id < b.id; }));
|
||||
if (renderTiles.size() != tileClippingMaskIDs.size()) {
|
||||
return false;
|
||||
}
|
||||
return std::equal(renderTiles.begin(), renderTiles.end(), tileClippingMaskIDs.begin(),
|
||||
[](const RenderTile& a, const auto& b) { return a.id == b.first; });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void PaintParameters::renderTileClippingMasks(const std::vector<std::reference_wrapper<RenderTile>>& renderTiles) {
|
||||
if (renderTiles.empty() || tileIDsIdentical(renderTiles, tileClippingMaskIDs)) {
|
||||
// The current stencil mask is for this source already; no need to draw another one.
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextStencilID + renderTiles.size() > 256) {
|
||||
// we'll run out of fresh IDs so we need to clear and start from scratch
|
||||
clearStencil();
|
||||
}
|
||||
|
||||
tileClippingMaskIDs.clear();
|
||||
|
||||
auto& program = staticData.programs.clippingMask;
|
||||
const style::Properties<>::PossiblyEvaluated properties {};
|
||||
const ClippingMaskProgram::Binders paintAttributeData(properties, 0);
|
||||
|
||||
for (const RenderTile& renderTile : renderTiles) {
|
||||
const int32_t stencilID = nextStencilID++;
|
||||
tileClippingMaskIDs.emplace(renderTile.id, stencilID);
|
||||
|
||||
program.draw(
|
||||
context,
|
||||
*renderPass,
|
||||
gfx::Triangles(),
|
||||
gfx::DepthMode::disabled(),
|
||||
gfx::StencilMode {
|
||||
gfx::StencilMode::Always{},
|
||||
stencilID,
|
||||
0b11111111,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Replace
|
||||
},
|
||||
gfx::ColorMode::disabled(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
staticData.quadTriangleIndexBuffer,
|
||||
staticData.tileTriangleSegments,
|
||||
program.computeAllUniformValues(
|
||||
ClippingMaskProgram::LayoutUniformValues {
|
||||
uniforms::matrix::Value( matrixForTile(renderTile.id) ),
|
||||
},
|
||||
paintAttributeData,
|
||||
properties,
|
||||
state.getZoom()
|
||||
),
|
||||
program.computeAllAttributeBindings(
|
||||
staticData.tileVertexBuffer,
|
||||
paintAttributeData,
|
||||
properties
|
||||
),
|
||||
ClippingMaskProgram::TextureBindings{},
|
||||
"clipping"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::StencilMode PaintParameters::stencilModeForClipping(const UnwrappedTileID& tileID) const {
|
||||
auto it = tileClippingMaskIDs.find(tileID);
|
||||
assert(it != tileClippingMaskIDs.end());
|
||||
const int32_t id = it != tileClippingMaskIDs.end() ? it->second : 0b00000000;
|
||||
return gfx::StencilMode{ gfx::StencilMode::Equal{ 0b11111111 },
|
||||
id,
|
||||
0b00000000,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Replace };
|
||||
}
|
||||
|
||||
gfx::ColorMode PaintParameters::colorModeForRenderPass() const {
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
#include <mbgl/gfx/stencil_mode.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/text/placement.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -21,6 +22,8 @@ class TransformState;
|
||||
class ImageManager;
|
||||
class LineAtlas;
|
||||
class UnwrappedTileID;
|
||||
class RenderSource;
|
||||
class RenderTile;
|
||||
|
||||
namespace gfx {
|
||||
class Context;
|
||||
@@ -62,13 +65,11 @@ public:
|
||||
float pixelRatio;
|
||||
Placement::VariableOffsets variableOffsets;
|
||||
std::array<float, 2> pixelsToGLUnits;
|
||||
algorithm::ClipIDGenerator clipIDGenerator;
|
||||
|
||||
Programs& programs;
|
||||
|
||||
gfx::DepthMode depthModeForSublayer(uint8_t n, gfx::DepthMaskType) const;
|
||||
gfx::DepthMode depthModeFor3D(gfx::DepthMaskType) const;
|
||||
gfx::StencilMode stencilModeForClipping(const ClipID&) const;
|
||||
gfx::ColorMode colorModeForRenderPass() const;
|
||||
|
||||
mat4 matrixForTile(const UnwrappedTileID&, bool aligned = false) const;
|
||||
@@ -77,10 +78,24 @@ public:
|
||||
mat4 alignedProjMatrix;
|
||||
mat4 nearClippedProjMatrix;
|
||||
|
||||
// Stencil handling
|
||||
public:
|
||||
void renderTileClippingMasks(const std::vector<std::reference_wrapper<RenderTile>>&);
|
||||
gfx::StencilMode stencilModeForClipping(const UnwrappedTileID&) const;
|
||||
|
||||
private:
|
||||
void clearStencil();
|
||||
|
||||
// This needs to be an ordered map so that we have the same order as the renderTiles.
|
||||
std::map<UnwrappedTileID, int32_t> tileClippingMaskIDs;
|
||||
int32_t nextStencilID = 1;
|
||||
|
||||
public:
|
||||
int numSublayers = 3;
|
||||
uint32_t currentLayer;
|
||||
float depthRangeSize;
|
||||
const float depthEpsilon = 1.0f / (1 << 16);
|
||||
|
||||
|
||||
float symbolFadeChange;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/style/layer.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
@@ -101,7 +101,7 @@ void RenderTile::finishRender(PaintParameters& parameters) {
|
||||
*parameters.renderPass,
|
||||
gfx::Lines { 4.0f * parameters.pixelRatio },
|
||||
gfx::DepthMode::disabled(),
|
||||
parameters.stencilModeForClipping(clip),
|
||||
gfx::StencilMode::disabled(),
|
||||
gfx::ColorMode::unblended(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
*tile.debugBucket->indexBuffer,
|
||||
@@ -125,7 +125,7 @@ void RenderTile::finishRender(PaintParameters& parameters) {
|
||||
*parameters.renderPass,
|
||||
gfx::Lines { 2.0f * parameters.pixelRatio },
|
||||
gfx::DepthMode::disabled(),
|
||||
parameters.stencilModeForClipping(clip),
|
||||
gfx::StencilMode::disabled(),
|
||||
gfx::ColorMode::unblended(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
*tile.debugBucket->indexBuffer,
|
||||
@@ -152,7 +152,7 @@ void RenderTile::finishRender(PaintParameters& parameters) {
|
||||
*parameters.renderPass,
|
||||
gfx::LineStrip { 4.0f * parameters.pixelRatio },
|
||||
gfx::DepthMode::disabled(),
|
||||
parameters.stencilModeForClipping(clip),
|
||||
gfx::StencilMode::disabled(),
|
||||
gfx::ColorMode::unblended(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
parameters.staticData.tileBorderIndexBuffer,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/renderer/tile_mask.hpp>
|
||||
|
||||
@@ -24,7 +23,6 @@ public:
|
||||
|
||||
UnwrappedTileID id;
|
||||
Tile& tile;
|
||||
ClipID clip;
|
||||
mat4 matrix;
|
||||
mat4 nearClippedMatrix;
|
||||
bool used = false;
|
||||
|
||||
@@ -420,61 +420,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
parameters.renderPass = parameters.encoder->createRenderPass("main buffer", { parameters.backend.getDefaultRenderable(), color, 1, 0 });
|
||||
}
|
||||
|
||||
// - CLIPPING MASKS ----------------------------------------------------------------------------
|
||||
// Draws the clipping masks to the stencil buffer.
|
||||
{
|
||||
const auto debugGroup(parameters.renderPass->createDebugGroup("clipping masks"));
|
||||
|
||||
static const Properties<>::PossiblyEvaluated properties {};
|
||||
static const ClippingMaskProgram::Binders paintAttributeData(properties, 0);
|
||||
|
||||
for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) {
|
||||
auto& program = parameters.staticData.programs.clippingMask;
|
||||
|
||||
program.draw(
|
||||
parameters.context,
|
||||
*parameters.renderPass,
|
||||
gfx::Triangles(),
|
||||
gfx::DepthMode::disabled(),
|
||||
gfx::StencilMode {
|
||||
gfx::StencilMode::Always(),
|
||||
static_cast<int32_t>(clipID.second.reference.to_ulong()),
|
||||
0b11111111,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Keep,
|
||||
gfx::StencilOpType::Replace
|
||||
},
|
||||
gfx::ColorMode::disabled(),
|
||||
gfx::CullFaceMode::disabled(),
|
||||
parameters.staticData.quadTriangleIndexBuffer,
|
||||
parameters.staticData.tileTriangleSegments,
|
||||
program.computeAllUniformValues(
|
||||
ClippingMaskProgram::LayoutUniformValues {
|
||||
uniforms::matrix::Value( parameters.matrixForTile(clipID.first) ),
|
||||
},
|
||||
paintAttributeData,
|
||||
properties,
|
||||
parameters.state.getZoom()
|
||||
),
|
||||
program.computeAllAttributeBindings(
|
||||
parameters.staticData.tileVertexBuffer,
|
||||
paintAttributeData,
|
||||
properties
|
||||
),
|
||||
ClippingMaskProgram::TextureBindings{},
|
||||
"clipping"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#if not defined(NDEBUG)
|
||||
// Render tile clip boundaries, using stencil buffer to calculate fill color.
|
||||
if (parameters.debugOptions & MapDebugOptions::StencilClip) {
|
||||
parameters.context.visualizeStencilBuffer();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Actually render the layers
|
||||
|
||||
parameters.depthRangeSize = 1 - (renderItems.size() + 2) * parameters.numSublayers * parameters.depthEpsilon;
|
||||
@@ -530,8 +475,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
|
||||
}
|
||||
|
||||
#if not defined(NDEBUG)
|
||||
// Render the depth buffer.
|
||||
if (parameters.debugOptions & MapDebugOptions::DepthBuffer) {
|
||||
if (parameters.debugOptions & MapDebugOptions::StencilClip) {
|
||||
// Render tile clip boundaries, using stencil buffer to calculate fill color.
|
||||
parameters.context.visualizeStencilBuffer();
|
||||
} else if (parameters.debugOptions & MapDebugOptions::DepthBuffer) {
|
||||
// Render the depth buffer.
|
||||
parameters.context.visualizeDepthBuffer(parameters.depthRangeSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/tile/custom_geometry_tile.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
@@ -51,7 +48,6 @@ void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_
|
||||
}
|
||||
|
||||
void RenderCustomGeometrySource::startRender(PaintParameters& parameters) {
|
||||
parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
|
||||
tilePyramid.startRender(parameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
#include <mbgl/tile/geojson_tile.hpp>
|
||||
#include <mbgl/renderer/tile_parameters.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
#include <mapbox/eternal.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -127,7 +124,6 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
}
|
||||
|
||||
void RenderGeoJSONSource::startRender(PaintParameters& parameters) {
|
||||
parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
|
||||
tilePyramid.startRender(parameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/tile/vector_tile.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids.hpp>
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
using namespace style;
|
||||
@@ -61,7 +58,6 @@ void RenderVectorSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
}
|
||||
|
||||
void RenderVectorSource::startRender(PaintParameters& parameters) {
|
||||
parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
|
||||
tilePyramid.startRender(parameters);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#include <mbgl/util/clip_id.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const ClipID& rhs) {
|
||||
return os << "mask=" << rhs.mask << ",ref=" << rhs.reference;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <bitset>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <forward_list>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct ClipID {
|
||||
ClipID() {}
|
||||
ClipID(const std::string &mask_, const std::string &reference_) : mask(mask_), reference(reference_) {}
|
||||
|
||||
std::bitset<8> mask;
|
||||
std::bitset<8> reference;
|
||||
|
||||
bool operator==(const ClipID &other) const {
|
||||
return mask == other.mask && reference == other.reference;
|
||||
}
|
||||
|
||||
ClipID& operator|=(const ClipID &other) {
|
||||
mask |= other.mask;
|
||||
reference |= other.reference;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const ClipID& rhs);
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,103 +0,0 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/algorithm/covered_by_children.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
using List = std::map<UnwrappedTileID, bool>;
|
||||
|
||||
TEST(CoveredByChildren, GrandChildren) {
|
||||
const List list {
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
// These grandchildren covers 1/0/0, but 1/0/0 only covers a quarter of
|
||||
// 0/0/0.
|
||||
{ UnwrappedTileID{ 2, 0, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 0, 1 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 1 }, true },
|
||||
};
|
||||
EXPECT_FALSE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list));
|
||||
|
||||
const List list2 {
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
|
||||
// Children of 1/0/0
|
||||
{ UnwrappedTileID{ 2, 0, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 0, 1 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 1 }, true },
|
||||
|
||||
// Children of 1/0/1
|
||||
{ UnwrappedTileID{ 2, 0, 2 }, true },
|
||||
{ UnwrappedTileID{ 2, 0, 3 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 2 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 3 }, true },
|
||||
|
||||
// Children of 1/1/0
|
||||
{ UnwrappedTileID{ 2, 2, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 2, 1 }, true },
|
||||
{ UnwrappedTileID{ 2, 3, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 3, 1 }, true },
|
||||
|
||||
// Children of 1/0/1
|
||||
{ UnwrappedTileID{ 2, 2, 2 }, true },
|
||||
{ UnwrappedTileID{ 2, 2, 3 }, true },
|
||||
{ UnwrappedTileID{ 2, 3, 2 }, true },
|
||||
{ UnwrappedTileID{ 2, 3, 3 }, true },
|
||||
};
|
||||
EXPECT_TRUE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list2));
|
||||
}
|
||||
|
||||
TEST(CoveredByChildren, NotCovered) {
|
||||
const List list1;
|
||||
EXPECT_FALSE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list1));
|
||||
|
||||
const List list2{
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
// 3 out of 4 child tiles
|
||||
{ UnwrappedTileID{ 1, 0, 0 }, true },
|
||||
{ UnwrappedTileID{ 1, 0, 1 }, true },
|
||||
// missing 1/1/0
|
||||
{ UnwrappedTileID{ 1, 1, 1 }, true },
|
||||
};
|
||||
EXPECT_FALSE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list2));
|
||||
|
||||
const List list3{
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
// all four child tiles, with a different wrap index
|
||||
{ UnwrappedTileID{ 1, { 1, 0, 0 } }, true },
|
||||
{ UnwrappedTileID{ 1, { 1, 0, 1 } }, true },
|
||||
{ UnwrappedTileID{ 1, { 1, 1, 0 } }, true },
|
||||
{ UnwrappedTileID{ 1, { 1, 1, 1 } }, true },
|
||||
};
|
||||
EXPECT_FALSE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list3));
|
||||
}
|
||||
|
||||
TEST(CoveredByChildren, Covered) {
|
||||
const List list1{
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
// all four child tiles
|
||||
{ UnwrappedTileID{ 1, 0, 0 }, true },
|
||||
{ UnwrappedTileID{ 1, 0, 1 }, true },
|
||||
{ UnwrappedTileID{ 1, 1, 0 }, true },
|
||||
{ UnwrappedTileID{ 1, 1, 1 }, true },
|
||||
};
|
||||
EXPECT_TRUE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list1));
|
||||
|
||||
const List list2{
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, true },
|
||||
// missing 1/0/0
|
||||
{ UnwrappedTileID{ 1, 0, 1 }, true },
|
||||
{ UnwrappedTileID{ 1, 1, 0 }, true },
|
||||
{ UnwrappedTileID{ 1, 1, 1 }, true },
|
||||
{ UnwrappedTileID{ 2, 0, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 0, 1 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 0 }, true },
|
||||
{ UnwrappedTileID{ 2, 1, 1 }, true },
|
||||
};
|
||||
EXPECT_TRUE(algorithm::coveredByChildren(UnwrappedTileID{ 0, 0, 0 }, list2));
|
||||
EXPECT_TRUE(algorithm::coveredByChildren(UnwrappedTileID{ 1, 0, 0 }, list2));
|
||||
EXPECT_FALSE(algorithm::coveredByChildren(UnwrappedTileID{ 2, 0, 0 }, list2));
|
||||
}
|
||||
@@ -1,459 +0,0 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
struct Renderable {
|
||||
UnwrappedTileID id;
|
||||
ClipID clip;
|
||||
bool used;
|
||||
bool needsClipping;
|
||||
|
||||
Renderable(UnwrappedTileID id_,
|
||||
ClipID clip_,
|
||||
bool used_ = true,
|
||||
bool needsClipping_ = true)
|
||||
: id(std::move(id_)),
|
||||
clip(std::move(clip_)),
|
||||
used(used_),
|
||||
needsClipping(needsClipping_) {}
|
||||
|
||||
bool operator==(const Renderable& rhs) const {
|
||||
return id == rhs.id && clip == rhs.clip;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
auto makeSorted(std::vector<Renderable>& renderables) {
|
||||
std::vector<std::reference_wrapper<Renderable>> sorted(renderables.begin(), renderables.end());
|
||||
std::sort(sorted.begin(), sorted.end(),
|
||||
[](const Renderable& a, const Renderable& b){ return a.id < b.id; });
|
||||
return sorted;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const Renderable& rhs) {
|
||||
return os << "Renderable{ " << rhs.id << ", " << rhs.clip << " }";
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, ParentAndFourChildren) {
|
||||
std::vector<Renderable> renderables{
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, {} },
|
||||
// All four covering children
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>({ renderables.begin(), renderables.end() });
|
||||
|
||||
EXPECT_EQ(decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
// 0/0/0 is missing because it is covered by children.
|
||||
{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
{ UnwrappedTileID{ 1, 0, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
{ UnwrappedTileID{ 1, 1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, ParentAndFourChildrenNegative) {
|
||||
std::vector<Renderable> renderables{
|
||||
Renderable{ UnwrappedTileID{ 1, -2, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, -2, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 0, -1, 0 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>(makeSorted(renderables));
|
||||
|
||||
EXPECT_EQ(decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 1, -2, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 1, -2, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
Renderable{ UnwrappedTileID{ 0, -1, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 1, -2, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
{ UnwrappedTileID{ 1, -2, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
{ UnwrappedTileID{ 1, -1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
{ UnwrappedTileID{ 1, -1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, NegativeParentAndMissingLevel) {
|
||||
std::vector<Renderable> renderables{
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, -1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, -2, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, -1, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, -2, 0 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>(makeSorted(renderables));
|
||||
|
||||
EXPECT_EQ(decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 1, -1, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 2, -1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 2, -2, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 2, -1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
Renderable{ UnwrappedTileID{ 2, -2, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 2, -2, 0 }, ClipID{ "00000111", "00000010" } },
|
||||
{ UnwrappedTileID{ 2, -2, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
{ UnwrappedTileID{ 2, -1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
{ UnwrappedTileID{ 2, -1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, SevenOnSameLevel) {
|
||||
std::vector<Renderable> renderables{
|
||||
// first column
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 2 }, {} },
|
||||
// second column
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 2 }, {} },
|
||||
// third column
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 0 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>({ renderables.begin(), renderables.end() });
|
||||
EXPECT_EQ(decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 2 }, ClipID{ "00000111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 2 }, ClipID{ "00000111", "00000110" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 0 }, ClipID{ "00000111", "00000111" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000111", "00000010" } },
|
||||
{ UnwrappedTileID{ 2, 0, 2 }, ClipID{ "00000111", "00000011" } },
|
||||
{ UnwrappedTileID{ 2, 1, 0 }, ClipID{ "00000111", "00000100" } },
|
||||
{ UnwrappedTileID{ 2, 1, 1 }, ClipID{ "00000111", "00000101" } },
|
||||
{ UnwrappedTileID{ 2, 1, 2 }, ClipID{ "00000111", "00000110" } },
|
||||
{ UnwrappedTileID{ 2, 2, 0 }, ClipID{ "00000111", "00000111" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, MultipleLevels) {
|
||||
std::vector<Renderable> renderables{
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, {} },
|
||||
// begin subtiles of (2/0/0)
|
||||
Renderable{ UnwrappedTileID{ 3, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 3, 0, 1 }, {} },
|
||||
// begin subtiles of (3/0/1)
|
||||
Renderable{ UnwrappedTileID{ 4, 0, 2 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 4, 1, 2 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 4, 0, 3 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 4, 1, 3 }, {} },
|
||||
// end subtiles of (3/0/1)
|
||||
Renderable{ UnwrappedTileID{ 3, 1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 3, 1, 1 }, {} },
|
||||
// end subtiles of (2/0/0)
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 0 }, {} },
|
||||
// begin subtiles of (2/1/0)
|
||||
Renderable{ UnwrappedTileID{ 3, 2, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 3, 2, 1 }, {} },
|
||||
// end subtiles of (2/1/0)
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>(makeSorted(renderables));
|
||||
ASSERT_EQ(decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00001111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 0, 0 }, ClipID{ "00001111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 0, 1 }, ClipID{ "00001111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 4, 0, 2 }, ClipID{ "00001111", "00001001" } },
|
||||
Renderable{ UnwrappedTileID{ 4, 1, 2 }, ClipID{ "00001111", "00001011" } },
|
||||
Renderable{ UnwrappedTileID{ 4, 0, 3 }, ClipID{ "00001111", "00001010" } },
|
||||
Renderable{ UnwrappedTileID{ 4, 1, 3 }, ClipID{ "00001111", "00001100" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 1, 0 }, ClipID{ "00001111", "00000101" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 1, 1 }, ClipID{ "00001111", "00000110" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 0 }, ClipID{ "00001111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 2, 0 }, ClipID{ "00001111", "00000111" } },
|
||||
Renderable{ UnwrappedTileID{ 3, 2, 1 }, ClipID{ "00001111", "00001000" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 2, 1, 0 }, ClipID{ "00001111", "00000010" } },
|
||||
{ UnwrappedTileID{ 3, 0, 0 }, ClipID{ "00001111", "00000011" } },
|
||||
{ UnwrappedTileID{ 3, 1, 0 }, ClipID{ "00001111", "00000101" } },
|
||||
{ UnwrappedTileID{ 3, 1, 1 }, ClipID{ "00001111", "00000110" } },
|
||||
{ UnwrappedTileID{ 3, 2, 0 }, ClipID{ "00001111", "00000111" } },
|
||||
{ UnwrappedTileID{ 3, 2, 1 }, ClipID{ "00001111", "00001000" } },
|
||||
{ UnwrappedTileID{ 4, 0, 2 }, ClipID{ "00001111", "00001001" } },
|
||||
{ UnwrappedTileID{ 4, 0, 3 }, ClipID{ "00001111", "00001010" } },
|
||||
{ UnwrappedTileID{ 4, 1, 2 }, ClipID{ "00001111", "00001011" } },
|
||||
{ UnwrappedTileID{ 4, 1, 3 }, ClipID{ "00001111", "00001100" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, Bug206) {
|
||||
std::vector<Renderable> renderables{
|
||||
Renderable{ UnwrappedTileID{ 10, 162, 395 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 10, 162, 396 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 10, 163, 395 }, {} },
|
||||
// begin subtiles of (10/163/395)
|
||||
Renderable{ UnwrappedTileID{ 11, 326, 791 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 12, 654, 1582 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 12, 654, 1583 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 12, 655, 1582 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 12, 655, 1583 }, {} },
|
||||
// end subtiles of (10/163/395)
|
||||
Renderable{ UnwrappedTileID{ 10, 163, 396 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 10, 164, 395 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 10, 164, 396 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>(makeSorted(renderables));
|
||||
EXPECT_EQ(
|
||||
decltype(renderables)({
|
||||
Renderable{ UnwrappedTileID{ 10, 162, 395 }, ClipID{ "00001111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 10, 162, 396 }, ClipID{ "00001111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 10, 163, 395 }, ClipID{ "00001111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 11, 326, 791 }, ClipID{ "00001111", "00000111" } },
|
||||
Renderable{ UnwrappedTileID{ 12, 654, 1582 }, ClipID{ "00001111", "00001000" } },
|
||||
Renderable{ UnwrappedTileID{ 12, 654, 1583 }, ClipID{ "00001111", "00001001" } },
|
||||
Renderable{ UnwrappedTileID{ 12, 655, 1582 }, ClipID{ "00001111", "00001010" } },
|
||||
Renderable{ UnwrappedTileID{ 12, 655, 1583 }, ClipID{ "00001111", "00001011" } },
|
||||
Renderable{ UnwrappedTileID{ 10, 163, 396 }, ClipID{ "00001111", "00000100" } },
|
||||
Renderable{ UnwrappedTileID{ 10, 164, 395 }, ClipID{ "00001111", "00000101" } },
|
||||
Renderable{ UnwrappedTileID{ 10, 164, 396 }, ClipID{ "00001111", "00000110" } },
|
||||
}),
|
||||
renderables);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 10, 162, 395 }, ClipID{ "00001111", "00000001" } },
|
||||
{ UnwrappedTileID{ 10, 162, 396 }, ClipID{ "00001111", "00000010" } },
|
||||
{ UnwrappedTileID{ 10, 163, 395 }, ClipID{ "00001111", "00000011" } },
|
||||
{ UnwrappedTileID{ 10, 163, 396 }, ClipID{ "00001111", "00000100" } },
|
||||
{ UnwrappedTileID{ 10, 164, 395 }, ClipID{ "00001111", "00000101" } },
|
||||
{ UnwrappedTileID{ 10, 164, 396 }, ClipID{ "00001111", "00000110" } },
|
||||
{ UnwrappedTileID{ 11, 326, 791 }, ClipID{ "00001111", "00000111" } },
|
||||
{ UnwrappedTileID{ 12, 654, 1582 }, ClipID{ "00001111", "00001000" } },
|
||||
{ UnwrappedTileID{ 12, 654, 1583 }, ClipID{ "00001111", "00001001" } },
|
||||
{ UnwrappedTileID{ 12, 655, 1582 }, ClipID{ "00001111", "00001010" } },
|
||||
{ UnwrappedTileID{ 12, 655, 1583 }, ClipID{ "00001111", "00001011" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, MultipleSources) {
|
||||
std::vector<Renderable> renderables1{
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, {} },
|
||||
// Differing children
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 2 }, {} },
|
||||
};
|
||||
std::vector<Renderable> renderables2{
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, {} },
|
||||
// Differing children
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 2 }, {} },
|
||||
};
|
||||
std::vector<Renderable> renderables3{
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, {} },
|
||||
// Differing children
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>({ renderables1.begin(), renderables1.end() });
|
||||
generator.update<Renderable>({ renderables2.begin(), renderables2.end() });
|
||||
generator.update<Renderable>({ renderables3.begin(), renderables3.end() });
|
||||
EXPECT_EQ(decltype(renderables1)({
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00000111", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "00000111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 1 }, ClipID{ "00000111", "00000011" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 2 }, ClipID{ "00000111", "00000100" } },
|
||||
}),
|
||||
renderables1);
|
||||
EXPECT_EQ(decltype(renderables2)({
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00011000", "00001000" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "00011111", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, ClipID{ "00011000", "00010000" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 2, 2 }, ClipID{ "00011111", "00000100" } },
|
||||
}),
|
||||
renderables2);
|
||||
EXPECT_EQ(decltype(renderables3)({
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "11100000", "00100000" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 1 }, ClipID{ "11100000", "01000000" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 0 }, ClipID{ "11100000", "01100000" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "11100000", "10000000" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 1, 1 }, ClipID{ "11111000", "00010000" } },
|
||||
}),
|
||||
renderables3);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "11111111", "00101001" } },
|
||||
{ UnwrappedTileID{ 1, 0, 1 }, ClipID{ "11111111", "01001001" } },
|
||||
{ UnwrappedTileID{ 1, 1, 0 }, ClipID{ "11111111", "01101001" } },
|
||||
{ UnwrappedTileID{ 1, 1, 1 }, ClipID{ "11111111", "10000010" } },
|
||||
{ UnwrappedTileID{ 2, 1, 1 }, ClipID{ "11111111", "00010001" } },
|
||||
{ UnwrappedTileID{ 2, 2, 1 }, ClipID{ "11111111", "01101011" } },
|
||||
{ UnwrappedTileID{ 2, 2, 2 }, ClipID{ "11111111", "10000100" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, SomeUnclippedTiles) {
|
||||
std::vector<Renderable> renderables1{
|
||||
Renderable { UnwrappedTileID { 7, 36, 49 }, {}, true, true },
|
||||
Renderable { UnwrappedTileID { 7, 36, 48 }, {}, true, true },
|
||||
Renderable { UnwrappedTileID { 7, 35, 48 }, {}, true, false },
|
||||
Renderable { UnwrappedTileID { 7, 35, 49 }, {}, true, false },
|
||||
Renderable { UnwrappedTileID { 7, 37, 48 }, {}, true, false },
|
||||
Renderable { UnwrappedTileID { 7, 37, 49 }, {}, true, false }
|
||||
};
|
||||
std::vector<Renderable> renderables2{
|
||||
Renderable { UnwrappedTileID { 7, 36, 49 }, {}, true, true },
|
||||
Renderable { UnwrappedTileID { 7, 36, 48 }, {}, true, true }
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>(makeSorted(renderables1));
|
||||
generator.update<Renderable>(makeSorted(renderables2));
|
||||
EXPECT_EQ(decltype(renderables1)({
|
||||
Renderable { UnwrappedTileID { 7, 36, 49 }, ClipID {"00000011","00000010"} },
|
||||
Renderable { UnwrappedTileID { 7, 36, 48 }, ClipID {"00000011","00000001"} },
|
||||
Renderable { UnwrappedTileID { 7, 35, 48 }, ClipID {"00000000","00000000"} },
|
||||
Renderable { UnwrappedTileID { 7, 35, 49 }, ClipID {"00000000","00000000"} },
|
||||
Renderable { UnwrappedTileID { 7, 37, 48 }, ClipID {"00000000","00000000"} },
|
||||
Renderable { UnwrappedTileID { 7, 37, 49 }, ClipID {"00000000","00000000"} }
|
||||
}),
|
||||
renderables1);
|
||||
EXPECT_EQ(decltype(renderables2)({
|
||||
Renderable { UnwrappedTileID { 7, 36, 49 }, ClipID {"00000011","00000010"} },
|
||||
Renderable { UnwrappedTileID { 7, 36, 48 }, ClipID {"00000011","00000001"} }
|
||||
}),
|
||||
renderables2);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID { 7, 36, 48 }, ClipID {"00000011","00000001"} },
|
||||
{ UnwrappedTileID { 7, 36, 49 }, ClipID {"00000011","00000010"} }
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, DuplicateIDs) {
|
||||
std::vector<Renderable> renderables1{
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, {} },
|
||||
};
|
||||
std::vector<Renderable> renderables2{
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, {} },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>({ renderables1.begin(), renderables1.end() });
|
||||
generator.update<Renderable>({ renderables2.begin(), renderables2.end() });
|
||||
EXPECT_EQ(decltype(renderables1)({
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00000011", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000011", "00000010" } },
|
||||
}),
|
||||
renderables1);
|
||||
EXPECT_EQ(decltype(renderables2)({
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00000011", "00000001" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000011", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000011", "00000010" } },
|
||||
}),
|
||||
renderables2);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 2, 0, 0 }, ClipID{ "00000011", "00000001" } },
|
||||
{ UnwrappedTileID{ 2, 0, 1 }, ClipID{ "00000011", "00000010" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
|
||||
TEST(GenerateClipIDs, SecondSourceHasParentOfFirstSource) {
|
||||
std::vector<Renderable> renderables1{
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, {} },
|
||||
};
|
||||
std::vector<Renderable> renderables2{
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, {} },
|
||||
// Same as in renderables1, but has a parent that it knocks out.
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, {} },
|
||||
};
|
||||
std::vector<Renderable> renderables3{
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, {} },
|
||||
};
|
||||
|
||||
algorithm::ClipIDGenerator generator;
|
||||
generator.update<Renderable>({ renderables1.begin(), renderables1.end() });
|
||||
generator.update<Renderable>({ renderables2.begin(), renderables2.end() });
|
||||
generator.update<Renderable>({ renderables3.begin(), renderables3.end() });
|
||||
EXPECT_EQ(decltype(renderables1)({
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "00000001", "00000001" } },
|
||||
}),
|
||||
renderables1);
|
||||
EXPECT_EQ(decltype(renderables2)({
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00000010", "00000010" } },
|
||||
Renderable{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "00000011", "00000001" } },
|
||||
}),
|
||||
renderables2);
|
||||
EXPECT_EQ(decltype(renderables3)({
|
||||
Renderable{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00000100", "00000100" } },
|
||||
}),
|
||||
renderables3);
|
||||
|
||||
const auto clipIDs = generator.getClipIDs();
|
||||
EXPECT_EQ(decltype(clipIDs)({
|
||||
{ UnwrappedTileID{ 0, 0, 0 }, ClipID{ "00000110", "00000110" } },
|
||||
{ UnwrappedTileID{ 1, 0, 0 }, ClipID{ "00000111", "00000101" } },
|
||||
}),
|
||||
clipIDs);
|
||||
}
|
||||
@@ -3,8 +3,6 @@
|
||||
"sources": [
|
||||
"test/actor/actor.test.cpp",
|
||||
"test/actor/actor_ref.test.cpp",
|
||||
"test/algorithm/covered_by_children.test.cpp",
|
||||
"test/algorithm/generate_clip_ids.test.cpp",
|
||||
"test/algorithm/update_renderables.test.cpp",
|
||||
"test/algorithm/update_tile_masks.test.cpp",
|
||||
"test/api/annotations.test.cpp",
|
||||
|
||||
Reference in New Issue
Block a user