04_장면 관리 개요

19
1 게임에서의 장면 관리 프로그래밍 개요 발표자 : 김성익 ([email protected] 발표일 : 2004.10.10

Transcript of 04_장면 관리 개요

Page 1: 04_장면 관리 개요

1

게임에서의 장면 관리프로그래밍 개요

발표자 : 김성익 ([email protected])

발표일 : 2004.10.10

Page 2: 04_장면 관리 개요

2

+ 게임에서 처리하는 개체수가 많아지거나, 표현 영역이 넓어질 경우, 렌더링, 충돌 체크 등의 지역적인 처리에 좀 더효율적인 접근이 필요하다.

+ 개체 수 = 씬에 1000개의 오브젝트가있는데, 실제로 평균적으로 화면에 렌더링 되는 것이 50개 정도라고 하면 장면 관리가 필요하다고 할 수 있다.

+ 영역의 넓이 = 1Km 에 오브젝트들이분포되어 있을 때 시야 거리가 10M 라면 모든 오브젝트의 단순 뷰 컬링보다효율적인 방법이 필요하다.

+ 게임에서 개체를 검색할 필요가 있는많은 분야에서 장면 관리가 필요하다.

오브젝트 렌더링, 충돌처리영향주는 라이팅 검사근접한 오브젝트 리스트

I. INTRODUCTION장면 관리 (Scene Managing) 개요

GTA3 – Rockstar Studios

Page 3: 04_장면 관리 개요

3

렌더링 관점

+ 게임에서는 렌더링 속도가 큰 영향을줌 => "가장 빠른 렌더링은 그리지 않는 것 “

+ 장면 관리는 화면에 렌더링 된 가능성이 있는 것들만 최소의 탐색으로 빠르게 검색

충돌처리 관점

+ 한 프레임에 N개의 오브젝트에 물리를 적용할 경우 오브젝트간의 충돌 검사사 N x (N-1) 번 일어나게 됨 => “가장 좋은 것은 충돌 가능성이 없는 오브젝트들과는 충돌 검사를 하지 않는 것”

+ 장면관리 => 최소의 탐색으로 충돌가능성 있는 오브젝트만 검색

정리하면

+ 많은 오브젝트들 중에서 처리하고자하는 영역에 포함된, 결과에 영향을 줄가능성이 있는 개체만 빠르게 검색하는것이 장면 관리의 기본

게임에서 많이 사용 되는 기법

+ 쿼드트리+ 옥트리+ k-d 트리+ BSP

장면 관리 역할

Page 4: 04_장면 관리 개요

4

일반적인 장면 관리 기법들의 공통점

+ 계층적으로 공간을 분할 구성하여 개체 리스트를 관리한다.

+ 모두 트리 구조로 되어 있다.

+ 특정 노드(부모)의 하위 노드(자식)가Test에 통과하지 않는 다면 그 이하는검사할 필요가 없다.

+ 재귀적인 탐색에 적합한 형태다.

+ 알고리즘적인 접근이기 때문에 영역의 크기와 용량이 비례하지 않는다.

공통적인 수도코드 (Pseudo Code)

II. 일반적인 장면 관리 기법

탐색(노드, 검사영역) {

for(i=0; i<자식수; i++) {

if (포함(노드.자식[i].바운드, 검사영역)) {

if (노드.자식[i].속성 == 리프) {

for(j=0; j<노드.자식[i].아이템수; j++) {

if (포함(노드.자식[i].아이템[j], 검사영역))

처리(노드.자식[i].아이템[j])

}

} else

탐색(노드.자식[i], 검사영역)

}

}

}

Page 5: 04_장면 관리 개요

5

+ 두 가지 축(일반적으로 X, Y)로 각 노드를 계속해서 4분할 하는 방식

+ 게임에서 높이축의 영향을 적게 받는경우 많이 사용된다.

+ 타일 베이스와 비교하면 영역의 크기에 따라 검색 속도의 영향을 적게 받으며 (개체의 수가 같다면 단순히1km맵과 100km 맵은 큰 차이가 없다.), 용량역시 영향을 받지 않는다.

+ 이상적인 트리인 경우 깊이는 log4N으로 6만개의 개체일 경우에도 깊이가4 레벨 정도로 적다

+ 공간 기준으로 트리를 구성할 경우에는 효과적으로 복잡한 곳은 깊이, 아닌곳은 낮게 설정된다.

1. 쿼드트리(Quadtree)

Page 6: 04_장면 관리 개요

6

트리 만들기

+ 현재 노드에 포함된 모든 아이템들을중심점을 기분으로 각 영역에 포함된것들로 나눈다. (중심점의 결정에 따라트리의 모양이 달라진다.)

+ 각 영역에 포함된 것들로 트리를 만들어트리의 최상위 노드를 자식으로 붙인다.

+ 트리의 깊이가 너무 깊어지거나 오브젝트수가 적당한 수 이하인 경우 더 이상 나누지 않으며, 이 노드를 리프(Leaf)라고 부르며 아이템들 리스트를 가지고있다.

트리를 나누는 중심점

+ 트리를 구성할 때 가장 영향을 많이주는 부분으로 가장 균형 잡힌 트리를위해서는 포함된 아이템을 4등분할 수있는 지점이다.

트리 생성(1)

Page 7: 04_장면 관리 개요

7

+ 일반적으로는 공간을 균일하게 분할한다. => 비교적 공평한 결과가 나오며, 동적인 개체 위치 이동 등으로 트리의모양이 잘 깨지지 않는다.

나누는 영역에 아이템이 겹치는 경우

+ 겹치는 모든 노드에 포함시킨다.

트리의 노드 수가 약간 증가할 수 있으나, 검색에 큰 무리는 없다.

하나의 아이템(개체)의 여러 개의 리프에 포함되기 때문에 하나의 아이템이여러 개 검색 될 수 있으므로 중복 검색에 대한 처리가 필요하다.

+ 노드에 아이템을 포함시키고 하위 노드에 넣지 않는다.

리프에 중복되어 등록되지 않으나, 상위에 등록될 경우 실제 결과와 상관없이 검색되기 때문에 수가 많으면 효율이 떨어질 수 있다.

+ 느슨한 노드를 만든다.

겹치는 경우 4 영역 중 임의의 하나의영역에 포함시킨다.

리프에 중복 등록되지 않는다

하위 노드는 포함한 아이템들로 바운드 영역을 새로 구한 후 저장한다.

트리 생성(2)

Page 8: 04_장면 관리 개요

8

트리 생성(3)

CQuadTree::_NODE * CQuadTree :: BuildTree(RECT *rectlist, int * itemidx, intnum, const RECT &bound, int lv)

{

int * temp = new int [num];

int i, n, side;

_NODE * node;

node = new _NODE;

memset(node, 0, sizeof(_NODE));

node->pivot.x = (bound.left + bound.right) / 2;

node->pivot.y = (bound.top + bound.bottom) / 2;

for(side=0; side<4; side++)

{

RECT localbound = Divide(bound, node->pivot, side);

for(i=0, n=0; i<num; i++)

if (ContactTest(rectlist[itemidx[i]], localbound) == true)

temp[n++] = itemidx[i];

if (n == 0){ // null node

node->child[side] = NULL;

} else

if (lv+1 >= _MAX_DEPTH || n <= _MAX_ITEM)

{ // leaf

int * leaf = new int [n+1];

for(i=0; i<n; i++)

leaf[i] = temp[i];

leaf[i] = -1;

node->child[side] = leaf;

node->mask |= 1<<side;

} else

{ // node

node->child[side] = BuildTree(rectlist, temp, n, localbound, lv+1);

}

}

delete [] temp;

return node;

}

Page 9: 04_장면 관리 개요

9

탐색 알고리즘

+ 앞서 소개한 탐색 수도코드와 같다.

+ 하위 노드가 바운드에 속하는 지 검사하고, 속하는 경우 하위 노드가 리프인지 검사해서 리프인 경우 그리기, 아니면 다시 재귀적으로 검색한다.

쿼드트리 탐색 (1)

{

int * leaf = (int*) node->child[side], i;

for(i=0; leaf[i] >= 0; i++)

{

if (m_UpdateCntList[leaf[i]] != m_UpdateCnt)

{

if (ContactTest(m_RECT, g_TestList[leaf[i]]) == true)

{

FillRect(m_HDC, &g_TestList[leaf[i]], NULL);

m_UpdateCntList[leaf[i]] = m_UpdateCnt;

}

}

}

} else

Explorer(rect, (_NODE*) node->child[side]);

}

}

}

}

