bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

カメラ

ビルボード的なやつの確認のためにカメラクラスを作成した。
とりあえず動いているので良しとする。

カメラクラス
ビュー行列とプロジェクション行列の管理をする。

カメラ制御クラス
カメラを参照してdolly, pan, tiltを行う。
dolly(ドリー):カメラの前後移動
pan(パン):カメラを左右に振る
tilt(チルト):カメラを上下に振る


カメラクラス

#ifndef __cCamera_h__
#define __cCamera_h__


#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include <windows.h>

/*!
	@brief	カメラ
*/
class cCamera
{
public:
	cCamera();
	virtual ~cCamera();

	// ビューマトリックスを設定
	void setLookAtLH( const XMVECTOR& Pos, const XMVECTOR& LookAt, const XMVECTOR& Up );
	void setViewMatrix( XMFLOAT4X4 ViewMatrix );

	XMMATRIX getViewMatrix();

	// 射影行列を設定
	void setPerspectiveFovLH( FLOAT fovAngleY, FLOAT width, FLOAT height, FLOAT NearZ, FLOAT FarZ );
	void setProjectionMatrix( XMFLOAT4X4 ProjectionMatrix );

	XMMATRIX getProjectionMatrix();

	// カメラ
	const XMVECTOR& getPosition() { return m_Position; }
	const XMVECTOR& getLookAt() { return m_LookAt; }
	const XMVECTOR& getUp() { return m_Up; }

	XMVECTOR getDirection() { return m_LookAt - m_Position; }

protected:
	XMMATRIX m_ViewMatrix;
	XMMATRIX m_ProjectionMatrix;

	XMVECTOR m_Position;
	XMVECTOR m_LookAt;
	XMVECTOR m_Up;

	FLOAT m_FovAngleY;
	FLOAT m_NearZ;
	FLOAT m_FarZ;
	FLOAT m_Width;
	FLOAT m_Height;

};

#endif	// __cCamera_h__

#include "cCamera.h"

cCamera::cCamera()
{
	m_ViewMatrix = XMMatrixIdentity();
	m_ProjectionMatrix = XMMatrixIdentity();
	m_Position = XMVectorSet(0.f,0.f,0.f,0.f);
	m_LookAt = XMVectorSet(0.f,0.f,0.f,0.f);
	m_Up = XMVectorSet(0.f,0.f,0.f,0.f);
	m_NearZ = 0.01f;
	m_FarZ = 100.f;
	m_Width = 640.f;
	m_Height = 480.f;
}

cCamera::~cCamera()
{
}
// ビューマトリックスを設定
void cCamera::setLookAtLH( const XMVECTOR& Pos, const XMVECTOR& LookAt, const XMVECTOR& Up )
{
	m_Position = Pos;
	m_LookAt = LookAt;
	m_Up = Up;
	m_ViewMatrix = XMMatrixLookAtLH( Pos, LookAt, Up );
}

void cCamera::setViewMatrix( XMFLOAT4X4 ViewMatrix )
{
	m_ViewMatrix = XMLoadFloat4x4( &ViewMatrix );
}

XMMATRIX cCamera::getViewMatrix()
{
	return m_ViewMatrix;
}
// 射影行列を設定
void cCamera::setPerspectiveFovLH( FLOAT fovAngleY, FLOAT width, FLOAT height, FLOAT NearZ, FLOAT FarZ )
{
	m_FovAngleY = fovAngleY;
	m_Width = width;
	m_Height = height;
	m_NearZ = NearZ;
	m_FarZ = FarZ;
	m_ProjectionMatrix = XMMatrixPerspectiveFovLH( fovAngleY, width/height, NearZ, FarZ );
}

void cCamera::setProjectionMatrix( XMFLOAT4X4 ProjectionMatrix )
{
	m_ProjectionMatrix = XMLoadFloat4x4( &ProjectionMatrix );
}

XMMATRIX cCamera::getProjectionMatrix()
{
	return m_ProjectionMatrix;
}


カメラ制御クラス

#ifndef __cCameraController_h__
#define __cCameraController_h__

#include "cCamera.h"

/*!
	@brief	カメラ制御
	@note	カメラの参照を得て制御
*/
class cCameraController
{
public:
	cCameraController();
	virtual ~cCameraController();

