Post on 30-Dec-2015
description
Game Programming 053D math for Games
2010 년 2 학기디지털콘텐츠전공
Unbuffered Input
Call-back Driven Framework
• Framework:– A partially-constructed application
• Encapsulating knowledge of how to use the low-level libraries
• Providing functions for the game flow • But functions are mostly empty
– Need to be completed by a programmer• Fill-in the missing details• Overide call-back functions
Call-back Driven Framework
• Example from Ogre3D’s game loop
while (true){
for (each frameListener){
frameListener.frameStarted();}
renderCurrentScene();
for (each frameListener){
frameListener.frameEnded();}
}
while (true){
for (each frameListener){
frameListener.frameStarted();}
renderCurrentScene();
for (each frameListener){
frameListener.frameEnded();}
}
Call-back Driven Framework
• Using Ogre’s FrameListenerClass GameFrameListener : public Ogre::FrameListener{public:
virtual void frameStarted(const FrameEvent &event){
// Do things happening before renderingpollJoypad(event);updatePlayerControls(events);updateDynamicSimulation(events);resolveCollisions(events);updateCamera(events);// etc.
}virtual void frameEnded(const FrameEvent &event){
// Do things after renderingdrawHud(events);
}}
Class GameFrameListener : public Ogre::FrameListener{public:
virtual void frameStarted(const FrameEvent &event){
// Do things happening before renderingpollJoypad(event);updatePlayerControls(events);updateDynamicSimulation(events);resolveCollisions(events);updateCamera(events);// etc.
}virtual void frameEnded(const FrameEvent &event){
// Do things after renderingdrawHud(events);
}}
OGRE3D: Frame Listener
• 한 장면이 화면에 렌더링되기 직전 /직후에 해야 할 일을 정의하고 있는 객체
• 추가 작업을 위해서는 frame listener 를 추가 생성하고 , 이를 root 에 등록시켜 사용
• 여러 개의 frame listener 가 존재할 수 있다 .
Frame Listener 의 맴버함수
frameStarted Called just before a frame is rendered.
frameRenderingQueued
Called after all render targets have had their rendering commands issued, but beforethe render windows have been asked to flip their buffers over
frameEnded Called just after a frame has been rendered.
virtual bool frameStarted(const FrameEvent& evt); virtual bool frameRenderingQueued(const FrameEvent& evt); virtual bool frameEnded(const FrameEvent& evt)
virtual bool frameStarted(const FrameEvent& evt); virtual bool frameRenderingQueued(const FrameEvent& evt); virtual bool frameEnded(const FrameEvent& evt)
FrameEvent structure: Real timeSinceLastEvent, Real timeSinceLastFrame 값을 기억하는 구조체
Frame Listener 의 호출• Root 객체의 rendering loop 내에서 호출
bool Root::renderOneFrame(void){ if(!_fireFrameStarted()) return false; if (!_updateAllRenderTargets()) return false; return _fireFrameEnded();}
bool Root::renderOneFrame(void){ if(!_fireFrameStarted()) return false; if (!_updateAllRenderTargets()) return false; return _fireFrameEnded();}
Ogre Engine 의 Rendering Loop• Root::startRendering() 함수에서 이뤄짐• Redering Loop 실행
– 매 프레임 마다 renderOneFrame 실행 :
• Loop 의 중단– FrameStarted, frameRenderingQueued, FrameEnded 에서
하나라도 false 를 return 할 경우
1. Frame Listener 들의 FrameStarted() 함수 호출1. Frame Listener 들의 FrameStarted() 함수 호출
3. Frame Listener 들의 FrameEnded() 함수 호출3. Frame Listener 들의 FrameEnded() 함수 호출
Frame Listener 들의 frameRenderingQueued() 함수 호출Frame Listener 들의 frameRenderingQueued() 함수 호출
2. 한 프레임 렌더링2. 한 프레임 렌더링
Input Handling
• Types of input handling– Unbuffered Input
• Testing states of Mouse/Keyboard every frame• Do action if necessary
– Buffered Input• Event(message)-driven• Event is queued into a buffer• Call message pump routines per frame
Ninja 움직이기• Add two functions in Application class:
class OgreApp : public BaseApplication{public: BasicTutorial4(void); virtual ~BasicTutorial4(void);protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);private: bool processUnbufferedInput(const Ogre::FrameEvent& evt);}
class OgreApp : public BaseApplication{public: BasicTutorial4(void); virtual ~BasicTutorial4(void);protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);private: bool processUnbufferedInput(const Ogre::FrameEvent& evt);}
Ninja 움직이기• Add two functions in Application class:
class OgreApp : public BaseApplication{public: BasicTutorial4(void); virtual ~BasicTutorial4(void);protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);private: bool processUnbufferedInput(const Ogre::FrameEvent& evt);}
class OgreApp : public BaseApplication{public: BasicTutorial4(void); virtual ~BasicTutorial4(void);protected: virtual void createScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);private: bool processUnbufferedInput(const Ogre::FrameEvent& evt);}
CreateScene 수정• Ninja 를 포함하고 light 를 세팅
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.25, 0.25, 0.25));
Ogre::Entity* ninjaEntity = mSceneMgr->createEntity("Ninja", "ninja.mesh");Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()
->createChildSceneNode("NinjaNode");node->attachObject(ninjaEntity);
Ogre::Light* pointLight = mSceneMgr->createLight("pointLight");pointLight->setType(Ogre::Light::LT_POINT);pointLight->setPosition(Ogre::Vector3(250, 150, 250));pointLight->setDiffuseColour(Ogre::ColourValue::White);pointLight->setSpecularColour(Ogre::ColourValue::White);
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.25, 0.25, 0.25));
Ogre::Entity* ninjaEntity = mSceneMgr->createEntity("Ninja", "ninja.mesh");Ogre::SceneNode *node = mSceneMgr->getRootSceneNode()
->createChildSceneNode("NinjaNode");node->attachObject(ninjaEntity);
Ogre::Light* pointLight = mSceneMgr->createLight("pointLight");pointLight->setType(Ogre::Light::LT_POINT);pointLight->setPosition(Ogre::Vector3(250, 150, 250));pointLight->setDiffuseColour(Ogre::ColourValue::White);pointLight->setSpecularColour(Ogre::ColourValue::White);
Frame Listner 수정• frameRenderingQueued 함수 override
bool OgreApp::frameRenderingQueued(const Ogre::FrameEvent& evt){ bool ret = BaseApplication::frameRenderingQueued(evt); if(!processUnbufferedInput(evt)) return false; return ret;}
bool OgreApp::frameRenderingQueued(const Ogre::FrameEvent& evt){ bool ret = BaseApplication::frameRenderingQueued(evt); if(!processUnbufferedInput(evt)) return false; return ret;}
Processing Input
bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt){ static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant
bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt){ static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant
Processing Input
• UnbufferedInput 구현– Mouse 와 keyboard 의 현재 상태를 얻어옴
(BaseApplication::frameRenderingQueued 에서 수행 )
• 다음과 같이 사용할 준비를 한다 . bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt){ static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant
bool OgreApp::processUnbufferedInput(const Ogre::FrameEvent& evt){ static bool mMouseDown = false; // If a mouse button is depressed static Ogre::Real mToggle = 0.0; // The time left until next toggle static Ogre::Real mRotate = 0.13; // The rotate constant static Ogre::Real mMove = 250; // The movement constant
mMouse->capture(); mKeyboard->capture();mMouse->capture(); mKeyboard->capture();
Toggle 기능 구현• 현재 mouse 와 마지막 mouse 상태의 비교를
통해 구현
bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left);
if (currMouse && ! mMouseDown){ Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible());}
mMouseDown = currMouse;
bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left);
if (currMouse && ! mMouseDown){ Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible());}
mMouseDown = currMouse;
Delayed Toggle 구현• 눌린 시간을 기억하여 어느 일정시간이상
눌렸으면 실행
mToggle -= evt.timeSinceLastFrame;
if ((mToggle < 0.0f ) && mKeyboard->isKeyDown(OIS::KC_1)){ mToggle = 0.5; Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible());}
mToggle -= evt.timeSinceLastFrame;
if ((mToggle < 0.0f ) && mKeyboard->isKeyDown(OIS::KC_1)){ mToggle = 0.5; Ogre::Light* light = mSceneMgr->getLight("pointLight"); light->setVisible(! light->isVisible());}
Keyboard 입력 구현• 키보드의 상태를 찾아내어 구현
Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
if (mKeyboard->isKeyDown(OIS::KC_I)) // ForwardtransVector.z -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_K)) // BackwardtransVector.z += mMove;
if (mKeyboard->isKeyDown(OIS::KC_U)) // UptransVector.y += mMove;
if (mKeyboard->isKeyDown(OIS::KC_O)) // DowntransVector.y -= mMove;
mSceneMgr->getSceneNode("NinjaNode")->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
if (mKeyboard->isKeyDown(OIS::KC_I)) // ForwardtransVector.z -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_K)) // BackwardtransVector.z += mMove;
if (mKeyboard->isKeyDown(OIS::KC_U)) // UptransVector.y += mMove;
if (mKeyboard->isKeyDown(OIS::KC_O)) // DowntransVector.y -= mMove;
mSceneMgr->getSceneNode("NinjaNode")->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
Rotate 구현• SHIFT 키와 조합하여 구현
if (mKeyboard->isKeyDown(OIS::KC_J)) // Left - yaw or strafe{ if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw left mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(mRotate * 5)); } else { transVector.x -= mMove; // Strafe left }}if (mKeyboard->isKeyDown(OIS::KC_L)) // Right - yaw or strafe{ if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw right mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(-mRotate * 5)); } else { transVector.x += mMove; // Strafe right }}
if (mKeyboard->isKeyDown(OIS::KC_J)) // Left - yaw or strafe{ if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw left mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(mRotate * 5)); } else { transVector.x -= mMove; // Strafe left }}if (mKeyboard->isKeyDown(OIS::KC_L)) // Right - yaw or strafe{ if(mKeyboard->isKeyDown( OIS::KC_LSHIFT )) { // Yaw right mSceneMgr->getSceneNode("NinjaNode")->yaw(Ogre::Degree(-mRotate * 5)); } else { transVector.x += mMove; // Strafe right }}
Buffered Input
• Unbuffered Input: – Every frame, the state of
OIS::Keyboard/OIS::Mouse is queried
• Buffered Input– Event-driven– Event:
• key-pressed/released• Mouse button pressed/released• Mouse move
Event-Driven Updating
• Event:– Any interesting change in the state of the
game– Examples:
• The player pressing a keyboard• The explosion going off• An enemy character spotting the player
Event-Driven Updating
• Event System– Similar to windows GUI– A subsystem of a game engine
• Register events of interests• Respond to the events when they occur
– Periodic services can be implemented by an event
• Example: Posting a event for every 1/30 sec.• Using the event que for posting a event for the future
Keyboard 입력 구현• 키보드의 상태를 찾아내어 구현
Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
if (mKeyboard->isKeyDown(OIS::KC_I)) // ForwardtransVector.z -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_K)) // BackwardtransVector.z += mMove;
if (mKeyboard->isKeyDown(OIS::KC_U)) // UptransVector.y += mMove;
if (mKeyboard->isKeyDown(OIS::KC_O)) // DowntransVector.y -= mMove;
mSceneMgr->getSceneNode("NinjaNode")->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
Ogre::Vector3 transVector = Ogre::Vector3::ZERO;
if (mKeyboard->isKeyDown(OIS::KC_I)) // ForwardtransVector.z -= mMove;
if (mKeyboard->isKeyDown(OIS::KC_K)) // BackwardtransVector.z += mMove;
if (mKeyboard->isKeyDown(OIS::KC_U)) // UptransVector.y += mMove;
if (mKeyboard->isKeyDown(OIS::KC_O)) // DowntransVector.y -= mMove;
mSceneMgr->getSceneNode("NinjaNode")->translate(transVector * evt.timeSinceLastFrame, Ogre::Node::TS_LOCAL);
3D Math for Games
• A game is:– a mathematical model of a virtual world
simulated in real-time on a computer.
• So, Mathematics provides everything !
• Games programmers must use of:– All branches of mathematics:
Trigonometry, algebra, statistics, calculus, and so on
Points
• Point: a location in n-dimensional space
• Coordinate systems:– Cartesian coordinate
– Cylindrical coordinate
– Spherical coordinate
𝐩= (𝑝1,𝑝2,𝑝3)
Vectors
• Point: absolute• Vector: relative (direction and magnitude)
• Basic Operations:– Multiplication by a scalar
– Addition and Subtraction
– Magnitude (length, norm)
(in a cartesian coordinate system)𝐚= (𝑎1,𝑎2,𝑎3)
Vectors
• Normalization and Unit vector
• Normal Vector
Vectors
• Dot product
– Dot product in action:• Collinear test• Collinear but opposite • Perpendicular test• Same direction (same side)• Opposite direction (opposite side)• Compute height from a plane
Vectors
• Cross product
– Cross product in action:• Find perpendicular direction from the given two
vectors• Compute torque (rotational force)
Vectors in Action!
• Ogre::Vector3 ClassOgreVector3.hOgreVector3.h
Linear Interpolation
• LERP (linear interpolation)– Given two points (vectors), finding inbetweens
P
Qv = Q - P
P + α v= P + α (Q – P)= (1- α) P + α Q
α
Matrices
• Basic Operations:– Addition
– Scalar multiplication
– Transpose
Matrices
• Matrix Multiplication
• Identity Matrix
AB ≠ BA
Matrices
• Vectors as a Matrix– Row vector
– Column vector
aM=b
Mp=q
=
Homogeneous Coordinates
• Any affine transformation between 3D spaces can be represented by a 4x4 matrix
110)( 131333 pTMpT
Transformations
• 2D rotation
• 2D scaling
1100
0cossin
0sincos
1
y
x
y
x
yx, yx ,
11100
00
00
1
ys
xs
y
x
s
s
y
x
y
x
y
x
Transformations
• 2D shear
• 2D reflection
11100
010
01
1
y
dyx
y
xd
y
x
11100
010
001
1
y
x
y
x
y
x
Affine Transformations
• 2D translation
11100
10
01
1y
x
y
x
ty
tx
y
x
t
t
y
x
Examples of Affine Transformations• 2D transformation for vectors
– Translation is simply ignored
11100
10
01
1
y
x
y
x
t
t
y
x
y
x
Affine Transformations
• 3D rotation
11000
0cossin0
0sincos0
0001
1
z
y
x
z
y
x
11000
0100
00cossin
00sincos
1
z
y
x
z
y
x
11000
0cos0sin
0010
0sin0cos
1
z
y
x
z
y
x
Pivot-Point Rotation• Rotation with respect to a pivot point (x,y)
100
sin)cos1(cossin
sin)cos1(sincos
100
10
01
100
0cossin
0sincos
100
10
01
),()(),(
xy
yx
y
x
y
x
yxTRyxT
Fixed-Point Scaling• Scaling with respect to a fixed point (x,y)
100
)1(0
)1(0
100
10
01
100
00
00
100
10
01
),(),(),(
yss
xss
y
x
s
s
y
x
yxTssSyxT
yy
xx
y
x
yx
Scaling Direction
• Scaling along an arbitrary axis
)(),()(1 RssSR yx
)(1 R),( yx ssS)(R
Matrices in Action
• Ogre::Matrix3, Ogre::Matrix4
Euler angles
• Arbitrary rotation can be represented by three rotation along x,y,z axis
1000
0
0
0CS-SSCCC
)()()(),,(
CCSCS
SCCSSCCSSSCS
SSCSC
RRRR xyzXYZ
Gimble
• Hardware implementation of Euler angles• Aircraft, Camera
Euler Angles
• Rotation about three orthogonal axes– 12 combinations
• XYZ, XYX, XZY, XZX• YZX, YZY, YXZ, YXY• ZXY, ZXZ, ZYX, ZYZ
• Gimble lock– Coincidence of inner most
and outmost gimbles’ rotation axes
– Loss of degree of freedom
Euler Angles
• Euler angles are ambiguous– Two different Euler angles can represent the
same orientation
– This ambiguity brings unexpected results of animation where frames are generated by interpolation.
),2
,0 and )0,2
, 21 (R(θ),r,r(rR zyx
Rotation and orientation
• Euler theorem– Every 3D frame can be written as a spinning by
θ about a fixed axis n, the eigenvector of the rotation matrix.
Problems with Euler angles
• Gimbal lock– Losing a degree of freedom
y
z
x
y
z
x
1 1
2
1
y
z
x
1
2
1
3
Problems with Euler angles
• How to Interpolate orientations with Euler angles?
y
z
x
y
z
x
Problems with Euler angles
• What we want is– A parameterization of orientation enabling us
to• Resolve the gimbal lock problem.• Get a simple steady rotation between any two
orientation. (Euler theorem)• Define rotational moves that are independent of the
choice of the coordinate system.
• Such a parameterization exists?– Yes, Unit quaternions.
Quaternion
• A complex number of four numbers
• Unit quaternion– A quaternion of unit length
– A point on the unit hyper-sphere S3
),,,( zyxwq
12222 zyxw
Representation
• Grouping the four components into a scalar and a 3D vector
),(),,,( vq wzyxw
Quaternion and Rotation
• Representing an rotation by a unit quaternion
)2
sinˆ,2
(cos
nq
Antipodal Points in S3
• and are the same orientationq q
qnnq
))2
2sin(ˆ),
2
2(cos( ),
2sinˆ,
2(cos
Algebra of quaternions
• Addition
• Multiplication– Non-commutative under multiplication
)](),[(
),(),(
2112212121
111121
vvvvvv
vvqq
ssww
ww
),(),(),( 1221111121 vvvvqq wwww
Algebra of quaternions
• Inverse operation
0 ),,(1
),( 22
11
vvvvv
vq www
w
Algebra of quaternions
• Rotation with a unit quaternion q
• Successive rotation with quaternions
,)( 1qpqpRq
).,,,0( where zyxp
)()()()())((1212
12112
12
1112 pRqqpqqqpqqqpRR qqqq
Into and Out of Quaternion Space• unit quaternion to rotation matrix
,
1000
02212222
02222122
02222221
22
22
22
yxwxyzwyxz
wxyzzxwzxy
wyxzwzxyzy
qR
).,(),,,( where vq wzyxw
Into and Out of Quaternion Space• Rotation matrix to unit quaternion
,
1000
0
0
0
if222120
121110
020100
RRR
RRR
RRR
R
2
))(trace(w
1/2R
w
RR
4x 1221
w
RR
4y 2002
w
RR
4z 0110
Quaternions in Action
• Ogre::QuaternionOgreQuaternion.hOgreQuaternion.h