반사벡터

Reflection Vector

 

 

 

반사 벡터는 정반사이다.

정반사는 입사각과 반사각이 동일한 반사를 의미한다. 

 

◎ 투영 벡터

반사 벡터를 구하려면 투영 벡터를 먼저 구해야 한다.

투영이란 어떤 벡터 v를 단위 벡터 n에 내적하여 구할 수 있는 v의 n방향으로의 길이를 뜻한다. 

내적값이 스칼라이므로 투영된 방향으로의 벡터를 구하려면 이 내적값에 방향벡터 n을 곱해주면 된다. 

(v·n)n을 이용해 벡터를 구할 수 있게 된다. 

* 왜 이렇게 되는지 추가 설명!

더보기

v와 n을 내적하면 cosθ를 결과값으로 얻게 된다.

v·n = ||v||||n||cosθ

 

여기서 이 삼각형은 직각삼각형이므로 코사인값은 밑변/빗변 즉, ||n|| / ||v|| 이다.

||n|| = ||v||cosθ 이고 투영한 길이를 w라고 했을 때

w = ||v||cosθ가 된다. 

 

길이를 구했으니 방향도 알아야 하는데, 길이가 1인 단위벡터는 방향의 정보만을 갖고 있으므로 

단위벡터인 n의 방향으로의 길이를 구하려는 투영의 값에 n을 곱해주면 된다.

 

n의 방향 벡터 = n / ||n||

투영 벡터 = ( n / ||n|| ) * ||v||cosθ

 

하지만 두 벡터 사이각을 항상 알 수 없으므로

v·n = ||v||||n||cosθ 라는 사실을 응용해서 v·n/||n|| = ||v||cosθ 이런식을 만들어내면

두 벡터만 주어졌을 때, 한 벡터를 다른 벡터에 투영하는 공식을 구했을 때

((v·n) / ||n|| ) * ( n / ||n|| ) 이런 공식이 나오게 된다.

 

◎ 반사벡터 

투영 벡터를 이용해 구한 벡터로 반사 벡터를 계산한다.

다음과 같이 입사벡터(P)와 법선 벡터(n)이 있을 때 반사 벡터(R)은 입사벡터(P)와 크기가 같고 반사각과 입사각이 같다.

P와 n을 이용하면 반사벡터(R)을 구할 수 있다. 

 

우선 위의 투영 벡터를 구하는 방식을 이용해 입사 벡터 P의 역벡터 -P를 n의 연장선상에 투영시켜서 투영벡터 n(-P · n)을 구한다. 

 

어떻게 투영 벡터를 구하는건지? 

더보기

이렇게 돌려보면 쉽게 알 수 있다!

 

그 후 입사 벡터 P의 시작 위치를 원점에 위치 시키고 투영으로 구한 n(-P·n)를 더하면 입사면에 투영된 벡터의 위치를 구할 수 있다. 

입사 벡터 P에 n(-P·n)를 한 번 더하면 입사면에 투영된 위치를, 두번 더하면 반사벡터 R을 구할 수 있다.

 

따라서 반사벡터 R을 구하는 공식은 다음과 같다.

R = P + 2n(-P·n)

 

 

 

 

참고 자료;

https://toymaker.tistory.com/entry/%EB%B0%98%EC%82%AC-%EB%B2%A1%ED%84%B0-Reflection-Vector


https://ifyouwanna.tistory.com/entry/%EB%B0%98%EC%82%AC%EB%B2%A1%ED%84%B0


https://gyong0.tistory.com/22

 

 

erase와 remove의 차이

erase, remove

 

 

 

한줄로 간단하게 말하자면 erase는 멤버함수이고 remove는 알고리즘이다.

 

◎ erase

컨테이너의 erase는 실제 객체를 제거한다.

하나를 지울 수 있는데 STL의 데이터 공간까지 다 지우는 것이다.

