제 15 장 픽킹.

Slides:



Advertisements
Similar presentations
강의 내용 : 카메라 DirectX 9 을 이용한 게임 개발 기본 코스. 목 차 카메라 요구사항 구현.
Advertisements

강의 내용 : DirectX 개요 DirectX 9 을 이용한 시각화. 목 차 DirectX 출현 배경 DirectX 현재 버전 DirectX 장점 DirectX 구성요소 DirectX SDK 다운로드 및 설치 DirectX SDK 폴더 구성 및 역할 샘플 코드 브라우저.
제17장 버텍스 셰이더의 소개.
2장. 윈도우즈 입출력 1/211 1.
7장. MDI 프로그래밍 MDI 프로그래밍에 대한 내용을 배우도록 한다. 지금까지 배운 것은 생성된 윈도우에 단일 화면이 존재하는 형태였다. 이것을 SDI라고 부르고 Single Document Interface의 약자이다. 하나의 문서를 하나의 화면에 보여주는 형태의.
윈도우 운영체제와 윈도우 응용 프로그램의 특징을 이해한다.
2장 렌더링 파이프라인 목표 Direct3D에서 3D 물체를 표현하는 방법을 배운다. 가상카메라를 모델링하는 방법을 배운다.
순차, 조건, 반복 이점숙 농대 뒷편 언덕을 넘어가며 같은 문제 다르게 해결 순차, 조건, 반복 이점숙
순차, 조건, 반복 이점숙 같은 문제 다르게 해결하기 순차, 조건, 반복 이점숙
WSAAsync Select 김대열 Bit - Academy Sunmoon University, Korea.
제1장 윈도우 프로그래밍 1.1 윈도우 프로그래밍의 개념 1.2 윈도우 프로그램의 기본 구조
5장. 단축키와 비트맵 윈도우 프로그램에는 화면에서 사용자들의 입력을 받아 들이고 출력을 위한 코드 외 부분이 존재한다. 이 부분을 주로 리소스라고 부르고 이들은 주로 화면에 나타난다. 메뉴, 툴바, 비트맵, 단축키, 대화상자 등이 여기에 속한다. 이 부분들은 우리의 프로그램의.
DirectX9를 이용한 3D GAME 프로그래밍 입문
(Numerical Analysis of Nonlinear Equation)
쉽게 풀어쓴 C언어 Express 제13장 구조체 C Express Slide 1 (of 25)
윤 홍 란 다이알로그(대화상자) 윤 홍 란
제12장 유연한 카메라 클래스 만들기 학기 컴퓨터게임(DirectX).
제13장 기본적인 지형 렌더링 학기 컴퓨터게임(DirectX).
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
Vector Bubble 충돌 검출 게임 설계 3조 강준순, 김훈석, 복현태.
9장 글꼴.
문 성 원 3D Game Programming QuadTree Culling 문 성 원 KoreaIT 전문학교 게임학과.
9장 글꼴.
제6장 텍스처링 학기 컴퓨터게임(DirectX).
제8장 스텐실.
제 14 장 파티클 시스템.
12장 유연한 카메라 클래스 만들기 한성대학교 멀티미디어공학과 게임 프로그래밍-I 강의노트
제 18 장 픽셀 셰이더의 소개.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
제4장 컬 러(COLOR) 컬러 표현 Direct3D는 RGB 세 성분을 이용해 컬러 표현
제5장 조명 학기 컴퓨터게임(DIrectX).
A Moments of Areas.
11장. 1차원 배열.
제 16 장 고수준 셰이딩 언어 소개.
C#.
13. 연산자 오버로딩.
어서와 C언어는 처음이지 제14장.
Chapter03 캔버스(1) HTML5 Programming.
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
GUI 소켓 애플리케이션 Chapter 08. * 학습목표 윈도우 GUI 애플리케이션의 구조와 동작 원리를 이해
Terrain.
10장 메쉬 파트 I.
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
WSAAsync Select 김대열 Bit - Academy Sunmoon University, Korea.
Clipping 이진학.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
11장 메쉬 파트II 학기 컴퓨터게임(DirectX).
다면체 다면체 다면체: 다각형인 면만으로 둘러싸인 입체도 형 면: 다면체를 둘러싸고 있는 다각형
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
평 면 도 형 삼각형 다각형 원과 부채꼴 다각형과 원 학습내용을 로 선택하세요 다각형과 원
객체기반 SW설계 팀활동지 4.
Real time Interaction HyoungSeok Kim
수학10-나 1학년 2학기 Ⅱ.부등식의 영역 1. 부등식의 영역(2/5) 부등식 영역 수업계획 수업활동.
3장. 제어 메시지 처리하기 1/211 1.
Window, Viewport Window, Viewport.
4장. 데이터 표현 방식의 이해. 4장. 데이터 표현 방식의 이해 4-1 컴퓨터의 데이터 표현 진법에 대한 이해 n 진수 표현 방식 : n개의 문자를 이용해서 데이터를 표현 그림 4-1.
가상현실의 활용 HyoungSeok Kim
원의 방정식 원의 방정식 x축, y축에 접하는 원의 방정식 두 원의 위치 관계 공통접선 원과 직선의 위치 관계
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
수치해석 ch3 환경공학과 김지숙.
DirectX 9 Ch1. Direct3D 초기화.
9장. spss statistics 20의 데이터 변수계산
SEOUL NATIONAL UNIVERSITY OF SCIENCE & TECHNOLOGY
7 생성자 함수.
6 객체.
20 XMLHttpRequest.
Presentation transcript:

