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

Revision 2108, 55.9 KB checked in by mattausch, 17 years ago (diff)

loading geometry in scene manager

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