前言,在上篇三角形基础上,我准备增设一个可移动的摄像机。这样我们就可以为所欲为地看三角形了。
运行截图
初始:
前后移动:
左右平动
滚动
俯仰
实现流程图
摄像机用法
一、创建摄像机全局变量
//三种方法创建摄像机
Camera TheCamera(Camera::AIRCRAFT);
Camera TheCamera(Camera::LANDOBJECT);
Camera TheCamera();
二、在Display()函数中
设置控制摄像机移动的按键
//可移动的摄像机
if (::GetAsyncKeyState('W') & 0x8000f)
TheCamera.walk(4.0f * timeDelta);
if (::GetAsyncKeyState('S') & 0x8000f)
TheCamera.walk(-4.0f * timeDelta);
if (::GetAsyncKeyState('A') & 0x8000f)
TheCamera.strafe(-4.0f * timeDelta);
if (::GetAsyncKeyState('D') & 0x8000f)
TheCamera.strafe(4.0f * timeDelta);
if (::GetAsyncKeyState('R') & 0x8000f)
TheCamera.fly(4.0f * timeDelta);
if (::GetAsyncKeyState('F') & 0x8000f)
TheCamera.fly(-4.0f * timeDelta);
if (::GetAsyncKeyState(VK_UP) & 0x8000f)
TheCamera.pitch(1.0f * timeDelta);
if (::GetAsyncKeyState(VK_DOWN) & 0x8000f)
TheCamera.pitch(-1.0f * timeDelta);
if (::GetAsyncKeyState(VK_LEFT) & 0x8000f)
TheCamera.yaw(-1.0f * timeDelta);
if (::GetAsyncKeyState(VK_RIGHT) & 0x8000f)
TheCamera.yaw(1.0f * timeDelta);
if (::GetAsyncKeyState('N') & 0x8000f)
TheCamera.roll(1.0f * timeDelta);
if (::GetAsyncKeyState('M') & 0x8000f)
TheCamera.roll(-1.0f * timeDelta);
三、进行取景变换
取景变换:每个物体创建时都是包含一个单独坐标系(局部坐标系。然后将这些创建好的物体添加到世界中(世界坐标系)。添加摄像机后,物体又位于摄像机的坐标系中(观察坐标系)。这里通过Device->SetTransform(D3DTS_VIEW, &V);
函数将世界坐标系的物体变换到观察者坐标系中。
D3DXMATRIX V;
TheCamera.getViewMatrix(&V);
Device->SetTransform(D3DTS_VIEW, &V);
摄像机实现代码
camera.h
#pragma once
#include "stdafx.h"
#ifndef __cameraH__
#define __cameraH__
#include <d3dx9.h>
class Camera
{
public:
enum CameraType { LANDOBJECT, AIRCRAFT };
Camera();
Camera(CameraType cameraType);
~Camera();
void strafe(float units); // left/right
void fly(float units); // up/down
void walk(float units); // forward/backward
void pitch(float angle); // rotate on right vector
void yaw(float angle); // rotate on up vector
void roll(float angle); // rotate on look vector
void getViewMatrix(D3DXMATRIX* V);
void setCameraType(CameraType cameraType);
void getPosition(D3DXVECTOR3* pos);
void setPosition(D3DXVECTOR3* pos);
void getRight(D3DXVECTOR3* right);
void getUp(D3DXVECTOR3* up);
void getLook(D3DXVECTOR3* look);
private:
CameraType _cameraType;
D3DXVECTOR3 _right;
D3DXVECTOR3 _up;
D3DXVECTOR3 _look;
D3DXVECTOR3 _pos;
};
#endif // __cameraH__
camera.cpp
#include "stdafx.h"
#include "Camera.h"
Camera::Camera()
{
_cameraType = AIRCRAFT;
_pos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
_look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}
Camera::Camera(CameraType cameraType)
{
_cameraType = cameraType;
_pos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
_look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}
Camera::~Camera()
{
}
void Camera::getPosition(D3DXVECTOR3* pos)
{
*pos = _pos;
}
void Camera::setPosition(D3DXVECTOR3* pos)
{
_pos = *pos;
}
void Camera::getRight(D3DXVECTOR3* right)
{
*right = _right;
}
void Camera::getUp(D3DXVECTOR3* up)
{
*up = _up;
}
void Camera::getLook(D3DXVECTOR3* look)
{
*look = _look;
}
void Camera::walk(float units)
{
// move only on xz plane for land object
if (_cameraType == LANDOBJECT)
_pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units;
if (_cameraType == AIRCRAFT)
_pos += _look * units;
}
void Camera::strafe(float units)
{
// move only on xz plane for land object
if (_cameraType == LANDOBJECT)
_pos += D3DXVECTOR3(_right.x, 0.0f, _right.z) * units;
if (_cameraType == AIRCRAFT)
_pos += _right * units;
}
void Camera::fly(float units)
{
// move only on y-axis for land object
if (_cameraType == LANDOBJECT)
_pos.y += units;
if (_cameraType == AIRCRAFT)
_pos += _up * units;
}
void Camera::pitch(float angle)
{
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &_right, angle);
// rotate _up and _look around _right vector
D3DXVec3TransformCoord(&_up, &_up, &T);
D3DXVec3TransformCoord(&_look, &_look, &T);
}
void Camera::yaw(float angle)
{
D3DXMATRIX T;
// rotate around world y (0, 1, 0) always for land object
if (_cameraType == LANDOBJECT)
D3DXMatrixRotationY(&T, angle);
// rotate around own up vector for aircraft
if (_cameraType == AIRCRAFT)
D3DXMatrixRotationAxis(&T, &_up, angle);
// rotate _right and _look around _up or y-axis
D3DXVec3TransformCoord(&_right, &_right, &T);
D3DXVec3TransformCoord(&_look, &_look, &T);
}
void Camera::roll(float angle)
{
// only roll for aircraft type
if (_cameraType == AIRCRAFT)
{
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &_look, angle);
// rotate _up and _right around _look vector
D3DXVec3TransformCoord(&_right, &_right, &T);
D3DXVec3TransformCoord(&_up, &_up, &T);
}
}
void Camera::getViewMatrix(D3DXMATRIX* V)
{
// Keep camera's axes orthogonal to eachother
D3DXVec3Normalize(&_look, &_look);
D3DXVec3Cross(&_up, &_look, &_right);
D3DXVec3Normalize(&_up, &_up);
D3DXVec3Cross(&_right, &_up, &_look);
D3DXVec3Normalize(&_right, &_right);
// Build the view matrix:
float x = -D3DXVec3Dot(&_right, &_pos);
float y = -D3DXVec3Dot(&_up, &_pos);
float z = -D3DXVec3Dot(&_look, &_pos);
(*V)(0, 0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;
(*V)(1, 0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;
(*V)(2, 0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;
(*V)(3, 0) = x; (*V)(3, 1) = y; (*V)(3, 2) = z; (*V)(3, 3) = 1.0f;
}
void Camera::setCameraType(CameraType cameraType)
{
_cameraType = cameraType;
}