어제 코딩 테스트 보느라 오랜만에 커피를 마셨는데 그 때문인지 새벽에 한숨도 자지 못했습니다.

누워서 멀뚱멀뚱 거리기 애매해 새벽부터 운동 가고 조금 일찍 개발을 시작했는데,

아침 먹고 나니까 거짓말처럼 눈이 감겨서 2시간 정도 눈을 붙인 것 같습니다.

전반적으로 집중력이 좀 떨어지는 하루였습니다.

 

Exit Climb 부분의 Animation이 제대로 재생되지 않는 문제를 건드려보았습니다.

Animation 조건문이나 State 이동 조건 등을 만져보았는데 별 다른 소득을 얻지 못했습니다.

아무리 생각해도 조건이 틀린 것 같다는 생각이 들지 않습니다.

 

그래서 혹 무언가 잘못 생각한 것이 있는가 싶어 Overlap Trigger 값을 로그로 찍어보려 하는데,

Client에서만 출력을 해서 정확히 알아보고 싶은데 조건을 잘못잡고 있습니다.

또한 이전에 RPC 부분에서 실제 값과 로그가 찍히는 값의 순서 차이로 인해

명확한 값을 잡지 못하는 것도 발목을 잡는 요소 중 하나입니다.

 

우선 다음에는 조건문을 정확히 파악해서 제대로 된 로그를 찍어보고자 합니다.

그 뒤에 State 이동 조건이 정확한지 확인해볼 예정입니다.

만약에 조건문이 잘못 짜여졌다면 다행이지만,

조건문이 정상이라면 완전히 암흑으로 문제가 빠졌다는 것이기에 걱정이 좀 됩니다.

 

다음에는 좀 더 컨디션 조절을 해서 더 집중하고자 합니다.

 

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.20 개발일지  (0) 2020.06.20
20.06.15 개발일지  (0) 2020.06.17
20.06.11 개발일지  (0) 2020.06.11
20.06.08 개발일지  (0) 2020.06.08
20.06.06 개발일지  (0) 2020.06.06

내용에 앞서 글을 작성하는 이유를 간단히 적습니다.

 

몇 주 전, 여러 회사에 입사 지원서를 넣었고 그 중 한 회사의 온라인 코딩 테스트를 오늘 보게 되었습니다.

알고리즘에 대해서는 기본은 한다고 생각을 했는데 오늘 큰 실수를 두번 하여 4문제 중 2문제 밖에 맞추지 못했습니다.

이에 상당한 충격과 조금은 현실 직시를 하게 되었습니다.

 

원래는 화요일에 Baekjoon 사이트에서 모의 테스트를 한달에 한번 보려고 계획 했습니다만,

조금 더 시간을 투자해야 할 것 같아 월요일부터 토요일까지 하루에 한문제씩 풀어보려 합니다.

 

https://www.acmicpc.net/problem/11444

 

11444번: 피보나치 수 6

첫째 줄에 n이 주어진다. n은 1,000,000,000,000,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

오늘 푼 문제는 [피보나치 수 6]입니다.

10^18 번째까지의 피보나치수를 1초 안에 연산하는 문제였습니다.

예전에 한번 풀어보려 했으나 실패하고, 그저께 다시 한번 도전 했다가 실패하고 오늘에서야 성공한 문제입니다.

 

처음에는 단순히 DP로 해결을 할 수 있을 줄 알았습니다.

하지만 이를 담을 수 있는 배열을 선언할 수 없어 DP를 사용할 수 없었습니다.

 

그 다음에는 실력 좋은 선배에게 조언을 구했습니다.

그러자 선배가 "피보나치에 메모리는 2개면 충분하다."라고 귀뜸해줬습니다.

아래차 항에서부터 윗차 항까지 연산을 하면서 덮어 쓰면 되기 때문입니다.

하지만 1초 안에 모든 연산을 할 수 없었습니다.

 

오늘은 위 두가지를 모두 실패하고

피보나치 수열의 윗차항에서 아랫차항으로 내려가면서 풀어내리면서 규칙을 찾아보았습니다.

그러자 한가지 규칙이 보였습니다.

피보나치 수열을 f(i)라 했을 때, 

 

f(n) = f(n -1) + f(n - 2) = 2f(n - 2) + f(n - 3)  = 3f(n - 3) + 2f(n - 4)..

이 때 

f(1) = f(2) = 1, f(3) = 2, f(4) = 3이므로 이를 위 식에 대입하면

f(n) = f(2)f(n - 1) + f(1)f(n - 2) = f(3)f(n - 2) + f(2)f(n - 3) = f(4)f(n - 3) + f(3)f(n - 4)...

이렇게 변합니다.

 

즉 f(n) = f(k + 1)f(n - k) + f(k)f(n - k - 1)이라는 식이 나옵니다.

이 때 연산을 가장 적게 할 수 있는 방법은 binary search. 즉 k = n / 2일 때입니다.

 

위 연산을 재귀함수로 풀고, memory로 set을 사용해 [k : f(k)]를 저장해 연산 횟수를 줄였습니다.

10^18승일 때 최대 연산이 540회만 발생하는 것입니다.

