3D 화면을그리기위해필요한기본기 XNA 에서 2D 화면을그릴때는 SpriteBatch 하나면끝났지만, 3D를그리기위해서는행렬과 Model, BasicEffect 등여러가지를알아야한다. 이제부터하나씩확인해보자. 먼저 XNA 에서 3D Model 을화면에나타내려면아래의 4

Similar documents
persona

Game Graphics XNA를 이용한 모바일 3D 게임 만들기 [2] XNA를 이용한 Windows Phone 7 3D 게임 만들기 1 스마트폰에 들어가는 앱(App) 중에 가장 많은 부분을 차지하는 영역이 바로 게임분 야로서 이번 시간은 Windows Phone

Microsoft PowerPoint - GameProgramming7-Model [호환 모드]

Microsoft PowerPoint - GameProgramming7-Model.ppt [호환 모드]

임베디드 시스템 소프트웨어

(Microsoft PowerPoint - \301\24613\260\255 - oFusion \276\300 \261\270\274\272)

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

Game Graphics XNA를 이용한 모바일 3D 게임 만들기 3 XNA를 이용한 Windows Phone 7 3D 게임 만들기 2 Windows Phone 7(WP 7)의 출시가 임박해지자, WP 7을 준비하고 있는 DELL, LG, Asus 등 제조사들의 발걸음

슬라이드 1

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

<4D F736F F F696E74202D20C1A63034B0AD202D20C7C1B7B9C0D3B8AEBDBAB3CABFCD20B9ABB9F6C6DBC0D4B7C2>

PowerPoint 프레젠테이션

Microsoft Word - windows server 2003 수동설치_non pro support_.doc

임베디드 시스템 소프트웨어

쉽게 풀어쓴 C 프로그래밍

임베디드 시스템 소프트웨어

PowerPoint 프레젠테이션

MVVM 패턴의 이해

Microsoft PowerPoint SDK설치.HelloAndroid(1.5h).pptx



iii. Design Tab 을 Click 하여 WindowBuilder 가자동으로생성한 GUI 프로그래밍환경을확인한다.

Microsoft PowerPoint - 13prac.pptx

제8장 자바 GUI 프로그래밍 II

Open GL

Vector Differential: 벡터 미분 Yonghee Lee October 17, 벡터미분의 표기 스칼라미분 벡터미분(Vector diffrential) 또는 행렬미분(Matrix differential)은 벡터와 행렬의 미분식에 대 한 표

윈도우시스템프로그래밍

PowerPoint 프레젠테이션

PowerPoint Presentation

3D MAX + WEEK 9 Hansung Univ. Interior Design

Microsoft PowerPoint - additional01.ppt [호환 모드]

PowerPoint 프레젠테이션

Windows 10 General Announcement v1.0-KO

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Microsoft PowerPoint - C++ 5 .pptx

서강대학교 공과대학 컴퓨터공학과 CSE4170 기초 컴퓨터 그래픽스 중간고사 (1/7) [CSE4170: 기초 컴퓨터 그래픽스] 중간고사 (담당교수: 임 인 성) 답은 연습지가 아니라 답안지에 기술할 것. 답 안지 공간이 부족할 경우, 답안지 뒷면에 기술 하고, 해당

<4D F736F F F696E74202D B3E22032C7D0B1E220C0A9B5B5BFECB0D4C0D3C7C1B7CEB1D7B7A1B9D620C1A638B0AD202D20C7C1B7B9C0D320BCD3B5B5C0C720C1B6C0FD>

ALTIBASE 사용자가이드 Templete

슬라이드 1

아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상

(Microsoft PowerPoint - 07\300\345.ppt [\310\243\310\257 \270\360\265\345])

Microsoft PowerPoint - lecture11-ch5.ppt [호환 모드]

Microsoft PowerPoint - [2009] 02.pptx

쉽게 풀어쓴 C 프로그래밍

<4D F736F F F696E74202D C61645FB3EDB8AEC7D5BCBA20B9D720C5F8BBE7BFEBB9FD2E BC8A3C8AF20B8F0B5E55D>

PowerPoint Presentation

윈도우시스템프로그래밍

이 장에서 사용되는 MATLAB 명령어들은 비교적 복잡하므로 MATLAB 창에서 명령어를 직접 입력하지 않고 확장자가 m 인 text 파일을 작성하여 실행을 한다

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

PowerPoint Presentation

UI TASK & KEY EVENT

목차 윈도우드라이버 1. 매뉴얼안내 운영체제 (OS) 환경 윈도우드라이버준비 윈도우드라이버설치 Windows XP/Server 2003 에서설치 Serial 또는 Parallel 포트의경우.