void Explorer(const RECT & rect, _NODE * node)

{

for(int side=0; side<4; side++)

{

if (node->child[side] != NULL)

{

if ((side==0&&rect.left<=node->pivot.x&&rect.top<=node->pivot.y) ||

(side==1&&rect.right>=node->pivot.x&&rect.top<=node->pivot.y) ||

(side==2&&rect.left<=node->pivot.x&&rect.bottom>=node->pivot.y) ||

(side==3&&rect.right>=node->pivot.x&&rect.bottom>=node->pivot.y)) {

if (node->mask&(1<<side))

Page 10: 04_장면 관리 개요

10

하위노드가 검색 영역과 겹치는 지 검사하는 방법

+ 서브 바운드를 구해서 영역과 검사검사 속도는 느리지만, 뷰 프러스텀

컬링시에는 이 방법만 유효한다

+ 중심점과 영역과 검사아래 0번 평면의 경우 중심점과 검색

영역의 left, top으로 판단 가능하다.

쿼드트리 탐색 (2)

+ 비트 마스트를 이용한 중심점과 영역검사

두 번째 연산 방식을 비트 세팅을 이용해서 방법으로 처리가 간단해진다. (셈플의 _OPTIMIZE 전처리기 이용한부분 참조)

이용 가능한 특성

+ 노드가 완전히 검사 영역안에 있다면하위 노드는 모두 영역안에 포함된다.

+ 리프가 검사 영역안에 있다면 상위모든 노드는 영역을 포함한다

+ 분할 지점이 영역 안에 있다면 모든자식은 영역을 포함한다.

Page 11: 04_장면 관리 개요

11

샘플 어플리케이션

+ 화면 상에 임의의 크기의 많은 수의개체들 분포되어 있을 때 임의의 영역의 개체를 선택할 경우 단 몇 번의 탐색으로 영역에 포함되는 개체를 얻을 수있다.

+ 선택 영역 : 보라색

+ 영역 안에 있는 리프에 있는 아이템 : 백색 개체, 백색 아웃라인 개체

+ 최종 선택 영역안에 있는 개체 : 백색

http://digibath.com/noerror/download/2dquadtree.zip

쿼드트리 샘플

Page 12: 04_장면 관리 개요

12

+ X, Y, Z축의 3가지 축 성분으로 공간을 분할한다.

+ 쿼드트리와 거의 대부분의 특성이 동일하다.

+ QuadTree 에 축이 하나 추가된 형태라고 볼 수 있다.

+ 공간적으로 골고루 분포된 형태의 씬에 적합하다.

+ 예를 들어 메시의 삼각형 단위의 충돌 디테일을 가진다면 내부적으로는 각트라이 앵들을 Octree 형태로 가지고있으면 효율적이다.

+ 공간을 8등분하기 때문에 탐색 복잡도는 훨씬 작아진다. 이상적인 경우O(log8N).

+ 쿼드트리와 마찬가지로 균일한 크기로 노드를 분할 할 경우 유연하게 동적인 개체 관리도 가능하다

2. 옥트리 (Octree)

Page 13: 04_장면 관리 개요

13

+ 옥트리나 쿼드 트리의 경우 아이템들이 한 라인을 이루거나 한 평면에 위치할 경우 비효율적으로 트리가 구성된다.

쿼드 트리의 가지가 2개인 채로 계속구성된다거나, 옥트리에서 아이템의 Y값이 모두 0이라거나 하는 식으로.

+ k-d 트리는 두개의 가지를 이진 트리의 일종으로 노드의 아이템을 이분할하기 좋은 축을 선택해서 트리를 생성한다.

+ 나누는 축은 한가지 요소 (x, y, z중의하나) 만으로 분할 되기 때문에 탐색 연산이 적고, 간단하다.

+ 옥트리나 쿼드 트리에 비해 아이템의분포에 큰 영향 없이 균형 있는 트리가구성된다.

+ 아이템이 자주 옮겨 다닐 경우 트리균형을 깰 수 있기 때문에, 동적인 개체보다는 정적인 개체에 적합하다.

3. k-d Tree

Page 14: 04_장면 관리 개요

14

+ 기본적인 트리의 속성은 이전의 트리들과 동일하다.

+ k-d 트리와 마찬가지로 두개의 가지를 가지는 이진 트리의 형태를 가진다.

+ 분할하는 평면은 축에 고정되어 있는것이 아니라 임의의 평면이 된다. (즉, 아이템을 나눌 때 형태의 영향을 덜 받게 되며, 나누는 평면에 겹치는 경우를줄일 수도 있다.)

+ 정적인 개체들에 대해서 균형 잡힌트리를 구성하는 것이 일반적이며 동적인 개체 관리에는 적합하지 않다.

+ 트리를 생성하는 시간이 많이 걸린다. (각 노드를 균형 있게 이분하는 평면을구하기가 쉽지 않다.)

퀘이크의 사례

+ 폴리곤으로 트리를 구성했으며, 노드에 페이스 리스트가 있고, 리프는 공간을 나타낸다.

+ 겹치는 폴리곤이 생길 경우 실제로폴리곤을 분할해서 정확하게 노드에 속하도록 되어있다.

+ 뷰 컬링의 경우 카메라의 위치와 노드의 분할 평면과의 위치로 탐색한다.

+ 충돌도 bsp특징을 이용해서 최적의탐색이 가능하다

4. BSP

Page 15: 04_장면 관리 개요

15

+ 단순히 영역 검사나 뷰 컬링을 이용한 장면 관리 기법이 아니라 기하적인특성을 이용하는 장면 관리 기법.

+ 기하적인 연산이 들어가기 때문에 탐색이 일반적인 탐색보다는 부담스러울수 있기 때문에 렌더링 할 때 주로 사용된다.

+ 포탈은 특별한 형태의 장면 관리 기법이다.

+ 오컬루젼 컬링, PVS는 독립된 장면관리 기법은 아니지만 장면 관리 기법에 붙어서 같이 사용되는 기술이다.

+ 실내 지형에는 포탈이 적합하다.

+ 거대한 개체가 필드상에 존재하는 ㄱ여우에는 오컬루젼 컬링이 도움이 된다.

+ 닫힌 지형이거나, 언덕, 성벽등의 특징 있는 지형에서는 PVS가 도움이 된다.

III. 렌더링 컬링을 위한장면 관리 기법

Page 16: 04_장면 관리 개요

16

특징

+ 노드는 트리 구성이 아닌 연결이 자유로운 그래프로 구성된다.

+ 기본적으로 노드는 기하적으로 구성되어 있기 때문에 개체 수의 영향을 받지 않으며, 개체의 이동에 따라 노드가바뀌지 않으므로 동적으로 처리 가능하다.

기본 원칙

+ 각 노드는 특정 영역으로 구성되며노드의 연결부는 포탈이 존재한다.

+ 임의의 노드에서 포탈이 보이지 않을경우 연결된 노드는 안 보인다.

+ 포탈을 통해서 보인 노드에서 다음노드로 연결 검사할 때는 상위 포탈을통해서 보이는 지 검사한다.

렌더링 수도 코드

1. 포탈(portal)

탐색(노드) {

그린다(노드)

for(i=0; i<자식수; i++) {

if (노드.자식[i].닫혔나 == false) {

if (화면에보이나(노드.자식[i].포탈)) {

탐색(노드.자식[i])

}

}

}

}

Page 17: 04_장면 관리 개요

17

기타

+ 연결된 노드가 작은 포탈을 통해 보일 경우 미리 렌더링된 이미지로 처리로 처리 가능하다.

+ 게임 내에서 문이나 도구로 포탈을가릴 경우 포탈 구조와 연동해서 연결된 노드를 렌더링하지 않을 수 있다

+ 특별한 형태로 지형이 구성되어야 하며, 포탈의 설정, 노드 결정 등의 데이터 수집 어려움으로 쉽게 적용하기 힘들다.

+ 실내 지형에 적합하다.

포탈(2)

http://www.cs.virginia.edu/~luebke/publications/portals.html

Page 18: 04_장면 관리 개요

18

+ 앞의 개체에 의해 뒤의 오브젝트가완전히 가려지는 지 검사하는 방식 => “가장 빠른 것은 그리지 않는 것”

구현방법

+ 기하적인 방법 : 기하적인 연산으로가리는 오브젝트에 의해 렌더링할 개체의 바운드가 완전히 가려지는 지 검사한다.

+ 하드웨어적인 방법 : 실제로 작은(!) 뷰에 가리는 오브젝트를 렌더링한 후렌더링할 계체를 그 뷰에 실제로 랜더링해서 화면에 찍힌 픽셀 수를 세어서0인 경우 완전히 가렸다고 판단한다.

기타

+ 연산량이 적은 편은 아니므로, 적절한 설정이 필요하며, 실제로 지형상 많은 걸 가려주는 거대한 개체가 존재해야 효과가 있다.

2. 오컬루젼컬링(occlusion culling)

Page 19: 04_장면 관리 개요

19

PVS(Potentially Visible Set)

+ 보일 가능성이 있는 집합이란 의미.

+ 쿼드트리, 옥트리, BSP에 상관없이임의의 리프에서 보일 가능성이 있는리프의 리스트를 알 수 있다.

+ 보일 가능성이 있는 리프의 리스트는실시간으로 계산한 데이터가 아닌 미리계산된 값을 사용한다.

+ 구성상 일괄적인 기하적 특성이 없지만, 탑, 산등의 시야를 가지를 것들이있을 때 그런 것들에 의해 절대로 볼 수없는 리프를 찾는 것

+ 미리 계산하는 값이기 때문에 빌드타임의 영향을 거의 안 받으므로 부르탈 포스 알고리즘(Brutal Force Algorithm – 가능한 많은 경우를 직접

대입하여 확률적으로 해결)을 활용할수 있다.

+ 정적인 데이터다.

퀘이크 사례

+ 임의의 리프에 있을 때 보일 가능성있는 모든 리프의 정보를 RLE + 비트데이타로 가지고 있다.

3. PVS