즉, iterator에 해당하는 하나의 요소만을 삭제하며 capacity가 감소한다.

erase는 iterator를 넘겨준다.

 

	vector<int> v;
	v.resize(10, 0);

	for (int i = 0; i < v.size(); ++i)
	{
		v[i] = i + 1;
	}

다음과 같이 1부터 10까지의 벡터가 있다고 가정한다. 

 

	auto iter = v.begin();
	v.erase(iter + 1); // index 1번값 = 2

	printVector(v);

iterator가 begin값에서 +1, 즉 2를 가리키고 있는 상태에서 erase시키면 다음과 같은 결과가 나온다. 

 

◎ remove

Algorithm의 remove는 그 요소를 덮어씌움으로써 지워진 것처럼 보이게 된다.

정확하게 말하면 지워야 할 원소를 뒤의 원소들을 하나씩 앞으로 당겨서 덮어 씌우는 것이다

erase는 capacity까지 감소되었지만 remove는 조건을 함께 넘기면 조건과 일치하는 원소들은 다 지워지는데 공간은 그대로 남아있고 데이터만 삭제 된다.

즉, 해당 조건에서 일치하는 모든 요소는 삭제하지만 capacity는 그대로이다. 

 

 

 

◎ erase + remove?

특정 조건에 해당하는 원소를 아예 지우려면 erase와 remove를 함께 사용하면 좋다.

remove는 제거되지 않은 마지막 원소를 가리키는 itertor를 리턴하기 때문에 

erase( remove(시작, 끝, value), 컨테이너의 end 반복자); 

의 형태로 사용해준다. 

 

 

'Study > STL' 카테고리의 다른 글

[STL] next_permutation & prev_permutation (순열)  (0) 2020.09.11

니티 그래픽스 최적화 스타트업(;비엘북스)을 읽고 정리한 내용입니다.

유니티 그래픽스 최적화 스타트업

렌더링 파이프라인




렌더링 파이프라인은 간단히 말하면 3D 이미지를 2D 래스터 이미지로 표현하기 위한 단계적 방법을 말한다.

◎ 게임 루프

빠르게 이미지를 생성 해 이미지 하나하나가 화면에 보이는 것을 프레임이라고 하며, 1초에 몇 프레임이 렌더링 되는지를 FPS(Frames per second)라는 단위로 나타낸다.
화면 구성 요소들(배경, 애니메이션 포즈, 위치 등)은 각 프레임마다 조금씩 다르다.
이 화면 구성 요소들은 각 프레임마다 관련된 연산을 수행한 후 렌더링 되어야 할 요소들의 현재 모습이 결정된 후에 화면에 그려지는 것이다.
만약 60FPS라고 한다면 1초에 60 프레임, 1/60초에 한 번씩 화면에 새로 그려지게 된다.

매 프레임마다 연산이 이루어지는 요소들은 다양하다.
예를 들어 게임 내 오브젝트들의 상호 작용을 위한 물리 연산, 다양한 입출력 장치의 신호, 게임 로직 처리 연산, 캐릭터 애니메이션 처리, 네트워크 처리, 오디오 처리 등이 있다.

이런 과정을 묶어 보면 게임은 다음과 같은 과정으로 나뉘어 수행된다.


Update 단계에서는 Physics(물리), Input(입력), Logic(로직 계산), Animation(애니메이션 계산) 등이 이루어지며 Render과정에서는 씬(Scene), GUI 등을 그린다.
업데이트 과정이 처리된 후에 렌더링이 이루어지며 이러한 업데이트와 렌더링 과정이 매 프레임마다 반복된다.

더 자세한 순서는 유니티의 공식 메뉴얼에 나와있다.

◎ 렌더링 파이프라인