PathEye 공식 블로그 다운로드 받으세요!! 지속적으로 업그래이드 됩니다. 여러분의 의견을 주시면 개발에 반영하겠 습니다.

Microsoft PowerPoint - chap01-C언어개요.pptx

KNK_C_05_Pointers_Arrays_structures_summary_v02

JDK이클립스

OCW_C언어 기초

PowerPoint Presentation

Microsoft PowerPoint UI-Event.Notification(1.5h).pptx

gnu-lee-oop-kor-lec06-3-chap7

SBR-100S User Manual

C++ Programming

API 매뉴얼

Microsoft PowerPoint - chap06-2pointer.ppt

스마트월드캠퍼스 교육교제

[로플랫]표준상품소개서_(1.042)

API 매뉴얼

Studuino소프트웨어 설치

Microsoft Word - cg07-midterm.doc

슬라이드 1

Microsoft PowerPoint - chap04-연산자.pptx

data

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

ISP and CodeVisionAVR C Compiler.hwp

Raspbian 설치 라즈비안 OS (Raspbian OS) 라즈베리파이 3 Model B USB 마우스 USB 키보드 마이크로 SD 카드 마이크로 SD 카드리더기 HDM I 케이블모니터

JUNIT 실습및발표

1. 객체의생성과대입 int 형변수 : 선언과동시에초기화하는방법 (C++) int a = 3; int a(3); // 기본타입역시클래스와같이처리가능 객체의생성 ( 복습 ) class CPoint private : int x, y; public : CPoint(int a

서현수

4 장클래스와객체 클래스와객체 public과 private 구조체와클래스객체의생성과생성자객체의소멸과소멸자생성자와소멸자의호출순서디폴트생성자와디폴트소멸자멤버초기화멤버함수의외부정의멤버함수의인라인함수선언 C++ 프로그래밍입문

Chap 6: Graphs

Łø·ŸÕ=¤ ¬ ÇX±xÒ¸ 06 - Èpº– 1

슬라이드 1

chap 5: Trees

adfasdfasfdasfasfadf

1 경영학을 위한 수학 Final Exam 2015/12/12(토) 13:00-15:00 풀이과정을 모두 명시하시오. 정리를 사용할 경우 명시하시오. 1. (각 6점) 다음 적분을 구하시오 Z 1 4 Z 1 (x + 1) dx (a) 1 (x 1)4 dx 1 Solut

설계란 무엇인가?

<4D F736F F D20BECBB1E220BDACBFEE20BAA4C5CD2C20C1C2C7A5B0E82C20C1C2C7A5BAAFC8AFC7E0B7C4>

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인

C++ Programming

쉽게 풀어쓴 C 프로그래밍

2) 활동하기 활동개요 활동과정 [ 예제 10-1]main.xml 1 <LinearLayout xmlns:android=" 2 xmlns:tools="

Contributors: Myung Su Seok and SeokJae Yoo Last Update: 09/25/ Introduction 2015년 8월현재전자기학분야에서가장많이쓰이고있는 simulation software는다음과같은알고리즘을사용하고있다.

슬라이드 1

구조체정의 자료형 (data types) 기본자료형 (primitive data types) : char, int, float 등과같이 C 언어에서제공하는자료형. 사용자정의자료형 (user-defined data types) : 다양한자료형을묶어서목적에따라새로운자료형을

Microsoft Word - cg12-midterm-answer

쉽게 풀어쓴 C 프로그래밍

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

<4D F736F F D20BDBAB8B6C6AE545620BCD3BFA1BCADC0C720534E5320C6F7C1F6BCC5B4D720B9D720C0FCB7AB5FBCDBB9CEC1A42E646F63>

Microsoft PowerPoint - Week04_DirectX9 프로그래밍의 기초2.pptx

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

Transcription:

