bool mouse_move()

in code/cpp/tools/scene_annotation_tool/main.cpp [2521:2629]


bool mouse_move(igl::opengl::glfw::Viewer& viewer, int mouse_x, int mouse_y) {

    int width_window, height_window;
    glfwGetFramebufferSize(viewer.window, &width_window, &height_window);

    if (g_mouse_rotation || g_mouse_translation || g_mouse_drawing) {
        g_mouse_prev_x = g_mouse_curr_x;
        g_mouse_prev_y = g_mouse_curr_y;
        g_mouse_curr_x = mouse_x;
        g_mouse_curr_y = mouse_y;
        if (g_mouse_ignore_counter > 0) {
            g_mouse_ignore_counter--;
        }
    }

    if (g_mouse_prev_x >= 0 && g_mouse_prev_x < width_window && g_mouse_prev_y >= 0 && g_mouse_prev_y < height_window &&
        g_mouse_curr_x >= 0 && g_mouse_curr_x < width_window && g_mouse_curr_y >= 0 && g_mouse_curr_y < height_window &&
        g_mouse_ignore_counter == 0) {

        if (g_mouse_rotation) {

            auto p_x_curr = ((2.0*g_mouse_curr_x) / width_window)  - 1.0;
            auto p_x_prev = ((2.0*g_mouse_prev_x) / width_window)  - 1.0;
            auto p_y_curr = ((2.0*g_mouse_curr_y) / height_window) - 1.0;
            auto p_y_prev = ((2.0*g_mouse_prev_y) / height_window) - 1.0;

            Eigen::Vector3f camera_eye_curr_;
            Eigen::Vector3f camera_rotation_axis_;
            Eigen::Vector3f camera_eye_next_;

            // horizontal rotation
            auto theta_curr  = std::acos(std::min(std::max(p_x_curr,-1.0),1.0));
            auto theta_prev  = std::acos(std::min(std::max(p_x_prev,-1.0),1.0));
            auto theta_delta = theta_curr - theta_prev;

            camera_eye_curr_      = viewer.core().camera_eye - viewer.core().camera_center;
            camera_rotation_axis_ = Eigen::Vector3f::UnitZ();
            camera_eye_next_      = Eigen::AngleAxisf(theta_delta, camera_rotation_axis_).toRotationMatrix()*camera_eye_curr_;
            viewer.core().camera_eye = viewer.core().camera_center + camera_eye_next_;

            // vertical rotation
            camera_eye_curr_ = viewer.core().camera_eye - viewer.core().camera_center;
            Eigen::Vector3f camera_eye_curr_norm = camera_eye_curr_ / camera_eye_curr_.norm();
            auto gamma = std::acos(std::min(std::max(camera_eye_curr_norm.dot(Eigen::Vector3f::UnitZ()),-1.0f),1.0f)); // angle between center-to-eye and up

            auto alpha_curr  = std::acos(std::min(std::max(p_y_curr,-1.0),1.0));
            auto alpha_prev  = std::acos(std::min(std::max(p_y_prev,-1.0),1.0));
            auto alpha_delta = alpha_curr - alpha_prev;

            auto eps = 1.0*(igl::PI/180.0); // maintain minimum angle between center-to-eye and poles
            auto alpha_delta_ = 0.0;

            if (alpha_delta < 0.0) {
                alpha_delta_ = std::min(std::max(alpha_delta, eps-gamma), 0.0); // always keep eye least eps away from north pole, most of the time this term is alpha_delta
            }
            if (alpha_delta > 0.0) {
                alpha_delta_ = std::min(std::max(alpha_delta, 0.0), igl::PI-gamma-eps); // always keep eye at least eps away from south pole, most of the time this term is alpha_delta
            }

            camera_rotation_axis_ = camera_eye_curr_.cross(Eigen::Vector3f::UnitZ()) / camera_eye_curr_.cross(Eigen::Vector3f::UnitZ()).norm();
            camera_eye_next_      = Eigen::AngleAxisf(-alpha_delta_, camera_rotation_axis_).toRotationMatrix()*camera_eye_curr_;
            viewer.core().camera_eye = viewer.core().camera_center + camera_eye_next_;
        }

        if (g_mouse_translation) {

            Eigen::Vector3f camera_look_at_dir;
            Eigen::Vector3f camera_right_dir;
            Eigen::Vector3f camera_up_dir;
            float camera_look_at_dist;

            auto fov_y = viewer.core().camera_view_angle * (igl::PI/180.0);
            auto fov_x = 2.0 * std::atan(width_window * std::tan(fov_y/2.0) / height_window);

            // horizontal translation
            camera_look_at_dir  = (viewer.core().camera_center - viewer.core().camera_eye) / (viewer.core().camera_center - viewer.core().camera_eye).norm();
            camera_right_dir    = camera_look_at_dir.cross(Eigen::Vector3f::UnitZ()) / camera_look_at_dir.cross(Eigen::Vector3f::UnitZ()).norm();
            camera_look_at_dist = (viewer.core().camera_center - viewer.core().camera_eye).norm();

            auto mouse_delta_x = g_mouse_curr_x - g_mouse_prev_x;
            auto delta_x       = -(mouse_delta_x / (width_window/2.0))*std::tan(fov_x/2.0)*camera_look_at_dist;
            auto delta_x_      = delta_x;

            viewer.core().camera_eye    = viewer.core().camera_eye    + delta_x_*camera_right_dir;
            viewer.core().camera_center = viewer.core().camera_center + delta_x_*camera_right_dir;

            // vertical translation
            camera_look_at_dir  = (viewer.core().camera_center - viewer.core().camera_eye) / (viewer.core().camera_center - viewer.core().camera_eye).norm();
            camera_right_dir    = camera_look_at_dir.cross(Eigen::Vector3f::UnitZ()) / camera_look_at_dir.cross(Eigen::Vector3f::UnitZ()).norm();
            camera_up_dir       = -(camera_look_at_dir.cross(camera_right_dir) / camera_look_at_dir.cross(camera_right_dir).norm());
            camera_look_at_dist = (viewer.core().camera_center - viewer.core().camera_eye).norm();

            auto mouse_delta_y = g_mouse_curr_y - g_mouse_prev_y;
            auto delta_y       = (mouse_delta_y / (height_window/2.0))*std::tan(fov_y/2.0)*camera_look_at_dist;
            auto delta_y_      = delta_y;

            viewer.core().camera_eye    = viewer.core().camera_eye    + delta_y_*camera_up_dir;
            viewer.core().camera_center = viewer.core().camera_center + delta_y_*camera_up_dir;
        }

        if (g_mouse_drawing) {
            if (mouse_x >= 0 && mouse_x < width_window && mouse_y >= 0 && mouse_y < height_window) {
                g_mouse_drawing_positions.push_back({mouse_x, mouse_y});
            }
        }
    }

    return true;
}