	void bindCamera(cCamera* camera);
	bool isBindCamera() { return m_pCamera?true:false; }

	// カメラを視線方向の前に移動
	void dollyIn(float dist);
	// カメラを視線方向の後ろに移動
	void dollyOut(float dist);

	// カメラを右に振る
	void panRight(float angle);
	// カメラを左に振る
	void panLeft(float angle);

	// カメラを上に振る
	void tiltUp(float angle);
	// カメラを下に振る
	void tiltDown(float angle);

protected:
	void dolly(float dist);
	void pan(float angle);
	void tilt(float angle);

protected:
	cCamera*	m_pCamera;
};


#endif	// __cCameraController_h__
#include "cCameraController.h"


/*!
	@brief	カメラ制御
*/

/*!
	@brief	コンストラクタ
*/
cCameraController::cCameraController()
: m_pCamera(NULL)
{
}

/*!
	@brief	デストラクタ
	@note	参照しているカメラの開放はしない
*/
cCameraController::~cCameraController()
{
	// カメラの開放は行わない
}

/*!
	@brief	制御するカメラの設定
*/
void cCameraController::bindCamera(cCamera* camera)
{
	m_pCamera = camera;
}

/*!
	@brief	カメラを視線方向の前に移動
*/
void cCameraController::dollyIn(float dist)
{
	if(!m_pCamera) {
		return;
	}
	dolly(dist);
}

/*!
	@brief	カメラを視線方向の後ろに移動
*/
void cCameraController::dollyOut(float dist)
{
	if(!m_pCamera) {
		return;
	}
	dolly(-dist);
}

/*

/*!
	@brief	カメラを右に振る
*/
void cCameraController::panRight(float angle)
{
	if(!m_pCamera) {
		return;
	}
	pan(angle);
}

/*!
	@brief	カメラを左に振る
*/
void cCameraController::panLeft(float angle)
{
	if(!m_pCamera) {
		return;
	}
	pan(-angle);
}

/*!
	@brief	カメラを上に振る
*/
void cCameraController::tiltUp(float angle)
{
	if(!m_pCamera) {
		return;
	}
	tilt(angle);
}

/*!
	@brief	カメラを下に振る
*/
void cCameraController::tiltDown(float angle)
{
	if(!m_pCamera) {
		return;
	}
	tilt(-angle);
}


void cCameraController::dolly(float dist)
{
	
	XMVECTOR dir = m_pCamera->getDirection();
	dir = XMVector3Normalize(dir);
	XMVECTOR eye = m_pCamera->getPosition();
	eye += dist * dir;
	XMVECTOR at = m_pCamera->getLookAt();
	XMVECTOR up = m_pCamera->getUp();
	m_pCamera->setLookAtLH( eye, at, up );
}


void cCameraController::pan(float angle)
{
	XMVECTOR eye = m_pCamera->getPosition();
	XMVECTOR up = m_pCamera->getUp();
	XMVECTOR at = m_pCamera->getLookAt();

	XMVECTOR pos = at - eye;
	XMVECTOR dir = XMVector3Normalize(pos);
	XMVECTOR right = XMVector3Cross(up, dir);
	up = XMVector3Normalize(XMVector3Cross(dir, right));
	XMVECTOR rot = XMQuaternionRotationAxis(up,angle);
	at = XMVector3Rotate( pos, rot ) + eye;
	m_pCamera->setLookAtLH( eye, at, up );
}


void cCameraController::tilt(float angle)
{
	XMVECTOR eye = m_pCamera->getPosition();
	XMVECTOR up = m_pCamera->getUp();
	XMVECTOR at = m_pCamera->getLookAt();

	XMVECTOR pos = at - eye;
	XMVECTOR dir = XMVector3Normalize(pos);
	XMVECTOR right = XMVector3Cross(dir,up);//(up, dir);
	up = XMVector3Normalize(XMVector3Cross(right, dir));//(dir, right));
	XMVECTOR rot = XMQuaternionRotationAxis(right,angle);
	at = XMVector3Rotate( pos, rot ) + eye;
	m_pCamera->setLookAtLH( eye, at, up );
}