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

Revision 1285, 48.5 KB checked in by szydlowski, 18 years ago (diff)

saving and loading entities to file

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