이 덕분에 오늘에서야 문제를 해결할 수 있었습니다.

 

코드를 보고 싶으신 분들은 아래 접은 글을 풀어서 보십시오.

더보기
#include <iostream>
#include <map>
#include <algorithm>

using namespace std;

const unsigned int FIBOLIMIT = 1000000007;

unsigned long long getFibo(map<unsigned long long, unsigned long long>& fibo, unsigned long long n)
{
    unsigned long long half = (unsigned long long)(n / 2);
    auto index = fibo.find(n);
    if (index != fibo.end())
    {
        return index->second;
    }
    else
    {
        unsigned long long a = (getFibo(fibo, half + 1) % FIBOLIMIT);
        unsigned long long b = (getFibo(fibo, n - half) % FIBOLIMIT);
        unsigned long long c = (getFibo(fibo, half) % FIBOLIMIT);
        unsigned long long d = (getFibo(fibo, n - half - 1) % FIBOLIMIT);
        fibo.insert(make_pair(n, (a * b + c * d) % FIBOLIMIT));
        return fibo[n];
    }
}

int main()
{
    unsigned long long n;
    map<unsigned long long, unsigned long long> fibo;
    fibo.insert(make_pair(0, 0));
    fibo.insert(make_pair(1, 1));
    fibo.insert(make_pair(2, 1));
    cin >> n;
    cout << getFibo(fibo, n) << endl;;
    return 0;
}

내일 온라인 코딩 테스트가 있어 오늘 하루 알고리즘 위주로 공부합니다.

'개발일지' 카테고리의 다른 글

20.07.01 비개발일지  (0) 2020.07.01
20.06.23 비개발일지  (0) 2020.06.23
20.05.02 비개발일지  (0) 2020.05.02
20.04.25 비개발일지  (0) 2020.04.25
0701 리슨서버 골자 구축  (0) 2019.07.01

VS 2019에서 제공하는 DirectX12 기본 프로젝트는 다음과 같이 이루어져 있다.

 

이 프로젝트를 빌드 하면 다음과 같은 결과물을 얻을 수 있다.

이 때 전체적인 창을 생성하는 부분이 App.h, App.cpp이다.

// The main function is only used to initialize our IFrameworkView class.
[Platform::MTAThread]
int main(Platform::Array<Platform::String^>^)
{
	auto direct3DApplicationSource = ref new Direct3DApplicationSource();
	CoreApplication::Run(direct3DApplicationSource);
	return 0;
}

App.cpp 파일 안에 선언되어 있는 main 함수다.

그런데 우리가 알던 main 함수와 많이 다르다.

main 함수 앞에 처음 보는 선언도 있고, main 함수가 받는 parameter도, 그 형식도 낯설다.

이는 UWP(Universal Windows Platform)에서 사용하는 C++/CX의 문법으로,

지금 여기서는 자세하게 설명하지 않을 것이다.

 

main 함수안에서는 Direct3DApplicationSource의 reference Object를 생성하고, CoreApplication에서 Run 함수에 parameter로 넘겨주면서 Run 함수를 선언하고 있다.

 

그렇다면 먼저 Direct3DApplicationSource를 보자.

ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
	virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView();
};
IFrameworkView^ Direct3DApplicationSource::CreateView()
{
	return ref new App();
}

간단히 설명하면, Direct3DApplicationSource는 Windows::ApplicationModel::Core::IFrameworkViewSource라는 Interface를 Implement 하는 Class이다.

IFrameworkViewSource 안에는 Windows::ApplicationModel::Core::IFrameworkView의 reference를 반환하는 CreateView() 라는 abstract function 하나가 선언되어 있다.

이 코드에서는 CreateView에서 App의 reference object를 생성해 반환한다.

즉, Direct3DApplicationSource는 App의 Factory라는 것이다.

 

그렇다면 이 App을 parameter로 받아서 실행되는 CoreApplication은 무엇일까?

이는 UWP에서 제공되는 Class로, 자세한 내용은 아래 링크로 대체한다.

https://docs.microsoft.com/en-us/uwp/api/windows.applicationmodel.core.coreapplication?view=winrt-19041

 

CoreApplication Class (Windows.ApplicationModel.Core) - Windows UWP applications

Enables apps to handle state changes, manage windows, and integrate with a variety of UI frameworks.

docs.microsoft.com

 

그렇다면 App은 어떤 내용들이 선언되어 있을까?

#include "pch.h"
#include "Common\DeviceResources.h"
#include "ExampleCreationMain.h"

namespace ExampleCreation
{
	// Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events.
	ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
	{
	public:
		App();

		// IFrameworkView methods.
		virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
		virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
		virtual void Load(Platform::String^ entryPoint);
		virtual void Run();
		virtual void Uninitialize();

	protected:
		// Application lifecycle event handlers.
		void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
		void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args);
		void OnResuming(Platform::Object^ sender, Platform::Object^ args);

		// Window event handlers.
		void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
		void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
		void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);

		// DisplayInformation event handlers.
		void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
		void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
		void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);

	private:
		// Private accessor for m_deviceResources, protects against device removed errors.
		std::shared_ptr<DX::DeviceResources> GetDeviceResources();

		std::shared_ptr<DX::DeviceResources> m_deviceResources;
		std::unique_ptr<ExampleCreationMain> m_main;
		bool m_windowClosed;
		bool m_windowVisible;
	};
}

