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

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