程序员的身体,众所周知,程序员需要大量的动脑,所以需要大量的供血,进而需要强大的心脏能力。这些无不是一颗定时炸弹,时刻威胁在程序的身体。所以,作为程序员,我们应该珍惜自己的身体。千万记住,你的公司,不会爱惜你的身体的,它只会从你身上进行剥削,榨取剩余价值。所以,我们应该掌握一个度,快到这个度时,忙中偷闲,喝杯茶去。BUG是解不完的,而生命只有一次。为了自己,为了家人,我们应该珍惜,时刻保持警惕。
到目前为止,我们已经学会了如果使用D3DXMatrixLookAtLH函数计算出观察矩阵(即取景变换矩阵)。当在某一个固定地点固定摄像机方位时,该函数十分有用,但其对用户接口输入做出响应的移动摄像机来说,就显得力不从心了。本章中,我们实现了一个Camera类,来实现摄像机方位的动态变化,绕3 个坐标轴进行旋转变换,进行平移,扫视,升降。
我们先来看camera.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__
再来看DirectX3D.h的代码:
#ifndef __DirectX3DH__
#define __DirectX3DH__
#include <d3dx9.h>
#include <string>
#include <limits>
namespace d3d
{
bool InitD3D(
HINSTANCE hInstance, // [in] Application instance.
int width, int height, // [in] Backbuffer dimensions.
bool windowed, // [in] Windowed (true)or full screen (false).
D3DDEVTYPE deviceType, // [in] HAL or REF
IDirect3DDevice9** device);// [out]The created device.
int EnterMsgLoop(
bool (*ptr_display)(float timeDelta));
LRESULT CALLBACK WndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
template<class T> void Release(T t)
{
if( t )
{
t->Release();
t = 0;
}
}
template<class T> void Delete(T t)
{
if( t )
{
delete t;
t = 0;
}
}
const D3DXCOLOR WHITE( D3DCOLOR_XRGB(255, 255, 255) );
const D3DXCOLOR BLACK( D3DCOLOR_XRGB( 0, 0, 0) );
const D3DXCOLOR RED( D3DCOLOR_XRGB(255, 0, 0) );
const D3DXCOLOR GREEN( D3DCOLOR_XRGB( 0, 255, 0) );
const D3DXCOLOR BLUE( D3DCOLOR_XRGB( 0, 0, 255) );
const D3DXCOLOR YELLOW( D3DCOLOR_XRGB(255, 255, 0) );
const D3DXCOLOR CYAN( D3DCOLOR_XRGB( 0, 255, 255) );
const D3DXCOLOR MAGENTA( D3DCOLOR_XRGB(255, 0, 255) );
//
// Lights
//
D3DLIGHT9 InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color);
D3DLIGHT9 InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color);
D3DLIGHT9 InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color);
//
// Materials
//
D3DMATERIAL9 InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);
const D3DMATERIAL9 WHITE_MTRL = InitMtrl(WHITE, WHITE, WHITE, BLACK, 2.0f);
const D3DMATERIAL9 RED_MTRL = InitMtrl(RED, RED, RED, BLACK, 2.0f);
const D3DMATERIAL9 GREEN_MTRL = InitMtrl(GREEN, GREEN, GREEN, BLACK, 2.0f);
const D3DMATERIAL9 BLUE_MTRL = InitMtrl(BLUE, BLUE, BLUE, BLACK, 2.0f);
const D3DMATERIAL9 YELLOW_MTRL = InitMtrl(YELLOW, YELLOW, YELLOW, BLACK, 2.0f);
//
// 外接体对象
//
struct BoundingBox
{
BoundingBox();
bool isPointInside(D3DXVECTOR3& p);
D3DXVECTOR3 _min;
D3DXVECTOR3 _max;
};
struct BoundingSphere
{
BoundingSphere();
D3DXVECTOR3 _center;
float _radius;
};
//
// Constants
//
const float INFINITY = FLT_MAX;
const float EPSILON = 0.001f;
// Function references "desert.bmp" internally. This file must
// be in the working directory.
bool DrawBasicScene(
IDirect3DDevice9* device,// Pass in 0 for cleanup.
float scale); // uniform scale
struct Vertex
{
Vertex(){}
Vertex(float x, float y, float z,
float nx, float ny, float nz, float u, float v)
{
_x = x; _y = y; _z = z;
_nx = nx; _ny = ny; _nz = nz;
_u = u; _v = v;
}
float _x, _y, _z, _nx, _ny, _nz, _u, _v;
static const DWORD FVF;
};
}
#endif
再来看camera.cpp的代码:
//
//
// File: camera.cpp
//
// Author: Frank Luna (C) All Rights Reserved
//
// System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0
//
// Desc: Defines a camera's position and orientation.
//
//
#include "camera.h"
/*
这里我们增加了一个Camera类的设计,首先使用了4个摄像机向量,右向量,上向量,观察向量以及位置向量来定义摄像机相对于
世界坐标系的位置和朝向。这些向量实质上为相对世界坐标系描述的摄像机定义了一个局部坐标系。由于右向量,上向量和观察向量定义了
摄像机在世界坐标系中的朝向,有时我们也将这三个向量统称为方向向量。方向向量必须是标准正交的。如果一个向量
集中的向量都彼此正交,并且均为1,则称该向量是标准正交的。前面,我们提到,标准正交矩阵的一个重要性质是其逆矩阵与其转置矩阵相等。
用上述4个向