Browse Source

Implemented cursor guide.

jcsyshc 1 year ago
parent
commit
331cdc2f9e

+ 1 - 1
CMakeLists.txt

@@ -33,7 +33,7 @@ add_executable(${PROJECT_NAME} src/main.cpp
         src/core/impl/object_manager.cpp
         src/core/impl/pc_utility.cpp
         src/module_v3/registration.cpp
-        src/module/guidance/cursor_guide.cpp
+        src/module/guidance/impl/cursor_guide.cpp
         src/module/impl/augment_manager.cpp
         src/module/impl/augment_manager_v2.cpp
         src/module/impl/camera_augment_helper.cpp

+ 10 - 0
src/core/math_helper.hpp

@@ -61,4 +61,14 @@ inline auto from_homo(const glm::vec4 &v) {
     return glm::vec3(v) / v.w;
 }
 
+// transform point
+inline glm::vec3 transform_p(const glm::mat4 &mat, const glm::vec3 &point) {
+    return from_homo(mat * to_homo(point));
+}
+
+// transform vector
+inline glm::vec3 transform_v(const glm::mat4 &mat, const glm::vec3 &vec) {
+    return glm::mat3(mat) * vec;
+}
+
 #endif //DEPTHGUIDE_MATH_HELPER_HPP

+ 7 - 0
src/impl/apps/depth_guide_v2/depth_guide_v2.cpp

@@ -70,11 +70,18 @@ app_depth_guide_v2::app_depth_guide_v2(const create_config &_conf) {
     std::copy(aug_list.begin(), aug_list.end(), std::back_inserter(aug_conf.item_list));
     aug_manager = std::make_unique<augment_manager_v2>(aug_conf);
 
+    auto guide_conf = cursor_guide::create_config{
+            .item_list = cursor_guide::item_list_from_aug(aug_list),
+            .sophiar_conn = sophiar_conn.get(),
+    };
+    aug_guide = std::make_unique<cursor_guide>(guide_conf);
+
     auto view_conf = camera_augment_helper_v2::create_config{
             .camera = camera_augment_helper_v2::create_config::freedom_camera_config{
                     .transform_var = LOAD_STR("camera_transform_var")},
             .sophiar_conn = sophiar_conn.get(),
             .manager = aug_manager.get(),
+            .act_guide = aug_guide.get(),
             .ctx = main_conf.asio_ctx,
     };
     aug_helper = std::make_unique<camera_augment_helper_v2>(view_conf);

+ 2 - 1
src/impl/apps/depth_guide_v2/depth_guide_v2.h

@@ -6,6 +6,7 @@
 #include "module_v3/registration.h"
 #include "module/augment_manager_v2.h"
 #include "module/camera_augment_helper_v2.h"
+#include "module/guidance/cursor_guide.h"
 #include "module/image_augment_helper.h"
 #include "module/image_streamer.h"
 #include "impl/app_base.h"
@@ -51,7 +52,6 @@ private:
     obj_name_type extra_name = name_end;
 
     // sophiar
-    using sophiar_conn_type = sophiar::local_connection;
     std::unique_ptr<sophiar_conn_type> sophiar_conn;
     std::unique_ptr<std::thread> sophiar_thread;
     std::string sophiar_start_var;
@@ -62,6 +62,7 @@ private:
 
     std::unique_ptr<augment_manager_v2> aug_manager;
     std::unique_ptr<camera_augment_helper_v2> aug_helper;
+    std::unique_ptr<cursor_guide> aug_guide;
 
     static constexpr auto baseline_dis = 65.0f; // mm
     std::unique_ptr<camera_augment_helper_v2> aug_left;

+ 0 - 1
src/impl/apps/remote_ar/remote_ar.h

@@ -66,7 +66,6 @@ private:
     CUcontext *cuda_ctx;
 
     // sophiar
-    using sophiar_conn_type = sophiar::local_connection;
     std::unique_ptr<sophiar_conn_type> sophiar_conn;
     std::unique_ptr<std::thread> sophiar_thread;
     std::string sophiar_start_var;

+ 0 - 69
src/impl/apps/tiny_player/tiny_player.cpp

@@ -26,79 +26,10 @@ app_tiny_player::app_tiny_player(const create_config &_conf) {
     bg_viewer = std::make_unique<image_viewer>(bg_viewer_conf);
 }
 
-void app_tiny_player::recorde_window_info() {
-    auto win = glfwGetCurrentContext();
-    glfwGetWindowPos(win, &win_info.x_pos, &win_info.y_pos);
-    glfwGetWindowSize(win, &win_info.width, &win_info.height);
-}
-
-void app_tiny_player::update_display() {
-    auto win = glfwGetCurrentContext();
-    if (!full_screen) {
-        glfwSetWindowMonitor(win, nullptr, win_info.x_pos, win_info.y_pos,
-                             win_info.width, win_info.height, GLFW_DONT_CARE);
-    } else {
-        assert(full_screen);
-        int monitor_num = 0;
-        auto monitors = glfwGetMonitors(&monitor_num);
-        assert(chose_monitor < monitor_num);
-        auto monitor = monitors[chose_monitor];
-        auto mode = glfwGetVideoMode(monitor);
-        glfwSetWindowMonitor(win, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
-    }
-}
-
-void app_tiny_player::show_display_configs() {
-    // display mode
-    if (ImGui::RadioButton("Windowed", !full_screen)) {
-        if (full_screen) {
-            full_screen = false;
-            update_display();
-        }
-    }
-    ImGui::SameLine();
-    if (ImGui::RadioButton("Full Screen", full_screen)) {
-        if (!full_screen) {
-            recorde_window_info();
-            full_screen = true;
-            update_display();
-        }
-    }
-
-    if (full_screen) {
-        int monitor_count;
-        auto monitors = glfwGetMonitors(&monitor_count);
-        if (chose_monitor >= monitor_count) {
-            chose_monitor = 0;
-        }
-        auto monitor_name_preview = glfwGetMonitorName(monitors[chose_monitor]);
-        if (ImGui::BeginCombo("Monitor", monitor_name_preview)) { // let user select monitors
-            for (int k = 0; k < monitor_count; ++k) {
-                auto is_selected = (chose_monitor == k);
-                auto monitor_name = fmt::format("{} - {}", k, glfwGetMonitorName(monitors[k]));
-                if (ImGui::Selectable(monitor_name.c_str(), is_selected)) {
-                    if (chose_monitor != k) {
-                        chose_monitor = k;
-                        update_display();
-                    }
-                }
-                if (is_selected) {
-                    ImGui::SetItemDefaultFocus();
-                }
-            }
-            ImGui::EndCombo();
-        }
-    }
-}
-
 void app_tiny_player::show_ui() {
     if (ImGui::Begin("Tiny Player Control")) {
         ImGui::PushItemWidth(200);
         in_player->show();
-
-        ImGui::SeparatorText("Display Configs");
-        show_display_configs();
-
         ImGui::PopItemWidth();
     }
     ImGui::End();

+ 0 - 14
src/impl/apps/tiny_player/tiny_player.h

@@ -29,20 +29,6 @@ private:
     std::unique_ptr<image_viewer> bg_viewer; // background viewer
     std::unique_ptr<image_player> in_player; // input player
 
-    bool full_screen = false;
-    int chose_monitor = 0;
-
-    struct {
-        int x_pos, y_pos;
-        int width, height;
-    } win_info; // windowed mode info
-
-    void recorde_window_info();
-
-    void update_display();
-
-    void show_display_configs();
-
 };
 
 

+ 96 - 1
src/impl/main_impl.cpp

@@ -38,6 +38,16 @@ std::chrono::milliseconds ui_interval;
 std::unique_ptr<app_base> app;
 
 bool hide_app_ui = false;
+bool hide_debug_ui = true;
+bool show_demo = false;
+
+// display config
+bool full_screen = false;
+int chose_monitor = 0;
+struct {
+    int x_pos, y_pos;
+    int width, height;
+} win_info; // windowed mode info
 
 void init_cuda() {
     cuInit(0);
@@ -146,6 +156,85 @@ void process_keys() {
     if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_H)) { // Ctrl+H
         hide_app_ui ^= true;
     }
+    if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_D)) { // Ctrl+D
+        hide_debug_ui ^= true;
+    }
+}
+
+void update_display() {
+    auto win = glfwGetCurrentContext();
+    if (!full_screen) {
+        glfwSetWindowMonitor(win, nullptr, win_info.x_pos, win_info.y_pos,
+                             win_info.width, win_info.height, GLFW_DONT_CARE);
+    } else {
+        assert(full_screen);
+        int monitor_num = 0;
+        auto monitors = glfwGetMonitors(&monitor_num);
+        assert(chose_monitor < monitor_num);
+        auto monitor = monitors[chose_monitor];
+        auto mode = glfwGetVideoMode(monitor);
+        glfwSetWindowMonitor(win, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
+    }
+}
+
+void recorde_window_info() {
+    auto win = glfwGetCurrentContext();
+    glfwGetWindowPos(win, &win_info.x_pos, &win_info.y_pos);
+    glfwGetWindowSize(win, &win_info.width, &win_info.height);
+}
+
+void show_display_config() {
+    // display mode
+    if (ImGui::RadioButton("Windowed", !full_screen)) {
+        if (full_screen) {
+            full_screen = false;
+            update_display();
+        }
+    }
+    ImGui::SameLine();
+    if (ImGui::RadioButton("Full Screen", full_screen)) {
+        if (!full_screen) {
+            recorde_window_info();
+            full_screen = true;
+            update_display();
+        }
+    }
+
+    if (full_screen) {
+        int monitor_count;
+        auto monitors = glfwGetMonitors(&monitor_count);
+        if (chose_monitor >= monitor_count) {
+            chose_monitor = 0;
+        }
+        auto monitor_name_preview = glfwGetMonitorName(monitors[chose_monitor]);
+        if (ImGui::BeginCombo("Monitor", monitor_name_preview)) { // let user select monitors
+            for (int k = 0; k < monitor_count; ++k) {
+                auto is_selected = (chose_monitor == k);
+                auto monitor_name = fmt::format("{} - {}", k, glfwGetMonitorName(monitors[k]));
+                if (ImGui::Selectable(monitor_name.c_str(), is_selected)) {
+                    if (chose_monitor != k) {
+                        chose_monitor = k;
+                        update_display();
+                    }
+                }
+                if (is_selected) {
+                    ImGui::SetItemDefaultFocus();
+                }
+            }
+            ImGui::EndCombo();
+        }
+    }
+}
+
+void show_debug_ui() {
+    if (ImGui::Begin("Debug")) {
+        ImGui::SeparatorText("Display Config");
+        show_display_config();
+
+        ImGui::SeparatorText("Miscellaneous");
+        ImGui::Checkbox("Show Demo", &show_demo);
+    }
+    ImGui::End();
 }
 
 void show_ui() {
@@ -165,7 +254,12 @@ void show_ui() {
     if (!hide_app_ui) {
         app->show_ui();
     }
-    ImGui::Render();
+    if (!hide_debug_ui) {
+        show_debug_ui();
+    }
+    if (show_demo) {
+        ImGui::ShowDemoWindow();
+    }
 
     cv::Size frame_size;
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
@@ -175,6 +269,7 @@ void show_ui() {
 
     app->render_background();
 
+    ImGui::Render();
     ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
     glfwSwapBuffers(window);
 }

+ 0 - 1
src/module/augment_manager.h

@@ -34,7 +34,6 @@ public:
         item_list_type item_list;
 
         // sophiar
-        using sophiar_conn_type = sophiar::local_connection;
         sophiar_conn_type *sophiar_conn = nullptr;
     };
 

+ 0 - 1
src/module/augment_manager_v2.h

@@ -43,7 +43,6 @@ public:
         // scene name will be used as input rather than output
         bool player_mode = false;
 
-        using sophiar_conn_type = sophiar::local_connection;
         sophiar_conn_type *sophiar_conn = nullptr;
 
         smart_cuda_stream *stream = nullptr;

+ 0 - 1
src/module/camera_augment_helper.h

@@ -13,7 +13,6 @@ public:
         std::string transform_var; // for sophiar
 
         // sophiar
-        using sophiar_conn_type = sophiar::local_connection;
         sophiar_conn_type *sophiar_conn = nullptr;
 
         augment_manager *manager = nullptr;

+ 3 - 2
src/module/camera_augment_helper_v2.h

@@ -11,6 +11,8 @@
 #include <memory>
 #include <variant>
 
+class cursor_guide;
+
 class camera_augment_helper_v2 {
 public:
 
@@ -35,10 +37,10 @@ public:
         camera_config_type camera;
 
         // sophiar
-        using sophiar_conn_type = sophiar::local_connection;
         sophiar_conn_type *sophiar_conn = nullptr;
 
         augment_manager_v2 *manager = nullptr;
+        cursor_guide *act_guide = nullptr; // active guidance
 
         using io_context = boost::asio::io_context;
         io_context *ctx = nullptr;
@@ -78,5 +80,4 @@ private:
 };
 
 
-
 #endif //DEPTHGUIDE_CAMERA_AUGMENT_HELPER_V2_H

+ 0 - 51
src/module/guidance/cursor_guide.cpp

@@ -1,51 +0,0 @@
-#include "cursor_guide.h"
-
-#include <glm/gtx/transform.hpp>
-
-#include <vtkSphereSource.h>
-
-struct cursor_guide::impl {
-
-    std::optional<glm::vec3> cursor_pos; // in world coordinate
-    mesh_ptr cursor_symbol;
-
-    void update(const guide_info &info) {
-        cursor_pos = info.position;
-    }
-
-    void pre_render_slot(const scene_ptr &info) {
-        if (!cursor_pos.has_value()) return;
-
-        if (cursor_symbol == nullptr) [[unlikely]] {
-            vtkNew<vtkSphereSource> source;
-            source->SetRadius(5); // TODO: make this adjustable
-            source->SetCenter(0, 0, 0);
-            source->Update();
-            cursor_symbol = mesh_type::from_vtk(source->GetOutput());
-        }
-
-        auto color = glm::vec3(0.0f, 1.0f, 0.0f); // TODO: make this adjustable
-        auto amb_factor = 0.9f;
-        auto item_info = scene_render_info::mesh_info{
-                .mesh = cursor_symbol,
-                .material = {.ambient = color * amb_factor, .diffuse = color,},
-        };
-        info->items.push_back(
-                {.info = item_info, .transform = glm::translate(*cursor_pos),});
-    }
-
-};
-
-cursor_guide::cursor_guide()
-        : pimpl(std::make_unique<impl>()) {
-}
-
-cursor_guide::~cursor_guide() = default;
-
-void cursor_guide::update(const guide_info &info) {
-    pimpl->update(info);
-}
-
-void cursor_guide::pre_render_slot(const scene_ptr &info) {
-    pimpl->pre_render_slot(info);
-}

+ 25 - 4
src/module/guidance/cursor_guide.h

@@ -8,21 +8,42 @@
 class cursor_guide {
 public:
 
-//    struct create_config {
-////        camera_augment_helper_v2 *parent;
-//    };
+    struct create_config {
 
-    cursor_guide();
+        struct item_type {
+            std::string disp_name;
+            std::string transform_var; // for sophiar
+        };
+
+        using item_list_type =
+                std::vector<item_type>;
+        item_list_type item_list;
+
+        sophiar_conn_type *sophiar_conn = nullptr;
+    };
+
+    using item_list_type =
+            create_config::item_list_type;
+    using aug_list_type =
+            augment_manager_v2::create_config::item_list_type;
+
+    static item_list_type item_list_from_aug(const aug_list_type &aug_list);
+
+    explicit cursor_guide(const create_config &conf);
 
     ~cursor_guide();
 
     struct guide_info {
         std::optional<glm::vec3> position; // 3D position of cursor
         float mouse_wheel = 0.f;
+        bool mouse_left: 1 = false;
+        bool mouse_right: 1 = false;
     };
 
     void update(const guide_info &info);
 
+    void show();
+
     void pre_render_slot(const scene_ptr &info);
 
 private:

+ 181 - 0
src/module/guidance/impl/cursor_guide.cpp

@@ -0,0 +1,181 @@
+#include "cursor_guide_impl.h"
+#include "core/imgui_utility.hpp"
+
+#include <glm/gtx/transform.hpp>
+
+#include <vtkSphereSource.h>
+
+#include <unordered_set>
+
+namespace cursor_guide_impl {
+
+    void point_set::emplace(const glm::vec3 &p, float r) {
+        // convert to object coordinate
+        auto obj_p_h = glm::inverse(transform) * to_homo(p);
+        c.emplace_back(from_homo(obj_p_h), r);
+    }
+
+    bool point_set::try_picking(const glm::vec3 &tp) {
+        auto ret = false;
+        for (auto &point: c) {
+            // convert to world coordinate
+            auto wp = transform_p(transform, point.position);
+            if (glm::distance(wp, tp) <= point.radius) {
+                point.is_picked = true;
+                ret = true;
+            } else {
+                point.is_picked = false;
+            }
+        }
+        return ret;
+    }
+
+    void point_set::remove_picked() {
+        c.remove_if([](auto &p) {
+            return p.is_picked;
+        });
+    }
+
+    mesh_cache_type mesh_cache;
+
+    mesh_ptr get_mesh(float radius) {
+        if (auto iter = mesh_cache.find(radius);
+                iter != mesh_cache.end()) {
+            return iter->second;
+        }
+        vtkNew<vtkSphereSource> source;
+        source->SetRadius(radius);
+        source->SetPhiResolution(16);
+        source->SetThetaResolution(16);
+        source->SetCenter(0, 0, 0);
+        source->Update();
+        auto mesh = mesh_type::from_vtk(source->GetOutput());
+        mesh_cache.emplace(radius, mesh);
+        return mesh;
+    }
+
+}
+
+void cursor_guide::impl::binding_store_type::update_transform() {
+    if (pimpl->sophiar_conn == nullptr) return;
+    auto trans = pimpl->sophiar_conn->
+            query_transform_variable(transform_var);
+    if (trans.has_value()) {
+        points.transform = to_mat4(*trans);
+    }
+}
+
+cursor_guide::impl::impl(const create_config &conf) {
+    sophiar_conn = conf.sophiar_conn;
+    std::ranges::transform(conf.item_list, std::back_inserter(binding_list),
+                           [this](auto &item) { return binding_store_type(this, item); });
+    if (conf.item_list.empty()) {
+        binding_list.emplace_back(this, binding_store_base_type{.disp_name = "Null"});
+    }
+}
+
+void cursor_guide::impl::update(const guide_info &info) {
+    free_pos = {};
+    if (!info.position) return;
+    auto wp = *info.position;
+
+    bool picked = false;
+    for (auto &bind: binding_list) {
+        picked |= bind.points.try_picking(wp);
+    }
+
+    if (picked) {
+        if (info.mouse_right) {
+            for (auto &bind: binding_list) {
+                bind.points.remove_picked();
+            }
+        }
+    } else {
+        if (info.mouse_left) {
+            assert(current_binding < binding_list.size());
+            binding_list[current_binding]
+                    .points.emplace(wp, current_radius);
+        } else {
+            free_pos = wp;
+            current_radius += info.mouse_wheel;
+            current_radius = std::max(current_radius, 1.0f);
+        }
+    }
+}
+
+void cursor_guide::impl::show() {
+    auto bind_preview = binding_list[current_binding].disp_name.c_str();
+    if (ImGui::BeginCombo("Point Binding", bind_preview)) {
+        for (int k = 0; k < binding_list.size(); ++k) {
+            auto is_selected = (current_binding == k);
+            if (ImGui::Selectable(binding_list[k].disp_name.c_str(), is_selected)) {
+                current_binding = k;
+            }
+            if (is_selected) {
+                ImGui::SetItemDefaultFocus();
+            }
+        }
+        ImGui::EndCombo();
+    }
+}
+
+void cursor_guide::impl::pre_render_slot(const scene_ptr &info) {
+    if (free_pos.has_value()) {
+        auto item_info = scene_render_info::mesh_info{
+                .mesh = get_mesh(current_radius),
+                .material = {.ambient = color_free * amb_factor, .diffuse = color_free,},
+        };
+        info->items.push_back(
+                {.info = item_info, .transform = glm::translate(*free_pos),});
+    }
+
+    for (auto &bind: binding_list) {
+        bind.update_transform();
+        auto &points = bind.points;
+        for (auto &point: points.c) {
+            auto wp = transform_p(points.transform, point.position);
+            auto color = point.is_picked ? color_picked : color_fixed;
+            auto item_info = scene_render_info::mesh_info{
+                    .mesh = get_mesh(point.radius),
+                    .material = {.ambient = color * amb_factor, .diffuse = color,},
+                    .enable_depth_alpha = true, .alpha_factor = 0.2,
+            };
+            info->items.push_back(
+                    {.info = item_info, .transform = glm::translate(wp),});
+        }
+    }
+}
+
+cursor_guide::item_list_type
+cursor_guide::item_list_from_aug(const aug_list_type &aug_list) {
+    using cache_type =
+            std::unordered_set<std::string>;
+    cache_type cache;
+
+    auto ret = item_list_type();
+    for (auto &item: aug_list) {
+        auto disp_name = item.disp_name;
+        if (cache.contains(disp_name)) continue;
+        ret.emplace_back(disp_name, item.transform_var);
+        cache.emplace(disp_name);
+    }
+    return ret;
+}
+
+cursor_guide::cursor_guide(const create_config &conf)
+        : pimpl(std::make_unique<impl>(conf)) {
+}
+
+cursor_guide::~cursor_guide() = default;
+
+void cursor_guide::update(const guide_info &info) {
+    pimpl->update(info);
+}
+
+void cursor_guide::show() {
+    pimpl->show();
+}
+
+void cursor_guide::pre_render_slot(const scene_ptr &info) {
+    pimpl->pre_render_slot(info);
+}

+ 92 - 0
src/module/guidance/impl/cursor_guide_impl.h

@@ -0,0 +1,92 @@
+#ifndef DEPTHGUIDE_CURSOR_GUIDE_IMPL_H
+#define DEPTHGUIDE_CURSOR_GUIDE_IMPL_H
+
+#include "module/guidance/cursor_guide.h"
+#include "core/math_helper.hpp"
+
+namespace cursor_guide_impl {
+
+    struct point_set {
+        struct point_type {
+            glm::vec3 position;
+            float radius;
+            bool is_picked = false;
+        };
+
+        using container_type =
+                std::list<point_type>;
+        using iterator_type =
+                container_type::iterator;
+
+        container_type c;
+
+        // object observed in world
+        glm::mat4 transform = glm::mat4(1.0f);
+
+        // p: in world coordinate
+        void emplace(const glm::vec3 &p, float r);
+
+        // tp: point in world coordinate
+        // return true if some point is picked.
+        bool try_picking(const glm::vec3 &tp);
+
+        void remove_picked();
+    };
+
+    using mesh_cache_type =
+            std::unordered_map<float, mesh_ptr>;
+    extern mesh_cache_type mesh_cache;
+
+    mesh_ptr get_mesh(float radius);
+
+}
+
+using namespace cursor_guide_impl;
+
+struct cursor_guide::impl {
+
+    static constexpr auto amb_factor = 0.9f;
+    static constexpr auto color_free = glm::vec3(0, 1, 0);
+    static constexpr auto color_picked = glm::vec3(1, 0, 0);
+    static constexpr auto color_fixed = glm::vec3(0, 0, 1);
+
+    sophiar_conn_type *sophiar_conn = nullptr;
+
+    float current_radius = 5.f;
+    std::optional<glm::vec3> free_pos; // in world coordinate
+
+    using binding_store_base_type
+            = create_config::item_type;
+
+    struct binding_store_type
+            : public binding_store_base_type {
+        using base_type = binding_store_base_type;
+
+        impl *pimpl = nullptr;
+        point_set points;
+
+        explicit binding_store_type(impl *_pimpl, const base_type &base)
+                : binding_store_base_type(base) {
+            pimpl = _pimpl;
+        }
+
+        void update_transform();
+    };
+
+    using binding_list_type =
+            std::vector<binding_store_type>;
+    binding_list_type binding_list;
+
+    size_t current_binding = 0;
+
+    explicit impl(const create_config &conf);
+
+    void update(const guide_info &info);
+
+    void show();
+
+    void pre_render_slot(const scene_ptr &info);
+
+};
+
+#endif //DEPTHGUIDE_CURSOR_GUIDE_IMPL_H

+ 0 - 1
src/module/impl/augment_manager_impl.h

@@ -35,7 +35,6 @@ struct augment_manager::impl {
             std::unordered_map<std::string, item_store_type>;
     item_pool_type item_pool;
 
-    using sophiar_conn_type = create_config::sophiar_conn_type;
     sophiar_conn_type *sophiar_conn = nullptr;
 
     bool enable = true; // enable this module

+ 0 - 1
src/module/impl/augment_manager_v2_impl.h

@@ -53,7 +53,6 @@ struct augment_manager_v2::impl {
 
     scene_ptr last_scene_info;
 
-    using sophiar_conn_type = create_config::sophiar_conn_type;
     sophiar_conn_type *sophiar_conn = nullptr;
 
     smart_cuda_stream *stream = nullptr;

+ 0 - 1
src/module/impl/camera_augment_helper_impl.h

@@ -26,7 +26,6 @@ struct camera_augment_helper::impl {
     std::string transform_var; // for sophiar
     glm::mat4 transform = glm::mat4(1.0f); // identity matrix, exclude extra_transform
 
-    using sophiar_conn_type = create_config::sophiar_conn_type;
     sophiar_conn_type *sophiar_conn = nullptr;
 
     augment_manager *manager = nullptr;

+ 36 - 17
src/module/impl/camera_augment_helper_v2.cpp

@@ -1,6 +1,7 @@
 #include "camera_augment_helper_v2_impl.h"
 #include "core/math_helper.hpp"
 #include "core/imgui_utility.hpp"
+#include "module/guidance/cursor_guide.h"
 
 #include <glm/gtc/matrix_transform.hpp>
 #include <glm/gtc/type_ptr.hpp>
@@ -86,6 +87,7 @@ glm::mat4 camera_augment_helper_v2::impl::fixed_info_type::extra_transform() con
 
 camera_augment_helper_v2::impl::impl(const create_config &conf) {
     manager = conf.manager;
+    act_guide = conf.act_guide;
     sophiar_conn = conf.sophiar_conn;
     ctx = conf.ctx;
 
@@ -262,8 +264,10 @@ void camera_augment_helper_v2::impl::show_fixed() {
 
 void camera_augment_helper_v2::impl::show() {
     ImGui::Checkbox("Ignore Missing", &ui->ignore_missing); // TODO: enable sync with another
-    ImGui::SameLine();
-    ImGui::Checkbox("Guidance", &ui->enable_active_guide);
+    if (allow_active_guide) {
+        ImGui::SameLine();
+        ImGui::Checkbox("Guidance", &ui->enable_active_guide);
+    }
     ImGui::SliderFloat("Clip Near", &ui->near, 1.0f, ui->far, "%.f", ImGuiSliderFlags_Logarithmic);
     ImGui::SliderFloat("Clip Far", &ui->far, ui->near, 10000.0f, "%.f", ImGuiSliderFlags_Logarithmic);
 
@@ -277,6 +281,11 @@ void camera_augment_helper_v2::impl::show() {
             RET_ERROR;
         }
     }
+
+    if (ui->enable_active_guide) {
+        ImGui::SeparatorText("Cursor Guidance");
+        act_guide->show();
+    }
 }
 
 std::optional<glm::vec3> camera_augment_helper_v2::impl::
@@ -304,30 +313,40 @@ get_cursor_coordinate(glm::vec2 s_pos) {
 
 void camera_augment_helper_v2::impl::pre_render_slot(const scene_ptr &info) {
     if (ui->enable_active_guide && allow_active_guide) {
-        auto s_pos = ImGui::GetMousePos();
         auto rec_info = scene_render_info::custom_info{
-                .func = [=, this] {
+                .func = [this] {
                     if (manager->get_current_camera_helper() != q_this) {
                         return; // not current camera helper
                     }
-                    auto w_pos = get_cursor_coordinate(to_vec2(s_pos));
-                    act_guide.update({.position = w_pos});
-                },
-        };
-        info->items.push_back({.info = rec_info});
-        act_guide.pre_render_slot(info);
-    }
 
-    if (enable_passive_guide) {
-        auto rec_info = scene_render_info::custom_info{
-                .func = [=, this] {
-                    auto w_pos = get_cursor_coordinate(pas_info.pos);
-                    pas_guide.update({.position = w_pos});
+                    auto s_pos = ImGui::GetMousePos();
+                    auto info = cursor_guide::guide_info{
+                            .position = get_cursor_coordinate(to_vec2(s_pos))
+                    };
+                    auto &io = ImGui::GetIO();
+                    if (!io.WantCaptureMouse) {
+                        info.mouse_left = io.MouseClicked[ImGuiMouseButton_Left];
+                        info.mouse_right = io.MouseClicked[ImGuiMouseButton_Right];
+                        info.mouse_wheel = io.MouseWheel;
+                    }
+                    act_guide->update(info);
                 },
         };
         info->items.push_back({.info = rec_info});
-        pas_guide.pre_render_slot(info);
+        act_guide->pre_render_slot(info);
     }
+
+    // TODO: not implemented
+//    if (enable_passive_guide) {
+//        auto rec_info = scene_render_info::custom_info{
+//                .func = [=, this] {
+//                    auto w_pos = get_cursor_coordinate(pas_info.pos);
+//                    pas_guide.update({.position = w_pos});
+//                },
+//        };
+//        info->items.push_back({.info = rec_info});
+//        pas_guide.pre_render_slot(info);
+//    }
 }
 
 camera_augment_helper_v2::camera_augment_helper_v2(const create_config &conf)

+ 2 - 4
src/module/impl/camera_augment_helper_v2_impl.h

@@ -3,7 +3,6 @@
 
 #include "module/camera_augment_helper_v2.h"
 #include "module/viewport_downloader.hpp"
-#include "module/guidance/cursor_guide.h"
 
 struct camera_augment_helper_v2::impl {
 
@@ -14,7 +13,6 @@ struct camera_augment_helper_v2::impl {
     bool is_missing = false;
 
     augment_manager_v2 *manager = nullptr;
-    using sophiar_conn_type = create_config::sophiar_conn_type;
     sophiar_conn_type *sophiar_conn = nullptr;
     using io_context = boost::asio::io_context;
     io_context *ctx = nullptr;
@@ -102,12 +100,12 @@ struct camera_augment_helper_v2::impl {
 
     // active guidance
     bool allow_active_guide = false;
-    cursor_guide act_guide;
+    cursor_guide *act_guide;
 
     // passive guidance
     bool enable_passive_guide = false;
     guide_info pas_info;
-    cursor_guide pas_guide;
+//    cursor_guide pas_guide;
 
     explicit impl(const create_config &conf);