제 15 장 픽킹

픽킹 스크린 좌표를 이용해 선택한 물체를 알아내는 테크닉 원점에서 시작하여 p를 통과하도록 광선을 발사하면 p를 둘러싼 투영을 가지는 물체와 교차 픽킹 광선을 계산한 다음에는 장면 내의 각 물체를 대상으로 광선과 교차하는지를 테스트 광선과 교차하는 물체가 바로 사용자가 선택한 물체임 픽킹은 모든 종류의 게임과 3D 애플리케이션에 적용 2009-1학기 컴퓨터게임(DirectX)

(그림1) p를 통과하도록 발사된 광선은 p를 둘러싸는 물체와 교차 투영창, Direct3D는 평면 z=1에 일치하도록 정의하고 있다 투영의 중심 (그림1) p를 통과하도록 발사된 광선은 p를 둘러싸는 물체와 교차 2009-1학기 컴퓨터게임(DirectX)

픽킹 구현 방법 스크린 포인트 s를 통해 투영창에 대응되는 포인트 p를 얻는다. 픽킹 광선과 모델을 동일한 공간으로 변환한다. 픽킹 광선과 교차하는 모델을 알아낸다. 교차된 물체는 선택된 스크린 물체와 대응된다. 2009-1학기 컴퓨터게임(DirectX)

스크린에서 투영창으로의 변환 Height Height Height 2009-1학기 컴퓨터게임(DirectX)

2009-1학기 컴퓨터게임(DirectX)

2009-1학기 컴퓨터게임(DirectX)

픽킹 광선의 계산 광선의 위치를 나타내는 원점이 p0이고 방향을 나타내는 벡터가 u라 하면, 인수 방정식 p(t)=p0+tu를 통해 광선을 표현할 수 있음 광선의 원점은 또한 뷰 스페이스의 원점임을 알 수 있으므로 p0=(0, 0, 0) 방향벡터 u = p – p0 =(px, py, 1)-(0, 0, 0)=p로 얻을 수 있음 2009-1학기 컴퓨터게임(DirectX)

d3d::Ray CalcPickingRay(int x, int y) { float px = 0.0f; 다음의 메서드는 스크린 스페이스 상의 클릭된 포인트의 x와 y 좌표를 이용해 픽킹 광선을 계산해 냄 d3d::Ray CalcPickingRay(int x, int y) { float px = 0.0f; float py = 0.0f; D3DVIEWPORT9 vp; Device->GetViewport(&vp); D3DXMATRIX proj; Device->GetTransform(D3DTS_PROJECTION, &proj); 2009-1학기 컴퓨터게임(DirectX)

px = ((( 2.0f*x) / vp.Width) - 1.0f) / proj(0, 0); py = (((-2.0f*y) / vp.Height) + 1.0f) / proj(1, 1); d3d::Ray ray; ray._origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f); ray._direction = D3DXVECTOR3(px, py, 1.0f); return ray; } Where Ray is defined as: struct Ray { D3DXVECTOR3 _origin; D3DXVECTOR3 _direction; }; 2009-1학기 컴퓨터게임(DirectX)