한 프레임의 렌더링은 프레임이 시작되면 화면에 그려야 할 오브젝트들을 하나씩 순차적으로 그리고 그려야 할 모든 오브젝트가 화면에 그려지고 나면 비로소 프레임이 끝나고 화면에 출력된다.
이때 화면에 오브젝트를 그리기 위해서는 많은 데이터가 필요하다.
이 데이터들은 (Mesh, Texture, Shader, Transform 등) 하나의 오브젝트가 렌더링 되는 과정, 그래픽스 파이프라인에서 사용한다.





참고 자료;
URL

 

Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption 

 

GameObject obj = Resources.Load<GameObject>("Prefabs/Item");
obj.transform.parent = content.transform;

 

코드에서 프리팹을 불러온 후 인스턴스화된 게임 오브젝트로 바꿔주지 않고 바로 parent를 변경하면 에러가 발생한다.

 

GameObject obj = Instantiate(Resources.Load<GameObject>("Prefabs/Item"));
obj.transform.parent = content.transform;

 

 

 

public enum poolType
{
     start,
     bullet,
     last
}
        
for(poolType p = poolType.start + 1; p < poolType.last; ++p)
{
     Debug.Log(p.ToString()); 
}

 

enum 열거형을 만들다가 string 값도 받아오고 싶을 때

자세한 코드는 지우고 Debug로 p의 값을 받아오게 출력해 보면 start의 다음부터 last 전값까지니까 bullet이 로그에 찍힌다. 

 

 

 

 

애니메이션 2

애니메이터 컨트롤러의 스테이트 머신

 

 

 

애니메이터 컨트롤러 = 스테이트 머신 + 애니메이션 클립

애니메이터는 컴포넌트가 아닌 '애셋'이다. 따라서 게임 오브젝트에 직접 적용할 수 없고 애니메이터의 프로퍼티에 있는 애니메이터 컨트롤러로 링크를 설정해 사용한다. 

애니메이터를 만들고 애니메이터 컴포넌트에 연결하는 방법

 

 

◎ 스테이트 머신

스테이트 머신은 동작 표현 방법의 하나이다. FSM(유한 상태 머신)이라 불리는 모델을 바탕으로 기호를 사용해 동작을 표현할 수 있는 것이 큰 특징이다. 유니티에선 애니메이션 동작의 표현을 위해 스테이트 머신을 사용한다.

 

Animator 창에서 오른쪽 클릭으로 생성한 empty state

 

Animator 창에서는 표현된 상태를 잇는 화살표 기호로 상태간의 트랜지션, 즉 전이를 표현한다.

컨트롤러를 만들면 처음 시작은 Entry이며 이 상태에서 빈 Empty State를 추가하면 Entry -> New State 사이의 화살표가 생긴다

 

 

Animator 창에서 state를 선택하면 보이는 해당 state의 inspector창

 

스테이트 인스펙터 창 기능

Motion : 애니메이션 클립

Speed : 재생 속도 (1.0이 기본 속도)

Multiplier : 재생 속도에 애니메이션 파라미터의 값을 곱한다.

Mirror : 애니메이션의 좌우 반전

Cycle Offset : 반복 재생 시키는 경우의 시작 위치 (재생 시간의 비율은 0과 1사이)

Foot IK : 스테이트 안에 IK 계산에서 발이 땅에 붙도록 자동 보정

Write Defaults : 스테이트를 시작할 때 키 없는 프로퍼티에 기본값을 설정

 

 

 

◎ 애니메이션 클립

애니메이션 클립은 컴포넌트가 아닌 애셋이다. 따라서 단독으로는 다룰 수 없다.

State의 인스펙터에 애니메이션 클립 애셋으로 링크를 연결해 그 스테이트의 상태일 때 애니메이션 클립이 재생되는 구조이다.

 

 

애니메이션 클립을 해당 State에 적용하는 방법은 간단하다. hierarchy 창에서 해당 animation 클립을 드래그앤 드랍으로 Motion에 넣어주면 된다.

 

