알고리즘 트레이닝 – 재귀(Recursion)적 알고리즘

원소가 n 개인 집합의 모든 부분집합을 생성하는 재귀적 알고리즘

#include <vector>

using namespace std;

class Subset
{
public:
    Subset();
    vector<int> subset;
    void search(int k);
}

Subset::Subset()
{
    search(1);
}

Subset::search(int k)
{
    int n = 3;
    if (k == n+1)
    {
        // 부분집합을 처리한다.
    }
    else
    {
        // k를 부분집합에 포함시킨다.
        subset.push_back(k);
        search(k+1);

        // k를 부분집합에 포함시키지 않는다.
        subset.pop_back();
        search(k+1);
    }
}

int main()
{
    Subset subset = Subset();
}

알고리즘 트레이닝 – 콜라스 추측(Collartz conjecture)

콜라스 추측법은 값이 짝수라면 이를 반으로 나누고, n이 홀수라면 3을 곱한후 1을 더하는 과정을 값이 1이 될때까지 수행하는 과정을 반복한다.

입력 : 3

출력 : 3 10 5 16 8 4 2 1

#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;
    while (true)
    {
        cout << n << " ";
        if (n == 1) break;
        if (n%2 == 0) n /= 2;
        else n = n*3+1;
    }
    cout << "\n";
}

입력값을 138367을 넣고 테스트를 해보면, int 값의 범위 초과로 오류가 발생한다. 단순히 값의 자료형을 long long 형으로 바꿔주면 해결된다.

테스트 HLOD 세팅 값.

  • HLOD Level 0
    • Cluster generation settings
      • Desired Bound Radius : 10000.0
      • Desired Filling Percentage : 50.0
      • Min Number Of Actors to Build : 2
    • Mesh generation settings
      • Transition Screen Size : 0.5
  • HLOD Level 1
    • Cluster generation settings
      • Desired Bound Radius : 25000.0
      • Desired Filling Percentage : 37.5
      • Min Number Of Actors to Build : 2
    • Mesh generation settings
      • Transition Screen Size : 0.3
  • HLOD Level 2
    • Cluster generation settings
      • Desired Bound Radius : 52500.0
      • Desired Filling Percentage : 28.125
      • Min Number Of Actors to Build : 2
    • Mesh generation settings
      • Transition Screen Size : 0.225
  • HLOD Level 3
    • Cluster generation settings
      • Desired Bound Radius : 131250.0
      • Desired Filling Percentage : 21.09375
      • Min Number Of Actors to Build : 2
    • Mesh generation settings
      • Transition Screen Size : 0.16875

Python 나무위키.

https://namu.wiki/w/Python

디자인 철학

Python 에서의 들여쓰기는 의무. 들여쓰기 자체로 코드 블럭이 된다.

def factorial(x):
    if x == 0:
        return 1
    else:
        return x * factorial(x - 1)

순수 객체지향

Python에는 원시 타입(Primitive Type) 이 없다. 모든 것이 객체로 취급된다. 상수 역시 상수가 저장된 객체라고 본다. 다음과 같은 상수 할당이 있을때,

x = 10

변수 x 에 10이 할당된 것이 아니라, 10이 저장된 상수 객체를 가리키는 것을 의미. 즉, 내부적으로는 C의 포인터 연산과 같은 동작이 행해지는 것이다.

x = 10
x = 20

이렇게 x에 대입되는 값을 변경할 경우, x가 가리키는 대상이 10이 저장된 상수 객체에서 20이 저장된 상수 객체로 바뀐 것이다.

파이썬의 객체는 변경 불가능한 객체 (Immutable Object)와 변경 가능한 객체(Mutable Object)로 나뉘며, 변경 불가능한 객체에는 상수, 문자열, 그리고 튜플이 있다. 이 세가지를 제외한 나머지 객체는 모두 변경 가능한 객체이며, 값을 수정 할 수 있다. 변경 불가능한 객체의 값을 수정할 때는 바뀐 값이 저장된 새로운 객체를 생성하고 해당 객체를 참조한다. 이와 같은 특징 때문에 파이썬은 순수 객체지향 언어라고 할 수 있고, 이와 같은 순수 객체지향 언어의 또다른 예로는 Ruby 가 있다.

함수의 매개변수로 Immutable 객체를 넘겼냐 Mutable 객체를 넘겼냐에 따라서 함수 바까에 있는 인자의 값도 수정할 수 있는지 없는지가 달라진다. Immutable 객체를 넘겼으면, 값의 복사만 일어나고 함수 바깥에는 영향을 주지 못하므로 ‘Call by Va;lue’ 가 될 것이며, Mutable 객체를 넘겼으면, 함수 바깥에 까지 영향을 줄 수 있으므로, ‘Call by Reference’ 가 될 것이다. 파이썬 공식 문서에서는 파이썬의 인자 전달 방식을 ‘Call byAssignment’ 또는 ‘Call by Object Reference’ 라고 명시 하고 있다.

반복 가능한 객체

