Vincent1@chollian.net 문 성 원 3D Game Programming QuadTree Culling vincent1@chollian.net 문 성 원 KoreaIT 전문학교 게임학과.

Slides:



Advertisements
Similar presentations
멘토링 2 주차 장 프로그래밍을 위한 자바의 자료형  값이 변하지 않는 상수  메모리 기억공간인 변수.
Advertisements

YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
어서와 Java는 처음이지! 제3장선택과 반복.
Vision System Lab, Sang-Hun Han
03장 영상처리를 위한 Visual C++ 디지털 영상 파일 포맷 MFC 응용 프로그램 마법사를 이용한 MFC 프로젝트 작성
어서와 Java는 처음이지! 제2장 자바 프로그래밍 기초.
컴퓨터 응용 및 실습 Part1. OOP&Java Programming data type Review
2장 닷넷 프레임워크.
C++ Espresso 제1장 기초 사항.
6장. 멀티스레드 멀티스레드 프로그래밍의 필요성을 이해하고 기본 개념을 익힌다.
D. 지뢰찾기 분석 설계 예제.
제12장 유연한 카메라 클래스 만들기 학기 컴퓨터게임(DirectX).
제13장 기본적인 지형 렌더링 학기 컴퓨터게임(DirectX).
실전 프로젝트 2 : 숫자야구 숫자 야구를 구현해보자.
제6장 객체배열과 벡터 객체 배열을 이해한다. 벡터(vector) 클래스를 사용할 수 있다.
명품 C++ 13장 예외 처리와 C 언어와의 링크 지정.
5장. 리스트 리스트 학습목표 목록이나 도표처럼 여러 데이터를 관리할 수 있는 자료형을 추상화
2주 실습강의 Java의 기본문법(1) 인공지능연구실.
8. 객체와 클래스 (기본).
제7장 제어구조 I – 식과 문장.
명품 JAVA Essential.
Internet Computing KUT Youn-Hee Han
태양계 시뮬레이션 팀 명: 복학생 강유진 박지혜.
스레드의 개념과 동작 원리를 이해한다. MFC 스레드의 두 종류인 작업자 스레드와 UI 스레드 사용법을 익힌다.
명품 C++ 8장 상속.
제2절 법인세의 계산구조와 세무조정 1. 각 사업연도소득에 대한 법인세 계산구조 회계와 사회 결산서상 당기순이익
Choi, Namseok Java 기초 (Java의 제어문과 배열) Choi, Namseok
명품 Java Programming.
MFC Application Frameworks (AFX)
제8장 스텐실.
제 14 장 파티클 시스템.
12장 유연한 카메라 클래스 만들기 한성대학교 멀티미디어공학과 게임 프로그래밍-I 강의노트
Visual C++ Programming Common Controls
Chapter 05. 클래스 완성. chapter 05. 클래스 완성 01. 복사 생성자 복사 생성(Copy Construction) 생성될 때 자신과 같은 타입의 객체를 변수로 받아, 이 객체와 같은 값을 갖는 새로운 객체를 생성하는 것 명시적인 생성 과정뿐만.
아두이노 프로그래밍 2일차 – Part4 아날로그 키패드 활용하기 강사: 김영준 목원대학교 겸임교수.
주소록 프로그램.
프로그래밍2 및 실습 C언어 기반의 C++ 2.
스택(Stack) 김진수
픽킹 문시몬.
C언어 프로그래밍의 이해 Ch13. 선행처리기와 주석문.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
Ch.1 Iterator Pattern <<interface>> Aggregate +iterator
Direct X Demo 따라하기 Direct X Wizard를 이용하여 프로젝트를 생성한다
' Strategic Alliance Partner with '
Terrain.
제 2장 어휘구조와 자료형 토 큰 리 터 럴 주 석 자 료 형 배 열 형.
제 12장. 사용자 정의형으로서의 클래스 학기 프로그래밍언어및실습 (C++).
윈도우 계산기 윈도우 보조프로그램 4칙연산 외 10여가지 기능 구현 ⑥ 메뉴 ⑤ 메모리 ③ 단항연산 ④ 지우기
[CPA340] Algorithms and Practice Youn-Hee Han
DirectX 9을 이용한 게임 개발 기본 코스 강의 내용 : blending.
제어문 & 반복문 C스터디 2주차.
4장 - PHP의 표현식과 흐름 제어-.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
2d game pRogramming 1차 발표 이재남.
[INA470] Java Programming Youn-Hee Han
자바 5.0 프로그래밍.
작성일 참고서적 – Programing Game AI by Example
Java 3장. 자바의 기본 구조 I : 변수, 자료형, 연산자 public class SumTest {
3D Shapes 3개 핵심 Properties가 존재 1.Material 표면의 재질을 설정합니다.
C 코드최적화 세명대학교 AI연구실 양승조.
제 11장. 템플릿과 STL 학기 프로그래밍언어및실습 (C++).
C# 10장. 참조형.
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
2015년 2학년 1반.
8단계 3층을 완성한다 Case 1 Case 2 Case 3 Case 4
어서와 C언어는 처음이지 제22장.
윤성우의 열혈 C++ 프로그래밍 윤성우 저 열혈강의 C++ 프로그래밍 개정판 Chapter 02. C언어 기반의 C++ 2.
Choi Younghwan CSE HUFS
PHP 기초문법 PHP를 공부하는데 있어 가장 기초가 되는 PHP기초문법에 대해서 배워 봅니다.
Report #3- 문제 1 Set(집합) 추상 데이터 타입을 정의하고, 다음과 같은 연산자들을 포함시켜라. 여기서 S, S1, S2는 집합을 나타내고, i는 집합 원소를 나타낸다. 연산 의미 create() Return {} insert(S, i) If i є S then.
Presentation transcript:

vincent1@chollian.net 문 성 원 3D Game Programming QuadTree Culling vincent1@chollian.net 문 성 원 KoreaIT 전문학교 게임학과

Division of Game Development QuadTree 거대한 지형을 빠르게 검색할 수 있다. 1단계 트리 구성 Point 프러스텀 컬링시 전체 데이터 검색이 아니라 큰 덩어리 단위로 필요 없는 데이터를 제거 하여 데이터 량을 줄인다. 2단계 트리 구성 Korea IT Division of Game Development

Division of Game Development QuadTree 생성 n 생성할 지형의 크기는 2 + 1 ( 예 129 x 129 높이 맵을 생성해야 한다) 정사각형의 지형을 단계적으로 트리 형태로 구성한다. 128 Point 정점의 인덱스를 쿼드 트리로만든다. 128 16512 16640 0 64 8250 8320 64 128 8320 8384 8256 8320 16512 16576 8320 8384 16576 16640 8256 8384 8320 129*(128-1) = 16512 129*129 = 16640 Korea IT Division of Game Development

Division of Game Development QuadTree 컬링 n 곙계구를 이용하여 절두체 컬링을 수행하고 절두체에 포함되지 않은 부모 노드를 제거하면 자동으로 자식 노드도 제거된다. 128 Point 쿼드 트리의 특성을 이용하여 상당히 큰 영역을 한꺼번에 그릴때 제외 시킬수 있다. 제거 제거 8256 제거 8384 8320 화면의 프러스템 129*(128-1) = 16512 129*129 = 16640 Korea IT Division of Game Development

Division of Game Development 구현 1) 지형생성을 위한 객체 생성 HRESULT InitObjects() { LPSTR tex[4] = { "tile2.tga", "", "", "" }; D3DXVECTOR3 vScale; vScale.x = vScale.z = 1.0f; vScale.y = 0.1f; g_pLog = new ZFLog( ZF_LOG_TARGET_WINDOW ); g_pCamera = new ZCamera; g_pFrustum = new ZFrustum; g_pTerrain = new ZTerrain; g_pTerrain->Create( g_pd3dDevice, &vScale, BMP_HEIGHTMAP, tex ); return S_OK; } 지형의 격자간 크기, 높이맵 용 이미지, 텍스쳐를 넘긴다. Korea IT Division of Game Development

