91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

OpenGL進階(十四) - UVN Camera實現

發布時間:2020-10-14 09:07:08 來源:網絡 閱讀:1371 作者:拳四郎 欄目:開發技術

提要

      3D游戲中最基本的一個功能就是3D漫游了,玩家可以通過鍵盤或者鼠標控制自己的視角。

      之前我們也學習過一個相關的函數,glLookAt,用來制定攝像機的位置,攝像機觀察目標位置,還有攝像機的放置方式,我們可以通過不斷地調用這個函數來實現3D漫游,但更方便的是抽象出一個攝像機類,實現一些攝像機的方法。


UVN相機

UVN使用三個相互垂直的向量來表示相機的位置與朝向:

1) 相機注視的向量N
2) 相機的上方向向量V
3) 相機的右方向向量U

如下圖,是在世界坐標系下的UVN相機的向量表示:

OpenGL進階(十四) - UVN Camera實現


綠色軸為N,藍色軸為V,紅色軸為U。

當要改變相機位置和朝向的時候,只需要將uvn矩陣和相應的變換矩陣相乘即可。


代碼實現

這里借助了一個第三方矩陣向量庫 - eigen。Ubuntu下的安裝的過程非常簡單,下載源碼之后,解壓,cd進目錄:

mkdir build
cd build 
cmake ..
sudo make install


寫一個頭文件:

eigen.h

#ifndef EIGEN_H #define EIGEN_H  #include "eigen3/Eigen/Dense" #include "eigen3/Eigen/LU" #include "eigen3/Eigen/Core"  #endif // EIGEN_H 

放在工程目錄下面,使用的時候包含進來就可以了。


看類聲明:glcamera.h

#ifndef GLCAMERA_H #define GLCAMERA_H #include "eigen.h" #include <GL/glu.h> #include <iostream>  using namespace Eigen; class GLCamera { public:     GLCamera();     GLCamera(const Vector3d& pos, const Vector3d& target, const Vector3d& up);     void setModelViewMatrix();     void setShape(float viewAngle,float aspect,float Near,float Far);     void slide(float du, float dv, float dn);     void roll(float angle);     void yaw(float angle);     void pitch(float angle);     float getDist();  private:     Vector3d m_pos;     Vector3d m_target;     Vector3d m_up;     Vector3d u,v,n;  };  #endif // GLCAMERA_H 

setModelViewMatrix:加載將當前MV矩陣。

setShape:設置攝像機的視角。

roll,yaw,pitch相當于繞N,V,U軸的旋轉,如下圖:

OpenGL進階(十四) - UVN Camera實現


下面是相機的實現:

#include "glcamera.h"  GLCamera::GLCamera() {  }  GLCamera::GLCamera(const Vector3d &pos, const Vector3d &target, const Vector3d &up) {     m_pos = pos;     m_target = target;     m_up = up;     n = Vector3d( pos.x()-target.x(), pos.y()-target.y(), pos.z()-target.z());     u = Vector3d(up.cross(n).x(), up.cross(n).y(), up.cross(n).z());     v = Vector3d(n.cross(u).x(),n.cross(u).y(),n.cross(u).z());       n.normalize();     u.normalize();     v.normalize();      setModelViewMatrix(); }  void GLCamera::setModelViewMatrix() {     double m[16];     m[0]=u.x(); m[4]=u.y(); m[8]=u.z(); m[12]=-m_pos.dot(u);     m[1]=v.x(); m[5]=v.y(); m[9]=v.z(); m[13]=-m_pos.dot(v);     m[2]=n.x(); m[6]=n.y(); m[10]=n.z(); m[14]=-m_pos.dot(n);     m[3]=0;  m[7]=0;  m[11]=0;  m[15]=1.0;     glMatrixMode(GL_MODELVIEW);     glLoadMatrixd(m);     //用M矩陣替換原視點矩陣 }  void  GLCamera::setShape(float viewAngle, float aspect, float Near, float Far) {     glMatrixMode(GL_PROJECTION);     glLoadIdentity();                                   //設置當前矩陣模式為投影矩陣并歸一化     gluPerspective(viewAngle,aspect, Near, Far);        //對投影矩陣進行透視變換 }  void GLCamera::slide(float du, float dv, float dn) {     //std::cout<<"u.x:"<<u.x()<<std::endl;     m_pos(0) = m_pos(0) + du*u.x()+dv*v.x()+dn*n.x();     m_pos(1) = m_pos(1) + du*u.y() +dv*v.y()+dn*n.y();     m_pos(2) = m_pos(2) + du*u.z()+dv*v.z()+dn*n.z();     m_target(0) = m_target(0)+du*u.x()+dv*v.x()+dn*n.x();     m_target(1) = m_target(0)+du*u.y()+dv*v.y()+dn*n.y();     m_target(2) = m_target(0)+du*u.z()+dv*v.z()+dn*n.z();     setModelViewMatrix(); }  void GLCamera::roll(float angle) {     float cs=cos(angle*3.14159265/180);     float sn=sin(angle*3.14159265/180);     Vector3d t(u);     Vector3d s(v);     u.x() = cs*t.x()-sn*s.x();     u.y() = cs*t.y()-sn*s.y();     u.z() = cs*t.z()-sn*s.z();      v.x() = sn*t.x()+cs*s.x();     v.y() = sn*t.y()+cs*s.y();     v.z() = sn*t.z()+cs*s.z();      setModelViewMatrix();          //每次計算完坐標軸變化后調用此函數更新視點矩陣 }  void GLCamera::pitch(float angle) {     float cs=cos(angle*3.14159265/180);     float sn=sin(angle*3.14159265/180);     Vector3d t(v);     Vector3d s(n);      v.x() = cs*t.x()-sn*s.x();     v.y() = cs*t.y()-sn*s.y();     v.z() = cs*t.z()-sn*s.z();      n.x() = sn*t.x()+cs*s.x();     n.y() = sn*t.y()+cs*s.y();     n.z() = sn*t.z()+cs*s.z();       setModelViewMatrix(); }  void GLCamera::yaw(float angle) {     float cs=cos(angle*3.14159265/180);     float sn=sin(angle*3.14159265/180);     Vector3d t(n);     Vector3d s(u);      n.x() = cs*t.x()-sn*s.x();     n.y() = cs*t.y()-sn*s.y();     n.z() = cs*t.z()-sn*s.z();      u.x() = sn*t.x()+cs*s.x();     u.y() = sn*t.y()+cs*s.y();     u.z() = sn*t.z()+cs*s.z();      setModelViewMatrix(); }  float  GLCamera::getDist() {     float dist = pow(m_pos.x(),2)+pow(m_pos.y(),2)+pow(m_pos.z(),2);     return pow(dist,0.5); } 


