-
Component class

- enum class로 Component에 필요한 정보들을 enum으로 들고 있을 것이다.
- 이때 Script말고 Transform, MeshRnederer, Camera, Animator는 하나만 존재할 것이고 Script나 나중에 만들 것 들은 여러개 가지고 있을 수도 있다
- enum으로 FIXED_COMPONENT_COUNT의 시작 번호를 ComponentType::End -1를 통해 Index로 접근이 가능 할 수 있도록 만들어 준다

- Component 클래스에 Start처럼 게임이 시작 됐을 때 값을 초기화 해주거나 Update처럼 매 프레임 Update되는 정보를 변경해주는 함수 뿐만 아니라 Awake 처럼 게임이 시작되기 전 값이 호출이 되거나 Update보다 늦게 Update를 하는 함수 등을 가상화 함수로 만들어준다

- SetGameObject 함수에서 GameObject 타입의 변수를 가져와 owner 변수에 저장하면서 이를 통해 Render나 Transform등의 정보를 가져올 수 있게 매개변수로 저장해주는 함수이다

- SetGameObject에서 owner 변수에 현재 GameObject 대한 정보를 저장해 줬으므로 두 함수에선 owner를 통해 필요한 정보를 바로 가져올 수 있게 함수로 만든것이다
- 이때 Weak_Ptr<>로 변수를 만들었기 때문에 lock()을 통해 Shared_Ptr<>로 만들어 사용할 수 있게 해줘야 한다
-
GameObject class

- stl에서 제공되는 array로 배열을 만들어 디버깅 모드에서 배열의 index를 초과하는 경우를 사전에 미리 잡아줄 수 있게 하였다
- 이때 Component.h에서 FIXED_COMPONENT_COUNT 를 enum으로 만들었으므로 ComponentType의 갯수만큼 배열을 만들어 사용할 수 있게 한다
- 벡터를 통해 MonoBehavior 객체를 배열로 만들어 여러 개의 스크립트를 관리할 수 있도록 해줄 것이다
-
MonoBehaviour class

- Component Class를 상속받아 만든 이 클래스는 스크립트를 어떤 게임 오브젝트에 붙여 생명력을 불어넣을 수 있게 만들 클래스이다
- 부모 클래스에 가상화 되어있는 함수 중 사용할 함수만 재정의 해준다

- 부모 클래스인 Component 클래스의 생성자에서 ComponentType 변수를 입력받게 만들어 예측하지 못한 이상한 값이 들어오는 것을 막아준다

- Component에 변수를 입력받게 만들어 자식 클래스의 생성자에서는 부모 클래스의 생성자에게 내가 어떠한 타입의 정보를 사용할 것인지 알려줄 수 있게 되는 것이다
-
Transform class

- Transform class에서 생성자 역시 ComponentType을 알려주어 Component class에게 어떠한 타입의 정보를 사용하는지 알려준다

- 기존에 UpdateTransform에서 TransformNormal 함수를 통해 월드 행렬 matWorld에서 right, up, look을 가져오게 구현을 했지만 다른 방법도 존재한다

- 이처럼 matWorld에 Right, Up, Backward를 가져오는 함수가 존재하므로 이러한 방법도 있단걸 알아두자
- TransformNormal VS TransformCoord
- TransformNormal 함수는 위치가 아닌 방향만을 원할 때 사용하여 방향 벡터를 구하는 함수이다
- TransformCoord 함수는 연산을 통해 위치 값을 구하는 함수이므로 위치가 바뀌거나 하는 등 이를 사용한다
-
GameObject class

- Component class에 있는 함수와 같은 함수들을 만들어 줌으로써 GameObject에서 내가 들고있는 모든 Component를 대상으로 똑같은 함수들을 호출하는 기능으로 사용할 것이다

- Render 함수에서는 GameObject에 Rnedr를 하는 기능을 직접 넣어주는 것이 아닌 렌더링을 관리하는 부품을 넣어주고 이것이 있으면 렌더링을 하고, 존재하지 않으면 렌더링을 하지 않는 방식으로 기능을 할 것이다

- 어떠한 ComponentType을 지정해주면 그 ComponentType에 해당하는 FixedComponent를 전달해주는 기능을 할 함수이다

- GameObject 대상으로 Transform을 빠르게 가져올 수 있게 해주거나 주인의 Transform 정보등을 가져올 수 있는 helper 함수이다
-
GameObject class

- Transform은 무조건 적으로 하나가 존재해야 하므로 GameObject내에 어거지로 가지고 있는 것이 아닌 부품화 하여 Component 배열이 들고 있을 수 있게 만들어야 한다
- 이처럼 component에 GameObject를 셋팅해주고, component로부터 현재 Type을 가져와 고고정된 Component Type들이면 m_arComponent[index]에 component를 저장해준다
- 그렇지 않다면 현재는 고정되지 않은 ComponentType은 Scripts만 존재하므로 m_vScripts에 component를 MonoBehaviour의 *로 캐스팅해 push_back해준다