Division of Game Development 구현 2) 정점을 셋팅하고 쿼드 트리를 생성 HRESULT ZTerrain::Create( LPDIRECT3DDEVICE9 pDev, D3DXVECTOR3* pvfScale, LPSTR lpBMPFilename, LPSTR lpTEXFilename[4] ) { m_pd3dDevice = pDev; m_vfScale = *pvfScale; if( FAILED( _BuildHeightMap( lpBMPFilename ) ) ) { _Destroy(); return E_FAIL; } // 정점 생성 if( FAILED( _LoadTextures( lpTEXFilename ) ) ) { _Destroy(); return E_FAIL; } // 텍스쳐 로드 if( FAILED( _CreateVIB() ) ) { _Destroy(); return E_FAIL; } // 버텍스,인덱스버퍼 m_pQuadTree = new ZQuadTree( m_cxDIB, m_czDIB ); // 정점의 인덱스를 트리로 구성 if( FAILED( _BuildQuadTree() ) ) { _Destroy(); return E_FAIL; } return S_OK; } 하이트 맵용 점점과 인덱스를 구성 인덱스의 경우 버퍼만 생성 쿼드 트리 생성 및 트리 구성 Korea IT Division of Game Development

Division of Game Development QuadTree Class class ZQuadTree { /// 쿼드트리에 보관되는 4개의 코너값에 대한 상수값 enum CornerType { CORNER_TL, CORNER_TR, CORNER_BL, CORNER_BR }; /// 쿼드트리와 프러스텀간의 관계 enum QuadLocation { FRUSTUM_OUT = 0, /// 프러스텀에서 완전벗어남 FRUSTUM_PARTIALLY_IN = 1, /// 프러스텀에 부분포함 FRUSTUM_COMPLETELY_IN = 2, /// 프러스텀에 완전포함 FRUSTUM_UNKNOWN = -1 }; /// 예외 private: ZQuadTree* m_pChild[4]; ///4개의 자식 노드 int m_nCenter; /// 중심값 int m_nCorner[4]; /// 네 귀퉁이 값 BOOL m_bCulled; /// 프러스텀에서 컬링된 노드인가? float m_fRadius; // 노드를 감싸는 경계구(bounding sphere)의 반지름 /// 자식 노드를 추가한다. ZQuadTree* _AddChild( int nCornerTL, int nCornerTR, int nCornerBL, int nCornerBR ); /// 4개의 코너값을 셋팅한다. BOOL _SetCorners( int nCornerTL, int nCornerTR, int nCornerBL, int nCornerBR ); Korea IT Division of Game Development

Division of Game Development QuadTree Class /// Quadtree를 4개의 하위 트리로 부분분할(subdivide)한다. BOOL _SubDivide(); // Quadtree를 subdivide한다. /// 현재 노드가 출력이 가능한 노드인가? BOOL _IsVisible() { return ( m_nCorner[CORNER_TR] - m_nCorner[CORNER_TL] <= 1 ); } /// 출력할 폴리곤의 인덱스를 생성한다. int _GenTriIndex( int nTris, LPVOID pIndex ); /// 메모리에서 쿼드트리를 삭제한다. void _Destroy(); // QuadTree를 구축한다. BOOL Build( TERRAINVERTEX* pHeightMap ); int GenerateIndex( LPVOID pIndex, TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ); /// 현재노드가 프러스텀에 포함되는가? int _IsInFrustum( TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ); /// _IsInFrustum()함수의 결과에 따라 프러스텀 컬링 수행 void _FrustumCull( TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ); }; 컬링에 따른 인덱스 생성 Korea IT Division of Game Development

Division of Game Development 구현 3) 쿼드 트리 생성 – 1 : 귀퉁이 좌표 셋팅 // 최초 루트노드 생성자 ZQuadTree::ZQuadTree( int cx, int cy ) { int i; m_nCenter = 0; for( i = 0 ; i < 4 ; i++ ) m_pChild[i] = NULL; } // 루트노드의 4개 코너값 설정 m_nCorner[CORNER_TL] = 0; m_nCorner[CORNER_TR] = cx - 1; m_nCorner[CORNER_BL] = cx * ( cy - 1 ); m_nCorner[CORNER_BR] = cx * cy - 1; m_nCenter = ( m_nCorner[CORNER_TL] + m_nCorner[CORNER_TR] + m_nCorner[CORNER_BL] + m_nCorner[CORNER_BR] ) / 4; m_fRadius = 0.0f; m_bCulled = FALSE; 쿼드 트리의 네 귀퉁이 값 설정. Korea IT Division of Game Development

Division of Game Development 구현 4) 쿼드 트리 생성 – 2 BOOL ZQuadTree::Build( TERRAINVERTEX* pHeightMap ) { if( _SubDivide() ) // 좌측상단과, 우측 하단의 거리를 구한다. D3DXVECTOR3 v = *((D3DXVECTOR3*)(pHeightMap+m_nCorner[CORNER_TL])) - *((D3DXVECTOR3*)(pHeightMap+m_nCorner[CORNER_BR])); // v의 거리값이 이 노드를 감싸는 경계구의 지름이므로, // 2로 나누어 반지름을 구한다. m_fRadius = D3DXVec3Length( &v ) / 2.0f; m_pChild[CORNER_TL]->Build( pHeightMap ); m_pChild[CORNER_TR]->Build( pHeightMap ); m_pChild[CORNER_BL]->Build( pHeightMap ); m_pChild[CORNER_BR]->Build( pHeightMap ); } return TRUE; 재귀적으로 트리를 구성한다. Korea IT Division of Game Development

Division of Game Development 구현 5) 쿼드 트리 생성 – 3 : 자식 노드로 분할한다. BOOL ZQuadTree::_SubDivide() { int nTopEdgeCenter; int nBottomEdgeCenter; int nLeftEdgeCenter; int nRightEdgeCenter; int nCentralPoint; // 상단변 가운데 nTopEdgeCenter= ( m_nCorner[CORNER_TL] + m_nCorner[CORNER_TR] ) / 2; // 하단변 가운데 nBottomEdgeCenter= ( m_nCorner[CORNER_BL] + m_nCorner[CORNER_BR] ) / 2; // 좌측변 가운데 nLeftEdgeCenter= ( m_nCorner[CORNER_TL] + m_nCorner[CORNER_BL] ) / 2; // 우측변 가운데 nRightEdgeCenter= ( m_nCorner[CORNER_TR] + m_nCorner[CORNER_BR] ) / 2; // 한가운데 nCentralPoint = ( m_nCorner[CORNER_TL] + m_nCorner[CORNER_TR] + m_nCorner[CORNER_BL] + m_nCorner[CORNER_BR] ) / 4; 네개의 귀퉁이 좌표와 중점을 구한다. Korea IT Division of Game Development

Division of Game Development 구현 // 더이상 분할이 불가능한가? 그렇다면 SubDivide() 종료 if( (m_nCorner[CORNER_TR] - m_nCorner[CORNER_TL]) <= 1 ) { return FALSE; } // 4개의 자식노드 추가 m_pChild[CORNER_TL] = _AddChild( m_nCorner[CORNER_TL], nTopEdgeCenter, nLeftEdgeCenter, nCentralPoint ); m_pChild[CORNER_TR] = _AddChild( nTopEdgeCenter, m_nCorner[CORNER_TR], nCentralPoint, nRightEdgeCenter ); m_pChild[CORNER_BL] = _AddChild( nLeftEdgeCenter, nCentralPoint, m_nCorner[CORNER_BL], nBottomEdgeCenter ); m_pChild[CORNER_BR] = _AddChild( nCentralPoint, nRightEdgeCenter, nBottomEdgeCenter, m_nCorner[CORNER_BR] ); return TRUE; 자식 노드를 추가한다. Korea IT Division of Game Development

Division of Game Development 구현 6) 쿼드 트리 생성 – 4 : 자식노드 추가 // 자식 노드를 추가한다. ZQuadTree* ZQuadTree::_AddChild( int nCornerTL, int nCornerTR, int nCornerBL, int nCornerBR ) { ZQuadTree* pChild; pChild = new ZQuadTree( this ); pChild->_SetCorners( nCornerTL, nCornerTR, nCornerBL, nCornerBR ); return pChild; } // 4개의 코너값을 셋팅한다. BOOL ZQuadTree::_SetCorners( int nCornerTL, int nCornerTR, int nCornerBL, int nCornerBR ) m_nCorner[CORNER_TL] = nCornerTL; m_nCorner[CORNER_TR] = nCornerTR; m_nCorner[CORNER_BL] = nCornerBL; m_nCorner[CORNER_BR] = nCornerBR; m_nCenter = ( m_nCorner[CORNER_TL] + m_nCorner[CORNER_TR] + m_nCorner[CORNER_BL] + m_nCorner[CORNER_BR] ) / 4; return TRUE; 자식 노드를 생성하여 값 셋팅 Korea IT Division of Game Development