Game Graphics XNA 를이용한모바일 3D 게임만들기 4 XNA 를이용한 Windows Phone 7 3D 게임만들기 3 지난 10월 11일. 드디어 windows Phone 7(WP7) 이세계시장에출시되었다. MS 가야심차게준비한 Windows phone 7이전체스마트폰시장에서어떤영향력을발휘할지사뭇궁금하다. 윈도우폰을통해게임을좋아하는사용자들은 XBox Live 에서즐기던게임들을 WP 환경에서도즐길수있게되었다. 이번시간은마지막시간으로지난강의에이어삼성전자 DMC 연구소의김동훈연구원이맡아진행하였다. 디자이너와같은프로그래밍에약한분들도쉽게따라가며 3D 게임을만들어볼수있는경험이되도록강의가구성되었다. 들어가며지난호에서는 2D게임제작에필요한기반기술과사운드출력, 크로스플랫폼프로젝트만들기등실전게임개발에필요한내용을설명했었다. 이번호는드디어 3D이다. Windows Phone 7을위해새롭게추가된 3D API 및 Effect 에대해설명하고, 예제를통해이를적용해보자. XNA 4.0 정식버전과 Platformer Starter Kit 4.0 필자가지난번에이야기한대로 9월 16일에 Windows Phone 7 정식개발환경과 XNA 4.0 정식버전이출시되었다. 이에따라 Platformer Starter Kit도 4.0 버전으로업그레이드되어 App Hub에서제공되고있다. Windows Phone 7 에서지원하는프레임워크, Silverlight 과 XNA 는사용목적이다르다. XNA 4.0 버전으로재탄생된 Platformer 예제. WP7 도당연히지원한다. App Hub는기존의 XNA Creators Club 이업그레이드된것으로 Windows Phone 7 개발자를위한통합개발자포털사이트이다. WP7 의 Application Framework 는 XNA와 Silverlight 로구성되기때문에 App Hub에서는 XNA와 Silverlight 관련자료를얻을수있으며, 99달러를지불하면 WP7 app을 5개까지만들어서세계에판매할수있다. 참고로 App Hub의 Community-Meet the MVPs 란을보면필자의이름과간단한프로필을확인할수있으니, 앞으로개발을하면서궁금한점이있을때필자에게부담없이메일을보내면되겠다. 새롭게개편된 App Hub 홈페이지 92 NOVEMBER 2010