沒什么好說的,都是矩陣的一些計算。

這樣就可以將你的攝像機融入到OpenGL工程中了,比如說放進一個Qt的工程,用一個GLWifget類來顯示OpenGL。

在initializeGL() 中,初始化camera

  Vector3d pos(0.0, 0.0, 12.0);     Vector3d target(0.0, 0.0, 0.0);     Vector3d up(0.0, 1.0, 0.0);     camera = new GLCamera(pos, target, up); 

在paintGL的時候,設置當前矩陣:

 glLoadIdentity();     camera->setModelViewMatrix(); 

在resizeGL中調整視角:

camera->setShape(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);

添加相應的鼠標事件:

void GLWidget::mousePressEvent(QMouseEvent *event) {     lastPos = event->pos(); }  void GLWidget::mouseMoveEvent(QMouseEvent *event) {     int dx = event->x() - lastPos.x();     int dy = event->y() - lastPos.y();     if (event->buttons() & Qt::LeftButton)     {         RotateX(dx);         RotateY(dy);     }     else if(event->buttons() & Qt::RightButton)     {         camera->roll(dx);         //camera->pitch(dy);         //camera->slide(0,0,-dy);     }     else if(event->buttons() & Qt::MiddleButton)     {         camera->slide(-dx,dy,0);     }     lastPos = event->pos();     updateGL(); }  void GLWidget::RotateX(float angle) {     float d=camera->getDist();     int cnt=100;     float theta=angle/cnt;     float slide_d=-2*d*sin(theta*3.14159265/360);     camera->yaw(theta/2);     for(;cnt!=0;--cnt)     {         camera->slide(slide_d,0,0);         camera->yaw(theta);     }     camera->yaw(-theta/2); }  void GLWidget::RotateY(float angle) {     float d = camera->getDist();     int cnt=100;     float theta=angle/cnt;     float slide_d=2*d*sin(theta*3.14159265/360);     camera->pitch(theta/2);     for(;cnt!=0;--cnt)     {         camera->slide(0,slide_d,0);         camera->pitch(theta);     }     camera->pitch(-theta/2); } 

效果就像這樣(gif 有點大,耐心等待):

OpenGL進階(十四) - UVN Camera實現


參考

openGL中camera類的設計以及使用 - http://blog.csdn.net/hobbit1988/article/details/7956838

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vn uv
AI

体育| 平果县| 安塞县| 攀枝花市| 青浦区| 陵川县| 内黄县| 山东省| 乃东县| 布尔津县| 务川| 昌都县| 綦江县| 堆龙德庆县| 大渡口区| 江口县| 乌兰县| 旅游| 女性| 思茅市| 宝应县| 海安县| 射阳县| 潮州市| 西华县| 容城县| 廉江市| 军事| 新余市| 丘北县| 蒲城县| 盐池县| 蓬莱市| 新兴县| 台安县| 棋牌| 彭阳县| 柘荣县| 上思县| 武功县| 六枝特区|