핚국산업기술대학교 제 7 강카메라와뷰포트 이대현교수
학습안내 학습목표 오우거엔짂의입력처리방식을종합적으로이해한다. 오우거엔짂의카메라의활용방법및뷰포트의활용방법을이해하고다양한방식으로게임화면을구성해본다. 학습내용 오우거엔짂의입력처리방식. 키입력밎마우스입력리스너인터페이스. 카메라의이동및회전. 시야절두체컬링의이해. 뷰포트를이용한 PIP의구현.
오우거엔진의입력처리방식 무버퍼입력 (unbuffered input) 방식 일종의폴링 (polling). 프레임리스너에서매번입력장치의상태를캡쳐한후, 그결과에따른처리. 버퍼입력 (buffered input) 방식 일종의인터럽트방식. 이벤트의발생및이에따른처리. 키리스너, 마우스리스너등의인터페이스를사용하여처리. 키가눌리면 KeyListener::keyPressed 이벤트발생. 키가떼어지면 KeyListener::keyReleased 이벤트발생. 마우스가움직이면 MouseListener::mouseMoved 이벤트발생.
KeyListener 인터페이스 키보드의입력을처리하는인터페이스클래스 키가눌렸다떼어질때마다, 두개의이벤트 : keypressed, keyreleased 가발생. 눌린키의정보는 KeyEvent 구조체에담겨있음. class _OISExport KeyListener public: virtual ~KeyListener() virtual bool keypressed( const KeyEvent &eve ) = 0; virtual bool keyreleased( const KeyEvent &evt ) = 0; ; 처리가끝나면반드시 true 를 return 해주어야함. false 를리턴하게되면, 입력버퍼에남아있는내용을제거함.
MouseListener 인터페이스 마우스의클릭입력을처리하는인터페이스클래스 class _OISExport MouseListener public: virtual ~MouseListener() virtual bool mousemoved( const MouseEvent &evt ) = 0; 마우스버튼 ID 는 MB_Left, MB_Right, MB_Middle ; virtual bool mousepressed( const MouseEvent &evt, MouseButtonID id ) = 0; virtual bool mousereleased( const MouseEvent &evt, MouseButtonID id ) = 0; evt.state.x.rel 에는마우스 x 위치의상대좌표 ( 원래위치와의차이 ) 값. evt.state.x.abs 에는마우스 x 위치절대좌표값 ( 렌더링윈도우기준 ). evt.state.y.rel, evt.state.y.abs evt.state.z.rel, evt.state.z.abs 마우스휠정보
키리스너및마우스리스너설정 class InputController : public FrameListener, public OIS::KeyListener, public OIS::MouseListener public: InputController(Root* root, OIS::Keyboard *keyboard, OIS::Mouse *mouse) : mroot(root), mkeyboard(keyboard), mmouse(mouse) 중략 keyboard->seteventcallback(this); mouse->seteventcallback(this); 마우스및키입력콜백함수등록 중략 bool mousemoved( const OIS::MouseEvent &evt ); bool mousepressed( const OIS::MouseEvent &evt, OIS::MouseButtonID id ); bool mousereleased( const OIS::MouseEvent &evt, OIS::MouseButtonID id ); bool keypressed( const OIS::KeyEvent &evt ); bool keyreleased( const OIS::KeyEvent &evt ); 후략 ; KeyLister, MouseListener 인터페이스사용
오우거엔진의카메라 Camera 클래스 씬을담아내어, 뷰포트에연결시켜주는클래스주요멤버함수 setposition(), lookat(), yaw(), roll(), pitch() 어떤장면을여러각도에서보고싶으면? 카메라홀더 라고불리는씬노드들을여러개만들고, 필요에따라씬노드에카메라를담으면된다.
실습 CameraControl WASD 키와마우스를이용한카메라조작
카메라조작씨나리오 키보드입력 W 키이 : 카메라의상향이동 S 키이 : 카메라의하향이동 A 키이 : 카메라의왼쪽이동 D 키이 : 카메라의오른쪽이동 마우스입력 마우스좌우이동 : 카메라의좌우회전 (Yaw) 패닝 (Panning) 마우스상하이동 : 카메라의상하회전 (Pitch) 피칭 (Pitching) 마우스휠이동 : 카메라의전짂후짂 주밍 (Zooming)
class InputController class InputController : public FrameListener, public OIS::KeyListener, public OIS::MouseListener public: InputController(Root* root, OIS::Keyboard *keyboard, OIS::Mouse *mouse) : mroot(root), mkeyboard(keyboard), mmouse(mouse) mcamera = mroot->getscenemanager("main")->getcamera("main"); mcameramovevector = Ogre::Vector3::ZERO; mcontinue = true; 실습 keyboard->seteventcallback(this); mouse->seteventcallback(this); bool framestarted(const FrameEvent &evt) mkeyboard->capture(); mmouse->capture(); mcamera->moverelative(mcameramovevector); return mcontinue;
class InputController bool keypressed( const OIS::KeyEvent &evt ) switch(evt.key) case OIS::KC_W: mcameramovevector.y += 1; break; case OIS::KC_S: mcameramovevector.y -= 1; break; case OIS::KC_A: mcameramovevector.x -= 1; break; case OIS::KC_D: mcameramovevector.x += 1; break; case OIS::KC_ESCAPE: mcontinue = false; break; 실습 return true; bool mousemoved( const OIS::MouseEvent &evt ) if (evt.state.buttondown(ois::mb_right)) mcamera->yaw(degree(-evt.state.x.rel)); mcamera->pitch(degree(-evt.state.y.rel)); mcamera->moverelative(ogre::vector3(0, 0, -evt.state.z.rel * 0.1f)); return true;
class LectureApp 실습 void go(void)... 중략... mkeyboard = static_cast<ois::keyboard*>(minputmanager->createinputobject(ois::oiskeyboard, true)); mmouse = static_cast<ois::mouse*>( minputmanager->createinputobject(ois::oismouse, true)); InputController* inputcontroller = new InputController(mRoot, mkeyboard, mmouse); mroot->addframelistener(inputcontroller);... 중략...
실행결과 WASD 키를이용핚카메라의상하좌우이동 마우스 ( 오른쪽버튼누른상태 ) 를이용핚패닝및피칭 마우스휠을이용핚카메라 Zoom-in / Zoom-out
버퍼입력 (Buffered Input) 설정 void go(void)... 중략... mkeyboard = static_cast<ois::keyboard*>(minputmanager->createinputobject(ois::oiskeyboard, true)); mmouse = static_cast<ois::mouse*>( minputmanager->createinputobject(ois::oismouse, true)); InputController* inputcontroller = new InputController(mRoot, mkeyboard, mmouse); mroot->addframelistener(inputcontroller);... 중략... 버퍼입력설정
콜백함수지정 InputController(Root* root, OIS::Keyboard *keyboard, OIS::Mouse *mouse) : mroot(root), mkeyboard(keyboard), mmouse(mouse) mcamera = mroot->getscenemanager("main")->getcamera("main"); mcameramovevector = Ogre::Vector3::ZERO; mcontinue = true; keyboard->seteventcallback(this); mouse->seteventcallback(this);
bool framestarted(const FrameEvent &evt) mkeyboard->capture(); mmouse->capture(); mcamera->moverelative(mcameramovevector); return mcontinue;
WASD 키를이용핚카메라이동벡터설정 bool keypressed( const OIS::KeyEvent &evt ) switch(evt.key) case OIS::KC_W: mcameramovevector.y += 1; break; case OIS::KC_S: mcameramovevector.y -= 1; break; case OIS::KC_A: mcameramovevector.x -= 1; break; case OIS::KC_D: mcameramovevector.x += 1; break; case OIS::KC_ESCAPE: mcontinue = false; break; return true; WSAD 키에따라, y 축또는 x 축으로이동값설정. bool keyreleased( const OIS::KeyEvent &evt ) switch(evt.key) case OIS::KC_W: mcameramovevector.y -= 1; break; case OIS::KC_S: mcameramovevector.y += 1; break; case OIS::KC_A: mcameramovevector.x += 1; break; case OIS::KC_D: mcameramovevector.x -= 1; break; case OIS::KC_ESCAPE: mcontinue = false; break; return true;
마우스입력에따른카메라조작 bool mousemoved( const OIS::MouseEvent &evt ) 오른쪽마우스가눌렸을때, 마우스 x, y 좌표의상대적이동량을이용하여, 카메라의회전을처리함. if (evt.state.buttondown(ois::mb_right)) mcamera->yaw(degree(-evt.state.x.rel)); mcamera->pitch(degree(-evt.state.y.rel)); mcamera->moverelative(ogre::vector3(0, 0, -evt.state.z.rel * 0.1f)); return true; 휠상태에따른카메라의 Zooming
마우스이동에따른카메라의회전 : yaw XZ 평면에서 Y 축을중심으로하는회전. 카메라의 + 회전방향과마우스의 x 의 + 방향이반대 화면 +x +y +x 캐릭터 + 회전 - 회전 카메라 +z
마우스이동에따른카메라의회전 : pitch YZ 평면에서 X 축을중심으로하는회전. 카메라의 + 회전방향과마우스의 y 의 + 방향이반대 + 회전 +y +z 카메라 - 회전 캐릭터 +x 화면 +y
Zoom-in 핛때, 실제로요구되는카메라의동작 +y 닌자 +x +z
move() 함수의경우, 카메라의이동 +y 닌자 +x 월드좌표계를기준으로카메라가이동한다!!! +z
moverelative() 함수의동작 +y 닌자 +x +z +x +z 카메라좌표계를기준으로카메라가이동한다!!!
실습 Frustrum 시야절두체설정
시야절두체 (Viewing Frustum) 3 차원의공간상에서카메라에의해보일수있는것들을담는범위 근클리핑거리 (near clipping distance): 카메라와근평면까지의거리원클리핑거리 (far clipping distance): 카메라와원평면까지의거리 근평면 (near plane) 원평면 (far plane)
절두체컬링 (Frustum Culling) 컬링방법 카메라로부터아주멀리있는물체는? 눈에안보인다 표시할필요가없다. 렌더링하지않는다. 계산량이줄어든다. 카메라로부터아주가까이있는물체는? 그물체를투과한다. 표시할필요가없다. 렌더링하지않는다. 계산량이줄어든다. 제거 표시 클리핑 제거
class LectureApp 실습 void go(void)... 중략... mcamera->setposition(0.0f, 100.0f, 500.0f); mcamera->lookat(0.0f, 100.0f, 0.0f); mcamera->setnearclipdistance(100); mcamera->setfarclipdistance(500);... 중략...
카메라줌인줌아웃에따른클리핑효과 Near clipping 거리에따른효과 Far clipping 거리에따른효과
실습 PictureInPicture PIP 의구현
뷰포트 카메라로잡은장면을실제로보여주는모니터 ( 렌더윈도우 ) 상의 2 차원평면
뷰포트생성 Viewport* Ogre::RenderTarget::addViewport ( Camera * cam, int ZOrder = 0, float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f) cam: 카메라객체 ZOrder: 뷰포트의계층순서 (0 이맨아래 ) left, top: 뷰포트의왼쪽위의좌표 (0-1 사이의값으로써렌더윈도우상에서비율값으로표시 ). width, height: 뷰포트의너비와높이 (0-1 사이의값으로써렌더윈도우상에서비율값으로표시 ).
class LectureApp void go(void)... 중략... 실습 mcamera = mscenemgr->createcamera("main"); mcamera->setposition(0.0f, 100.0f, 500.0f); mcamera->lookat(0.0f, 100.0f, 0.0f); mviewport = mwindow->addviewport(mcamera, 0); mviewport->setbackgroundcolour(colourvalue(0.0f,0.0f,0.5f)); mcamera->setaspectratio(real(mviewport->getactualwidth()) /Real(mViewport->getActualHeight())); mmapcamera = mscenemgr->createcamera("mapcamera"); mmapcamera->setposition(0.0f, 800.0f, 1.0f); mmapcamera->lookat(0.0f, 0.0f, 0.0f); mmapviewport = mwindow->addviewport(mmapcamera, 1, 0.79, 0.01, 0.2, 0.2); mmapviewport->setbackgroundcolour(colourvalue(0.0f,0.0f,1.0f)); mmapcamera->setaspectratio(real(mmapviewport->getactualwidth()) /Real(mMapViewport->getActualHeight()));... 중략...
실행화면 : PIP 구현 (Picture-In-Picture)
MapCamera 의설정 void go(void) mmapcamera = mscenemgr->createcamera("mapcamera"); mmapcamera->setposition(0.0f, 800.0f, 1.0f); mmapcamera->lookat(0.0f, 0.0f, 0.0f); mmapviewport = mwindow-> addviewport(mmapcamera, 1, 0.79, 0.01, 0.2, 0.2); mmapviewport->setbackgroundcolour(colourvalue(0.0f,0.0f,1.0f)); mmapcamera->setaspectratio(real(mmapviewport->getactualwidth()) /Real(mMapViewport->getActualHeight()));
학습정리 오우거엔진의입력처리방식 무버퍼입력방식 폴링. 버퍼입력방식 인터럽트. 키입력및마우스입력처리리스너 카메라 입력을 capture() 하면 OIS 는콜백함수의 keypressed(), keyreleased(), mousemoved() 등의함수를호출함. 3D 씬을담아서뷰포트에연결함. 주요멤버함수 setposition(), lookat(), yaw(), roll(), pitch() move() 와 moverelative() 기능차이. 절두체컬링 시야내에있는것만렌더링함으로써, 엔짂실행속도최적화. 뷰포트 카메라를통해서담아낸장면을표시하는사각영역. addviewport(), setbackgroundcolour(), setaspectratio()