当前位置:文档之家› 第10讲摄像机漫游分析解析

第10讲摄像机漫游分析解析

摄像机漫游设置观察矩阵代码://建立并设置观察矩阵D3DXVECTOR3 vEyePt( 0.0f,0.0f,-15.0f );D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );D3DXVECTOR3 vUpV ec( 0.0f, 1.0f, 0.0f );D3DXMA TRIX matView;D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );观察变换---摄像机属性通常用四个分量来确定一个摄像机相对于世界坐标系的位置和朝向:左分量、上分量、观察分量和位置分量。

在世界坐标系中,这几个分量都通过向量表示,并且实际上它们为摄像机定义了一个局部坐标系,需要将世界坐标系中的物体随着摄像机一起进行变换,以便让摄像机的坐标系与世界坐标系完全重合摄像机变换1.沿各分量平移由于摄像机包含向右、向上、观察三个分量,因此可以控制摄像机分别沿这三个分量进行平移。

其中,沿右分量的平移称作扫视,沿上分量的平移称作升降,而沿观察分量的平移称作平动,如图所示2.绕各分量旋转摄像机的另一种变换是分别绕上分量、右分量和观察分量进行旋转。

其中,绕上分量的旋转称作偏航,绕右分量的旋转称作俯仰,而绕观察分量的旋转称作滚动,如图所示3.绕观察点旋转摄像机的平移和旋转已经能够满足简单的应用,但是有时候还需要将观察点固定,并控制摄像机围绕该点做圆周运动,以便能够从不同角度观察同一物体。

因此,还需要让摄像机绕某个点进行旋转,如图所示以摄像机在y方向上绕点l=(l x,l y,l z)旋转为例,假设当前摄像机位于p点(观察点l与p点同在y平面内),那么当摄像机按逆时针方向旋转a 角度后应该位于p’点,如图所示。

//摄像机绕Y轴旋转fAngle角度VOID CCamera::CircleRotationY(FLOAT fAngle){D3DXMA TRIX R;D3DXMatrixRotationAxis(&R, &m_vUpVec, fAngle);D3DXVec3TransformCoord(&m_vRightVec, &m_vRightVec, &R);D3DXVec3TransformCoord(&m_vLookVec, &m_vLookVec, &R);float dx = m_vPosition.x - m_vLookat.x;float dz = m_vPosition.z - m_vLookat.z;m_vPosition.x = m_vLookat.x + dx * cosf(fAngle) - dz * sinf(fAngle);m_vPosition.z = m_vLookat.z + dx * sinf(fAngle) + dz * cosf(fAngle);ResetLookatPos(&m_vLookat);}根据上面介绍的内容,可以定义一个具有九个自由度的摄像机CCamera类,其中可以沿三个分量平移、绕三个分量旋转,以及在三个坐标方向上绕观察点旋转。

4.CCamera类定义#pragma once#include <d3d9.h>#include <d3dx9.h>//--------------------------------------------------------------------------------------// Name: class CCamera// Desc: 虚拟摄像机平移、旋转//--------------------------------------------------------------------------------------class CCamera{private:D3DXVECTOR3 m_vRightVec; // 摄像机右侧向量D3DXVECTOR3 m_vUpVec; // 摄像机上方向量D3DXVECTOR3 m_vLookVec; //摄像机视线方向D3DXVECTOR3 m_vPosition; // 摄像机当前位置D3DXMA TRIX m_matView; // 摄像机矩阵D3DXMA TRIX m_matProj; // 投影矩阵D3DXVECTOR3 m_vLookat; //摄像机视线位置LPDIRECT3DDEVICE9 m_pd3dDevice;public:CCamera(IDirect3DDevice9 *pd3dDevice);virtual ~CCamera(void);public:VOID GetViewMatrix(D3DXMA TRIX *pMatrix);//获取摄像机矩阵VOID GetProjMatrix(D3DXMATRIX *pMatrix) { *pMatrix = m_matProj; }VOID GetCameraPos(D3DXVECTOR3 *pVector) { *pVector = m_vPosition; }VOID GetLookVector(D3DXVECTOR3 *pVector) { *pVector = m_vLookVec; }VOID ResetLookatPos(D3DXVECTOR3 *pLookat = NULL);//设置视线位置VOID ResetCameraPos(D3DXVECTOR3 *pVector = NULL);//设置摄像机位置VOID ResetViewMatrix(D3DXMA TRIX *pMatrix = NULL);//设置摄像机(观察)矩阵VOID ResetProjMatrix(D3DXMA TRIX *pMatrix = NULL);//设置投影矩阵public:// 沿各分量平移VOID MoveAlongRightVec(FLOAT fUnits); // 沿right向量移动VOID MoveAlongUpVec(FLOAT fUnits); // 沿up向量移动VOID MoveAlongLookVec(FLOAT fUnits); // 沿look向量移动// 绕各分量旋转VOID RotationRightVec(FLOAT fAngle); // 绕right向量选择VOID RotationUpVec(FLOAT fAngle); // 绕up向量旋转VOID RotationLookVec(FLOAT fAngle); // 绕look向量旋转// 绕空间点旋转VOID CircleRotationX(FLOAT fAngle); // 在X方向上绕观察点旋转VOID CircleRotationY(FLOAT fAngle); // 在Y方向上绕观察点旋转VOID CircleRotationZ(FLOAT fAngle); // 在Z方向上绕观察点旋转};5、摄像机类CCamera类的实现#include "Camera.h"#include <fstream>CCamera::CCamera(IDirect3DDevice9 *pd3dDevice){m_pd3dDevice = pd3dDevice;m_vRightVec = D3DXVECTOR3(1.0f, 0.0f, 0.0f); // 默认右向量与X正半轴重合m_vUpVec = D3DXVECTOR3(0.0f, 1.0f, 0.0f); // 默认上向量与Y正半轴重合m_vLookVec = D3DXVECTOR3(0.0f, 0.0f, 1.0f); // 默认观察向量与Z正半轴重合m_vPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f); // 默认摄像机的位置为原点m_vLookat = D3DXVECTOR3(0.0f, 0.0f, 0.0f);GetViewMatrix(&m_matView); // 取得取景变换矩阵D3DXMatrixPerspectiveFovLH(&m_matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 2000.0f); // 投影变换矩阵}CCamera::~CCamera(void){}VOID CCamera::GetViewMatrix(D3DXMATRIX *pMatrix){// 使各分量相互垂直D3DXVec3Normalize(&m_vLookVec, &m_vLookVec);D3DXVec3Cross(&m_vUpVec, &m_vLookVec, &m_vRightVec); // 上向量与观察向量垂直D3DXVec3Normalize(&m_vUpVec, &m_vUpVec); // 规格化上向量D3DXVec3Cross(&m_vRightVec, &m_vUpVec, &m_vLookVec); // 右向量与上向量垂直//你能通过左手法则确定叉积返回的向量。

