#include #include #include #include #include #include namespace mbgl { namespace gfx { DrawableBuilder::DrawableBuilder(std::string name_) : name(std::move(name_)), vertexAttrName("a_pos"), renderPass(mbgl::RenderPass::Opaque), impl(std::make_unique()) {} DrawableBuilder::~DrawableBuilder() = default; const gfx::ColorMode& DrawableBuilder::getColorMode() const { return impl->colorMode; } void DrawableBuilder::setColorMode(const gfx::ColorMode& value) { impl->colorMode = value; } const gfx::CullFaceMode& DrawableBuilder::getCullFaceMode() const { return impl->cullFaceMode; } void DrawableBuilder::setCullFaceMode(const gfx::CullFaceMode& value) { impl->cullFaceMode = value; } const gfx::VertexAttributeArray& DrawableBuilder::getVertexAttributes() const { return impl->vertexAttrs; } UniqueDrawable& DrawableBuilder::getCurrentDrawable(bool createIfNone) { if (!currentDrawable && createIfNone) { currentDrawable = createDrawable(); } return currentDrawable; } void DrawableBuilder::flush() { if (curVertexCount()) { const auto& draw = getCurrentDrawable(/*createIfNone=*/true); draw->setEnabled(enabled); draw->setLineWidth(static_cast(lineWidth)); draw->setEnableColor(enableColor); draw->setEnableStencil(enableStencil); draw->setRenderPass(renderPass); draw->setDrawPriority(drawPriority); draw->setSubLayerIndex(subLayerIndex); draw->setDepthType(depthType); draw->setIs3D(is3D); draw->setColorMode(impl->colorMode); draw->setCullFaceMode(impl->cullFaceMode); draw->setShader(shader); draw->setTextures(textures); draw->setTweakers(tweakers); const auto& builderAttrs = getVertexAttributes(); if (auto drawAttrs = builderAttrs.clone()) { draw->setVertexAttributes(std::move(*drawAttrs)); } init(); } if (currentDrawable) { drawables.emplace_back(std::move(currentDrawable)); } } util::SimpleIdentity DrawableBuilder::getDrawableId() { return currentDrawable ? currentDrawable->getID() : util::SimpleIdentity::Empty; } DrawPriority DrawableBuilder::getDrawPriority() const { return drawPriority; } void DrawableBuilder::setDrawPriority(DrawPriority value) { drawPriority = value; if (currentDrawable) { currentDrawable->setDrawPriority(value); } } void DrawableBuilder::resetDrawPriority(DrawPriority value) { setDrawPriority(value); for (auto& drawble : drawables) { drawble->setDrawPriority(value); } } void DrawableBuilder::setTexture(const std::shared_ptr& texture, int32_t location) { textures.insert(std::make_pair(location, gfx::Texture2DPtr{})).first->second = std::move(texture); } void DrawableBuilder::addTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { const auto n = static_cast(impl->vertices.elements()); impl->vertices.emplace_back(Impl::VT({{{x0, y0}}})); impl->vertices.emplace_back(Impl::VT({{{x1, y1}}})); impl->vertices.emplace_back(Impl::VT({{{x2, y2}}})); impl->buildIndexes.insert(impl->buildIndexes.end(), {n, static_cast(n + 1), static_cast(n + 2)}); if (impl->segments.empty()) { impl->segments.emplace_back(createSegment(gfx::Triangles(), {0, 0})); } auto& segment = impl->segments.back(); segment->getSegment().vertexLength += 3; segment->getSegment().indexLength += 3; } void DrawableBuilder::appendTriangle(int16_t x0, int16_t y0) { const auto n = (uint16_t)impl->vertices.elements(); impl->vertices.emplace_back(Impl::VT({{{x0, y0}}})); impl->buildIndexes.insert(impl->buildIndexes.end(), {static_cast(n - 2), static_cast(n - 1), n}); assert(!impl->segments.empty()); auto& segment = impl->segments.back(); segment->getSegment().vertexLength += 1; segment->getSegment().indexLength += 3; } void DrawableBuilder::addQuad(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { addTriangle(x0, y0, x1, y0, x0, y1); appendTriangle(x1, y1); } void DrawableBuilder::setVertexAttributes(const VertexAttributeArray& attrs) { impl->vertexAttrs = attrs; } void DrawableBuilder::setVertexAttributes(VertexAttributeArray&& attrs) { impl->vertexAttrs = std::move(attrs); } std::size_t DrawableBuilder::addVertices(const std::vector>& vertices, std::size_t vertexOffset, std::size_t vertexLength) { const auto baseIndex = impl->vertices.elements(); std::for_each(std::next(vertices.begin(), vertexOffset), std::next(vertices.begin(), vertexOffset + vertexLength), [&](const std::array& x) { impl->vertices.emplace_back(Impl::VT({{x}})); }); return baseIndex; } void DrawableBuilder::setRawVertices(std::vector&& data, std::size_t count, AttributeDataType type) { impl->rawVertices = std::move(data); impl->rawVerticesCount = count; impl->rawVerticesType = type; } void DrawableBuilder::setSegments(const gfx::DrawMode mode, std::vector indexes, const SegmentBase* segments, const std::size_t segmentCount) { setSegments(mode, std::make_shared(std::move(indexes)), segments, segmentCount); } void DrawableBuilder::setSegments(const gfx::DrawMode mode, gfx::IndexVectorBasePtr indexes, const SegmentBase* segments, const std::size_t segmentCount) { impl->sharedIndexes = std::move(indexes); for (std::size_t i = 0; i < segmentCount; ++i) { const auto& seg = segments[i]; #if !defined(NDEBUG) if (mode.type == DrawModeType::Triangles) { assert(seg.indexLength % 3 == 0); } else if (mode.type == DrawModeType::Lines) { assert(seg.indexLength % 2 == 0); } const auto vertexCount = curVertexCount(); assert(!vertexCount || seg.vertexOffset + seg.vertexLength <= curVertexCount()); assert(seg.indexOffset + seg.indexLength <= impl->sharedIndexes->elements()); if (vertexCount) { for (decltype(seg.indexLength) j = 0; j < seg.indexLength; ++j) { assert(impl->sharedIndexes->vector()[seg.indexOffset + j] < vertexCount); } } #endif auto segCopy = SegmentBase{ // no copy constructor seg.vertexOffset, seg.indexOffset, seg.vertexLength, seg.indexLength, seg.sortKey, }; impl->segments.emplace_back(createSegment(mode, std::move(segCopy))); } } void DrawableBuilder::addLines(const std::vector& indexes, std::size_t indexOffset, std::size_t indexLength, std::size_t baseIndex) { if (!indexLength) { return; } impl->segments.emplace_back(createSegment(Lines(lineWidth), SegmentBase{/*.vertexOffset = */ 0, /*.indexOffset = */ indexes.size(), /*.vertexLength = */ 0, /*.indexLength = */ indexLength})); if (impl->buildIndexes.empty()) { impl->buildIndexes.reserve(indexLength); } for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength); ++i) { impl->buildIndexes.emplace_back(static_cast(*i + baseIndex)); } } void DrawableBuilder::addTriangles(const std::vector& indexes, std::size_t indexOffset, std::size_t indexLength, std::size_t baseIndex) { if (!indexLength) { return; } impl->segments.emplace_back(createSegment(Triangles(), SegmentBase{/*.vertexOffset = */ 0, /*.indexOffset = */ impl->buildIndexes.size(), /*.vertexLength = */ impl->vertices.elements(), /*.indexLength = */ indexLength})); if (impl->buildIndexes.empty()) { impl->buildIndexes.reserve(indexLength); } for (auto i = std::next(indexes.begin(), indexOffset); i != std::next(indexes.begin(), indexOffset + indexLength); ++i) { impl->buildIndexes.emplace_back(static_cast(*i + baseIndex)); } } std::size_t DrawableBuilder::curVertexCount() const { return impl->rawVerticesCount ? impl->rawVerticesCount : impl->vertices.elements(); } } // namespace gfx } // namespace mbgl