파이썬의 가장 큰 특징 중 하나. 파이썬은 반복 가능한 객체(iterable)라는 강력한 기능을 제공한다. 이 객체는 집합, 문자열, 리스트, 튜플, 딕셔너리, 그리고 함수 까지도 반복이 가능하며, 이것을 for 구문에서 사용할 수 있게 해준다. 리스트와 튜플 등은 좀 편해지는 정도라 할 수있지만, 함수의 값을 반복할 수 있다는 것은 큰 장점이다. 그 예로, n의 배수를 구하는 f(n) 함수가 있을 때,

def f(n):
    x = 1
    while 1:
        yield n*x
        x += 1

와 같은 함수를 만드는 것도 가능하다. 함수를 호출하고 나서도 함수가 완전히 끝나기 전까지는 지역 변수가 남아있으며, 함수가 끝나야 지역변수가 삭제된다.

Google Cloud Platform

SnackLabChat 프로젝트 생성

DedicatedServer용 VM 인스턴스(가상서버) 생성

ssh key 생성 PuttyGen 을 사용.

메타데이터 > SSH 키 > “수정” 버튼 클릭 후 PuttyGen 에서 생성한 PublicKey 를 등록.

WinSCP 를 이용. 서버접속 완료.

4.20.3 소스 버전으로 fps example 데디케이티드 서버 테스트 빌드

WinSCP 로 구글 클라우드 의 VM에 접속된 상태.

ThirdPerson sample 프로젝트 리눅스 서버 빌드 및 서버에 실행

언리얼 엔진 사용시 include Windows.h 선언시 TEXT 매크로 충돌.

 

Waring 메세지

1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winnt.h(536): warning C4005: 'TEXT': macro redefinition
1>  c:\program files\epic games\ue_4.19\engine\source\runtime\core\public\HAL/Platform.h(854): note: see previous definition of 'TEXT'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winnt.h(17005): warning C4668: '_APISET_RTLSUPPORT_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winnt.h(536): warning C4005: 'TEXT': macro redefinition
1>  c:\program files\epic games\ue_4.19\engine\source\runtime\core\public\HAL/Platform.h(854): note: see previous definition of 'TEXT'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\interlockedapi.h(73): warning C4668: '_APISET_INTERLOCKED_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winnt.h(17005): warning C4668: '_APISET_RTLSUPPORT_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\processthreadsapi.h(1170): warning C4668: '_WIN32_WINNT_WINTHRESHOLD' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(357): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(472): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(1302): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\interlockedapi.h(73): warning C4668: '_APISET_INTERLOCKED_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\processthreadsapi.h(1170): warning C4668: '_WIN32_WINNT_WINTHRESHOLD' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winbase.h(8618): warning C4668: 'NTDDI_WIN7SP1' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(357): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(472): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\securitybaseapi.h(1302): warning C4668: '_APISET_SECURITYBASE_VER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
1>C:\Program Files (x86)\Windows Kits\8.1\include\um\winbase.h(8618): warning C4668: 'NTDDI_WIN7SP1' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'

Warning 안뜨게 하기.

// 언리얼 엔진에서도 Windows.h를 사용 하기때문에 TEXT 메크로 및 관련 부분의 처리를 PreWindowsApi.h 를 통해서 처리 하고 있었음.
// 그러므로 Windows.h 를 include 하는 부분의 상단에 PreWindowsApi.h 를 include 선언 해서 사용 하면 Waring을 안 볼 수 있다.
#include "PreWindowsApi.h" // winnt.h(536): warning C4005: 'TEXT': macro redefinition
#include 

[UE4] ImposterBaker + HLOD 적용

Imposter Baker

3D오브젝트를 평면, 반원, 구의 형태로 캡쳐 하여 스프라이트 형식의 텍스쳐를 생성 하여 기존의 단순한 2D 기반의 빌보드의 형태 ( 트레디셔널 방식 ) 에서 부터 3D 처럼 생긴 빌보드 ( 옥타헤드럴 방식 ) 의 기능을 제공.

기존의 빌보드는 단순히 랜더링하는 오브젝트를 바라보는 수준이었지만, 임포스터베이커는 진화한 형태의 빌보드라 할 수 있다.

HLOD  – Hierarchical Level of Detail

HLOD는 월드에 배치 되어있는 오브젝트를 (보통은 카메라의) 거리에 따라 디테일을 틀리게 설정해주는 기법. 멀리있을때는 낮은 디테일의 리소스로 가까이 있어서 자세히 봐야 할때는 높은 디테일의 리소스 ( 메시, 텍스쳐, 그림자, 라이트 등) 로 변경.

거리별 mesh actor 들을 하나로 묶어서 드로우 콜을 줄여주는 등의 기능을 간단한 설정으로 최적화를 할수 있도록 도와주는 기능이다.

장점

이 두가지를 섞어서 사용하면 매우 많은 드로우콜과 메시들의 트라이앵글수를 감소 시킬 수 있으며, 더불어 메시 액터들의 LOD 로우폴리로 설정한 메시들 보다 (훨씬) 더 나은 디테일을 가져 갈 수도 있다.

