基于之前做的項目圖形移動處理-CSDN博客添加了相機,透視投影,鼠標控制圖形旋轉。雖然個人感覺這個項目用的是一個二維的三角形,給他加透視投影和相機意義不大,因為透視投影是近大遠小,我這個程序設置了放大縮小的限制,說實話,理論上加沒加看不出去別來,只是為了實踐一下,并且是通過鼠標讓三角形旋轉,也不需要再設置相機繞著三角形看不同角度,視覺上是一樣的。后面改用三維度圖形才會有區別。這里就講講相對于之前的項目新添加到功能吧。
三角形旋轉事件
我設計的這個是根據鼠標橫向/縱向移動,使得三角形繞y軸/x軸旋轉。
添加的成員變量
//旋轉參數QVector3D m_rotationangles;//三維向量,存放x,y,z軸旋轉角度bool m_isrotating;QPoint m_lastmousepos;
m_rotationangles | 是一個三維向量,里面存放著繞x,y,z軸旋轉的角度。 |
m_isrotating | 旋轉狀態 |
m_lastmousepos | 記錄上一次鼠標停留的坐標 |
在構造函數中初始化m_rotationangles為一個{0,0,0}的向量矩陣,m_isrotating為false
myWediget::myWediget(QWidget *parent) : QOpenGLWidget(parent) {setFocusPolicy(Qt::StrongFocus);m_rotationangles=QVector3D(0,0,0);//初始化為000m_isrotating=false;//初始化旋轉狀態
}
鼠標事件加入
我們設計他的邏輯是鼠標左鍵按下以后,m_lastmousepos會記錄鼠標的當前位置,然后鼠標拖動,用現在鼠標的位置-上次鼠標的位置得到的是一個移動路徑的向量,注意這里操作角度用的數據都是向量,然后更新旋轉矩陣{x,y,z},繞x軸正向旋轉就是m_rotationangles.x()+delta.y()*0.5f,為什么加的是delta的y,可以試著想一下,想讓三角形繞x軸旋轉不就是用鼠標向上向下移動。
//鼠標按下事件
void myWediget::mousePressEvent(QMouseEvent *event)
{if(event->button()==Qt::LeftButton){m_isrotating=true;//開始旋轉m_lastmousepos=event->pos();//獲取鼠標位置event->accept();}
}//鼠標松開事件
void myWediget::mouseReleaseEvent(QMouseEvent *event)
{if(event->button()==Qt::LeftButton){m_isrotating=false;event->accept();}
}//鼠標移動事件
void myWediget::mouseMoveEvent(QMouseEvent *event)
{if(m_isrotating){QPoint delta=event->pos()-m_lastmousepos;m_rotationangles.setX(m_rotationangles.x()+delta.y()*0.5f);//繞x軸旋轉m_rotationangles.setY(m_rotationangles.y()+delta.x()*0.5f);//繞y軸旋轉m_lastmousepos=event->pos();update();event->accept();}
}
把旋轉矩陣傳入繪制函數逐幀繪制,在原有基礎上加幾句就行了
transform.rotate(m_rotationangles.x(),1,0,0);
transform.rotate(m_rotationangles.y(),0,1,0);
transform.rotate(m_rotationangles.z(),0,0,1);
前面第一個參數是旋轉矩陣的對應軸的參數,后面是要繞哪個軸旋轉就把他設置為1,到這里功能就完成了,為啥沒設置shader,我之前的項目中transform就是專門用來處理三角形運動的uniform,之前是只有移動和縮放,縮放建議最后處理,不然有些問題。
透視投影和相機
另外兩個帶一嘴吧,透視投影是近大遠小的效果,繪畫讓三位圖形比較立體
//設置透視投影QMatrix4x4 projection;projection.perspective(45.0f,(float)w/h,0.1,100.0f);sdprogram.bind();sdprogram.setUniformValue("projection",projection);sdprogram.release();
? ? ?projection.perspective(45.0f,(float)w/h,0.1,100.0f);第一個參數是視角,可以理解為你眼睛張多大,第二個參數就是寬高比,推薦和屏幕或者視口一致,第三個最近離你多近,超過了就看不見了,第四個就是最遠離你有多遠,超出了就看不見了,就是模擬你眼睛。
再就是相機,相機 是有一個自己的坐標系的,鏡頭指向的方向是自己坐標系z軸的正方向
// 視圖矩陣(相機后移3單位)QMatrix4x4 view;view.translate(0, 0, -3.0f);
我這里就把他后移了三個單位,十分簡陋,因為設置了和沒設置沒區別,就懶得設置他了,我這是不是有些敷衍哈哈。
就這樣,程序大功告成,展示最終效果
?