Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/ExampleFrameListener.h @ 112

Last change on this file since 112 was 89, checked in by bknecht, 17 years ago

merge of mainloop branch to trunk

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