生活随笔
收集整理的這篇文章主要介紹了
arcball原理 旋转视图 关键点总结 及代码
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
旋轉(zhuǎn)軸
arcball原理前期計算是在相機視角下,所以計算出來的旋轉(zhuǎn)軸也在相機視角下,所以要把旋轉(zhuǎn)軸向量變換到世界坐標系。變換步驟:假設旋轉(zhuǎn)軸是一個過相機坐標系原點的單位向量(也可以看做一個坐標點),利用view矩陣的逆矩陣將這個坐標點變換到世界坐標系中,得到新的坐標點然后減去世界坐標系中相機的位置(相機坐標系的原點),就可以得到世界坐標系中的旋轉(zhuǎn)軸。
世界坐標系中的上向量
當使用lookAt函數(shù)的時候需要一個世界坐標系的上向量,很多教程給的(0,1,0)向量,但是如果一直使用這個向量,當利用arcball原理旋轉(zhuǎn)視圖的時候,由于叉乘原理相機坐標系會在相機處于世界坐標系Z軸原點附近發(fā)生突變,這會使視圖旋轉(zhuǎn)出現(xiàn)錯誤。所以需要在相機旋轉(zhuǎn)的時候保持更新這個上向量,更新方法很簡單,始終讓這個上向量和方向向量保持90度就可以,具體做法和上面類似。
之前的博文基礎:
https://blog.csdn.net/weixin_42376458/article/details/104481641?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159178073819725222460919%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=159178073819725222460919&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_blog_v1-1-104481641.pc_v2_rank_blog_v1&utm_term=arcball
代碼 (Qt代碼)(這套代碼無誤可行)
完整的程序可見github:
https://github.com/chenandongtime/OpenGL/tree/master/HelloTriange
#ifndef CAMERA_H
#define CAMERA_H#include <QObject>
#include<QMatrix4x4>
#include<QVector3D>
#include<QVector4D>
#include<math.h>class camera : public QObject
{Q_OBJECT
public:camera(QObject
*parent
,QVector3D camPosition
);
private:QVector3D position
; QVector3D target
; QVector3D worldUp
; QMatrix4x4 view
; QMatrix4x4 worldM
; float sensitivity
;
public:QMatrix4x4
getView();void rotateCamera(float xOffset
,float yOffset
);QMatrix4x4
getWorldRotateM(QVector3D axis
,float theta
);void scale(float scalef
);void translateWorldM(float xOffset
,float yOffset
);QMatrix4x4
getWorldM();signals
:};#endif
#include "camera.h"
#include <QDebug>
camera
::camera(QObject
*parent
,QVector3D camPosition
) : QObject(parent
),position(camPosition
)
{this->target
= QVector3D(0,0,0);this->worldUp
= QVector3D(0,1,0);this->view
= this->getView();this->sensitivity
= 3.0;this->worldM
= QMatrix4x4();
}QMatrix4x4 camera
::getView()
{QMatrix4x4 Identiy
;Identiy
.lookAt(this->position
,this->target
,this->worldUp
); view
= Identiy
;return view
;
}void camera
::rotateCamera(float xOffset
, float yOffset
)
{xOffset
= xOffset
* sensitivity
;yOffset
= yOffset
* sensitivity
;QVector3D
BallCenter(0,0,-1); QVector3D
pointOne(0,0,0);float zOffset
= sqrt((1 - xOffset
* xOffset
- yOffset
* yOffset
)) - 1;QVector3D
pointTwo(xOffset
,yOffset
,zOffset
);QVector3D
vecOne(pointOne
- BallCenter
);QVector3D
vecTwo(pointTwo
- BallCenter
);QVector3D axisView
= QVector3D
::crossProduct(vecOne
,vecTwo
); axisView
.normalize();QVector4D axisWorld4D
= this->view
.inverted() * QVector4D(axisView
[0],axisView
[1],axisView
[2],1); QVector3D axisWorld
= QVector3D(axisWorld4D
[0] - this->position
[0],axisWorld4D
[1] - this->position
[1],axisWorld4D
[2] - this->position
[2]);axisWorld
.normalize();float theta
= acos(QVector3D
::dotProduct(vecOne
,vecTwo
));QMatrix4x4 worldRotateM
= this->getWorldRotateM(axisWorld
,theta
);this->position
= worldRotateM
* this->position
;QVector4D worldUpTemp
= QVector4D(0,1,0,1);worldUpTemp
= this->view
.inverted() * worldUpTemp
; worldUpTemp
= worldRotateM
* worldUpTemp
; QVector3D worldUpPos
= QVector3D(worldUpTemp
[0],worldUpTemp
[1],worldUpTemp
[2]);this->worldUp
= worldUpPos
- this->position
;
}QMatrix4x4 camera
::getWorldRotateM(QVector3D axis
, float theta
)
{if(axis
.length() == 0) {QMatrix4x4 Identiy
;return Identiy
;}QMatrix4x4 Trans
;Trans(0,3) = -this->target
[0];Trans(1,3) = -this->target
[1];Trans(2,3) = -this->target
[2];
float cosA
;float sinA
;float u
= sqrt(axis
[1]*axis
[1]+axis
[2]*axis
[2]);if( u
< 0.001) {cosA
= 1;sinA
= 0;}else{cosA
= axis
[2] / u
;sinA
= axis
[1] / u
;}QMatrix4x4 rotateToXZ
;rotateToXZ(1,1) = cosA
;rotateToXZ(2,1) = sinA
;rotateToXZ(1,2) = -sinA
;rotateToXZ(2,2) = cosA
;float v
= sqrt(u
*u
+ axis
[0]*axis
[0]);float cosB
= u
/ v
;float sinB
= axis
[0] / v
;QMatrix4x4 rotateToZ
;rotateToZ(0,0) = cosB
;rotateToZ(0,2) = -sinB
;rotateToZ(2,0) = sinB
;rotateToZ(2,2) = cosB
;QMatrix4x4 rotateTheta
;rotateTheta(0,0) = cos(theta
);rotateTheta(0,1) = -sin(theta
);rotateTheta(1,0) = sin(theta
);rotateTheta(1,1) = cos(theta
);QMatrix4x4 worldRotateM
= Trans
.inverted() * rotateToXZ
.inverted() * rotateToZ
.inverted() * rotateTheta
*rotateToZ
* rotateToXZ
* Trans
;return worldRotateM
;
}void camera
::scale(float scalef
)
{if(scalef
<= 0) return;this->position
= this->position
* sqrt(scalef
);
}void camera
::translateWorldM(float xOffset
, float yOffset
)
{QVector4D
TransInView(xOffset
,yOffset
,0,1);QVector4D TransInWorld
= this->view
.inverted() * TransInView
- QVector4D(position
[0],position
[1],position
[2],1);float TransDis
= sqrt(this->position
.length())/2;TransInWorld
= TransInWorld
* TransDis
;this->worldM(0,3) += TransInWorld
.x() * TransDis
;this->worldM(1,3) += TransInWorld
.y() * TransDis
;this->worldM(2,3) += TransInWorld
.z() * TransDis
;
}QMatrix4x4 camera
::getWorldM()
{return this->worldM
;
}
總結(jié)
以上是生活随笔為你收集整理的arcball原理 旋转视图 关键点总结 及代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。