주석에 App의 기능이 대략적으로 설명이 되어 있다.

우리가 실행시킬 어플리케이션을 Windows shell과 연결시키고, lifecycle 이벤트를 조종하는 역할을 한다.

이에 대한 내용은 함수들에 붙은 주석에서도 자세히 설명을 하고 있다.

 

따로 설명할 부분은 Field들이다.

bool로 선언된 두 개의 field들은 밑에서 따로 설명 할 예정이다.

이 외에 우리는 DeviceResources와 ExampleCreationMain를 가지고 있다.

 

DeviceResources는 DirectX device resource들과 관련된 모든 것을 다룬다.

창 크기, dpi부터 해서 d3d관련 변수들의 getter 함수들까지 제공한다.

ExampleCreationMain은 빌드를 했을 시 우리가 실제로 보게 되는 화면.

즉, 무지개빛 큐브가 회전하는 것을 선언하고 있는 부분이다.

 

사실상 이 두 부분이 DirectX를 공부하면서 우리가 머리로도, 손으로도 익혀야 하는 부분이다.

하지만 벌써부터 DirectX 부분으로 빠진다면 나중에 어떤 부분이 공부해야 할 부분이고,

어떤 부분이 넘어갈 수 있는 부분인지 햇갈릴 수 있다.

그러니 DeviceResources와 ExampleCreationMain은 뒤에 다시 언급하고,

우선은 App 함수의 구현부를 보면서 기능을 파악해보도록 한다.

 

App::App() :
	m_windowClosed(false),
	m_windowVisible(true)
{
}

App의 생성자는 m_windowClosed와 m_windowVisible 값을 초기화 해주고 있다.

이 생성자를 생성된 창이 열려 있고 화면 상에 표시가 되게 설정을 해주는 것 같다.

직접 창을 생성한다고 하지 않은 이유는 그 기능을 Initialize에서 해주고 있기 때문이다.

// The first method called when the IFrameworkView is being created.
void App::Initialize(CoreApplicationView^ applicationView)
{
	// Register event handlers for app lifecycle. This example includes Activated, so that we
	// can make the CoreWindow active and start rendering on the window.
	applicationView->Activated +=
		ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);

	CoreApplication::Suspending +=
		ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);

	CoreApplication::Resuming +=
		ref new EventHandler<Platform::Object^>(this, &App::OnResuming);
}

이 함수는 IFrameworkView가 생성 될 때 가장 먼저 호출이 된다.

내부적으로는 Application의 LifeCycle과 관련된 Event Handling이 이루어진다.

물론 여기서 사용되는 Event들도 App 안에서 선언을 해두고 있다.

void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{
	// Run() won't start until the CoreWindow is activated.
	CoreWindow::GetForCurrentThread()->Activate();
}

void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
{
	// Save app state asynchronously after requesting a deferral. Holding a deferral
	// indicates that the application is busy performing suspending operations. Be
	// aware that a deferral may not be held indefinitely. After about five seconds,
	// the app will be forced to exit.
	SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();

	create_task([this, deferral]()
	{
		m_main->OnSuspending();
		deferral->Complete();
	});
}

void App::OnResuming(Platform::Object^ sender, Platform::Object^ args)
{
	// Restore any data or state that was unloaded on suspend. By default, data
	// and state are persisted when resuming from suspend. Note that this event
	// does not occur if the app was previously terminated.

	m_main->OnResuming();
}

이 3가지는 선언, 중지, 재시작 시 호출되는 Event 함수들이다.

OnActivated는 현재 활성화 된 thread의 CoreWindow Instance 활성화 한다.

UWP에서 제공하는 함수로, 화면에 window를 표시 할 때 호출한다.

또한 Run 함수가 동작하기 위해서는 CoreWindow가 반드시 Activate 되어야 하기에, OnActivated에서 선언한다.

https://docs.microsoft.com/en-us/uwp/api/windows.ui.core.corewindow.getforcurrentthread?view=winrt-19041

 

CoreWindow.GetForCurrentThread Method (Windows.UI.Core) - Windows UWP applications

Gets the CoreWindow instance for the currently active thread.

docs.microsoft.com

 

OnSuspending은 app의 상태를 연기 요청이 들어온 이후 비동기적으로 저장한다.

연기 상태가 지속되는 것은 app이 종료 작업을 하기에 너무 바쁜 것을 의미한다.

때문에 5초간 연기 상태가 지속되면, app을 강제로 종료시킨다.

 

OnResuming은 종료 상태로부터 로드 되지 않은 모든 데이터나 상태들을 복구한다.

단, 앱이 종료되는 시점에서는 이 이벤트는 호출되지 않는다.

 

SetWindow 함수는 CoreWindow object가 생성 되었거나, 재생성 되었을 때 호출되는 함수다.

