Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutorial/Tutorial/src/ExampleFrameListener.h @ 30

Last change on this file since 30 was 30, checked in by nicolasc, 17 years ago

used cmake
included a resonable base structure

File size: 12.0 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10You may use this sample code for anything you like, it is not covered by the
11LGPL like the rest of the engine.
12-----------------------------------------------------------------------------
13*/
14/*
15-----------------------------------------------------------------------------
16Filename:    ExampleFrameListener.h
17Description: Defines an example frame listener which responds to frame events.
18This frame listener just moves a specified camera around based on
19keyboard and mouse movements.
20Mouse:    Freelook
21W or Up:  Forward
22S or Down:Backward
23A:        Step left
24D:        Step right
25             PgUp:     Move upwards
26             PgDown:   Move downwards
27             F:        Toggle frame rate stats on/off
28                         R:        Render mode
29             T:        Cycle texture filtering
30                       Bilinear, Trilinear, Anisotropic(8)
31             P:        Toggle on/off display of camera position / orientation
32-----------------------------------------------------------------------------
33*/
34
35#ifndef __ExampleFrameListener_H__
36#define __ExampleFrameListener_H__
37
38#include "Ogre.h"
39#include "OgreStringConverter.h"
40#include "OgreException.h"
41
42//Use this define to signify OIS will be used as a DLL
43//(so that dll import/export macros are in effect)
44#define OIS_DYNAMIC_LIB
45#include <OIS/OIS.h>
46
47using namespace Ogre;
48
49class ExampleFrameListener: public FrameListener, public WindowEventListener
50{
51protected:
52
53        void updateStats(void)
54        {
55                static String currFps = "Current FPS: ";
56                static String avgFps = "Average FPS: ";
57                static String bestFps = "Best FPS: ";
58                static String worstFps = "Worst FPS: ";
59                static String tris = "Triangle Count: ";
60                static String batches = "Batch Count: ";
61
62                // update stats when necessary
63                try {
64                        OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
65                        OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
66                        OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
67                        OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
68
69                        const RenderTarget::FrameStats& stats = mWindow->getStatistics();
70                        guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
71                        guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS));
72                        guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
73                                +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
74                        guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
75                                +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
76
77                        OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
78                        guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));
79
80                        OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches");
81                        guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount));
82
83                        OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
84                        guiDbg->setCaption(mDebugText);
85                }
86                catch(...) { }
87        }
88
89public:
90        // Constructor takes a RenderWindow because it uses that to determine input context
91        ExampleFrameListener(RenderWindow* win, Camera* cam, bool bufferedKeys = false, bool bufferedMouse = false,
92                             bool bufferedJoy = false ) :
93                mCamera(cam), mTranslateVector(Vector3::ZERO), mWindow(win), mStatsOn(true), mNumScreenShots(0),
94                mMoveScale(0.0f), mRotScale(0.0f), mTimeUntilNextToggle(0), mFiltering(TFO_BILINEAR),
95                mAniso(1), mSceneDetailIndex(0), mMoveSpeed(100), mRotateSpeed(36), mDebugOverlay(0),
96                mInputManager(0), mMouse(0), mKeyboard(0), mJoy(0)
97        {
98                using namespace OIS;
99
100                mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
101
102                LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
103                ParamList pl;
104                size_t windowHnd = 0;
105                std::ostringstream windowHndStr;
106
107                win->getCustomAttribute("WINDOW", &windowHnd);
108                windowHndStr << windowHnd;
109                pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
110
111                mInputManager = InputManager::createInputSystem( pl );
112
113                //Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse)
114                mKeyboard = static_cast<Keyboard*>(mInputManager->createInputObject( OISKeyboard, bufferedKeys ));
115                mMouse = static_cast<Mouse*>(mInputManager->createInputObject( OISMouse, bufferedMouse ));
116                try {
117                        mJoy = static_cast<JoyStick*>(mInputManager->createInputObject( OISJoyStick, bufferedJoy ));
118                }
119                catch(...) {
120                        mJoy = 0;
121                }
122
123                //Set initial mouse clipping size
124                windowResized(mWindow);
125
126                showDebugOverlay(true);
127
128                //Register as a Window listener
129                WindowEventUtilities::addWindowEventListener(mWindow, this);
130        }
131
132        //Adjust mouse clipping area
133        virtual void windowResized(RenderWindow* rw)
134        {
135                unsigned int width, height, depth;
136                int left, top;
137                rw->getMetrics(width, height, depth, left, top);
138
139                const OIS::MouseState &ms = mMouse->getMouseState();
140                ms.width = width;
141                ms.height = height;
142        }
143
144        //Unattach OIS before window shutdown (very important under Linux)
145        virtual void windowClosed(RenderWindow* rw)
146        {
147                //Only close for window that created OIS (the main window in these demos)
148                if( rw == mWindow )
149                {
150                        if( mInputManager )
151                        {
152                                mInputManager->destroyInputObject( mMouse );
153                                mInputManager->destroyInputObject( mKeyboard );
154                                mInputManager->destroyInputObject( mJoy );
155
156                                OIS::InputManager::destroyInputSystem(mInputManager);
157                                mInputManager = 0;
158                        }
159                }
160        }
161
162        virtual ~ExampleFrameListener()
163        {
164                //Remove ourself as a Window listener
165                WindowEventUtilities::removeWindowEventListener(mWindow, this);
166                windowClosed(mWindow);
167        }
168
169        virtual bool processUnbufferedKeyInput(const FrameEvent& evt)
170        {
171                using namespace OIS;
172
173                if(mKeyboard->isKeyDown(KC_A))
174                        mTranslateVector.x = -mMoveScale;       // Move camera left
175
176                if(mKeyboard->isKeyDown(KC_D))
177                        mTranslateVector.x = mMoveScale;        // Move camera RIGHT
178
179                if(mKeyboard->isKeyDown(KC_UP) || mKeyboard->isKeyDown(KC_W) )
180                        mTranslateVector.z = -mMoveScale;       // Move camera forward
181
182                if(mKeyboard->isKeyDown(KC_DOWN) || mKeyboard->isKeyDown(KC_S) )
183                        mTranslateVector.z = mMoveScale;        // Move camera backward
184
185                if(mKeyboard->isKeyDown(KC_PGUP))
186                        mTranslateVector.y = mMoveScale;        // Move camera up
187
188                if(mKeyboard->isKeyDown(KC_PGDOWN))
189                        mTranslateVector.y = -mMoveScale;       // Move camera down
190
191                if(mKeyboard->isKeyDown(KC_RIGHT))
192                        mCamera->yaw(-mRotScale);
193
194                if(mKeyboard->isKeyDown(KC_LEFT))
195                        mCamera->yaw(mRotScale);
196
197                if( mKeyboard->isKeyDown(KC_ESCAPE) || mKeyboard->isKeyDown(KC_Q) )
198                        return false;
199
200        if( mKeyboard->isKeyDown(KC_F) && mTimeUntilNextToggle <= 0 )
201                {
202                        mStatsOn = !mStatsOn;
203                        showDebugOverlay(mStatsOn);
204                        mTimeUntilNextToggle = 1;
205                }
206
207                if( mKeyboard->isKeyDown(KC_T) && mTimeUntilNextToggle <= 0 )
208                {
209                        switch(mFiltering)
210                        {
211                        case TFO_BILINEAR:
212                                mFiltering = TFO_TRILINEAR;
213                                mAniso = 1;
214                                break;
215                        case TFO_TRILINEAR:
216                                mFiltering = TFO_ANISOTROPIC;
217                                mAniso = 8;
218                                break;
219                        case TFO_ANISOTROPIC:
220                                mFiltering = TFO_BILINEAR;
221                                mAniso = 1;
222                                break;
223                        default: break;
224                        }
225                        MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
226                        MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
227
228                        showDebugOverlay(mStatsOn);
229                        mTimeUntilNextToggle = 1;
230                }
231
232                if(mKeyboard->isKeyDown(KC_SYSRQ) && mTimeUntilNextToggle <= 0)
233                {
234                        std::ostringstream ss;
235                        ss << "screenshot_" << ++mNumScreenShots << ".png";
236                        mWindow->writeContentsToFile(ss.str());
237                        mTimeUntilNextToggle = 0.5;
238                        mDebugText = "Saved: " + ss.str();
239                }
240
241                if(mKeyboard->isKeyDown(KC_R) && mTimeUntilNextToggle <=0)
242                {
243                        mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;
244                        switch(mSceneDetailIndex) {
245                                case 0 : mCamera->setPolygonMode(PM_SOLID); break;
246                                case 1 : mCamera->setPolygonMode(PM_WIREFRAME); break;
247                                case 2 : mCamera->setPolygonMode(PM_POINTS); break;
248                        }
249                        mTimeUntilNextToggle = 0.5;
250                }
251
252                static bool displayCameraDetails = false;
253                if(mKeyboard->isKeyDown(KC_P) && mTimeUntilNextToggle <= 0)
254                {
255                        displayCameraDetails = !displayCameraDetails;
256                        mTimeUntilNextToggle = 0.5;
257                        if (!displayCameraDetails)
258                                mDebugText = "";
259                }
260
261                // Print camera details
262                if(displayCameraDetails)
263                        mDebugText = "P: " + StringConverter::toString(mCamera->getDerivedPosition()) +
264                                                 " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation());
265
266                // Return true to continue rendering
267                return true;
268        }
269
270        bool processUnbufferedMouseInput(const FrameEvent& evt)
271        {
272                using namespace OIS;
273
274                // Rotation factors, may not be used if the second mouse button is pressed
275                // 2nd mouse button - slide, otherwise rotate
276                const MouseState &ms = mMouse->getMouseState();
277                if( ms.buttonDown( MB_Right ) )
278                {
279                        mTranslateVector.x += ms.X.rel * 0.13;
280                        mTranslateVector.y -= ms.Y.rel * 0.13;
281                }
282                else
283                {
284                        mRotX = Degree(-ms.X.rel * 0.13);
285                        mRotY = Degree(-ms.Y.rel * 0.13);
286                }
287
288                return true;
289        }
290
291        void moveCamera()
292        {
293                // Make all the changes to the camera
294                // Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW
295                //(e.g. airplane)
296                mCamera->yaw(mRotX);
297                mCamera->pitch(mRotY);
298                mCamera->moveRelative(mTranslateVector);
299        }
300
301        void showDebugOverlay(bool show)
302        {
303                if (mDebugOverlay)
304                {
305                        if (show)
306                                mDebugOverlay->show();
307                        else
308                                mDebugOverlay->hide();
309                }
310        }
311
312        // Override frameStarted event to process that (don't care about frameEnded)
313        bool frameStarted(const FrameEvent& evt)
314        {
315                using namespace OIS;
316
317                if(mWindow->isClosed()) return false;
318
319                //Need to capture/update each device
320                mKeyboard->capture();
321                mMouse->capture();
322                if( mJoy ) mJoy->capture();
323
324                bool buffJ = (mJoy) ? mJoy->buffered() : true;
325
326                //Check if one of the devices is not buffered
327                if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )
328                {
329                        // one of the input modes is immediate, so setup what is needed for immediate movement
330                        if (mTimeUntilNextToggle >= 0)
331                                mTimeUntilNextToggle -= evt.timeSinceLastFrame;
332
333                        // If this is the first frame, pick a speed
334                        if (evt.timeSinceLastFrame == 0)
335                        {
336                                mMoveScale = 1;
337                                mRotScale = 0.1;
338                        }
339                        // Otherwise scale movement units by time passed since last frame
340                        else
341                        {
342                                // Move about 100 units per second,
343                                mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
344                                // Take about 10 seconds for full rotation
345                                mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
346                        }
347                        mRotX = 0;
348                        mRotY = 0;
349                        mTranslateVector = Ogre::Vector3::ZERO;
350                }
351
352                //Check to see which device is not buffered, and handle it
353                if( !mKeyboard->buffered() )
354                        if( processUnbufferedKeyInput(evt) == false )
355                                return false;
356                if( !mMouse->buffered() )
357                        if( processUnbufferedMouseInput(evt) == false )
358                                return false;
359
360                if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )
361                        moveCamera();
362
363                return true;
364        }
365
366        bool frameEnded(const FrameEvent& evt)
367        {
368                updateStats();
369                return true;
370        }
371
372protected:
373        Camera* mCamera;
374
375        Vector3 mTranslateVector;
376        RenderWindow* mWindow;
377        bool mStatsOn;
378
379        std::string mDebugText;
380
381        unsigned int mNumScreenShots;
382        float mMoveScale;
383        Degree mRotScale;
384        // just to stop toggles flipping too fast
385        Real mTimeUntilNextToggle ;
386        Radian mRotX, mRotY;
387        TextureFilterOptions mFiltering;
388        int mAniso;
389
390        int mSceneDetailIndex ;
391        Real mMoveSpeed;
392        Degree mRotateSpeed;
393        Overlay* mDebugOverlay;
394
395        //OIS Input devices
396        OIS::InputManager* mInputManager;
397        OIS::Mouse*    mMouse;
398        OIS::Keyboard* mKeyboard;
399        OIS::JoyStick* mJoy;
400};
401
402#endif
Note: See TracBrowser for help on using the repository browser.