게임엔진 제 11 강애니메이션 이대현교수 한국산업기술대학교게임공학과
학습목차 메쉬뷰어 (Mesh Viewer) 의설치및실행. 애니메이션기초이론 오우거엔진의애니메이션기법 정지상태의닌자애니메이션. 걷기상태의닌자애니메이션. 로봇의이동속도의조절. 지형위를돌아다니는닌자의애니메이션
메쉬뷰어 (Mesh Viewer) 설치 강의실자료실로부터 CeguiMeshViewer_Setup.exe 를다운로드하여설치.
ninja.mesh 의선택
애니메이션실행
Ninja 의애니메이션종류 Attack1, Attack2, Attack3 Backflip Block Climb Crouch Death1, Death2 HighJump, Jump, JumpNoHeight Idle1, Idle2, Idle3 Kick, SideKick Spin Stealth Walk
애니메이션원리 애니메이션은일련의정지이미지 (still image) 를연속적으로보여주어, 보는사람으로하여금이미지들을연속된동작으로착각하도록함. 잔상효과 (persistence of vision) 이미지가이미사라졌음에도불구하고사람의눈이나뇌에계속남아있으려는경향. 일반적으로초당 15 장이상의그림이보여지면자연스러운움직임을얻을수있음. 텔레비젼, 영사기, 비디오플레이어는각각이표시하는초당프레임율이다르지만모두잔상효과를이용함. Animation frames Sequential viewing
애니메이션의방법 키프레임애니메이션 (Key-frame animation) 수동으로애니메이션을구성 모션캡쳐 (Motion capture) 애니메이션을측정하여기록함. 절차적애니메이션 (Procedural Animation) 자동으로애니메이션을생성. 일종의시뮬레이션
키프레임 (Key Frame) 과보간 (Interpolation) 움직임의특징이되는키프레임을지정 ( 사용자가수동으로 ) 보간알고리즘을이용하여키프레임사이의중간프레임들을생성해냄. Key Frame #1 Key Frame #2 Interpolation
키프레임애니메이션의특징 숙련된애니메이터가필요함. 수작업으로키프레임을만들어야하기때문에, 시간과비용이많이필요. 고품질 / 고비용
모션캡쳐 사람의몸에센서또는마커를부착하여, 오브젝트의움직임을동작데이터로서그대로측정하고기록하는방식. 광학식및기계식 기록된데이터를가공하는데긴시간이걸림. 적절한품질 / 적절한비용.
절차적애니메이션 (Procedural Animation) 수학적인시뮬레이션을이용하여물체의움직임을자동으로생성하는방식. 입립자시스템 (Particle system) 이나유동표면 (Flexible surface) 과같은자연현상이나사람이직접제어하기에는복잡한시스템의애니메이션구현에유리함. 유체, 안개, 연기, 구름, 옷표면 실시간구현을위해서는고성능의하드웨어필요.
애니메이션방법의선택 Passive Objects Active Characters Simulation Keyframing Motion Capture
캐릭터애니메이션 정점애니메이션 (Vertex Animation) 계층적애니메이션 (Hierarchical Animation) 골격애니메이션 (Skeletal Animation) 스키닝 (Skinning) 역기구학 (Inverse Kinematics)
정점애니메이션 앞키프레임의메쉬의정점과, 뒷키프레임의메쉬의정점으로부터중간프레임에해당되는정점을보간함으로써중간프레임메쉬를생성함. 정점모핑 (Vertext Morphing) V world = ( 1 a) V + a V 0 a 1 1 2
골격애니메이션 (Skeletal Animation) 인간의몸속에뼈가있듯이, 3 차원적으로구성된뼈대를만들고, 이뼈대에메시를자식으로붙이는방식. M M M bone_ transformt = bone_ local bone_ animation M bone_ parent V world = V local M mesh_ local M bone_ transform
운동학 (Kinematics) Forward Kinematics( 순운동학 ) 다관절체의관절각도가결정되면각부분의위치와방향을구하는기술 다관절체의표현의기초가됨 Inverse Kinematics( 역운동학 ) 각부분의위치와각도로부터다관절체의관절각도을계산하는기술 움직임을지정할때관절각도보다위치와방향을사용하는것이애니메이터가움직임을생성하기쉽다.
오우거엔진의애니메이션기법 Skeletal Animation Mesh animation using a skeletal structure to determine how the mesh deforms. Vertex Animation Mesh animation using snapshots of vertex data to determine how the shape of the mesh changes. SceneNode Animation Animating SceneNodes automatically to create effects like camera sweeps, objects following predefined paths, etc.
오우거엔진의골격애니메이션 여러개의본 (Bone) 을이용하여골격을만듬. 본에는메쉬를구성하는정점들이연결됨..skeleton 파일에골격정보및애니메이션정보가담김. 본을움직이면이에따라본에연결된정점들의전역좌표가변경됨 애니메이션!! 특징 하나의골격은무한개의본 (Bone) 을가질수있음. 본에대해서계층적순운동학알고리즘이적용. 하나의골격은여러개의애니메이션이름들을가짐.( 예, 'Walk', 'Run', 'Jump', 'Shoot ) 하나의애니메이션을구성하기위한키프레임수는제한이없음. 선형보간및스플라인보간지원. 부드러운스키닝지원. 애니메이션블렌딩 ( 애니메이션과애니메이션사이의부드러운연결 ) 하드웨어스키닝 셰이더를이용한애니메이션가능.
부드러운스키닝 본마다분할된메쉬를갖는경우, 관절부분이끊기는현상이발생할수있음. 정점은여러개의본에동시에할당됨 본의영향을가중치로도입하여, 정점을복합적으로계산함으로써부드러운관절연결을표현함.
오우거엔진의정점애니메이션 메쉬를애니메이션하기위해정점을직접적으로이동함..mesh 파일에애니메이션정보가담김. Morph Animation 키프레임은정점절대위치의스냅샷을저장. 중간프레임을보간함. 구조가급격하게변하여 skeletal animation 이부적합한경우에효과적임. 애니메이션블렌딩은불가능함. Pose Animation 기본정점데이터에대한 offset( 변위, 차이 ) 값을이용하여메쉬를구성함. 하나의키프레임은여러개의 Pose 를갖게됨. 애니메이션블렌딩지원. Facial( 얼굴 ) 애니메이션에적합함.
실습 IdleNinja IDLE 상태의닌자애니메이션
PlayState.cpp bool PlayState::enter(void) { 중략 실습 manimationstate = ninjaentity->getanimationstate("idle1"); manimationstate->setloop(true); manimationstate->setenabled(true); }
실행결과 : 애니메이션이실행되지않는다?
PlayState.cpp bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 실습 manimationstate->addtime(evt.timesincelastframe); 후략 }
애니메이션설정 애니메이션을 IDLE1 상태로설정한다. manimationstate = ninjaentity->getanimationstate("idle1"); manimationstate->setloop(true); manimationstate->setenabled(true); IDLE1 상태의애니메이션의계속반복. false 면한번만애니메이션을수행. 실제로 IDLE1 상태의애니메이션동작이일어나도록설정한다.
애니메이션시간업데이트 애니메이션루프는시간이진행됨에따라, 동작한다. 현재시간을갱신하지않으면, 시간진행이없는것으로간주하여, 애니메이션이일어나지않는다. 따라서, 매프레임마다, 경과된시간을알려주어야한다. addtime() 함수를이용하여, 이전애니매이션시간대비하여, 현재까지경과된시간을알려줌으로써, 다음애니메이션동작을표시. bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 manimationstate->addtime(evt.timesincelastframe); 후략 } 직전에수행되었던, framestarted() 함수의실행완료시점이후, 현재 framestarted() 함수호출이될때까지의경과시간.
실습 WalkNinja 닌자 Walking 애니메이션
PlayState.cpp bool PlayState::enter(void) { 중략 실습 manimationstate = ninjaentity->getanimationstate( Walk"); manimationstate->setloop(true); manimationstate->setenabled(true); } bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 ninjanode->translate(vector3(0, 0, -5.0f)); manimationstate->addtime(evt.timesincelastframe); 후략 }
실행결과 : 닌자의카메라를향한전진
닌자의걷기이동 로봇노드를매프레임마다 -z 축으로 0.5 거리만큼이동. bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 ninjanode->translate(vector3(0, 0, -5.0f)); manimationstate->addtime(evt.timesincelastframe); 후략 }
걷기애니메이션의가장큰문제점 닌자의이동속도가일정하지않다. 매프레임마다로봇을일정량만큼이동시킨다. framestarted() 함수의호출속도는 2 가지요소에따라달라짐. PC 의성능 : PC 의성능이높을수록, framestarted() 함수는훨씬더빠른속도로반복호출된다. 닌자가단위시간당빨리움직이게된다. 프로그램의로드 : 프로그램내에서여러가지처리를하거나, 대규모의지형렌더링, 수백개의캐릭터애니메이션등이있게되면, framestarted() 함수의호출이더뎌진다. 닌자가단위시간당천천히움직이게된다.
해결방법? 닌자노드의이동량에직전프레임과현재프레임시간차이를곱한다. bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 ninjanode->translate(vector3(0, 0, -50 * evt.timesincelastframe)); manimationstate->addtime(evt.timesincelastframe); 후략 }
실습 WalkAroundNinja 지형위를돌아다니는닌자
PlayState.cpp (1) bool PlayState::enter(void) { 중략 실습 mwalkspeed = 80.0f; mdirection = Vector3::ZERO; mwalklist.push_back( Vector3( 250.0f, 50.0f, 400.0f ) ); mwalklist.push_back( Vector3( 800.0f, 50.0f, 50.0f ) ); mwalklist.push_back( Vector3( 1000.0f, 50.0f, 400.0f ) ); }
PlayState.cpp (2) bool PlayState::frameStarted(GameManager* game, const FrameEvent& evt) { 중략 if (mdirection == Vector3::ZERO) { if (nextlocation()) { manimationstate = ninjaentity->getanimationstate("walk"); manimationstate->setloop(true); manimationstate->setenabled(true); } } else { Real move = mwalkspeed * evt.timesincelastframe; mdistance -= move; if (mdistance <= 0.0f) { ninjanode->setposition( mdestination ); mdirection = Vector3::ZERO; if (! nextlocation( ) ) { manimationstate = ninjaentity->getanimationstate( "Idle1" ); manimationstate->setloop( true ); manimationstate->setenabled( true ); } } else ninjanode->translate( mdirection * move ); } 후략 } 실습
PlayState.cpp (3) bool PlayState::nextLocation(void) { if (mwalklist.empty()) return false; mdestination = mwalklist.front(); mwalklist.pop_front(); mdirection = mdestination - ninjanode->getposition( ); mdistance = mdirection.normalise( ); return true; } 실습
실행결과 : 닌자가공간상의네점사이를이동한다.
걷기목표포인트리스트의생성 bool PlayState::enter(void) { 중략 닌자의이동방향을나타내는벡터. 이값이 ZERO 면, 정지상태임을나타낸다. mwalkspeed = 80.0f; mdirection = Vector3::ZERO; mwalklist.push_back( Vector3( 250.0f, 50.0f, 400.0f ) ); mwalklist.push_back( Vector3( 800.0f, 50.0f, 50.0f ) ); mwalklist.push_back( Vector3( 1000.0f, 50.0f, 400.0f ) ); } std::deque<vector3> mwalklist; 로선언됨.
걷기목표지점의획득 bool PlayState::nextLocation(void) { if (mwalklist.empty()) // 더이상목표지점이없으면 false 리턴 return false; mdestination = mwalklist.front(); // 큐의가장앞에서꺼내기 mwalklist.pop_front(); // 가장앞포인트를제거 mdirection = mdestination - ninjanode->getposition( ); // 방향계산 mdistance = mdirection.normalise( ); // 거리계산 return true; }
닌자의이동구현 닌자가정지상태이면 if (mdirection == Vector3::ZERO) { 다음이동목표지점을가져온다. if (nextlocation()) { manimationstate = ninjaentity->getanimationstate("walk"); manimationstate->setloop(true); manimationstate->setenabled(true); } 이동목표지점이있으면, 애니메이션상태를걷기 ( Walk ) 상태로설정한다.
닌자가이동중이면. } else { Real move = mwalkspeed * evt.timesincelastframe; mdistance -= move; if (mdistance <= 0.0f) { ninjanode->setposition( mdestination ); mdirection = Vector3::ZERO; 다음이동목표지점이없으면, 애니메이션상태를 Idle1 상태로설정한다. if (! nextlocation( ) ) { manimationstate = ninjaentity->getanimationstate( "Idle1" ); manimationstate->setloop( true ); manimationstate->setenabled( true ); } } else ninjanode->translate( mdirection * move ); } 닌자노드를 mdirection 방향으로, move 만큼이동시킨다.
실습과제 #7 및과제 #3 두명의닌자애니메이션 지형위에두명의닌자를서로마주보게배치 대전모드 1, 2 키이를이용하여조종할닌자를선택 커서키이를이용하여, 닌자를이동. 닌자의액션을키이를통해서지시. Attack1(t), Attack2(y), Attack3(u), Backflip(f), Block(b) HighJump(h), Jump(j), JumpNoHeight(n) Kick(k), SideKick(l), Spin(m) 제출방법 e-mail: kpu.homework@gmail.com 메일제목 : 2009 게임엔진과제 (3) 학번이름 솔루션파일을압축하여첨부파일로해서제출. 실행파일및오브젝트파일은제거해야함. (clean) 제출기한 : 다음주수요일, 기한넘기면받지않음. copy 제출시 0점 (3회시 F)