Division of Game Development 구현 7) 지형 draw시 culling 수행 HRESULT ZTerrain::Draw( ZFrustum* pFrustum ) { LPDWORD pI; if( FAILED( m_pIB->Lock( 0, (m_cxDIB-1)*(m_czDIB-1)*2 * sizeof(TRIINDEX), (void**)&pI, 0 ) ) ) return E_FAIL; // 인데스를 프러스템에서 체크 m_nTriangles = m_pQuadTree->GenerateIndex( pI, m_pvHeightMap, pFrustum ); m_pIB->Unlock(); //g_pLog->Log( "Triangles=%d", m_nTriangles ); _Render(); return S_OK; } 인덱스 버퍼를 lock걸고 인덱스를 생성한다. 매번 화면 그려줄 때 프러스텀에 의해서 보여지는 부분만 그려준다. Korea IT Division of Game Development

Division of Game Development 구현 8) 컬링을 통한 인덱스 생성 Int ZQuadTree::GenerateIndex( LPVOID pIndex, TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ) { // 커링을 쿼드 트리별로 하고 _FrustumCull( pHeightMap, pFrustum ); // 컬링된 인덱스 생성 return _GenTriIndex( 0, pIndex ); } 쿼드 트리별 프로스텀 컬링 수행 컬링을 하고 이에 따라서 인덱스를 생성한다. Korea IT Division of Game Development

Division of Game Development 구현 9) 인덱스에 대한 컬링 수행 void ZQuadTree::_FrustumCull( TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ) { int ret; ret = _IsInFrustum( pHeightMap, pFrustum ); switch( ret ) case FRUSTUM_COMPLETELY_IN : // 프러스텀에 완전포함, 하위노드 검색 필요없음 m_bCulled = FALSE; return; case FRUSTUM_PARTIALLY_IN : break; case FRUSTUM_OUT : // 프러스텀에서 완전벗어남, 하위노드 검색 필요없음 m_bCulled = TRUE; } if( m_pChild[0] ) m_pChild[0]->_FrustumCull( pHeightMap, pFrustum ); if( m_pChild[1] ) m_pChild[1]->_FrustumCull( pHeightMap, pFrustum ); if( m_pChild[2] ) m_pChild[2]->_FrustumCull( pHeightMap, pFrustum ); if( m_pChild[3] ) m_pChild[3]->_FrustumCull( pHeightMap, pFrustum ); 프러스텀 포함 유무 판단 m_bCulled = FALSE 되면 쿼드 트리 검색시 제외된다. 재귀적으로 수행 Korea IT Division of Game Development

Division of Game Development 구현 10) 프러스템 내에 속하는 유무 판단 int ZQuadTree::_IsInFrustum( TERRAINVERTEX* pHeightMap, ZFrustum* pFrustum ) { BOOL b[4]; BOOL bInSphere; bInSphere = pFrustum->IsInSphere( (D3DXVECTOR3*)(pHeightMap+m_nCenter), m_fRadius ); if( !bInSphere ) return FRUSTUM_OUT; // 쿼드트리의 4군데 경계 프러스텀 테스트 b[0] = pFrustum->IsIn( (D3DXVECTOR3*)(pHeightMap+m_nCorner[0]) ); b[1] = pFrustum->IsIn( (D3DXVECTOR3*)(pHeightMap+m_nCorner[1]) ); b[2] = pFrustum->IsIn( (D3DXVECTOR3*)(pHeightMap+m_nCorner[2]) ); b[3] = pFrustum->IsIn( (D3DXVECTOR3*)(pHeightMap+m_nCorner[3]) ); // 4개모두 프러스텀 안에 있음 if( (b[0] + b[1] + b[2] + b[3]) == 4 ) return FRUSTUM_COMPLETELY_IN; // 일부분이 프러스텀에 있는 경우 return FRUSTUM_PARTIALLY_IN; } 경계구 안에 없으면 점단위의 프러스텀 테스트 생략. Korea IT Division of Game Development

Division of Game Development 구현 11) 지형의 인덱스 생성 // 출력할 폴리곤의 인덱스를 생성한다. Int ZQuadTree::_GenTriIndex( int nTris, LPVOID pIndex ) { // 컬링된 노드라면 그냥 리턴 if( m_bCulled ) m_bCulled = FALSE; return nTris; } // 현재 노드가 출력 되지 않는가 ? if( _IsVisible() ) #ifdef _USE_INDEX16 LPWORD p = ((LPWORD)pIndex) + nTris * 3; #else LPDWORD p = ((LPDWORD)pIndex) + nTris * 3; #endif // *p++ = m_nCorner[0]; *p++ = m_nCorner[1]; *p++ = m_nCorner[2]; nTris++; 경계구 안에 없으면 점단위의 프러스텀 테스트 생략. 자식 노드는 검색 필요 없다. 인덱스 값 셋팅 Korea IT Division of Game Development