아니면 아직 스테이트를 생성하지 않은 경우에는 Animator 창에서 오른쪽 버튼을 클릭해서 [From Selected Clip]을 선택하면 애니메이션 클립이 연결된 State를 생성할 수 있다. 

 

애니메이션 재생을 현재 Idle 상태에서 걷기로 바꾸고 싶다면 Idle 스테이트에서 Walk 스테이트로 화살표(트랜지션)를 이어준다. 

 

 

 

 

참고 자료;

유니티 게임 프로그래밍 바이블 (김은철, 유세라 옮김 ; 위키북스) 

 

 

상태

FSM(Finite State machine) ; 유한 상태 기계

 

 

FSM이란 여러 제한된 상태가 존재하며 그 존재들이 특정 조건에 따라 상태를 전이하는 형태의 개념적 모델이다.

간단하게 말하자면 보스의 패턴 구현 시 어느 특정 조건을 달성해 공격을 할 수 있게 되는 상황을 만들었다면 IDLE -> ATTACK 으로 상태가 바뀌는 것도 간단한 FSM 구현에 속한다. 

키 입력 등을 통해 '입력'이나 '이벤트가' 현재 움직여야 하는 머신에 전달이 되면 그에 해당하는 상태를 머신이 갖게 되는 것이다. 

 

 

◎ FSM의 장점?

1. 가질 수 있는 '상태'가 한정되며 한 번에 '한 가지' 상태만을 갖는다. 

상태란 행동이나 현재의 기능을 뜻한다. 예를 들어 플레이어의 움직임에서 생각해보면 걷기, 달리기, 점프 등은 각각 상태인 것이다. 

여기서 동시에 두 가지 상태가 일어나지 않게 하기 위해 사용하는 것이 FSM이다.

 

 

2. 내부 구조와 구현이 쉽다

머신의 행동을 직관적으로 간단하게 구현할 수 있다. 

 

3. 오류의 수정이 용이하며 유연성이 있다. 

 

4. 각 상태에는 입력에 따라 다음 상태로 바뀌는 '전이'가 있다.

입력이 들어왔을 때 현재 상태에 해당하는 전이가 있다면 전이가 가리키는 다음 상태로 변경한다.

예를 들어 기본 IDLE 상태에서 Down 키를 누르면 엎드리기 상태로 바뀌지만 점프 상태에서 Down키를 누르면 내려찍기로 전이한다.

 

 

 

 

◎ FSM의 단점

1. 규모가 커지면 설계가 복잡해 진다.

 

2. 제한된 범위의 문제에만 적용이 가능하다.

 

 

 

 

 

참고 자료;

더 빠르고 깔끔한 게임 코드를 구현하는 13가지 디자인 패턴 게임 프로그래밍 (저; 로버트 나이스트롬 , 역; 박일, 출판사; 한빛미디어)


https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=debuff9710&logNo=221333379009 

 

'Study > 디자인패턴' 카테고리의 다른 글

[디자인패턴] 어댑터 (Adapter)  (0) 2021.10.12
[디자인패턴] 싱글톤(Singletone)  (0) 2020.10.23

 

 

 

프로젝트를 git에 올리는데 ignore에 Library 폴더를 추가해줬음에도 metadata가 자꾸 포함이 됐다.

git ignore를 수정한 후 적용이 안됐던 문제가 전에 있어서 그거 때문인가? 싶었는데

 

결론적으로는 .gitignore 파일을 수정했다. 

 

# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Mm]emoryCaptures/

 

내 git ignore 중 Libary 관련 내용은 다음과 같았는데 이 내용에서 폴더 이름 앞의 '/'를 빼줬다.

 

# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
#
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
[Ll]ogs/
[Mm]emoryCaptures/

 

이런 문제일거라고는 처음에 생각도 못해서 고생하긴 했는데 어쨌든 해결했다. 

 

 

-------------

 

아.. 나중에 알고보니 gitignore를 유니티 프로젝트 바깥에 놔줬다. 

 

+ Recent posts