std::tuple<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const Trade::MeshData2D& meshData, const BufferUsage usage) {
    Mesh mesh;
    mesh.setPrimitive(meshData.primitive());

    /* Decide about stride and offsets */
    UnsignedInt stride = sizeof(Shaders::Generic2D::Position::Type);
    const UnsignedInt normalOffset = sizeof(Shaders::Generic2D::Position::Type);
    if(meshData.hasTextureCoords2D())
        stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type);

    /* Create vertex buffer */
    std::unique_ptr<Buffer> vertexBuffer{new Buffer{Buffer::TargetHint::Array}};

    /* Interleave positions */
    Containers::Array<char> data = MeshTools::interleave(
        meshData.positions(0),
        stride - sizeof(Shaders::Generic2D::Position::Type));
    mesh.addVertexBuffer(*vertexBuffer, 0,
        Shaders::Generic2D::Position(),
        stride - sizeof(Shaders::Generic2D::Position::Type));

    /* Add also texture coordinates, if present */
    if(meshData.hasTextureCoords2D()) {
        MeshTools::interleaveInto(data,
            normalOffset,
            meshData.textureCoords2D(0),
            stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type));
        mesh.addVertexBuffer(*vertexBuffer, 0,
            normalOffset,
            Shaders::Generic2D::TextureCoordinates(),
            stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type));
    }

    /* Fill vertex buffer with interleaved data */
    vertexBuffer->setData(data, usage);

    /* If indexed, fill index buffer and configure indexed mesh */
    std::unique_ptr<Buffer> indexBuffer;
    if(meshData.isIndexed()) {
        Containers::Array<char> indexData;
        Mesh::IndexType indexType;
        UnsignedInt indexStart, indexEnd;
        std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices());

        indexBuffer.reset(new Buffer{Buffer::TargetHint::ElementArray});
        indexBuffer->setData(indexData, usage);
        mesh.setCount(meshData.indices().size())
            .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd);

    /* Else set vertex count */
    } else mesh.setCount(meshData.positions(0).size());

    return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer));
}
void CapsuleTest::wireframe2D() {
    Trade::MeshData2D capsule = Capsule2D::wireframe(2, 4, 0.5f);

    CORRADE_COMPARE_AS(capsule.positions(0), (std::vector<Vector2>{
        {0.0f, -1.5f},

        {-0.707107f, -1.20711f},
        {0.707107f, -1.20711f},

        {-1.0f, -0.5f},
        {1.0f, -0.5f},

        {-1.0f, -0.25f},
        {1.0f, -0.25f},

        {-1.0f, 0.0f},
        {1.0f, 0.0f},

        {-1.0f, 0.25f},
        {1.0f, 0.25f},

        {-1.0f, 0.5f},
        {1.0f, 0.5f},

        {-0.707107f, 1.20711f},
        {0.707107f, 1.20711f},

        {0.0f, 1.5f}
    }), TestSuite::Compare::Container);

    CORRADE_COMPARE_AS(capsule.indices(), (std::vector<UnsignedInt>{
        0, 1, 0, 2,

        1, 3, 2, 4,
        3, 5, 4, 6,
        5, 7, 6, 8,
        7, 9, 8, 10,
        9, 11, 10, 12,
        11, 13, 12, 14,

        13, 15, 14, 15
    }), TestSuite::Compare::Container);
}