// Called when the CoreWindow object is created (or re-created).
void App::SetWindow(CoreWindow^ window)
{
	window->SizeChanged += 
		ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);

	window->VisibilityChanged +=
		ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);

	window->Closed += 
		ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);

	DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();

	currentDisplayInformation->DpiChanged +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);

	currentDisplayInformation->OrientationChanged +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);

	DisplayInformation::DisplayContentsInvalidated +=
		ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
}

이 안에서는 Initialize 함수와 마찬가지로, window의 상태 변화와 관련된 event handling들이 선언되어 있다.

역시 Event들은 App에서 선언하고 있다. 

대부분의 함수들은 눈에 들어올 것이다.

하지만 UWP에서 제공하고 있는 DisplayInformation::GetForCurrentView()은 낯설 것이다.

이 함수는 현재 thread의 CoreApplicationView와 연결되어 있는 DisplayInformation Instance를 반환한다.

이 DisplayInformation Instance는 view와 묶여 있고, 다른 thread에서는 사용할 수 없다.

https://docs.microsoft.com/en-us/uwp/api/windows.graphics.display.displayinformation.getforcurrentview?view=winrt-19041

 

DisplayInformation.GetForCurrentView Method (Windows.Graphics.Display) - Windows UWP applications

Gets the DisplayInformation instance associated with the current thread's CoreApplicationView. This DisplayInformation instance is tied to the view and cannot be used from other threads.

docs.microsoft.com

// Window event handlers.

void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
{
	GetDeviceResources()->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height));
	m_main->OnWindowSizeChanged();
}

void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
{
	m_windowVisible = args->Visible;
}

void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
{
	m_windowClosed = true;
}

// DisplayInformation event handlers.

void App::OnDpiChanged(DisplayInformation^ sender, Object^ args)
{
	// Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
	// if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
	// you should always retrieve it using the GetDpi method.
	// See DeviceResources.cpp for more details.
	GetDeviceResources()->SetDpi(sender->LogicalDpi);
	m_main->OnWindowSizeChanged();
}

void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
{
	GetDeviceResources()->SetCurrentOrientation(sender->CurrentOrientation);
	m_main->OnWindowSizeChanged();
}

void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
{
	GetDeviceResources()->ValidateDevice();
}

 이 Event 안의 함수들은 모두 DeviceResources에서 선언된 것들을 사용하고 있다.

그렇기에 지금은 각 Event 함수 이름을 보고 기능을 유추하는 것으로 넘어가면 될 것이다.

 

Load는 Run 함수가 호출 되기 전 외부 리소스들을 불러오거나, 활성화 하는 함수이다.

여기서는 App이 가지고 있는 ExampleCreationMain object인 m_main이 선언되어 있지 않을 때 새 object를 채워넣어준다.

// Initializes scene resources, or loads a previously saved app state.
void App::Load(Platform::String^ entryPoint)
{
	if (m_main == nullptr)
	{
		m_main = std::unique_ptr<ExampleCreationMain>(new ExampleCreationMain());
	}
}

 

대망의 Run 함수다. 이 함수는 window가 활성화 된 이후에 호출이 된다.

// This method is called after the window becomes active.
void App::Run()
{
	while (!m_windowClosed)
	{
		if (m_windowVisible)
		{
			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);

			auto commandQueue = GetDeviceResources()->GetCommandQueue();
			PIXBeginEvent(commandQueue, 0, L"Update");
			{
				m_main->Update();
			}
			PIXEndEvent(commandQueue);

			PIXBeginEvent(commandQueue, 0, L"Render");
			{
				if (m_main->Render())
				{
					GetDeviceResources()->Present();
				}
			}
			PIXEndEvent(commandQueue);
		}
		else
		{
			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
		}
	}
}

순서대로 살펴보자.

ProcessEvents는 dispatcher에게 input event queue에 있는 event들을 실행시키는 함수이다.

parameter로 받는 CoreProcessEventsOption은 몇 개의 event들을 실행시킬지를 나타낸다.

https://docs.microsoft.com/en-us/uwp/api/windows.ui.core.coredispatcher.processevents?view=winrt-19041

 

CoreDispatcher.ProcessEvents(CoreProcessEventsOption) Method (Windows.UI.Core) - Windows UWP applications

Starts the dispatcher processing the input event queue for this instance of CoreWindow.

docs.microsoft.com

그 아래에 PIXBeginEVent, PIXEndEvent는 PIX라는 라이브러리에서 선언된 함수이다.

PIX event를 이용해 특정 구역의 함수가 CPU에서 작동해야 하는지, 아니면 GPU에서 작동해야 하는지를 표시해주기도 하고, 중요한 작업을 표현하기도 한다.

Windows SDK에서는 오래된 버전인 pix.h를 제공한다. 이는 현재 제공 중인 pix3.h와 비슷한 기능들을 제공하고 있지만, PIX와는 쓸모 없고 호환되지 않는다.

https://devblogs.microsoft.com/pix/winpixeventruntime/

 

WinPixEventRuntime | PIX on Windows

PIX events are used to instrument your game, labeling regions of CPU or GPU work and marking important occurrences.  Including this instrumentation while developing the game can make PIX captures far nicer to work with. An “event” represents a region

devblogs.microsoft.com

마지막으로 App.h 상단부에 include 되어 있는 header들을 살펴보자.

