Direct-X学习笔记--三维摄像机

本文介绍了在DirectX中如何实现3D摄像机,包括摄像机类的封装,使用右分量、上分量、观察分量和位置分量确定摄像机的位置和朝向。摄像机的操作包括平移和旋转六种方式,详细解析了roll、yaw、pitch的含义及其在摄像机旋转中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.介绍

哇!到了传说中的3D摄像机啦!

之前我们写的东东,都是观察点不动,通过世界变换让东西动,今天,通过三维摄像机我们就可以改变我们的观察点,观察方向,随意在三维空间中驰骋。之前我们所设定的视角都是通过D3DXMatrixLookAtLH这个函数,通过几个设定好的向量,将视角初始化的,而在程序真正运行时,视角就不再改变了,而这次,我们要实时的生成视角变换矩阵,实时的改变我们的视角,我们所谓的摄像机就是这个原理。

我们通过一个类来封装摄像机,这个类主要的字段就是用四个分量:右分量(rightvector)、上分量(up vector)、观察分量(lookvector)和位置分量(position vector),来确定一个摄像机相对于世界坐标系的位置和朝向。并根据这四个分量计算出一个取景变换矩阵,然后通过取景变换(VIEWTRANSFORM)实现改变视角。


通过这些分量,我们可以确定摄像机的位置和朝向。操作有平移和旋转,那么一共就有6中操作:

(1)沿着观察分量平移(前进后退)

(2)沿着观察分量旋转(左右翻滚)

(3)沿着右分量平移(左右移动)

(4)沿着右分量旋转(朝上下看)

(5)沿着上分量平移(上下移动)

(6)沿着上分量旋转(朝左右看)


二.操作

这里,我们把摄像机的功能封装成一个类,这样,我们就可以非常方便的使用摄像机的功能,而不需要写一大堆代码啦。

要用到几个函数:

(1)D3DXVec3Normalize 将向量单位化
(2)D3DXVec3Cross        叉乘,第二个,第三个参数为参加运算的向量,生成的结果为垂直与两个向量构成平面的向量,由一个参数输出结果
(3)D3DXVec3Dot  点乘,结果返回
(4)D3DXMatrixRotationAxis 创建一个绕任意轴旋转一定角度的矩阵,第一个参数为输出矩阵,第二个参数为轴,第三个参数为角度
(5)D3DXVec3TransformCoord 根据矩阵变换一个向量,第一个参数为输出向量,第二个参数为被变化向量,第三个参数为矩阵
(6)D3DXVec3Length      获得向量的长度,返回

取景变换所解决的其实就是世界坐标系中的物体在以摄像机为中心的坐标系中如何来表示的问题。这就是说,需要将世界坐标系中的物体随着摄像机一起进行变换,这样摄像机的坐标系就与世界坐标系完全重合了。摄像机其实也相当于三维世界中的一个物体,和我们绘制的东西一样。我们把摄像机移动到世界坐标系的原点,然后让右向量与世界坐标系的x方向重合,上向量与世界坐标系的y方向重合,观察向量与世界坐标系的z方向重合,这样,我们就能生成一个矩阵。
当然这个矩阵感觉比较麻烦,我们照抄下来,生成即可。

计算取景变换矩阵的方法如下:
void CCamera::CalculateViewMatrix(D3DXMATRIX *pMatrix)
{
	//规范化三个向量使之成为正交矩阵

	//规范化观察向量
	D3DXVec3Normalize(&m_vLookVector, &m_vLookVector);
	//使上向量与观察向量垂直
	D3DXVec3Cross(&m_vUpVector, &m_vLookVector, &m_vRightVector);
	//规范化上向量
	D3DXVec3Normalize(&m_vUpVector, &m_vUpVector);
	//右向量与上向量垂直
	D3DXVec3Cross(&m_vRightVector, &m_vUpVector, &m_vLookVector);
	//规范化右向量
	D3DXVec3Normalize(&m_vRightVector, &m_vRightVector);

	//创建取景变换矩阵
	pMatrix->_11 = m_vRightVector.x;
	pMatrix->_12 = m_vUpVector.x;
	pMatrix->_13 = m_vLookVector.x;
	pMatrix->_14 = 0.0f;

	pMatrix->_21 = m_vRightVector.y;
	pMatrix->_22 = m_vUpVector.y;
	pMatrix->_23 = m_vLookVector.y;
	pMatrix->_24 = 0.0f;

	pMatrix->_31 = m_vRightVector.z;
	pMatrix->_32 = m_vUpVector.z;
	pMatrix->_33 = m_vLookVector.z;
	pMatrix->_34 = 0.0f;

	pMatrix->_41 = -D3DXVec3Dot(&m_vRightVector, &m_vCameraPosition);
	pMatrix->_42 = -D3DXVec3Dot(&m_vUpVector, &m_vCameraPosition);
	pMatrix->_43 = -D3DXVec3Dot(&m_vLookVector, &m_vCameraPosition);
	pMatrix->_44 = 1.0f;
}
这样,我们就可以根据摄像机类中的四个向量(相机位置,上分量,右分量,观察分量)获得取景变换的矩阵,通过指针传递参数。这样,我们实时的根据这个矩阵进行取景变换,就可以得到实时的画面情况。而我们在逻辑部分要做的就是改变摄像机类中的各个分量即可。

整个摄像机类的设计如下:

.h文件
/************************************************************************/
/* 封装一个摄像机类                                                     */
/************************************************************************/
#ifndef __CCAMERA_H_
#define __CCAMERA_H_
#include "stdafx.h"
#pragma once
class CCamera
{
private:
	//成员变量
	IDirect3DDevice9* m_pDevice;		//D3D设备对象
	D3DXVECTOR3 m_vRightVector;	        //右分量向量
	D3DXVECTOR3 m_vUpVector;			//上分量向量
	D3DXVECTOR3 m_vLookVector;			//观察分量向量
	D3DXVECTOR3 m_vCameraPosition;		//摄像机位置
	D3DXVECTOR3 m_vTargetPosition;		//观察目标位置
	D3DXMATRIX  m_matView;				//取景变换矩阵
	D3DXMATRIX  m_matProj;				//投影变换矩阵

public:
	CCamera(IDirect3DDevice9* pDevice);
	~CCamera(void);

	//计算取景变换矩阵
	void CalculateViewMatrix(D3DXMATRIX *pMatrix);
	//获得投影矩阵
	void GetProjectionMatrix(D3DXMATRIX* pMatrix){*pMatrix = m_matProj;}
	//获得当前摄像机位置向量
	void GetCameraPosition(D3DXVECTOR3* pVector){*pVector = m_vCameraPosition;}
	//返回当前观察向量
	void GetLookVector(D3DXVECTOR3* pVector){*pVector = m_vLookVector;}
	//设置摄像机观察位置向量(默认参数为NULL)
	void  SetTargetPosition(D3DXVECTOR3* pVector = NULL);
	//设置摄像机所在位置向量(默认参数为NULL)
	void SetCameraPosition(D3DXVECTOR3* pVector = NULL);
	//设置取景变换矩阵(默认参数为NULL)
	void SetViewMatrix(D3DXMATRIX* pMatrix = NULL);
	//设置投影变换矩阵(默认参数为NULL)
	void SetProjectionMartix(D3DMATRIX* pMatrix = NULL);


	
	//沿着right分量平移
	void MoveAlongRightVec(float fUnits);
	//沿着up分量平移
	void MoveAlongUpVec(float fUnits);
	//沿着look
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值