From 840ca2bb19bb287cee1558c51c6fd896e74e3595 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 10 Jan 2017 17:16:35 +0300 Subject: [PATCH] Added different frequency of arrows on traffic lines --- drape/drape_tests/CMakeLists.txt | 1 + drape/drape_tests/drape_tests.pro | 1 + drape/drape_tests/static_texture_tests.cpp | 16 +++++++ drape/shaders/traffic_vertex_shader.vsh | 11 ++--- drape/static_texture.cpp | 16 ++++--- drape/static_texture.hpp | 6 ++- drape_frontend/traffic_generator.cpp | 52 +++++++++++++++++----- drape_frontend/traffic_generator.hpp | 5 ++- drape_frontend/traffic_renderer.cpp | 2 +- 9 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 drape/drape_tests/static_texture_tests.cpp diff --git a/drape/drape_tests/CMakeLists.txt b/drape/drape_tests/CMakeLists.txt index 3d80914617..63159690d3 100644 --- a/drape/drape_tests/CMakeLists.txt +++ b/drape/drape_tests/CMakeLists.txt @@ -39,6 +39,7 @@ set( img.hpp memory_comparer.hpp pointers_tests.cpp + static_texture_tests.cpp stipple_pen_tests.cpp texture_of_colors_tests.cpp testingmain.cpp diff --git a/drape/drape_tests/drape_tests.pro b/drape/drape_tests/drape_tests.pro index c204c72dd4..1aaf5536a2 100644 --- a/drape/drape_tests/drape_tests.pro +++ b/drape/drape_tests/drape_tests.pro @@ -40,6 +40,7 @@ SOURCES += \ glyph_packer_test.cpp \ img.cpp \ pointers_tests.cpp \ + static_texture_tests.cpp \ stipple_pen_tests.cpp \ testingmain.cpp \ texture_of_colors_tests.cpp \ diff --git a/drape/drape_tests/static_texture_tests.cpp b/drape/drape_tests/static_texture_tests.cpp new file mode 100644 index 0000000000..6d8c726755 --- /dev/null +++ b/drape/drape_tests/static_texture_tests.cpp @@ -0,0 +1,16 @@ +#include "testing/testing.hpp" + +#include "drape/static_texture.hpp" + +#include +#include + +UNIT_TEST(CheckTrafficArrowTextures) +{ + static std::vector skinPaths = {"6plus", "mdpi", "hdpi", "xhdpi", "xxhdpi"}; + for (size_t i = 0; i < skinPaths.size(); ++i) + { + dp::StaticTexture texture("traffic-arrow", skinPaths[i], nullptr); + TEST(texture.IsLoadingCorrect(), ()); + } +} diff --git a/drape/shaders/traffic_vertex_shader.vsh b/drape/shaders/traffic_vertex_shader.vsh index 7625f7cc79..6aba2dbb21 100644 --- a/drape/shaders/traffic_vertex_shader.vsh +++ b/drape/shaders/traffic_vertex_shader.vsh @@ -1,6 +1,6 @@ attribute vec3 a_position; attribute vec4 a_normal; -attribute vec2 a_colorTexCoord; +attribute vec4 a_colorTexCoord; uniform mat4 modelView; uniform mat4 projection; @@ -13,7 +13,7 @@ varying vec2 v_maskTexCoord; varying float v_halfLength; const float kShapeCoordScalar = 1000.0; -const float kMinVisibleArrowPart = 0.9; +const float kArrowVSize = 0.25; void main(void) { @@ -33,9 +33,10 @@ void main(void) } float uOffset = length(vec4(kShapeCoordScalar, 0, 0, 0) * modelView) * a_normal.w; - v_colorTexCoord = a_colorTexCoord; - v_maskTexCoord = vec2(uOffset * u_trafficParams.z, 0.5 * a_normal.z + 0.5) * u_trafficParams.w; - v_maskTexCoord.x *= step(kMinVisibleArrowPart, v_maskTexCoord.x); + v_colorTexCoord = a_colorTexCoord.xy; + float v = mix(a_colorTexCoord.z, a_colorTexCoord.z + kArrowVSize, 0.5 * a_normal.z + 0.5); + v_maskTexCoord = vec2(uOffset * u_trafficParams.z, v) * u_trafficParams.w; + v_maskTexCoord.x *= step(a_colorTexCoord.w, v_maskTexCoord.x); v_halfLength = a_normal.z; vec4 pos = vec4(transformedAxisPos, a_position.z, 1.0) * projection; float w = pos.w; diff --git a/drape/static_texture.cpp b/drape/static_texture.cpp index 830f739eef..9e2e91ad90 100644 --- a/drape/static_texture.cpp +++ b/drape/static_texture.cpp @@ -20,7 +20,7 @@ namespace using TLoadingCompletion = function; using TLoadingFailure = function; -void LoadData(string const & textureName, string const & skinPathName, +bool LoadData(string const & textureName, string const & skinPathName, TLoadingCompletion const & completionHandler, TLoadingFailure const & failureHandler) { @@ -39,15 +39,17 @@ void LoadData(string const & textureName, string const & skinPathName, catch (RootException & e) { failureHandler(e.what()); - return; + return false; } int w, h, bpp; - unsigned char * data = stbi_png_load_from_memory(&rawData[0], static_cast(rawData.size()), &w, &h, &bpp, 0); + unsigned char * data = stbi_png_load_from_memory(&rawData[0], static_cast(rawData.size()), + &w, &h, &bpp, 0); ASSERT_EQUAL(bpp, 4, ("Incorrect texture format")); completionHandler(data, w, h); stbi_image_free(data); + return true; } class StaticResourceInfo : public Texture::ResourceInfo @@ -66,10 +68,10 @@ StaticTexture::StaticTexture(string const & textureName, string const & skinPath : m_textureName(textureName) , m_info(make_unique_dp()) { - Load(skinPathName, allocator); + m_isLoadingCorrect = Load(skinPathName, allocator); } -void StaticTexture::Load(string const & skinPathName, ref_ptr allocator) +bool StaticTexture::Load(string const & skinPathName, ref_ptr allocator) { auto completionHandler = [this, &allocator](unsigned char * data, uint32_t width, uint32_t height) { @@ -90,13 +92,13 @@ void StaticTexture::Load(string const & skinPathName, ref_ptr allocator) { Destroy(); - Load(skinPathName, allocator); + m_isLoadingCorrect = Load(skinPathName, allocator); } ref_ptr StaticTexture::FindResource(Texture::Key const & key, bool & newResource) diff --git a/drape/static_texture.hpp b/drape/static_texture.hpp index 9385faf917..aa2aa7e4c5 100644 --- a/drape/static_texture.hpp +++ b/drape/static_texture.hpp @@ -23,12 +23,16 @@ public: void Invalidate(string const & skinPathName, ref_ptr allocator); + bool IsLoadingCorrect() const { return m_isLoadingCorrect; } + private: void Fail(); - void Load(string const & skinPathName, ref_ptr allocator); + bool Load(string const & skinPathName, ref_ptr allocator); string m_textureName; drape_ptr m_info; + + bool m_isLoadingCorrect; }; } // namespace dp diff --git a/drape_frontend/traffic_generator.cpp b/drape_frontend/traffic_generator.cpp index 373847354b..61239beb3b 100644 --- a/drape_frontend/traffic_generator.cpp +++ b/drape_frontend/traffic_generator.cpp @@ -24,6 +24,31 @@ namespace df namespace { +// Values of the following arrays are based on traffic-arrow texture. +static array(traffic::SpeedGroup::Count)> kCoordVOffsets = +{ + 0.75f, // G0 + 0.75f, // G1 + 0.75f, // G2 + 0.5f, // G3 + 0.25f, // G4 + 0.0f, // G5 + 0.75f, // TempBlock + 0.0f, // Unknown +}; + +static array(traffic::SpeedGroup::Count)> kMinCoordU = +{ + 0.15f, // G0 + 0.15f, // G1 + 0.15f, // G2 + 0.33f, // G3 + 0.5f, // G4 + 0.0f, // G5 + 0.15f, // TempBlock + 0.0f, // Unknown +}; + dp::BindingInfo const & GetTrafficStaticBindingInfo() { static unique_ptr s_info; @@ -52,7 +77,7 @@ dp::BindingInfo const & GetTrafficLineStaticBindingInfo() } void SubmitStaticVertex(glsl::vec3 const & pivot, glsl::vec2 const & normal, float side, - float offsetFromStart, glsl::vec2 const & texCoord, + float offsetFromStart, glsl::vec4 const & texCoord, vector & staticGeom) { staticGeom.emplace_back(pivot, TrafficStaticVertex::TNormal(normal, side, offsetFromStart), texCoord); @@ -63,7 +88,7 @@ void GenerateCapTriangles(glsl::vec3 const & pivot, vector const & n vector & staticGeometry) { float const kEps = 1e-5; - glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); + glsl::vec4 const uv = glsl::vec4(glsl::ToVec2(colorRegion.GetTexRect().Center()), 0.0f, 0.0f); size_t const trianglesCount = normals.size() / 3; for (int j = 0; j < trianglesCount; j++) { @@ -141,6 +166,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg ASSERT(m_colorsCacheValid, ()); dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[static_cast(segmentColoringIt->second)]; + float const vOffset = kCoordVOffsets[static_cast(segmentColoringIt->second)]; + float const minU = kMinCoordU[static_cast(segmentColoringIt->second)]; int width = 0; if (TrafficRenderer::CanBeRendereredAsLine(g.m_roadClass, tileKey.m_zoomLevel, width)) @@ -161,7 +188,8 @@ void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSeg { vector staticGeometry; bool const generateCaps = (tileKey.m_zoomLevel > kGenerateCapsZoomLevel[static_cast(g.m_roadClass)]); - GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), generateCaps, depth, staticGeometry); + GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), generateCaps, depth, + vOffset, minU, staticGeometry); if (staticGeometry.empty()) continue; @@ -215,7 +243,8 @@ void TrafficGenerator::FlushGeometry(TrafficBatcherKey const & key, dp::GLState void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - bool generateCaps, float depth, vector & staticGeometry) + bool generateCaps, float depth, float vOffset, float minU, + vector & staticGeometry) { vector const & path = polyline.GetPoints(); ASSERT_GREATER(path.size(), 1, ()); @@ -229,7 +258,8 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c glsl::vec2 lastPoint, lastTangent, lastLeftNormal, lastRightNormal; bool firstFilled = false; - glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); + glsl::vec4 const uvStart = glsl::vec4(glsl::ToVec2(colorRegion.GetTexRect().Center()), vOffset, 1.0f); + glsl::vec4 const uvEnd = glsl::vec4(uvStart.x, uvStart.y, uvStart.z, minU); for (size_t i = 1; i < path.size(); ++i) { if (path[i].EqualDxDy(path[i - 1], 1.0E-5)) @@ -257,12 +287,12 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c glsl::vec3 const startPivot = glsl::vec3(p1, depth); glsl::vec3 const endPivot = glsl::vec3(p2, depth); - SubmitStaticVertex(startPivot, rightNormal, -1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uv, staticGeometry); - SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uv, staticGeometry); - SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uv, staticGeometry); - SubmitStaticVertex(endPivot, leftNormal, 1.0f, maskSize, uv, staticGeometry); + SubmitStaticVertex(startPivot, rightNormal, -1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uvEnd, staticGeometry); + SubmitStaticVertex(endPivot, rightNormal, -1.0f, maskSize, uvEnd, staticGeometry); + SubmitStaticVertex(startPivot, leftNormal, 1.0f, 0.0f, uvStart, staticGeometry); + SubmitStaticVertex(endPivot, leftNormal, 1.0f, maskSize, uvEnd, staticGeometry); } // Generate caps. diff --git a/drape_frontend/traffic_generator.hpp b/drape_frontend/traffic_generator.hpp index 7983a1cddd..e9c331c8d2 100644 --- a/drape_frontend/traffic_generator.hpp +++ b/drape_frontend/traffic_generator.hpp @@ -93,7 +93,7 @@ struct TrafficStaticVertex { using TPosition = glsl::vec3; using TNormal = glsl::vec4; - using TTexCoord = glsl::vec2; + using TTexCoord = glsl::vec4; TrafficStaticVertex() = default; TrafficStaticVertex(TPosition const & position, TNormal const & normal, @@ -180,7 +180,8 @@ private: void GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, - bool generateCaps, float depth, vector & staticGeometry); + bool generateCaps, float depth, float vOffset, float minU, + vector & staticGeometry); void GenerateLineSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, float depth, vector & staticGeometry); diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index c3ab0c3c08..139d8ba5d9 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -24,7 +24,7 @@ int constexpr kMinVisibleArrowZoomLevel = 16; int constexpr kRoadClass2MinVisibleArrowZoomLevel = 17; int constexpr kOutlineMinZoomLevel = 14; -float const kTrafficArrowAspect = 24.0f / 8.0f; +float const kTrafficArrowAspect = 128.0f / 8.0f; float const kLeftWidthInPixel[] = {