基于OpenCASCADE自制三维建模软件(五)鼠标模式

鼠标控制模式用于三维空间可视化导航,通过鼠标的按键及少数键盘按键的组合,可以实现对三维视图的平移、缩放、选择等操作。

一、选择导航模式

由于之前使用过Blender,其鼠标的操作方式比较好用,因此这里使用Blender导航。Blender导航参照Blender的操作。以前需要SHIFT配合鼠标才能完成视图平移. 在2016年Blender增加了一个功能改变了这一情况。要平移视图,现在可以同时按下鼠标左键和鼠标右键并在视图中拖动。

在这里插入图片描述
在三维界面头文件中加入模式枚举,及添加鼠标操作相关成员:

//c3dwidget.h
class C3DWidget : public QWidget
{
	......
protected:
    //!三维场景转换模式
    enum CurrentAction3d
    {
        CurAction3d_Nothing,
        CurAction3d_DynamicPanning, //平移
        CurAction3d_DynamicZooming, //缩放
        CurAction3d_DynamicRotation //旋转
    };
protected:
    //!覆写键盘按键按下事件
    void keyPressEvent(QKeyEvent *event);
    //!覆写键盘按键释放事件
    void keyReleaseEvent(QKeyEvent *event);
    //!覆写鼠标按键按下事件
    void mousePressEvent(QMouseEvent *event);
    //!覆写鼠标按键释放事件
    void mouseReleaseEvent(QMouseEvent *event);
    //!覆写鼠标移动事件
    void mouseMoveEvent(QMouseEvent *event);
    //!覆写鼠标滚轮事件
    void wheelEvent(QWheelEvent *event);
private:
    Standard_Integer m_x_max;    //!记录鼠标平移坐标X
    Standard_Integer m_y_max;    //!记录鼠标平移坐标Y
    CurrentAction3d m_current_mode; //!三维场景转换模式
    bool m_shift_key_pressed;   //!记录Shift键是否被按下
    ......
};

二、平移

平移的方式有两种,通过if判断当前操作是否为平移方式的其中一种。其中一种需要加上SHIFT按键,则通过m_shift_key_pressed 变量判断SHIFT键是否被按下。

void C3DWidget::mousePressEvent(QMouseEvent *event)
{
    if( ((event->buttons() & Qt::MidButton) && (QApplication::keyboardModifiers()==Qt::ShiftModifier) )  //平移方式1
        ||((event->buttons()&Qt::LeftButton)&&(event->buttons()&Qt::RightButton)))//平移方式2
    {
        m_current_mode = CurAction3d_DynamicPanning;
        m_x_max = event->pos().x(); //记录起始X位置
        m_y_max = event->pos().y(); //记录起始Y位置
    }
    ......
}
void C3DWidget::mouseReleaseEvent(QMouseEvent *)
{
    m_current_mode = CurAction3d_Nothing;
}

void C3DWidget::mouseMoveEvent(QMouseEvent *event)
{
    switch (m_current_mode)
    {
    case CurAction3d_DynamicPanning:
        //执行平移
        m_view->Pan(event->pos().x() - m_x_max, m_y_max - event->pos().y());
        m_x_max = event->pos().x();
        m_y_max = event->pos().y();
        break;
    ......
    }
}

三、缩放

缩放通过V3d_View类的Zoom方法实现,Zoom方法的设计是通过相邻两次鼠标位置判断缩小或放大,以及缩放的程度。前两个参数为第一次鼠标的位置,后两个参数为第二次鼠标的位置。而滚动鼠标滚轮会Qt的wheelEvent事件,向上滚动和向下滚动event->angleDelta().y()会返回或正或负的数值,将此值模拟第二次鼠标的位置,实现三维界面缩放功能。

void C3DWidget::wheelEvent(QWheelEvent *event)
{
    m_view->Zoom(0, 0, event->angleDelta().y(), 0); //执行缩放
}

5月9日更新:原来的程序只在固定点缩放,作以下更改后,缩放跟随鼠标的位置进行。

void C3DWidget::wheelEvent(QWheelEvent *event)
{
    m_view->StartZoomAtPoint(event->pos().x(),event->pos().y());
    m_view->ZoomAtPoint(0, 0, event->angleDelta().y(), 0); //执行缩放
}

在这里插入图片描述


四、旋转

鼠标的中键按下时,通过V3d_View类的StartRotation方法记录起始位置。鼠标发生移动后,使用Rotation方法实现三维界面旋转。

void C3DWidget::mousePressEvent(QMouseEvent *event)
{
    if(......)//平移
    {......}
    else if(event->buttons() & Qt::MidButton)  //旋转
    {
        m_current_mode = CurAction3d_DynamicRotation;
        m_view->StartRotation(event->pos().x(), event->pos().y());
    }
    ......
}
void C3DWidget::mouseMoveEvent(QMouseEvent *event)
{
    switch (m_current_mode)
    {
    ......
    case CurAction3d_DynamicRotation:
        //执行旋转
        m_view->Rotation(event->pos().x(), event->pos().y());
        break;
    ......
    }
}

五、实际效果

在这里插入图片描述

项目仓库

https://github.com/Jelatine/JellyCAD

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片