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

Revision 1258, 46.3 KB checked in by szydlowski, 18 years ago (diff)

pre-big-changes-backup (TM)
working state before attempt to include terrain rendering

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