From 0f1b758d24c58798aab53cc34da3c4aba8999efa Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Tue, 23 Jan 2024 10:34:07 +0100 Subject: [PATCH 1/3] Add support for self-masking vector layers --- .../graphics/objects/LineGroup2dOpenGl.cpp | 6 +----- .../cpp/graphics/objects/Polygon2dOpenGl.cpp | 21 +++++++++++++------ .../graphics/objects/PolygonGroup2dOpenGl.cpp | 16 ++++++++++++-- .../objects/PolygonPatternGroup2dOpenGl.cpp | 16 ++++++++++++-- .../objects/Quad2dInstancedOpenGl.cpp | 16 ++++++++++++-- .../cpp/graphics/objects/Quad2dOpenGl.cpp | 16 ++++++++++++-- .../Quad2dStretchedInstancedOpenGl.cpp | 16 ++++++++++++-- .../objects/Text2dInstancedOpenGl.cpp | 16 ++++++++++++-- .../cpp/graphics/objects/Text2dOpenGl.cpp | 16 ++++++++++++-- .../shared/graphics/RenderPassConfig.kt | 1 + .../jni/graphics/NativeRenderPassConfig.cpp | 8 ++++--- .../jni/graphics/NativeRenderPassConfig.h | 3 ++- bridging/ios/MCRenderPassConfig+Private.mm | 6 ++++-- bridging/ios/MCRenderPassConfig.h | 8 +++++-- bridging/ios/MCRenderPassConfig.mm | 8 +++++-- djinni/graphics/core.djinni | 1 + .../public/BackgroundVectorLayerDescription.h | 2 +- shared/public/LineVectorLayerDescription.h | 7 ++++--- shared/public/PolygonVectorLayerDescription.h | 7 ++++--- shared/public/RasterVectorLayerDescription.h | 2 +- shared/public/RenderPassConfig.h | 6 ++++-- shared/public/SymbolVectorLayerDescription.h | 7 ++++--- shared/public/Tiled2dMapVectorLayer.h | 1 + shared/public/VectorLayerDescription.h | 7 +++++-- shared/src/map/layers/icon/IconLayer.cpp | 2 +- shared/src/map/layers/line/LineLayer.cpp | 2 +- .../src/map/layers/polygon/PolygonLayer.cpp | 2 +- shared/src/map/layers/text/TextLayer.cpp | 2 +- .../tiled/raster/Tiled2dMapRasterLayer.cpp | 6 +++--- .../tiled/vector/Tiled2dMapVectorLayer.cpp | 10 ++++----- .../Tiled2dMapVectorLayerParserHelper.cpp | 13 +++++++++--- .../Tiled2dMapVectorSourceDataManager.cpp | 3 +++ .../Tiled2dMapVectorSourceDataManager.h | 1 + .../Tiled2dMapVectorSourceTileDataManager.cpp | 3 ++- .../Tiled2dMapVectorBackgroundSubLayer.cpp | 2 +- ...iled2dMapVectorSourceSymbolDataManager.cpp | 3 ++- 36 files changed, 194 insertions(+), 68 deletions(-) diff --git a/android/src/main/cpp/graphics/objects/LineGroup2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/LineGroup2dOpenGl.cpp index 74bea30b4..5da48238a 100644 --- a/android/src/main/cpp/graphics/objects/LineGroup2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/LineGroup2dOpenGl.cpp @@ -109,11 +109,7 @@ void LineGroup2dOpenGl::render(const std::shared_ptr<::RenderingContextInterface std::shared_ptr openGlContext = std::static_pointer_cast(context); if (isMasked) { - if (isMaskInversed) { - glStencilFunc(GL_EQUAL, 0, 255); - } else { - glStencilFunc(GL_EQUAL, 128, 255); - } + glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 255); } else { glEnable(GL_STENCIL_TEST); glStencilMask(0xFF); diff --git a/android/src/main/cpp/graphics/objects/Polygon2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/Polygon2dOpenGl.cpp index c1d566edf..8401fbd02 100644 --- a/android/src/main/cpp/graphics/objects/Polygon2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Polygon2dOpenGl.cpp @@ -104,14 +104,23 @@ void Polygon2dOpenGl::render(const std::shared_ptr<::RenderingContextInterface> std::shared_ptr openGlContext = std::static_pointer_cast(context); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - if (isMaskInversed) { - glStencilFunc(GL_EQUAL, 0, 255); - } else { - glStencilFunc(GL_EQUAL, 128, 255); - } + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; } - glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); + } + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); drawPolygon(openGlContext, program, mvpMatrix); diff --git a/android/src/main/cpp/graphics/objects/PolygonGroup2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/PolygonGroup2dOpenGl.cpp index 7c886aaf0..b051f63c2 100644 --- a/android/src/main/cpp/graphics/objects/PolygonGroup2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/PolygonGroup2dOpenGl.cpp @@ -98,9 +98,21 @@ void PolygonGroup2dOpenGl::render(const std::shared_ptr<::RenderingContextInterf if (!ready) return; + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } std::shared_ptr openGlContext = std::static_pointer_cast(context); diff --git a/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp index 5806483b8..7bc3ecbca 100644 --- a/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp @@ -141,9 +141,21 @@ void PolygonPatternGroup2dOpenGl::render(const std::shared_ptr<::RenderingContex glUseProgram(program); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } prepareTextureDraw(program); diff --git a/android/src/main/cpp/graphics/objects/Quad2dInstancedOpenGl.cpp b/android/src/main/cpp/graphics/objects/Quad2dInstancedOpenGl.cpp index 05abb60c2..f701f1eec 100644 --- a/android/src/main/cpp/graphics/objects/Quad2dInstancedOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Quad2dInstancedOpenGl.cpp @@ -206,9 +206,21 @@ void Quad2dInstancedOpenGl::render(const std::shared_ptr<::RenderingContextInter glUseProgram(program); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } if (usesTextureCoords) { diff --git a/android/src/main/cpp/graphics/objects/Quad2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/Quad2dOpenGl.cpp index a9ada46c5..fab8e48d8 100644 --- a/android/src/main/cpp/graphics/objects/Quad2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Quad2dOpenGl.cpp @@ -193,9 +193,21 @@ void Quad2dOpenGl::render(const std::shared_ptr<::RenderingContextInterface> &co glUseProgram(program); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } if (usesTextureCoords) { diff --git a/android/src/main/cpp/graphics/objects/Quad2dStretchedInstancedOpenGl.cpp b/android/src/main/cpp/graphics/objects/Quad2dStretchedInstancedOpenGl.cpp index 8312584c3..bf6dcf70f 100644 --- a/android/src/main/cpp/graphics/objects/Quad2dStretchedInstancedOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Quad2dStretchedInstancedOpenGl.cpp @@ -205,9 +205,21 @@ void Quad2dStretchedInstancedOpenGl::render(const std::shared_ptr<::RenderingCon glUseProgram(program); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } if (usesTextureCoords) { diff --git a/android/src/main/cpp/graphics/objects/Text2dInstancedOpenGl.cpp b/android/src/main/cpp/graphics/objects/Text2dInstancedOpenGl.cpp index 411f69ccc..580434682 100644 --- a/android/src/main/cpp/graphics/objects/Text2dInstancedOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Text2dInstancedOpenGl.cpp @@ -200,9 +200,21 @@ void Text2dInstancedOpenGl::render(const std::shared_ptr<::RenderingContextInter glUseProgram(program); + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } if (usesTextureCoords) { diff --git a/android/src/main/cpp/graphics/objects/Text2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/Text2dOpenGl.cpp index 8aef63ffe..4eb9f3754 100644 --- a/android/src/main/cpp/graphics/objects/Text2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/Text2dOpenGl.cpp @@ -209,9 +209,21 @@ void Text2dOpenGl::render(const std::shared_ptr<::RenderingContextInterface> &co return; } + GLuint stencilMask = 0; + GLuint validTarget = 0; + GLenum zpass = GL_KEEP; if (isMasked) { - glStencilFunc(GL_EQUAL, isMaskInversed ? 0 : 128, 128); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + stencilMask += 128; + validTarget = isMaskInversed ? 0 : 128; + } + if (renderPass.isPassMasked) { + stencilMask += 127; + zpass = GL_INCR; + } + + if (stencilMask != 0) { + glStencilFunc(GL_EQUAL, validTarget, stencilMask); + glStencilOp(GL_KEEP, GL_KEEP, zpass); } glUseProgram(program); diff --git a/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderPassConfig.kt b/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderPassConfig.kt index fccc13827..f3d4473b6 100644 --- a/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderPassConfig.kt +++ b/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/RenderPassConfig.kt @@ -5,4 +5,5 @@ package io.openmobilemaps.mapscore.shared.graphics data class RenderPassConfig( val renderPassIndex: Int, + val isPassMasked: Boolean, ) \ No newline at end of file diff --git a/bridging/android/jni/graphics/NativeRenderPassConfig.cpp b/bridging/android/jni/graphics/NativeRenderPassConfig.cpp index d37a188ab..91733ef5f 100644 --- a/bridging/android/jni/graphics/NativeRenderPassConfig.cpp +++ b/bridging/android/jni/graphics/NativeRenderPassConfig.cpp @@ -13,16 +13,18 @@ NativeRenderPassConfig::~NativeRenderPassConfig() = default; auto NativeRenderPassConfig::fromCpp(JNIEnv* jniEnv, const CppType& c) -> ::djinni::LocalRef { const auto& data = ::djinni::JniClass::get(); auto r = ::djinni::LocalRef{jniEnv->NewObject(data.clazz.get(), data.jconstructor, - ::djinni::get(::djinni::I32::fromCpp(jniEnv, c.renderPassIndex)))}; + ::djinni::get(::djinni::I32::fromCpp(jniEnv, c.renderPassIndex)), + ::djinni::get(::djinni::Bool::fromCpp(jniEnv, c.isPassMasked)))}; ::djinni::jniExceptionCheck(jniEnv); return r; } auto NativeRenderPassConfig::toCpp(JNIEnv* jniEnv, JniType j) -> CppType { - ::djinni::JniLocalScope jscope(jniEnv, 2); + ::djinni::JniLocalScope jscope(jniEnv, 3); assert(j != nullptr); const auto& data = ::djinni::JniClass::get(); - return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_renderPassIndex))}; + return {::djinni::I32::toCpp(jniEnv, jniEnv->GetIntField(j, data.field_renderPassIndex)), + ::djinni::Bool::toCpp(jniEnv, jniEnv->GetBooleanField(j, data.field_isPassMasked))}; } } // namespace djinni_generated diff --git a/bridging/android/jni/graphics/NativeRenderPassConfig.h b/bridging/android/jni/graphics/NativeRenderPassConfig.h index 4cbd4d35f..35308d7f9 100644 --- a/bridging/android/jni/graphics/NativeRenderPassConfig.h +++ b/bridging/android/jni/graphics/NativeRenderPassConfig.h @@ -25,8 +25,9 @@ class NativeRenderPassConfig final { friend ::djinni::JniClass; const ::djinni::GlobalRef clazz { ::djinni::jniFindClass("io/openmobilemaps/mapscore/shared/graphics/RenderPassConfig") }; - const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "", "(I)V") }; + const jmethodID jconstructor { ::djinni::jniGetMethodID(clazz.get(), "", "(IZ)V") }; const jfieldID field_renderPassIndex { ::djinni::jniGetFieldID(clazz.get(), "renderPassIndex", "I") }; + const jfieldID field_isPassMasked { ::djinni::jniGetFieldID(clazz.get(), "isPassMasked", "Z") }; }; } // namespace djinni_generated diff --git a/bridging/ios/MCRenderPassConfig+Private.mm b/bridging/ios/MCRenderPassConfig+Private.mm index 9afa4ac8b..9841ab1a9 100644 --- a/bridging/ios/MCRenderPassConfig+Private.mm +++ b/bridging/ios/MCRenderPassConfig+Private.mm @@ -10,12 +10,14 @@ auto RenderPassConfig::toCpp(ObjcType obj) -> CppType { assert(obj); - return {::djinni::I32::toCpp(obj.renderPassIndex)}; + return {::djinni::I32::toCpp(obj.renderPassIndex), + ::djinni::Bool::toCpp(obj.isPassMasked)}; } auto RenderPassConfig::fromCpp(const CppType& cpp) -> ObjcType { - return [[MCRenderPassConfig alloc] initWithRenderPassIndex:(::djinni::I32::fromCpp(cpp.renderPassIndex))]; + return [[MCRenderPassConfig alloc] initWithRenderPassIndex:(::djinni::I32::fromCpp(cpp.renderPassIndex)) + isPassMasked:(::djinni::Bool::fromCpp(cpp.isPassMasked))]; } } // namespace djinni_generated diff --git a/bridging/ios/MCRenderPassConfig.h b/bridging/ios/MCRenderPassConfig.h index f407896fd..9e9216fee 100644 --- a/bridging/ios/MCRenderPassConfig.h +++ b/bridging/ios/MCRenderPassConfig.h @@ -6,9 +6,13 @@ @interface MCRenderPassConfig : NSObject - (nonnull instancetype)init NS_UNAVAILABLE; + (nonnull instancetype)new NS_UNAVAILABLE; -- (nonnull instancetype)initWithRenderPassIndex:(int32_t)renderPassIndex NS_DESIGNATED_INITIALIZER; -+ (nonnull instancetype)renderPassConfigWithRenderPassIndex:(int32_t)renderPassIndex; +- (nonnull instancetype)initWithRenderPassIndex:(int32_t)renderPassIndex + isPassMasked:(BOOL)isPassMasked NS_DESIGNATED_INITIALIZER; ++ (nonnull instancetype)renderPassConfigWithRenderPassIndex:(int32_t)renderPassIndex + isPassMasked:(BOOL)isPassMasked; @property (nonatomic, readonly) int32_t renderPassIndex; +@property (nonatomic, readonly) BOOL isPassMasked; + @end diff --git a/bridging/ios/MCRenderPassConfig.mm b/bridging/ios/MCRenderPassConfig.mm index 04d6a98fc..444046acd 100644 --- a/bridging/ios/MCRenderPassConfig.mm +++ b/bridging/ios/MCRenderPassConfig.mm @@ -7,22 +7,26 @@ @implementation MCRenderPassConfig - (nonnull instancetype)initWithRenderPassIndex:(int32_t)renderPassIndex + isPassMasked:(BOOL)isPassMasked { if (self = [super init]) { _renderPassIndex = renderPassIndex; + _isPassMasked = isPassMasked; } return self; } + (nonnull instancetype)renderPassConfigWithRenderPassIndex:(int32_t)renderPassIndex + isPassMasked:(BOOL)isPassMasked { - return [[self alloc] initWithRenderPassIndex:renderPassIndex]; + return [[self alloc] initWithRenderPassIndex:renderPassIndex + isPassMasked:isPassMasked]; } #ifndef DJINNI_DISABLE_DESCRIPTION_METHODS - (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p renderPassIndex:%@>", self.class, (void *)self, @(self.renderPassIndex)]; + return [NSString stringWithFormat:@"<%@ %p renderPassIndex:%@ isPassMasked:%@>", self.class, (void *)self, @(self.renderPassIndex), @(self.isPassMasked)]; } #endif diff --git a/djinni/graphics/core.djinni b/djinni/graphics/core.djinni index 450bbf437..b6d69aa56 100644 --- a/djinni/graphics/core.djinni +++ b/djinni/graphics/core.djinni @@ -58,6 +58,7 @@ render_pass_interface = interface +c +j +o { render_pass_config = record { render_pass_index: i32; + is_pass_masked: bool; } renderer_interface = interface +c +j +o { diff --git a/shared/public/BackgroundVectorLayerDescription.h b/shared/public/BackgroundVectorLayerDescription.h index de72b789b..4119dc5e3 100644 --- a/shared/public/BackgroundVectorLayerDescription.h +++ b/shared/public/BackgroundVectorLayerDescription.h @@ -65,7 +65,7 @@ class BackgroundVectorLayerDescription: public VectorLayerDescription { BackgroundVectorStyle style, std::optional renderPassIndex, std::shared_ptr interactable): - VectorLayerDescription(identifier, "", "", 0, 0, nullptr, renderPassIndex, interactable, false), + VectorLayerDescription(identifier, "", "", 0, 0, nullptr, renderPassIndex, interactable, false, false), style(style) {}; std::unique_ptr clone() override { diff --git a/shared/public/LineVectorLayerDescription.h b/shared/public/LineVectorLayerDescription.h index cef864260..caef87fa3 100644 --- a/shared/public/LineVectorLayerDescription.h +++ b/shared/public/LineVectorLayerDescription.h @@ -134,14 +134,15 @@ class LineVectorLayerDescription: public VectorLayerDescription { LineVectorStyle style, std::optional renderPassIndex, std::shared_ptr interactable, - bool multiselect): - VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, multiselect), + bool multiselect, + bool selfMasked): + VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, multiselect, selfMasked), style(style) {}; std::unique_ptr clone() override { return std::make_unique(identifier, source, sourceLayer, minZoom, maxZoom, filter ? filter->clone() : nullptr, style, renderPassIndex, - interactable ? interactable->clone() : nullptr, multiselect); + interactable ? interactable->clone() : nullptr, multiselect, selfMasked); } virtual UsedKeysCollection getUsedKeys() const override { diff --git a/shared/public/PolygonVectorLayerDescription.h b/shared/public/PolygonVectorLayerDescription.h index f082d3ab7..84cc869ca 100644 --- a/shared/public/PolygonVectorLayerDescription.h +++ b/shared/public/PolygonVectorLayerDescription.h @@ -99,14 +99,15 @@ class PolygonVectorLayerDescription: public VectorLayerDescription { PolygonVectorStyle style, std::optional renderPassIndex, std::shared_ptr interactable, - bool multiselect): - VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, multiselect), + bool multiselect, + bool selfMasked): + VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, multiselect, selfMasked), style(style) {}; std::unique_ptr clone() override { return std::make_unique(identifier, source, sourceLayer, minZoom, maxZoom, filter ? filter->clone() : nullptr, style, renderPassIndex, - interactable ? interactable->clone() : nullptr, multiselect); + interactable ? interactable->clone() : nullptr, multiselect, selfMasked); } virtual UsedKeysCollection getUsedKeys() const override { diff --git a/shared/public/RasterVectorLayerDescription.h b/shared/public/RasterVectorLayerDescription.h index 949ab93e1..32f1fb700 100644 --- a/shared/public/RasterVectorLayerDescription.h +++ b/shared/public/RasterVectorLayerDescription.h @@ -144,7 +144,7 @@ class RasterVectorLayerDescription: public VectorLayerDescription { bool underzoom, bool overzoom, std::optional<::RectCoord> bounds): - VectorLayerDescription(identifier, source, "", minZoom, maxZoom, nullptr, renderPassIndex, interactable, false), + VectorLayerDescription(identifier, source, "", minZoom, maxZoom, nullptr, renderPassIndex, interactable, false, false), style(style), url(url), underzoom(underzoom), overzoom(overzoom), adaptScaleToScreen(adaptScaleToScreen), numDrawPreviousLayers(numDrawPreviousLayers), maskTiles(maskTiles), zoomLevelScaleFactor(zoomLevelScaleFactor), bounds(bounds) {}; diff --git a/shared/public/RenderPassConfig.h b/shared/public/RenderPassConfig.h index e5e0e35a4..ac0347f31 100644 --- a/shared/public/RenderPassConfig.h +++ b/shared/public/RenderPassConfig.h @@ -8,9 +8,11 @@ struct RenderPassConfig final { int32_t renderPassIndex; + bool isPassMasked; - //NOLINTNEXTLINE(google-explicit-constructor) - RenderPassConfig(int32_t renderPassIndex_) + RenderPassConfig(int32_t renderPassIndex_, + bool isPassMasked_) : renderPassIndex(std::move(renderPassIndex_)) + , isPassMasked(std::move(isPassMasked_)) {} }; diff --git a/shared/public/SymbolVectorLayerDescription.h b/shared/public/SymbolVectorLayerDescription.h index 4dcc6c58c..9743afc36 100644 --- a/shared/public/SymbolVectorLayerDescription.h +++ b/shared/public/SymbolVectorLayerDescription.h @@ -509,14 +509,15 @@ class SymbolVectorLayerDescription: public VectorLayerDescription { std::shared_ptr filter, SymbolVectorStyle style, std::optional renderPassIndex, - std::shared_ptr interactable): - VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, false), + std::shared_ptr interactable, + bool selfMasked): + VectorLayerDescription(identifier, source, sourceId, minZoom, maxZoom, filter, renderPassIndex, interactable, false, selfMasked), style(style) {}; std::unique_ptr clone() override { return std::make_unique(identifier, source, sourceLayer, minZoom, maxZoom, filter ? filter->clone() : nullptr, style, renderPassIndex, - interactable ? interactable : nullptr); + interactable ? interactable : nullptr, selfMasked); } virtual UsedKeysCollection getUsedKeys() const override { diff --git a/shared/public/Tiled2dMapVectorLayer.h b/shared/public/Tiled2dMapVectorLayer.h index 4da145b47..312dec2d5 100644 --- a/shared/public/Tiled2dMapVectorLayer.h +++ b/shared/public/Tiled2dMapVectorLayer.h @@ -105,6 +105,7 @@ class Tiled2dMapVectorLayer std::vector> renderObjects; std::shared_ptr maskingObject; bool isModifyingMask; + bool selfMasked; int32_t renderPassIndex; }; diff --git a/shared/public/VectorLayerDescription.h b/shared/public/VectorLayerDescription.h index e683b5ab4..30ebe58ce 100644 --- a/shared/public/VectorLayerDescription.h +++ b/shared/public/VectorLayerDescription.h @@ -27,6 +27,7 @@ class VectorLayerDescription { std::shared_ptr filter; std::optional renderPassIndex; bool multiselect; + bool selfMasked; virtual VectorLayerType getType() = 0; @@ -60,7 +61,8 @@ class VectorLayerDescription { std::shared_ptr filter, std::optional renderPassIndex, std::shared_ptr interactable, - bool multiselect): + bool multiselect, + bool selfMasked): identifier(identifier), source(source), sourceLayer(sourceId), @@ -69,7 +71,8 @@ class VectorLayerDescription { filter(filter), renderPassIndex(renderPassIndex), interactable(interactable), - multiselect(multiselect) {} + multiselect(multiselect), + selfMasked(selfMasked) {} virtual ~VectorLayerDescription() = default; diff --git a/shared/src/map/layers/icon/IconLayer.cpp b/shared/src/map/layers/icon/IconLayer.cpp index 0601d3e5a..390a8fbba 100644 --- a/shared/src/map/layers/icon/IconLayer.cpp +++ b/shared/src/map/layers/icon/IconLayer.cpp @@ -339,7 +339,7 @@ std::vector> IconLayer::buildRenderPasses std::vector> renderPasses; for (const auto &passEntry : currentRenderPassObjectMap) { std::shared_ptr renderPass = - std::make_shared(RenderPassConfig(passEntry.first), passEntry.second, mask); + std::make_shared(RenderPassConfig(passEntry.first, false), passEntry.second, mask); renderPasses.push_back(renderPass); } return renderPasses; diff --git a/shared/src/map/layers/line/LineLayer.cpp b/shared/src/map/layers/line/LineLayer.cpp index fcc45ac15..9d4a5f274 100644 --- a/shared/src/map/layers/line/LineLayer.cpp +++ b/shared/src/map/layers/line/LineLayer.cpp @@ -185,7 +185,7 @@ void LineLayer::generateRenderPasses() { std::vector> newRenderPasses; for (const auto &passEntry : renderPassObjectMap) { std::shared_ptr renderPass = - std::make_shared(RenderPassConfig(passEntry.first), passEntry.second, mask); + std::make_shared(RenderPassConfig(passEntry.first, false), passEntry.second, mask); newRenderPasses.push_back(renderPass); } { diff --git a/shared/src/map/layers/polygon/PolygonLayer.cpp b/shared/src/map/layers/polygon/PolygonLayer.cpp index 9e1b6c442..5e91a7514 100644 --- a/shared/src/map/layers/polygon/PolygonLayer.cpp +++ b/shared/src/map/layers/polygon/PolygonLayer.cpp @@ -250,7 +250,7 @@ void PolygonLayer::generateRenderPasses() { std::vector> newRenderPasses; for (const auto &passEntry : renderPassObjectMap) { std::shared_ptr renderPass = - std::make_shared(RenderPassConfig(passEntry.first), passEntry.second, mask); + std::make_shared(RenderPassConfig(passEntry.first, false), passEntry.second, mask); newRenderPasses.push_back(renderPass); } { diff --git a/shared/src/map/layers/text/TextLayer.cpp b/shared/src/map/layers/text/TextLayer.cpp index b1a377a51..391d81f05 100644 --- a/shared/src/map/layers/text/TextLayer.cpp +++ b/shared/src/map/layers/text/TextLayer.cpp @@ -190,7 +190,7 @@ void TextLayer::generateRenderPasses() { std::vector> newRenderPasses; for (const auto &passEntry : renderPassObjectMap) { - std::shared_ptr renderPass = std::make_shared(RenderPassConfig(passEntry.first), passEntry.second); + std::shared_ptr renderPass = std::make_shared(RenderPassConfig(passEntry.first, false), passEntry.second); newRenderPasses.push_back(renderPass); } diff --git a/shared/src/map/layers/tiled/raster/Tiled2dMapRasterLayer.cpp b/shared/src/map/layers/tiled/raster/Tiled2dMapRasterLayer.cpp index e9ed32ff4..b5382a7d1 100644 --- a/shared/src/map/layers/tiled/raster/Tiled2dMapRasterLayer.cpp +++ b/shared/src/map/layers/tiled/raster/Tiled2dMapRasterLayer.cpp @@ -416,19 +416,19 @@ void Tiled2dMapRasterLayer::generateRenderPasses() { mask.getGraphicsObject()->setup(renderingContext); std::shared_ptr renderPass = - std::make_shared(RenderPassConfig(0), + std::make_shared(RenderPassConfig(0, false), std::vector>{renderObject}, mask.getGraphicsMaskObject()); renderPass->setScissoringRect(scissorRect); newRenderPasses.push_back(renderPass); } else if (mask) { //TODO: general mask would no longer work now, we would have to merge the tile-mask with the layer-mask std::shared_ptr renderPass = - std::make_shared(RenderPassConfig(0), + std::make_shared(RenderPassConfig(0, false), std::vector>{renderObject}, mask); renderPass->setScissoringRect(scissorRect); newRenderPasses.push_back(renderPass); } else { - std::shared_ptr renderPass = std::make_shared(RenderPassConfig(0), + std::shared_ptr renderPass = std::make_shared(RenderPassConfig(0, false), std::vector>{ renderObject}); renderPass->setScissoringRect(scissorRect); diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index 8e5dbb3f6..617f796aa 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -618,18 +618,18 @@ void Tiled2dMapVectorLayer::pregenerateRenderPasses() { continue; } if (description->maskingObject != lastMask && !renderObjects.empty()) { - newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex), renderObjects, lastMask)); + newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex, false), renderObjects, lastMask)); renderObjects.clear(); lastMask = nullptr; } - if (description->isModifyingMask) { + if (description->isModifyingMask || description->selfMasked) { if (!renderObjects.empty()) { - newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex), renderObjects, lastMask)); + newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex, false), renderObjects, lastMask)); } renderObjects.clear(); lastMask = nullptr; - newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex), description->renderObjects, description->maskingObject)); + newPasses.emplace_back(std::make_shared(RenderPassConfig(description->renderPassIndex, description->selfMasked), description->renderObjects, description->maskingObject)); } else { renderObjects.insert(renderObjects.end(), description->renderObjects.begin(), description->renderObjects.end()); lastMask = description->maskingObject; @@ -637,7 +637,7 @@ void Tiled2dMapVectorLayer::pregenerateRenderPasses() { } } if (!renderObjects.empty()) { - newPasses.emplace_back(std::make_shared(RenderPassConfig(lastRenderPassIndex), renderObjects, lastMask)); + newPasses.emplace_back(std::make_shared(RenderPassConfig(lastRenderPassIndex, false), renderObjects, lastMask)); renderObjects.clear(); lastMask = nullptr; } diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp index 099a4da51..18b412e5c 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp @@ -224,6 +224,7 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ std::optional renderPassIndex; std::shared_ptr interactable = globalIsInteractable; bool layerMultiselect = false; + bool layerSelfMasked = false; std::shared_ptr blendMode; if (val["metadata"].is_object()) { @@ -236,6 +237,9 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ if (!val["metadata"]["multiselect"].is_null()) { layerMultiselect = val["metadata"].value("multiselect", false); } + if (!val["metadata"]["selfMasked"].is_null()) { + layerSelfMasked = val["metadata"].value("selfMasked", false); + } if (!val["metadata"]["blend-mode"].is_null()) { blendMode = parser.parseValue(val["metadata"]["blend-mode"]); } @@ -306,7 +310,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ style, renderPassIndex, interactable, - layerMultiselect); + layerMultiselect, + layerSelfMasked); layers.push_back(layerDesc); @@ -365,7 +370,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ filter, style, renderPassIndex, - interactable); // in-layer layerMultiselect not yet supported + interactable, + layerSelfMasked); // in-layer layerMultiselect not yet supported layers.push_back(layerDesc); } else if (val["type"] == "fill") { @@ -385,7 +391,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ style, renderPassIndex, interactable, - layerMultiselect); + layerMultiselect, + layerSelfMasked); layers.push_back(layerDesc); } diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.cpp b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.cpp index 33aa362dd..c45dfa05a 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.cpp +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.cpp @@ -34,6 +34,9 @@ Tiled2dMapVectorSourceDataManager::Tiled2dMapVectorSourceDataManager(const WeakA if (layerDescription->getType() == VectorLayerType::line) { modifyingMaskLayers.insert(index); } + if (layerDescription->selfMasked) { + selfMaskedLayers.insert(index); + } } } diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h index 2deb6f5b7..b7a064bc0 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h @@ -84,6 +84,7 @@ class Tiled2dMapVectorSourceDataManager : public ActorObject { std::unordered_map layerNameIndexMap; std::unordered_set modifyingMaskLayers; + std::unordered_set selfMaskedLayers; std::optional<::RectI> scissorRect = std::nullopt; diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp index 0144a8a7a..26c37e7f8 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp @@ -67,9 +67,10 @@ void Tiled2dMapVectorSourceTileDataManager::pregenerateRenderPasses() { assert(mask->asGraphicsObject()->isReady()); for (const auto &[layerIndex, renderObjects]: subTiles) { const bool modifiesMask = modifyingMaskLayers.find(layerIndex) != modifyingMaskLayers.end(); + const bool selfMasked = selfMaskedLayers.find(layerIndex) != selfMaskedLayers.end(); const auto optRenderPassIndex = mapDescription->layers[layerIndex]->renderPassIndex; const int32_t renderPassIndex = optRenderPassIndex ? *optRenderPassIndex : 0; - renderDescriptions.push_back(std::make_shared(Tiled2dMapVectorLayer::TileRenderDescription{layerIndex, renderObjects, mask, modifiesMask, renderPassIndex})); + renderDescriptions.push_back(std::make_shared(Tiled2dMapVectorLayer::TileRenderDescription{layerIndex, renderObjects, mask, modifiesMask, selfMasked, renderPassIndex})); } } vectorLayer.syncAccess([source = this->source, &renderDescriptions](const auto &layer){ diff --git a/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp b/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp index 267883bff..a28e560d0 100644 --- a/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp +++ b/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp @@ -76,7 +76,7 @@ void Tiled2dMapVectorBackgroundSubLayer::onAdded(const std::shared_ptr(patternObject->getPolygonObject(), true)); } - auto renderPass = std::make_shared(RenderPassConfig(0), renderObjects ); + auto renderPass = std::make_shared(RenderPassConfig(0, false), renderObjects ); renderPasses = { renderPass }; diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp index b3ab657a6..363272ab7 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp @@ -721,6 +721,7 @@ void Tiled2dMapVectorSourceSymbolDataManager::pregenerateRenderPasses() { } for (const auto &[layerIdentifier, symbolGroups]: symbolGroupsMap) { const int32_t index = layerNameIndexMap.at(layerIdentifier); + bool selfMasked = selfMaskedLayers.find(index) != selfMaskedLayers.end(); std::vector> renderObjects; for (const auto &group: std::get<1>(symbolGroups)) { @@ -732,7 +733,7 @@ void Tiled2dMapVectorSourceSymbolDataManager::pregenerateRenderPasses() { const auto optRenderPassIndex = mapDescription->layers[index]->renderPassIndex; const int32_t renderPassIndex = optRenderPassIndex ? *optRenderPassIndex : 0; - renderDescriptions.push_back(std::make_shared(Tiled2dMapVectorLayer::TileRenderDescription{index, renderObjects, nullptr, false, renderPassIndex})); + renderDescriptions.push_back(std::make_shared(Tiled2dMapVectorLayer::TileRenderDescription{index, renderObjects, nullptr, false, selfMasked, renderPassIndex})); } } From ae51246ce381efc5bda9fe9012ab1fc623f58f28 Mon Sep 17 00:00:00 2001 From: Christoph Maurhofer Date: Wed, 24 Jan 2024 18:26:42 +0100 Subject: [PATCH 2/3] Keep order of polygon/line geometries in vector layers, don't override maxZoom in geoJson decoding --- .../vector/geojson/geojsonvt/geojsonvt.hpp | 4 --- .../tiles/line/Tiled2dMapVectorLineTile.cpp | 31 +++++++++------- .../tiles/line/Tiled2dMapVectorLineTile.h | 2 +- .../Tiled2dMapVectorPolygonPatternTile.cpp | 35 ++++++++++--------- .../Tiled2dMapVectorPolygonPatternTile.h | 3 +- .../polygon/Tiled2dMapVectorPolygonTile.cpp | 24 ++++++------- .../polygon/Tiled2dMapVectorPolygonTile.h | 2 +- 7 files changed, 53 insertions(+), 48 deletions(-) diff --git a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp index 87db2bf65..86d7feca2 100644 --- a/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp +++ b/shared/src/map/layers/tiled/vector/geojson/geojsonvt/geojsonvt.hpp @@ -118,8 +118,6 @@ class GeoJSONVT: public GeoJSONVTInterface, public std::enable_shared_from_this< // as there are no opportunities for simplification, merging, or meaningful point reduction. if (geoJson->hasOnlyPoints) { self->options.maxZoom = self->options.minZoom; - } else { - self->options.maxZoom = 18; } const uint32_t z2 = 1u << self->options.maxZoom; @@ -175,8 +173,6 @@ class GeoJSONVT: public GeoJSONVTInterface, public std::enable_shared_from_this< // as there are no opportunities for simplification, merging, or meaningful point reduction. if (geoJson->hasOnlyPoints) { options.maxZoom = options.minZoom; - } else { - options.maxZoom = 18; } const uint32_t z2 = 1u << options.maxZoom; diff --git a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp index 106c92cfb..380eed5a2 100644 --- a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp @@ -229,8 +229,8 @@ void Tiled2dMapVectorLineTile::setVectorTileData(const Tiled2dMapVectorTileDataV if (!tileData->empty()) { std::unordered_map subGroupCoordCount; - std::unordered_map, int>>>> styleGroupNewLinesMap; - std::unordered_map, int>>> styleGroupLineSubGroupMap; + std::vector, int>>>> styleGroupNewLinesVector; + std::vector, int>>> styleGroupLineSubGroupVector; bool anyInteractable = false; @@ -267,6 +267,8 @@ void Tiled2dMapVectorLineTile::setVectorTileData(const Tiled2dMapVectorTileDataV shader->asShaderProgramInterface()->setBlendMode(lineDescription->style.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); shaders.push_back(shader); reusableLineStyles.push_back({ reusableStyle }); + styleGroupLineSubGroupVector.push_back(std::vector, int>>()); + styleGroupNewLinesVector.push_back({}); featureGroups.push_back(std::vector>>{{hash, featureContext}}); } styleHashToGroupMap.insert({hash, {styleGroupIndex, styleIndex}}); @@ -286,13 +288,13 @@ void Tiled2dMapVectorLineTile::setVectorTileData(const Tiled2dMapVectorTileDataV int numCoords = (int)lineCoordinates.size(); int coordCount = subGroupCoordCount[styleGroupIndex]; if (coordCount + numCoords > maxNumLinePoints - && !styleGroupLineSubGroupMap[styleGroupIndex].empty()) { - styleGroupNewLinesMap[styleGroupIndex].push_back(styleGroupLineSubGroupMap[styleGroupIndex]); - styleGroupLineSubGroupMap[styleGroupIndex] = std::vector, int>>(); + && !styleGroupLineSubGroupVector[styleGroupIndex].empty()) { + styleGroupNewLinesVector[styleGroupIndex].push_back(styleGroupLineSubGroupVector[styleGroupIndex]); + styleGroupLineSubGroupVector.push_back(std::vector, int>>()); subGroupCoordCount[styleGroupIndex] = 0; } - styleGroupLineSubGroupMap[styleGroupIndex].push_back({lineCoordinates, std::min(maxStylesPerGroup - 1, styleIndex)}); + styleGroupLineSubGroupVector[styleGroupIndex].push_back({lineCoordinates, std::min(maxStylesPerGroup - 1, styleIndex)}); subGroupCoordCount[styleGroupIndex] = (int)subGroupCoordCount[styleGroupIndex] + numCoords; lineCoordinatesVector.push_back(lineCoordinates); } @@ -304,15 +306,18 @@ void Tiled2dMapVectorLineTile::setVectorTileData(const Tiled2dMapVectorTileDataV } } - for (const auto &[groupIndex, lineSubGroup] : styleGroupLineSubGroupMap) { - if (!lineSubGroup.empty() && subGroupCoordCount[groupIndex] > 0) styleGroupNewLinesMap[groupIndex].push_back(lineSubGroup); + for (int styleGroupIndex = 0; styleGroupIndex < styleGroupLineSubGroupVector.size(); styleGroupIndex++) { + const auto &lineSubGroup = styleGroupLineSubGroupVector[styleGroupIndex]; + if (!lineSubGroup.empty() && subGroupCoordCount[styleGroupIndex] > 0) { + styleGroupNewLinesVector[styleGroupIndex].push_back(lineSubGroup); + } } if (anyInteractable) { tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsInteractable, description->identifier); } - addLines(styleGroupNewLinesMap); + addLines(styleGroupNewLinesVector); } else { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); @@ -320,8 +325,8 @@ void Tiled2dMapVectorLineTile::setVectorTileData(const Tiled2dMapVectorTileDataV } -void Tiled2dMapVectorLineTile::addLines(const std::unordered_map, int>>>> &styleIdLinesMap) { - if (styleIdLinesMap.empty()) { +void Tiled2dMapVectorLineTile::addLines(const std::vector, int>>>> &styleIdLinesVector) { + if (styleIdLinesVector.empty()) { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); return; @@ -337,8 +342,8 @@ void Tiled2dMapVectorLineTile::addLines(const std::unordered_map> lineGroupObjects; std::vector> newGraphicObjects; - for (const auto &[styleGroupIndex, styleLines]: styleIdLinesMap) { - for (const auto &lineSubGroup: styleLines) { + for (int styleGroupIndex = 0; styleGroupIndex < styleIdLinesVector.size(); styleGroupIndex++) { + for (const auto &lineSubGroup: styleIdLinesVector[styleGroupIndex]) { const auto &shader = shaders.at(styleGroupIndex); auto lineGroupGraphicsObject = objectFactory->createLineGroup(shader->asShaderProgramInterface()); diff --git a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h index 16a4e8872..17f650d23 100644 --- a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h @@ -43,7 +43,7 @@ class Tiled2dMapVectorLineTile bool onClickConfirmed(const Vec2F &posScreen) override; private: - void addLines(const std::unordered_map, int>>>> &styleIdLinesMap); + void addLines(const std::vector, int>>>> &styleIdLinesVector); void setupLines(const std::vector> &newLineGraphicsObjects); diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp index 9d32cd4d6..728267b29 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp @@ -58,6 +58,7 @@ void Tiled2dMapVectorPolygonPatternTile::updateVectorLayerDescription(const std: toClear.insert(toClear.begin(), polygons.second.begin(), polygons.second.end()); } styleGroupPolygonsMap.clear(); + polygonRenderOrder.clear(); shaders.clear(); setVectorTileData(tileData); } @@ -165,7 +166,7 @@ void Tiled2dMapVectorPolygonPatternTile::setVectorTileData(const Tiled2dMapVecto bool anyInteractable = false; - std::unordered_map> styleGroupNewPolygonsMap; + std::vector> styleGroupNewPolygonsVector; std::unordered_map styleIndicesOffsets; std::int32_t indices_offset = 0; @@ -206,7 +207,7 @@ void Tiled2dMapVectorPolygonPatternTile::setVectorTileData(const Tiled2dMapVecto shader->asShaderProgramInterface()->setBlendMode(polygonDescription->style.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); shaders.push_back(shader); featureGroups.push_back(std::vector>>{{hash, featureContext}}); - styleGroupNewPolygonsMap[styleGroupIndex].push_back({{},{}}); + styleGroupNewPolygonsVector.push_back({{{}, {}}}); styleIndicesOffsets[styleGroupIndex] = 0; } styleHashToGroupMap.insert({hash, {styleGroupIndex, styleIndex}}); @@ -230,19 +231,19 @@ void Tiled2dMapVectorPolygonPatternTile::setVectorTileData(const Tiled2dMapVecto int32_t indexOffset = styleIndicesOffsets.at(styleGroupIndex); size_t new_size = indexOffset + verticesCount; if (new_size >= indicesLimit) { - styleGroupNewPolygonsMap[styleGroupIndex].push_back({{},{}}); + styleGroupNewPolygonsVector[styleGroupIndex].push_back({{}, {}}); styleIndicesOffsets[styleGroupIndex] = 0; indexOffset = 0; } for (auto const &index: polygon.indices) { - styleGroupNewPolygonsMap.at(styleGroupIndex).back().indices.push_back(indexOffset + index); + styleGroupNewPolygonsVector[styleGroupIndex].back().indices.push_back(indexOffset + index); } for (auto const &coordinate: polygon.coordinates) { - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(coordinate.x); - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(coordinate.y); - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(styleIndex); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(coordinate.x); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(coordinate.y); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(styleIndex); } styleIndicesOffsets.at(styleGroupIndex) += verticesCount; @@ -260,16 +261,16 @@ void Tiled2dMapVectorPolygonPatternTile::setVectorTileData(const Tiled2dMapVecto tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsInteractable, description->identifier); } - addPolygons(styleGroupNewPolygonsMap); + addPolygons(styleGroupNewPolygonsVector); } else { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); } } -void Tiled2dMapVectorPolygonPatternTile::addPolygons(const std::unordered_map> &styleGroupNewPolygonsMap) { +void Tiled2dMapVectorPolygonPatternTile::addPolygons(const std::vector> &styleGroupNewPolygonsVector) { - if (styleGroupNewPolygonsMap.empty()) { + if (styleGroupNewPolygonsVector.empty()) { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); return; @@ -284,9 +285,11 @@ void Tiled2dMapVectorPolygonPatternTile::addPolygons(const std::unordered_map>> polygonGroupObjectsMap; + std::vector> polygonsRenderOrder; std::vector> newGraphicObjects; - for (auto const &[styleGroupIndex, polygonDescs]: styleGroupNewPolygonsMap) { + for (int styleGroupIndex = 0; styleGroupIndex < styleGroupNewPolygonsVector.size(); styleGroupIndex++) { + const auto polygonDescs = styleGroupNewPolygonsVector[styleGroupIndex]; const auto &shader = shaders.at(styleGroupIndex); for (const auto &polygonDesc: polygonDescs) { const auto polygonObject = objectFactory->createPolygonPatternGroup(shader->asShaderProgramInterface()); @@ -298,11 +301,13 @@ void Tiled2dMapVectorPolygonPatternTile::addPolygons(const std::unordered_mapsetVertices(polygonDesc.vertices, polygonDesc.indices); polygonGroupObjectsMap[styleGroupIndex].push_back(layerObject); + polygonsRenderOrder.push_back(layerObject); newGraphicObjects.push_back(polygonObject->asGraphicsObject()); } } styleGroupPolygonsMap = polygonGroupObjectsMap; + polygonRenderOrder = polygonsRenderOrder; #ifdef __APPLE__ setupPolygons(newGraphicObjects); @@ -331,11 +336,9 @@ void Tiled2dMapVectorPolygonPatternTile::setupPolygons(const std::vector> Tiled2dMapVectorPolygonPatternTile::generateRenderObjects() { std::vector> newRenderObjects; - for (const auto &[styleGroupId, polygons] : styleGroupPolygonsMap) { - for (const auto &polygon : polygons) { - for (const auto &config: polygon->getRenderConfig()) { - newRenderObjects.push_back(std::make_shared(config->getGraphicsObject())); - } + for (const auto &polygon: polygonRenderOrder) { + for (const auto &config: polygon->getRenderConfig()) { + newRenderObjects.push_back(std::make_shared(config->getGraphicsObject())); } } diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h index cdf62573b..7e947dec6 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h @@ -53,7 +53,7 @@ class Tiled2dMapVectorPolygonPatternTile std::vector indices; }; - void addPolygons(const std::unordered_map> &styleGroupNewPolygonsMap); + void addPolygons(const std::vector> &styleGroupNewPolygonsVector); void setupPolygons(const std::vector> &newPolygonObjects); @@ -67,6 +67,7 @@ class Tiled2dMapVectorPolygonPatternTile std::vector> shaders; std::unordered_map>> styleGroupPolygonsMap; + std::vector> polygonRenderOrder; std::vector>>> featureGroups; std::unordered_map> styleHashToGroupMap; UsedKeysCollection usedKeys; diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp index ddb73e25f..c29f131f3 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp @@ -148,7 +148,7 @@ void Tiled2dMapVectorPolygonTile::setVectorTileData(const Tiled2dMapVectorTileDa bool anyInteractable = false; - std::unordered_map> styleGroupNewPolygonsMap; + std::vector> styleGroupNewPolygonsVector; std::unordered_map styleIndicesOffsets; for (auto featureIt = tileData->begin(); featureIt != tileData->end(); featureIt++) { @@ -185,7 +185,7 @@ void Tiled2dMapVectorPolygonTile::setVectorTileData(const Tiled2dMapVectorTileDa shader->asShaderProgramInterface()->setBlendMode(polygonDescription->style.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); shaders.push_back(shader); featureGroups.push_back(std::vector>>{{hash, featureContext}}); - styleGroupNewPolygonsMap[styleGroupIndex].push_back({{},{}}); + styleGroupNewPolygonsVector.push_back({{{}, {}}}); styleIndicesOffsets[styleGroupIndex] = 0; } styleHashToGroupMap.insert({hash, {styleGroupIndex, styleIndex}}); @@ -208,19 +208,19 @@ void Tiled2dMapVectorPolygonTile::setVectorTileData(const Tiled2dMapVectorTileDa int32_t indexOffset = styleIndicesOffsets.at(styleGroupIndex); size_t new_size = indexOffset + verticesCount; if (new_size >= indicesLimit) { - styleGroupNewPolygonsMap[styleGroupIndex].push_back({{},{}}); + styleGroupNewPolygonsVector[styleGroupIndex].push_back({{}, {}}); styleIndicesOffsets[styleGroupIndex] = 0; indexOffset = 0; } for (auto const &index: polygon.indices) { - styleGroupNewPolygonsMap.at(styleGroupIndex).back().indices.push_back(indexOffset + index); + styleGroupNewPolygonsVector[styleGroupIndex].back().indices.push_back(indexOffset + index); } for (auto const &coordinate: polygon.coordinates) { - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(coordinate.x); - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(coordinate.y); - styleGroupNewPolygonsMap.at(styleGroupIndex).back().vertices.push_back(styleIndex); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(coordinate.x); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(coordinate.y); + styleGroupNewPolygonsVector[styleGroupIndex].back().vertices.push_back(styleIndex); } styleIndicesOffsets.at(styleGroupIndex) += verticesCount; @@ -238,16 +238,16 @@ void Tiled2dMapVectorPolygonTile::setVectorTileData(const Tiled2dMapVectorTileDa tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsInteractable, description->identifier); } - addPolygons(styleGroupNewPolygonsMap); + addPolygons(styleGroupNewPolygonsVector); } else { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); } } -void Tiled2dMapVectorPolygonTile::addPolygons(const std::unordered_map> &styleGroupNewPolygonsMap) { +void Tiled2dMapVectorPolygonTile::addPolygons(const std::vector> &styleGroupNewPolygonsVector) { - if (styleGroupNewPolygonsMap.empty()) { + if (styleGroupNewPolygonsVector.empty()) { auto selfActor = WeakActor(mailbox, shared_from_this()); tileCallbackInterface.message(&Tiled2dMapVectorLayerTileCallbackInterface::tileIsReady, tileInfo, description->identifier, selfActor); return; @@ -264,9 +264,9 @@ void Tiled2dMapVectorPolygonTile::addPolygons(const std::unordered_map> polygonGroupObjects; std::vector> newGraphicObjects; - for (auto const &[styleGroupIndex, polygonDescs]: styleGroupNewPolygonsMap) { + for (int styleGroupIndex = 0; styleGroupIndex < styleGroupNewPolygonsVector.size(); styleGroupIndex++) { const auto &shader = shaders.at(styleGroupIndex); - for (const auto &polygonDesc: polygonDescs) { + for (const auto &polygonDesc: styleGroupNewPolygonsVector[styleGroupIndex]) { const auto polygonObject = objectFactory->createPolygonGroup(shader->asShaderProgramInterface()); #if DEBUG polygonObject->asGraphicsObject()->setDebugLabel(description->identifier); diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h index c0c5c4515..a1604063b 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h @@ -49,7 +49,7 @@ class Tiled2dMapVectorPolygonTile std::vector indices; }; - void addPolygons(const std::unordered_map> &styleGroupNewPolygonsMap); + void addPolygons(const std::vector> &styleGroupNewPolygonsVector); void setupPolygons(const std::vector> &newPolygonObjects); From 0d4377879afc010c8775aefb019cae58b40006e5 Mon Sep 17 00:00:00 2001 From: Marco Zimmermann Date: Thu, 1 Feb 2024 09:21:31 +0100 Subject: [PATCH 3/3] adds iOS part --- ios/graphics/Model/BaseGraphicsObject.swift | 34 +++++++++++++++++++ .../Model/Polygon/PolygonGroup2d.swift | 31 +++++++---------- ios/graphics/RenderingContext.swift | 2 +- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/ios/graphics/Model/BaseGraphicsObject.swift b/ios/graphics/Model/BaseGraphicsObject.swift index b25d9c78e..7830a94d2 100644 --- a/ios/graphics/Model/BaseGraphicsObject.swift +++ b/ios/graphics/Model/BaseGraphicsObject.swift @@ -78,4 +78,38 @@ extension BaseGraphicsObject: MCGraphicsObjectInterface { isMasked: isMasked, screenPixelAsRealMeterFactor: screenPixelAsRealMeterFactor) } + + // MARK: - Stencil + + func maskStencilState(readMask: UInt32 = 0b1111_1111, writeMask: UInt32 = 0b0000_0000) -> MTLDepthStencilState? { + let s = MTLStencilDescriptor() + s.stencilCompareFunction = .equal + s.stencilFailureOperation = .zero + s.depthFailureOperation = .keep + s.depthStencilPassOperation = .keep + s.readMask = readMask + s.writeMask = writeMask + + let desc = MTLDepthStencilDescriptor() + desc.frontFaceStencil = s + desc.backFaceStencil = s + + return device.makeDepthStencilState(descriptor: desc) + } + + func renderPassMaskStencilState() -> MTLDepthStencilState? { + let s = MTLStencilDescriptor() + s.stencilCompareFunction = .equal + s.stencilFailureOperation = .keep + s.depthFailureOperation = .keep + s.depthStencilPassOperation = .incrementWrap + s.readMask = 0b1111_1111 + s.writeMask = 0b0000_0001 + + let desc = MTLDepthStencilDescriptor() + desc.frontFaceStencil = s + desc.backFaceStencil = s + + return device.makeDepthStencilState(descriptor: desc) + } } diff --git a/ios/graphics/Model/Polygon/PolygonGroup2d.swift b/ios/graphics/Model/Polygon/PolygonGroup2d.swift index 3c0cf8287..77de10b37 100644 --- a/ios/graphics/Model/Polygon/PolygonGroup2d.swift +++ b/ios/graphics/Model/Polygon/PolygonGroup2d.swift @@ -20,6 +20,8 @@ final class PolygonGroup2d: BaseGraphicsObject { private var indicesCount: Int = 0 private var stencilState: MTLDepthStencilState? + private var renderPassStencilState: MTLDepthStencilState? + init(shader: MCShaderProgramInterface, metalContext: MetalContext) { guard let shader = shader as? PolygonGroupShader else { @@ -31,25 +33,9 @@ final class PolygonGroup2d: BaseGraphicsObject { label: "PolygonGroup2d") } - private func setupStencilStates() { - let ss2 = MTLStencilDescriptor() - ss2.stencilCompareFunction = .equal - ss2.stencilFailureOperation = .zero - ss2.depthFailureOperation = .keep - ss2.depthStencilPassOperation = .keep - ss2.readMask = 0b1111_1111 - ss2.writeMask = 0b0000_0000 - - let s2 = MTLDepthStencilDescriptor() - s2.frontFaceStencil = ss2 - s2.backFaceStencil = ss2 - - stencilState = device.makeDepthStencilState(descriptor: s2) - } - override func render(encoder: MTLRenderCommandEncoder, context: RenderingContext, - renderPass _: MCRenderPassConfig, + renderPass pass: MCRenderPassConfig, mvpMatrix: Int64, isMasked: Bool, screenPixelAsRealMeterFactor _: Double) { @@ -70,12 +56,21 @@ final class PolygonGroup2d: BaseGraphicsObject { if isMasked { if stencilState == nil { - setupStencilStates() + stencilState = self.maskStencilState() } encoder.setDepthStencilState(stencilState) encoder.setStencilReferenceValue(0b1100_0000) } + if pass.isPassMasked { + if renderPassStencilState == nil { + renderPassStencilState = self.renderPassMaskStencilState() + } + + encoder.setDepthStencilState(renderPassStencilState) + encoder.setStencilReferenceValue(0b1100_0000) + } + shader.setupProgram(context) shader.preRender(context) diff --git a/ios/graphics/RenderingContext.swift b/ios/graphics/RenderingContext.swift index ea6bdd4c6..76c494454 100644 --- a/ios/graphics/RenderingContext.swift +++ b/ios/graphics/RenderingContext.swift @@ -85,7 +85,7 @@ public class RenderingContext: NSObject { guard let encoder else { return } stencilClearQuad.render(encoder: encoder, context: self, - renderPass: .init(renderPass: 0), + renderPass: .init(renderPass: 0, isPassMasked: false), mvpMatrix: 0, isMasked: false, screenPixelAsRealMeterFactor: 1)