SimpleMath.cpp, .h, .inl
Git으로 공유 중인 DirectXTK12 내에서 제공하는 수학 관련 클래스
계산 최적화 및 행렬의 전치, 역행렬, up vector, right vector 등을 쉽게 구할 수 있도록 도와주고
행렬 변환 시 필요한 것들을 만들 수 있음
해당 라이브러리는 오른손 좌표계를 기준으로 만들어져 있음
class Component
{
public:
...
public:
virtual void Awake() { }
virtual void Start() { }
virtual void Update() { }
virtual void LateUpdate() { }
virtual void FinalUpdate() { }
...
};
유저 스크립트에서 사용되지 않고 엔진에서 사용할만 FinalUpdate 함수 추가
모든 메쉬들의 업데이트가 끝난 뒤 행렬 계산을 위함
position, rotation, scale
최상위 객체의 경우 월드 좌표계를 기준으로하는 값이지만,
하위 객체일 경우 parent 객체의 로컬 좌표계를 기준으로하는 값임
class Transform : public Component
{
public:
...
private:
Vec3 _localPosition = {};
Vec3 _localRotation = {};
Vec3 _localScale = { 1.f, 1.f, 1.f };
Matrix _matLocal = {};
Matrix _matWorld = {};
weak_ptr<Transform> _parent;
};
transform에서 자신의 local 정보들과 parent를 정의
void Transform::FinalUpdate()
{
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;
_matWorld = _matLocal * _parent->GetLocalToWorldMatrix();
}
FinalUpdate 함수에서 자신의 정보들을 가지고 행렬들을 만든다.
SRT를 곱하여 local 변환 함수를 만들고
local에서 world 변환 행렬을 곱하여 world 좌표계 행렬을 만든다.
추후 회전 행렬은 사원수로 교체
struct TransformParams
{
Matrix matWVP;
};
Transform 클래스에서 관리하던 TransformMatrix를 위와 같이 변경
cbuffer TRANSFORM_PARAMS : register(b0)
{
row_major matrix matWVP;
};
TransformMatrix를 사용하던 쉐이더 파일 수정
쉐이더에서 행렬을 접근하는 방식과 DirectX에서 행렬을 접근하는 방식이 다르기 때문에
row_major와 같이 명시적으로 알려줘야 함
VS_OUT VS_Main(VS_IN input)
{
...
output.pos = mul(float4(input.pos, 1.f), matWVP);
...
return output;
}
입력된 좌표 값과 MVP 행렬을 곱하여 투영 위치를 계산
해당 값은 위치이기 때문에 1.f를 추가
enum class PROJECTION_TYPE
{
PERSPECTIVE,
ORTHOGRAPHIC,
};
카메라가 가지는 두 가지 타입
class Camera : public Component
{
public:
...
private:
PROJECTION_TYPE _type = PROJECTION_TYPE::PERSPECTIVE;
float _near = 1.f;
float _far = 1000.f;
float _fov = XM_PI / 4.f;
float _scale = 1.f;
Matrix _matView = {};
Matrix _matProjection = {};
...
};
카메라는 기본적인 near, far, fov 등의 투영 시 필요한 값들을 가지도록 정의
void Camera::FinalUpdate()
{
_matView = GetTransform()->GetLocalToWorldMatrix().Invert();
...
if (_type == PROJECTION_TYPE::PERSPECTIVE)
_matProjection = ::XMMatrixPerspectiveFovLH(_fov, width / height, _near, _far);
else
_matProjection = ::XMMatrixOrthographicLH(width * _scale, height * _scale, _near, _far);
...
}
카메라의 월드 변환 행렬의 역행렬을 구함 => camera view 변환 행렬
DirectX 함수를 이용하여 투영 변환 행렬을 구한다.
(SimplaMath 투영 변환 행렬은 오른손 좌표계 기준)
void Transform::PushData()
{
Matrix matWVP = _matWorld * Camera::S_MatView * Camera::S_MatProjection;
CONST_BUFFER(CONSTANT_BUFFER_TYPE::TRANSFORM)->PushData(&matWVP, sizeof(matWVP));
}
PushData 함수가 불릴 때 constant buffer에 MVP 변환 행렬을 업로드
void MeshRenderer::Render()
{
GetTransform()->PushData();
_material->PushData();
_mesh->Render();
}
MeshRenderer에서 렌더링 시 transform과 material의 데이터를 GPU에 업로드 후
mesh를 렌더링 한다.
또한 Render 함수가 update 함수에서 불렸는데
이를 게임 로직 업데이트 부분과 렌더링 부분을 나누기 위하여 해당 부분을 삭제함
void Engine::Update()
{
...
GET_SINGLE(SceneManager)->Update();
Render();
...
}
void Engine::Render()
{
RenderBegin();
GET_SINGLE(SceneManager)->Render();
RenderEnd();
}
엔진에서 update로 로직과 렌더링을 모두 하던 부분을 분리
임시적으로 scene manager가 오브젝트들을 렌더링 하도록 구현
void SceneManager::Render()
{
...
const vector<shared_ptr<GameObject>>& gameObjects = _activeScene->GetGameObjects();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetCamera() == nullptr)
continue;
gameObject->GetCamera()->Render();
}
}
Scene에서 카메라 객체를 찾아 카메라를 렌더링
=>
light 추가 후 수정
shared_ptr<Scene> SceneManager::LoadTestScene()
{
...
shared_ptr<GameObject> camera = make_shared<GameObject>();
camera->AddComponent(make_shared<Transform>());
camera->AddComponent(make_shared<Camera>());
camera->GetTransform()->SetLocalPosition(Vec3(0.f, 100.f, 0.f));
scene->AddGameObject(camera);
}
Scene에 카메라를 추가하여 테스트