Qt 3D OpenGL实现场景漫游实例

移动开发
本文介绍的是Qt3D OpenGL实现场景漫游实例,现在3D越来越流行了,要好还的研究。先来看内容。

Qt 3D OpenGL实现场景漫游实例是本文要介绍的内容,一个不错的OpenGL程序当然免不了对整个场景漫游。在我程序中便是用W、A、S、D来靠近,远离,向左,向右来移动场景,Q、E、Z、C则是旋转场景。同时,补充一条,我用鼠标滚轮实现了物体的放大和缩小,效果上和按W、S键是相同的,但本质上是有差别的,呵呵~

我要贴出的这个Camera类是从《OpenGL游戏编程》里提取出来的,并且已经在Qt环境下运行成功(本来代码是在VS2005)。

Camera.h内容:

  1. #ifndef __CAMERA_H__  
  2. #define __CAMERA_H__  
  3.  
  4. #include "Vector.h" /* 包含向量类头文件 */  
  5.  
  6. /* 摄像机类 */  
  7. class Camera  
  8. {  
  9. public:  
  10.  
  11.         /* 构造函数和析构函数 */  
  12.  Camera();  
  13.  ~Camera();  
  14.  
  15.         /* 获得摄像机状态方法 */  
  16.  Vector3 getPosition()   { return m_Position;  }  
  17.  Vector3 getView()     { return m_View;   }  
  18.  Vector3 getUpVector()   { return m_UpVector;  }  
  19.  float   getSpeed()      {   return m_Speed;         }  
  20.  
  21.         /* 设置速度 */  
  22.  void setSpeed(float speed)  
  23.  {  
  24.   m_Speed  = speed;  
  25.  }  
  26.  
  27.         /* 设置摄像机的位置, 观察点和向上向量 */  
  28.  void setCamera(float positionX, float positionY, float positionZ,  
  29.         float viewX,     float viewY,     float viewZ,  
  30.        float upVectorX, float upVectorY, float upVectorZ);  
  31.         /* 旋转摄像机方向 */  
  32.  void rotateView(float angle, float X, float Y, float Z);  
  33.         /* 根据鼠标设置摄像机观察方向 */  
  34.         void setViewByMouse();  
  35.         /* 左右摄像机移动 */  
  36.  void yawCamera(float speed);  
  37.         /* 前后移动摄像机 */  
  38.  void moveCamera(float speed);  
  39.         /* 放置摄像机 */  
  40.  void setLook();  
  41.         /* 得到摄像机指针 */  
  42.  static Camera* GetCamera(void) { return m_pCamera;}  
  43. private:  
  44.         /* 摄像机属性 */  
  45.         static Camera  *m_pCamera;      /* 当前全局摄像机指针 */  
  46.         Vector3        m_Position;      /* 位置 */  
  47.         Vector3        m_View;          /* 朝向 */  
  48.         Vector3        m_UpVector;      /* 向上向量 */  
  49.         float          m_Speed;         /* 速度 */  
  50. };  
  51. #endif //__CAMERA_H__ 

