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

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