按照第一个向量指向第二个向量弯曲你的左手,//这时拇指所指的方向就是叉积向量所指的方向。

D3DXVec3Normalize(&m_vRightVec, &m_vRightVec); // 规格化右向量// 创建取景变换矩阵pMatrix->_11 = m_vRightVec.x; // RxpMatrix->_12 = m_vUpVec.x; // UxpMatrix->_13 = m_vLookVec.x; // LxpMatrix->_14 = 0.0f;pMatrix->_21 = m_vRightVec.y; // RypMatrix->_22 = m_vUpVec.y; // UypMatrix->_23 = m_vLookVec.y; // LypMatrix->_24 = 0.0f;pMatrix->_31 = m_vRightVec.z; // RzpMatrix->_32 = m_vUpVec.z; // UzpMatrix->_33 = m_vLookVec.z; // LzpMatrix->_34 = 0.0f;pMatrix->_41 = -D3DXVec3Dot(&m_vRightVec, &m_vPosition); // -P*RpMatrix->_42 = -D3DXVec3Dot(&m_vUpVec, &m_vPosition); // -P*UpMatrix->_43 = -D3DXVec3Dot(&m_vLookVec, &m_vPosition); // -P*LpMatrix->_44 = 1.0f;}VOID CCamera::ResetLookatPos(D3DXVECTOR3 *pLookat){if (pLookat != NULL) m_vLookat = (*pLookat);else m_vLookat = D3DXVECTOR3(0.0f, 0.0f, 1.0f);m_vLookVec = m_vLookat - m_vPosition;D3DXVec3Normalize(&m_vLookVec, &m_vLookVec);D3DXVec3Cross(&m_vUpVec, &m_vLookVec, &m_vRightVec);D3DXVec3Normalize(&m_vUpVec, &m_vUpVec);D3DXVec3Cross(&m_vRightVec, &m_vUpVec, &m_vLookVec);D3DXVec3Normalize(&m_vRightVec, &m_vRightVec);}VOID CCamera::ResetCameraPos(D3DXVECTOR3 *pVector){D3DXVECTOR3 V = D3DXVECTOR3(0.0f, 0.0f, 0.0f);m_vPosition = pVector ? (*pVector) : V;}VOID CCamera::ResetViewMatrix(D3DXMA TRIX *pMatrix){if (pMatrix) m_matView = *pMatrix;else GetViewMatrix(&m_matView);m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView);m_vRightVec = D3DXVECTOR3(m_matView._11, m_matView._12, m_matView._13);m_vUpVec = D3DXVECTOR3(m_matView._21, m_matView._22, m_matView._23);m_vLookVec = D3DXVECTOR3(m_matView._31, m_matView._32, m_matView._33); }VOID CCamera::ResetProjMatrix(D3DXMA TRIX *pMatrix){if (pMatrix != NULL) m_matProj = *pMatrix;else D3DXMatrixPerspectiveFovLH(&m_matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f);m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProj);}// 沿右向量平移fUnits个单位VOID CCamera::MoveAlongRightVec(FLOAT fUnits){m_vPosition += m_vRightVec * fUnits;m_vLookat += m_vRightVec * fUnits;}// 沿上向量平移fUnits个单位VOID CCamera::MoveAlongUpVec(FLOAT fUnits){m_vPosition += m_vUpVec * fUnits;m_vLookat += m_vUpVec * fUnits;}// 沿观察向量平移fUnits个单位VOID CCamera::MoveAlongLookVec(FLOAT fUnits){m_vPosition += m_vLookVec * fUnits;m_vLookat += m_vLookVec * fUnits;}//旋转使用D3DXMatrixRotationAxis函数实现,绕right\up\look方向旋转的实现方法:VOID CCamera::RotationRightVec(FLOAT fAngle){D3DXMA TRIX R;D3DXMatrixRotationAxis(&R, &m_vRightVec, fAngle);D3DXVec3TransformCoord(&m_vUpVec, &m_vPosition, &R);D3DXVec3TransformCoord(&m_vLookVec, &m_vLookVec, &R);m_vLookat = m_vLookVec * D3DXVec3Length(&m_vPosition);}/*D3DXVec3TransformCoord用矩阵变换3-D向量,并且用w = 1投影结果。

相关主题