Как вы наверное могли уже понять нам понадобятся кватернионы и классы для работы с DirectInput'ом (статьи по этим темам можно посмотреть на этом сайте в разделах Алгоритмы и DirectX->DirectInput8 соответственно). Поэтому приступим сразу к реализации камеры.

    Первым делом нам надо настроить сопособ проецирования (между ортогональной проекцией и перспективной мы ни минуты не сомневаясь выберем последнюю). Делается это так:

	//выбираем матрицу которую будем устанавливать
	glMatrixMode( GL_PROJECTION );
	//загружаем единичную матрицу
	glLoadIdentity();
	//устанавливаем перспективную проекцию с углом обзора в 60 градусов
	//ближней плоскостью отсечения на расстоянии 1 и дальней на расстоянии 1000
	//здесь же 1.33 – это отношение ширины экрана к высоте (800/600)
	gluPerspective( 60 , 1.33 , 1 , 1000 );

    Как вы видите мы здесь использовали функцию gluPerspective, которая как видно про префиксу «glu» является частью библиотеки утилит. Для того чтобы компиляция прошла без ошибок, вам надо будет подключить файл glu.h и либку glu32.lib. Например так:

#pragma		comment ( lib , "glu32.lib" )

    Реализация класса камеры.

class Camera{
public:
	Vector4	target , norm , eye;
	Camera( void ){}
	Camera( Vector4 e , Vector4 n , Vector4 t ){
		eye = e;
		norm = n;
		target = t;
	}

	//basik movement functions
	void    MoveLeft( void );
	void    MoveRight( void );
	void    MoveForward( void );
	void    MoveBackward( void );
	void	MoveUp( void );
	void	MoveDown( void );

	//input functions
	void	KeyboardInput( Keyboard & );
	void	MouseInput( Mouse & , int , int );

	//init functions
	void	ReInitCamera( void );
	void	InitCamera( Vector4 , Vector4 , Vector4 );

	//camera rotation functions
	void	SpinAlongY( float );//Y - norm
};

    Здесь поля target , norm , eye - это соответственно вектор направления взгляда, вектор вертикали вида, и координаты точки визирования. Для облегчения восприятия рекомендую обратить свой взор на рисунок:

    Теперь быстренько пробежимся по методам класса. «Быстренко» потому что они до безобразия простые.

void	Camera::MoveUp( void ){
	eye += CAM_VELOSITY * norm;
}

void	Camera::MoveDown( void ){
	eye -= CAM_VELOSITY * norm; 
}

void    Camera::MoveLeft( void ){ 
	eye += CAM_VELOSITY * ( norm * target );
}

void    Camera::MoveRight( void ){
	eye += CAM_VELOSITY * ( target * norm );
}

void    Camera::MoveForward( void ){
	eye += CAM_VELOSITY * target;
}

void    Camera::MoveBackward( void ){
	eye -= CAM_VELOSITY * target;
}

void	Camera::KeyboardInput( cKeyboard &Keyboard ){
	Keyboard.GetKeyboardState();

	if( Keyboard.GetButtonState( DIK_W ) )MoveForward();
	if( Keyboard.GetButtonState( DIK_S ) )MoveBackward();
	if( Keyboard.GetButtonState( DIK_A ) )MoveLeft();
	if( Keyboard.GetButtonState( DIK_D ) )MoveRight();

	ReInitCamera();
}

void	Camera::ReInitCamera( void ){
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	gluLookAt(	eye.x , eye.y , eye.z , 
		eye.x + target.x , eye.y + target.y , eye.z + target.z , 
		norm.x , norm.y , norm.z );
}

void	Camera::InitCamera( cVector4 EYE , cVector4 TARGET , cVector4 NORM ){
	eye	= EYE;
	target	= TARGET;
	norm	= NORM;

	ReInitCamera();
}

void	Camera::SpinAlongX( float Angle ){
	cQuaternion		ry;
	ry.fRy( Angle );
	target = ry * target;
}

void	Camera::MouseInput( cMouse &Mouse , int SCREEN_WIDTH , int SCREEN_HEIGHT ){
	float	x( Mouse.GetOffset( 0 ) );
	float	AngleX( ( ( float )  -x ) / 300 );
	SpinAlongX( AngleX );
	SetCursorPos( SCREEN_WIDTH / 2 , SCREEN_HEIGHT / 2 );
	ReInitCamera();
}

    Здесь CAM_VELOSITY – это некоторая константа, которая хранит скорость перемещения камеры. Далее:

	//сообщаем системе, что сейчас будем менять матрицу вида
	glMatrixMode( GL_MODELVIEW ); 
	glLoadIdentity();
	//передаем параметры положения камеры
	gluLookAt(	eye.x , eye.y , eye.z , 
		eye.x + target.x , eye.y + target.y , eye.z + target.z , 
		norm.x , norm.y , norm.z );

    Вот вроде и все. Просто да?

    Исходники можно скачать здесь.