From a5682fd50dec18f07558c3d19e53a9aed6103657 Mon Sep 17 00:00:00 2001
From: Aaron <aaron.kreuzberg@rwth-aachen.de>
Date: Wed, 3 Nov 2021 16:39:44 +0100
Subject: [PATCH] picking samples

---
 extern/glow-extras           |    2 +-
 samples/basic/viewer/main.cc | 1146 ++++++++++++++++------------------
 2 files changed, 539 insertions(+), 609 deletions(-)

diff --git a/extern/glow-extras b/extern/glow-extras
index 1978c6b..a9e9479 160000
--- a/extern/glow-extras
+++ b/extern/glow-extras
@@ -1 +1 @@
-Subproject commit 1978c6b5209d2de5fbfbb250f74385817149b193
+Subproject commit a9e947979d85b8186c9faddb13d442dc261ab322
diff --git a/samples/basic/viewer/main.cc b/samples/basic/viewer/main.cc
index 55e8944..c5e50e4 100644
--- a/samples/basic/viewer/main.cc
+++ b/samples/basic/viewer/main.cc
@@ -27,334 +27,6 @@
 // path to sample files
 std::string const dataPath = glow::util::pathOf(__FILE__) + "/../../../data/";
 
-void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_attribute<tg::color3> const& col)
-{
-    // {
-    //     // In this case a Picker is defined for the Renderable (Picking Texture filled) but no callback will be executed.
-    //     gv::view(pos, col, gv::pick(), "Picker defined without callback");
-    // }
-
-    {
-        auto g = gv::grid();
-
-        // Only on_left_click callback defined
-        gv::view(pos, col,
-                 gv::pick().onLeftClick(
-                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
-                     {
-                         std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                   << "ID: " << (int)face_id << std::endl;
-                         std::cout << "World_Position " << world_pos << std::endl;
-                         std::cout << "Normal " << normal << std::endl;
-                         gv::picking_result res;
-                         res.mPickingColor = tg::color3::cyan;
-                         return res;
-                     }),
-                 "picking MeshRenderable - callback on left click");
-
-        // Only on_left_click callback defined - LineRenderable - uncolored
-        gv::view(gv::lines(pos),
-                 gv::pick().onLeftClick(
-                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                     {
-                         std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                   << "ID: " << int(face_id) << std::endl;
-                         std::cout << "World_Position" << world_pos << std::endl;
-                         std::cout << "Normal" << normal << std::endl;
-                     }),
-                 "picking LineRenderable - callback on left click");
-
-        {
-            // Only on_left_click callback defined - PointRenderable - uncolored
-            gv::view(gv::points(pos),
-                     gv::pick().onLeftClick(
-                         [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
-                         {
-                             std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                       << "ID: " << int(vertex_id) << std::endl;
-                             std::cout << "World_Position" << world_pos << std::endl;
-                             std::cout << "Normal" << normal << std::endl;
-                             return;
-                         }),
-                     "picking PointRenderable - callback on left click - spheres");
-        }
-
-        {
-            // Only on_left_click callback defined - PointRenderable - uncolored - square billboards - NOT WORKING APPROPRIATELY
-            gv::view(gv::points(pos).point_size_world(0.03f).camera_facing().square(),
-                     gv::pick().onLeftClick(
-                         [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
-                         {
-                             std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                       << "ID: " << int(vertex_id) << std::endl;
-                             std::cout << "World_Position" << world_pos << std::endl;
-                             std::cout << "Normal" << normal << std::endl;
-                             return;
-                         }),
-                     "picking PointRenderables - callback on left click - billboards");
-        }
-    }
-    {
-        auto r1 = gv::make_and_configure_renderable(pos, col,
-                                                    gv::pick().onRightClick(
-                                                        [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                                                        {
-                                                            std::cout << "Something has been picked! ON_RIGHT_CLICK"
-                                                                      << "ID: " << int(face_id) << std::endl;
-                                                            return;
-                                                        }),
-                                                    "picking MeshRenderable - callback on right click");
-        auto r2 = gv::make_and_configure_renderable(pos, col,
-                                                    gv::pick().onHover(
-                                                        [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                                                        {
-                                                            std::cout << "Something has been picked! ON_HOVER"
-                                                                      << "ID: " << (int)face_id << std::endl;
-                                                            return;
-                                                        }),
-                                                    "picking MeshRenderable - callback on hover");
-        gv::interactive(
-            [&](float)
-            {
-                auto g = gv::grid();
-                gv::view(r1);
-                gv::view(r2);
-            });
-    }
-    {
-        auto g = gv::grid();
-
-        // Only on_right_click callback defined
-        gv::view(pos, col,
-                 gv::pick().onRightClick(
-                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                     {
-                         std::cout << "Something has been picked! ON_RIGHT_CLICK"
-                                   << "ID: " << int(face_id) << std::endl;
-                         return;
-                     }),
-                 "picking MeshRenderable - callback on right click");
-
-        // Only on_hover callback defined
-        gv::view(pos, col,
-                 gv::pick().onHover(
-                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                     {
-                         std::cout << "Something has been picked! ON_HOVER"
-                                   << "ID: " << (int)face_id << std::endl;
-                         return;
-                     }),
-                 "picking MeshRenderable - callback on hover");
-    }
-
-    {
-        /* Picking in interactive mode with ImGui example. Does only work for MeshRenderable in the given configuration because face_indices are not included in Point- or LineRenderables.*/
-        pm::face_index face_index_i;
-        uint32_t face_id_i;
-        tg::pos3 world_pos_i;
-        tg::vec3 normal_i;
-
-        pm::Mesh m2;
-        m2.copy_from(m);
-
-        pm::vertex_attribute<tg::pos3> pos2(m2);
-        pos2.copy_from(pos);
-
-        gv::interactive(
-            [&](auto)
-            {
-                gv::view(pos2, col,
-                         gv::pick().onLeftClick(
-                             [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                             {
-                                 std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                           << "ID: " << int(face_id) << std::endl;
-                                 std::cout << "World_Position" << world_pos << std::endl;
-                                 std::cout << "Normal" << normal << std::endl;
-
-                                 face_index_i = face_id;
-                                 world_pos_i = world_pos;
-                                 normal_i = normal;
-                             }),
-                         "picking interactive mode");
-
-                ImGui::Begin("Picking");
-
-                ImGui::Value("pm::face_index", face_index_i.value);
-
-                ImGui::Value("WorldPos.x", world_pos_i.x);
-                ImGui::Value("WorldPos.y", world_pos_i.y);
-                ImGui::Value("WorldPos.z", world_pos_i.z);
-
-                ImGui::Value("Normal.x", normal_i.x);
-                ImGui::Value("Normal.y", normal_i.y);
-                ImGui::Value("Normal.z", normal_i.z);
-
-                if (ImGui::Button("Delete selected face"))
-                {
-                    // delete selected face - after deleting one face another face has to be picked
-                    std::cout << "DELETE FACE" << std::endl;
-                    m2.faces().remove(m2.faces()[face_index_i]);
-                }
-
-                ImGui::End();
-            });
-    }
-
-    {
-        /* Picking in interactive mode with ImGui example. Does only work for MeshRenderable in the given configuration because face_indices are not included in Point- or LineRenderables.*/
-        pm::vertex_index vertex_index_i;
-        uint32_t vertex_id_i;
-        tg::pos3 world_pos_i;
-        tg::vec3 normal_i;
-
-        pm::Mesh m2;
-        m2.copy_from(m);
-
-        pm::vertex_attribute<tg::pos3> pos2(m2);
-        pos2.copy_from(pos);
-
-        // auto copy = pm::copy(pos.mesh(), pos);
-        // auto m2 = copy._Myfirst._Val.get();
-        // auto pos2 = copy._Get_rest()._Myfirst._Val;
-
-        gv::interactive(
-            [&](auto)
-            {
-                gv::view(gv::points(pos2),
-                         gv::pick().onLeftClick(
-                             [&vertex_index_i, &world_pos_i, &normal_i](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
-                             {
-                                 std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                           << "ID: " << int(vertex_id) << std::endl;
-                                 std::cout << "World_Position" << world_pos << std::endl;
-                                 std::cout << "Normal" << normal << std::endl;
-
-                                 vertex_index_i = vertex_id;
-                                 world_pos_i = world_pos;
-                                 normal_i = normal;
-
-                                 return;
-                             }),
-                         "picking interactive mode - PointRenderable");
-
-                ImGui::Begin("Picking");
-
-                ImGui::Value("pm::vertex_index", vertex_index_i.value);
-
-                ImGui::Value("WorldPos.x", world_pos_i.x);
-                ImGui::Value("WorldPos.y", world_pos_i.y);
-                ImGui::Value("WorldPos.z", world_pos_i.z);
-
-                ImGui::Value("Normal.x", normal_i.x);
-                ImGui::Value("Normal.y", normal_i.y);
-                ImGui::Value("Normal.z", normal_i.z);
-
-                if (ImGui::Button("Delete selected vertex"))
-                {
-                    // delete selected vertex - after deleting one vertex another vertex has to be picked
-                    std::cout << "DELETE VERTEX" << std::endl;
-                    m2.vertices().remove(m2.vertices()[vertex_index_i]);
-                }
-
-                ImGui::End();
-            });
-    }
-
-    {
-        // On_hover, on_right_click, and on_left_click callbacks defined simultaneously
-        gv::view(pos, col,
-                 gv::pick()
-                     .onLeftClick(
-                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                         {
-                             std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                       << "ID: " << int(face_id) << std::endl;
-                             return;
-                         })
-                     .onRightClick(
-                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                         {
-                             std::cout << "Something has been picked! ON_RIGHT_CLICK"
-                                       << "ID: " << int(face_id) << std::endl;
-                             return;
-                         })
-                     .onHover(
-                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
-                         {
-                             std::cout << "Something has been picked! ON_HOVER"
-                                       << "ID: " << int(face_id) << std::endl;
-                             return;
-                         }),
-                 "picking MeshRenderable - multiple callbacks: on left click, on right click, on hover"
-
-        );
-    }
-
-    {
-        // User-defined Picking IDs - MeshRenderable
-        pm::face_attribute<int32_t> fa = pm::face_attribute<int32_t>(m);
-        int i = 0;
-        for (auto f : m.faces())
-        {
-            fa[f] = 1000 + i;
-            i++;
-        }
-        gv::view(pos, col,
-                 gv::pick(fa).onLeftClick(
-                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
-                     {
-                         std::cout << "Something has been picked! ON_LEFT_CLICK"
-                                   << "ID: " << (int)face_id << std::endl;
-                         std::cout << "World_Position" << world_pos << std::endl;
-                         std::cout << "Normal" << normal << std::endl;
-                         gv::picking_result res;
-                         res.mPickingColor = tg::color3::cyan;
-                         return res;
-                     }),
-                 "simple picking: callback on left click - user-defined IDs");
-    }
-
-    {
-        auto v = gv::view(pos, "Multiple renderables");
-
-        // Check multiple Renderables.
-        gv::view(pos, gv::pick().onLeftClick(
-                          [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
-                          {
-                              std::cout << "Something has been picked! PICKER 1 "
-                                        << "ID: " << (int)face_id << std::endl;
-                              std::cout << "World_Position" << world_pos << std::endl;
-                              std::cout << "Normal" << normal << std::endl;
-                              gv::picking_result res;
-                              res.mPickingColor = tg::color3::cyan;
-                              return res;
-                          }));
-
-        pm::Mesh m2;
-        m2.copy_from(m);
-
-        pm::vertex_attribute<tg::pos3> pos2(m2);
-        pos2.copy_from(pos);
-
-        for (auto p : m2.vertices())
-        {
-            pos2[p] = pos2[p] + tg::vec3(2, 2, 2);
-        }
-
-        gv::view(pos2, gv::pick().onLeftClick(
-                           [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
-                           {
-                               std::cout << "Something has been picked! PICKER 2 "
-                                         << "ID: " << (int)face_id << std::endl;
-                               std::cout << "World_Position" << world_pos << std::endl;
-                               std::cout << "Normal" << normal << std::endl;
-                               gv::picking_result res;
-                               res.mPickingColor = tg::color3::cyan;
-                               return res;
-                           }));
-    }
-}
 
 void simple_view(pm::vertex_attribute<tg::pos3> const& pos)
 {
@@ -837,308 +509,604 @@ void viewer_canvas(pm::vertex_attribute<tg::pos3> const& pos)
     {
         auto c = gv::canvas();
 
-        tg::rng rng;
+        tg::rng rng;
+
+        // splats are always world sized and have no default size
+        c.set_splat_size(0.4f);
+
+        for (auto i = 0; i < 50; ++i)
+        {
+            auto p = uniform(rng, tg::boundary_of(tg::sphere3(tg::pos3::zero, 8.f)));
+            auto n = normalize(p - tg::pos3::zero);
+            c.add_splat(p, n);
+        }
+    }
+
+    // c.add_lines allows segments and tg objects that defines edges(obj) or ranges thereof
+    // c.add_line is the single line only version
+    {
+        auto c = gv::canvas();
+
+        // meshes work by rendering their edges
+        c.add_lines(pos);
+
+        // tg::objects that support edges_of(obj) work (and types do not have to be float)
+        c.add_lines(tg::iaabb3(-10, 10), tg::color3::green);
+
+        // add_line can be used with pos/pos or pos/vec as well
+        tg::rng rng;
+        for (auto i = 0; i < 10; ++i)
+            c.add_line(tg::pos3(1, 2, 3), tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f), tg::color3::blue);
+    }
+
+    // c.add_faces allows triangles, quads, meshes, anything with a surface or ranges thereof
+    // c.add_face is the single line only version
+    {
+        auto c = gv::canvas();
+
+        // meshes work by rendering their faces (assumes planar polygons)
+        c.add_faces(pos);
+
+        // most finite tg::objects work
+        c.add_faces(tg::aabb3(-3, -2), tg::color3::red);
+
+        // add_face can be used with pos/pos/pos (triangle) or pos/pos/pos/pos (quad) as well
+        tg::rng rng;
+        for (auto i = 0; i < 10; ++i)
+        {
+            auto p0 = tg::pos3(1, 2, 3);
+            auto p1 = p0 + tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f);
+            auto p2 = p0 + tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f);
+            c.add_face(p0, p1, p2, tg::color3::blue);
+        }
+    }
+
+    // return value of add_xyz
+    // is a reference to all added primitives
+    // and can be used to change properties
+    // NOTE: this is only valid until the next add_xyz call
+    {
+        auto c = gv::canvas();
+
+        auto vnormals = pm::vertex_normals_by_area(pos);
+        auto vcolors = pos.map([](tg::pos3 p) { return tg::color3(abs(p)); });
+
+        // .color(...) changes the color of all added primitives in that call
+        c.add_lines(tg::iaabb3(-8, 8)).color(0, 0, 1);
+
+        // .size changes all sizes
+        // .normal_translate translates each splat in normal direction
+        // .colors can be used to set different points per splat
+        c.add_splats(pos, vnormals).size(0.01f).normal_translate(0.03f).colors(vcolors);
+
+        // .color(...) also works with hex strings
+        c.add_faces(pos).color("#f00");
+    }
+
+    // extra features
+    {
+        auto c = gv::canvas();
+
+        c.add_faces(pos);
+
+        // .add_arrow can be used to add arrows
+        tg::rng rng;
+        for (auto i = 0; i < 20; ++i)
+        {
+            auto d = tg::uniform<tg::dir3>(rng);
+
+            auto end = tg::pos3(d * 2.f);
+            auto start = end + d * uniform(rng, 0.3f, 0.7f);
+
+            c.add_arrow(start, end, 0.05f, tg::color3::red);
+        }
+
+        // .add_label can be used to add labels
+        // normals is optional and can be used for preferred directions
+        auto normals = pm::vertex_normals_by_area(pos);
+        for (auto i = 0; i < 20; ++i)
+        {
+            auto v = pos.mesh().vertices().random(rng);
+            c.add_points(pos[v], tg::color3::red);
+            c.add_label(pos, normals, v, "vertex " + std::to_string(int(v)));
+        }
+    }
+}
+
+void interactive_viewer(pm::vertex_attribute<tg::pos3> const& pos)
+{
+    // gv::interactive([&](float dt) { ... });
+    // this opens an interactive viewer
+    // the lambda is called every frame
+    // inside, viewer commands can be used, as well as ImGui UI elements
+    // the scene config and all renderables are hashed and the viewer accumulation is cleared when the hash changes
+
+    // a simple interactive viewer with some interactive-related controls
+    gv::interactive(
+        [&](auto)
+        {
+            if (ImGui::Button("make screenshot"))
+                gv::make_screenshot("screenshot.png", 1920, 1080);
+
+            if (ImGui::Button("close viewer"))
+                gv::close_viewer();
+
+            gv::view(pos, "interactive viewer with custom buttons. It is slow because nothing is cached.");
+        });
+
+    // creating renderables is expensive, cache them whenever possible
+    // NOTE: capture by value if the interactive viewer is not the top-most viewer
+    {
+        auto const r = gv::make_renderable(pos);
+        gv::interactive(
+            [r](auto dt)
+            {
+                static auto time = 0.f;
+                time += dt;
+
+                gv::view(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f)),
+                         "Caching renderables in interactive views increases performance.");
+            });
+    }
+
+    // using imgui in an interactive view
+    {
+        auto const r = gv::make_renderable(pos);
+        gv::interactive(
+            [r](auto)
+            {
+                static float configurable = 0.f;
+
+                ImGui::SliderFloat("Height", &configurable, -3.f, 3.f);
+
+                gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), "interactive translation of a model");
+            });
+    }
+
+    // an interactive textured torus with animated texture coordinates
+    {
+        glow::SharedTexture2D tex = glow::Texture2D::createFromFile(dataPath + "textures/tiles.color.png", glow::ColorSpace::sRGB);
+
+        // create torus mesh
+        pm::Mesh m;
+        auto pos = m.vertices().make_attribute<tg::pos3>();
+        auto uv = m.vertices().make_attribute<tg::pos2>();
+        pm::objects::add_quad(
+            m,
+            [&](pm::vertex_handle v, float x, float y)
+            {
+                auto [cx, sx] = tg::sin_cos(tg::pi<float> * 2 * x);
+                auto [cy, sy] = tg::sin_cos(tg::pi<float> * 2 * y);
+
+                auto const orad = 8.f;
+                auto const irad = 3.f;
+
+                tg::vec3 t;
+                t.x = cx;
+                t.z = sx;
+                tg::pos3 p;
+                p.x = orad * cx;
+                p.y = irad * cy;
+                p.z = orad * sx;
+                p += t * irad * sy;
+
+                pos[v] = p;
+                uv[v] = {1 - x, y};
+            },
+            32, 32);
+
+        auto a = 0.f;
+        auto animate = false;
+        gv::interactive(
+            [&](auto dt)
+            {
+                ImGui::Begin("Torus");
+                ImGui::SliderFloat("angle", &a, 0.f, 360.f);
+                ImGui::Checkbox("Animate", &animate);
+                ImGui::End();
+
+                if (animate)
+                    a += 5 * dt;
+
+                // texture coordinates are rotated by "a" degrees
+                view(pos, gv::textured(uv, tex).transform(tg::rotation_around(tg::pos2::zero, tg::degree(a))), "animated texture coordinates");
+            });
+    }
+}
+
+void scenarios()
+{
+    // in contrast to the other example groups, this group does not introduce new concepts.
+    // it combines the single features and shows how they can be used in some scenarios
+
+    // debugging / visualizing geometric operations
+    {
+        auto g = gv::grid();
+        tg::rng rng;
+
+        // construct a random box
+        const auto c = uniform(rng, tg::sphere3::unit);
+        auto e0 = uniform_vec(rng, tg::sphere3::unit);
+        auto e1 = cross(e0, uniform_vec(rng, tg::sphere3::unit));
+        auto e2 = cross(e1, e0);
+        e0 = normalize(e0) * uniform(rng, 0.5f, 0.9f);
+        e1 = normalize(e1) * uniform(rng, 0.5f, 0.9f);
+        e2 = normalize(e2) * uniform(rng, 0.5f, 0.9f);
+        const auto box = tg::box3(c, {e0, e1, e2});
+
+        // check for some random points if they are inside or outside the box
+        const auto range = tg::sphere3(tg::pos3::zero, 2.f);
+        std::vector<tg::pos3> insidePoints;
+        std::vector<tg::pos3> outsidePoints;
+        for (auto i = 0; i < 1000; ++i)
+        {
+            const auto p = uniform(rng, range);
+            if (contains(box, p))
+                insidePoints.push_back(p);
+            else
+                outsidePoints.push_back(p);
+        }
+
+        {
+            auto v = gv::view();
+            gv::view(box, tg::color4(tg::color3::cyan, 0.5f), "Visualize contained and outside points");
+            gv::view(gv::lines(box), tg::color3::cyan);
+            gv::view(insidePoints, gv::maybe_empty, tg::color3::green);
+            gv::view(outsidePoints, gv::maybe_empty, tg::color3::red);
+        }
+
+        // project outside points onto the box
+        std::vector<tg::segment3> projections;
+        projections.reserve(outsidePoints.size());
+        for (const auto& p : outsidePoints)
+            projections.emplace_back(p, project(p, box));
 
-        // splats are always world sized and have no default size
-        c.set_splat_size(0.4f);
+        {
+            auto v = gv::view();
+            gv::view(box, tg::color3::cyan, "Visualize projection of outside points");
+            gv::view(outsidePoints, gv::maybe_empty);
+            gv::view(projections, gv::maybe_empty);
+        }
 
-        for (auto i = 0; i < 50; ++i)
+        // measure distance between points and box
+        std::vector<tg::pos3> points;
+        std::vector<float> distances;
+        const auto num = 25;
+        points.reserve(num);
+        distances.reserve(num);
+        for (auto i = 0; i < num; ++i)
         {
-            auto p = uniform(rng, tg::boundary_of(tg::sphere3(tg::pos3::zero, 8.f)));
-            auto n = normalize(p - tg::pos3::zero);
-            c.add_splat(p, n);
+            auto p = uniform(rng, range);
+            points.push_back(p);
+            distances.push_back(distance(p, box));
+        }
+
+        {
+            auto v = gv::view();
+            gv::view(box, tg::color3::cyan, "Use point spheres to visualize distances");
+            gv::view(points);
+            gv::view(gv::points(points).point_size_world(distances)); // point_size specifies the radius of the rendered spheres
         }
     }
+}
 
-    // c.add_lines allows segments and tg objects that defines edges(obj) or ranges thereof
-    // c.add_line is the single line only version
-    {
-        auto c = gv::canvas();
+void vector_graphics()
+{
+    // TODO: text
+    // TODO: 2D camera controls
 
-        // meshes work by rendering their edges
-        c.add_lines(pos);
+    // see Vector2DSample for more sample code
+    glow::vector::image2D img;
+    auto g = graphics(img);
+    g.fill(tg::disk2({100.f, 100.f}, 70), tg::color3::red);
+    g.draw(tg::circle2({100.f, 100.f}, 70), {tg::color3::black, 2});
+    gv::view(img, "2D vector graphics");
+}
 
-        // tg::objects that support edges_of(obj) work (and types do not have to be float)
-        c.add_lines(tg::iaabb3(-10, 10), tg::color3::green);
+void custom_renderables()
+{
+    // TODO
+}
 
-        // add_line can be used with pos/pos or pos/vec as well
-        tg::rng rng;
-        for (auto i = 0; i < 10; ++i)
-            c.add_line(tg::pos3(1, 2, 3), tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f), tg::color3::blue);
-    }
+void picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_attribute<tg::color3> const& col)
+{
+    // gv::view(obj, args, gv::pick().on...([&](pm::face_index, tg::pos3, tg::vec3){...}), ...);
+    // adds a Picker to a Renderable (MeshRenderable, PointRenderable, LineRenderable) that enables the picking of individual primitives and the visual representation
+    // every time a primitive gets picked, the callback function defined in the gv::pick().on...() call will be executed
+    // picking can be defined on up to two buttons and on hover (gv::pick().onLeftClick(...), gv::pick().onRightClick(...), gv::pick().onHover(...)).
+    // callback functions need to have the signature as given above and might return a gv::view::picking_result or void.
+    // gv::view::picking_result as return type can change the visual appearence of the picked primitive via modifying the member attributes pickingColor, borderColor, and borderWidth;
+    //
+    // in interactive mode (gv::interactive()) operations on picked primitives can be performed
 
-    // c.add_faces allows triangles, quads, meshes, anything with a surface or ranges thereof
-    // c.add_face is the single line only version
     {
-        auto c = gv::canvas();
+        auto g = gv::grid();
 
-        // meshes work by rendering their faces (assumes planar polygons)
-        c.add_faces(pos);
+        // Only on_left_click callback defined
+        gv::view(pos, col,
+                 gv::pick().onLeftClick(
+                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
+                     {
+                         std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                   << "ID: " << (int)face_id << std::endl;
+                         std::cout << "World_Position " << world_pos << std::endl;
+                         std::cout << "Normal " << normal << std::endl;
+                         gv::picking_result res;
+                         res.pickingColor = tg::color3::cyan;
+                         return res;
+                     }),
+                 "picking MeshRenderable - callback on left click");
 
-        // most finite tg::objects work
-        c.add_faces(tg::aabb3(-3, -2), tg::color3::red);
+        // Only on_left_click callback defined - LineRenderable - uncolored
+        gv::view(gv::lines(pos),
+                 gv::pick().onLeftClick(
+                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                     {
+                         std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                   << "ID: " << int(face_id) << std::endl;
+                         std::cout << "World_Position" << world_pos << std::endl;
+                         std::cout << "Normal" << normal << std::endl;
+                     }),
+                 "picking LineRenderable - callback on left click");
 
-        // add_face can be used with pos/pos/pos (triangle) or pos/pos/pos/pos (quad) as well
-        tg::rng rng;
-        for (auto i = 0; i < 10; ++i)
         {
-            auto p0 = tg::pos3(1, 2, 3);
-            auto p1 = p0 + tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f);
-            auto p2 = p0 + tg::uniform<tg::dir3>(rng) * uniform(rng, 0.3f, 0.8f);
-            c.add_face(p0, p1, p2, tg::color3::blue);
+            // Only on_left_click callback defined - PointRenderable - uncolored
+            gv::view(gv::points(pos),
+                     gv::pick().onLeftClick(
+                         [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
+                         {
+                             std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                       << "ID: " << int(vertex_id) << std::endl;
+                             std::cout << "World_Position" << world_pos << std::endl;
+                             std::cout << "Normal" << normal << std::endl;
+                             return;
+                         }),
+                     "picking PointRenderable - callback on left click - spheres");
+        }
+
+        {
+            // Only on_left_click callback defined - PointRenderable - uncolored - square billboards - NOT WORKING APPROPRIATELY
+            gv::view(gv::points(pos).point_size_world(0.03f).camera_facing().square(),
+                     gv::pick().onLeftClick(
+                         [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
+                         {
+                             std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                       << "ID: " << int(vertex_id) << std::endl;
+                             std::cout << "World_Position" << world_pos << std::endl;
+                             std::cout << "Normal" << normal << std::endl;
+                             return;
+                         }),
+                     "picking PointRenderables - callback on left click - billboards");
         }
     }
 
-    // return value of add_xyz
-    // is a reference to all added primitives
-    // and can be used to change properties
-    // NOTE: this is only valid until the next add_xyz call
     {
-        auto c = gv::canvas();
-
-        auto vnormals = pm::vertex_normals_by_area(pos);
-        auto vcolors = pos.map([](tg::pos3 p) { return tg::color3(abs(p)); });
-
-        // .color(...) changes the color of all added primitives in that call
-        c.add_lines(tg::iaabb3(-8, 8)).color(0, 0, 1);
+        auto g = gv::grid();
 
-        // .size changes all sizes
-        // .normal_translate translates each splat in normal direction
-        // .colors can be used to set different points per splat
-        c.add_splats(pos, vnormals).size(0.01f).normal_translate(0.03f).colors(vcolors);
+        // Only on_right_click callback defined
+        gv::view(pos, col,
+                 gv::pick().onRightClick(
+                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                     {
+                         std::cout << "Something has been picked! ON_RIGHT_CLICK"
+                                   << "ID: " << int(face_id) << std::endl;
+                         return;
+                     }),
+                 "picking MeshRenderable - callback on right click");
 
-        // .color(...) also works with hex strings
-        c.add_faces(pos).color("#f00");
+        // Only on_hover callback defined
+        gv::view(pos, col,
+                 gv::pick().onHover(
+                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                     {
+                         std::cout << "Something has been picked! ON_HOVER"
+                                   << "ID: " << (int)face_id << std::endl;
+                         return;
+                     }),
+                 "picking MeshRenderable - callback on hover");
     }
 
-    // extra features
     {
-        auto c = gv::canvas();
-
-        c.add_faces(pos);
+        /* Picking in interactive mode with ImGui example */
+        pm::face_index face_index_i;
+        uint32_t face_id_i;
+        tg::pos3 world_pos_i;
+        tg::vec3 normal_i;
 
-        // .add_arrow can be used to add arrows
-        tg::rng rng;
-        for (auto i = 0; i < 20; ++i)
-        {
-            auto d = tg::uniform<tg::dir3>(rng);
+        pm::Mesh m2;
+        m2.copy_from(m);
 
-            auto end = tg::pos3(d * 2.f);
-            auto start = end + d * uniform(rng, 0.3f, 0.7f);
+        pm::vertex_attribute<tg::pos3> pos2(m2);
+        pos2.copy_from(pos);
 
-            c.add_arrow(start, end, 0.05f, tg::color3::red);
-        }
+        gv::interactive(
+            [&](auto)
+            {
+                gv::view(pos2, col,
+                         gv::pick().onLeftClick(
+                             [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                             {
+                                 std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                           << "ID: " << int(face_id) << std::endl;
+                                 std::cout << "World_Position" << world_pos << std::endl;
+                                 std::cout << "Normal" << normal << std::endl;
 
-        // .add_label can be used to add labels
-        // normals is optional and can be used for preferred directions
-        auto normals = pm::vertex_normals_by_area(pos);
-        for (auto i = 0; i < 20; ++i)
-        {
-            auto v = pos.mesh().vertices().random(rng);
-            c.add_points(pos[v], tg::color3::red);
-            c.add_label(pos, normals, v, "vertex " + std::to_string(int(v)));
-        }
-    }
-}
+                                 face_index_i = face_id;
+                                 world_pos_i = world_pos;
+                                 normal_i = normal;
+                             }),
+                         "picking interactive mode - callback on left click - delete selected face");
 
-void interactive_viewer(pm::vertex_attribute<tg::pos3> const& pos)
-{
-    // gv::interactive([&](float dt) { ... });
-    // this opens an interactive viewer
-    // the lambda is called every frame
-    // inside, viewer commands can be used, as well as ImGui UI elements
-    // the scene config and all renderables are hashed and the viewer accumulation is cleared when the hash changes
+                ImGui::Begin("Picking");
 
-    // a simple interactive viewer with some interactive-related controls
-    gv::interactive(
-        [&](auto)
-        {
-            if (ImGui::Button("make screenshot"))
-                gv::make_screenshot("screenshot.png", 1920, 1080);
+                ImGui::Value("pm::face_index", face_index_i.value);
 
-            if (ImGui::Button("close viewer"))
-                gv::close_viewer();
+                ImGui::Value("WorldPos.x", world_pos_i.x);
+                ImGui::Value("WorldPos.y", world_pos_i.y);
+                ImGui::Value("WorldPos.z", world_pos_i.z);
 
-            gv::view(pos, "interactive viewer with custom buttons. It is slow because nothing is cached.");
-        });
+                ImGui::Value("Normal.x", normal_i.x);
+                ImGui::Value("Normal.y", normal_i.y);
+                ImGui::Value("Normal.z", normal_i.z);
 
-    // creating renderables is expensive, cache them whenever possible
-    // NOTE: capture by value if the interactive viewer is not the top-most viewer
-    {
-        auto const r = gv::make_renderable(pos);
-        gv::interactive(
-            [r](auto dt)
-            {
-                static auto time = 0.f;
-                time += dt;
+                if (ImGui::Button("Delete selected face"))
+                {
+                    // delete selected face - after deleting one face another face has to be picked
+                    std::cout << "DELETE FACE" << std::endl;
+                    m2.faces().remove(m2.faces()[face_index_i]);
+                }
 
-                gv::view(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f)),
-                         "Caching renderables in interactive views increases performance.");
+                ImGui::End();
             });
     }
 
-    // using imgui in an interactive view
     {
-        auto const r = gv::make_renderable(pos);
+        /* Picking in interactive mode with ImGui example.*/
+        pm::vertex_index vertex_index_i;
+        uint32_t vertex_id_i;
+        tg::pos3 world_pos_i;
+        tg::vec3 normal_i;
+
+        pm::Mesh m2;
+        m2.copy_from(m);
+
+        pm::vertex_attribute<tg::pos3> pos2(m2);
+        pos2.copy_from(pos);
+
         gv::interactive(
-            [r](auto)
+            [&](auto)
             {
-                static float configurable = 0.f;
+                gv::view(gv::points(pos2),
+                         gv::pick().onLeftClick(
+                             [&vertex_index_i, &world_pos_i, &normal_i](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal)
+                             {
+                                 std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                           << "ID: " << int(vertex_id) << std::endl;
+                                 std::cout << "World_Position" << world_pos << std::endl;
+                                 std::cout << "Normal" << normal << std::endl;
 
-                ImGui::SliderFloat("Height", &configurable, -3.f, 3.f);
+                                 vertex_index_i = vertex_id;
+                                 world_pos_i = world_pos;
+                                 normal_i = normal;
 
-                gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), "interactive translation of a model");
-            });
-    }
+                                 return;
+                             }),
+                         "picking interactive mode - PointRenderable");
 
-    // an interactive textured torus with animated texture coordinates
-    {
-        glow::SharedTexture2D tex = glow::Texture2D::createFromFile(dataPath + "textures/tiles.color.png", glow::ColorSpace::sRGB);
+                ImGui::Begin("Picking");
 
-        // create torus mesh
-        pm::Mesh m;
-        auto pos = m.vertices().make_attribute<tg::pos3>();
-        auto uv = m.vertices().make_attribute<tg::pos2>();
-        pm::objects::add_quad(
-            m,
-            [&](pm::vertex_handle v, float x, float y)
-            {
-                auto [cx, sx] = tg::sin_cos(tg::pi<float> * 2 * x);
-                auto [cy, sy] = tg::sin_cos(tg::pi<float> * 2 * y);
+                ImGui::Value("pm::vertex_index", vertex_index_i.value);
 
-                auto const orad = 8.f;
-                auto const irad = 3.f;
+                ImGui::Value("WorldPos.x", world_pos_i.x);
+                ImGui::Value("WorldPos.y", world_pos_i.y);
+                ImGui::Value("WorldPos.z", world_pos_i.z);
 
-                tg::vec3 t;
-                t.x = cx;
-                t.z = sx;
-                tg::pos3 p;
-                p.x = orad * cx;
-                p.y = irad * cy;
-                p.z = orad * sx;
-                p += t * irad * sy;
+                ImGui::Value("Normal.x", normal_i.x);
+                ImGui::Value("Normal.y", normal_i.y);
+                ImGui::Value("Normal.z", normal_i.z);
 
-                pos[v] = p;
-                uv[v] = {1 - x, y};
-            },
-            32, 32);
+                if (ImGui::Button("Delete selected vertex"))
+                {
+                    // delete selected vertex - after deleting one vertex another vertex has to be picked
+                    std::cout << "DELETE VERTEX" << std::endl;
+                    m2.vertices().remove(m2.vertices()[vertex_index_i]);
+                }
 
-        auto a = 0.f;
-        auto animate = false;
-        gv::interactive(
-            [&](auto dt)
-            {
-                ImGui::Begin("Torus");
-                ImGui::SliderFloat("angle", &a, 0.f, 360.f);
-                ImGui::Checkbox("Animate", &animate);
                 ImGui::End();
-
-                if (animate)
-                    a += 5 * dt;
-
-                // texture coordinates are rotated by "a" degrees
-                view(pos, gv::textured(uv, tex).transform(tg::rotation_around(tg::pos2::zero, tg::degree(a))), "animated texture coordinates");
             });
     }
-}
-
-void scenarios()
-{
-    // in contrast to the other example groups, this group does not introduce new concepts.
-    // it combines the single features and shows how they can be used in some scenarios
 
-    // debugging / visualizing geometric operations
     {
-        auto g = gv::grid();
-        tg::rng rng;
-
-        // construct a random box
-        const auto c = uniform(rng, tg::sphere3::unit);
-        auto e0 = uniform_vec(rng, tg::sphere3::unit);
-        auto e1 = cross(e0, uniform_vec(rng, tg::sphere3::unit));
-        auto e2 = cross(e1, e0);
-        e0 = normalize(e0) * uniform(rng, 0.5f, 0.9f);
-        e1 = normalize(e1) * uniform(rng, 0.5f, 0.9f);
-        e2 = normalize(e2) * uniform(rng, 0.5f, 0.9f);
-        const auto box = tg::box3(c, {e0, e1, e2});
+        // On_hover, on_right_click, and on_left_click callbacks defined simultaneously
+        gv::view(pos, col,
+                 gv::pick()
+                     .onLeftClick(
+                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                         {
+                             std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                       << "ID: " << int(face_id) << std::endl;
+                             return;
+                         })
+                     .onRightClick(
+                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                         {
+                             std::cout << "Something has been picked! ON_RIGHT_CLICK"
+                                       << "ID: " << int(face_id) << std::endl;
+                             return;
+                         })
+                     .onHover(
+                         [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal)
+                         {
+                             std::cout << "Something has been picked! ON_HOVER"
+                                       << "ID: " << int(face_id) << std::endl;
+                             return;
+                         }),
+                 "picking MeshRenderable - multiple callbacks: on left click, on right click, on hover");
+    }
 
-        // check for some random points if they are inside or outside the box
-        const auto range = tg::sphere3(tg::pos3::zero, 2.f);
-        std::vector<tg::pos3> insidePoints;
-        std::vector<tg::pos3> outsidePoints;
-        for (auto i = 0; i < 1000; ++i)
+    {
+        // User-defined Picking IDs - MeshRenderable
+        pm::face_attribute<int32_t> fa = pm::face_attribute<int32_t>(m);
+        int i = 0;
+        for (auto f : m.faces())
         {
-            const auto p = uniform(rng, range);
-            if (contains(box, p))
-                insidePoints.push_back(p);
-            else
-                outsidePoints.push_back(p);
+            fa[f] = 1000 + i;
+            i++;
         }
+        gv::view(pos, col,
+                 gv::pick(fa).onLeftClick(
+                     [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
+                     {
+                         std::cout << "Something has been picked! ON_LEFT_CLICK"
+                                   << "ID: " << (int)face_id << std::endl;
+                         std::cout << "World_Position" << world_pos << std::endl;
+                         std::cout << "Normal" << normal << std::endl;
+                         gv::picking_result res;
+                         res.pickingColor = tg::color3::cyan;
+                         return res;
+                     }),
+                 "simple picking: callback on left click - user-defined IDs");
+    }
 
-        {
-            auto v = gv::view();
-            gv::view(box, tg::color4(tg::color3::cyan, 0.5f), "Visualize contained and outside points");
-            gv::view(gv::lines(box), tg::color3::cyan);
-            gv::view(insidePoints, gv::maybe_empty, tg::color3::green);
-            gv::view(outsidePoints, gv::maybe_empty, tg::color3::red);
-        }
+    {
+        auto v = gv::view(pos, "pciking multiple renderables: different callbacks defined");
 
-        // project outside points onto the box
-        std::vector<tg::segment3> projections;
-        projections.reserve(outsidePoints.size());
-        for (const auto& p : outsidePoints)
-            projections.emplace_back(p, project(p, box));
+        // Check multiple Renderables.
+        gv::view(pos, gv::pick().onHover(
+                          [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
+                          {
+                              std::cout << "Something has been picked! PICKER 1 "
+                                        << "ID: " << (int)face_id << std::endl;
+                              std::cout << "World_Position" << world_pos << std::endl;
+                              std::cout << "Normal" << normal << std::endl;
+                              gv::picking_result res;
+                              res.pickingColor = tg::color3::cyan;
+                              return res;
+                          }));
 
-        {
-            auto v = gv::view();
-            gv::view(box, tg::color3::cyan, "Visualize projection of outside points");
-            gv::view(outsidePoints, gv::maybe_empty);
-            gv::view(projections, gv::maybe_empty);
-        }
+        pm::Mesh m2;
+        m2.copy_from(m);
 
-        // measure distance between points and box
-        std::vector<tg::pos3> points;
-        std::vector<float> distances;
-        const auto num = 25;
-        points.reserve(num);
-        distances.reserve(num);
-        for (auto i = 0; i < num; ++i)
-        {
-            auto p = uniform(rng, range);
-            points.push_back(p);
-            distances.push_back(distance(p, box));
-        }
+        pm::vertex_attribute<tg::pos3> pos2(m2);
+        pos2.copy_from(pos);
 
+        for (auto p : m2.vertices())
         {
-            auto v = gv::view();
-            gv::view(box, tg::color3::cyan, "Use point spheres to visualize distances");
-            gv::view(points);
-            gv::view(gv::points(points).point_size_world(distances)); // point_size specifies the radius of the rendered spheres
+            pos2[p] = pos2[p] + tg::vec3(2, 2, 2);
         }
-    }
-}
-
-void vector_graphics()
-{
-    // TODO: text
-    // TODO: 2D camera controls
-
-    // see Vector2DSample for more sample code
-    glow::vector::image2D img;
-    auto g = graphics(img);
-    g.fill(tg::disk2({100.f, 100.f}, 70), tg::color3::red);
-    g.draw(tg::circle2({100.f, 100.f}, 70), {tg::color3::black, 2});
-    gv::view(img, "2D vector graphics");
-}
-
-void custom_renderables()
-{
-    // TODO
-}
 
-void picking()
-{
-    // TODO
+        gv::view(pos2, gv::pick().onLeftClick(
+                           [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result
+                           {
+                               std::cout << "Something has been picked! PICKER 2 "
+                                         << "ID: " << (int)face_id << std::endl;
+                               std::cout << "World_Position" << world_pos << std::endl;
+                               std::cout << "Normal" << normal << std::endl;
+                               gv::picking_result res;
+                               res.pickingColor = tg::color3::cyan;
+                               return res;
+                           }));
+    }
 }
 
 void headless_screenshot(pm::vertex_attribute<tg::pos3> const& pos)
@@ -1323,11 +1291,10 @@ int main()
     pm::Mesh m;
     auto pos = m.vertices().make_attribute<tg::pos3>();
     load(dataPath + "suzanne.obj", m, pos);
-    // pm::objects::add_cube(m, pos);
     normalize(pos); // make it -1..1*/
     auto col = pm::face_attribute<tg::color3>(m);
-    int it = 0;
 
+    // initially random colors for faces (picking sample)
     auto r = tg::rng();
     for (auto x : m.faces())
     {
@@ -1336,45 +1303,6 @@ int main()
         col[x] = color;
     }
 
-    pm::Mesh m_2;
-    auto pos_2 = pm::vertex_attribute<tg::pos3>(m_2);
-    const auto t1_vh0 = m_2.vertices().add();
-    const auto t1_vh1 = m_2.vertices().add();
-    const auto t1_vh2 = m_2.vertices().add();
-    const auto t2_vh0 = m_2.vertices().add();
-    const auto t2_vh1 = m_2.vertices().add();
-    const auto t2_vh2 = m_2.vertices().add();
-    const auto t3_vh0 = m_2.vertices().add();
-    const auto t3_vh1 = m_2.vertices().add();
-    const auto t3_vh2 = m_2.vertices().add();
-
-    pos_2[t1_vh0] = tg::pos3(0, 0, 0);
-    pos_2[t1_vh1] = tg::pos3(20, 0, 0);
-    pos_2[t1_vh2] = tg::pos3(0, 20, 0);
-    pos_2[t2_vh0] = tg::pos3(0, 20, 0);
-    pos_2[t2_vh1] = tg::pos3(20, 0, 0);
-    pos_2[t2_vh2] = tg::pos3(20, 20, 0);
-    pos_2[t3_vh0] = tg::pos3(20, 20, 0);
-    pos_2[t3_vh1] = tg::pos3(40, 20, 0);
-    pos_2[t3_vh2] = tg::pos3(40, 0, 0);
-
-    auto col_2 = pm::face_attribute<tg::color3>(m_2);
-    const auto f1 = m_2.faces().add(t1_vh0, t1_vh1, t1_vh2);
-    const auto f2 = m_2.faces().add(t2_vh0, t2_vh1, t2_vh2);
-    const auto f3 = m_2.faces().add(t3_vh0, t3_vh1, t3_vh2);
-
-    col_2[f1] = tg::color3::blue;
-    col_2[f2] = tg::color3::cyan;
-    col_2[f2] = tg::color3::magenta;
-
-    // deduplicate(m, pos);
-    // m.compactify();
-
-    // simple picking demo
-    {
-        simple_picking(m, pos, col);
-    }
-
     // basic demos
     {
         simple_view(pos);
@@ -1405,6 +1333,8 @@ int main()
     {
         vector_graphics();
 
+        picking(m, pos, col);
+
         custom_renderables();
 
         special_use_cases(pos);
@@ -1418,4 +1348,4 @@ int main()
     known_issues(pos);
 
     return EXIT_SUCCESS;
-}
+}
\ No newline at end of file
-- 
GitLab