#include "pch.h"
#include "Common\DeviceResources.h"
#include "ExampleCreationMain.h"

Common\DeviceResources.h와 ExampleCreationMain.h는 위에서 한차례 설명 했듯이, 따로 만들어줘야 하는 코드다.

남은 pch.h는 template에서 제공하는 공용 header이다.

#include <wrl.h>
#include <wrl/client.h>
#include <dxgi1_4.h>
#include <d3d12.h>
#include "Common\d3dx12.h"
#include <pix.h>
#include <DirectXColors.h>
#include <DirectXMath.h>
#include <memory>
#include <vector>
#include <agile.h>
#include <concrt.h>

#if defined(_DEBUG)
#include <dxgidebug.h>
#endif

wrl.h와 wrl/client.h는 WRL(Windows Runtime C++ Template Library)의 기능을 사용할 수 있는 header들이다.

이 부분에 대해서는 한 차례 탐구를 했다가 실패를 한 사례가 있는데, 적절한 블로그를 찾아서 링크를 공유한다.

https://megayuchi.com/2016/11/14/winrt-ccx-wrl/

 

WinRT, C++/CX , WRL

먼저 WinRT에 대해서 얘기해보자. Windows 8시절부터 Store App을 개발하던 프로그래머가 아니라면 좀 생소할 수도 있는데 Windows Runtime의 약자이고 Store App을 위한 새로운 Windows API이다. 공식적으로 소��

megayuchi.com

블로그에 정리된 내용을 옮겨오자면

  1. C++로 WinRT API를 사용할 수 있는 통로는 C++/CX와 WRL 두가지가 있다.
  2. WRL은 데스크탑 어플리케이션에서 WinRT API를 호출하거나 MS내부에서 사용할 목적으로 만들었던 것으로 보인다.
  3. MS에선 WRL로의 개발을 장려하고 싶지 않았다. C++로 개발하는 경우 C++/CX를 권장했다.
  4. Windows 8.x가 실패하고 새로운 국면에 접어들었다. 사람들은 여전히 데스크탑 어플리케이션을 원했고 데스크탑 어플리케이션은 Windows에 있어 여전히 중요한 영역이었다.
  5. 새로운 펜.잉크 API, Surface Dial과 같은 디바이스들을 데스크탑에서 사용해야할 필요가 있었고 WRL에 대해서 다시 신경을 쓰게 된것으로 보인다.
  6. 최근 C++/WinRT를 보면 사실상 UWP에서 C++/CX대신 WRL을 사용하게 된다. 만약 MS가 C++/WinRT를 지속적으로 밀게 된다면 사실살 WRL이 C++/CX를 밀어내고 UWP앱 개발도구의 메이저가 된다.

사실 지금은 크게 상관 없을 수 있다.

이 글을 읽는 사람이 있다면, 그 사람도 필시 게임 클라이언트 개발에 관심이 있는 사람일 것이다.

아직 직장을 경험해 보지 않고, 이 분야에 대해서 문외한인 내가 이렇다 저렇다 결론을 내릴 수 있을리가 없다.

다만 우리가 앞에서 대충 넘어갔던 것이 무엇이고, 현재 어떤 상황인지 대략 참고는 가능할 것이라 생각한다.

 

header 안에 "dx"가 있는 것들은 대체로 DirectX 출신이다.

dxgi1_4.h, d3d12.h, dxgidebug.h가 그러하다.

DirectXColors.h, DirectXMath.h도 일단은 DirectX를 사용하기 위해서는 필요하니 동일선상에 둘 수도 있다.

필요에 따라 선택할 수 있지만 DirectX를 사용한다면 이 5가지 header에 DirectXPackedVector.h, DirectXCollision.h는 선언을 해두는 편이 여러모로 편리할 것이다.

 

d3dx12.h MS에서 제공하는 D3D12 Helper Library에 속한 header이다. 

공식은 아니지만 사실상 DirectX는 Windows에서 거의 사용하지 않겠는가?

사용 여부는 실제로 현업에서 사용하는지를 알아보고 판단 할 것 같다.

 

pix.h는 위에서 한차례 설명했듯이 PIX 라이브러리 기능을 사용하는 header이다.

PIX와 호환은 안되지만, Windows SDK에 있어서 간단하게 추가할 수 있으니 그대로 사용하는 것이 편리할 것이다.

 

vector와 memory는 생략하겠다. 이는 C++에서 제공하는 것들이다.

 

agile.h는 MS Document에 검색해도 잘 나오지 않는다.

때문에 본인도 이 부분에 대해서는 확신이 적다. 그러니 참고 링크를 먼저 올리고, 정리를 해보고자 한다.

https://docs.microsoft.com/en-us/cpp/cppcx/platform-agile-class?view=vs-2019

 

Platform::Agile Class

Platform::Agile Class In this article --> Represents an object that has a MashalingBehavior=Standard as an agile object, which greatly reduces the chances for runtime threading exceptions. The Agile enables the non-agile object to call, or be called from,

docs.microsoft.com

https://docs.microsoft.com/en-us/cpp/cppcx/threading-and-marshaling-c-cx?view=vs-2019

 