3D 화면을그리기위해필요한기본기 XNA 에서 2D 화면을그릴때는 SpriteBatch 하나면끝났지만, 3D를그리기위해서는행렬과 Model, BasicEffect 등여러가지를알아야한다. 이제부터하나씩확인해보자. 먼저 XNA 에서 3D Model 을화면에나타내려면아래의 4가지과정은반드시거쳐야한다. QuickTime 을실행해서 FBX 파일을열고확인하는자세한과정은다음의주소에서확인하면된다. (http://blog.naver.com/fly33499/120061402853) 1. Content Project 에 Model 데이터추가및로딩 2. Model 에적용할 World, View, Projection 행렬을설정 3. Model 의변환행렬을얻어냄 4. Model 이가지고있는 mesh 의 effect 에 2번에서설정한 world, view, projection 행렬, 변환행렬 (Bone), 빛 (Light) 을적용 딱 4단계다. 여기에 BasicEffect, SkinnedEffect 등여러가지 Effect 를적용하면서몇가지의과정이더추가되기에, 위에서설명한 4가지과정은모든 Effect 의기본이된다. 이번호예제로제공되는파일을받아압축을풀면 spaceship.fbx 파일과 enemy.tga 파일이있을것이다. spaceship.fbx 파일은 3D 모델파일로, Maya 나 3ds Max 에서쉽게 fbx 로 export 가가능한포맷이다. 다만 XNA 에서사용하기위해서는최신버전의 FBX Exporter 를이용하므로아래의사이트에서각자버전에맞는 Exporter 를설치하도록하자. 예제파일다운로드 (http://usa.autodesk.com/adsk/servlet/pc/item?siteid=123112&id=10775855) Autodesk FBX 홈페이지에서는다양한버전의 Maya 와 3ds Max를지원한다. 3ds Max, Maya 에서모델을 export 하는과정은생략한다. 이와관련된내용은 Naver XNA 카페에있는자료를통해공부할수있다. (http://cafe.naver.com/xna) Export 가끝났다면 3D 모델데이터가제대로 export 되었는지를확인해야된다. 이를위해 Autodesk 에서는 QuickTime 에서사용할수있는 FBX Viewer Plugin 을제공하고있다. Viewer 설치파일은같은사이트하단에서찾을수있다. QuickTime Viewer 를통해 fbx 파일을로딩한화면 대부분의 FBX Exporter 관련문의를보면 export 한모델이제대로 XNA 화면에서나오지않는경우가많은데, 이럴때 QuickTime FBX Viewer 를통해미리확인한다면고생할일이반으로줄어든다. FBX 파일등록및 View, Projection 행렬설정하기자, 이제 spaceship.fbx 파일을 Content Project 에등록하고코드에서읽어보자. Content Project 에등록하는것은기존과같은방법으로 FBX 파일을 Content Project 에추가하면된다. 단! 텍스처파일은추가하지않는다. Content Project 가추가된 FBX 파일을빌드하면서관련된텍스처파일을자동으로찾기때문이다. 텍스처를제외한 fbx 파일만추가한다. Viewer 를설치하기전에반드시 QuickTime 을먼저설치해야한다. NOVEMBER 2010 93

이렇게프로젝트에추가된파일을아래와같은코드로읽어들이면된다. Model spaceshipmodel; protected override void LoadContent() // SpriteBatch 초기화 spritebatch = new SpriteBatch(GraphicsDevice); 먼저, View 행렬을만들어보자. 이미위에서설명한대로 View 행렬을만들기위해서는현재카메라의위치와바라보는지점의좌표가필요하다. 이에추가적으로 Up Vector 라는것이필요한데, 여기서는월드좌표계에서의기준 Up Vector 인 (0,1,0) 을사용할것이다. Up Vector 와관련된자세한내용은여기서는생략하도록한다. 필자의블로그에서카메라관련내용을검색해보면확인할수있다. 이를바탕으로 View 행렬을만들어보면아래와같다. // 우주선모델 spaceshipmodel = Content.Load<Model>("spaceship"); Model 클래스는 XNA에서 3D Model 을그리기위해제공하는것으로 FBX 나 X파일등을읽어서로딩하면 Model 클래스데이터로변환되어로딩된다. Model 클래스는아래와같이단순하게정의되어있다. Vector3 cameraposition = new Vector3(0, 20, 100); Vector3 cameralookatposition = new Vector3(0, 0, 0); Matrix cameraviewmatrix = Matrix.CreateLookAt(cameraPosition, cameralookatposition, Vector3.Up); (0,1,0) 의 Up 벡터를쉽게쓰기위해 Vector3.Up 을이용하였다는것을제외하면생각보다간단하다. 위코드의의미는 (0, 20, 100) 에위치한카메라가 (0,0,0) 을바라보고있다는것이다. 자, 이제 Projection 행렬이다. Projection 은차원을줄인다는의미로 3차원이 2차원이되게만들어주는행렬이되겠다. 위에서계산된 View 행렬을어떻게 2D 화면에잘맞춰서보여줄수있을까? 이를위해아래절두체그림을보도록하자. Model Class 이제 Model 에적용할 world, view, projection 행렬을설정해보자. World 행렬은 3D 공간상에위치한절대적위치를말한다.( 상대적위치가아님 ). 또한위치뿐만아니라스케일, 회전도같이적용한행렬형태로사용된다. Spaceship model을 (100,100,100) 으로이동하고, 반으로크기를줄이고, Y축으로 50도바라보게하는행렬을만들면아래와같다. Matrix scalemat = Matrix.CreateScale(0.5f); Matrix rotationmat = Matrix.CreateRotationY(MathHelper.ToRadians(50)); Matrix translationmat = Matrix.CreateTranslation(100,100,100); Matrix worldmat = scalemat * rotationmat * translationmat; 참고로행렬은반드시 Scale * Rotation * Translation 순으로곱해야한다. 3ds Max나 Maya 에서 3D Camera 를다뤄봤다면이미툴을통해화면을구성해보았으므로 Camera 에익숙할것이다. 3D 프로그래밍적으로본다면 3D 화면은 View, Projection 행렬로구성된다. View행렬의의미는 3D 공간에서 Camera 가위치한지점 (Position) 에서특정지점을바라보는것 (LookAt) 을의미한다. Projection 행렬의의미는 Camera 가바라보는화면을화면해상도에맞게 2D 평면으로만들어주는것을의미한다. 절두체 (View Frustum) 뭔가복잡해보이는그림이나왔다. 결론을먼저이야기해보자. Angle, aspect ratio, near/far clip이필요하다는것이다. 그림에서 near, far clip 은거리를의미한다. Near 가 10일경우, 9인위치에있는물체는보이지않는것이고, far 가 1000 인경우, 1001 에위치한물체는화면에보이지않는다. Aspect Ratio( 종횡비 ) 는말그대로화면의너비를높이로나눈것을말하고, Field of view angle ( 시야각 ) 은보통 45도를쓰는데, 시야각수치를이것저것바꾸어보면재미있는샷이나온다. 꼭해보기를권장한다. 이를바탕으로 Projection 행렬을만들어보면아래와같다. float near = 10; float far = 1000; float aspectratio = GraphicsDevice.Viewport.AspectRatio; Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper. ToRadians(45), aspectratio, near, far); 94 NOVEMBER 2010

Matrix.CreatePerspectiveFieldOfView() 함수는시야각을 degree 가아닌 radian 으로입력받기때문에 50도를 radian 으로바꿔서입력하였고, 종횡비는 GraphicsDevice.Viewport 가 AspectRatio 를이미알고있기에이값을사용하였다. 이제, 위에서설정한 View, Projection 행렬을이용하여화면에그려보자. 3D Model 을화면에그리기 Model 을화면에그리기위해서는 Effect 를사용해야한다. XNA 4.0 에서는총 5개의 Effect 가사용목적에따라제공되며, 이중기본 3D Model 을그리는데사용되는 BasicEffect 와스키닝애니메이션을위해제공되는 SkinnedEffect 에대해알아보도록하자. BasicEffect 를통해 Fog, light 등의속성편집을통해효과적인 3D 장면을만들수있다. WP7 에서는 5 개의 Effect 들이제공된다. SkinnedEffect는스키닝애니메이션에서다루기로하고, 먼저 BasicEffect 부터알아보자. Effect는이미 3D Model을 Content Project 에추가할때설정할수있었다.( 디폴트설정이 BasicEffect 임 ) protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.CornflowerBlue); // 우주선모델의 root 변환행렬을설정, 월드좌표계적용 // 우주선이너무커서 scale을 0.01f로설정, 100배작아짐 // 행렬은 SRT 순으로곱해야한다. Scale*Rotation*Translation spaceshipmodel.root.transform = Matrix.CreateScale(0.01f); // model 의변환행렬을 bonetransform 에복사. Matrix[] bonetransforms = new Matrix[spaceshipModel.Bones.Count]; spaceshipmodel.copyabsolutebonetransformsto(bonetransforms); // Draw the model. foreach (ModelMesh mesh in spaceshipmodel.meshes) foreach (BasicEffect effect in mesh.effects) // 변환행렬중현재 bone index에해당하는행렬을 effect.world에설정 effect.world = bonetransforms[mesh.parentbone.index]; // View 행렬을만든다. (0,20,100) 에서원점을바라본다. effect.view = Matrix.CreateLookAt(new Vector3(0,20,100), Vector3. Zero, Vector3.Up); Fbx 파일의속성편집. BasicEffect 를비롯한 5 개의 Effect 중선택할수있다. Content Processor 의 Default Effect 를 BasicEffect 로설정할경우, 화면에그릴때반드시 BasicEffect를이용해그려야만한다. BasicEffect 는대략 20개정도의멤버변수및함수를제공하고있다. 대부분은이름만봐도의미를이해할수있을정도이며, 이중가장중요한 4 개에대해서알아보자. (4개만으로도화면출력이가능 ) // Projection 행렬을만든다. 시야각은 45도, 종횡비는 AspectRatio가알려준다, 근거리는 10, 원거리는 1000으로설정 // 10 미만, 1000 초과인사물은보이지않게된다. effect.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 10, 1000); // 디폴트로빛을설정한다.( 기본으로 3점조명이들어간다 ) NOVEMBER 2010 95

