640 likes | 828 Views
Game Programming 05 3D 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
E N D
Game Programming 053D math for Games 2010년 2학기 디지털콘텐츠전공
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(); } }
Call-back Driven Framework • Using Ogre’s FrameListener Class GameFrameListener : public Ogre::FrameListener { public: virtual void frameStarted(const FrameEvent &event) { // Do things happening before rendering pollJoypad(event); updatePlayerControls(events); updateDynamicSimulation(events); resolveCollisions(events); updateCamera(events); // etc. } virtual void frameEnded(const FrameEvent &event) { // Do things after rendering drawHud(events); } }
OGRE3D: Frame Listener • 한장면이 화면에 렌더링되기 직전/직후에 해야 할 일을 정의하고 있는 객체 • 추가 작업을 위해서는 frame listener를 추가 생성하고, 이를 root에 등록시켜 사용 • 여러 개의 frame listener 가 존재할 수 있다.
Frame Listener의 맴버함수 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(); }
Ogre Engine의 Rendering Loop • Root::startRendering() 함수에서 이뤄짐 • Redering Loop 실행 • 매 프레임 마다 renderOneFrame 실행: • Loop의 중단 • FrameStarted, frameRenderingQueued, FrameEnded에서 하나라도 false를 return 할 경우 1. Frame Listener들의 FrameStarted() 함수 호출 2. 한 프레임 렌더링 Frame Listener들의 frameRenderingQueued() 함수 호출 3. Frame Listener들의 FrameEnded() 함수 호출
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); }
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); }
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);
Frame Listner 수정 • frameRenderingQueued 함수 override 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
Processing Input • UnbufferedInput 구현 • Mouse와 keyboard의 현재 상태를 얻어옴(BaseApplication::frameRenderingQueued에서 수행) • 다음과 같이 사용할 준비를 한다. mMouse->capture(); mKeyboard->capture(); 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
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;
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()); }
Keyboard 입력 구현 • 키보드의 상태를 찾아내어 구현 Ogre::Vector3 transVector = Ogre::Vector3::ZERO; if (mKeyboard->isKeyDown(OIS::KC_I)) // Forward transVector.z -= mMove; if (mKeyboard->isKeyDown(OIS::KC_K)) // Backward transVector.z += mMove; if (mKeyboard->isKeyDown(OIS::KC_U)) // Up transVector.y += mMove; if (mKeyboard->isKeyDown(OIS::KC_O)) // Down transVector.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 } }
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)) // Forward transVector.z -= mMove; if (mKeyboard->isKeyDown(OIS::KC_K)) // Backward transVector.z += mMove; if (mKeyboard->isKeyDown(OIS::KC_U)) // Up transVector.y += mMove; if (mKeyboard->isKeyDown(OIS::KC_O)) // Down transVector.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 worldsimulated 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
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)
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 Class OgreVector3.h
Linear Interpolation • LERP (linear interpolation) • Given two points (vectors), finding inbetweens Q v= Q - P α 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 =
Homogeneous Coordinates • Any affine transformation between 3D spaces can be represented by a 4x4 matrix
Transformations • 2D rotation • 2D scaling
Transformations • 2D shear • 2D reflection
Affine Transformations • 2D translation
Examples of Affine Transformations • 2D transformation for vectors • Translation is simply ignored
Affine Transformations • 3D rotation
Pivot-Point Rotation • Rotation with respect to a pivot point (x,y)
Fixed-Point Scaling • Scaling with respect to a fixed point (x,y)
Scaling Direction • Scaling along an arbitrary axis
Matrices in Action • Ogre::Matrix3, Ogre::Matrix4
Euler angles • Arbitrary rotation can be represented by three rotation along x,y,z axis
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.
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.