基於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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章