Camera

이승덱·2021년 8월 5일
0

Graphics&DirectX

목록 보기
20/37
post-thumbnail

Camera

  • 카메라를 통해 화면에 Object가 비춰지기 까지 여러 단계의 좌표변환이 일어난다.
1. Local좌표계에서 World 좌표계로 변환
	Matrix matScale = Matrix::CreateScale(_localScale);
	Matrix matRotation = Matrix::CreateRotationX(_localRotation.x);
	matRotation *= Matrix::CreateRotationY(_localRotation.y);
	matRotation *= Matrix::CreateRotationZ(_localRotation.z);
	Matrix matTranslation = Matrix::CreateTranslation(_localPosition);

	_matLocal = matScale * matRotation * matTranslation; // SRT
	_matWorld = _matLocal;

	shared_ptr<Transform> parent = GetParent().lock();
	if (parent != nullptr)
	{
		_matWorld *= parent->GetLocalToWorldMatrix();
	}
  • Object의 scale, position, rotation값을 통해서 월드 좌표계 변환 행렬을 구하여 _matWorld에 저장한다.
  • 만약 Parent를 가진 Object라면 Parent를 기준으로한 Local 값이기 때문에 Parent의 월드 변환 행렬을 곱해 실제 World 변환 행렬을 구해준다.
2. World좌표계에서 View로 변환
3. View에서 Projection으로 변환
void Camera::FinalUpdate()
{
	_matView = GetTransform()->GetLocalToWorldMatrix().Invert();

	float width = static_cast<float>(GEngine->GetWindow().width);
	float height = static_cast<float>(GEngine->GetWindow().height);

	if (_type == PROJECTION_TYPE::PERSPECTIVE)
		_matProjection = ::XMMatrixPerspectiveFovLH(_fov, width / height, _near, _far);	// 투영 변환 행렬
	else
		_matProjection = ::XMMatrixOrthographicLH(width * _scale, height * _scale, _near, _far);

	S_MatView = _matView;
	S_MatProjection = _matProjection;
}
  • Camera의 Transform을 통해서 View 변환 행렬을 구한다. 여기서 주의할 점은 .Invert()를 해야한다는 점이다. 그 이유는 카메라가 왼쪽 이동을 하면 Object는 화면상에서 카메라의 방향 반대인 오른쪽 이동을 해야 자연스럽기 때문에 Camera의 World변환 행렬의 역행렬을 View 변환 행렬로 사용한다. 구한 값을 _matView에 저장한다.
  • Projection 행렬은 그 타입에 따라 window의 크기 설정을 기반으로 계산하여 _matProjection에 저장한다.
4. Projection에서 Screen으로 변환
void Transform::PushData()
{
	// World * View * Projection  
	 Matrix matWVP = _matWorld * Camera::S_MatView * Camera::S_MatProjection;
	CONST_BUFFER(CONSTANT_BUFFER_TYPE::TRANSFORM)->PushData(&matWVP, sizeof(matWVP));
}
  • 행렬의 곱은 결합법칙이 성립하므로 각각의 단계에서 다음 단계로 변환할 때마다 행렬 곱을 실행하는 것 보다 모든 행렬곱을 먼저하고, 최종 변환 좌표 행렬을 구하여 Object 좌표에 행렬곱을 실행하는 것이 바람직하다.
    따라서
Matrix matWVP = _matWorld * Camera::S_MatView * Camera::S_MatProjection;

을 통하여 Screen에 실질적으로 비춰질 좌표를 구한 뒤,

CONST_BUFFER(CONSTANT_BUFFER_TYPE::TRANSFORM)->PushData(&matWVP, sizeof(matWVP));

를 통해 Transform을 담당하는 상수버퍼에 데이터를 넘겨준다.

Test

	// GameObject인 Camera의 Position을 가져옴
	Vec3 pos = GetTransform()->GetLocalPosition();

	if (INPUT->GetButton(KEY_TYPE::W))
		pos += GetTransform()->GetLook() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::S))
		pos -= GetTransform()->GetLook() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::A))
		pos -= GetTransform()->GetRight() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::D))
		pos += GetTransform()->GetRight() * _speed * DELTA_TIME;

	if (INPUT->GetButton(KEY_TYPE::Q))
	{
		Vec3 rotation = GetTransform()->GetLocalRotation();
		rotation.x += DELTA_TIME * 0.5f;
		GetTransform()->SetLocalRotation(rotation);
	}

	if (INPUT->GetButton(KEY_TYPE::E))
	{
		Vec3 rotation = GetTransform()->GetLocalRotation();
		rotation.x -= DELTA_TIME * 0.5f;
		GetTransform()->SetLocalRotation(rotation);
	}

	GetTransform()->SetLocalPosition(pos);
  • script를 카메라 Object에 추가하여 키보드를 통한 카메라 이동을 구현해 보았다.

빅토르가 시연을 도와주었다

  • 카메라가 우측 이동을 한 모습이다. 따라서 Object는 좌측 이동을 하였다.

  • 카메라가 좌측 이동을 한 모습이다. 따라서 Object는 우측 이동을 하였다.

  • 카메라가 전방 이동을 한 모습이다. 따라서 Object가 더 가깝게 그려진다.

  • 카메라가 후방 이동을 한 모습이다. 따라서 Object가 더 멀게 그려진다.

  • 카메라가 위쪽 방향으로 회전한 모습이다. 따라서 object가 아래에서 그려지며 약간 기울어져 그려진다.

  • 카메라가 위쪽 방향으로 회전한 모습이다. 따라서 object가 위에서 그려지며 약간 기울어져 그려진다.
profile
공부 기록용 블로그입니다

0개의 댓글