이번 시간에는 에러 발생 시 이를 제대로 처리해줄 수 있도록 C++ exception을 활용하여 기능을 추가할 것이다. 커스텀 Exception 클래스를 정의하자. 여기서의 핵심이 되는 내용은 whatBuffer와 what()인데, stringstream을 활용해 타입과 로그 string을 whatBuffer에 저장하고 whatBuffer.c_str()으로 char*를 반환한다. 이때 그냥 한번에 return oss.str().c_str()을 하지 않는 이유는 stream의 특성 상 함수 종료시 삭제되기 때문에 (정확히는 stream은 copy가 불가능하므로 함수의 반환값으로 lvalue stream을 사용할 수 없는 것) 함수 외부의 클래스 멤버로 저장된 whatBuffer에 데이터를 저장해둔 후 이를..
지금까지 만든 내용들을 사용하기 편하도록 프레임워크의 형태로 만들어보자. 우선 winapi 헤더를 직접 define하는 대신 별도의 헤더를 정의해 거기서 window 헤더를 define해주고 대신 그 헤더를 define해주자. 사실 이런 방식은 다른 프로젝트에서도 흔히 볼 수 있는 방식인데, WinApi를 사용할 때 특히 이 부분이 중요한 이유는, 윈도우api가 자체적으로 정의하는 요소들이 프로젝트 내부에서 문제를 일으킬 수 있기 때문이다. 한가지 예시로, 아래 헤더에서 #define NOMINMAX는 windows minmax 사용해제 옵션 매크로를 켜준 것으로, 이걸 켜주지 않으면 std::min std::max 등과 충돌해 예기치 못한(잡기도 힘든) 버그들이 발생할 수 있다. 추가로, 이 헤더를 정..
이번 시간에는 WM_CHAR 메세지와 마우스 관련 메세지 처리에 대해 알아보자. 프로그램 실행 후 알파뱃 키를 누르면 WM_CHAR과 WM_KEYDOWN 둘다 뜨는 것을 볼 수 있는데, 이 둘은 용도가 다르다. WM_CHAR은 텍스트 인풋을 받는다거나 할 때 사용되는 메세지로, 알파뱃키(+엔터나 스페이스바와 같은 일부 특수한 경우)에 대해서만 호출된다. 즉 F1을 누르면 WM_KEYDOWN은 뜨지만 WM_CHAR 메세지는 받지 않는다. 또 대소문자 구분(Shift)없이 누른 키에 대한 값을 출력했던 WM_KEYDOWN과 달리, WM_CHAR은 쉬프트 눌린 여부에 따라 파라미터 값도 변한다. 그리고 이렇게 어떤 상황에서 WM_CHAR을 출력해야하는지를 결정하는 과정이 앞서 대략적인 흐름을 살필 때 봤던 T..
지난 시간에 이어서 윈도우 메세지를 계속 다뤄보자. 시작하기에 앞서, 윈도우 MSDN에는 메세지 하나하나에 대한 개별적인 항목은 있으나 메세지들의 목록이 없어 불편하기 때문에, 대신 사용할 수 있는 사이트 하나를 기재한다. https://wiki.winehq.org/List_Of_Windows_Messages 다만 여기에는 목록만 있을 뿐 어떤게 자주 쓰이는지에 대한 정보는 없기 때문에, 편의를 위해 우리의 커스텀 WndProc이 어떤 메세지를 수신할 때마다 그 메세지의 이름과 lParam, wParam을 출력해주는 WindowsMessageMap이라는 객체를 만들어 사용하자. 또 이 객체에는 자주 쓰는 메세지들에 대해서는 메세지 int와 메세지 이름을 맵핑시켜주어 출력될 수 있게 만들자. 구현에 어려운..
앞서 2. WinMain에서 윈도우 OS는 윈도우(창)과 메세지 이렇게 두 가지가 핵심적인 역할을 한다고 언급한 바 있다. 그 중 이번에는 메세지를 자세히 살펴보자. 윈도우는 특정 사건이 발생했을 때(ex.클릭) 메세지를 보내 그에 맞는 행동을 실행하는 방식의 아키텍처이다. 이렇게 보면 message driven같기도 한데, 또 어떤 면에서는 (백그라운드에서 자원을 관리한다던지) event driven 같기도 하고, 사실 윈도우OS정도 되는 어마어마한 프로그램은 굳이 방식을 구분짓는 게 무의미하다고 생각이 들긴 한다. 아무튼 중요한 건 메세지를 보내 사건을 처리한다는 점이다. 윈도우에서 사건이 발생되면 다음과 같은 흐름으로 처리된다. 가로줄로 어플리케이션 단과 OS단을 구분지어놓은 것을 신경쓰며 살펴보자..
이번에는 실제로 눈에 보이는 윈도우 창을 띄워보자. 지난 시간에 우리의 Entry point인 WinMain 함수를 살펴보았는데, 그 세부적인 파라미터는 아래에서 확인할 수 있다. MSDN 링크: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain #include int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // register window class /* 윈도우 함수에서 앞으로 자주 볼 방식으로, 함수에 파라미터 몇십개를 일일히 넘겨주는 것보다, 이 데이터들이 들어있는 구조체를 ..
Direct3D를 사용해 무언가를 만들기 위해서 WinAPI를 익히는 건 사실상 필수적이다. 하지만 API 자체도 굉장히 낡고 복잡하고, 코드 자체도 읽기 쉽지 않기에 모든 것을 외우려고 하기 보다는 흐름과 사용법을 익힌다는 마인드로 접근하자. 빈 cpp 프로젝트를 만들고, Entry 지점이 될 cpp 파일 하나를 만들어 준다. Visual Studio를 사용한다면 필요에 따라 COnfiguration들을 바꿔주자. 또 본 학습 내용에서 C++ language standard는 가장 최신의 standard를 사용한다. 참고하자. Window 어플리케이션을 만들 때는 Entry point가 main()이 아니라 WinMain()으로 지정되어 있다. 함수 파라미터는 위와 같다. 함수에서 while(true)..
3D Engine 시리즈의 포스트들은 아래 깃허브 레포지토리에서도 확인하실 수 있습니다. https://github.com/hagukin/DxEngine 본 레포지토리는 바닥부터 3D 엔진을 만들어나가는 과정을 따라가며 필요한 지식들을 익히는 것을 목표로 만들어졌다. 대략적인 학습 과정은 위와 같으며, 3D 그래픽스, 프로그래밍, 선형대수학에 대한 선수지식이 있음을 가정한다. 앞으로 학습해야 할 내용이 방대하고, 기록 목적이 정보를 공유하는 것보다는 스스로 복습하기 위한 용도인 만큼, 본 레포지토리의 학습 기록에서는 내용을 읽기 쉽게 완벽한 정리하는 것에 초점을 두기보다는 나중에 내 스스로가 다시 살펴봤을 때 이해할 수 있을 정도로만 핵심 내용들만 간추려서 정리할 내용이다. 윈도우 API 파트는 추후 다..