Threading and Marshaling (C++/CX)

Threading and Marshaling (C++/CX) In this article --> In the vast majority of cases, instances of Windows Runtime classes, like standard C++ objects, can be accessed from any thread. Such classes are referred to as "agile". However, a small number of Windo

docs.microsoft.com

MS에서 agile은 말 그대로 agile한 object를 지칭하는 것 같다.

그 과정에 Threading과 Marshaling이 나오는데, Marshaling은 다음을 참고하자.

https://ko.wikipedia.org/wiki/%EB%A7%88%EC%83%AC%EB%A7%81_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)

 

마샬링 (컴퓨터 과학) - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 과학에서 마셜링(marshalling, l을 하나만 사용하여 marshaling이라고도 표기)이란 한 객체의 메모리에서 표현방식을 저장 또는 전송에 적합한 다른 데이터 형

ko.wikipedia.org

결국 agile은 Object를 빠르게 공유할 수 있는 것들. 혹은 그 속성을 지칭한다.

Object가 agile하려면 병렬화(threading)이나 직렬화(Marshaling)가 가능해야 하는데,

이것이 불가능한 것들을 가능한 형태로 변경 할 수 있도록 기능을 제공하는 것이 agile.h라고 생각된다.

 

concrt.h는 동시성 런타임과 관련된 header이다.

관련 내용을 찾아보았는데, 이 내용이 코드 내에서 어디에 어떻게 사용되었는지 파악하지 못했다.

우선은 관련 링크를 참조한다. 

https://docs.microsoft.com/ko-kr/cpp/parallel/concrt/overview-of-the-concurrency-runtime?view=vs-2019

 

동시성 런타임 개요

동시성 런타임 개요Overview of the Concurrency Runtime 이 문서의 내용 --> 이 문서에서는 동시성 런타임에 대한 개요를 제공합니다.This document provides an overview of the Concurrency Runtime. 또한 동시성 런타임의

docs.microsoft.com

이번 챕터의 최종 목표는 2가지이다.

1. 예시 Template 코드에서 Rendering 부분만 지워서 해당 부분에 필요한 내용만 채워넣으면 어떤 예시라도 바로바로 테스트가 가능한 형태로 가공하기.

2. Window Desktop Application으로 동일한 기능 구현하기.

 

제대로 시작하기 전에는 1번이 오래 걸리고 2번이 생각보다 쉽게 갈 것 같았다.

하지만 막상 어느정도 정리하고 나니까 1번이 가시권이고 2번이 까마득하다.

그도 그럴게 MS가 만든 Template라서 당연할 수 있지만, 코드 자체가 성능 면을 상당히 세심하게 고려하고 짜여졌다.

때문에 우리처럼 이를 보고 처음 공부하려는 사람들은 어려움이 적지 않다.

하물며 이걸 이해해가면서 다른 방식으로 프로그래밍이라니... 눈물이 앞을 가린다.

 

일단은 1번을 먼저 해놓고, 2번을 고민해보려 한다.

다음에는 앞에서 빼먹었던 ExampleCreationMain, DeviceResources 코드들 중심으로 분석을 하려 한다.

그 뒤에는 책에서의 입문 chapter를 정리하고, 예시 코드를 실제 이 프로젝트에서 구현해보겠다.

오늘은 Climb 상태에서 적절하게 재생되지 않는 Animation이 재생되도록 수정을 하였습니다.

 

이전에 새 구조를 구상 했는데 이미 구현된 구조랑 동일 했다고 한번 언급 했을 것입니다.

사실 두 구조에는 한가지 차이가 있습니다.

이미 구현된 구조체는 FullBodyMotion이 모두 하나의 FSM으로 구현되어 있습니다.

즉, 각 행동들은 State로 구분되고, Climb는 Conduit으로 구분되어 내부적으로 FSM을 다시 갖습니다.

하지만 새 구현체는 바로 Blend by IdleType으로 바로 Sub-FSM으로 구분됩니다.

이렇게 구현한 이유는 Climb는 Enter만 지나면 각자 다른 형태로라도 Idle 상태가 유지되기 때문입니다.

 

그래서 이전과 동일하지만, 조금 다른 구조를 적용하자 Enter Climb Animation이 작동하였습니다.

비록 아직은 Lower Enter만 확인했지만, 어차피 Upper 부분은

Ledge와 Enter/Exit 시 위치 보정을 해줘야 하기 때문에 당장 확인을 못합니다.

그러니 현재로써는 이정도가 성공적인 구현 수준인 것 같습니다.

 

여세를 몰아 Movement도 구현하였고, 이 또한 성공적으로 작동하였습니다.

Animation에 비해 이동 속도가 빠르지만, 이는 나중에 조절하면 됩니다.

 

다만 Exit 부분이 제대로 작동하지 않습니다.

조건문이 문제가 되는데 이 부분만 좀 더 노력해서 처리하면 그 다음은 다른 Climb Object들의 Animation.

그리고 Ledge 처리 하면서 Climb Enter/Exit Upper Side에서의 위치 보정을 하면 될 것 같습니다.

 

