#include "drape_frontend/area_shape.hpp" #include "drape_frontend/render_state.hpp" #include "drape_frontend/shader_def.hpp" #include "drape/attribute_provider.hpp" #include "drape/batcher.hpp" #include "drape/texture_manager.hpp" #include "drape/utils/vertex_decl.hpp" #include "indexer/map_style_reader.hpp" #include "base/buffer_vector.hpp" #include "base/logging.hpp" #include "std/algorithm.hpp" namespace df { AreaShape::AreaShape(vector && triangleList, BuildingOutline && buildingOutline, AreaViewParams const & params) : m_vertexes(move(triangleList)) , m_buildingOutline(move(buildingOutline)) , m_params(params) {} void AreaShape::Draw(ref_ptr batcher, ref_ptr textures) const { dp::TextureManager::ColorRegion region; textures->GetColorRegion(m_params.m_color, region); m2::PointD const colorUv(region.GetTexRect().Center()); m2::PointD outlineUv(0.0, 0.0); if (m_buildingOutline.m_generateOutline) { dp::TextureManager::ColorRegion outlineRegion; textures->GetColorRegion(m_params.m_outlineColor, outlineRegion); ASSERT_EQUAL(region.GetTexture(), outlineRegion.GetTexture(), ()); outlineUv = outlineRegion.GetTexRect().Center(); } if (m_params.m_is3D) DrawArea3D(batcher, colorUv, outlineUv, region.GetTexture()); else if (m_params.m_hatching) DrawHatchingArea(batcher, colorUv, region.GetTexture(), textures->GetHatchingTexture()); else DrawArea(batcher, colorUv, outlineUv, region.GetTexture()); } void AreaShape::DrawArea(ref_ptr batcher, m2::PointD const & colorUv, m2::PointD const & outlineUv, ref_ptr texture) const { glsl::vec2 const uv = glsl::ToVec2(colorUv); buffer_vector vertexes; vertexes.resize(m_vertexes.size()); transform(m_vertexes.begin(), m_vertexes.end(), vertexes.begin(), [&uv, this](m2::PointD const & vertex) { return gpu::AreaVertex(glsl::vec3(glsl::ToVec2(ConvertToLocal(m2::PointD(vertex), m_params.m_tileCenter, kShapeCoordScalar)), m_params.m_depth), uv); }); auto state = CreateGLState(gpu::AREA_PROGRAM, RenderState::GeometryLayer); state.SetColorTexture(texture); dp::AttributeProvider provider(1, static_cast(vertexes.size())); provider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertexes.data())); batcher->InsertTriangleList(state, make_ref(&provider)); // Generate outline. if (m_buildingOutline.m_generateOutline && !m_buildingOutline.m_indices.empty()) { glsl::vec2 const ouv = glsl::ToVec2(outlineUv); vector vertices; vertices.reserve(m_buildingOutline.m_vertices.size()); for (size_t i = 0; i < m_buildingOutline.m_vertices.size(); i++) { glsl::vec2 const pos = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[i], m_params.m_tileCenter, kShapeCoordScalar)); vertices.emplace_back(gpu::AreaVertex(glsl::vec3(pos, m_params.m_depth), ouv)); } auto outlineState = CreateGLState(gpu::AREA_OUTLINE_PROGRAM, RenderState::GeometryLayer); outlineState.SetColorTexture(texture); outlineState.SetDrawAsLine(true); dp::AttributeProvider outlineProvider(1, static_cast(vertices.size())); outlineProvider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertices.data())); batcher->InsertLineRaw(outlineState, make_ref(&outlineProvider), m_buildingOutline.m_indices); } } void AreaShape::DrawHatchingArea(ref_ptr batcher, m2::PointD const & colorUv, ref_ptr texture, ref_ptr hatchingTexture) const { glsl::vec2 const uv = glsl::ToVec2(colorUv); m2::RectD bbox; for (auto const & v : m_vertexes) bbox.Add(v); double const maxU = bbox.SizeX() * m_params.m_baseGtoPScale / hatchingTexture->GetWidth(); double const maxV = bbox.SizeY() * m_params.m_baseGtoPScale / hatchingTexture->GetHeight(); buffer_vector vertexes; vertexes.resize(m_vertexes.size()); for (size_t i = 0; i < m_vertexes.size(); ++i) { vertexes[i].m_position = glsl::vec3(glsl::ToVec2(ConvertToLocal(m_vertexes[i], m_params.m_tileCenter, kShapeCoordScalar)), m_params.m_depth); vertexes[i].m_colorTexCoord = uv; vertexes[i].m_maskTexCoord.x = static_cast(maxU * (m_vertexes[i].x - bbox.minX()) / bbox.SizeX()); vertexes[i].m_maskTexCoord.y = static_cast(maxV * (m_vertexes[i].y - bbox.minY()) / bbox.SizeY()); } auto state = CreateGLState(gpu::HATCHING_AREA_PROGRAM, RenderState::GeometryLayer); state.SetColorTexture(texture); state.SetMaskTexture(hatchingTexture); state.SetTextureFilter(gl_const::GLLinear); dp::AttributeProvider provider(1, static_cast(vertexes.size())); provider.InitStream(0, gpu::HatchingAreaVertex::GetBindingInfo(), make_ref(vertexes.data())); batcher->InsertTriangleList(state, make_ref(&provider)); } void AreaShape::DrawArea3D(ref_ptr batcher, m2::PointD const & colorUv, m2::PointD const & outlineUv, ref_ptr texture) const { ASSERT(!m_buildingOutline.m_indices.empty(), ()); ASSERT(!m_buildingOutline.m_normals.empty(), ()); glsl::vec2 const uv = glsl::ToVec2(colorUv); vector vertexes; vertexes.reserve(m_vertexes.size() + m_buildingOutline.m_normals.size() * 6); for (size_t i = 0; i < m_buildingOutline.m_normals.size(); i++) { int const startIndex = m_buildingOutline.m_indices[i * 2]; int const endIndex = m_buildingOutline.m_indices[i * 2 + 1]; glsl::vec2 const startPt = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[startIndex], m_params.m_tileCenter, kShapeCoordScalar)); glsl::vec2 const endPt = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[endIndex], m_params.m_tileCenter, kShapeCoordScalar)); glsl::vec3 normal(glsl::ToVec2(m_buildingOutline.m_normals[i]), 0.0f); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_minPosZ), normal, uv)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, uv)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, uv)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, uv)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, uv)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_posZ), normal, uv)); } glsl::vec3 const normal(0.0f, 0.0f, -1.0f); for (auto const & vertex : m_vertexes) { glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)); vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(pt, -m_params.m_posZ), normal, uv)); } auto state = CreateGLState(gpu::AREA_3D_PROGRAM, RenderState::Geometry3dLayer); state.SetColorTexture(texture); state.SetBlending(dp::Blending(false /* isEnabled */)); dp::AttributeProvider provider(1, static_cast(vertexes.size())); provider.InitStream(0, gpu::Area3dVertex::GetBindingInfo(), make_ref(vertexes.data())); batcher->InsertTriangleList(state, make_ref(&provider)); // Generate outline. if (m_buildingOutline.m_generateOutline) { glsl::vec2 const ouv = glsl::ToVec2(outlineUv); auto outlineState = CreateGLState(gpu::AREA_3D_OUTLINE_PROGRAM, RenderState::Geometry3dLayer); outlineState.SetColorTexture(texture); outlineState.SetBlending(dp::Blending(false /* isEnabled */)); outlineState.SetDrawAsLine(true); vector vertices; vertices.reserve(m_buildingOutline.m_vertices.size()); for (size_t i = 0; i < m_buildingOutline.m_vertices.size(); i++) { glsl::vec2 const pos = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[i], m_params.m_tileCenter, kShapeCoordScalar)); vertices.emplace_back(gpu::AreaVertex(glsl::vec3(pos, -m_params.m_posZ), ouv)); } dp::AttributeProvider outlineProvider(1, static_cast(vertices.size())); outlineProvider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertices.data())); batcher->InsertLineRaw(outlineState, make_ref(&outlineProvider), m_buildingOutline.m_indices); } } } // namespace df