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

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