Qt 3D OpenGL實(shí)現(xiàn)場(chǎng)景漫游實(shí)例
Qt 3D OpenGL實(shí)現(xiàn)場(chǎng)景漫游實(shí)例是本文要介紹的內(nèi)容,一個(gè)不錯(cuò)的OpenGL程序當(dāng)然免不了對(duì)整個(gè)場(chǎng)景漫游。在我程序中便是用W、A、S、D來(lái)靠近,遠(yuǎn)離,向左,向右來(lái)移動(dòng)場(chǎng)景,Q、E、Z、C則是旋轉(zhuǎn)場(chǎng)景。同時(shí),補(bǔ)充一條,我用鼠標(biāo)滾輪實(shí)現(xiàn)了物體的放大和縮小,效果上和按W、S鍵是相同的,但本質(zhì)上是有差別的,呵呵~
我要貼出的這個(gè)Camera類是從《OpenGL游戲編程》里提取出來(lái)的,并且已經(jīng)在Qt環(huán)境下運(yùn)行成功(本來(lái)代碼是在VS2005)。
Camera.h內(nèi)容:
- #ifndef __CAMERA_H__
- #define __CAMERA_H__
- #include "Vector.h" /* 包含向量類頭文件 */
- /* 攝像機(jī)類 */
- class Camera
- {
- public:
- /* 構(gòu)造函數(shù)和析構(gòu)函數(shù) */
- Camera();
- ~Camera();
- /* 獲得攝像機(jī)狀態(tài)方法 */
- Vector3 getPosition() { return m_Position; }
- Vector3 getView() { return m_View; }
- Vector3 getUpVector() { return m_UpVector; }
- float getSpeed() { return m_Speed; }
- /* 設(shè)置速度 */
- void setSpeed(float speed)
- {
- m_Speed = speed;
- }
- /* 設(shè)置攝像機(jī)的位置, 觀察點(diǎn)和向上向量 */
- void setCamera(float positionX, float positionY, float positionZ,
- float viewX, float viewY, float viewZ,
- float upVectorX, float upVectorY, float upVectorZ);
- /* 旋轉(zhuǎn)攝像機(jī)方向 */
- void rotateView(float angle, float X, float Y, float Z);
- /* 根據(jù)鼠標(biāo)設(shè)置攝像機(jī)觀察方向 */
- void setViewByMouse();
- /* 左右攝像機(jī)移動(dòng) */
- void yawCamera(float speed);
- /* 前后移動(dòng)攝像機(jī) */
- void moveCamera(float speed);
- /* 放置攝像機(jī) */
- void setLook();
- /* 得到攝像機(jī)指針 */
- static Camera* GetCamera(void) { return m_pCamera;}
- private:
- /* 攝像機(jī)屬性 */
- static Camera *m_pCamera; /* 當(dāng)前全局?jǐn)z像機(jī)指針 */
- Vector3 m_Position; /* 位置 */
- Vector3 m_View; /* 朝向 */
- Vector3 m_UpVector; /* 向上向量 */
- float m_Speed; /* 速度 */
- };
- #endif //__CAMERA_H__
Camera.cpp內(nèi)容:
- #include "Stdafx.h"
- #include "Camera.h" /* 包含攝像機(jī)頭文件 */
- #include "Vector.h" /* 包含向量類 */
- #include "math.h"
- Camera* Camera::m_pCamera = NULL;
- /* 構(gòu)造函數(shù) */
- Camera::Camera()
- {
- /* 初始化向量值 */
- Vector3 zero = Vector3(0.0, 0.0, 0.0);
- Vector3 view = Vector3(0.0, 1.0, 0.5);
- Vector3 up = Vector3(0.0, 0.0, 1.0);
- /* 初始化攝像機(jī) */
- //觀察位置 Eye
- m_Position = zero;
- //被觀察點(diǎn)
- m_View = view;
- //倒立還是正立
- m_UpVector = up;
- //前進(jìn)速度
- m_Speed = 0.05f;
- //相機(jī)指針
- m_pCamera = this;
- }
- Camera::~Camera()
- {
- }
- /* 設(shè)置攝像機(jī)的位置,朝向和向上向量 */
- void Camera::setCamera( float positionX, float positionY, float positionZ,
- float viewX, float viewY, float viewZ,
- float upVectorX, float upVectorY, float upVectorZ)
- {
- /* 構(gòu)造向量 */
- Vector3 Position = Vector3(positionX, positionY, positionZ);
- Vector3 View = Vector3(viewX, viewY, viewZ);
- Vector3 UpVector = Vector3(upVectorX, upVectorY, upVectorZ);
- /* 設(shè)置攝像機(jī) */
- m_Position = Position;
- m_View = View;
- m_UpVector = UpVector;
- }
- /* 旋轉(zhuǎn)攝像機(jī)方向 */
- void Camera::rotateView(float angle, float x, float y, float z)
- {
- Vector3 newView;
- /* 計(jì)算方向向量 */
- Vector3 view = m_View - m_Position;
- /* 計(jì)算 sin 和cos值 */
- float cosTheta = (float)cos(angle);
- float sinTheta = (float)sin(angle);
- /* 計(jì)算旋轉(zhuǎn)向量的x值 */
- newView.x = (cosTheta + (1 - cosTheta) * x * x) * view.x;
- newView.x += ((1 - cosTheta) * x * y - z * sinTheta) * view.y;
- newView.x += ((1 - cosTheta) * x * z + y * sinTheta) * view.z;
- /* 計(jì)算旋轉(zhuǎn)向量的y值 */
- newView.y = ((1 - cosTheta) * x * y + z * sinTheta) * view.x;
- newView.y += (cosTheta + (1 - cosTheta) * y * y) * view.y;
- newView.y += ((1 - cosTheta) * y * z - x * sinTheta) * view.z;
- /* 計(jì)算旋轉(zhuǎn)向量的z值 */
- newView.z = ((1 - cosTheta) * x * z - y * sinTheta) * view.x;
- newView.z += ((1 - cosTheta) * y * z + x * sinTheta) * view.y;
- newView.z += (cosTheta + (1 - cosTheta) * z * z) * view.z;
- /* 更新攝像機(jī)的方向 */
- m_View = m_Position + newView;
- }
- /* 用鼠標(biāo)旋轉(zhuǎn)攝像機(jī) */
- void Camera::setViewByMouse()
- {/*此函數(shù)已放棄。如要使用,在Update處調(diào)用即可*/
- /*< 保存當(dāng)前鼠標(biāo)位置 */ POINT mousePos;
- int middleX = GetSystemMetrics(SM_CXSCREEN) >> 1; /*< 得到屏幕寬度的一半 */
- int middleY = GetSystemMetrics(SM_CYSCREEN) >> 1; /*< 得到屏幕高度的一半 */
- float angleY = 0.0f;/*< 攝像機(jī)左右旋轉(zhuǎn)角度 */
- float angleZ = 0.0f;/*< 攝像機(jī)上下旋轉(zhuǎn)角度 */
- static float currentRotX = 0.0f; /* 得到當(dāng)前鼠標(biāo)位置 */
- GetCursorPos(&mousePos); ShowCursor(TRUE); /* 如果鼠標(biāo)沒(méi)有移動(dòng),則不用更新 */
- if( (mousePos.x == middleX) && (mousePos.y == middleY) )
- return; /* 設(shè)置鼠標(biāo)位置在屏幕中心 */
- SetCursorPos(middleX, middleY); /* 得到鼠標(biāo)移動(dòng)方向 */
- angleY = (float)( (middleX - mousePos.x) ) / 1000.0f;
- angleZ = (float)( (middleY - mousePos.y) ) / 1000.0f;
- static float lastRotX = 0.0f; /* 用于保存旋轉(zhuǎn)角度 */
- lastRotX = currentRotX; /* 跟蹤攝像機(jī)上下旋轉(zhuǎn)角度 */
- currentRotX += angleZ; /* 如果上下旋轉(zhuǎn)弧度大于1.0,我們截取到1.0并旋轉(zhuǎn) */
- if(currentRotX > 1.0f)
- {
- currentRotX = 1.0f;
- /* 根據(jù)保存的角度旋轉(zhuǎn)方向 */
- if(lastRotX != 1.0f)
- {
- /* 通過(guò)叉積找到與旋轉(zhuǎn)方向垂直的向量 */
- Vector3 vAxis = m_View - m_Position;
- vAxisvAxis = vAxis.crossProduct(m_UpVector);
- vAxisvAxis = vAxis.normalize();
- ///旋轉(zhuǎn)
- rotateView( 1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);
- }
- }
- /* 如果旋轉(zhuǎn)弧度小于-1.0,則也截取到-1.0并旋轉(zhuǎn) */
- else if(currentRotX < -1.0f)
- {
- currentRotX = -1.0f;
- if(lastRotX != -1.0f)
- {
- /* 通過(guò)叉積找到與旋轉(zhuǎn)方向垂直的向量 */
- Vector3 vAxis = m_View - m_Position;
- vAxisvAxis = vAxis.crossProduct(m_UpVector);
- vAxisvAxis = vAxis.normalize();
- ///旋轉(zhuǎn)
- rotateView( -1.0f - lastRotX, vAxis.x, vAxis.y, vAxis.z);
- }
- }
- /* 否則就旋轉(zhuǎn)angleZ度 */
- else
- {
- /* 找到與旋轉(zhuǎn)方向垂直向量 */
- Vector3 vAxis = m_View - m_Position;
- vAxisvAxis = vAxis.crossProduct(m_UpVector);
- vAxisvAxis = vAxis.normalize();
- ///旋轉(zhuǎn)
- rotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
- }
- /* 總是左右旋轉(zhuǎn)攝像機(jī) */
- rotateView(angleY, 0, 1, 0);
- }
- /* 左右移動(dòng)攝像機(jī) */
- void Camera::yawCamera(float speed)
- {
- Vector3 yaw;
- Vector3 cross = m_View - m_Position;
- crosscross = cross.crossProduct(m_UpVector);
- ///歸一化向量
- yaw = cross.normalize();
- m_Position.x += yaw.x * speed;
- m_Position.z += yaw.z * speed;
- m_View.x += yaw.x * speed;
- m_View.z += yaw.z * speed;
- }
- /* 前后移動(dòng)攝像機(jī) */
- void Camera::moveCamera(float speed)
- {
- /* 計(jì)算方向向量 */
- Vector3 vector = m_View - m_Position;
- vectorvector = vector.normalize(); /*< 單位化 */
- /* 更新攝像機(jī) */
- m_Position.x += vector.x * speed; /*< 根據(jù)速度更新位置 */
- m_Position.y += vector.y * speed;
- m_Position.z += vector.z * speed;
- m_View.x += vector.x * speed; /*< 根據(jù)速度更新方向 */
- m_View.y += vector.y * speed;
- m_View.z += vector.z * speed;
- }
- /* 設(shè)置視點(diǎn) */
- void Camera::setLook()
- {
- /* 設(shè)置視口 */
- gluLookAt(m_Position.x, m_Position.y, m_Position.z,
- m_View.x, m_View.y, m_View.z,
- m_UpVector.x, m_UpVector.y, m_UpVector.z);
- }
使用方法:
- /* 設(shè)置全局相機(jī) */
- m_Camera.setLook();
- /* 初始化相機(jī) */
- m_Camera.setCamera(0.0f, 0.0f, -3.0f, //Eye
- 0.0f, 0.0f, -7.0f, //Center
- 0.0f, 1.0f, 0.0f); //Up
- case Qt::Key_W://鏡頭靠近
- m_Camera.moveCamera(m_Camera.getSpeed());
- break;
- case Qt::Key_S://鏡頭遠(yuǎn)離
- m_Camera.moveCamera(-m_Camera.getSpeed());
上面記得要先初始化相機(jī),然后給其“擺放”好,然后利用鍵盤(pán)事件改變其視點(diǎn)就好了
小結(jié):Qt 3D OpenGL實(shí)現(xiàn)場(chǎng)景漫游實(shí)例的內(nèi)容介紹完了,希望本文對(duì)你有幫助!



























