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

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