- 이때 Shared_from_this()를 사용하기 위해서 반드시 enable_shared_form_this<>를 반드시 넣어줘야한다
- 스마트포인터를 사용할 때 Shared_Ptr<>(this)를 그냥 넘겨주게 되면 레퍼런스 카운터를 이중으로 관리하여 문제가 생기기 때문에 반드시 shared_form_this()를 사용해야 한다
- 이때 enable_shared_form_this<>에서 Weak_Ptr을 만들어 반환해 주는데 시간이 좀 걸리기 때문에 생성자에서는 사용하면 오류가 생긴다

- Transform은 반드시 하나가 존재해야 하므로 Transform을 얻어오거나, 새로 만들어주는 함수를 구현해준다

- 이제 Transform 변수들이 사라져 오류가 생기므로 GetOrAddTransform을 통해 Transform을 가져오거나 만들어준 뒤 월드 행렬을 가져와준다
-
결과

- 지금까지 작업을 통해 이미지가 잘 나와야 한다
-
Camera class
- Camera class 역시 Component class를 상속받아 만들어 준다
- 이때 Camera가 존재하지 않으면 화면이 보이지 않을 것이다

- enum class로 ProjectionType을 정수로 나타낼 수 있게 만들어준다
- 이를 통해 카메라가 원근 투영과 직교 투영을 하게 만들 것이다

- 물체를 만들었을 때 shader에서 카메라와 연관성이 있는 행렬은 View와 Projection이다
- View는 카메라의 위치와 카메라가 바라보는 look 벡터로 만드는 것이 View 변환 행렬이었고, 이를 통해 비율로 만들어 주는 것이 Projection 변환 행렬이였다
- 그래서 View와 Projection은 카메라랑만 연관되어 있으므로 별도로 Camera라는 버퍼를 만들어 한번만 넘겨줘도 된다
- TransformData는 모든 물체가 각각 가지고 있으므로 물체를 그릴때 마다 버퍼를 넘겨줘야 하는데 그럴 필요가 없다는 뜻이다

- 따라서 카메라는 왠만하면 하나만 존재할것 이므로 언제 어디서든 View와 Projection 행렬을 사용할 수 있게 static 변수로 만들어 초기화 해준다
- 카메라가 많아지거나 다른 구조로 바꾸게 되면 바뀔 수 있다

- UpdateMatrix 함수에서는 View와 Projection 행렬을 구해줄 것이다
- 카메라가 정확하게 World와 겹치는 위치에 존재한다면 View를 Matrix::Identity로 사용이 가능할 것이지만 그렇지 않기 때문에 카메라가 바라보는 방향과 임의의 윗쪽 방향 벡터 값의 외적을 통해 Right 벡터를 구해주고, 다시 바라보는 방향의 벡터와 Right 벡터의 외적을 통해 카메라의 Up 벡터를 구할 수 있다
- 이를 구해주는 함수가 ::XMMatrixLookAtLH 함수가 있다
- 이 함수는 카메라가 존재하는 위치, 카메라가 바라보고 있는 앞 방향, 임의의 윗쪽 방향을 넘겨줘야 하므로 각각을 구해 넘겨준다
- 조금더 쉬운 방법은 GetTransform()을 통해 World 행렬을 가져와 역행렬을 구해주면 된다
- 왜 역행렬을 구하면 되는가?
- 카메라를 기준에서 월드를 기준으로 바꾸는 행렬이 World변환 행렬이였는데 이를 반대로 하는것은 World 변환 행렬의 역행렬이기 때문에 가능하다
- Projection을 수하는 방법은 ProjectionType에 따라 XMMatrixPerspectiveFovLH, XMMatrixOrthographicLH를 사용하여 원근 투영인지 직교 투영인지를 연산하여 Projection변수에 저장해준다
-
Game class

- 테스트를 위해 Game class에 GameObject로 monster 변수와 camera 변수를 만들어 초기화 및 Update, Render를 해준다
-
다음 시간 할일
- shader에서 cbuffer를 통해 TransformData를 넘겨주는 부분에서 View와 Projection을 분리시킬 것이다
- 현재 GameObject 클래스는 카메라와 GameObject를 한번에 모두 관리하고 있는데 이때 cbuffer에 World를 넘겨주는 것을 따로 빼줄것이다
- 그 이유는 카메라한태는 그려지지 않을 것이기 때문에 굳이 필요하지 않다
- Weak_Ptr<>
- Weak_Ptr을 lock()을 하게되면 Shared_Ptr로 만들 수 있다
- Shared_from_this
- shared_ptr 대신 사용할 수 있는 키워드이다
- shared_ptr로 this를 넘기면 레퍼런스 카운트를 2중으로 관리하기 때문에 메모리 누수가 발생하기 때문에 사용하면 안된다
- enable_shared_from_this<>
- Shared_from_this를 사용하기 위해서는 클래스에서 반드시 enable_shared_from_this<>로 자기 클래스를 반드시 상속받드시 만들어 줘야한다
- 이는 weak_ptr을 가지고 있고 생성자 단계에서 자기 자신에 대한 스마트 포인터를 weak_ptr에 넘겨준다
- weak_ptr을 채워주고 shared_from_this를 사용해야 하므로 생성자에서 shared_from_this를 콜하면 안된다