日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

arcball 鼠标 相机转动

發(fā)布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 arcball 鼠标 相机转动 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

利用arcball原理來是相機在某個半徑旋轉(zhuǎn),而且相機的目標(biāo)方向永遠指向最初的目標(biāo)方向,就是類似于相機在球面上旋轉(zhuǎn)并且始終指向球心。
直接上程序流圖和代碼。

arcball原理還有相關(guān)的旋轉(zhuǎn)矩陣在上一篇文章有介紹:這里
程序流圖:

主函數(shù):/*arcBallRotate 函數(shù)說明:給定單位化后,鼠標(biāo)在屏幕上的偏移量,計算在arcball原理下,相機實際位置的變換,并改變相機的實際位置參數(shù)說明:double x : x方向偏移量double y : y方向便宜量*/ void Camera::arcBallRotate(double x, double y) {//創(chuàng)建在相機坐標(biāo)系下的旋轉(zhuǎn)軸和旋轉(zhuǎn)角度arma::vec3 axisVec;double theta;arcball(x, y, axisVec, theta);//計算世界坐標(biāo)系下的旋轉(zhuǎn)軸arma::vec3 worldAxis = cameraToWorldCoord(axisVec);//構(gòu)建世界坐標(biāo)系的坐標(biāo)系Axis axis;axis.position = target;axis.direction = worldAxis;//在世界坐標(biāo)系下旋轉(zhuǎn)theta角,并得到新的相機位置this->position = this->axisRotateTheta(axis, theta, position); } /* arcball 函數(shù)說明:在單位化下,計算屏幕中鼠標(biāo)移動的偏移量,在單位球上產(chǎn)生的位置變換,并且用旋轉(zhuǎn)軸和旋轉(zhuǎn)角表示參數(shù)說明:double x 范圍輸入0.0 - 1.0;表示在相機坐標(biāo)系下x方向偏移量double y 范圍輸入0.0 - 1.0;表示在相機坐標(biāo)系下y方向的偏移量arma::vec3 &axisVec 經(jīng)過計算后返回的旋轉(zhuǎn)軸方向向量,如果計算失敗返回的就是輸入值double &thete 經(jīng)過計算后旋轉(zhuǎn)的角度,若計算失敗返回輸入值函數(shù)返回值說明:如果返回true,則表示計算成功,否則表示計算失敗*/ bool Camera::arcball(double x, double y, arma::vec3& axisVec, double& theta) { //檢查x的范圍是否符合要求if ((x > 1.0) || (x < -1.0)){return false;}//檢查y的范圍是否符合要求if ((y > 1.0) || (y < -1.0)){return false;}double z = sqrt((1 - x * x - y * y));//arcball原理計算Zarma::vec3 startPoint({ 0.0,0.0,1.0 });//相機在相機坐標(biāo)系下鼠標(biāo)移動前的位置arma::vec3 endPoint({x,y,z});//相機在相機坐標(biāo)系下鼠標(biāo)移動后的位置axisVec = arma::normalise(arma::cross(startPoint, endPoint));//得到歸一化的叉乘向量,也即旋轉(zhuǎn)軸向量theta = acos(arma::norm_dot(startPoint, endPoint));return true; }/* cameraToWorldCoord 函數(shù)說明:將相機坐標(biāo)系中的點,向量,轉(zhuǎn)化到世界坐標(biāo)系中去。參數(shù)說明:const arma::vec3& position: 相機坐標(biāo)系中的點或者向量函數(shù)返回值說明:轉(zhuǎn)化后世界坐標(biāo)系中的點或者向量*/ arma::vec3 Camera::cameraToWorldCoord(const arma::vec3& position) {//獲得模型視圖轉(zhuǎn)化矩陣//由于opengl的模型視圖矩陣按列保存,所以需要做個轉(zhuǎn)換float m[16];glGetFloatv(GL_MODELVIEW_MATRIX, m);//獲得模型矩陣并且保存在m中,這個矩陣可能有問題,實際上應(yīng)該獲取的是相機變換矩陣View 而不是世界變換矩陣和相機變換矩陣的和矩陣。//將m保存的數(shù)據(jù)轉(zhuǎn)換到modviewMat中,將按列存儲的數(shù)據(jù)變成按行存儲的數(shù)據(jù)arma::Mat<double> ModviewMat(4, 4);for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++){ModviewMat(j, i) = m[i * 4 + j];}//先將數(shù)據(jù)轉(zhuǎn)存到Mat中去 arma::Mat<double> originPosition(1, 4);originPosition(0, 0) = position[0];originPosition(0, 1) = position[1];originPosition(0, 2) = position[2];originPosition(0, 3) = 1.0;arma::Mat<double> newPosition(1, 4);newPosition = originPosition * arma::inv(ModviewMat);//通過逆矩陣計算新的坐標(biāo)****關(guān)鍵計算*****arma::vec3 worldPositon({ newPosition(0, 0), newPosition(0, 1), newPosition(0, 2) });//將數(shù)據(jù)轉(zhuǎn)存到Vec中return worldPositon; } /*axisRotateTheta 函數(shù)說明:使相機位置 繞給定的旋轉(zhuǎn)軸 旋轉(zhuǎn)給定的角度。參數(shù)說明:cosnt Axis & axis: 旋轉(zhuǎn)坐標(biāo)軸double theta :旋轉(zhuǎn)角度值, 正值為右手螺旋,負值為左手螺旋函數(shù)返回值:旋轉(zhuǎn)后的坐標(biāo)*/ arma::vec Camera::axisRotateTheta(const Axis& axis, double theta, const arma::vec3& origin) {/*繞任意軸旋轉(zhuǎn)有7步*///step 1 :計算平移矩陣arma::Mat<double> Trans(4, 4,arma::fill::eye);Trans(3, 0) = 0 - axis.position[0];Trans(3, 1) = 0 - axis.position[1];Trans(3, 2) = 0 - axis.position[2];//計算使其繞X軸旋轉(zhuǎn)并落入XOZ平面內(nèi)的矩陣double u = sqrt(axis.direction[1] * axis.direction[1] + axis.direction[2] * axis.direction[2]);double cosA;double sinA;if (u == 0.0) //注意判斷U等于0的特殊情況{cosA = 1.0;sinA = 0.0;}cosA = ((double)axis.direction[2]) / u;sinA = ((double)axis.direction[1]) / u;arma::Mat<double> RotateX(4, 4, arma::fill::eye);RotateX(1, 1) = cosA;RotateX(1, 2) = sinA;RotateX(2, 1) = -sinA;RotateX(2, 2) = cosA;//計算繞y軸旋轉(zhuǎn)B角,使其與Z軸重合double v = sqrt(u * u + axis.direction[0] * axis.direction[0]);double cosB = u / v;double sinB = axis.direction[0] / v;arma::Mat<double> RotateY(4, 4, arma::fill::eye);RotateY(0, 0) = cosB;RotateY(0, 2) = sinB;RotateY(2, 0) = -sinB;RotateY(2, 2) = cosB;//繞Z軸旋轉(zhuǎn)theta角arma::Mat<double> RotateTheta(4, 4, arma::fill::eye);RotateTheta(0, 0) = cos(theta);RotateTheta(0, 1) = sin(theta);RotateTheta(1, 0) = -sin(theta);RotateTheta(1, 1) = cos(theta);//將當(dāng)前坐標(biāo)乘以組合矩陣arma::Mat<double> originP(1, 4);originP(0, 0) = origin[0];originP(0, 1) = origin[1];originP(0, 2) = origin[2];originP(0, 3) = 1;arma::Mat<double> newP = originP * Trans * RotateX * RotateY * RotateTheta* arma::inv(RotateY) * arma::inv(RotateX) * arma::inv(Trans);//返回變換后的坐標(biāo)return arma::vec({newP(0,0),newP(0,1),newP(0,2)}); }

完整的camera頭文件

#ifndef __CAMERA__ #define __CAMERA__#include <armadillo>struct Axis {arma::vec3 direction;//旋轉(zhuǎn)軸方向arma::vec3 position; //旋轉(zhuǎn)軸位置 };class Camera { public:Camera(const arma::vec3& position, const arma::vec3& target, const arma::vec3& upVec);~Camera() {}; public:void defineModelView();//確定視圖矩陣,必須在繪圖之前確定,每次繪圖之前應(yīng)該先調(diào)用void translateX(const double &x); //改變相機位置的X坐標(biāo)void translateY(const double &y); //改變相機位置的Y坐標(biāo)void translateZ(const double &z); //改變相機位置的Z坐標(biāo)void rotateY(const double& theta); //相機繞著y軸旋轉(zhuǎn)arma::vec3 getPosition()const { return position; } //返回相機位置坐標(biāo)信息/*arcBallRotate 函數(shù)說明:給定單位化后,鼠標(biāo)在屏幕上的偏移量,計算在arcball原理下,相機實際位置的變換,并改變相機的實際位置參數(shù)說明:double x : x方向偏移量double y : y方向便宜量*/void arcBallRotate(double x, double y);private:/* arcball 函數(shù)說明:在單位化下,計算屏幕中鼠標(biāo)移動的偏移量,在單位球上產(chǎn)生的位置變換,并且用旋轉(zhuǎn)軸和旋轉(zhuǎn)角表示參數(shù)說明:double x 范圍輸入0.0 - 1.0;表示在相機坐標(biāo)系下x方向偏移量double y 范圍輸入0.0 - 1.0;表示在相機坐標(biāo)系下y方向的偏移量arma::vec3 &axisVec 經(jīng)過計算后返回的旋轉(zhuǎn)軸方向向量,如果計算失敗返回的就是輸入值double &thete 經(jīng)過計算后旋轉(zhuǎn)的角度,若計算失敗返回輸入值函數(shù)返回值說明:如果返回true,則表示計算成功,否則表示計算失敗*/bool arcball(double x, double y, arma::vec3& axisVec, double& theta);/* cameraToWorldCoord 函數(shù)說明:將相機坐標(biāo)系中的點,向量,轉(zhuǎn)化到世界坐標(biāo)系中去。參數(shù)說明:const arma::vec3& position: 相機坐標(biāo)系中的點或者向量函數(shù)返回值說明:轉(zhuǎn)化后世界坐標(biāo)系中的點或者向量*/arma::vec3 cameraToWorldCoord(const arma::vec3& position);/*axisRotateTheta 函數(shù)說明:使相機位置 繞給定的旋轉(zhuǎn)軸 旋轉(zhuǎn)給定的角度。參數(shù)說明:cosnt Axis & axis: 旋轉(zhuǎn)坐標(biāo)軸double theta :旋轉(zhuǎn)角度值, 正值為右手螺旋,負值為左手螺旋函數(shù)返回值:旋轉(zhuǎn)后的坐標(biāo)*/arma::vec axisRotateTheta(const Axis& axis, double theta ,const arma::vec3 &origin);private:arma::vec3 position; //表示相機位置arma::vec3 target; //表示相機目標(biāo)arma::vec3 upVec;//表示上向量 };#endif // ! __CAMERA__

總結(jié)

以上是生活随笔為你收集整理的arcball 鼠标 相机转动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。