광선의 변환 앞에서의 픽킹 광선은 뷰 스페이스에서 표현된 것이며, 광선-물체 교차 테스트를 위해서는 광선과 물체가 반드시 동일한 좌표 시스템 내에 위치해야 함 모든 물체를 뷰 스페이스로 변환하는 것보다는 월드 스페이스나 혹은 물체의 지역 스페이스로 픽킹 광선을 변환하는 것이 수월 변환 행렬을 이용해 광선 r(t)=p0+tu의 원점 p0과 방향 u를 변환할 수 있음. 다음과 같은 함수를 이용해 광선을 변환 2009-1학기 컴퓨터게임(DirectX)

void TransformRay(d3d::Ray* ray, D3DXMATRIX* T) { // transform the ray's origin, w = 1. D3DXVec3TransformCoord( &ray->_origin, T); // transform the ray's direction, w = 0. D3DXVec3TransformNormal( &ray->_direction, 2009-1학기 컴퓨터게임(DirectX)

// normalize the direction D3DXVec3Normalize(&ray->_direction, &ray->_direction); } 2009-1학기 컴퓨터게임(DirectX)

광선-물체 교차 동일한 좌표 시스템에 픽킹 광선과 물체가 준비되면 광선이 물체를 교차하는지를 테스트할 준비가 완료된 것 첫 번째 방법은 물체를 이루는 모든 삼각형들에 차례대로 광선 교차 테스트를 수행 하지만 장면의 모든 삼각형을 대상으로 교차 테스트를 수행한다는 것은 효율 면에서 그리 좋은 선택이 아님 다소 정확성이 떨어지기는 하지만 각 물체의 경계 구체를 이용하는 방법이 효율 면에서 좀더 유리. 2009-1학기 컴퓨터게임(DirectX)

(그림15.3) p-c로 구성된 벡터의 길이 ||p-c||는 구의 중심점 c와 반지름 r이 있다고 할 때 다음과 같은 암시적 방정식을 이용해 포인트 p를 테스트할 수 있음 ||p-c||-r=0 방정식이 만족되면 p가 구 내에 있음. +y c p-c p +x (그림15.3) p-c로 구성된 벡터의 길이 ||p-c||는 p가 구체 내에 있을 경우 구체의 반지름과 같음 2009-1학기 컴퓨터게임(DirectX)

광선과 구체의 교차 확인 광선 p(t) = p0 + tu가 구체와 교차하는지를 확인하기 위해서는 광선을 암시적 구방정식에 넣고 구 방정식을 만족시키는 인자 t를 풀어 교차점 (s)를 구해야 함 우선 구 방정식에 광선을 넣음 ||p(t) - c|| - r = 0 ||p0 + tu - c|| - r = 0 ||p0 + tu - c||2 – r2 = 0 u2 t2 + 2u(p0 – c)t + (p0 – c)2 – r2 = 0 2009-1학기 컴퓨터게임(DirectX)

A=u·u, B=2(u·(p0-c)), 그리고 C=(p0-c) ·(p0-c)-r2에서 u를 정규화할 경우 A=1임 여기에서 다음과 같은 2차 방정식을 얻음 At2+Bt+C=0 A=u·u, B=2(u·(p0-c)), 그리고 C=(p0-c) ·(p0-c)-r2에서 u를 정규화할 경우 A=1임 u가 정규화 되었다고 가정하면 t0과 t1을 풀어낼 수 있음 2009-1학기 컴퓨터게임(DirectX)

다음의 메서드는 전달된 광선이 전달된 구체를 교차할 경우 True를 리턴하며, 빗나갈 경우 False를 리턴 Bool PickApp::RaySphereIntersectionTest(Ray* ray, BoundingSphere* sphere) { D3DXVECTOR3 v = ray->_origin - sphere->_center; float b = 2.0f * D3DXVec3Dot(&ray->_direction, &v); float c = D3DXVec3Dot(&v, &v) - (sphere->_radius * sphere->_radius); // find the discriminant float discriminant = (b * b) - (4.0f * c); 2009-1학기 컴퓨터게임(DirectX)

// test for imaginary number if( discriminant < 0.0f ) return false; discriminant = sqrtf(discriminant); float s0 = (-b + discriminant) / 2.0f; float s1 = (-b - discriminant) / 2.0f; // if a solution is >= 0, then we intersected the sphere if( s0 >= 0.0f || s1 >= 0.0f ) return true; } 2009-1학기 컴퓨터게임(DirectX)

(a) (b) (c) (d) (e) 광선이 구체내부에 있음. 하나는 양수, 하나는 음수 광선이 구체와 접촉, t0=t1, 구체를 빗나감 광선이 구체내부에 있음. 하나는 양수, 하나는 음수 광선이 구체와 접촉, t0=t1, 해는 양수 광선이 구체를 교차 T0, t1 이 모두 양수 광선이 구체의 중심을 교차 t0, t1이 다 음수 2009-1학기 컴퓨터게임(DirectX)

예제 애플리케이션: 픽킹 주전자를 둘러싼 구를 마우스로 클릭할 수 있고, 만약 구체를 맞추면 이를 알려주는 메시지 상자가 열림 WM_LBUTTONDOWN 메시지를 이용해 마우스 클릭 이벤트를 처리 case WM_LBUTTONDOWN: // compute the ray in view space given the clicked screen point d3d::Ray ray = CalcPickingRay(LOWORD(lParam), HIWORD(lParam)); // transform the ray to world space D3DXMATRIX view; Device->GetTransform(D3DTS_VIEW, &view); 2009-1학기 컴퓨터게임(DirectX)

D3DXMATRIX viewInverse; D3DXMatrixInverse(&viewInverse, 0, &view); TransformRay(&ray, &viewInverse); // test for a hit if( RaySphereIntTest(&ray, &BSphere) ) ::MessageBox(0, "Hit!", "HIT", 0); break; 2009-1학기 컴퓨터게임(DirectX)

2009-1학기 컴퓨터게임(DirectX)

예제 프로그램: 픽킹 #include "d3dUtility.h" IDirect3DDevice9* Device = 0; const int Width = 640; const int Height = 480; ID3DXMesh* Teapot = 0; ID3DXMesh* Sphere = 0; D3DXMATRIX World; d3d::BoundingSphere BSphere; d3d::Ray CalcPickingRay(int x, int y) { float px = 0.0f; float py = 0.0f; 2009-1학기 컴퓨터게임(DirectX)

Device->GetViewport(&vp); D3DXMATRIX proj; D3DVIEWPORT9 vp; Device->GetViewport(&vp); D3DXMATRIX proj; Device->GetTransform(D3DTS_PROJECTION, &proj); px = ((( 2.0f*x) / vp.Width) - 1.0f) / proj(0, 0); py = (((-2.0f*y) / vp.Height) + 1.0f) / proj(1, 1); d3d::Ray ray; ray._origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f); ray._direction = D3DXVECTOR3(px, py, 1.0f); return ray; } 2009-1학기 컴퓨터게임(DirectX)