Camera.cpp内容:

  1. #include "Stdafx.h"  
  2. #include "Camera.h"                    /* 包含摄像机头文件 */  
  3. #include "Vector.h"                    /* 包含向量类 */  
  4. #include "math.h"  
  5.  
  6. Camera* Camera::m_pCamera = NULL;  
  7.  
  8. /* 构造函数 */  
  9. Camera::Camera()  
  10. {  
  11.     /* 初始化向量值 */  
  12.     Vector3 zero = Vector3(0.0, 0.0, 0.0);  
  13.     Vector3 view = Vector3(0.0, 1.0, 0.5);  
  14.     Vector3 up   = Vector3(0.0, 0.0, 1.0);  
  15.  
  16.     /* 初始化摄像机 */  
  17.  
  18.     //观察位置 Eye  
  19.     m_Position = zero;  
  20.  
  21.     //被观察点  
  22.     m_View  = view;  
  23.  
  24.     //倒立还是正立  
  25.     m_UpVector = up;  
  26.  
  27.     //前进速度  
  28.     m_Speed     = 0.05f;  
  29.  
  30.     //相机指针  
  31.     m_pCamera = this;  
  32.  
  33. }  
  34.  
  35. Camera::~Camera()  
  36. {  
  37. }  
  38.  
  39. /* 设置摄像机的位置,朝向和向上向量 */  
  40. void Camera::setCamera( float positionX, float positionY, float positionZ,  
  41.                         float viewX,     float viewY,     float viewZ,  
  42.                         float upVectorX, float upVectorY, float upVectorZ)  
  43. {  
  44.     /* 构造向量 */  
  45.     Vector3 Position = Vector3(positionX, positionY, positionZ);  
  46.     Vector3 View  = Vector3(viewX, viewY, viewZ);  
  47.     Vector3 UpVector = Vector3(upVectorX, upVectorY, upVectorZ);  
  48.  
  49.     /* 设置摄像机 */  
  50.     m_Position = Position;  
  51.     m_View     = View;  
  52.     m_UpVector = UpVector;  
  53. }  
  54.  
  55. /*  旋转摄像机方向  */  
  56. void Camera::rotateView(float angle, float x, float y, float z)  
  57. {  
  58.     Vector3 newView;  
  59.  
  60.     /* 计算方向向量 */  
  61.     Vector3 view = m_View - m_Position;  
  62.  
  63.     /* 计算 sin 和cos值 */  
  64.     float cosTheta = (float)cos(angle);  
  65.     float sinTheta = (float)sin(angle);  
  66.  
  67.     /* 计算旋转向量的x值 */  
  68.     newView.x  = (cosTheta + (1 - cosTheta) * x * x)  * view.x;  
  69.     newView.x += ((1 - cosTheta) * x * y - z * sinTheta) * view.y;  
  70.     newView.x += ((1 - cosTheta) * x * z + y * sinTheta) * view.z;  
  71.  
  72.     /* 计算旋转向量的y值 */  
  73.     newView.y  = ((1 - cosTheta) * x * y + z * sinTheta) * view.x;  
  74.     newView.y += (cosTheta + (1 - cosTheta) * y * y)  * view.y;  
  75.     newView.y += ((1 - cosTheta) * y * z - x * sinTheta) * view.z;  
  76.  
  77.     /* 计算旋转向量的z值 */  
  78.     newView.z  = ((1 - cosTheta) * x * z - y * sinTheta) * view.x;  
  79.     newView.z += ((1 - cosTheta) * y * z + x * sinTheta) * view.y;  
  80.     newView.z += (cosTheta + (1 - cosTheta) * z * z)  * view.z;  
  81.  
  82.     /* 更新摄像机的方向 */  
  83.     m_View = m_Position + newView;  
  84. }  
  85.  
  86. /* 用鼠标旋转摄像机 */  
  87. void Camera::setViewByMouse()  
  88. {/*此函数已放弃。如要使用,在Update处调用即可*/  
  89.  
  90.     /*< 保存当前鼠标位置 */     POINT mousePos;   
  91.     int middleX = GetSystemMetrics(SM_CXSCREEN) >> 1; /*< 得到屏幕宽度的一半 */   
  92.     int middleY = GetSystemMetrics(SM_CYSCREEN) >> 1; /*< 得到屏幕高度的一半 */  
  93.  
  94.     float angleY = 0.0f;/*< 摄像机左右旋转角度 */  
  95.     float angleZ = 0.0f;/*< 摄像机上下旋转角度 */   
  96.     static float currentRotX = 0.0f;     /* 得到当前鼠标位置 */   
  97.     GetCursorPos(&mousePos);     ShowCursor(TRUE);     /* 如果鼠标没有移动,则不用更新 */  
  98.      if( (mousePos.x == middleX) && (mousePos.y == middleY) )  
  99.          return;     /* 设置鼠标位置在屏幕中心 */   
  100.     SetCursorPos(middleX, middleY);     /* 得到鼠标移动方向 */  
  101.      angleY = (float)( (middleX - mousePos.x) ) / 1000.0f;  
  102.      angleZ = (float)( (middleY - mousePos.y) ) / 1000.0f;  
  103.      static float lastRotX = 0.0f;      /* 用于保存旋转角度 */   
  104.     lastRotX = currentRotX;     /* 跟踪摄像机上下旋转角度 */  
  105.      currentRotX += angleZ;     /* 如果上下旋转弧度大于1.0,我们截取到1.0并旋转 */   
  106.     if(currentRotX > 1.0f)  
  107.     {  
  108.         currentRotX = 1.0f;  
  109.         /* 根据保存的角度旋转方向 */  
  110.         if(lastRotX != 1.0f)  
  111.         {  
  112.             /* 通过叉积找到与旋转方向垂直的向量 */  
  113.             Vector3 vAxis = m_View - m_Position;  
  114.             vAxisvAxis = vAxis.crossProduct(m_UpVector);  
  115.             vAxisvAxis = vAxis.normalize();  
  116.             ///旋转  
  117.             rotateView( 1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);  
  118.         }  
  119.     }  
  120.     /* 如果旋转弧度小于-1.0,则也截取到-1.0并旋转 */  
  121.     else if(currentRotX < -1.0f)  
  122.     {  
  123.         currentRotX = -1.0f;  
  124.  
  125.         if(lastRotX != -1.0f)  
  126.         {  
  127.             /* 通过叉积找到与旋转方向垂直的向量 */  
  128.             Vector3 vAxis = m_View - m_Position;  
  129.             vAxisvAxis = vAxis.crossProduct(m_UpVector);  
  130.             vAxisvAxis = vAxis.normalize();  
  131.  
  132.             ///旋转  
  133.             rotateView( -1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);  
  134.         }  
  135.     }  
  136.     /* 否则就旋转angleZ度 */  
  137.     else  
  138.     {  
  139.         /* 找到与旋转方向垂直向量 */  
  140.         Vector3 vAxis = m_View - m_Position;  
  141.         vAxisvAxis = vAxis.crossProduct(m_UpVector);  
  142.         vAxisvAxis = vAxis.normalize();  
  143.         ///旋转  
  144.         rotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);  
  145.     }  
  146.     /* 总是左右旋转摄像机 */  
  147.     rotateView(angleY, 0, 1, 0);  
  148. }  
  149. /* 左右移动摄像机 */  
  150. void Camera::yawCamera(float speed)  
  151. {  
  152.     Vector3 yaw;  
  153.     Vector3 cross = m_View - m_Position;  
  154.     crosscross = cross.crossProduct(m_UpVector);  
  155.     ///归一化向量  
  156.     yaw = cross.normalize();  
  157.     m_Position.x += yaw.x * speed;  
  158.     m_Position.z += yaw.z * speed;  
  159.     m_View.x += yaw.x * speed;  
  160.     m_View.z += yaw.z * speed;  
  161. }  
  162. /* 前后移动摄像机 */  
  163. void Camera::moveCamera(float speed)  
  164. {  
  165.     /* 计算方向向量 */  
  166.     Vector3 vector = m_View - m_Position;  
  167.     vectorvector = vector.normalize();         /*< 单位化 */  
  168.     /* 更新摄像机 */  
  169.     m_Position.x += vector.x * speed;    /*< 根据速度更新位置 */  
  170.     m_Position.y += vector.y * speed;  
  171.     m_Position.z += vector.z * speed;  
  172.     m_View.x += vector.x * speed;   /*< 根据速度更新方向 */  
  173.     m_View.y += vector.y * speed;  
  174.     m_View.z += vector.z * speed;  
  175. }  
  176. /* 设置视点 */  
  177. void Camera::setLook()  
  178. {  
  179.     /* 设置视口 */  
  180.     gluLookAt(m_Position.x, m_Position.y, m_Position.z,  
  181.               m_View.x,  m_View.y,     m_View.z,  
  182.               m_UpVector.x, m_UpVector.y, m_UpVector.z);  

使用方法:

  1. /* 设置全局相机 */  
  2. m_Camera.setLook();  
  3.  
  4. /* 初始化相机 */  
  5. m_Camera.setCamera(0.0f, 0.0f, -3.0f,   //Eye  
  6.                    0.0f, 0.0f, -7.0f,   //Center  
  7.                    0.0f, 1.0f, 0.0f);  //Up  
  8.  
  9. case Qt::Key_W://镜头靠近  
  10.     m_Camera.moveCamera(m_Camera.getSpeed());  
  11.     break;  
  12. case Qt::Key_S://镜头远离  
  13.     m_Camera.moveCamera(-m_Camera.getSpeed()); 

上面记得要先初始化相机,然后给其“摆放”好,然后利用键盘事件改变其视点就好了

小结:Qt 3D OpenGL实现场景漫游实例的内容介绍完了,希望本文对你有帮助!

责任编辑:zhaolei 来源: 网络转载
相关推荐

2011-06-20 14:40:19

Qt 3D

2016-04-07 09:46:50

H5VR3d

2012-02-27 10:00:50

HTML 5

2012-06-16 16:57:52

WebGL

2010-02-14 15:27:25

2009-03-19 20:41:31

VirtualBox GuestsOpenGL 3D

2013-07-25 09:32:26

OpenGL ESAndroid4.3

2015-04-27 15:35:42

Cocos3D场景编辑器

2011-05-26 10:55:39

2021-09-16 07:52:18

SwiftUScroll效果

2022-09-19 19:16:42

轮播图has

2024-07-31 15:30:05

2024-12-10 15:17:11

2012-11-26 12:51:44

木材3D打

2021-03-08 15:40:46

开源技术 软件

2011-10-06 13:30:45

宏碁投影仪

2010-06-09 10:50:08

OpenSUSE 3D

2023-05-26 07:08:05

CSS模糊实现文字

2011-05-26 10:05:07

优派投影机

2023-05-03 09:01:41

CanvasWebGL
点赞
收藏

51CTO技术栈公众号