source: GTP/trunk/App/Demos/Vis/HillyTerrain/OGRE/TerrainFrameListener.cpp @ 2305

Revision 2305, 56.7 KB checked in by mattausch, 17 years ago (diff)
Line 
1#include <OgreNoMemoryMacros.h>
2#include <CEGUI/CEGUI.h>
3#include <../CEGUIRenderer/include/OgreCEGUIRenderer.h>
4#include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h>
5#include <../CEGUIRenderer/include/OgreCEGUITexture.h>
6#include <OgreMemoryMacros.h>
7#include "TerrainFrameListener.h"
8#include "OgrePlatformQueryManager.h"
9#include "VisibilityInfo.h"
10#include "OgreOcclusionQueriesQueryManager.h"
11#include "TestCullingTerrainApplication.h"
12#include <string>
13
14
15//-- captions for overlays
16String TerrainFrameListener::msAlgorithmCaptions[] =
17{
18        "Coherent Hierarchical Culling",
19        "View Frustum Culling",
20        "Random Update Culling",
21        "Stop and Wait Culling",
22        "Standard Rendering"
23};
24
25//-- captions for overlays
26String TerrainFrameListener::msApprevAlgorithmCaptions[] =
27{
28        "CHC",
29        "VFC",
30        "RUC",
31        "SWC",
32        "DEF"
33};
34
35
36String TerrainFrameListener::msQueryTypeCaptions[] =
37{
38        "from camera",
39        "from viewpoint"
40};
41
42String TerrainFrameListener::msQueryRelativeVisCaptions[] =
43{
44        "visible pixels",
45        "relative visibility"
46};
47
48String TerrainFrameListener::msQueryMethodCaptions[] =
49{
50        "occlusion queries",
51        "item buffer"
52};
53
54Real TerrainFrameListener::msObjectTerrainOffsets[] =
55{
56        0,
57        -0.1,
58        //7,
59        0
60};
61
62Real TerrainFrameListener::msObjectScales[] =
63{
64        0.07,
65        0.03,
66        //0.1,
67        0.03
68};
69
70String TerrainFrameListener::msObjectCaptions[] =
71{
72        "robot",
73        "athene",
74        "natFX_Tree1_LOD2",
75        //"tree2",
76        //"HongKong_Tower",
77        "ninja"
78        //"ogrehead"
79};
80
81// output file for frame info
82const char* frames_out_filename = "frame.out";
83// output file for object positions / orientations
84const char* objects_out_filename = "objects.out";
85       
86std::ofstream video_out("video.lst");
87
88// if we are recording a demo
89static const bool DEMO_HACK = false;
90
91//using namespace GtpVisibility;
92
93//-----------------------------------------------------------------------
94TerrainFrameListener::TerrainFrameListener(RenderWindow* win, Camera* cam,
95                                                                                   SceneManager *sceneManager,
96                                                                                   CEGUI::Renderer *renderer,
97                                                                                   TerrainContentGenerator *sceneGenerator,
98                                                                                   Camera *vizCamera,
99                                                                                   SceneNode *camNode,
100                                                                                   Light *sunLight,
101                                                                                   TestCullingTerrainApplication *app):
102mCamera(cam),
103mWindow(win),
104mNumScreenShots(0),
105mTimeDelay(0),
106mSceneDetailIndex(0),
107mMoveScale(0.0f),
108mRotScale(0.0f),
109mTranslateVector(Vector3::ZERO),
110mAniso(1),
111mFiltering(TFO_BILINEAR),
112mGUIRenderer(renderer),
113mSceneMgr(sceneManager),
114mCurrentObject(NULL),
115mTerrainContentGenerator(sceneGenerator),
116mVisibilityThreshold(0),
117mAssumedVisibility(0),
118mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING),
119mNodeVizMode(NODEVIZ_NONE),
120mVizCameraHeight(Real(2000.0)),
121mCamNode(camNode),
122mAppState(WALKTHROUGH),
123mCurrentFrame(0),
124mReplayTimeElapsed(0),
125mRotateSpeed(72),
126mMoveSpeed(50),
127mVizCamera(vizCamera),
128mStatsOn(true),
129mShutdownRequested(false),
130mLMouseDown(false),
131mRMouseDown(false),
132mShowOctree(false),
133mShowViewCells(false),
134mUseDepthPass(false),
135mTestGeometryForVisibleLeaves(false),
136mShowVisualization(false),
137mCullCamera(false),
138mRecordFrames(false),
139mShowShadows(false),
140mShowHelp(false),
141mDisplayCameraDetails(false),
142mVisualizeCulledNodes(false),
143mSunLight(sunLight),
144mShiftPressed(false),
145mShowQueryStats(false),
146mQueryManager(NULL),
147mVisibilityManager(NULL),
148mDelayedQueriesIssued(0.0),
149mDelayedTraversedNodes(0.0),
150mCurrentObjectType(0),
151mApplication(app),
152mUseAnimation(false),
153mDeleteObjects(false),
154mUseItemBuffer(false),
155mItemBufferMode(GtpVisibility::QueryManager::PATCH_VISIBILITY),
156mRecordVideo(false),
157mPureRenderTimeFps(0.0),
158mNumVideoFrames(0),
159mPrecomputedFps(0),
160mRecordDemo(false),
161mSavePrecomputedFps(false),
162mUseBufferedInputMouse(false),
163mVizScale(25),
164mUseViewCells(false),
165mViewCellsLoaded(false),
166mUseVisibilityFilter(false),
167mFloorDist(2),
168mFlushQueue(false)
169{
170        //mInputDevice = PlatformManager::getSingleton().createInputReader();
171        //mInputDevice->initialise(win, true, true);
172
173        mEventProcessor = new EventProcessor();
174       
175        mEventProcessor->initialise(win);
176        mEventProcessor->startProcessingEvents();
177        mEventProcessor->addMouseListener(this);
178        mEventProcessor->addMouseMotionListener(this);
179        mEventProcessor->addKeyListener(this);
180
181        mInputDevice = mEventProcessor->getInputReader();       
182
183        mInputDevice->setBufferedInput(true, mUseBufferedInputMouse);
184
185        // create ray query executor, used to place objects in terrain
186        mRayQueryExecutor = new RayQueryExecutor(mSceneMgr);
187       
188
189        //////////
190        //-- overlays
191       
192        mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
193        mHelpOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/HelpOverlay");
194        mQueryOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/QueryOverlay");
195        mCullStatsOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/CullStatsOverlay");
196
197        String ext = "Example/Visibility/";
198
199        //-- overlays
200   
201        initVisStatsOverlay(); // visibility stats overlay
202        initHelpOverlay();     // help overlay
203        initQueryOverlay();    // visibility query stats overlay
204       
205        // show stats overlays
206        if (!DEMO_HACK)
207        {
208                showStats(true);
209        }
210        else
211        {
212                mMyStatsOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/MyStatsOverlay");
213                mMyStatsAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/MyAlgorithmInfo");
214                mMyStatsAlgorithmInfo->setCaption("");
215       
216                const int top = 10;
217                mMyStatsAlgorithmInfo->setTop(top);
218
219                char str[100]; sprintf(str,": %d", 0);
220                mMyStatsFpsInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/MyFpsInfo");
221                mMyStatsFpsInfo->setCaption(str);
222
223                mMyStatsOverlay->show();
224        }
225
226        // loading view cells overlay
227        mLoadingOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/LoadingOverlay");
228        mMyLoadingInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Loading/MyLoadingInfo");
229        mMyLoadingInfo->setCaption("loading view cells ...");
230
231        mLoadingOverlay->hide();
232
233        // note: larger magnification for terrain to show single objects
234        if (TestCullingTerrainApplication::msShowHillyTerrain)
235                mVizScale = 25;
236        else
237                mVizScale = 1;
238
239        // the scale factor for the visualized bounding boxes
240        mSceneMgr->setOption("NodeVizScale", &mVizScale);
241       
242        /////////
243        //-- set the current culling algorithm type
244        //setAlgorithm(mApplication->mAlgorithm);
245
246        bool isNormalExecution;
247               
248        mSceneMgr->getOption("NormalExecution", &isNormalExecution);
249        if (isNormalExecution)
250        {
251                // no algorithm
252                mCurrentAlgorithm =
253                        GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS;
254        }
255        else
256        {
257                mSceneMgr->getOption("Algorithm", &mCurrentAlgorithm);
258        }
259       
260        applyCurrentAlgorithm();
261       
262        ///////////////////////////////
263
264        // set scene manager options
265        setTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
266
267        //mSceneMgr->setOption("UseDepthPass", &mUseDepthPass);
268        mSceneMgr->getOption("UseDepthPass", &mUseDepthPass);
269
270        if (mUseDepthPass)
271                mUseDepthPassInfo->setCaption(": true");
272        else
273                mUseDepthPassInfo->setCaption(": false");
274       
275        mSceneMgr->getOption("FlushQueue", &mFlushQueue);
276       
277        if (mFlushQueue)
278                LogManager::getSingleton().logMessage("initial setting: flushing queue");
279        else
280                LogManager::getSingleton().logMessage("initial setting: not flushing queue");
281
282        mSceneMgr->setOption("ShowOctree", &mShowOctree);
283        mSceneMgr->setOption("ShowViewCells", &mShowViewCells);
284        mSceneMgr->setOption("CullCamera", &mCullCamera);
285        mSceneMgr->setOption("PrepareVisualization", &mShowVisualization);
286       
287        applyObjectType();
288
289        // initialise timer
290        mTimer = Root::getSingleton().getTimer();
291        mTimeFrameEnded = mTimeFrameStarted = mTimer->getMilliseconds();
292       
293        // init view cell parameters
294        mSceneMgr->setOption("UseVisibilityFilter", &mUseVisibilityFilter);
295
296        // reset statistics
297        mWalkthroughStats.Reset();
298
299}
300//-----------------------------------------------------------------------
301void TerrainFrameListener::switchMouseMode()
302{
303        mUseBufferedInputMouse = !mUseBufferedInputMouse;
304        mInputDevice->setBufferedInput(true, mUseBufferedInputMouse);
305
306        if (!mUseBufferedInputMouse)
307                CEGUI::MouseCursor::getSingleton().hide();
308        else
309                CEGUI::MouseCursor::getSingleton().show();
310}
311//-----------------------------------------------------------------------
312TerrainFrameListener::~TerrainFrameListener()
313{
314        OGRE_DELETE(mRayQueryExecutor);
315        OGRE_DELETE(mEventProcessor);
316        OGRE_DELETE(mQueryManager);
317}
318//-----------------------------------------------------------------------
319void TerrainFrameListener::mouseMoved(MouseEvent *e)
320{
321        // Update CEGUI with the mouse motion
322    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() *
323                mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight());
324}
325//-----------------------------------------------------------------------
326void TerrainFrameListener::mousePressed(MouseEvent* e)
327{
328        // Left mouse button down
329        if (e->getButtonID() & InputEvent::BUTTON0_MASK)
330        {
331                CEGUI::MouseCursor::getSingleton().hide();
332
333                // Setup the ray scene query
334                Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY());
335                Real val = Math::RangeRandom(0, 360); // random rotation
336
337                // get results, create a node/entity on the position
338                mCurrentObject =
339                        mTerrainContentGenerator->GenerateSceneObject(mouseRay.getOrigin(),
340                                                                                                                  Vector3(val, 0, 0),
341                                                                                                                  msObjectCaptions[mCurrentObjectType]);
342               
343                mLMouseDown = true;
344        }
345        // Right mouse button down
346        /*else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
347        {
348         CEGUI::MouseCursor::getSingleton().hide();
349         mRMouseDown = true;
350        }*/
351}
352//-----------------------------------------------------------------------
353void TerrainFrameListener::mouseDragDropped(MouseEvent* e)
354{
355        // Left mouse button up
356    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
357    {
358                CEGUI::MouseCursor::getSingleton().show();
359               
360            mLMouseDown = false;
361    }
362    // Right mouse button up
363    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
364    {
365        CEGUI::MouseCursor::getSingleton().show();
366
367                mRMouseDown = false;
368    }
369}
370//-----------------------------------------------------------------------
371void TerrainFrameListener::mouseReleased(MouseEvent* e)
372{
373    // Left mouse button up
374    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
375    {
376                CEGUI::MouseCursor::getSingleton().show();
377               
378                // start animation: only robot has animation phases
379                if (mCurrentObject && (mCurrentObjectType == TestCullingTerrainApplication::ROBOT))
380                {
381                        // HACK: not neccesary the last element
382                        Entity *ent = mTerrainContentGenerator->GetGeneratedEntities()->back();
383                        EntityState *entState = new EntityState(ent, EntityState::MOVING, Math::RangeRandom(0.5, 1.5));
384                        mApplication->getEntityStates().push_back(entState);
385                }
386
387            mLMouseDown = false;
388    }
389    // Right mouse button up
390    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
391    {
392        CEGUI::MouseCursor::getSingleton().show();
393
394        mRMouseDown = false;
395    }
396}
397//-----------------------------------------------------------------------
398void TerrainFrameListener::mouseDragged(MouseEvent *e)
399{
400        // If we are dragging the left mouse button.             
401        if (mLMouseDown)
402    {
403                if (!mCurrentObject)
404                        return;
405
406                Vector3 queryResult;
407                Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY());
408
409                if (mRayQueryExecutor->executeRayQuery(&queryResult, mouseRay))
410                {
411                        // apply offset so object is ON terrain
412                        queryResult.y += msObjectTerrainOffsets[mCurrentObjectType];
413                        mCurrentObject->setPosition(queryResult);
414                }
415        }
416}
417//-----------------------------------------------------------------------
418bool TerrainFrameListener::frameStarted(const FrameEvent &evt)
419{
420        if (mWindow->isClosed())
421        {
422        return false;
423        }
424       
425        if (mDeleteObjects)
426        {
427                mApplication->deleteEntityStates();
428                mTerrainContentGenerator->RemoveGeneratedObjects();
429                mDeleteObjects = false;
430        }
431
432        if (mUseAnimation)
433        {
434                // update animation phases
435                mApplication->updateAnimations(evt.timeSinceLastFrame);
436        }
437
438        if (mDisplayCameraDetails)  // Print camera details
439    {       
440        mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) +
441                        " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation()));
442    }
443
444        //-- setup what is needed for immediate mouse/key movement
445        if (mTimeDelay >= 0)
446        {
447                mTimeDelay -= evt.timeSinceLastFrame;
448        }
449       
450        // If this is the first frame, pick a speed
451        if (evt.timeSinceLastFrame == 0)
452        {
453                mMoveScale = 1;
454                mRotScale = 0.1;
455        }
456        // Otherwise scale movement units by time passed since last frame
457        else
458        {
459                // Move about 100 units per second,
460                mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
461                // Take about 10 seconds for full rotation
462                mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
463        }
464
465        mRotX = 0;
466        mRotY = 0;
467        mTranslateVector = Vector3::ZERO;
468
469        if (!processUnbufferedKeyInput(evt))
470        {
471                return false;
472        }
473        if (!mUseBufferedInputMouse)
474        {
475                if (!processUnbufferedMouseInput(evt))
476                {       
477                        return false;   
478                }
479        }
480
481        if (mShowVisualization)
482        {
483                ////////////////
484                //-- set parameters for visualization
485
486                // important for visualization => draw octree bounding boxes
487                if (0) mSceneMgr->setOption("ShowOctree", &mShowVisualization);
488               
489                ///////////////
490                //-- setup visualization camera
491
492                mVizCamera->setPosition(0, 0, 0);
493                mVizCamera->setOrientation(Quaternion::IDENTITY);
494
495                Vector3 camPos = mCamNode->getPosition();
496                mVizCamera->setPosition(camPos.x, mVizCameraHeight, camPos.z);
497
498                // point down -Z axis
499                mVizCamera->pitch(Radian(Degree(270.0)));
500
501                // rotation arounnd X axis
502                mVizCamera->yaw(Math::ATan2(-mCamera->getDerivedDirection().x,
503                        -mCamera->getDerivedDirection().z));
504               
505                const float moveFactor = 200;
506                // move by a constant so view plane is on bottom of viewport
507                mVizCamera->moveRelative(Vector3(0, moveFactor, 0));
508        }
509        else
510        {
511                // frame start time
512                mTimeFrameStarted = mTimer->getMilliseconds();
513        }
514
515        //////////////
516        //-- set application state
517
518        switch (mAppState)
519        {
520        case REPLAY:
521                /// set the current camera data to loaded frame information
522                setCurrentFrameInfo(evt.timeSinceLastFrame);
523
524                // HACK for demo: save new frame rates for the same walkthrough
525                if (mSavePrecomputedFps)
526                {
527                        addFrameInfo(mPrecomputedFpsFrameInfo, mCamNode, evt.timeSinceLastFrame);
528                }
529
530                break;
531        case WALKTHROUGH:
532                //-- recording the camera settings per frame
533                if (mRecordFrames)
534                {
535                        addFrameInfo(mFrameInfo, mCamNode, evt.timeSinceLastFrame);
536                        // print recording message
537                        mWindow->setDebugText("Recording frame " +
538                                StringConverter::toString((int)mFrameInfo.size() - 1));
539                }       
540                // move camera according to input
541                moveCamera();
542
543                // clamp camera so we always walk along the terrain
544                if (TestCullingTerrainApplication::msShowHillyTerrain)
545                {
546                        mApplication->Clamp2Terrain(mCamNode, 5);
547                        //Ogre::LogManager::getSingleton().logMessage("clamp to terrain");
548                }
549                else
550                {
551                        mApplication->Clamp2FloorPlane(mFloorDist);
552                        //Ogre::LogManager::getSingleton().logMessage("clamp to floor");
553                }
554
555                break;
556
557        default:
558                Ogre::LogManager::getSingleton().logMessage("should not come here");
559                break;
560        };     
561
562        return true;
563}
564//-----------------------------------------------------------------------
565void TerrainFrameListener::applyVisibilityQuery(bool fromPoint,
566                                                                                                bool relativeVisibility,
567                                                                                                bool useItemBuffer)
568{
569        int itemBufferMode = useItemBuffer ? mItemBufferMode : 0;
570       
571        int queryModes = 0;
572        queryModes |= GtpVisibility::QueryManager::PATCH_VISIBILITY;
573        queryModes |= GtpVisibility::QueryManager::GEOMETRY_VISIBILITY;
574        queryModes |= GtpVisibility::QueryManager::NODE_VISIBILITY;
575
576        // no visibility manager available => no visibility scene manager, return
577        GtpVisibility::VisibilityManager *visManager = NULL;   
578        if (!mSceneMgr->getOption("VisibilityManager", &visManager))
579        {
580                Ogre::LogManager::getSingleton().logMessage("no vismanager found");
581                return;
582        }
583
584        PlatformHierarchyInterface *hierarchyInterface = NULL;
585        if (!mSceneMgr->getOption("HierarchyInterface", &hierarchyInterface))
586        {
587                Ogre::LogManager::getSingleton().logMessage("no hierarchy interface found");
588                return;
589        }
590
591        const bool approximateVisibility = false;
592
593        mQueryManager = new OcclusionQueriesQueryManager(hierarchyInterface,
594                                                                                                         mWindow->getViewport(0),
595                                                                                                         queryModes,
596                                                                                                         itemBufferMode);
597
598        visManager->SetQueryManager(mQueryManager);
599
600        NodeInfoContainer visibleNodes;
601        MeshInfoContainer visibleGeometry;
602        PatchInfoContainer visiblePatches;
603
604        if (fromPoint)
605        {
606                mQueryManager->ComputeFromPointVisibility(mCamNode->getPosition(),
607                                                                                                  &visibleNodes,
608                                                                                                  &visibleGeometry,
609                                                                                                  &visiblePatches,
610                                                                                                  relativeVisibility,
611                                                                                                  approximateVisibility);
612        }
613        else
614        {
615                mQueryManager->ComputeCameraVisibility(*mCamera,
616                                                                                           &visibleNodes,
617                                                                                           &visibleGeometry,
618                                                                                           &visiblePatches,
619                                                                                           relativeVisibility,
620                                                                                           approximateVisibility);
621        }
622               
623        std::stringstream d;
624        d << "Query mode: " << queryModes << ", "
625          << msQueryTypeCaptions[fromPoint ?  1 : 0].c_str() << " "
626          << msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str() << " "
627      << msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str();
628        LogManager::getSingleton().logMessage(d.str());
629
630
631        float averageNodeVis = 0, averageGeometryVis = 0, averagePatchVis = 0;
632        int geomSize = 0, nodesSize = 0, patchSize = 0;
633
634        /////////////////
635        //-- apply queries on geometry level
636
637        MeshInfoContainer::iterator geomIt, geomIt_end = visibleGeometry.end();
638
639        for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt)
640        {
641                // add if not 0
642                if ((*geomIt).GetVisiblePixels())
643                {
644                        float vis = relativeVisibility ?
645                                (*geomIt).ComputeRelativeVisibility() : (float)(*geomIt).GetVisiblePixels();
646       
647                        averageGeometryVis += vis;
648                        ++ geomSize;
649                       
650                        std::stringstream d;
651                        d << "Geometry " << geomSize << " id: " << (*geomIt).GetSource()->getSubEntity(0)->getId()
652                          << " visibility: "  << (*geomIt).GetVisiblePixels() << ", " << (*geomIt).GetProjectedPixels();
653                        LogManager::getSingleton().logMessage(d.str());
654                }
655        }
656
657
658        ////////////////
659        //-- apply queries on node level
660
661        NodeInfoContainer::iterator nodesIt, nodesIt_end = visibleNodes.end();
662
663        for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++nodesIt)
664        {
665                // add if not 0
666                if ((*nodesIt).GetVisiblePixels())
667                {
668                        float vis = relativeVisibility ?
669                                (*nodesIt).ComputeRelativeVisibility() : (float)(*nodesIt).GetVisiblePixels();
670               
671                        averageNodeVis += vis;
672                        ++ nodesSize;
673
674                        std::stringstream d; d << "Node visibility: " << vis;
675                        LogManager::getSingleton().logMessage(d.str());
676                }       
677        }
678
679
680        ////////////////
681        //-- apply queries on patch level
682
683
684        PatchInfoContainer::iterator patchIt, patchIt_end = visiblePatches.end();
685
686        for (patchIt = visiblePatches.begin(); patchIt != patchIt_end; ++ patchIt)
687        {
688                // add if not 0
689                if ((*patchIt).GetVisiblePixels())
690                {
691                        float vis = relativeVisibility ?
692                                (*patchIt).ComputeRelativeVisibility() : (float)(*patchIt).GetVisiblePixels();
693               
694                        averagePatchVis += vis;
695                        ++ patchSize;
696
697                        std::stringstream d; d << "Patch visibility: " << vis;
698                        LogManager::getSingleton().logMessage(d.str());
699                }       
700        }
701
702        ///////////////////////////////////////////////////////////////
703        //-- update visibility queries stats
704
705        if (nodesSize)
706                averageNodeVis /= (float)nodesSize;
707        if (geomSize)
708                averageGeometryVis /= (float)geomSize;
709        if (patchSize)
710                averagePatchVis /= (float)patchSize;
711
712
713    try
714        {
715                char str[100];
716               
717                sprintf(str, ": %s, %s, %s",
718                                msQueryTypeCaptions[fromPoint ?  1 : 0].c_str(),
719                                msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str(),
720                                msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str());
721
722                mQueryTypeInfo->setCaption(str);
723
724                sprintf(str, ": %d", (int)nodesSize);
725                mQueryVisibleNodesInfo->setCaption(str);
726       
727                sprintf(str,": %d", (int)geomSize);
728                mQueryVisibleGeometryInfo->setCaption(str);
729               
730                sprintf(str,": %d", (int)patchSize);
731                mQueryVisiblePatchInfo->setCaption(str);
732
733                sprintf(str,": %3.3f", averageNodeVis);
734                mQueryNodeVisibilityInfo->setCaption(str);
735
736                sprintf(str,": %3.3f", averageGeometryVis);
737                mQueryGeometryVisibilityInfo->setCaption(str);
738
739                sprintf(str,": %3.3f", averagePatchVis);
740                mQueryPatchVisibilityInfo->setCaption(str);
741        }
742        catch (...)
743        {
744                // ignore
745        }
746
747        // show the results
748        if (!mShowQueryStats && !mShowHelp)
749        {
750                mQueryOverlay->show();
751                mShowQueryStats = true;
752        }
753
754        delete mQueryManager;
755}
756
757
758bool TerrainFrameListener::processUnbufferedMouseInput(const FrameEvent& evt)
759{
760        // Rotation factors, may not be used if the second mouse button is pressed.
761    // If the second mouse button is pressed, then the mouse movement results in
762    // sliding the camera, otherwise we rotate.
763    if (mInputDevice->getMouseButton(1))
764    {
765                mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
766                mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
767        }
768        else
769        {
770                mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
771                mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
772        }
773
774        return true;
775}
776//-----------------------------------------------------------------------
777bool TerrainFrameListener::frameEnded(const FrameEvent& evt)
778{
779        if (mShutdownRequested)
780                return false;
781
782        // timer end time
783        if (!mShowVisualization)
784        {
785                mTimeFrameEnded = mTimer->getMilliseconds();
786        }
787
788    updateStats();
789
790        if (mRecordVideo) // record current frame
791        {
792                takeVideoFrame(video_out);
793        }
794
795        //-- IMPORTANT: must be set, otherwise terrain is not rendered correctly
796        mSceneMgr->endFrame();
797
798        if (mTimeDelay <= 0) // simulates approx. one second
799                mTimeDelay = 1.0;
800
801        return true;
802}
803//-----------------------------------------------------------------------
804void TerrainFrameListener::moveCamera()
805{
806        // move node rather than camera so orientation is right in the visualization
807        mCamNode->yaw(mRotX, Ogre::Node::TS_WORLD);
808        //mCamNode->rotate(Vector3(0,1,0), mRotX, Ogre::Node::TS_WORLD);
809        mCamNode->pitch(mRotY);
810
811        mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector);
812}
813//-----------------------------------------------------------------------
814void TerrainFrameListener::writeFrames(const std::string filename,
815                                                                           const FrameInfoContainer &frameInfo) const
816{
817        std::ofstream ofstr(filename.c_str());
818        std::vector<frame_info>::const_iterator it, it_end;
819        it_end = frameInfo.end();
820
821        int i = 0;
822
823        for (it = frameInfo.begin(); it < it_end; ++ it, ++ i)
824        {
825                ofstr << StringConverter::toString((*it).position) << " "
826                          << StringConverter::toString((*it).orientation) << " "
827                          << StringConverter::toString((*it).timeElapsed) << " "
828                          << StringConverter::toString((*it).fps) << "\n";
829        }
830
831        std::stringstream d; d << "saved " << i << " frames to file " << filename;
832        Ogre::LogManager::getSingleton().logMessage(d.str());
833
834        ofstr.close();
835}
836//-----------------------------------------------------------------------
837void TerrainFrameListener::loadFrames(const std::string filename, 
838                                                                          FrameInfoContainer &frameInfo)
839{
840        std::ifstream ifstr(filename.c_str());
841        char line[256];
842        frame_info info;
843
844        // reset current values
845        frameInfo.clear();
846       
847        mCurrentFrame = 0;
848        int i = 0;
849        while (!ifstr.eof())
850        {
851                ifstr.getline(line, 256);
852                sscanf(line, "%f %f %f %f %f %f %f %f %f", &info.position.x, &info.position.y, &info.position.z,
853                           &info.orientation.w, &info.orientation.x, &info.orientation.y, &info.orientation.z,
854                           &info.timeElapsed, &info.fps);
855               
856                mFrameInfo.push_back(info);
857               
858                // std::stringstream d; d << StringConverter::toString(info.position) << " " << StringConverter::toString(info.orientation);
859                // LogManager::getSingleton().logMessage(d.str());
860                ++ i;
861        }
862       
863        std::stringstream d;
864        d << "loaded " << i << " frames from file " << filename;
865        Ogre::LogManager::getSingleton().logMessage(d.str());
866
867        ifstr.close();
868}
869//-----------------------------------------------------------------------
870void TerrainFrameListener::nextAppState()
871{
872        mCurrentFrame = 0;
873        int lastState = mAppState;
874
875        // transition to the next state
876        mAppState = (mAppState + 1) % STATE_NUM;
877
878        // if last state was replay state: post process
879        if (lastState == REPLAY)
880        {
881        // reset debug text
882                mWindow->setDebugText("");
883                               
884                // hack for producing demo:
885                // we produced precomputed fps during the last replay =>
886                // save them to file
887                if (mSavePrecomputedFps) //!mPrecomputedFpsFrameInfo.empty())
888                {
889                        std::string filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out";
890
891                        writeFrames(filename, mPrecomputedFpsFrameInfo);
892                        mPrecomputedFpsFrameInfo.clear();
893                }
894
895                std::stringstream d;
896                mWalkthroughStats.Print(d, msApprevAlgorithmCaptions[mCurrentAlgorithm]);
897               
898                LogManager::getSingleton().logMessage(d.str());
899        }
900       
901        //-- replay recorded walkthrough
902        if (mAppState == REPLAY)
903        {
904                // no standard recording during replay
905                mRecordFrames = false;
906
907                // no stats information
908                mWindow->setDebugText("");
909
910                // clear previous walktrough
911                mFrameInfo.clear();
912
913                std::string filename;
914               
915                // if recording demo,
916                // we use precomputed fps which corresponds to current method,
917                // e.g., for chc we load precomputed chc fps from disc.
918                if (mRecordDemo)
919                {
920                        filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out";
921                }
922                else // standard filename
923                {
924                        filename = frames_out_filename;
925                }
926
927                //-- load recorded walkthrough from disk
928                loadFrames(filename, mFrameInfo);
929               
930               
931                // if there are still no recorded frames,
932                // no walkthrough was recorded => set next state
933                if (mFrameInfo.empty())
934                {
935                        nextAppState();
936                }
937                else // actual replay
938                {
939                        mWindow->setDebugText("Replay");
940                       
941                        // reset, because we measure fps stats during walkthrough
942                        // (warning: average fps broken)
943                        mWindow->resetStatistics();
944                        mWalkthroughStats.Reset();
945
946                        //-- initialise frame data
947                        mReplayTimeElapsed = 0;
948
949                        mCamNode->setPosition(mFrameInfo[0].position);
950                        mCamNode->setOrientation(mFrameInfo[0].orientation);
951                }
952        }
953
954}
955//-----------------------------------------------------------------------
956void TerrainFrameListener::toggleRecord()
957{
958        mRecordFrames = !mRecordFrames;
959
960        if (mRecordFrames)
961        {
962                // starting new recording => clear old frame info
963                mFrameInfo.clear();
964        }
965        else // recording just ended => write frame info to file
966        {
967                writeFrames(frames_out_filename, mFrameInfo);
968                mWindow->setDebugText("");
969        }
970}
971//-----------------------------------------------------------------------
972void TerrainFrameListener::changeThreshold(int incr)
973{
974        mVisibilityThreshold += incr;
975
976        if (mVisibilityThreshold < 0)
977        {
978                mVisibilityThreshold = 0;
979        }
980
981        char str[100]; sprintf(str,": %d", mVisibilityThreshold);
982
983        mSceneMgr->setOption("Threshold", &mVisibilityThreshold);
984        mThresholdInfo->setCaption(str);
985}
986//-----------------------------------------------------------------------
987void TerrainFrameListener::changeAssumedVisibility(int incr)
988{
989        mAssumedVisibility += incr;
990
991        if (mAssumedVisibility < 0)
992        {       
993                mAssumedVisibility = 0;
994        }
995
996        char str[100]; sprintf(str,": %d", mAssumedVisibility);
997
998        mSceneMgr->setOption("AssumedVisibility", &mAssumedVisibility);
999        mAssumedVisibilityInfo->setCaption(str);
1000}
1001//-----------------------------------------------------------------------
1002void TerrainFrameListener::changeVizScale(const int incr)
1003{
1004        mVizScale += incr;
1005
1006        if (mVizScale < 1)
1007        {       
1008                mVizScale = 1;
1009        }
1010
1011        mSceneMgr->setOption("NodeVizScale", &mVizScale);
1012}
1013//-----------------------------------------------------------------------
1014void TerrainFrameListener::changeFloorDist(const float incr)
1015{
1016        mFloorDist += incr;
1017
1018        if (mFloorDist < 2)
1019        {       
1020                mFloorDist = 2;
1021        }
1022}
1023//-----------------------------------------------------------------------
1024void TerrainFrameListener::zoomVizCamera(int zoom)
1025{
1026        mVizCameraHeight += zoom;
1027
1028        if(mVizCameraHeight < 0)
1029                mVizCameraHeight = 0;
1030}
1031//-----------------------------------------------------------------------
1032void TerrainFrameListener::nextAlgorithm()
1033{
1034        // possible algorithms: 3 culling algorithms + standard rendering
1035        mCurrentAlgorithm = (mCurrentAlgorithm + 1) %
1036                (GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS + 1);
1037        applyCurrentAlgorithm();
1038}
1039//-----------------------------------------------------------------------
1040void TerrainFrameListener::applyObjectType()
1041{
1042        if (mCurrentObjectType >= 3) // TODO: define a constant
1043                mCurrentObjectType = 0;
1044
1045        // parameters for new object
1046        mTerrainContentGenerator->SetOffset(msObjectTerrainOffsets[mCurrentObjectType]);
1047        Real scale = msObjectScales[mCurrentObjectType];
1048        mTerrainContentGenerator->SetScale(Vector3(scale, scale, scale));
1049
1050        mCurrentObjectTypeInfo->setCaption(": " + msObjectCaptions[mCurrentObjectType]);
1051}
1052//-----------------------------------------------------------------------
1053void TerrainFrameListener::applyCurrentAlgorithm()
1054{
1055        bool isNormalExecution;
1056       
1057        if (mCurrentAlgorithm < GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS)
1058        {
1059                isNormalExecution = false;
1060                mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
1061        }
1062        else
1063        {       // standard rendering without changed render queue flow
1064                isNormalExecution = true;
1065        }
1066       
1067        mSceneMgr->setOption("NormalExecution", &isNormalExecution);
1068        mAlgorithmInfo->setCaption(": " + msAlgorithmCaptions[mCurrentAlgorithm]);
1069
1070        if (1)
1071        {
1072                std::stringstream d; d << "algorithm: " << msAlgorithmCaptions[mCurrentAlgorithm];
1073                Ogre::LogManager::getSingleton().logMessage(d.str());
1074        }
1075}
1076//-----------------------------------------------------------------------
1077void TerrainFrameListener::updateStats()
1078{
1079        unsigned int opt = 0;
1080        char str[100];
1081       
1082        static String currFpsString = "Current FPS: ";
1083        static String avgFpsString = "Average FPS: ";
1084        static String bestFpsString = "Best FPS: ";
1085        static String worstFpsString = "Worst FPS: ";
1086        static String trisString = "Triangle Count: ";
1087
1088        int currentFps;
1089       
1090        // HACK for demo: use precomputed FPS instead of real FPS
1091        if (mRecordDemo)
1092        {
1093                currentFps = mPrecomputedFps;
1094        }
1095        else
1096        {
1097                currentFps = mWindow->getStatistics().lastFPS;
1098        }
1099
1100#if 0
1101        // HACK: take pure rendering time, only measures the render call
1102        long pureRenderTime = mTimeFrameEnded - mTimeFrameStarted;
1103
1104        if (pureRenderTime)
1105        {
1106                mPureRenderTimeFps = 1000.0 / (float) pureRenderTime;
1107        }
1108        currentFps = mPureRenderRenderTimeFps;
1109        //std::stringstream d; d << "Pure render time fps: " << mPureRenderTimeFps << "\n";
1110        //Ogre::LogManager::getSingleton().logMessage(d.str());
1111#endif
1112       
1113        unsigned int nodeInfo[3];
1114    mSceneMgr->getOption("NumRenderedNodes", nodeInfo);
1115        mSceneMgr->getOption("NumQueryCulledNodes", nodeInfo+1);
1116        mSceneMgr->getOption("NumFrustumCulledNodes", nodeInfo+2);
1117
1118
1119        mWalkthroughStats.UpdateFrame(currentFps,
1120                                                                  mWindow->getBestFPS(),
1121                                                                  mWindow->getWorstFPS(),
1122                                                                  (int)mWindow->getTriangleCount(),
1123                                                                  nodeInfo[0],
1124                                                                  nodeInfo[1],
1125                                                                  nodeInfo[2]);
1126
1127        // HACK: compute average fps ourselfs, because ogre avg. fps is wrong
1128        // TODO: update only once per second
1129        float avgFps = (float)mWalkthroughStats.mAccFps / (float)(mWalkthroughStats.mFrameCount);
1130       
1131
1132        // update stats when necessary
1133    try
1134        {
1135                OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
1136                OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
1137                OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
1138                OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
1139
1140                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
1141
1142                // HACK: take newly computed avg. fps instead of Ogre avg fps and update only once per second
1143                if (mTimeDelay < 0)
1144                {               
1145                        guiAvg->setCaption(avgFpsString + StringConverter::toString(avgFps) + " ms");
1146                        //guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps));
1147                }
1148
1149                if (0)
1150                {
1151                        std::stringstream d;
1152                        d << "fps: " << StringConverter::toString(currentFps) << ", "
1153                          << "avg fps: " << StringConverter::toString(avgFps);
1154                        LogManager::getSingleton().logMessage(d.str());
1155                }
1156
1157                //guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
1158                guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps));
1159               
1160                //std::stringstream d; d << "frame rate :" << stats.lastFPS;
1161                //Ogre::LogManager::getSingleton().logMessage(d.str());
1162
1163                guiBest->setCaption(bestFpsString + StringConverter::toString(stats.bestFPS)
1164                                                        + " " + StringConverter::toString(stats.bestFrameTime) + " ms");
1165                guiWorst->setCaption(worstFpsString + StringConverter::toString(stats.worstFPS)
1166                                                         + " " + StringConverter::toString(stats.worstFrameTime) + " ms");
1167
1168                OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
1169        guiTris->setCaption(trisString + StringConverter::toString(stats.triangleCount));
1170               
1171                //LogManager::getSingleton().logMessage(StringConverter::toString(stats.triangleCount));
1172
1173                OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
1174                guiDbg->setCaption(mWindow->getDebugText());
1175
1176
1177                //-- culling stats
1178
1179                mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt);
1180                mFrustumCulledNodesInfo->setCaption(str);
1181
1182                mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt);
1183                mQueryCulledNodesInfo->setCaption(str);
1184       
1185                mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt);
1186                mHierarchyNodesInfo->setCaption(str);
1187
1188                mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt);
1189                mRenderedNodesInfo->setCaption(str);
1190
1191                sprintf(str,": %d", mTerrainContentGenerator->GetObjectCount());
1192                mObjectsCountInfo->setCaption(str);
1193
1194                // take old value into account in order to create no sudden changes
1195                mSceneMgr->getOption("NumQueriesIssued", &opt);
1196                mDelayedQueriesIssued = mDelayedQueriesIssued * 0.8 + (float)opt * 0.2f;
1197                sprintf(str,": %d", (int)mDelayedQueriesIssued);
1198                mQueriesIssuedInfo->setCaption(str);
1199
1200                mSceneMgr->getOption("NumTraversedNodes", &opt);
1201                mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2f;
1202                sprintf(str,": %d", (int)mDelayedTraversedNodes);
1203                mTraversedNodesInfo->setCaption(str);
1204
1205                if (mRecordVideo)
1206                {
1207                        // update stats for demo
1208                        mMyStatsAlgorithmInfo->setCaption(msApprevAlgorithmCaptions[mCurrentAlgorithm]);
1209                        sprintf(str,": %d", (int)currentFps);
1210                        mMyStatsFpsInfo->setCaption(str);
1211                }
1212
1213        }
1214        catch (...)
1215        {
1216                // ignore
1217        }
1218}
1219//-----------------------------------------------------------------------
1220void TerrainFrameListener::setTestGeometryForVisibleLeaves(bool testGeometryForVisibleLeaves)
1221{
1222        mSceneMgr->setOption("TestGeometryForVisibleLeaves", &mTestGeometryForVisibleLeaves);
1223       
1224        /* disable optimization which tests geometry instead of aabb
1225         * for "delayed" rendering of transparents (i.e., render transparents after all the solids)
1226         * because otherwise visible transparents could be skipped
1227         */
1228        bool delayedRendering = !mTestGeometryForVisibleLeaves;
1229
1230        mSceneMgr->setOption("DelayRenderTransparents", &delayedRendering);
1231
1232        if (mTestGeometryForVisibleLeaves)
1233        {
1234                mTestGeometryForVisibleLeavesInfo->setCaption(": true");
1235        }
1236        else
1237        {
1238                mTestGeometryForVisibleLeavesInfo->setCaption(": false");
1239        }
1240}
1241//-----------------------------------------------------------------------
1242void TerrainFrameListener::toggleShowOctree()
1243{
1244        mShowOctree = !mShowOctree;
1245        mSceneMgr->setOption("ShowOctree", &mShowOctree);
1246}
1247//-----------------------------------------------------------------------
1248void TerrainFrameListener::toggleShowViewCells()
1249{
1250        mShowViewCells = !mShowViewCells;
1251        mSceneMgr->setOption("ShowViewCells", &mShowViewCells);
1252}
1253//-----------------------------------------------------------------------
1254void TerrainFrameListener::toggleUseViewCells()
1255{
1256        // HACK: no view cells for hilly terrain
1257        if (mApplication->msShowHillyTerrain)
1258                return;
1259
1260        mUseViewCells = !mUseViewCells;
1261
1262        // load on demand
1263        if (mUseViewCells)// && !mViewCellsLoaded)
1264        {
1265                LogManager::getSingleton().logMessage("using view cells");
1266                mLoadingOverlay->show();
1267
1268                // call once to load view cell loading overlay
1269                mWindow->update();
1270                mViewCellsLoaded = mApplication->LoadViewCells(mApplication->mViewCellsFilename);
1271               
1272                if (!mViewCellsLoaded)
1273                        LogManager::getSingleton().logMessage("loading view cells failed");
1274                else
1275                        LogManager::getSingleton().logMessage("view cells successfully loaded");
1276       
1277                mLoadingOverlay->hide();
1278        }
1279
1280        if (mUseViewCells)
1281                mViewCellsInfo->setCaption(": on");
1282        else
1283                mViewCellsInfo->setCaption(": off");
1284
1285        mSceneMgr->setOption("UseViewCells", &mUseViewCells);
1286}
1287//-----------------------------------------------------------------------
1288void TerrainFrameListener::toggleUseVisibilityFilter()
1289{
1290        mUseVisibilityFilter = !mUseVisibilityFilter;
1291        mSceneMgr->setOption("UseVisibilityFilter", &mUseVisibilityFilter);
1292}
1293//-----------------------------------------------------------------------
1294void TerrainFrameListener::toggleUseDepthPass()
1295{
1296        mUseDepthPass = !mUseDepthPass;
1297
1298        mSceneMgr->setOption("UseDepthPass", &mUseDepthPass);
1299       
1300        if (mUseDepthPass)
1301        {
1302                mUseDepthPassInfo->setCaption(": true");
1303        }
1304        else
1305        {
1306                mUseDepthPassInfo->setCaption(": false");
1307        }
1308}
1309//-----------------------------------------------------------------------
1310void TerrainFrameListener::toggleFlushQueue()
1311{
1312        mFlushQueue = !mFlushQueue;
1313
1314        mSceneMgr->setOption("FlushQueue", &mFlushQueue);
1315       
1316        if (mFlushQueue)
1317        {
1318                LogManager::getSingleton().logMessage("flushing queue");
1319                //mFlushQueueInfo->setCaption(": true");
1320        }
1321        else
1322        {
1323                LogManager::getSingleton().logMessage("not flushing queue");
1324                //mFlushQueueInfo->setCaption(": false");
1325        }
1326}
1327
1328//-----------------------------------------------------------------------
1329void TerrainFrameListener::toggleShowViz()
1330{
1331        mVisualizeCulledNodes = mShowVisualization = !mShowVisualization;
1332       
1333        // create viewport with priority VIZ_VIEWPORT_Z_ORDER:
1334        // will be rendered over standard viewport
1335        if (mShowVisualization)
1336        {       
1337                Viewport *vizvp = mWindow->addViewport(mVizCamera,
1338                        VIZ_VIEWPORT_Z_ORDER, 0.6, 0.6, 0.4, 0.4);
1339                               
1340                vizvp->setBackgroundColour(ColourValue(0.0, 0.3, 0.2, 1));
1341
1342                vizvp->setOverlaysEnabled(false);
1343                // Alter the camera aspect ratio to match the viewport
1344        mVizCamera->setAspectRatio(Real(vizvp->getActualWidth()) /
1345                                                                   Real(vizvp->getActualHeight()));
1346               
1347                mSceneMgr->setOption("VisualizeCulledNodes", &mVisualizeCulledNodes);
1348       
1349        }
1350        else
1351        {
1352                // remove visualization viewport
1353                mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER);
1354
1355                // octree bounding boxes are shown for visualization purpose, reset now
1356                mSceneMgr->setOption("ShowOctree", &mShowOctree);
1357        }
1358}
1359//-----------------------------------------------------------------------
1360void TerrainFrameListener::toggleShowShadows()
1361{
1362        mShowShadows = !mShowShadows;
1363
1364        mSunLight->setCastShadows(mShowShadows);
1365
1366        if (mShowShadows)
1367        {
1368                mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
1369                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
1370                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);           
1371        }
1372        else
1373        {
1374                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
1375        }
1376
1377}
1378//-----------------------------------------------------------------------
1379void TerrainFrameListener::nextNodeVizMode()
1380{
1381        mNodeVizMode = (mNodeVizMode + 1) % NODEVIZ_MODES_NUM;
1382
1383        bool renderNodesForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES) ||
1384                (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
1385        bool renderNodesContentForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
1386        //bool renderNodesContentForViz = mNodeVizMode == NODEVIZ_RENDER_GEOMETRY;
1387
1388        mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz);
1389        mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz);
1390}
1391//-----------------------------------------------------------------------
1392void TerrainFrameListener::keyPressed(KeyEvent* e)
1393{
1394        // hide exact visibility query overlay
1395        if (mShowQueryStats)
1396        {
1397                mQueryOverlay->hide();
1398                mShowQueryStats = false;
1399        }
1400
1401        switch(e->getKey())
1402        {
1403       
1404        case KC_SUBTRACT:
1405                changeThreshold(-10);
1406                break;
1407        case KC_ADD:
1408                changeThreshold(10);
1409                break;
1410
1411        case KC_ESCAPE:
1412                mShutdownRequested = true;
1413                e->consume();
1414                return;
1415
1416        case KC_SPACE:
1417                nextAlgorithm();
1418                break;
1419
1420        case KC_LSHIFT:
1421                mShiftPressed = true;
1422                break;
1423        case KC_DELETE:
1424                mDeleteObjects = true;
1425                break;
1426
1427        case KC_C:
1428                if (mItemBufferMode != GtpVisibility::QueryManager::GEOMETRY_VISIBILITY)
1429                {
1430                        mItemBufferMode = GtpVisibility::QueryManager::GEOMETRY_VISIBILITY;
1431                }
1432                else
1433                {
1434                        mItemBufferMode = GtpVisibility::QueryManager::PATCH_VISIBILITY;
1435                }
1436                break;
1437         case KC_E: // hack for recording demo using precomputed fps
1438                mSavePrecomputedFps = !mSavePrecomputedFps;
1439                break;
1440
1441    case KC_F:
1442                nextFilter();
1443                break;
1444        case KC_G:
1445                mTestGeometryForVisibleLeaves = !mTestGeometryForVisibleLeaves;
1446                setTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
1447                break;
1448        case KC_H:
1449                toggleShowShadows();
1450                break;
1451        case KC_L:
1452                toggleShowViewCells();
1453                break;
1454        case KC_M: // hack for recording demo using precomputed fps
1455                mRecordDemo = !mRecordDemo;
1456                break;
1457        case KC_O:
1458                switchMouseMode();
1459                break;
1460        case KC_P:
1461                toggleDisplayCameraDetails();
1462                break;
1463        case KC_V:
1464                toggleUseViewCells();
1465                break;
1466        case KC_Q:
1467                toggleUseVisibilityFilter();
1468                break;
1469        case KC_R:
1470                nextSceneDetailLevel();
1471                break;
1472        case KC_T:
1473                toggleShowOctree();
1474                break;
1475        case KC_U:
1476                mCamNode->resetOrientation();
1477                mCamNode->setPosition(mApplication->mInitialPosition);
1478                break;
1479        case KC_X:
1480                toggleUseDepthPass();
1481                break;
1482        case KC_I:
1483                toggleFlushQueue();
1484                break;
1485        case KC_Z:
1486                mCamNode->resetOrientation();
1487                break;
1488
1489
1490        ///////////////
1491        //-- visualization
1492
1493        case KC_1:
1494                toggleShowViz();
1495                break;
1496        case KC_2:
1497                nextNodeVizMode();
1498                break;
1499        case KC_7:
1500                {
1501                        // generate new objects
1502                        const int numObjects = 500;
1503                        mApplication->generateScene(numObjects, mCurrentObjectType);
1504                }
1505                break;
1506        case KC_8:
1507                changeAssumedVisibility(-5);
1508                // changeAssumedVisibility(-500);
1509                break;
1510        case KC_9:
1511                changeAssumedVisibility(5);
1512                // changeAssumedVisibility(500);
1513                break;
1514
1515//#if USE_PERFHUD
1516        case KC_F1:
1517                toggleShowHelp();
1518                break;
1519        case KC_F2:
1520                mStatsOn = !mStatsOn;
1521                showStats(mStatsOn);
1522                break;
1523        case KC_F3:
1524                nextAppState();
1525                break;
1526        case KC_F4:
1527                toggleRecord();
1528                break;
1529
1530        case KC_F5:
1531                {
1532                        unsigned int pixels = 0;
1533                        mSceneMgr->getOption("VisibleObjects", &pixels);
1534
1535                        std::stringstream d; d << "visible objects: " << pixels;
1536                        LogManager::getSingleton().logMessage(d.str());
1537                        const bool fromPoint = false;
1538                        //applyVisibilityQuery(fromPoint, mShiftPressed, mUseItemBuffer);
1539                        break;
1540                }
1541
1542        case KC_F6:
1543                {
1544                        const bool fromPoint = true;
1545                        applyVisibilityQuery(fromPoint, mShiftPressed, mUseItemBuffer);
1546                        break;
1547                }       
1548        case KC_F7:
1549                ++ mCurrentObjectType;
1550                applyObjectType();
1551                break;
1552//#endif
1553
1554        case KC_F8:
1555
1556                mTerrainContentGenerator->WriteObjects(objects_out_filename);
1557                break;
1558
1559        case KC_F9:
1560                mUseAnimation = !mUseAnimation;
1561                break;
1562
1563        case KC_F10:
1564                mRecordVideo = !mRecordVideo;
1565                       
1566        case KC_F11:
1567                takeScreenshot();
1568                break;
1569       
1570        case KC_F12:
1571                break;
1572        //KEY_PRESSED(KC_F3, 0.3, writeFrames());
1573        //KEY_PRESSED(KC_F4, 0.3, loadFrames());
1574        default:
1575                break;
1576        }
1577
1578        CEGUI::System::getSingleton().injectKeyDown(e->getKey());
1579        CEGUI::System::getSingleton().injectChar(e->getKeyChar());
1580        e->consume();
1581}
1582//-----------------------------------------------------------------------
1583void TerrainFrameListener::keyReleased(KeyEvent* e)
1584{
1585        if (e->getKey() == KC_LSHIFT)
1586        {
1587                mShiftPressed = false;
1588        }
1589       
1590        CEGUI::System::getSingleton().injectKeyUp(e->getKey());
1591        e->consume();
1592}
1593//-----------------------------------------------------------------------
1594void TerrainFrameListener::keyClicked(KeyEvent* e)
1595{
1596        // Do nothing
1597        e->consume();
1598}
1599//-----------------------------------------------------------------------
1600void TerrainFrameListener::addFrameInfo(FrameInfoContainer &frameInfos,
1601                                                                                SceneNode *camNode,
1602                                                                                Real timeElapsed)
1603{
1604        frame_info info;
1605
1606        info.orientation = mCamNode->getOrientation();
1607        info.position = mCamNode->getPosition();
1608        info.timeElapsed = timeElapsed;
1609        info.fps = mWindow->getStatistics().lastFPS;
1610
1611        frameInfos.push_back(info);
1612}
1613//-----------------------------------------------------------------------
1614void TerrainFrameListener::setCurrentFrameInfo(const Real timeElapsed)
1615{
1616        //-- find current frame relative to elapsed frame time         
1617        mReplayTimeElapsed -= timeElapsed;
1618       
1619        while ((mReplayTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1))
1620        {
1621                mReplayTimeElapsed += mFrameInfo[mCurrentFrame ++].timeElapsed;
1622        }
1623
1624
1625        // TODO: crashes here if recording / replaying on the same time!!
1626        const frame_info new_frame = mFrameInfo[mCurrentFrame];
1627        const frame_info old_frame = mFrameInfo[mCurrentFrame - 1];
1628               
1629        /////////////
1630        //-- interpolate frames
1631        Real factor = 1;
1632
1633        if (old_frame.timeElapsed > 0)
1634        {
1635                factor = mReplayTimeElapsed / old_frame.timeElapsed;
1636        }
1637
1638        const Vector3 camPos = old_frame.position + factor
1639                * (new_frame.position - old_frame.position);
1640
1641        // interpolate the orientation
1642        const Quaternion camOrienation =
1643                Quaternion::Slerp(factor, old_frame.orientation, new_frame.orientation, true);
1644
1645        // HACK for demo: interpolate precomputed fps
1646        mPrecomputedFps = old_frame.fps + factor * (new_frame.fps - old_frame.fps);
1647
1648        mCamNode->setPosition(camPos);
1649        mCamNode->setOrientation(camOrienation);
1650       
1651        // stop replaying after one full walkthrough
1652        if (mCurrentFrame == (int)mFrameInfo.size() - 1)
1653        {
1654                nextAppState();
1655        }
1656}
1657//-----------------------------------------------------------------------   
1658bool TerrainFrameListener::processUnbufferedKeyInput(const FrameEvent& evt)
1659{
1660        bool cursorPressed = false;
1661       
1662        /* Move camera forward by keypress. */
1663    if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W))
1664        {
1665                mTranslateVector.z = -mMoveScale;
1666                cursorPressed = true;
1667        }
1668    /* Move camera backward by keypress. */
1669    if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S))
1670    {
1671                mTranslateVector.z = mMoveScale;
1672                cursorPressed = true;
1673    }
1674
1675        if (mInputDevice->isKeyDown(KC_A))
1676        {
1677                mTranslateVector.x -= mMoveScale;
1678                mTranslateVector.y += mMoveScale;
1679
1680                cursorPressed = true;
1681        }
1682
1683        if (mInputDevice->isKeyDown(KC_D))
1684        {
1685                mTranslateVector.x += mMoveScale;
1686                mTranslateVector.y -= mMoveScale;
1687
1688                cursorPressed = true;
1689        }
1690
1691    if (mInputDevice->isKeyDown(KC_RIGHT))
1692    {
1693        mCamNode->yaw(-mRotScale, Ogre::Node::TS_WORLD);
1694                cursorPressed = true;
1695    }
1696
1697    if (mInputDevice->isKeyDown(KC_LEFT))
1698    {
1699        mCamNode->yaw(mRotScale, Ogre::Node::TS_WORLD);
1700                cursorPressed = true;
1701    }
1702        // visualization camera
1703        if (mInputDevice->isKeyDown(KC_3))
1704        {
1705                zoomVizCamera(50);
1706        }
1707        if (mInputDevice->isKeyDown(KC_4))
1708        {
1709                zoomVizCamera(-50);
1710        }
1711
1712        if (mInputDevice->isKeyDown(KC_5))
1713        {
1714                changeVizScale(-1);
1715        }
1716
1717        if (mInputDevice->isKeyDown(KC_6))
1718        {
1719                changeVizScale(1);
1720        }
1721       
1722        if (mInputDevice->isKeyDown(KC_7))
1723        {
1724                changeFloorDist(-1);
1725        }
1726       
1727        if (mInputDevice->isKeyDown(KC_8))
1728        {
1729                changeFloorDist(1);
1730        }
1731
1732
1733        // show the results
1734        if (cursorPressed && mShowQueryStats)
1735        {
1736                mQueryOverlay->hide();
1737                mShowQueryStats = false;
1738        }
1739
1740    // Return true to continue rendering
1741    return true;
1742}
1743//-----------------------------------------------------------------------
1744void TerrainFrameListener::nextFilter()
1745{
1746        switch (mFiltering)
1747        {
1748        case TFO_BILINEAR:
1749                mFiltering = TFO_TRILINEAR;
1750                mAniso = 1;
1751                break;
1752        case TFO_TRILINEAR:
1753                mFiltering = TFO_ANISOTROPIC;
1754                mAniso = 8;
1755                break;
1756        case TFO_ANISOTROPIC:
1757                mFiltering = TFO_BILINEAR;
1758                mAniso = 1;
1759                break;
1760        default:
1761                break;
1762        }
1763
1764    MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
1765    MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
1766
1767        // reload stats
1768    showStats(mStatsOn);
1769}
1770//-----------------------------------------------------------------------
1771void TerrainFrameListener::nextSceneDetailLevel()
1772{
1773#if OGRE_103
1774        mSceneDetailIndex = (mSceneDetailIndex + 1) % 3;
1775        switch (mSceneDetailIndex)
1776        {
1777                case 0:
1778                        mCamera->setDetailLevel(SDL_SOLID);
1779                        break;
1780                case 1:
1781                        mCamera->setDetailLevel(SDL_WIREFRAME);
1782                        break;
1783                case 2:
1784                        mCamera->setDetailLevel(SDL_POINTS);
1785                        break;
1786        }
1787#endif
1788}
1789//-----------------------------------------------------------------------
1790void TerrainFrameListener::takeVideoFrame(std::ofstream &ofstr)
1791{
1792        char name[50];
1793
1794        sprintf(name, "frame_%05d.tga", ++mNumVideoFrames);
1795    mWindow->writeContentsToFile(name);
1796    //mWindow->setDebugText(String("Wrote ") + name);
1797
1798        ofstr << name << "\n";
1799}
1800//-----------------------------------------------------------------------
1801void TerrainFrameListener::takeScreenshot()
1802{
1803        char name[50];
1804
1805        sprintf(name, "screenshot_%05d.png", ++mNumScreenShots);
1806    mWindow->writeContentsToFile(name);
1807    //mWindow->setDebugText(String("Wrote ") + name);
1808}
1809//-----------------------------------------------------------------------
1810void TerrainFrameListener::toggleDisplayCameraDetails()
1811{
1812        mDisplayCameraDetails = !mDisplayCameraDetails;
1813       
1814    if (!mDisplayCameraDetails)
1815        {
1816                mWindow->setDebugText("");
1817        }
1818}
1819//-----------------------------------------------------------------------
1820void TerrainFrameListener::showStats(bool show)
1821{
1822        if (mDebugOverlay && mCullStatsOverlay)
1823        {
1824                if (show)
1825                {
1826                        mDebugOverlay->show();
1827                        mCullStatsOverlay->show();
1828                }
1829                else
1830                {
1831                        mDebugOverlay->hide();
1832                        mCullStatsOverlay->hide();
1833                }
1834        }
1835}
1836
1837//-----------------------------------------------------------------------
1838void TerrainFrameListener::toggleShowHelp()
1839{
1840        mShowHelp = !mShowHelp;
1841
1842        if (mShowHelp)
1843        {
1844                mHelpOverlay->show();
1845        }
1846        else
1847        {
1848                mHelpOverlay->hide();
1849        }
1850}
1851//-----------------------------------------------------------------------
1852void TerrainFrameListener::initOverlayElement(OverlayElement **elInfo, String ext,
1853                                                                                          String name, int top, String caption)
1854{
1855        OverlayElement *el =
1856                OverlayManager::getSingleton().getOverlayElement(ext + name);
1857
1858        (*elInfo) = OverlayManager::getSingleton().getOverlayElement(ext + name + "Info");
1859        (*elInfo)->setCaption(caption);
1860
1861        el->setTop(top);
1862        (*elInfo)->setTop(top);
1863}
1864//-----------------------------------------------------------------------
1865void TerrainFrameListener::initHelpOverlayElement(String name, int top)
1866{
1867        OverlayElement *el = OverlayManager::getSingleton().getOverlayElement(
1868                "Example/Visibility/Help/" + name);
1869
1870        el->setTop(top);
1871}
1872//-----------------------------------------------------------------------
1873void TerrainFrameListener::initHelpOverlay()
1874{
1875        const int vert_space = 15;
1876        int top = 30;
1877
1878        initHelpOverlayElement("ShowHelp", top); top += vert_space;
1879        initHelpOverlayElement("Stats", top); top += vert_space;
1880        initHelpOverlayElement("AppState", top); top += vert_space;
1881        initHelpOverlayElement("Recorded", top); top += vert_space;
1882        initHelpOverlayElement("Animation", top); top += vert_space;
1883        initHelpOverlayElement("Video", top); top += vert_space;
1884        initHelpOverlayElement("Screenshots", top); top += vert_space;
1885        initHelpOverlayElement("WriteOut", top); top += vert_space;
1886
1887
1888        top +=vert_space;
1889        initHelpOverlayElement("SceneDetail", top); top += vert_space;
1890        initHelpOverlayElement("DisplayCameraDetails", top); top += vert_space;
1891        initHelpOverlayElement("DisplayOctree", top); top += vert_space;
1892        initHelpOverlayElement("UseShadows", top); top += vert_space;
1893        initHelpOverlayElement("Filter", top); top += vert_space;
1894
1895        //-- visualization
1896        top += vert_space;
1897        initHelpOverlayElement("VizSection", top); top += vert_space;
1898        initHelpOverlayElement("Viz", top); top += vert_space;
1899        initHelpOverlayElement("NextVizMode", top); top += vert_space;
1900        initHelpOverlayElement("ZoomViz", top); top += vert_space;
1901
1902
1903        //-- visibility queries
1904        top += vert_space;
1905        initHelpOverlayElement("VisQuery", top); top += vert_space;
1906        initHelpOverlayElement("FromCameraQuery", top); top += vert_space;
1907        initHelpOverlayElement("FromPointQuery", top); top += vert_space;
1908        initHelpOverlayElement("QueryType", top); top += vert_space;
1909        initHelpOverlayElement("QueryTarget", top); top += vert_space;
1910
1911        //-- object generation
1912        top += vert_space;
1913        initHelpOverlayElement("SceneObjects", top); top += vert_space;
1914        initHelpOverlayElement("PlaceObjects", top); top += vert_space;
1915        initHelpOverlayElement("GenerateObjects", top); top += vert_space;
1916        initHelpOverlayElement("RemoveObjects", top); top += vert_space;
1917        initHelpOverlayElement("DropObject", top); top += vert_space;
1918
1919        OverlayElement *helpPanel = OverlayManager::getSingleton().getOverlayElement(
1920                "Example/Visibility/Help/HelpPanel");
1921
1922        helpPanel->setHeight(top + 10);
1923}
1924//-----------------------------------------------------------------------
1925void TerrainFrameListener::initVisStatsOverlay()
1926{
1927        const int border_height = 10;
1928        const int vert_space = 15;
1929
1930        //-- visibility culling stats overlay
1931        int top = border_height;
1932
1933        String ext = "Example/Visibility/";
1934       
1935        initOverlayElement(&mAlgorithmInfo, ext, "Algorithm", top,
1936                ": " + msAlgorithmCaptions[mCurrentAlgorithm]); top += vert_space;
1937
1938        initOverlayElement(&mThresholdInfo, ext, "Threshold", top, ": 0"); top += vert_space;
1939        initOverlayElement(&mTestGeometryForVisibleLeavesInfo, ext,
1940                                           "TestGeometryForVisibleLeaves", top, ": true"); top += vert_space;
1941        initOverlayElement(&mUseDepthPassInfo, ext, "UseDepthPass", top, ": false"); top += vert_space;
1942        initOverlayElement(&mAssumedVisibilityInfo, ext, "AssumedVisibility", top, ": 0"); top += vert_space;
1943        initOverlayElement(&mCurrentObjectTypeInfo, ext, "CurrentObjectType", top, ": "); top += vert_space;
1944        initOverlayElement(&mViewCellsInfo, ext, "ViewCells", top, ": "); top += vert_space;
1945        //initOverlayElement(&mHelpInfo, ext, "Help", top, ": "); top += vert_space;
1946
1947        OverlayElement *optionsPanel = OverlayManager::getSingleton().
1948                getOverlayElement("Example/Visibility/VisibilityPanel");
1949
1950        optionsPanel->setHeight(top + border_height);
1951
1952        top = border_height;
1953        //ext = "Example/Visibility/";
1954        initOverlayElement(&mFrustumCulledNodesInfo, ext, "FrustumCulledNodes", top, ": 0"); top += vert_space;
1955        initOverlayElement(&mQueryCulledNodesInfo, ext, "QueryCulledNodes", top, ": 0"); top += vert_space;
1956        initOverlayElement(&mTraversedNodesInfo, ext, "TraversedNodes", top, ": 0"); top += vert_space;
1957        initOverlayElement(&mHierarchyNodesInfo, ext, "HierarchyNodes", top, ": 0"); top += vert_space;
1958        initOverlayElement(&mRenderedNodesInfo, ext, "RenderedNodes", top, ": 0"); top += vert_space;
1959        initOverlayElement(&mObjectsCountInfo, ext, "ObjectsCount", top, ": 0"); top += vert_space;
1960        initOverlayElement(&mQueriesIssuedInfo, ext, "QueriesIssued", top, ": 0"); top += vert_space;
1961
1962        OverlayElement *visPanel = OverlayManager::getSingleton().
1963                getOverlayElement("Example/Visibility/VisibilityStatsPanel");
1964
1965        visPanel->setHeight(top + border_height);
1966}
1967//-----------------------------------------------------------------------
1968void TerrainFrameListener::initQueryOverlay()
1969{
1970        const int border_height = 10;
1971        const int vert_space = 15;
1972
1973        //-- visibility culling stats overlay
1974        int top = border_height + 25;
1975
1976        const String ext = "Example/Visibility/Query/";
1977           
1978        initOverlayElement(&mQueryTypeInfo , ext, "QueryType", top,     ": 0"); top += vert_space;
1979       
1980        initOverlayElement(&mQueryVisibleNodesInfo , ext, "VisibleNodes", top,  ": 0"); top += vert_space;
1981        initOverlayElement(&mQueryVisibleGeometryInfo , ext, "VisibleGeometry", top,    ": 0"); top += vert_space;
1982        initOverlayElement(&mQueryVisiblePatchInfo , ext, "VisiblePatches", top,        ": 0"); top += vert_space;
1983       
1984        initOverlayElement(&mQueryNodeVisibilityInfo , ext, "NodeVisibility", top,      ": 0"); top += vert_space;
1985        initOverlayElement(&mQueryGeometryVisibilityInfo , ext, "GeometryVisibility", top,      ": 0"); top += vert_space;
1986        initOverlayElement(&mQueryPatchVisibilityInfo , ext, "PatchVisibility", top,    ": 0"); top += vert_space;
1987
1988        OverlayElement *queryPanel =
1989                OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/QueryPanel");
1990
1991        queryPanel->setHeight(top + border_height);
1992}
1993//-----------------------------------------------------------------------
1994void TerrainFrameListener::setAlgorithm(const int algorithm)
1995{
1996        mCurrentAlgorithm = algorithm;
1997        applyCurrentAlgorithm();
1998}
Note: See TracBrowser for help on using the repository browser.