void TransformRay(d3d::Ray* ray, D3DXMATRIX* T) { // transform the ray's origin, w = 1. D3DXVec3TransformCoord( &ray->_origin, T); // transform the ray's direction, w = 0. D3DXVec3TransformNormal( &ray->_direction, // normalize the direction D3DXVec3Normalize(&ray->_direction, &ray->_direction); } 2009-1학기 컴퓨터게임(DirectX)

bool RaySphereIntTest(d3d::Ray* ray, d3d::BoundingSphere* sphere) { D3DXVECTOR3 v = ray->_origin - sphere->_center; float b = 2.0f * D3DXVec3Dot(&ray->_direction, &v); float c = D3DXVec3Dot(&v, &v) - (sphere->_radius * sphere->_radius); // find the discriminant float discriminant = (b * b) - (4.0f * c); // test for imaginary number if( discriminant < 0.0f ) return false; discriminant = sqrtf(discriminant); 2009-1학기 컴퓨터게임(DirectX)

float s0 = (-b + discriminant) / 2.0f; // if a solution is >= 0, then we intersected the sphere if( s0 >= 0.0f || s1 >= 0.0f ) return true; return false; } bool Setup() { D3DXCreateTeapot(Device, &Teapot, 0); BYTE* v = 0; Teapot->LockVertexBuffer(0, (void**)&v); 2009-1학기 컴퓨터게임(DirectX)

D3DXComputeBoundingSphere( (D3DXVECTOR3*)v, Teapot->GetNumVertices(), D3DXGetFVFVertexSize(Teapot->GetFVF()), &BSphere._center, &BSphere._radius); Teapot->UnlockVertexBuffer(); // Build a sphere mesh that describes the teapot's bounding sphere. D3DXCreateSphere(Device, BSphere._radius, 20, 20, &Sphere, 0); // Set light. D3DXVECTOR3 dir(0.707f, -0.0f, 0.707f); D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f); D3DLIGHT9 light = d3d::InitDirectionalLight(&dir, &col); 2009-1학기 컴퓨터게임(DirectX)

Device->SetLight(0, &light); Device->LightEnable(0, true); Device->SetRenderState(D3DRS_NORMALIZENORMALS, true); Device->SetRenderState(D3DRS_SPECULARENABLE, false); // Set view matrix. D3DXVECTOR3 pos(0.0f, 0.0f, -10.0f); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &pos, &target, &up); Device->SetTransform(D3DTS_VIEW, &V); // Set projection matrix. D3DXMATRIX proj; 2009-1학기 컴퓨터게임(DirectX)

D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.25f, // 45 - degree (float)Width / (float)Height, 1.0f, 1000.0f); Device->SetTransform(D3DTS_PROJECTION, &proj); return true; } void Cleanup() { d3d::Release<ID3DXMesh*>(Teapot); d3d::Release<ID3DXMesh*>(Sphere); 2009-1학기 컴퓨터게임(DirectX)

bool Display(float timeDelta) { if( Device ) // Update: Update Teapot. static float r = 0.0f; static float v = 1.0f; static float angle = 0.0f; D3DXMatrixTranslation(&World, cosf(angle) * r, sinf(angle) * r, 10.0f); // transfrom the bounding sphere to match the teapots position in the // world. BSphere._center = D3DXVECTOR3(cosf(angle)*r, sinf(angle)*r, 10.0f); 2009-1학기 컴퓨터게임(DirectX)

v = -v; // reverse direction if( r <= 0.0f ) r += v * timeDelta; if( r >= 8.0f ) v = -v; // reverse direction if( r <= 0.0f ) angle += 1.0f * D3DX_PI * timeDelta; if( angle >= D3DX_PI * 2.0f ) angle = 0.0f; // Render Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); Device->BeginScene(); 2009-1학기 컴퓨터게임(DirectX)

Device->SetTransform(D3DTS_WORLD, &World); // Render the teapot. Device->SetTransform(D3DTS_WORLD, &World); Device->SetMaterial(&d3d::YELLOW_MTRL); Teapot->DrawSubset(0); // Render the bounding sphere with alpha blending so we can see // through it. Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); D3DMATERIAL9 blue = d3d::BLUE_MTRL; blue.Diffuse.a = 0.25f; // 25% opacity Device->SetMaterial(&blue); Sphere->DrawSubset(0); 2009-1학기 컴퓨터게임(DirectX)

Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); Device->EndScene(); Device->Present(0, 0, 0, 0); } return true; // WndProc LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) case WM_DESTROY: ::PostQuitMessage(0); break; 2009-1학기 컴퓨터게임(DirectX)

if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; case WM_KEYDOWN: if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); break; case WM_LBUTTONDOWN: // compute the ray in view space given the clicked screen point d3d::Ray ray = CalcPickingRay(LOWORD(lParam), HIWORD(lParam)); // transform the ray to world space D3DXMATRIX view; Device->GetTransform(D3DTS_VIEW, &view); D3DXMATRIX viewInverse; D3DXMatrixInverse(&viewInverse, 0, &view); 2009-1학기 컴퓨터게임(DirectX)

TransformRay(&ray, &viewInverse); // test for a hit if( RaySphereIntTest(&ray, &BSphere) ) ::MessageBox(0, "Hit!", "HIT", 0); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); // WinMain int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) { 2009-1학기 컴퓨터게임(DirectX)

if(!d3d::InitD3D(hinstance, Width, Height, true, D3DDEVTYPE_HAL, &Device)) { ::MessageBox(0, "InitD3D() - FAILED", 0, 0); return 0; } if(!Setup()) ::MessageBox(0, "Setup() - FAILED", 0, 0); d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); 2009-1학기 컴퓨터게임(DirectX)