자세한 내용은 아래의 유튜브 링크를 통해 확인.

프로젝트 테스트하면서 확인 된 이슈들

언리얼엔진 4.19 에서는 임포스터 베이커는 적용이 되지만, 임포스터 베이커를 적용시킨 액터를 HLOD 와 같이 사용 하는것은 안된다.

  • Actor 의 HLOD 항목중에 “Use MaxLOD as Imposter” 항목이 엔진에 적용이 되어 있지 않기 때문에, 임포스터가 적용된 액터들을 HLOD 의 프록시 메시로 생성 시, 임포스터가 적용된 오브젝트가 보이는것이 아니고 떨렁 매시 한조각만 보이게 되는것을 확인 할 수 있다.

언리얼엔진 4.20  사용시 임포스터베이커를 사용시 블루프린트의 노드를 수정해야한다.

  • “BP_Generate_ImposterSprites” 블루프린트를 열어보면, Construction Script 안의 Scene Capture Setup 항목 에서SceneCaptureComponent2D 의 StaticMeshActor 변수를 초기화 부분을 보면, 기전에는 그냥 변수를 끌어와서 거기다가 배열을 생성해서 넣게 되어 있는데, 이 부분이 엔진 버전업이 되면서, Array에서 제공하는 SetElem 함수로 액터를 넣게 변경이 되었다.
  • 특정 조건에서 “Use MaxLOD as Imposter” 항목이 체크 되었을때 0을 나누기 했다는 에러 메세지와 함께 에디터가 종료되는 증상이 있어서 확인 중.

테스트 중인 영상과 사용방법에 대한 이슈

배경 어셋들을 임포스터화 시킨다음에 HLOD 로 묶어서 사용 하는 것으로 생각 하고 있었지만, 그게 아니고 HLOD로 만들어진 클러스터의 오브젝트 들에 대한 것들을 임포스터 화 해서 사용하는 것 같다. 현재 아래의 영상은 HLOD로 클러스터로 묶어서 나온 액터들을 임포스터 화 해서 빌드 한후 드로우 콜과 트라이앵글 수를 체크해 보았다. 만약 이런 방식이라면 관리 와 수정등등이 매우 복잡해서 쓰기가 꺼려질것 같은데, 좀더 체크 해 보아야 할 듯 하다.

  • 드로우콜 수
  • 트라이앵글 수

다음목표

    1. 캐릭터와 에니메이션에 관련된 최적화에 대한 고민
    2. 그외의 최적화에 관련된 고민

유튜브링크 : 옥타헤드럴 임포스터 & HLOD 섹션 부터 시작 – 포트나이트 모바일 아트 최적화

임포스터 및 HLOD 설정 가이드

  • 사용엔진버전 : 언리얼 4.20.2 버전
  • 사용플러그인 : 임포스터 베이커

[C#] IEnumerable, Linq 사용 예제

유니티에서 Foreach 를 실행시 Garbage를 생성시키는것을 피하기위해서 주로 사용 했었는데, 근래에는 Foreach를 사용해도 Garbage를 생성 하지 않는다 한다.

다음목표

  1. IEnumerable 를 어떤 케이스에서 쓰는게 효율적일지 생각해보자.
  2. Linq 는 어떤 상황일때 쓰는게 좋을지 생각해보자.
using UnityEngine;
using System.Collections;
using System.Collections.Generic; // IEnumerable 쓰려고.
using System.Linq;

public class Bong9_Enumerable : MonoBehaviour {

	// Use this for initialization
	void Start () {

        ///
        /// string 객체에는 IEnumerable 인터페이스가 구현 되어있다.
        /// 

        string[] strList = { "bong9", "bong8", "bong7", "b09", "b08", "b07" };

        // 구현.
        Debug.Log("------IEnumerable() Start ------");
        IEnumerable(strList);
        Debug.Log("------IEnumerable() End ------");

        // Linq 사용.
        Debug.Log("------IEnumerable_Linq() Start ------");
        IEnumerable_Linq(strList);
        Debug.Log("------IEnumerable_Linq() End ------");
	}

    void IEnumerable_Linq(string[] strList)
    {
        // 조건 : 글자수가 3개 이하.
        IEnumerable enumerable = from str in strList where str.Length <= 3 select str;

        IEnumerator e = enumerable.GetEnumerator();

        while (e.MoveNext())
        {
            Debug.Log(e.Current);
        }
    }

    void IEnumerable(string[] strList)
    {
        IEnumerator e = strList.GetEnumerator();

        while (e.MoveNext())
        {
            Debug.Log(e.Current);
        }
        // Debug.Log(e.Current); // 이미 열거가 완료되어 에러.

        e.Reset(); // 열거 초기화.
        e.MoveNext();
        Debug.Log(e.Current + "열거 초기화 후 다시 출력.");
    }

	// Update is called once per frame
	void Update () {

	}
}