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

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