source: GTP/trunk/App/Demos/Vis/KdTreeDemo/OGRE/src/TestKdTreeAppListener.cpp @ 1274

Revision 1274, 48.1 KB checked in by szydlowski, 18 years ago (diff)

modifications to terrain rendering and demo mode

Line 
1#include <fstream>
2#include <cstdlib>
3
4#include <OgrePanelOverlayElement.h>
5#include "TestKdTreeAppListener.h"
6#include <windows.h>
7
8const Real       KdTreeAppListener::DEMO_WAIT = 5.0;
9const String KdTreeAppListener::NA = ": N/A";
10const String KdTreeAppListener::RENDERMETHOD[] = { "INT", "VFC", "SWC", "CHC" };
11const String KdTreeAppListener::RENDERMETHODCAPTION[] =
12{
13        "Internal Frustum Culling",
14        "View Frustum Culling",
15        "Stop and Wait Culling",
16        "Coherent Hierarchical Culling"
17};
18const String KdTreeAppListener::BUILDMETHOD[] = { "RE", "PQ" };
19const String KdTreeAppListener::BUILDMETHODCAPTION[] = { "Recursive", "Priority Queue" };
20const String KdTreeAppListener::SCENEMANAGER[] = { "KDT", "KTE", "OCM", "OCT", "TER", "GEN" };
21const String KdTreeAppListener::SCENEMANAGERNAME[] =
22{
23        "KdTreeSceneManager",
24        "KdTreeTerrainSceneManager",
25        "OcclusionCullingSceneManager",
26        "OctreeSceneManager",
27        "TerrainSceneManager",
28        "DefaultSceneManager"
29};
30
31void KdTreeAppListener::updateStats(void)
32{
33        static unsigned int opt = 0;
34        static char str[100];
35
36        static String currFps = "Current FPS: ";
37        static String avgFps = "Average FPS: ";
38        static String bestFps = "Best FPS: ";
39        static String worstFps = "Worst FPS: ";
40        static String tris = "Triangle Count: ";
41
42        // update stats when necessary
43        try {
44                OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
45                OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
46                OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
47                OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
48
49                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
50
51                guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
52                guiCurr->setCaption(currFps + StringConverter::toString((int)stats.lastFPS));
53                guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
54                        +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
55                guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
56                        +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
57
58                OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
59                guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));
60
61                OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
62                guiDbg->setCaption(mWindow->getDebugText());
63
64
65                //-- culling stats
66                mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt);
67                mFrustumCulledNodesInfo->setCaption(str);
68
69                mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt);
70                mQueryCulledNodesInfo->setCaption(str);
71
72                mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt);
73                mHierarchyNodesInfo->setCaption(str);
74
75                mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt);
76                mRenderedNodesInfo->setCaption(str);
77
78                // take old value into account in order to create no sudden changes
79                mSceneMgr->getOption("NumQueriesIssued", &opt);
80                mDelayedQueriesIssued = mDelayedQueriesIssued * 0.8 + (float)opt * 0.2f;
81                sprintf(str,": %d", (int)mDelayedQueriesIssued);
82                mQueriesIssuedInfo->setCaption(str);
83
84                mSceneMgr->getOption("NumTraversedNodes", &opt);
85                mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2f;
86                sprintf(str,": %d", (int)mDelayedTraversedNodes);
87                mTraversedNodesInfo->setCaption(str);
88        }
89        catch(...)
90        {
91                // ignore
92        }
93}
94
95// Constructor takes a RenderWindow because it uses that to determine input context
96KdTreeAppListener::KdTreeAppListener(RenderWindow* win, SceneManager* sm, const Options& options,
97                                                                         bool useBufferedInputKeys, bool useBufferedInputMouse):
98// basic
99mWindow(win),
100mSceneMgr(sm),
101mOptions(options),
102mUseBufferedInputKeys(useBufferedInputKeys),
103mUseBufferedInputMouse(useBufferedInputMouse),
104// elements
105mCamNode(0),
106mCamera(0),
107mTopCam(0),
108// toggle
109mStatsOn(true),
110mVizCamera(false),
111mFreeMove(false),
112mTopCamFollow(true),
113mShowTree(SHOWTREE_OFF),
114//counters
115mSeqNum(0),
116mNumScreenShots(0),
117// rendering/texture options
118mSceneDetailIndex(PM_SOLID),
119mFiltering(TFO_ANISOTROPIC),
120mAniso(8),
121// chc stats
122mDelayedQueriesIssued(0.0f),
123mDelayedTraversedNodes(0.0f),
124// movement
125mTranslateVector(Vector3::ZERO),
126mVizCamTransVect(Vector3::ZERO),
127mRotX(0.0f),
128mRotY(0.0f),
129mMoveScale(0.0f),
130mRotScale(0.0f),
131mDeathAngle(0.0f),
132mRaySceneQuery(0),
133// just to stop toggles flipping too fast
134mTimeUntilNextToggle(0.0f),
135// stuff for walkthrough recording/playback
136mTimeUntilNextLogWrite(options.mDemoInterval),
137mTimeRemaining(0.0f),
138mWaitBeforeDemoStart(0.0f),
139mAppState(AS_NORMAL)
140{
141        mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse;
142
143        if (mInputTypeSwitchingOn)
144        {
145                mEventProcessor = new EventProcessor();
146                mEventProcessor->initialise(win);
147                mEventProcessor->startProcessingEvents();
148                mEventProcessor->addKeyListener(this);
149                mInputDevice = mEventProcessor->getInputReader();
150
151        }
152        else
153        {
154                mInputDevice = PlatformManager::getSingleton().createInputReader();
155                mInputDevice->initialise(win,true, true);
156        }
157
158        MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
159        MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
160
161        mCamera = sm->getCamera("PlayerCam");
162        mTopCam = sm->getCamera("TopCam");
163        mCamNode = sm->getSceneNode("PlayerCamNode");
164
165        mRaySceneQuery = mSceneMgr->createRayQuery(Ray(mCamNode->getPosition(), Vector3::NEGATIVE_UNIT_Y));
166
167        mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
168        mKdTreeOverlay = OverlayManager::getSingleton().getByName("KdTree/DebugOverlay");
169        mDemoOverlay = 0;
170        mDemoStatus = 0;
171        mDemoTime = 0;
172
173        initKdTreeOverlay();
174        initStatsOverlay();
175
176        if (!mOptions.mDemoInfileName.empty())
177                loadFrames(mOptions.mDemoInfileName, mFrameList);
178
179        if (!mOptions.mDemoInfileName.empty() && mOptions.mDemoMode)
180        {
181                // force X second wait when in demo mode - avoids initial low framerate due to loading delays
182                mWaitBeforeDemoStart = DEMO_WAIT;
183                // set playback icon
184                togglePlayback();
185                // hide all other overlays
186                mStatsOn = false;
187        }
188
189        showDebugOverlay(mStatsOn);
190        setDemoOverlay();
191}
192//-----------------------------------------------------------------------
193KdTreeAppListener::~KdTreeAppListener()
194{
195        if (mInputTypeSwitchingOn)
196        {
197                delete mEventProcessor;
198        }
199        else
200        {
201                PlatformManager::getSingleton().destroyInputReader( mInputDevice );
202        }
203}
204//-----------------------------------------------------------------------
205void KdTreeAppListener::initOverlayElement(OverlayElement **elInfo, String ext,
206        String name, int top, String caption)
207{
208        OverlayElement *el =
209                OverlayManager::getSingleton().getOverlayElement(ext + name);
210
211        (*elInfo) = OverlayManager::getSingleton().getOverlayElement(ext + name + "Info");
212        (*elInfo)->setCaption(caption);
213
214        el->setTop(top);
215        (*elInfo)->setTop(top);
216}
217//-----------------------------------------------------------------------
218void KdTreeAppListener::initStatsOverlay()
219{
220        const int border_height = 10;
221        const int vert_space = 15;
222
223        //-- visibility culling stats overlay
224        int top = border_height;
225
226        String ext = "KdTree/Visibility/";
227
228        initOverlayElement(&mFrustumCulledNodesInfo, ext, "FrustumCulledNodes", top, ": 0"); top += vert_space;
229        initOverlayElement(&mQueryCulledNodesInfo, ext, "QueryCulledNodes", top, ": 0"); top += vert_space;
230        initOverlayElement(&mTraversedNodesInfo, ext, "TraversedNodes", top, ": 0"); top += vert_space;
231        initOverlayElement(&mHierarchyNodesInfo, ext, "HierarchyNodes", top, ": 0"); top += vert_space;
232        initOverlayElement(&mRenderedNodesInfo, ext, "RenderedNodes", top, ": 0"); top += vert_space;
233        initOverlayElement(&mObjectsCountInfo, ext, "ObjectsCount", top, ": 0"); top += vert_space;
234        initOverlayElement(&mQueriesIssuedInfo, ext, "QueriesIssued", top, ": 0"); top += vert_space;
235
236        OverlayElement *visPanel = OverlayManager::getSingleton().
237                getOverlayElement("KdTree/VisibilityStatsPanel");
238
239        visPanel->setHeight(top + border_height);
240}
241//-----------------------------------------------------------------------
242void KdTreeAppListener::initKdTreeOverlay()
243{
244        const int border_height = 10;
245        const int vert_space = 15;
246        int top = border_height;
247
248        String ext = "KdTree/";
249        String sMD, sKT, sKI, sHL, sBM, sRM, sFM, sTC, sEV;
250
251        int maxd;
252        if (mSceneMgr->getOption("KdTreeMaxDepth", &maxd))
253                sMD = ": " + StringConverter::toString(maxd);
254        else
255                sMD = NA;
256
257        Real kt;
258        if (mSceneMgr->getOption("KT", &kt))
259                sKT = ": " + StringConverter::toString(kt);
260        else
261                sKT = NA;
262
263        Real ki;
264        if (mSceneMgr->getOption("KI", &ki))
265                sKI = ": " + StringConverter::toString(ki);
266        else
267                sKI = NA;
268
269        int hl;
270        if (mSceneMgr->getOption("HiLiteLevel", &hl))
271                sHL = ": " + StringConverter::toString(hl);
272        else
273                sHL = NA;
274        if (mShowTree == SHOWTREE_OFF)
275                sHL = ": off";
276
277        int bm;
278        if (mSceneMgr->getOption("BuildMethod", &bm))
279                sBM = ": " + BUILDMETHODCAPTION[bm];
280        else
281                sBM = NA;
282
283        int rm;
284        if (mSceneMgr->getOption("RenderMethod", &rm))
285                sRM = ": " + RENDERMETHODCAPTION[rm];
286        else
287                sRM = NA;
288
289        // hack to allow mode switching in OCM
290        if (mOptions.mSceneManager == SM_OCM)
291        {
292                rm = CONV_KDT_TO_OCM_ALG(mOptions.mRenderMethod);
293                sRM = ": " + RENDERMETHODCAPTION[CONV_OCM_TO_KDT_ALG(rm)];
294        }
295
296        bool enh;
297        if (mSceneMgr->getOption("EnhancedVisibility", &enh))
298        {
299                if (enh)
300                        sEV = ": Enhanced";
301                else
302                        sEV = ": Simple";
303        }
304        else
305        {
306                sEV = NA;
307        }
308
309        sFM = NA;
310        if (mFreeMove)
311                sFM = ": Free";
312        else
313                sFM = ": Ground";
314
315        sTC = NA;
316        if (mTopCamFollow)
317                sTC = ": Follow";
318        else
319                sTC = ": Free";
320
321        initOverlayElement(&mRenderMethodInfo, ext, "RenderMethod", top, sRM); top += vert_space;
322        initOverlayElement(&mEnhancedVisInfo, ext, "EnhancedVis", top, sEV); top += vert_space;
323        initOverlayElement(&mBuildMethodInfo, ext, "BuildMethod", top, sBM); top += vert_space;
324        initOverlayElement(&mKdTreeMaxDepthInfo, ext, "KdTreeMaxDepth", top, sMD); top += vert_space;
325        initOverlayElement(&mHighlightLevelInfo, ext, "HighlightLevel", top, sHL); top += vert_space;
326        initOverlayElement(&mKTInfo, ext, "KT", top, sKT); top += vert_space;
327        initOverlayElement(&mKIInfo, ext, "KI", top, sKI); top += vert_space;
328        initOverlayElement(&mMovementInfo, ext, "Movement", top, sFM); top += vert_space;
329        initOverlayElement(&mTopCamInfo, ext, "TopCam", top, sTC); top += vert_space;
330
331        OverlayElement *visPanel = OverlayManager::getSingleton().
332                getOverlayElement("KdTree/OptionsPanel");
333
334        visPanel->setHeight(top + border_height);
335}
336
337void KdTreeAppListener::showDebugOverlay(bool show)
338{
339        if (mDebugOverlay && mKdTreeOverlay)
340        {
341                if (show)
342                {
343                        mDebugOverlay->show();
344                        mKdTreeOverlay->show();
345                }
346                else
347                {
348                        mDebugOverlay->hide();
349                        mKdTreeOverlay->hide();
350                }
351        }
352}
353
354void KdTreeAppListener::toggleVizCamera()
355{
356        static int nodeVizMode = 0;
357
358        nodeVizMode = (nodeVizMode + 1) % NODEVIZ_MODES_NUM;
359
360        if (nodeVizMode != 0)
361        {
362                if (!mVizCamera)
363                {
364                        Viewport* tvp = mWindow->addViewport(mTopCam,
365                                VIZ_VIEWPORT_Z_ORDER, 0.66, 0.66, 0.34, 0.34);
366                        tvp->setBackgroundColour(ColourValue(1.0, 0.0, 0.0));
367                        tvp->setOverlaysEnabled(false);
368
369                        mTopCam->setAspectRatio(
370                                Real(tvp->getActualWidth())/Real(tvp->getActualHeight()));
371                        mVizCamera = true;
372                        mSceneMgr->setOption("VisualizeCulledNodes", &mVizCamera);
373                }
374
375                bool renderNodesForViz = (nodeVizMode == NODEVIZ_RENDER_NODES) ||
376                        (nodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
377                bool renderNodesContentForViz = (nodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
378
379                mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz);
380                mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz);
381        }
382        else
383        {
384                mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER);
385                mVizCamera = false;
386                mSceneMgr->setOption("VisualizeCulledNodes", &mVizCamera);
387        }
388}
389
390void KdTreeAppListener::toggleShowBoxes()
391{
392        mShowTree = (mShowTree + 1) % SHOWTREE_MODES_NUM;
393        bool show = false, all = false;
394
395        switch (mShowTree)
396        {
397        case SHOWTREE_OFF:
398                break;
399        case SHOWTREE_HILITE:
400                show = true;
401                break;
402        case SHOWTREE_ALL:
403                show = all = true;
404                break;
405        }
406
407        // set display
408
409        if (mSceneMgr->getTypeName() == "OctreeSceneManager")
410                mSceneMgr->setOption("ShowOctree", &show);
411        else if (
412                mSceneMgr->getTypeName() == "KdTreeSceneManager" ||
413                mSceneMgr->getTypeName() == "KdTreeTerrainSceneManager")
414                mSceneMgr->setOption("ShowKdTree", &show);
415
416        // set showall
417        mSceneMgr->setOption("ShowAllBoxes", &all);
418
419        if (!show)
420                mHighlightLevelInfo->setCaption(": off");
421        else
422        {
423                int hl;
424                if (mSceneMgr->getOption("HiLiteLevel", &hl))
425                        mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
426                else
427                        mHighlightLevelInfo->setCaption(NA);
428        }
429}
430
431void KdTreeAppListener::toggleEnhancedVisibility()
432{
433        bool mode;
434        if (mSceneMgr->getOption("EnhancedVisibility", &mode))
435        {
436                mode = !mode;
437                if (mSceneMgr->setOption("EnhancedVisibility", &mode))
438                {
439                        if (mode)
440                                mEnhancedVisInfo->setCaption(": Enhanced");
441                        else
442                                mEnhancedVisInfo->setCaption(": Simple");
443                }
444        }
445        else
446        {
447                mEnhancedVisInfo->setCaption(NA);
448        }
449}
450
451void KdTreeAppListener::toggleBuildMethod()
452{
453        int bm;
454
455        if (mSceneMgr->getOption("BuildMethod", &bm))
456        {
457                bm = (bm + 1) % KdTree::KDBM_SIZE;
458                if (mSceneMgr->setOption("BuildMethod", &bm))
459                        mBuildMethodInfo->setCaption(": " + BUILDMETHODCAPTION[bm]);
460        }
461        else
462        {
463                mBuildMethodInfo->setCaption(NA);
464        }
465}
466
467void KdTreeAppListener::toggleRenderMethod()
468{
469        int rm;
470
471        if (mSceneMgr->getOption("RenderMethod", &rm))
472        {
473                rm = (rm + 1) % KdTree::KDRM_SIZE;
474                if (mSceneMgr->setOption("RenderMethod", &rm))
475                        mRenderMethodInfo->setCaption(": " + RENDERMETHODCAPTION[rm]);
476        }
477        else
478        {
479                mRenderMethodInfo->setCaption(NA);
480        }
481
482        // hack to allow mode switching in OCM, cannot extract setting from sm
483        if (mOptions.mSceneManager == SM_OCM)
484        {
485                static int alg = CONV_KDT_TO_OCM_ALG(mOptions.mRenderMethod);
486                alg = (alg + 1) % 3;
487                if (mSceneMgr->setOption("Algorithm", &alg))
488                        mRenderMethodInfo->setCaption(": " + RENDERMETHODCAPTION[CONV_OCM_TO_KDT_ALG(alg)]);
489        }
490}
491
492bool KdTreeAppListener::processUnbufferedKeyInput(const FrameEvent& evt)
493{
494        // ignore all keystrokes except escape when in demo mode
495        if (mOptions.mDemoMode)
496        {
497                if (mInputDevice->isKeyDown(KC_ESCAPE))
498                        return false;
499                else
500                        return true;
501        }
502
503        if (mInputDevice->isKeyDown(KC_F1) && mTimeUntilNextToggle <= 0)
504        {
505                // TODO show help overlay
506        }
507
508        // show/hide vis viewport
509        if (mInputDevice->isKeyDown(KC_F2) && mTimeUntilNextToggle <= 0)
510        {
511                toggleVizCamera();
512                mTimeUntilNextToggle = 0.5;
513        }
514
515        // show/hide kdtree boxes
516        if (mInputDevice->isKeyDown(KC_F3) && mTimeUntilNextToggle <= 0)
517        {
518                toggleShowBoxes();
519                mTimeUntilNextToggle = 0.5;
520        }
521
522        if (mInputDevice->isKeyDown(KC_F4) && mTimeUntilNextToggle <= 0)
523        {
524                bool toggleShow;
525                mSceneMgr->getOption("ShowNodes", &toggleShow);
526                toggleShow = !toggleShow;
527                mSceneMgr->setOption("ShowNodes", &toggleShow);
528                mTimeUntilNextToggle = 0.5;
529        }
530
531        // demo recording stuff
532        if (mInputDevice->isKeyDown(KC_F5) && mTimeUntilNextToggle <= 0)
533        {
534                toggleRecord();
535                mTimeUntilNextToggle = 0.5;
536        }
537
538        if (mInputDevice->isKeyDown(KC_F6) && mTimeUntilNextToggle <= 0)
539        {
540                if (!mOptions.mDemoOutfileName.empty() && !mFrameList.empty())
541                        saveFrames(mOptions.mDemoOutfileName, mFrameList);
542                mTimeUntilNextToggle = 0.5;
543        }
544
545        if (mInputDevice->isKeyDown(KC_F9) && mTimeUntilNextToggle <= 0)
546        {
547                togglePlayback();
548                mTimeUntilNextToggle = 0.5;
549        }
550
551        if (mInputDevice->isKeyDown(KC_0) && mTimeUntilNextToggle <= 0)
552        {
553                toggleBuildMethod();
554                mTimeUntilNextToggle = 0.5;
555        }
556
557        if (mInputDevice->isKeyDown(KC_SPACE) && mTimeUntilNextToggle <= 0)
558        {
559                toggleRenderMethod();
560                mTimeUntilNextToggle = 0.5;
561        }
562
563        if (mInputDevice->isKeyDown(KC_V) && mTimeUntilNextToggle <= 0)
564        {
565                toggleEnhancedVisibility();
566                mTimeUntilNextToggle = 0.5;
567        }
568
569        if (mInputDevice->isKeyDown(KC_B) && mTimeUntilNextToggle <= 0)
570        {
571                mSceneMgr->showBoundingBoxes( ! mSceneMgr->getShowBoundingBoxes() );
572                mTimeUntilNextToggle = 0.5;
573        }
574
575        const static int vizCamSpeedup = 12;
576        // moving the cull camera
577        if (mInputDevice->isKeyDown(KC_NUMPAD2))
578        {
579                mVizCamTransVect.y = -mMoveScale * vizCamSpeedup;
580        }
581        if (mInputDevice->isKeyDown(KC_NUMPAD8))
582        {
583                mVizCamTransVect.y = mMoveScale * vizCamSpeedup;
584        }
585        if (mInputDevice->isKeyDown(KC_NUMPAD4))
586        {
587                mVizCamTransVect.x = -mMoveScale * vizCamSpeedup;
588        }
589        if (mInputDevice->isKeyDown(KC_NUMPAD6))
590        {
591                mVizCamTransVect.x = mMoveScale * vizCamSpeedup;
592        }
593        if (mInputDevice->isKeyDown(KC_SUBTRACT))
594        {
595                mVizCamTransVect.z = mMoveScale * vizCamSpeedup;
596        }
597        if (mInputDevice->isKeyDown(KC_ADD))
598        {
599                mVizCamTransVect.z = -mMoveScale * vizCamSpeedup;
600        }
601
602        if ((mInputDevice->isKeyDown(KC_1) || mInputDevice->isKeyDown(KC_2)) && mTimeUntilNextToggle <= 0)
603        {
604                int currdepth;
605                if (mSceneMgr->getOption("KdTreeMaxDepth", &currdepth))
606                {
607                        if (mInputDevice->isKeyDown(KC_1))
608                                currdepth--;
609                        else if (mInputDevice->isKeyDown(KC_2))
610                                currdepth++;
611
612                        if (mSceneMgr->setOption("KdTreeMaxDepth", &currdepth))
613                        {
614                                mKdTreeMaxDepthInfo->setCaption(": " + StringConverter::toString(currdepth));
615                                int hl;
616                                if (mSceneMgr->getOption("HiLiteLevel", &hl))
617                                        mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
618                                else
619                                        mHighlightLevelInfo->setCaption(NA);
620                        }
621                }
622                else
623                {
624                        mKdTreeMaxDepthInfo->setCaption(NA);
625                        mHighlightLevelInfo->setCaption(NA);
626                }
627
628                if (mShowTree == SHOWTREE_OFF)
629                        mHighlightLevelInfo->setCaption(": off");
630
631                mTimeUntilNextToggle = 0.2;
632        }
633
634        if ((mInputDevice->isKeyDown(KC_3) || mInputDevice->isKeyDown(KC_4)) && mTimeUntilNextToggle <= 0)
635        {
636                int hl;
637                if (mSceneMgr->getOption("HiLiteLevel", &hl))
638                {
639                        if (mInputDevice->isKeyDown(KC_3))
640                                hl--;
641                        else if (mInputDevice->isKeyDown(KC_4))
642                                hl++;
643
644                        if (mSceneMgr->setOption("HiLiteLevel", &hl))
645                                mHighlightLevelInfo->setCaption(": " + StringConverter::toString(hl));
646                }
647                else
648                {
649                        mHighlightLevelInfo->setCaption(NA);
650                }
651
652                if (mShowTree == SHOWTREE_OFF)
653                        mHighlightLevelInfo->setCaption(": off");
654
655                mTimeUntilNextToggle = 0.2;
656        }
657
658
659        if ((mInputDevice->isKeyDown(KC_5) ||mInputDevice->isKeyDown(KC_6)) && mTimeUntilNextToggle <= 0)
660        {
661                Real kt;
662                if (mSceneMgr->getOption("KT", &kt))
663                {
664                        if (mInputDevice->isKeyDown(KC_5))
665                                kt -= 0.1;
666                        else if (mInputDevice->isKeyDown(KC_6))
667                                kt += 0.1;
668
669                        if (kt < 0.1)
670                                kt = 0.1;
671
672                        if (mSceneMgr->setOption("KT", &kt))
673                                mKTInfo->setCaption(": " + StringConverter::toString(kt));
674                }
675                else
676                {
677                        mKTInfo->setCaption(NA);
678                }
679
680                mTimeUntilNextToggle = 0.2;
681        }
682
683        if ((mInputDevice->isKeyDown(KC_7) || mInputDevice->isKeyDown(KC_8)) && mTimeUntilNextToggle <= 0)
684        {
685                Real ki;
686                if (mSceneMgr->getOption("KI", &ki))
687                {
688                        if (mInputDevice->isKeyDown(KC_7))
689                                ki -= 0.1;
690                        else if (mInputDevice->isKeyDown(KC_8))
691                                ki += 0.1;
692
693                        if (ki < 0.1)
694                                ki = 0.1;
695
696                        if (mSceneMgr->setOption("KI", &ki))
697                                mKIInfo->setCaption(": " + StringConverter::toString(ki));
698                }
699                else
700                {
701                        mKIInfo->setCaption(NA);
702                }
703
704                mTimeUntilNextToggle = 0.2;
705        }
706
707        if (mInputDevice->isKeyDown(KC_U) && mTimeUntilNextToggle <= 0)
708        {
709                mFreeMove = !mFreeMove;
710                String move = ": N/A";
711                if (mFreeMove)
712                        move = ": Free";
713                else
714                        move = ": Ground";
715
716                mMovementInfo->setCaption(move);
717
718                mTimeUntilNextToggle = 0.5;
719        }
720
721        if (mInputDevice->isKeyDown(KC_I) && mTimeUntilNextToggle <= 0)
722        {
723                mTopCamFollow = !mTopCamFollow;
724                String move = ": N/A";
725                if (mTopCamFollow)
726                        move = ": Follow";
727                else
728                        move = ": Free";
729
730                mTopCamInfo->setCaption(move);
731
732                mTimeUntilNextToggle = 0.5;
733        }
734
735        if (mInputDevice->isKeyDown(KC_BACK) && mTimeUntilNextToggle <= 0)
736        {
737                mSceneMgr->setOption("RebuildKdTree", 0);
738                mTimeUntilNextToggle = 1;
739        }
740
741        //if (mInputDevice->isKeyDown(KC_N) && mTimeUntilNextToggle <= 0)
742        //{
743        //      //Entity * ent = mSceneMgr->createEntity("randominsert" + StringConverter::toString(mSeqNum), "robot.mesh");
744        //      Entity * ent = mSceneMgr->createEntity("randominsert" + StringConverter::toString(mSeqNum), "razor.mesh");
745        //      //Vector3 position(Math::RangeRandom(100, 1125), -0, Math::RangeRandom(-1125, 1125));
746        //      Vector3 position(Math::RangeRandom(-5000, 5000), Math::RangeRandom(-5000, 5000), Math::RangeRandom(-5000, 5000));
747        //      //Quaternion orientation(Radian(Math::RangeRandom(-Math::PI, Math::PI)), Vector3::UNIT_Y);
748        //      Vector3 axis(Math::RangeRandom(-1,1),Math::RangeRandom(-1,1),Math::RangeRandom(-1,1));
749        //      axis.normalise();
750        //      Quaternion orientation(Radian(Math::RangeRandom(-Math::PI, Math::PI)), axis);
751        //      Vector3 scale(Math::RangeRandom(0.5, 5),Math::RangeRandom(0.5, 5),Math::RangeRandom(0.5, 5));
752        //      SceneNode * anchor = mSceneMgr->getSceneNode("AnchorNode");
753        //      SceneNode *sn = anchor->createChildSceneNode("RandomInsertNode" + StringConverter::toString(mSeqNum), position, orientation);
754        //      sn->attachObject(ent);
755        //      sn->setScale(scale);
756        //      mTimeUntilNextToggle = 0.5;
757        //      mSeqNum++;
758        //}
759
760        //if (mInputDevice->isKeyDown(KC_J) && mTimeUntilNextToggle <= 0)
761        //{
762        //      if (mSeqNum > 0)
763        //      {
764        //              mSeqNum--;
765        //              mSceneMgr->destroySceneNode("RandomInsertNode" + StringConverter::toString(mSeqNum));
766        //              mSceneMgr->destroyEntity("randominsert" + StringConverter::toString(mSeqNum));
767        //              mTimeUntilNextToggle = 0.5;
768        //      }
769        //}
770
771        //if (mInputDevice->isKeyDown(KC_P) && mTimeUntilNextToggle <= 0)
772        //{
773        //      LogManager::getSingleton().logMessage("############## Camera Position:");
774        //      LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getPosition()));
775        //      LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getOrientation()));
776        //      LogManager::getSingleton().logMessage("############## Cull Camera Position:");
777        //      LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getPosition()));
778        //      LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getOrientation()));
779        //      mTimeUntilNextToggle = 1.0;
780        //}
781
782        if (mInputDevice->isKeyDown(KC_A))
783        {
784                // Move camera left
785                mTranslateVector.x = -mMoveScale;
786        }
787
788        if (mInputDevice->isKeyDown(KC_D))
789        {
790                // Move camera RIGHT
791                mTranslateVector.x = mMoveScale;
792        }
793
794        /* Move camera forward by keypress. */
795        if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W) )
796        {
797                mTranslateVector.z = -mMoveScale;
798        }
799
800        /* Move camera backward by keypress. */
801        if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S) )
802        {
803                mTranslateVector.z = mMoveScale;
804        }
805
806        if (mInputDevice->isKeyDown(KC_PGUP))
807        {
808                // Move camera up
809                mTranslateVector.y = mMoveScale;
810        }
811
812        if (mInputDevice->isKeyDown(KC_PGDOWN))
813        {
814                // Move camera down
815                mTranslateVector.y = -mMoveScale;
816        }
817
818        if (mInputDevice->isKeyDown(KC_RIGHT))
819        {
820                mCamNode->yaw(-mRotScale, Ogre::Node::TS_WORLD);
821        }
822
823        if (mInputDevice->isKeyDown(KC_LEFT))
824        {
825                mCamNode->yaw(mRotScale, Ogre::Node::TS_WORLD);
826        }
827
828        if( mInputDevice->isKeyDown( KC_ESCAPE) )
829        {           
830                return false;
831        }
832
833        // see if switching is on, and you want to toggle
834        if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_M) && mTimeUntilNextToggle <= 0)
835        {
836                switchMouseMode();
837                mTimeUntilNextToggle = 1;
838        }
839
840        if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_K) && mTimeUntilNextToggle <= 0)
841        {
842                // must be going from immediate keyboard to buffered keyboard
843                switchKeyMode();
844                mTimeUntilNextToggle = 1;
845        }
846        if (mInputDevice->isKeyDown(KC_F) && mTimeUntilNextToggle <= 0)
847        {
848                mStatsOn = !mStatsOn;
849                showDebugOverlay(mStatsOn);
850
851                mTimeUntilNextToggle = 1;
852        }
853        if (mInputDevice->isKeyDown(KC_T) && mTimeUntilNextToggle <= 0)
854        {
855                switch(mFiltering)
856                {
857                case TFO_BILINEAR:
858                        mFiltering = TFO_TRILINEAR;
859                        mAniso = 1;
860                        break;
861                case TFO_TRILINEAR:
862                        mFiltering = TFO_ANISOTROPIC;
863                        mAniso = 8;
864                        break;
865                case TFO_ANISOTROPIC:
866                        mFiltering = TFO_BILINEAR;
867                        mAniso = 1;
868                        break;
869                default:
870                        break;
871                }
872                MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
873                MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
874
875
876                showDebugOverlay(mStatsOn);
877
878                mTimeUntilNextToggle = 1;
879        }
880
881        if (mInputDevice->isKeyDown(KC_SYSRQ) && mTimeUntilNextToggle <= 0)
882        {
883                char tmp[20];
884                sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots);
885                mWindow->writeContentsToFile(tmp);
886                mTimeUntilNextToggle = 0.5;
887                mWindow->setDebugText(String("Wrote ") + tmp);
888        }
889
890        if (mInputDevice->isKeyDown(KC_R) && mTimeUntilNextToggle <=0)
891        {
892                mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;
893                switch(mSceneDetailIndex) {
894                        case 0 : mCamera->setPolygonMode(PM_SOLID) ; break ;
895                        case 1 : mCamera->setPolygonMode(PM_WIREFRAME) ; break ;
896                        case 2 : mCamera->setPolygonMode(PM_POINTS) ; break ;
897                }
898                mTimeUntilNextToggle = 0.5;
899        }
900
901        static bool displayCameraDetails = false;
902        if (mInputDevice->isKeyDown(KC_P) && mTimeUntilNextToggle <= 0)
903        {
904                displayCameraDetails = !displayCameraDetails;
905                mTimeUntilNextToggle = 0.5;
906                if (!displayCameraDetails)
907                {
908                        mWindow->setDebugText("");
909                }
910                else
911                {
912                        LogManager::getSingleton().logMessage("############## Camera Position:");
913                        LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getDerivedPosition()));
914                        LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mCamera->getDerivedOrientation()));
915                        LogManager::getSingleton().logMessage("############## Cull Camera Position:");
916                        LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getPosition()));
917                        LogManager::getSingleton().logMessage("############## " + StringConverter::toString(mTopCam->getOrientation()));
918                }
919        }
920        if (displayCameraDetails)
921        {
922                // Print camera details
923                mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) + " " +
924                        "O: " + StringConverter::toString(mCamera->getDerivedOrientation()));
925        }
926
927        // Return true to continue rendering
928        return true;
929}
930
931bool KdTreeAppListener::processUnbufferedMouseInput(const FrameEvent& evt)
932{
933        /* Rotation factors, may not be used if the second mouse button is pressed. */
934
935        /* If the second mouse button is pressed, then the mouse movement results in
936        sliding the camera, otherwise we rotate. */
937        if( mInputDevice->getMouseButton( 1 ) )
938        {
939                mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
940                mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
941        }
942        else
943        {
944                mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
945                mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
946        }
947
948
949        return true;
950}
951
952void KdTreeAppListener::moveCamera()
953{
954
955        // Make all the changes to the camera
956        // Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW (e.g. airplane)
957        mCamNode->yaw(mRotX, Ogre::Node::TS_WORLD);
958        mCamNode->pitch(mRotY);
959        //mCamNode->moveRelative(mTranslateVector);
960        mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector);
961        mTopCam->moveRelative(mVizCamTransVect);
962        if (mTopCamFollow)
963        {
964                Vector3 toppos = mTopCam->getPosition();
965                Vector3 campos = mCamNode->getPosition();
966                mTopCam->setPosition(Vector3::ZERO);
967                mTopCam->setOrientation(Quaternion::IDENTITY);
968                mTopCam->setPosition(campos.x, toppos.y, campos.z);
969                mTopCam->pitch(Radian(-Math::HALF_PI));
970        }
971
972        if (!mFreeMove)
973        {
974                if (mOptions.mSceneFiles == TERRAIN_SCENE)
975                {
976                        static Vector3 pos;
977                        static Ray updateRay;
978                        pos = mCamNode->getPosition();
979                        updateRay.setOrigin(pos);
980                        updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
981                        mRaySceneQuery->setRay(updateRay);
982                        RaySceneQueryResult& qryResult = mRaySceneQuery->execute();
983                        RaySceneQueryResult::iterator i = qryResult.begin();
984                        if (i != qryResult.end() && i->worldFragment)
985                        {
986                                SceneQuery::WorldFragment* wf = i->worldFragment;
987                                mCamNode->setPosition(pos.x, wf->singleIntersection.y + 10, pos.z);
988                        }
989                }
990                else
991                {
992                        static Vector3 pos;
993                        static Ray updateRay;
994                        pos = mCamNode->getPosition();
995                        updateRay.setOrigin(pos);
996                        updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
997                        mRaySceneQuery->setRay(updateRay);
998                        RaySceneQueryResult& qryResult = mRaySceneQuery->execute();
999                        RaySceneQueryResult::iterator i = qryResult.begin();
1000                        while (i != qryResult.end() && i->movable)
1001                        {
1002                                if (i->movable->getName() != "PlayerCam")
1003                                {
1004                                        MovableObject *mov = i->movable;
1005                                        mCamNode->setPosition(pos.x, mov->getWorldBoundingBox().getCenter().y + 2, pos.z);
1006                                        break;
1007                                }
1008                                i++;
1009                        }
1010                }
1011        }
1012}
1013
1014// Override frameStarted event to process that (don't care about frameEnded)
1015bool KdTreeAppListener::frameStarted(const FrameEvent& evt)
1016{
1017        if(mWindow->isClosed())
1018                return false;
1019
1020        if (!mInputTypeSwitchingOn)
1021        {
1022                mInputDevice->capture();
1023        }
1024
1025
1026        if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys)
1027        {
1028                // one of the input modes is immediate, so setup what is needed for immediate mouse/key movement
1029                if (mTimeUntilNextToggle >= 0)
1030                        mTimeUntilNextToggle -= evt.timeSinceLastFrame;
1031
1032                // If this is the first frame, pick a speed
1033                if (evt.timeSinceLastFrame == 0)
1034                {
1035                        mMoveScale = 1;
1036                        mRotScale = 0.1;
1037                }
1038                // Otherwise scale movement units by time passed since last frame
1039                else
1040                {
1041                        // Move about 100 units per second,
1042                        mMoveScale = mOptions.mMoveSpeed * evt.timeSinceLastFrame;
1043                        // Take about 10 seconds for full rotation
1044                        mRotScale = mOptions.mRotateSpeed * evt.timeSinceLastFrame;
1045                }
1046                mRotX = 0;
1047                mRotY = 0;
1048                mTranslateVector = Vector3::ZERO;
1049                mVizCamTransVect = Vector3::ZERO;
1050        }
1051
1052        if (mUseBufferedInputKeys)
1053        {
1054                // no need to do any processing here, it is handled by event processor and
1055                // you get the results as KeyEvents
1056        }
1057        else
1058        {
1059                if (processUnbufferedKeyInput(evt) == false)
1060                {
1061                        return false;
1062                }
1063        }
1064        if (mUseBufferedInputMouse)
1065        {
1066                // no need to do any processing here, it is handled by event processor and
1067                // you get the results as MouseEvents
1068        }
1069        else
1070        {
1071                if (processUnbufferedMouseInput(evt) == false)
1072                {
1073                        return false;
1074                }
1075        }
1076       
1077        // do nothing until delay passes to stabilize frame rate
1078        mWaitBeforeDemoStart -= evt.timeSinceLastFrame;
1079        if (mWaitBeforeDemoStart > 0.0)
1080        {
1081                // do full turn to preload geometry
1082                static Real dps = (360 / DEMO_WAIT);
1083                mCamNode->yaw(Radian(Degree(dps * evt.timeSinceLastFrame)), Ogre::Node::TS_WORLD);
1084                return true;
1085        }
1086
1087        // demo playback - replace position with stored one
1088        if (mAppState == AS_PLAYBACK)
1089        {
1090                // update time
1091                mTimeRemaining -= evt.timeSinceLastFrame;
1092
1093                // update stats
1094                ++ mDemoStats.mNumFrames;
1095                ++ mDemoStats.mTotalNumFrames;
1096                mDemoStats.mEllapsedTime += evt.timeSinceLastFrame;
1097                mDemoStats.mTotalEllapsedTime += evt.timeSinceLastFrame;
1098
1099                // set time display
1100                int m = (int)mDemoStats.mTotalEllapsedTime / 60;
1101                int s = (int)mDemoStats.mTotalEllapsedTime % 60;
1102
1103                mDemoTime->setCaption(
1104                        StringConverter::toString(m, 2, '0') + ":" +
1105                        StringConverter::toString(s, 2, '0'));
1106
1107                // set FPS display
1108                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
1109                mDemoFPSDisp->setCaption(StringConverter::toString((int)stats.lastFPS));
1110
1111                // store fps when in demo mode
1112                if (mOptions.mDemoMode)
1113                {
1114                        // save FPS
1115                        mTimeUntilNextLogWrite -= evt.timeSinceLastFrame;
1116                        if (mTimeUntilNextLogWrite <= 0.0)
1117                        {
1118                                mTimeUntilNextLogWrite += mOptions.mDemoInterval;
1119                                //const RenderTarget::FrameStats& stats = mWindow->getStatistics();
1120                                //mDemoFPS.push_back(stats.lastFPS);
1121                                mDemoFPS.push_back(mDemoStats.mNumFrames / mDemoStats.mEllapsedTime);
1122                                mDemoStats.mNumFrames = 0;
1123                                mDemoStats.mEllapsedTime = 0.0f;
1124                        }
1125                }
1126
1127                static FrameList::iterator lastFrame;
1128                if (mCurrFrame == mFrameList.begin())
1129                        lastFrame = mCurrFrame;
1130
1131                // advance to next stored frame
1132                while (mTimeRemaining <= 0.0 && mCurrFrame != mFrameList.end())
1133                {
1134                        lastFrame = mCurrFrame;
1135                        ++ mCurrFrame;
1136                        mTimeRemaining += mCurrFrame->mElapsedTime;
1137                }
1138
1139                // when reached last frame, reset and stop playback
1140                if (mCurrFrame == mFrameList.end())
1141                {
1142                        togglePlayback();
1143                        // exit app when in demo mode
1144                        if (mOptions.mDemoMode)
1145                        {
1146                                saveLog();
1147                                return false;
1148                        }
1149                }
1150                // interpolate position & orientation and modify move vectors
1151                else
1152                {
1153                       
1154                        // interpolation factor
1155                        Real factor = 1.0 - mTimeRemaining / mCurrFrame->mElapsedTime;
1156
1157                        // interpolate position and orientation
1158                        Vector3 pos = lastFrame->mPosition +
1159                                factor * (mCurrFrame->mPosition - lastFrame->mPosition);
1160
1161                        Quaternion or = Quaternion::Slerp(factor, lastFrame->mOrientation,
1162                                mCurrFrame->mOrientation);
1163
1164                        // update camera
1165                        mCamNode->setPosition(pos);
1166                        mCamNode->setOrientation(or);
1167
1168                        // update viz camera
1169                        mTopCam->moveRelative(mVizCamTransVect);
1170                        if (mTopCamFollow)
1171                        {
1172                                Vector3 toppos = mTopCam->getPosition();
1173                                Vector3 campos = mCamNode->getPosition();
1174                                mTopCam->setPosition(Vector3::ZERO);
1175                                mTopCam->setOrientation(Quaternion::IDENTITY);
1176                                mTopCam->setPosition(campos.x, toppos.y, campos.z);
1177                                mTopCam->pitch(Radian(-Math::HALF_PI));
1178                        }
1179
1180                }
1181        }
1182        else
1183        {
1184                if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys)
1185                {
1186                        // one of the input modes is immediate, so update the movement vector
1187
1188                        moveCamera();
1189
1190                }
1191        }
1192
1193        //saveFrameInfo(evt.timeSinceLastFrame);
1194        if (mAppState == AS_RECORD)
1195        {
1196                // update stats
1197                ++ mDemoStats.mTotalNumFrames;
1198                mDemoStats.mTotalEllapsedTime += evt.timeSinceLastFrame;
1199
1200                // set time display
1201                int m = (int)mDemoStats.mTotalEllapsedTime / 60;
1202                int s = (int)mDemoStats.mTotalEllapsedTime % 60;
1203
1204                mDemoTime->setCaption(
1205                        StringConverter::toString(m, 2, '0') + ":" +
1206                        StringConverter::toString(s, 2, '0'));
1207
1208                // set FPS display
1209                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
1210                mDemoFPSDisp->setCaption(StringConverter::toString((int)stats.lastFPS));
1211
1212                // store frame
1213                mFrameList.push_back(FrameInfo(mCamNode->getPosition(), mCamNode->getOrientation(), evt.timeSinceLastFrame));
1214        }
1215
1216
1217        //Camera        *followCam = mSceneMgr->getCamera("FollowCam");
1218        //if (followCam->getAutoTrackTarget() != 0)
1219        //{
1220        //      // Move the death thingy & update lookat camera FOV
1221        //      SceneNode *deathPivotNode = mSceneMgr->getSceneNode("deathPivotNode");
1222        //      SceneNode *deathNode = mSceneMgr->getSceneNode("movingNode");
1223        //      SceneNode *pivotNode = mSceneMgr->getSceneNode("pivotNode");
1224
1225        //      Vector3 fcpos = followCam->getPosition();
1226        //      Vector3 oldpos = deathNode->getWorldPosition();
1227
1228        //      Radian deltaAngle = Radian(evt.timeSinceLastFrame / mRotationPeriod * Math::TWO_PI);
1229        //      deathPivotNode->rotate(Vector3::UNIT_Y, deltaAngle);
1230        //      pivotNode->rotate(Vector3::UNIT_Y, deltaAngle * 4);
1231
1232        //      Vector3 pos = deathNode->getWorldPosition();
1233
1234        //      Real olddist = (oldpos - fcpos).length();
1235        //      Real dist = (pos - fcpos).length();
1236
1237        //      Radian oldfov = followCam->getFOVy();
1238        //      Radian fov = Radian(olddist / dist) * oldfov;
1239
1240        //      followCam->setFOVy(fov);
1241        //}
1242
1243        return true;
1244}
1245
1246bool KdTreeAppListener::frameEnded(const FrameEvent& evt)
1247{
1248        if (!mOptions.mDemoMode)
1249                updateStats();
1250
1251        return true;
1252}
1253
1254void KdTreeAppListener::switchMouseMode()
1255{
1256        mUseBufferedInputMouse = !mUseBufferedInputMouse;
1257        mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
1258}
1259void KdTreeAppListener::switchKeyMode()
1260{
1261        mUseBufferedInputKeys = !mUseBufferedInputKeys;
1262        mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse);
1263}
1264
1265void KdTreeAppListener::keyClicked(KeyEvent* e)
1266{
1267        if (e->getKeyChar() == 'm')
1268        {
1269                switchMouseMode();
1270        }
1271        else if (e->getKeyChar() == 'k')
1272        {
1273
1274                switchKeyMode();
1275        }
1276}
1277
1278/************************************************************************/
1279/* functions for recording & playback of demos                          */
1280/************************************************************************/
1281
1282//-----------------------------------------------------------------------------
1283void KdTreeAppListener::toggleRecord()
1284{
1285        // start recording
1286        if (mAppState == AS_NORMAL)
1287        {
1288                // change state
1289                mAppState = AS_RECORD;
1290
1291                // clear old recording
1292                mFrameList.clear();
1293
1294                // reset stats
1295                mDemoStats.mNumFrames = 0;
1296                mDemoStats.mTotalNumFrames = 0;
1297                mDemoStats.mEllapsedTime = 0.0f;
1298                mDemoStats.mTotalEllapsedTime = 0.0f;
1299        }
1300        // stop recording
1301        else if (mAppState == AS_RECORD)
1302        {
1303                // change state
1304                mAppState = AS_NORMAL;
1305
1306        }
1307        // update display
1308        setDemoOverlay();
1309}
1310
1311//-----------------------------------------------------------------------------
1312void KdTreeAppListener::togglePlayback()
1313{
1314        static Vector3 pos;
1315        static Quaternion or;
1316
1317        // start playback
1318        if (mAppState == AS_NORMAL && !mFrameList.empty())
1319        {
1320                // change state
1321                mAppState = AS_PLAYBACK;
1322
1323                // save old position
1324                pos = mCamNode->getPosition();
1325                or = mCamNode->getOrientation();
1326
1327                // reset demo
1328                mCurrFrame = mFrameList.begin();
1329                mTimeRemaining = mCurrFrame->mElapsedTime;
1330
1331                // reset stats
1332                mDemoStats.mNumFrames = 0;
1333                mDemoStats.mTotalNumFrames = 0;
1334                mDemoStats.mEllapsedTime = 0.0f;
1335                mDemoStats.mTotalEllapsedTime = 0.0f;
1336        }
1337        // stop playback
1338        else if (mAppState == AS_PLAYBACK)
1339        {
1340                // change state
1341                mAppState = AS_NORMAL;
1342
1343                // restore old position
1344                mCamNode->setPosition(pos);
1345                mCamNode->setOrientation(or);
1346        }
1347
1348        // update display
1349        setDemoOverlay();
1350}
1351
1352
1353//-----------------------------------------------------------------------------
1354void KdTreeAppListener::saveFrames(const String& filename, FrameList& framelist)
1355{
1356        size_t dot = filename.find_last_of(".");
1357        String ext = filename.substr(dot + 1, filename.length());
1358        if (ext == "txt")
1359                saveFramesAscii(filename, framelist);
1360        else if (ext == "bin")
1361                saveFramesBinary(filename, framelist);
1362        else
1363                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid extension for demo file: " + ext, "KdTreeApp::loadFrames");
1364}
1365
1366//-----------------------------------------------------------------------------
1367void KdTreeAppListener::saveFramesAscii(const String& filename, FrameList& framelist)
1368{
1369        // open file
1370        std::ofstream dest(filename.c_str());
1371        if (dest.is_open())
1372        {
1373                FrameList::iterator it = framelist.begin();
1374                FrameList::iterator end = framelist.end();
1375
1376                // dump values
1377                while (it != end)
1378                {
1379                        dest <<
1380                                StringConverter::toString(it->mPosition) << " " <<
1381                                StringConverter::toString(it->mOrientation) << " " <<
1382                                StringConverter::toString(it->mElapsedTime) << "\n";
1383                        ++ it;
1384                }
1385
1386                dest.close();
1387        }
1388        else
1389        {
1390                LogManager::getSingleton().logMessage("##Error##: Failed to open file for saving demo: " + filename);
1391        }
1392
1393
1394}
1395
1396//-----------------------------------------------------------------------------
1397void KdTreeAppListener::saveFramesBinary(const String& filename, FrameList& framelist)
1398{
1399        std::ofstream dest(filename.c_str(), std::ios_base::out | std::ios_base::binary);
1400
1401        if (dest.is_open())
1402        {
1403                FrameList::iterator it = framelist.begin();
1404                FrameList::iterator end = framelist.end();
1405
1406                int size = sizeof(Real);
1407
1408                // dump values
1409                while (it != end)
1410                {
1411                        dest.write((char *)&it->mPosition.x, size);
1412                        dest.write((char *)&it->mPosition.y, size);
1413                        dest.write((char *)&it->mPosition.z, size);
1414                        dest.write((char *)&it->mOrientation.w, size);
1415                        dest.write((char *)&it->mOrientation.x, size);
1416                        dest.write((char *)&it->mOrientation.y, size);
1417                        dest.write((char *)&it->mOrientation.z, size);
1418                        dest.write((char *)&it->mElapsedTime, size);
1419                        ++ it;
1420                }
1421
1422                dest.close();
1423        }
1424        else
1425        {
1426                LogManager::getSingleton().logMessage("##Error##: Failed to open file for saving demo: " + filename);
1427        }
1428}
1429
1430//-----------------------------------------------------------------------------
1431void KdTreeAppListener::loadFrames(const String& filename, FrameList& framelist)
1432{
1433        size_t dot = filename.find_last_of(".");
1434        String ext = filename.substr(dot + 1, filename.length());
1435        if (ext == "txt")
1436                loadFramesAscii(filename, framelist);
1437        else if (ext == "bin")
1438                loadFramesBinary(filename, framelist);
1439        else
1440                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid extension for demo file: " + ext, "KdTreeApp::loadFrames");
1441}
1442
1443//-----------------------------------------------------------------------------
1444void KdTreeAppListener::loadFramesAscii(const String& filename, FrameList& framelist)
1445{
1446        // open file
1447        std::ifstream src(filename.c_str());
1448        if (src.is_open())
1449        {
1450                // clear the list
1451                framelist.clear();
1452
1453                Vector3 pos;
1454                Quaternion or;
1455                Real time;
1456
1457                while (!src.eof())
1458                {
1459                        src >> pos.x;   
1460                        src >> pos.y;   
1461                        src >> pos.z;
1462
1463                        src >> or.w;
1464                        src >> or.x;
1465                        src >> or.y;
1466                        src >> or.z;
1467
1468                        src >> time;
1469
1470                        framelist.push_back(FrameInfo(pos, or, time));
1471                }
1472
1473                // HACK pop last frame, was doubled while reading
1474                framelist.pop_back();
1475
1476                src.close();
1477        }
1478        else
1479        {
1480                LogManager::getSingleton().logMessage("##Error##: Failed to open file for reading demo: " + filename);
1481        }
1482}
1483
1484//-----------------------------------------------------------------------------
1485void KdTreeAppListener::loadFramesBinary(const String& filename, FrameList& framelist)
1486{
1487        // open file
1488        std::ifstream src(filename.c_str(), std::ios_base::out | std::ios_base::binary);
1489        if (src.is_open())
1490        {
1491                // clear the list
1492                framelist.clear();
1493
1494                int size = sizeof(Real);
1495
1496                Vector3 pos;
1497                Quaternion or;
1498                Real time;
1499
1500                while (!src.eof())
1501                {
1502                        src.read((char *)&pos.x, size);
1503                        src.read((char *)&pos.y, size);
1504                        src.read((char *)&pos.z, size);
1505                        src.read((char *)&or.w, size);
1506                        src.read((char *)&or.x, size);
1507                        src.read((char *)&or.y, size);
1508                        src.read((char *)&or.z, size);
1509                        src.read((char *)&time, size);
1510
1511                        framelist.push_back(FrameInfo(pos, or, time));
1512                }
1513
1514                // HACK pop last frame, was doubled while reading
1515                framelist.pop_back();
1516
1517                src.close();
1518        }
1519        else
1520        {
1521                LogManager::getSingleton().logMessage("##Error##: Failed to open file for reading demo: " + filename);
1522        }
1523}
1524
1525//-----------------------------------------------------------------------------
1526void KdTreeAppListener::saveLog()
1527{
1528        // field separator and record separator
1529        static const String fs = ",", rs ="\n", ds = ":";
1530        // stats
1531        Real minFPS = Math::POS_INFINITY, maxFPS = 0.0, avgFPS = 0.0;
1532        String line, storedname;
1533        String demopath, demoname;
1534        StringUtil::splitFilename(mOptions.mDemoInfileName, demoname, demopath);
1535       
1536        // check if logfile exists
1537        std::ifstream logread(mOptions.mDemoLogfileName.c_str());
1538        if (logread.is_open())
1539        {
1540                // read first line, shuold start with the name of the demo
1541                // if matches, OK, otherwise do something
1542                logread >> line;
1543                storedname = line.substr(0,line.find_first_of(','));
1544                if (storedname != demoname)
1545                {
1546                        LogManager::getSingleton().logMessage(
1547                                "##Error##: Saved demo stats do not match the current demo: " +
1548                                storedname + " != " + demoname);
1549                        logread.close();
1550                        return;
1551                }
1552        }
1553        // otherwise write header
1554        else
1555        {
1556                std::ofstream logheader(mOptions.mDemoLogfileName.c_str());
1557                if (logheader.is_open())
1558                {
1559                        // demo title
1560                        logheader << demoname << fs;
1561                        // seconds
1562                        for (size_t i = 0; i < mDemoFPS.size(); i ++)
1563                        {
1564                                logheader << (i+1) << fs;
1565                        }
1566                        // minFPS, avgFPS, maxFPS, comment, record separator
1567                        logheader << "\"min FPS\"" << fs << "\"avg FPS\"" << fs << "\"max FPS\"" << fs
1568                                << "\"# Frames \"" << fs << "\"Total Time\"" << fs << "\"Comment\"" << rs;
1569                        logheader.close();
1570                }
1571                else
1572                {
1573                        LogManager::getSingleton().logMessage(
1574                                "##Error##: Failed to write log demo header to " +
1575                                mOptions.mDemoLogfileName);
1576                        return;
1577
1578                }
1579        }
1580
1581        // append current stats
1582        std::ofstream logwrite(mOptions.mDemoLogfileName.c_str(), std::ios_base::app);
1583        if (logwrite.is_open())
1584        {
1585                // demo settings
1586                logwrite << "\"" << SCENEMANAGER[mOptions.mSceneManager];
1587                if (mOptions.mSceneManager == SM_KDT || mOptions.mSceneManager == SM_KTE)
1588                {
1589                        logwrite << ds << RENDERMETHOD[mOptions.mRenderMethod] << ds << mOptions.mMaxDepth << ds
1590                                << mOptions.mKT << ds << mOptions.mKI;
1591                }
1592                else if (mOptions.mSceneManager == SM_OCM && mOptions.mRenderMethod != KdTree::KDRM_INTERNAL)
1593                {
1594                        logwrite << ds << RENDERMETHOD[(mOptions.mRenderMethod+3)%3];
1595                }
1596                logwrite << "\"" << fs;
1597                // per second stats
1598                for (std::list<Real>::iterator it = mDemoFPS.begin(); it != mDemoFPS.end(); it ++)
1599                {
1600                        if (*it < minFPS)
1601                                minFPS = *it;
1602
1603                        if (*it > maxFPS)
1604                                maxFPS = *it;
1605
1606                        //avgFPS += *it;
1607
1608                        logwrite << (int)(*it) << fs;
1609
1610                }
1611                //avgFPS /= mDemoFPS.size();
1612                avgFPS = mDemoStats.mTotalNumFrames / mDemoStats.mTotalEllapsedTime;
1613                // minFPS, avgFPS, maxFPS, comment, record separator
1614                logwrite << (int)minFPS << fs << (int)avgFPS << fs << (int)maxFPS << fs
1615                        << mDemoStats.mTotalNumFrames << fs << mDemoStats.mTotalEllapsedTime << fs
1616                        << "\"" << mOptions.mComment << "\"" << rs;
1617                logwrite.close();
1618        }
1619        else
1620        {
1621                LogManager::getSingleton().logMessage(
1622                        "##Error##: Failed to write demo log to " +
1623                        mOptions.mDemoLogfileName);
1624        }
1625}
1626
1627//-----------------------------------------------------------------------------
1628void KdTreeAppListener::saveFrameInfo(Real elapsedTime)
1629{
1630        mFrameList.push_back(FrameInfo(mCamNode->getPosition(), mCamNode->getOrientation(), elapsedTime));
1631}
1632
1633//-----------------------------------------------------------------------------
1634void KdTreeAppListener::setDemoOverlay()
1635{
1636        // init overlay if not present
1637        if (!mDemoOverlay || !mDemoStatus || !mDemoTime)
1638        {
1639                OGRE_DELETE(mDemoOverlay);
1640                OGRE_DELETE(mDemoStatus);
1641                OGRE_DELETE(mDemoTime);
1642
1643                mDemoStatus = OverlayManager::getSingleton().createOverlayElement("Panel", "KdTree/DemoStatus");
1644                mDemoStatus->setMetricsMode(GMM_PIXELS);
1645                mDemoStatus->setDimensions(32, 32);
1646                mDemoStatus->setLeft(64);
1647
1648                mDemoTime = static_cast<TextAreaOverlayElement *>
1649                        (OverlayManager::getSingleton().createOverlayElement("TextArea", "KdTree/DemoTime"));
1650                mDemoTime->setMetricsMode(GMM_PIXELS);
1651                mDemoTime->setTop(6);
1652                mDemoTime->setLeft(104);
1653                mDemoTime->setFontName("TrebuchetMSBold");
1654                mDemoTime->setCharHeight(24.0);
1655                mDemoTime->setCaption("00:00");
1656
1657                mDemoFPSDisp = static_cast<TextAreaOverlayElement *>
1658                        (OverlayManager::getSingleton().createOverlayElement("TextArea", "KdTree/DemoFPS"));
1659                mDemoFPSDisp->setMetricsMode(GMM_PIXELS);
1660                mDemoFPSDisp->setAlignment(TextAreaOverlayElement::Right);
1661                mDemoFPSDisp->setTop(6);
1662                mDemoFPSDisp->setLeft(48);
1663                mDemoFPSDisp->setFontName("TrebuchetMSBold");
1664                mDemoFPSDisp->setCharHeight(24.0);
1665                mDemoFPSDisp->setCaption("0");
1666
1667                PanelOverlayElement *demoCont = static_cast<PanelOverlayElement *>
1668                        (OverlayManager::getSingleton().createOverlayElement("Panel", "KdTree/DemoTimePanel"));
1669                demoCont->setMetricsMode(GMM_PIXELS);
1670                demoCont->setHorizontalAlignment(GHA_CENTER);
1671                demoCont->setVerticalAlignment(GVA_TOP);
1672                demoCont->setTop(5);
1673                demoCont->setLeft(-80);
1674                demoCont->setDimensions(160, 32);
1675                demoCont->addChild(mDemoFPSDisp);
1676                demoCont->addChild(mDemoStatus);
1677                demoCont->addChild(mDemoTime);
1678                //demoCont->setMaterialName("Core/StatsBlockCenter");
1679
1680                mDemoOverlay = OverlayManager::getSingleton().create("KdTree/DemoOverlay");
1681                mDemoOverlay->setZOrder(500);
1682                //mDemoOverlay->add2D(static_cast<PanelOverlayElement *>(mDemoStatus));
1683                mDemoOverlay->add2D(demoCont);
1684        }
1685
1686        switch(mAppState)
1687        {
1688        case AS_NORMAL:
1689                mDemoOverlay->hide();
1690                break;
1691        case AS_PLAYBACK:
1692                mDemoStatus->setMaterialName("KdTree/DemoPlayButton");
1693                mDemoTime->setColourTop(ColourValue(0.5, 0.7, 0.5));
1694                mDemoTime->setColourBottom(ColourValue(0.3, 0.5, 0.3));
1695                mDemoFPSDisp->setColourTop(ColourValue(0.5, 0.7, 0.5));
1696                mDemoFPSDisp->setColourBottom(ColourValue(0.3, 0.5, 0.3));
1697                mDemoOverlay->show();
1698                break;
1699        case AS_RECORD:
1700                mDemoStatus->setMaterialName("KdTree/DemoRecordButton");
1701                mDemoTime->setColourTop(ColourValue(0.7, 0.5, 0.5));
1702                mDemoTime->setColourBottom(ColourValue(0.5, 0.3, 0.3));
1703                mDemoFPSDisp->setColourTop(ColourValue(0.7, 0.5, 0.5));
1704                mDemoFPSDisp->setColourBottom(ColourValue(0.5, 0.3, 0.3));
1705                mDemoOverlay->show();
1706                break;
1707        default:
1708            break;
1709        }
1710
1711}
Note: See TracBrowser for help on using the repository browser.