이 과정이 짧아도 2주는 걸릴 것 같고, 이게 되면 비로소야 Climb 기능이 완성이 됩니다.

그 뒤에는 Puzzle, Trap의 버그 수정 및 MultiPlay기능 적용, 그 뒤에는 Teleport Trap 개선과 VanishTrap 구현.

그리고 게임 편의성 및 더 그럴듯한 Character Movement 및 Animation 적용을 할 것입니다.

 

Climb 기능 완성을 6월 중으로 마무리 하고, Puzzle과 Trap쪽을 7월까지 마무리 하는 것이 목표입니다.

물론 그 전에 게임 회사에 입사하면 계획이 달라질것이지만.

 

이왕이면 언리얼이나 C++을 사용하는 회사에 입사를 했으면 합니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.15 개발일지  (0) 2020.06.17
20.06.15 개발일지  (0) 2020.06.15
20.06.08 개발일지  (0) 2020.06.08
20.06.06 개발일지  (0) 2020.06.06
20.06.04 개발일지  (0) 2020.06.04

새로 구상한 FSM을 적용하려고 보았더니 이전에 적용했던 것과 완벽히 동일한 것이었습니다.

 

차이점이라면 Entry Point를 잘못 잡았다는 것...

 

테스트 해보면서 필요 없는 부분을 깎아 냈는데 여전히 원하는대로 움직이지는 않습니다.

 

Animation을 Loop 하지 않았음에도 정상적으로 작동하지 않는 것이 혼란스럽습니다.

 

내일은 Project Rebuild를 해보려 합니다.

 

그래도 안된다면 Enter Animation을 Montage로 적용해보려 합니다.

 

예전에 언리얼 커뮤니티의 한 분이 "Montage에 지원하는 기능이 많아 가능하면 Montage로 처리하는 것이 더 좋다."라고 했던 기억이 있는데, 이 부분에 대해 실제로 어떤지는 잘 모르겠습니다.

 

Montage를 쓰지 않아도 되는 곳에서도 Montage를 쓰는 편이 좋은지, 필요한 곳에서만 써야 하는 것인지.

 

Animation 부분은 유난히 깊이 있게 하는 사람이 적어 정보를 구하기 힘든 것 같습니다.

 

 

그리고 당분간 개발 시간이 줄어들 것 같습니다.

 

요일을 줄이는 것은 아니고, 개발 하는 날에 개발하는 시간을 조금만 줄일 예정입니다.

 

그 이유는 상반기 입사 지원을 했던 회사 중 한 곳에서 온라인 테스트를 보라는 메일을 받았기 때문입니다.

 

금주 일요일에 보는데, 아마 다른 회사들도 2주 내로 온라인 테스트를 보라는 메일이 올 것 같습니다.

 

이 때문에 본 프로젝트 개발 시간을 조금 줄이고 온라인 테스트 준비를 하려 합니다.

 

 

날이 더워서 개발 능률이 불과 일주일 전보다 절반 가량 떨어진 것 같습니다.

 

빨리 회사 붙어서 에어콘 빵빵한 곳에서 코딩하고 싶습니다.

https://redchiken.tistory.com/136

 

20.05.26 - 2015 ACM-ICPC 연습

https://www.acmicpc.net/contest/view/116 2015 ACM-ICPC 연습 www.acmicpc.net 오늘 늦잠 잘 정도로 컨디션도 안좋고, 오른쪽 손목이 좋지 않아서 조금만 하려고 했습니다. 하지만 막상 문제를 풀려니까 저번에..

redchiken.tistory.com

풀수 있는 문제는 다 풀었고 이 뒤로는 넘기려고 합니다.

 

해결법은 예측이 가는데 너무 오래 잡으니까 도저히 손이 가지를 않습니다.

 

앞으로는 이런 하나의 문제 세트를 풀 때는 한달 단위로 시간을 제한해야 할 것 같습니다.

 

못풀었던 문제 중 Party는 아직 마땅한 해결법을 찾지 못했습니다.

Dynamic Programming을 쓰면 어떻게 될 것 같은데 구조를 명확히 떠올리지 못했습니다.

 

Save the computer는 Dynamic Programming을 쓸 것도 없이, 반복적인 계산으로 해결이 될 것 같습니다.

다만 이 계산을 유추해내는 과정이 수학적으로 복잡한 연산을 취해줘야 합니다.

 

Scorched Earth는 일반적인 식 하나로는 유추가 되지를 않았습니다.

풍속이 없는 경우, 동일 고도에 있는 경우, 동일 위도에 있는 경우 등에 대해 모두 경우를 나누어서 생각해야 합니다.

그 결과 적절한 식을 구하기는 했으나, 이를 프로그래밍까지 할 기운이 남지 않았습니다.

 

Free Willy는 연습 문제 중 가장 어려운 문제였던 것 같습니다.

전형적인 Branch and Bound로, 제한 횟수보다 1 낮을 때에만 연산이 줄어드는 경우라 생각합니다.

이대로 구현을 한다면 정답은 구하겠지만, 제한 시간 내에 풀지는 의문입니다.

 

다음주에는 DP를 문제를 2개 정도 풀어보려 합니다.