Division of Game Development 구현 *p++ = m_nCorner[2]; *p++ = m_nCorner[1]; *p++ = m_nCorner[3]; nTris++; return nTris; } // 자식 노드들 검색 재귀적으로 if( m_pChild[CORNER_TL] ) nTris = m_pChild[CORNER_TL]->_GenTriIndex( nTris, pIndex ); if( m_pChild[CORNER_TR] ) nTris = m_pChild[CORNER_TR]->_GenTriIndex( nTris, pIndex ); if( m_pChild[CORNER_BL] ) nTris = m_pChild[CORNER_BL]->_GenTriIndex( nTris, pIndex ); if( m_pChild[CORNER_BR] ) nTris = m_pChild[CORNER_BR]->_GenTriIndex( nTris, pIndex ); 자식 노드 재귀적 검색 하여 인덱스 생성 Korea IT Division of Game Development

Division of Game Development 구현 12) 그려주기 HRESULT ZTerrain::_Render() { m_pd3dDevice->SetTexture( 0, m_pTex[0] ); // 0번 텍스쳐 스테이지에 텍스쳐 고정(색깔맵) m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(TERRAINVERTEX) ); m_pd3dDevice->SetFVF( TERRAINVERTEX::FVF ); m_pd3dDevice->SetIndices( m_pIB ); m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, m_cxDIB * m_czDIB, 0, m_nTriangles ); return S_OK; } 인덱스 방식으로 그리기 Korea IT Division of Game Development