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

Revision 1296, 51.3 KB checked in by szydlowski, 18 years ago (diff)

Implemented PVS support in kdtree scene manager - not complete, defunct
modified BoundingBoxConverter? to work with KdTreeSceneManager?

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