문제는 역시 backjoon 사이트에서 구해올 것 같습니다.

'개발일지 > Algorithm' 카테고리의 다른 글

20.06.14 Baekjoon - 피보나치 수 6  (0) 2020.06.14
20.06.10 개발일지  (0) 2020.06.10
20.06.02 2015 ACM-ICPC 연습  (0) 2020.06.02
20.05.26 - 2015 ACM-ICPC 연습  (0) 2020.05.26
20.05.19 - 2015 ACM-ICPC 연습  (0) 2020.05.19

http://prod.danawa.com/info/?pcode=4750551

 

[다나와] Cannice W3 (정품)

최저가 72,670원

prod.danawa.com

여기 노이즈 캔슬링이 되는 이어폰이 있다.

 

지인이 망가졌다는 것을 어떻게든 써보고 싶어서 받아 왔는데 선을 꼬아서 쓰면 좀 되는가 싶더니 결국 한쪽 소리가 아예 출력되지 않는다.

 

그렇게 몇 년을 방치 하다가 최근 눈에 다시 들어와버렸다.

 

이왕 버리는거 한번 고쳐서 써볼까 싶어 스스로 고쳐보기를 도전해보았다.

 

소리가 나오지 않는 쪽을 분리한 사진이다.

 

사실 아무데나 분리 했는데 마침 소리가 나지 않는 곳이었다.

 

저 중 하얀건 전지고 파란건 기판, 알록달록한건 전선이다.

 

카메라가 포커싱을 못잡아서 안타깝지만, 저 중 몇몇 납뗌을 눌러주면 소리가 잘 나온다.

 

다행히 전선 문제는 아닌 것 같고, 남뗌 부분에서 문제가 발생한 것 같다.

 

조만간 다이소에서 납뗌 용품을 사서 납뗌을 보강해보려 합니다.

 

만약 된다면 기존에 사용하던 LG 블루투스 이어폰과 음질을 비교하여 더 좋은 것을 일상 생활에서,
더 떨어지는 것을 운동 할 때 쓰면 좋겠습니다.

 

 

3주 연속으로 일주일 중 유일하게 쉬는 날인 주말 일요일에 입사지원을 하느라 많이 지쳤습니다.

 

또한 오랫동안 고민한 이슈를 해결하였기에 하루 정도 휴가를 주고자 합니다.

 

체력도 보충하고 집중력도 충전하는 시간을 갖도록 하겠습니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.15 개발일지  (0) 2020.06.15
20.06.11 개발일지  (0) 2020.06.11
20.06.06 개발일지  (0) 2020.06.06
20.06.04 개발일지  (0) 2020.06.04
20.06.03 개발일지  (0) 2020.06.03

이전 문제가 해결된 이후로 2주 가까이 지났습니다.

 

오늘에서야 문제를 해결할 수 있었습니다.

 

저번에 적었듯이, MovingDirection이 Climb 중 Moving Input이 들어오는 상태에서 해제 될 시 값이 고정되는 문제가 있었습니다.

 

처음에는 Climb 중 이동을 맡는 MoveForward 함수 내부를 수정할까 고민을 했는데,

내부에서 무언가를 추가/제거 하는 것으로 문제가 해결 될 것 같지가 않았습니다.

그 이후 생각이 나는 해결책은 Tick에서 상태를 조절해주는 것인데,

기껏 Tick에서 기능들을 빼고 다시 넣는 것도 웃기는 것 같았습니다.

 

그러다가 이전에 Tick에 있던 기능들을 제거 할 때 CharacterMovementComponent의 OnMovementModeChanged 등과 같은 Event를 이용했던 것을 떠올렸습니다.

이번에도 문제가 발생하기 직전에 OnClimbEndOverlap Event가 호출이 되기에, 그 안에서 MovingDirection을 초기화 했습니다.

그러자 아무 일도 없다는듯이 문제가 해결되었습니다.

 

처음에는 Climb 상태가 아닐 때에도 Move Input이 들어오면 MovingDirection 값이 변하는데 왜 고정이 되는지 야속했습니다.

하지만 조금 더 생각을 해보니, Animation에 대해 열 댓개의 트리거들을 사용하고 있는데 작은 예외라도 처리를 해주는게 옳지 않았나 싶은 생각이 들었습니다.

 

그렇게 저를 괴롭히던 Climb 기능은 기능적인 측면에서는 모두 완성되었습니다.

남은 것은 각 기능 별 적절한 Animation이 재생이 되는 것인데,

Animation Blueprint를 수정해본 결과 State Machine에 구조적 결함이 있는 것을 발견했습니다.

 

그래서 FullBodyMotion쪽 State Machine들을 전면 개선해야 Animation이 정상 재생 될 것 같습니다.

이 과정에서 Ledge, Slide 등의 Animation도 같이 수정되기에 이 두 기능들 적용이 병행되어야 할 것 같습니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.06.11 개발일지  (0) 2020.06.11
20.06.08 개발일지  (0) 2020.06.08
20.06.04 개발일지  (0) 2020.06.04
20.06.03 개발일지  (0) 2020.06.03
20.06.01 개발일지  (0) 2020.06.01

+ Recent posts