From 4603ca037cab2d0f732285ce9e006744ad3118d6 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 26 Aug 2014 15:24:16 -0700 Subject: background-image support --- src/map/transform_state.cpp | 30 ++++++++++++++++++-- src/renderer/painter.cpp | 67 +++++++++++++++++++++++++++++++++++++-------- src/style/style_layer.cpp | 1 + src/style/style_parser.cpp | 1 + src/util/mat3.cpp | 46 ++++++++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/map/transform_state.cpp b/src/map/transform_state.cpp index d103897375..4b1bc4161e 100644 --- a/src/map/transform_state.cpp +++ b/src/map/transform_state.cpp @@ -83,11 +83,31 @@ const std::array TransformState::getFramebufferDimensions() const { return framebuffer; } - float TransformState::getPixelRatio() const { return pixelRatio; } +float TransformState::worldSize() const { + return scale * util::tileSize; +} + +float TransformState::lngX(float lon) const { + return (180 + lon) * worldSize() / 360; +} + +float TransformState::latY(float lat) const { + float y = 180 / M_PI * std::log(std::tan(M_PI / 4 + lat * M_PI / 360)); + return (180 - y) * worldSize() / 360; +} + +std::array TransformState::locationCoordinate(float lon, float lat) const { + float k = std::pow(2, getIntegerZoom()) / worldSize(); + return {{ + lngX(lon) * k, + latY(lat) * k + }}; +} + #pragma mark - Zoom @@ -95,12 +115,16 @@ float TransformState::getNormalizedZoom() const { return std::log(scale * util::tileSize / 512.0f) / M_LN2; } +double TransformState::getZoom() const { + return std::log(scale) / M_LN2; +} + int32_t TransformState::getIntegerZoom() const { return std::floor(getZoom()); } -double TransformState::getZoom() const { - return std::log(scale) / M_LN2; +double TransformState::getZoomFraction() const { + return getZoom() - getIntegerZoom(); } double TransformState::getScale() const { diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 9643fb1561..474b7b954f 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -7,6 +7,9 @@ #include #include #include +#include +#include + #if defined(DEBUG) #include #endif @@ -188,24 +191,66 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr layer_desc void Painter::renderBackground(util::ptr layer_desc) { const BackgroundProperties& properties = layer_desc->getProperties(); + const std::shared_ptr sprite = map.getSprite(); + + if (properties.image.size() && sprite) { + if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque)) + return; + + SpriteAtlas &spriteAtlas = *map.getSpriteAtlas(); + SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, *sprite, true); + float zoomFraction = map.getState().getZoomFraction(); + + useProgram(patternShader->program); + patternShader->u_matrix = identityMatrix; + patternShader->u_pattern_tl = imagePos.tl; + patternShader->u_pattern_br = imagePos.br; + patternShader->u_mix = zoomFraction; + patternShader->u_opacity = properties.opacity; + + std::array size = imagePos.size; + double lon, lat; + map.getLonLat(lon, lat); + std::array center = map.getState().locationCoordinate(lon, lat); + float scale = 1 / std::pow(2, zoomFraction); + + mat3 matrix; + matrix::identity(matrix); + matrix::scale(matrix, matrix, + 1.0f / size[0], + 1.0f / size[1]); + matrix::translate(matrix, matrix, + std::fmod(center[0] * 512, size[0]), + std::fmod(center[1] * 512, size[1])); + matrix::rotate(matrix, matrix, -map.getState().getAngle()); + matrix::scale(matrix, matrix, + scale * map.getState().getWidth() / 2, + -scale * map.getState().getHeight() / 2); + patternShader->u_patternmatrix = matrix; + + backgroundBuffer.bind(); + patternShader->bind(0); + spriteAtlas.bind(true); + } else { + Color color = properties.color; + color[0] *= properties.opacity; + color[1] *= properties.opacity; + color[2] *= properties.opacity; + color[3] *= properties.opacity; - Color color = properties.color; - color[0] *= properties.opacity; - color[1] *= properties.opacity; - color[2] *= properties.opacity; - color[3] *= properties.opacity; + if ((color[3] >= 1.0f) != (pass == RenderPass::Opaque)) + return; - if ((color[3] >= 1.0f) == (pass == RenderPass::Opaque)) { useProgram(plainShader->program); plainShader->u_matrix = identityMatrix; plainShader->u_color = color; backgroundArray.bind(*plainShader, backgroundBuffer, BUFFER_OFFSET(0)); - - glDisable(GL_STENCIL_TEST); - depthRange(strata + strata_epsilon, 1.0f); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glEnable(GL_STENCIL_TEST); } + + glDisable(GL_STENCIL_TEST); + depthRange(strata + strata_epsilon, 1.0f); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glEnable(GL_STENCIL_TEST); } mat4 Painter::translatedMatrix(const mat4& matrix, const std::array &translation, const Tile::ID &id, TranslateAnchorType anchor) { diff --git a/src/style/style_layer.cpp b/src/style/style_layer.cpp index 4f758fe723..d78750195b 100644 --- a/src/style/style_layer.cpp +++ b/src/style/style_layer.cpp @@ -235,6 +235,7 @@ void StyleLayer::applyStyleProperties(const float z, const BackgroundProperties &background = properties.get(); applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now); applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now); + applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now); } void StyleLayer::updateProperties(float z, const timestamp now) { diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index c2247d51b2..3aa12a6670 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -640,6 +640,7 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) { parseOptionalProperty>("background-opacity", Key::BackgroundOpacity, klass, value); parseOptionalProperty>("background-color", Key::BackgroundColor, klass, value); + parseOptionalProperty("background-image", Key::BackgroundImage, klass, value); } void StyleParser::parseReference(JSVal value, util::ptr &layer) { diff --git a/src/util/mat3.cpp b/src/util/mat3.cpp index 38858d2385..263768ee41 100644 --- a/src/util/mat3.cpp +++ b/src/util/mat3.cpp @@ -38,7 +38,51 @@ void matrix::identity(mat3& out) { out[8] = 1.0f; } -void matrix::scale(mat3& out, const mat3& a, const float x, const float y) { +void matrix::translate(mat3& out, const mat3& a, float x, float y) { + float a00 = a[0], a01 = a[1], a02 = a[2], + a10 = a[3], a11 = a[4], a12 = a[5], + a20 = a[6], a21 = a[7], a22 = a[8]; + + out[0] = a00; + out[1] = a01; + out[2] = a02; + + out[3] = a10; + out[4] = a11; + out[5] = a12; + + out[6] = x * a00 + y * a10 + a20; + out[7] = x * a01 + y * a11 + a21; + out[8] = x * a02 + y * a12 + a22; +} + +void matrix::rotate(mat3& out, const mat3& a, float rad) { + float s = std::sin(rad), + c = std::cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a10 = a[3], + a11 = a[4], + a12 = a[5], + a20 = a[6], + a21 = a[7], + a22 = a[8]; + + out[0] = c * a00 + s * a10; + out[1] = c * a01 + s * a11; + out[2] = c * a02 + s * a12; + + out[3] = c * a10 - s * a00; + out[4] = c * a11 - s * a01; + out[5] = c * a12 - s * a02; + + out[6] = a20; + out[7] = a21; + out[8] = a22; +}; + +void matrix::scale(mat3& out, const mat3& a, float x, float y) { out[0] = x * a[0]; out[1] = x * a[1]; out[2] = x * a[2]; -- cgit v1.2.1