effect.enabledefaultlighting(); mesh.draw(); ParentBone.Index] 을대입하는이유이며, Mesh.draw() 에서 effect. world 와정점을곱하게된다. 그리고자동차모델의 Root 변환행렬자체를변경하여자동차모델이가지고있는변환행렬에변화를주는코드가아래의코드이다. base.draw(gametime); 위에서설명한 View, Projection, World 가적용된위치를확인하자. EnableDefaultLighting() 함수를호출하면 BasicEffect 가제공하는디폴트빛이설정된다. 위의코드가화면을그릴때가장기본적인코드이고, 앞으로계속위의코드를기반으로쓰일테니반드시이해하도록하자. 이제 Model 과 BasicEffect 의관계에대해조금더자세히생각해보자. Model Class 는여러개의 submesh 를가지고있을수있고, 해당 submesh 는화면에그려지는방식 (Effect) 이다를수있다. 가령자동차를생각해보면, 자동차는몸체와문짝, 바퀴 4개로이뤄지는데, 이들은각각 submesh 이고, 텍스처나재질이다르고화면에보여지는위치등이다를것이다. spaceshipmodel.root.transform = Matrix.CreateScale(0.01f); Root.Transform 을설정하면, spaceshipmodel.copyabsolutebonet ransformsto(bonetransforms); 을통해값을얻을때내부의변환행렬들이 Root.Transform 과곱해져서월드좌표의값이나온다. 자, 이제예제를실행해보자, 아래와같은화면이나올것이다. 3D 우주선과의첫만남이다! 기본예제실행 : 3d 우주선 ( 회전없음 ) 실행해보면, 아무런반응이없는데생동감을주기위해 Y축회전과키보드입력을통한이동을구현하자. 자동차 3D 모델은바퀴, 문짝등의여러개의 submesh 로구성됨 using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Media; 자동차라는하나의몸체에붙어있다하더라도각각부품을화면에그리기위해서는 world 좌표계에서보여지는최종위치를얻어야하므로자신의부모의 world 행렬을얻어내는것이다. 이부모의 world 행렬과자신의행렬을곱하면 world 행렬로변환된다. 왜부모의 world 행렬과자신의행렬을곱하면 world 행렬로변환될까? 엄마뱃속에있는아이를생각해보면쉽다. 아이는항상엄마의중심에서일정한거리에위치해있다 ( 상대적위치 ). 이때엄마가어디론가간다고했을때, 아이의입장에서자신의 World 위치는엄마의절대위치더하기자신과엄마의상대적인위치가될것이다. ( 행렬은곱하기로모든것을말한다.) 위에서설명한과정이코드에서 effect.world 에 bonetransform[mesh. namespace example3 public class Game1 : Microsoft.Xna.Framework.Game GraphicsDeviceManager graphics; SpriteBatch spritebatch; Model spaceshipmodel; public Game1() graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; 96 NOVEMBER 2010

// Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); protected override void Initialize() base.initialize(); protected override void LoadContent() spritebatch = new SpriteBatch(GraphicsDevice); spaceshipmodel = Content.Load<Model>("spaceship"); GraphicsDevice.Clear(Color.CornflowerBlue); degreey++; // 360도이상이면다시 0도로만듦 if (degreey > 360) degreey = 0; // 우주선모델의 root 변환행렬을설정, 월드좌표계적용 // 우주선이너무커서 scale을 0.01f로설정, 100배작아짐 // 행렬은 SRT 순으로곱해야한다. Scale*Rotation*Translation spaceshipmodel.root.transform = Matrix.CreateScale(0.01f) * Matrix. CreateRotationY(MathHelper.ToRadians(degreeY)) * Matrix.CreateTranslation(vSpacePosition); protected override void UnloadContent() Vector3 vspaceposition = Vector3.Zero; protected override void Update(GameTime gametime) // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState. Pressed) this.exit(); // XNA 4.0 정식버전이나오면서, 키보드가제대로지원된다. // 키보드를 enable시키기위해서는에뮬레이터화면에서 [Page Up] 키를누르면된다. //http://blogs.msdn.com/b/velloso/archive/2010/09/24/windows-phone-7- emulator-simulating-the-accelerometer.aspx KeyboardState keyboard = Keyboard.GetState(); if (keyboard.iskeydown(keys.left)) vspaceposition.x--; if (keyboard.iskeydown(keys.right)) vspaceposition.x++; if (keyboard.iskeydown(keys.up)) vspaceposition.y++; if (keyboard.iskeydown(keys.down)) vspaceposition.y--; base.update(gametime); int degreey = 0; protected override void Draw(GameTime gametime) // model의변환행렬을 bonetransform에복사. Matrix[] bonetransforms = new Matrix[spaceshipModel.Bones.Count]; spaceshipmodel.copyabsolutebonetransformsto(bonetransforms); // Draw the model. foreach (ModelMesh mesh in spaceshipmodel.meshes) foreach (BasicEffect effect in mesh.effects) // 변환행렬중현재 bone index에해당하는행렬을 effect.world에설정 effect.world = bonetransforms[mesh.parentbone.index]; // View행렬을만든다.(0,20,100) 에서원점을바라본다. effect.view = Matrix.CreateLookAt(new Vector3(0,20,100), Vector3. Zero, Vector3.Up); // Projection 행렬을만든다. 시야각은 45도, 종횡비는 AspectRatio가 // 알려준다, 근거리는 10, 원거리는 1000으로설정 // 10 미만, 1000 초과인사물은보이지않게된다. effect.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 10, 1000); // 디폴트로빛을설정한다.(3점조명이들어간다 ) effect.enabledefaultlighting(); mesh.draw(); base.draw(gametime); XNA 4.0 정식버전에서는키보드를제대로지원하게되었다. 키보드를사용하기위해서는반드시에뮬레이터에서키를눌러 야한다. 예제를실행해서도만약방향키를눌렀는데이동하지않는다면, 키를눌러보기바란다. NOVEMBER 2010 97

// 행렬은 SRT 순으로곱해야한다. Scale*Rotation*Translation dudemodel.root.transform = Matrix.CreateScale(0.5f); // model 의변환행렬을 bonetransform 에복사. Matrix[] bonetransforms = new Matrix[dudeModel.Bones.Count]; dudemodel.copyabsolutebonetransformsto(bonetransforms); 기본예제실행 : 3D 우주선 (Y축회전및키보드이동지원 ) 필자의샘플이외에도 App Hub 사이트에서 3D 모델과 2D Interface 가혼합된형태의예제를찾을수있다. 특히아래의주소예제에서는 BasicEffect 에서의 light 처리등을배울수있다. (http://create.msdn.com/en-us/education/catalog/sample/graphics_3d) // Draw the model. foreach (ModelMesh mesh in dudemodel.meshes) foreach (BasicEffect effect in mesh.effects) effect.setbonetransform(bonetransforms); // View행렬을만든다. (0,20,100) 에서원점을바라본다. effect.view = Matrix.CreateLookAt(new Vector3(0,20,100), Vector3. Zero, Vector3.Up); // Projection 행렬을만든다. 시야각은 45도, 종횡비는 AspectRatio 가알려준다, // 근거리는 10, 원거리는 1000으로설정 // 10 미만, 1000 초과인사물은보이지않게된다. effect.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 10, 1000); // 디폴트로빛을설정한다.(3점조명이들어간다 ) effect.enabledefaultlighting(); 3D Graphcis 예제, 2D 와 3D 를혼합하는방법에대해배울수있다. 스키닝애니메이션처리하기자, 이번호의대미는스키닝애니메이션으로마무리해보자. 이미설명한대로스키닝애니메이션은 SkinnedEffect 를사용한다. 부록으로제공되는 dude.fbx 파일을 Content Project 에추가하고 Content Processor 에서 Default Effect 를 SkinnedEffect 로설정한다. Default Effect 를 SkinnedEffect 로변경 mesh.draw(); base.draw(gametime); 기존코드와큰차이가없다. Effect.SetBoneTransform(boneTransforms) 을하는이유는기존에는 sub mesh 에대해서직접부모의월드행렬을꺼내서대입을해줬는데, 스키닝애니메이션에서는하나의정점이여러개의변환행렬에영향을받을수있기때문에이와관련된계산은내부에서처리하도록전체변환행렬리스트를넘기는것이다. SkinnedEffect 내부에서 Blending Weight 값들을이용한계산을할것이다. 자실행해보자. 어떻게나오는가? 그리고위에서설명했던대로비슷하게 Draw 코드를아래와같이작성한다. protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.CornflowerBlue); // 너무커서 scale 을 0.01f 로설정, 100 배작아짐 스키닝이제대로적용되지않아 3D 모델이깨지는현상 98 NOVEMBER 2010

허걱, 완전깨져서나온다. 이문제가생긴이유는무엇일까? 바로스키닝데이터를기반으로한변환행렬정보가만들어지지않았기때문이다. SkinnedEffect 는화면에그리는역할만하지, 애니메이션행렬의계산을하지않는다. 따라서 dude 의걷는동작을애니메이션하기위해뭔가가필요하다. 이를위해 App Hub에있는스키닝예제는 AnimationPlayer 와 SkinnedModelPipeline 을제공한다. (http://create.msdn.com/en-us/education/catalog/sample/skinned_model) 이두개의파일을예제프로젝트폴더에복사하자. 2개의 dll 파일을필자가만든예제폴더에복사한다. 그리고 SkinnedModelPipeline.dll 은 Content Project 에참조로추가하고, SkinnedModel.dll 은코드관련프로젝트에참조로추가한다. 스키닝을위해 App Hub 에서는예제를제공한다. 위예제에나온방법은 XNA 4.0 에기본탑재된내용이아니기때문에, 여러개의프로젝트로구성되어있으며, 코드가공개되어있어커스터마이징이가능하다. 필자가평소에사용하는방법으로예제프로젝트에서스키닝애니메이션을구현하는과정을설명하겠다. 먼저, App Hub에서제공하는 Skinning Sample 을받아서압축을풀고프로젝트를열어서전체빌드한다. 프로젝트 - 참조 - 찾아보기를통해 dll 을추가할수있다. 모든과정이완료되면아래와같은프로젝트구성을확인할수있다. App Hub 에서제공되는예제프로젝트구성 예제는총 5개의프로젝트로구성되어있지만우리에게필요한것은 SkinnedModelPhone, SkinnedModelPipeline 프로젝트이다. 전체빌드가성공적으로끝났다면 SkinnedModelPipeline 프로젝트빌드결과로 SkinnedModelPipeline.dll 파일이생성되고, SkinnedModelPhone 프로젝트빌드결과로 SkinnedModel.dll 파일이생성되게된다. 생성위치는아래와같다. (1) Skinning_4_0\SkinnedModel\bin\Windows Phone\Debug\ SkinnedModel.dll (2) Skinning_4_0\SkinnedModelPipeline\bin\x86\Debug\ SkinnedModelPipeline.dll 스키닝을위한프로젝트참조설정완료 이제 dude.fbx 의속성중 Content Processor 를 SkinnedModelPipeline 으로변경한다. NOVEMBER 2010 99

// 모델에서스키닝데이터를얻는다. SkinningData skinningdata = dudemodel.tag as SkinningData; 3D 모델파일의 Content Processor 를 SkinnedModelProcessor 로변경이제준비작업은다끝났다. AnimationPlayer 가적용된풀소스를보도록하자. using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Media; using SkinnedModel; // AnimationPlayer을위해 namespace 추가 namespace example3_1 public class Game1 : Microsoft.Xna.Framework.Game GraphicsDeviceManager graphics; SpriteBatch spritebatch; Model dudemodel; AnimationPlayer animationplayer; public Game1() graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; // Frame rate is 30 fps by default for Windows Phone. TargetElapsedTime = TimeSpan.FromTicks(333333); protected override void Initialize() base.initialize(); protected override void LoadContent() spritebatch = new SpriteBatch(GraphicsDevice); // 스키닝데이터에있는애니메이션 Set 중 Take 001 애니메이션을얻는다. // Take 001은 FBX 파일을 Export를하면생성되는기본애니메이션이름이다. // 여기서는 walk 애니메이션을나타낸다. AnimationClip clip = skinningdata.animationclips["take 001"]; // 스키닝데이터를바탕으로 AnimationPlayer를생성한다. animationplayer = new AnimationPlayer(skinningData); // walk 애니메이션시작 animationplayer.startclip(clip); protected override void UnloadContent() float rotatioy = 0.0f; protected override void Update(GameTime gametime) // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState. Pressed) this.exit(); // 주어진시간에맞게애니메이션을갱신시킨다. // 너무커서 scale을 0.5f로설정, 2배로작아짐 // 행렬은 SRT 순으로곱해야한다. Scale*Rotation*Translation // AnimationPlayer에 world 행렬을적용하는것은아래와같다. KeyboardState keyboard = Keyboard.GetState(); if (keyboard.iskeydown(keys.left)) rotatioy -= 0.1f; if (keyboard.iskeydown(keys.right)) rotatioy += 0.1f; Matrix worldmat = Matrix. CreateScale( 0. 5f ) * Matrix. CreateRotationY(rotatioY); animationplayer.update(gametime.elapsedgametime, true, worldmat); base.update(gametime); protected override void Draw(GameTime gametime) GraphicsDevice.Clear(Color.CornflowerBlue); // 스키닝이적용된변환행렬리스트를얻어낸다. Matrix[] bones = animationplayer.getskintransforms(); dudemodel = Content.Load<Model>("dude"); // Render the skinned mesh. 100 NOVEMBER 2010

foreach (ModelMesh mesh in dudemodel.meshes) foreach (SkinnedEffect effect in mesh.effects) effect.setbonetransforms(bones); // View행렬을만든다. (0,0,-100) 에서 (0,30,0) 을바라본다. effect.view = Matrix.CreateLookAt(new Vector3(0, 40, -60), new Vector3(0,20,0), Vector3.Up); effect.enabledefaultlighting(); // Specular 색깔을설정하고, 반사도를결정한다.( 없어도무방 ) effect.specularcolor = new Vector3(0.5f); effect.specularpower = 16; mesh.draw(); // Projection 행렬을만든다. 시야각은 45도, 종횡비는 AspectRatio가알려준다. 근거리는 10, 원거리는 1000으로설정 // 10 미만, 1000 초과인사물은보이지않게된다. effect.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 10, 1000); base.draw(gametime); 실행하면아래와같이 dude 가걷는모습을볼수있을것이다. 추가로왼쪽오른쪽화살표를누르면 dude 가 Y축으로회전하는것을확인할수있다. BasicEffect 와 SkinnedEffect 를비롯한 WP7에서추가된 5개의 Effect 와관련된설명및적용방법은필자의블로그 (http://gomdong. pe.kr) 에서확인할수있다. Dude 의스키닝애니메이션적용된모습 (Y 축회전적용 ) 맺음말이번호에서는 Windows Phone 7에서 3D Model 을화면에출력하고스키닝애니메이션을적용하였다. 이로서 WP7 소개에서부터 3D 게임까지의 3개월연재를마치게되었다. 이번연재통해독자여러분께서 WP7 게임개발을시작하는데도움이되었으면한다. 항상질문에목말라있는필자다. 주저없이문의주시길 ~! ( 지금까지수고해주신김동훈님께다시한번감사의말씀을전합니다.) 김동훈 삼성전자 DMC 연구소연구원, Microsoft XNA/DirectX MVP 블로그 http://gomdong.pe.kr fly33499@gmail.com NOVEMBER 2010 101