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

Revision 2145, 56.6 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       
583        if (!mSceneMgr->getOption("VisibilityManager", visManager))
584                return;
585
586        GtpVisibility::HierarchyInterface *hierarchyInterface = NULL;
587        if (!mSceneMgr->getOption("HierarchyInterface", hierarchyInterface))
588                return;
589
590        mQueryManager = new OcclusionQueriesQueryManager(hierarchyInterface,
591                        mWindow->getViewport(0), queryModes, itemBufferMode);
592
593        //mQueryManager = new PlatformQueryManager(sm->GetHierarchyInterface(), mWindow->getViewport(0), false);
594
595
596        visManager->SetQueryManager(mQueryManager);
597
598        GtpVisibility::NodeInfoContainer visibleNodes;
599        GtpVisibility::MeshInfoContainer visibleGeometry;
600        GtpVisibility::PatchInfoContainer visiblePatches;
601
602
603        if (fromPoint)
604        {
605                mQueryManager->
606                        ComputeFromPointVisibility(mCamNode->getPosition(), &visibleNodes,
607                                                                           &visibleGeometry, &visiblePatches, relativeVisibility);
608        }
609        else
610        {
611                mQueryManager->ComputeCameraVisibility(*mCamera,
612                            &visibleNodes, &visibleGeometry, &visiblePatches, relativeVisibility);
613        }
614               
615        std::stringstream d;
616        d << "Query mode: " << queryModes << ", "
617          << msQueryTypeCaptions[fromPoint ?  1 : 0].c_str() << " "
618          << msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str() << " "
619      << msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str();
620        LogManager::getSingleton().logMessage(d.str());
621
622
623        float averageNodeVis = 0, averageGeometryVis = 0, averagePatchVis = 0;
624        int geomSize = 0, nodesSize = 0, patchSize = 0;
625
626        ///////////////////////////////////////////////////////////////////////////
627        //-- apply queries on geometry level
628
629        GtpVisibility::MeshInfoContainer::iterator geomIt, geomIt_end = visibleGeometry.end();
630
631        for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt)
632        {
633                // add if not 0
634                if ((*geomIt).GetVisiblePixels())
635                {
636                        float vis = relativeVisibility ?
637                                (*geomIt).ComputeRelativeVisibility() : (float)(*geomIt).GetVisiblePixels();
638       
639                        averageGeometryVis += vis;
640                        ++ geomSize;
641                       
642                        std::stringstream d;
643                        d << "Geometry " << geomSize << " id: " << (*geomIt).GetSource()->getSubEntity(0)->getId()
644                          << " visibility: "  << (*geomIt).GetVisiblePixels() << ", " << (*geomIt).GetProjectedPixels();
645                        LogManager::getSingleton().logMessage(d.str());
646                }
647        }
648
649
650
651        ///////////////////////////////////////////////////////////////////////////
652        //-- apply queries on node level
653
654
655        GtpVisibility::NodeInfoContainer::iterator nodesIt, nodesIt_end = visibleNodes.end();
656
657        for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++nodesIt)
658        {
659                // add if not 0
660                if ((*nodesIt).GetVisiblePixels())
661                {
662                        float vis = relativeVisibility ?
663                                (*nodesIt).ComputeRelativeVisibility() : (float)(*nodesIt).GetVisiblePixels();
664               
665                        averageNodeVis += vis;
666                        ++ nodesSize;
667
668                        std::stringstream d; d << "Node visibility: " << vis;
669                        LogManager::getSingleton().logMessage(d.str());
670                }       
671        }
672
673
674        ///////////////////////////////////////////////////////////////////////////
675        //-- apply queries on patch level
676
677
678        GtpVisibility::PatchInfoContainer::iterator patchIt, patchIt_end = visiblePatches.end();
679
680        for (patchIt = visiblePatches.begin(); patchIt != patchIt_end; ++ patchIt)
681        {
682                // add if not 0
683                if ((*patchIt).GetVisiblePixels())
684                {
685                        float vis = relativeVisibility ?
686                                (*patchIt).ComputeRelativeVisibility() : (float)(*patchIt).GetVisiblePixels();
687               
688                        averagePatchVis += vis;
689                        ++ patchSize;
690
691                        std::stringstream d; d << "Patch visibility: " << vis;
692                        LogManager::getSingleton().logMessage(d.str());
693                }       
694        }
695
696        ///////////////////////////////////////////////////////////////
697        //-- update visibility queries stats
698
699        if (nodesSize)
700                averageNodeVis /= (float)nodesSize;
701        if (geomSize)
702                averageGeometryVis /= (float)geomSize;
703        if (patchSize)
704                averagePatchVis /= (float)patchSize;
705
706
707    try
708        {
709                char str[100];
710               
711                sprintf(str, ": %s, %s, %s",
712                                msQueryTypeCaptions[fromPoint ?  1 : 0].c_str(),
713                                msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str(),
714                                msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str());
715
716                mQueryTypeInfo->setCaption(str);
717
718                sprintf(str, ": %d", (int)nodesSize);
719                mQueryVisibleNodesInfo->setCaption(str);
720       
721                sprintf(str,": %d", (int)geomSize);
722                mQueryVisibleGeometryInfo->setCaption(str);
723               
724                sprintf(str,": %d", (int)patchSize);
725                mQueryVisiblePatchInfo->setCaption(str);
726
727                sprintf(str,": %3.3f", averageNodeVis);
728                mQueryNodeVisibilityInfo->setCaption(str);
729
730                sprintf(str,": %3.3f", averageGeometryVis);
731                mQueryGeometryVisibilityInfo->setCaption(str);
732
733                sprintf(str,": %3.3f", averagePatchVis);
734                mQueryPatchVisibilityInfo->setCaption(str);
735        }
736        catch (...)
737        {
738                // ignore
739        }
740
741        // show the results
742        if (!mShowQueryStats && !mShowHelp)
743        {
744                mQueryOverlay->show();
745                mShowQueryStats = true;
746        }
747
748        delete mQueryManager;
749}
750
751
752bool TerrainFrameListener::processUnbufferedMouseInput(const FrameEvent& evt)
753{
754        /* Rotation factors, may not be used if the second mouse button is pressed. */
755
756    /* If the second mouse button is pressed, then the mouse movement results in
757       sliding the camera, otherwise we rotate. */
758    if (mInputDevice->getMouseButton(1))
759    {
760                mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
761                mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
762        }
763        else
764        {
765                mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
766                mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
767        }
768
769        return true;
770}
771//-----------------------------------------------------------------------
772bool TerrainFrameListener::frameEnded(const FrameEvent& evt)
773{
774        if (mShutdownRequested)
775                return false;
776
777        // timer end time
778        if (!mShowVisualization)
779        {
780                mTimeFrameEnded = mTimer->getMilliseconds();
781        }
782
783    updateStats();
784
785        if (mRecordVideo) // record current frame
786        {
787                takeVideoFrame(video_out);
788        }
789
790        //-- IMPORTANT: must be set, otherwise terrain is not rendered correctly
791        mSceneMgr->endFrame();
792
793        if (mTimeDelay <= 0) // simulates approx. one second
794                mTimeDelay = 1.0;
795
796        return true;
797}
798//-----------------------------------------------------------------------
799void TerrainFrameListener::moveCamera()
800{
801        // move node rather than camera so orientation is right in the visualization
802        mCamNode->yaw(mRotX, Ogre::Node::TS_WORLD);
803        //mCamNode->rotate(Vector3(0,1,0), mRotX, Ogre::Node::TS_WORLD);
804        mCamNode->pitch(mRotY);
805
806        mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector);
807}
808//-----------------------------------------------------------------------
809void TerrainFrameListener::writeFrames(const std::string filename,
810                                                                           const FrameInfoContainer &frameInfo) const
811{
812        std::ofstream ofstr(filename.c_str());
813        std::vector<frame_info>::const_iterator it, it_end;
814        it_end = frameInfo.end();
815
816        int i = 0;
817
818        for (it = frameInfo.begin(); it < it_end; ++ it, ++ i)
819        {
820                ofstr << StringConverter::toString((*it).position) << " "
821                          << StringConverter::toString((*it).orientation) << " "
822                          << StringConverter::toString((*it).timeElapsed) << " "
823                          << StringConverter::toString((*it).fps) << "\n";
824        }
825
826        std::stringstream d; d << "saved " << i << " frames to file " << filename;
827        Ogre::LogManager::getSingleton().logMessage(d.str());
828
829        ofstr.close();
830}
831//-----------------------------------------------------------------------
832void TerrainFrameListener::loadFrames(const std::string filename, 
833                                                                          FrameInfoContainer &frameInfo)
834{
835        std::ifstream ifstr(filename.c_str());
836        char line[256];
837        frame_info info;
838
839        // reset current values
840        frameInfo.clear();
841       
842        mCurrentFrame = 0;
843        int i = 0;
844        while (!ifstr.eof())
845        {
846                ifstr.getline(line, 256);
847                sscanf(line, "%f %f %f %f %f %f %f %f %f", &info.position.x, &info.position.y, &info.position.z,
848                           &info.orientation.w, &info.orientation.x, &info.orientation.y, &info.orientation.z,
849                           &info.timeElapsed, &info.fps);
850               
851                mFrameInfo.push_back(info);
852               
853                // std::stringstream d; d << StringConverter::toString(info.position) << " " << StringConverter::toString(info.orientation);
854                // LogManager::getSingleton().logMessage(d.str());
855                ++ i;
856        }
857       
858        std::stringstream d;
859        d << "loaded " << i << " frames from file " << filename;
860        Ogre::LogManager::getSingleton().logMessage(d.str());
861
862        ifstr.close();
863}
864//-----------------------------------------------------------------------
865void TerrainFrameListener::nextAppState()
866{
867        mCurrentFrame = 0;
868        int lastState = mAppState;
869
870        // transition to the next state
871        mAppState = (mAppState + 1) % STATE_NUM;
872
873        // if last state was replay state: post process
874        if (lastState == REPLAY)
875        {
876        // reset debug text
877                mWindow->setDebugText("");
878                               
879                // hack for producing demo:
880                // we produced precomputed fps during the last replay =>
881                // save them to file
882                if (mSavePrecomputedFps) //!mPrecomputedFpsFrameInfo.empty())
883                {
884                        std::string filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out";
885
886                        writeFrames(filename, mPrecomputedFpsFrameInfo);
887                        mPrecomputedFpsFrameInfo.clear();
888                }
889
890                std::stringstream d;
891                mWalkthroughStats.Print(d, msApprevAlgorithmCaptions[mCurrentAlgorithm]);
892               
893                LogManager::getSingleton().logMessage(d.str());
894        }
895       
896        //-- replay recorded walkthrough
897        if (mAppState == REPLAY)
898        {
899                // no standard recording during replay
900                mRecordFrames = false;
901
902                // no stats information
903                mWindow->setDebugText("");
904
905                // clear previous walktrough
906                mFrameInfo.clear();
907
908                std::string filename;
909               
910                // if recording demo,
911                // we use precomputed fps which corresponds to current method,
912                // e.g., for chc we load precomputed chc fps from disc.
913                if (mRecordDemo)
914                {
915                        filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out";
916                }
917                else // standard filename
918                {
919                        filename = frames_out_filename;
920                }
921
922                //-- load recorded walkthrough from disk
923                loadFrames(filename, mFrameInfo);
924               
925               
926                // if there are still no recorded frames,
927                // no walkthrough was recorded => set next state
928                if (mFrameInfo.empty())
929                {
930                        nextAppState();
931                }
932                else // actual replay
933                {
934                        mWindow->setDebugText("Replay");
935                       
936                        // reset, because we measure fps stats during walkthrough
937                        // (warning: average fps broken)
938                        mWindow->resetStatistics();
939                        mWalkthroughStats.Reset();
940
941                        //-- initialise frame data
942                        mReplayTimeElapsed = 0;
943
944                        mCamNode->setPosition(mFrameInfo[0].position);
945                        mCamNode->setOrientation(mFrameInfo[0].orientation);
946                }
947        }
948
949}
950//-----------------------------------------------------------------------
951void TerrainFrameListener::toggleRecord()
952{
953        mRecordFrames = !mRecordFrames;
954
955        if (mRecordFrames)
956        {
957                // starting new recording => clear old frame info
958                mFrameInfo.clear();
959        }
960        else // recording just ended => write frame info to file
961        {
962                writeFrames(frames_out_filename, mFrameInfo);
963                mWindow->setDebugText("");
964        }
965}
966//-----------------------------------------------------------------------
967void TerrainFrameListener::changeThreshold(int incr)
968{
969        mVisibilityThreshold += incr;
970
971        if (mVisibilityThreshold < 0)
972        {
973                mVisibilityThreshold = 0;
974        }
975
976        char str[100]; sprintf(str,": %d", mVisibilityThreshold);
977
978        mSceneMgr->setOption("Threshold", &mVisibilityThreshold);
979        mThresholdInfo->setCaption(str);
980}
981//-----------------------------------------------------------------------
982void TerrainFrameListener::changeAssumedVisibility(int incr)
983{
984        mAssumedVisibility += incr;
985
986        if (mAssumedVisibility < 0)
987        {       
988                mAssumedVisibility = 0;
989        }
990
991        char str[100]; sprintf(str,": %d", mAssumedVisibility);
992
993        mSceneMgr->setOption("AssumedVisibility", &mAssumedVisibility);
994        mAssumedVisibilityInfo->setCaption(str);
995}
996//-----------------------------------------------------------------------
997void TerrainFrameListener::changeVizScale(const int incr)
998{
999        mVizScale += incr;
1000
1001        if (mVizScale < 1)
1002        {       
1003                mVizScale = 1;
1004        }
1005
1006        mSceneMgr->setOption("NodeVizScale", &mVizScale);
1007}
1008//-----------------------------------------------------------------------
1009void TerrainFrameListener::changeFloorDist(const float incr)
1010{
1011        mFloorDist += incr;
1012
1013        if (mFloorDist < 2)
1014        {       
1015                mFloorDist = 2;
1016        }
1017}
1018//-----------------------------------------------------------------------
1019void TerrainFrameListener::zoomVizCamera(int zoom)
1020{
1021        mVizCameraHeight += zoom;
1022
1023        if(mVizCameraHeight < 0)
1024                mVizCameraHeight = 0;
1025}
1026//-----------------------------------------------------------------------
1027void TerrainFrameListener::nextAlgorithm()
1028{
1029        // possible algorithms: 3 culling algorithms + standard rendering
1030        mCurrentAlgorithm = (mCurrentAlgorithm + 1) %
1031                (GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS + 1);
1032        applyCurrentAlgorithm();
1033}
1034//-----------------------------------------------------------------------
1035void TerrainFrameListener::applyObjectType()
1036{
1037        if (mCurrentObjectType >= 3) // TODO: define a constant
1038                mCurrentObjectType = 0;
1039
1040        // parameters for new object
1041        mTerrainContentGenerator->SetOffset(msObjectTerrainOffsets[mCurrentObjectType]);
1042        Real scale = msObjectScales[mCurrentObjectType];
1043        mTerrainContentGenerator->SetScale(Vector3(scale, scale, scale));
1044
1045        mCurrentObjectTypeInfo->setCaption(": " + msObjectCaptions[mCurrentObjectType]);
1046}
1047//-----------------------------------------------------------------------
1048void TerrainFrameListener::applyCurrentAlgorithm()
1049{
1050        bool isNormalExecution;
1051       
1052        if (mCurrentAlgorithm < GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS)
1053        {
1054                isNormalExecution = false;
1055                mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
1056        }
1057        else
1058        {       // standard rendering without changed render queue flow
1059                isNormalExecution = true;
1060        }
1061       
1062        mSceneMgr->setOption("NormalExecution", &isNormalExecution);
1063        mAlgorithmInfo->setCaption(": " + msAlgorithmCaptions[mCurrentAlgorithm]);
1064
1065        if (1)
1066        {
1067                std::stringstream d; d << "algorithm: " << msAlgorithmCaptions[mCurrentAlgorithm];
1068                Ogre::LogManager::getSingleton().logMessage(d.str());
1069        }
1070}
1071//-----------------------------------------------------------------------
1072void TerrainFrameListener::updateStats()
1073{
1074        unsigned int opt = 0;
1075        char str[100];
1076       
1077        static String currFpsString = "Current FPS: ";
1078        static String avgFpsString = "Average FPS: ";
1079        static String bestFpsString = "Best FPS: ";
1080        static String worstFpsString = "Worst FPS: ";
1081        static String trisString = "Triangle Count: ";
1082
1083        int currentFps;
1084       
1085        // HACK for demo: use precomputed FPS instead of real FPS
1086        if (mRecordDemo)
1087        {
1088                currentFps = mPrecomputedFps;
1089        }
1090        else
1091        {
1092                currentFps = mWindow->getStatistics().lastFPS;
1093        }
1094
1095#if 0
1096        // HACK: take pure rendering time, only measures the render call
1097        long pureRenderTime = mTimeFrameEnded - mTimeFrameStarted;
1098
1099        if (pureRenderTime)
1100        {
1101                mPureRenderTimeFps = 1000.0 / (float) pureRenderTime;
1102        }
1103        currentFps = mPureRenderRenderTimeFps;
1104        //std::stringstream d; d << "Pure render time fps: " << mPureRenderTimeFps << "\n";
1105        //Ogre::LogManager::getSingleton().logMessage(d.str());
1106#endif
1107       
1108        unsigned int nodeInfo[3];
1109    mSceneMgr->getOption("NumRenderedNodes", nodeInfo);
1110        mSceneMgr->getOption("NumQueryCulledNodes", nodeInfo+1);
1111        mSceneMgr->getOption("NumFrustumCulledNodes", nodeInfo+2);
1112
1113
1114        mWalkthroughStats.UpdateFrame(currentFps,
1115                                                                  mWindow->getBestFPS(),
1116                                                                  mWindow->getWorstFPS(),
1117                                                                  (int)mWindow->getTriangleCount(),
1118                                                                  nodeInfo[0],
1119                                                                  nodeInfo[1],
1120                                                                  nodeInfo[2]);
1121
1122        // HACK: compute average fps ourselfs, because ogre avg. fps is wrong
1123        // TODO: update only once per second
1124        float avgFps = (float)mWalkthroughStats.mAccFps / (float)(mWalkthroughStats.mFrameCount);
1125       
1126
1127        // update stats when necessary
1128    try
1129        {
1130                OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
1131                OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
1132                OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
1133                OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
1134
1135                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
1136
1137                // HACK: take newly computed avg. fps instead of Ogre avg fps and update only once per second
1138                if (mTimeDelay < 0)
1139                {               
1140                        guiAvg->setCaption(avgFpsString + StringConverter::toString(avgFps) + " ms");
1141                        //guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps));
1142                }
1143
1144                if (0)
1145                {
1146                        std::stringstream d;
1147                        d << "fps: " << StringConverter::toString(currentFps) << ", "
1148                          << "avg fps: " << StringConverter::toString(avgFps);
1149                        LogManager::getSingleton().logMessage(d.str());
1150                }
1151
1152                //guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
1153                guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps));
1154               
1155                //std::stringstream d; d << "frame rate :" << stats.lastFPS;
1156                //Ogre::LogManager::getSingleton().logMessage(d.str());
1157
1158                guiBest->setCaption(bestFpsString + StringConverter::toString(stats.bestFPS)
1159                                                        + " " + StringConverter::toString(stats.bestFrameTime) + " ms");
1160                guiWorst->setCaption(worstFpsString + StringConverter::toString(stats.worstFPS)
1161                                                         + " " + StringConverter::toString(stats.worstFrameTime) + " ms");
1162
1163                OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
1164        guiTris->setCaption(trisString + StringConverter::toString(stats.triangleCount));
1165               
1166                //LogManager::getSingleton().logMessage(StringConverter::toString(stats.triangleCount));
1167
1168                OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
1169                guiDbg->setCaption(mWindow->getDebugText());
1170
1171
1172                //-- culling stats
1173
1174                mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt);
1175                mFrustumCulledNodesInfo->setCaption(str);
1176
1177                mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt);
1178                mQueryCulledNodesInfo->setCaption(str);
1179       
1180                mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt);
1181                mHierarchyNodesInfo->setCaption(str);
1182
1183                mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt);
1184                mRenderedNodesInfo->setCaption(str);
1185
1186                sprintf(str,": %d", mTerrainContentGenerator->GetObjectCount());
1187                mObjectsCountInfo->setCaption(str);
1188
1189                // take old value into account in order to create no sudden changes
1190                mSceneMgr->getOption("NumQueriesIssued", &opt);
1191                mDelayedQueriesIssued = mDelayedQueriesIssued * 0.8 + (float)opt * 0.2f;
1192                sprintf(str,": %d", (int)mDelayedQueriesIssued);
1193                mQueriesIssuedInfo->setCaption(str);
1194
1195                mSceneMgr->getOption("NumTraversedNodes", &opt);
1196                mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2f;
1197                sprintf(str,": %d", (int)mDelayedTraversedNodes);
1198                mTraversedNodesInfo->setCaption(str);
1199
1200                if (mRecordVideo)
1201                {
1202                        // update stats for demo
1203                        mMyStatsAlgorithmInfo->setCaption(msApprevAlgorithmCaptions[mCurrentAlgorithm]);
1204                        sprintf(str,": %d", (int)currentFps);
1205                        mMyStatsFpsInfo->setCaption(str);
1206                }
1207
1208        }
1209        catch (...)
1210        {
1211                // ignore
1212        }
1213}
1214//-----------------------------------------------------------------------
1215void TerrainFrameListener::setTestGeometryForVisibleLeaves(bool testGeometryForVisibleLeaves)
1216{
1217        mSceneMgr->setOption("TestGeometryForVisibleLeaves", &mTestGeometryForVisibleLeaves);
1218       
1219        /* disable optimization which tests geometry instead of aabb
1220         * for "delayed" rendering of transparents (i.e., render transparents after all the solids)
1221         * because otherwise visible transparents could be skipped
1222         */
1223        bool delayedRendering = !mTestGeometryForVisibleLeaves;
1224
1225        mSceneMgr->setOption("DelayRenderTransparents", &delayedRendering);
1226
1227        if (mTestGeometryForVisibleLeaves)
1228        {
1229                mTestGeometryForVisibleLeavesInfo->setCaption(": true");
1230        }
1231        else
1232        {
1233                mTestGeometryForVisibleLeavesInfo->setCaption(": false");
1234        }
1235}
1236//-----------------------------------------------------------------------
1237void TerrainFrameListener::toggleShowOctree()
1238{
1239        mShowOctree = !mShowOctree;
1240        mSceneMgr->setOption("ShowOctree", &mShowOctree);
1241}
1242//-----------------------------------------------------------------------
1243void TerrainFrameListener::toggleShowViewCells()
1244{
1245        mShowViewCells = !mShowViewCells;
1246        mSceneMgr->setOption("ShowViewCells", &mShowViewCells);
1247}
1248//-----------------------------------------------------------------------
1249void TerrainFrameListener::toggleUseViewCells()
1250{
1251        // HACK: no view cells for hilly terrain
1252        if (mApplication->msShowHillyTerrain)
1253                return;
1254
1255        mUseViewCells = !mUseViewCells;
1256
1257        // load on demand
1258        if (mUseViewCells)// && !mViewCellsLoaded)
1259        {
1260                LogManager::getSingleton().logMessage("using view cells");
1261                mLoadingOverlay->show();
1262
1263                // call once to load view cell loading overlay
1264                mWindow->update();
1265                mViewCellsLoaded = mApplication->LoadViewCells(mApplication->mViewCellsFilename);
1266               
1267                if (!mViewCellsLoaded)
1268                        LogManager::getSingleton().logMessage("loading view cells failed");
1269                else
1270                        LogManager::getSingleton().logMessage("view cells successfully loaded");
1271       
1272                mLoadingOverlay->hide();
1273        }
1274
1275        if (mUseViewCells)
1276                mViewCellsInfo->setCaption(": on");
1277        else
1278                mViewCellsInfo->setCaption(": off");
1279
1280        mSceneMgr->setOption("UseViewCells", &mUseViewCells);
1281}
1282//-----------------------------------------------------------------------
1283void TerrainFrameListener::toggleUseVisibilityFilter()
1284{
1285        mUseVisibilityFilter = !mUseVisibilityFilter;
1286        mSceneMgr->setOption("UseVisibilityFilter", &mUseVisibilityFilter);
1287}
1288//-----------------------------------------------------------------------
1289void TerrainFrameListener::toggleUseDepthPass()
1290{
1291        mUseDepthPass = !mUseDepthPass;
1292
1293        mSceneMgr->setOption("UseDepthPass", &mUseDepthPass);
1294       
1295        if (mUseDepthPass)
1296        {
1297                mUseDepthPassInfo->setCaption(": true");
1298        }
1299        else
1300        {
1301                mUseDepthPassInfo->setCaption(": false");
1302        }
1303}
1304//-----------------------------------------------------------------------
1305void TerrainFrameListener::toggleFlushQueue()
1306{
1307        mFlushQueue = !mFlushQueue;
1308
1309        mSceneMgr->setOption("FlushQueue", &mFlushQueue);
1310       
1311        if (mFlushQueue)
1312        {
1313                LogManager::getSingleton().logMessage("flushing queue");
1314                //mFlushQueueInfo->setCaption(": true");
1315        }
1316        else
1317        {
1318                LogManager::getSingleton().logMessage("not flushing queue");
1319                //mFlushQueueInfo->setCaption(": false");
1320        }
1321}
1322
1323//-----------------------------------------------------------------------
1324void TerrainFrameListener::toggleShowViz()
1325{
1326        mVisualizeCulledNodes = mShowVisualization = !mShowVisualization;
1327       
1328        // create viewport with priority VIZ_VIEWPORT_Z_ORDER:
1329        // will be rendered over standard viewport
1330        if (mShowVisualization)
1331        {       
1332                Viewport *vizvp = mWindow->addViewport(mVizCamera,
1333                        VIZ_VIEWPORT_Z_ORDER, 0.6, 0.6, 0.4, 0.4);
1334                               
1335                vizvp->setBackgroundColour(ColourValue(0.0, 0.3, 0.2, 1));
1336
1337                vizvp->setOverlaysEnabled(false);
1338                // Alter the camera aspect ratio to match the viewport
1339        mVizCamera->setAspectRatio(Real(vizvp->getActualWidth()) /
1340                                                                   Real(vizvp->getActualHeight()));
1341               
1342                mSceneMgr->setOption("VisualizeCulledNodes", &mVisualizeCulledNodes);
1343       
1344        }
1345        else
1346        {
1347                // remove visualization viewport
1348                mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER);
1349
1350                // octree bounding boxes are shown for visualization purpose, reset now
1351                mSceneMgr->setOption("ShowOctree", &mShowOctree);
1352        }
1353}
1354//-----------------------------------------------------------------------
1355void TerrainFrameListener::toggleShowShadows()
1356{
1357        mShowShadows = !mShowShadows;
1358
1359        mSunLight->setCastShadows(mShowShadows);
1360
1361        if (mShowShadows)
1362        {
1363                mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
1364                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
1365                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);           
1366        }
1367        else
1368        {
1369                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
1370        }
1371
1372}
1373//-----------------------------------------------------------------------
1374void TerrainFrameListener::nextNodeVizMode()
1375{
1376        mNodeVizMode = (mNodeVizMode + 1) % NODEVIZ_MODES_NUM;
1377
1378        bool renderNodesForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES) ||
1379                (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
1380        bool renderNodesContentForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
1381        //bool renderNodesContentForViz = mNodeVizMode == NODEVIZ_RENDER_GEOMETRY;
1382
1383        mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz);
1384        mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz);
1385}
1386//-----------------------------------------------------------------------
1387void TerrainFrameListener::keyPressed(KeyEvent* e)
1388{
1389        // hide exact visibility query overlay
1390        if (mShowQueryStats)
1391        {
1392                mQueryOverlay->hide();
1393                mShowQueryStats = false;
1394        }
1395
1396        switch(e->getKey())
1397        {
1398       
1399        case KC_SUBTRACT:
1400                changeThreshold(-10);
1401                break;
1402        case KC_ADD:
1403                changeThreshold(10);
1404                break;
1405
1406        case KC_ESCAPE:
1407                mShutdownRequested = true;
1408                e->consume();
1409                return;
1410
1411        case KC_SPACE:
1412                nextAlgorithm();
1413                break;
1414
1415        case KC_LSHIFT:
1416                mShiftPressed = true;
1417                break;
1418        case KC_DELETE:
1419                mDeleteObjects = true;
1420                break;
1421
1422        case KC_C:
1423                if (mItemBufferMode != GtpVisibility::QueryManager::GEOMETRY_VISIBILITY)
1424                {
1425                        mItemBufferMode = GtpVisibility::QueryManager::GEOMETRY_VISIBILITY;
1426                }
1427                else
1428                {
1429                        mItemBufferMode = GtpVisibility::QueryManager::PATCH_VISIBILITY;
1430                }
1431                break;
1432         case KC_E: // hack for recording demo using precomputed fps
1433                mSavePrecomputedFps = !mSavePrecomputedFps;
1434                break;
1435
1436    case KC_F:
1437                nextFilter();
1438                break;
1439        case KC_G:
1440                mTestGeometryForVisibleLeaves = !mTestGeometryForVisibleLeaves;
1441                setTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves);
1442                break;
1443        case KC_H:
1444                toggleShowShadows();
1445                break;
1446        case KC_L:
1447                toggleShowViewCells();
1448                break;
1449        case KC_M: // hack for recording demo using precomputed fps
1450                mRecordDemo = !mRecordDemo;
1451                break;
1452        case KC_O:
1453                switchMouseMode();
1454                break;
1455        case KC_P:
1456                toggleDisplayCameraDetails();
1457                break;
1458        case KC_V:
1459                toggleUseViewCells();
1460                break;
1461        case KC_Q:
1462                toggleUseVisibilityFilter();
1463                break;
1464        case KC_R:
1465                nextSceneDetailLevel();
1466                break;
1467        case KC_T:
1468                toggleShowOctree();
1469                break;
1470        case KC_U:
1471                mCamNode->resetOrientation();
1472                mCamNode->setPosition(mApplication->mInitialPosition);
1473                break;
1474        case KC_X:
1475                toggleUseDepthPass();
1476                break;
1477        case KC_I:
1478                toggleFlushQueue();
1479                break;
1480        case KC_Z:
1481                mCamNode->resetOrientation();
1482                break;
1483
1484
1485        ///////////////
1486        //-- visualization
1487
1488        case KC_1:
1489                toggleShowViz();
1490                break;
1491        case KC_2:
1492                nextNodeVizMode();
1493                break;
1494        case KC_7:
1495                mTerrainContentGenerator->WriteObjects(objects_out_filename);
1496                break;
1497        case KC_8:
1498                changeAssumedVisibility(-5);
1499                // changeAssumedVisibility(-500);
1500                break;
1501        case KC_9:
1502                changeAssumedVisibility(5);
1503                // changeAssumedVisibility(500);
1504                break;
1505
1506//#if USE_PERFHUD
1507        case KC_F1:
1508                toggleShowHelp();
1509                break;
1510        case KC_F2:
1511                mStatsOn = !mStatsOn;
1512                showStats(mStatsOn);
1513                break;
1514        case KC_F3:
1515                nextAppState();
1516                break;
1517        case KC_F4:
1518                toggleRecord();
1519                break;
1520
1521        case KC_F5:
1522                applyVisibilityQuery(false, mShiftPressed, mUseItemBuffer);
1523                break;
1524
1525        case KC_F6:
1526                applyVisibilityQuery(true, mShiftPressed, mUseItemBuffer);
1527                break;
1528       
1529        case KC_F7:
1530                ++ mCurrentObjectType;
1531                applyObjectType();
1532                break;
1533//#endif
1534
1535        case KC_F8:
1536                {       // generate new objects
1537                        const int objNum = 500;
1538                        mApplication->generateScene(objNum, mCurrentObjectType);
1539                }
1540                break;
1541        case KC_F9:
1542                mUseAnimation = !mUseAnimation;
1543                break;
1544
1545        case KC_F10:
1546                mRecordVideo = !mRecordVideo;
1547                       
1548        case KC_F11:
1549                takeScreenshot();
1550                break;
1551       
1552       
1553        //KEY_PRESSED(KC_F3, 0.3, writeFrames());
1554        //KEY_PRESSED(KC_F4, 0.3, loadFrames());
1555        default:
1556                break;
1557        }
1558
1559        CEGUI::System::getSingleton().injectKeyDown(e->getKey());
1560        CEGUI::System::getSingleton().injectChar(e->getKeyChar());
1561        e->consume();
1562}
1563//-----------------------------------------------------------------------
1564void TerrainFrameListener::keyReleased(KeyEvent* e)
1565{
1566        if (e->getKey() == KC_LSHIFT)
1567        {
1568                mShiftPressed = false;
1569        }
1570       
1571        CEGUI::System::getSingleton().injectKeyUp(e->getKey());
1572        e->consume();
1573}
1574//-----------------------------------------------------------------------
1575void TerrainFrameListener::keyClicked(KeyEvent* e)
1576{
1577        // Do nothing
1578        e->consume();
1579}
1580//-----------------------------------------------------------------------
1581void TerrainFrameListener::addFrameInfo(FrameInfoContainer &frameInfos,
1582                                                                                SceneNode *camNode,
1583                                                                                Real timeElapsed)
1584{
1585        frame_info info;
1586
1587        info.orientation = mCamNode->getOrientation();
1588        info.position = mCamNode->getPosition();
1589        info.timeElapsed = timeElapsed;
1590        info.fps = mWindow->getStatistics().lastFPS;
1591
1592        frameInfos.push_back(info);
1593}
1594//-----------------------------------------------------------------------
1595void TerrainFrameListener::setCurrentFrameInfo(const Real timeElapsed)
1596{
1597        //-- find current frame relative to elapsed frame time         
1598        mReplayTimeElapsed -= timeElapsed;
1599       
1600        while ((mReplayTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1))
1601        {
1602                mReplayTimeElapsed += mFrameInfo[mCurrentFrame ++].timeElapsed;
1603        }
1604
1605
1606        // TODO: crashes here if recording / replaying on the same time!!
1607        const frame_info new_frame = mFrameInfo[mCurrentFrame];
1608        const frame_info old_frame = mFrameInfo[mCurrentFrame - 1];
1609               
1610        /////////////
1611        //-- interpolate frames
1612        Real factor = 1;
1613
1614        if (old_frame.timeElapsed > 0)
1615        {
1616                factor = mReplayTimeElapsed / old_frame.timeElapsed;
1617        }
1618
1619        const Vector3 camPos = old_frame.position + factor
1620                * (new_frame.position - old_frame.position);
1621
1622        // interpolate the orientation
1623        const Quaternion camOrienation =
1624                Quaternion::Slerp(factor, old_frame.orientation, new_frame.orientation, true);
1625
1626        // HACK for demo: interpolate precomputed fps
1627        mPrecomputedFps = old_frame.fps + factor * (new_frame.fps - old_frame.fps);
1628
1629        mCamNode->setPosition(camPos);
1630        mCamNode->setOrientation(camOrienation);
1631       
1632        // stop replaying after one full walkthrough
1633        if (mCurrentFrame == (int)mFrameInfo.size() - 1)
1634        {
1635                nextAppState();
1636        }
1637}
1638//-----------------------------------------------------------------------   
1639bool TerrainFrameListener::processUnbufferedKeyInput(const FrameEvent& evt)
1640{
1641        bool cursorPressed = false;
1642       
1643        /* Move camera forward by keypress. */
1644    if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W))
1645        {
1646                mTranslateVector.z = -mMoveScale;
1647                cursorPressed = true;
1648        }
1649    /* Move camera backward by keypress. */
1650    if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S))
1651    {
1652                mTranslateVector.z = mMoveScale;
1653                cursorPressed = true;
1654    }
1655
1656        if (mInputDevice->isKeyDown(KC_A))
1657        {
1658                mTranslateVector.x -= mMoveScale;
1659                mTranslateVector.y += mMoveScale;
1660
1661                cursorPressed = true;
1662        }
1663
1664        if (mInputDevice->isKeyDown(KC_D))
1665        {
1666                mTranslateVector.x += mMoveScale;
1667                mTranslateVector.y -= mMoveScale;
1668
1669                cursorPressed = true;
1670        }
1671
1672    if (mInputDevice->isKeyDown(KC_RIGHT))
1673    {
1674        mCamNode->yaw(-mRotScale, Ogre::Node::TS_WORLD);
1675                cursorPressed = true;
1676    }
1677
1678    if (mInputDevice->isKeyDown(KC_LEFT))
1679    {
1680        mCamNode->yaw(mRotScale, Ogre::Node::TS_WORLD);
1681                cursorPressed = true;
1682    }
1683        // visualization camera
1684        if (mInputDevice->isKeyDown(KC_3))
1685        {
1686                zoomVizCamera(50);
1687        }
1688        if (mInputDevice->isKeyDown(KC_4))
1689        {
1690                zoomVizCamera(-50);
1691        }
1692
1693        if (mInputDevice->isKeyDown(KC_5))
1694        {
1695                changeVizScale(-1);
1696        }
1697
1698        if (mInputDevice->isKeyDown(KC_6))
1699        {
1700                changeVizScale(1);
1701        }
1702       
1703        if (mInputDevice->isKeyDown(KC_7))
1704        {
1705                changeFloorDist(-1);
1706        }
1707       
1708        if (mInputDevice->isKeyDown(KC_8))
1709        {
1710                changeFloorDist(1);
1711        }
1712
1713
1714        // show the results
1715        if (cursorPressed && mShowQueryStats)
1716        {
1717                mQueryOverlay->hide();
1718                mShowQueryStats = false;
1719        }
1720
1721    // Return true to continue rendering
1722    return true;
1723}
1724//-----------------------------------------------------------------------
1725void TerrainFrameListener::nextFilter()
1726{
1727        switch (mFiltering)
1728        {
1729        case TFO_BILINEAR:
1730                mFiltering = TFO_TRILINEAR;
1731                mAniso = 1;
1732                break;
1733        case TFO_TRILINEAR:
1734                mFiltering = TFO_ANISOTROPIC;
1735                mAniso = 8;
1736                break;
1737        case TFO_ANISOTROPIC:
1738                mFiltering = TFO_BILINEAR;
1739                mAniso = 1;
1740                break;
1741        default:
1742                break;
1743        }
1744
1745    MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
1746    MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
1747
1748        // reload stats
1749    showStats(mStatsOn);
1750}
1751//-----------------------------------------------------------------------
1752void TerrainFrameListener::nextSceneDetailLevel()
1753{
1754#if OGRE_103
1755        mSceneDetailIndex = (mSceneDetailIndex + 1) % 3;
1756        switch (mSceneDetailIndex)
1757        {
1758                case 0:
1759                        mCamera->setDetailLevel(SDL_SOLID);
1760                        break;
1761                case 1:
1762                        mCamera->setDetailLevel(SDL_WIREFRAME);
1763                        break;
1764                case 2:
1765                        mCamera->setDetailLevel(SDL_POINTS);
1766                        break;
1767        }
1768#endif
1769}
1770//-----------------------------------------------------------------------
1771void TerrainFrameListener::takeVideoFrame(std::ofstream &ofstr)
1772{
1773        char name[50];
1774
1775        sprintf(name, "frame_%05d.tga", ++mNumVideoFrames);
1776    mWindow->writeContentsToFile(name);
1777    //mWindow->setDebugText(String("Wrote ") + name);
1778
1779        ofstr << name << "\n";
1780}
1781//-----------------------------------------------------------------------
1782void TerrainFrameListener::takeScreenshot()
1783{
1784        char name[50];
1785
1786        sprintf(name, "screenshot_%05d.png", ++mNumScreenShots);
1787    mWindow->writeContentsToFile(name);
1788    //mWindow->setDebugText(String("Wrote ") + name);
1789}
1790//-----------------------------------------------------------------------
1791void TerrainFrameListener::toggleDisplayCameraDetails()
1792{
1793        mDisplayCameraDetails = !mDisplayCameraDetails;
1794       
1795    if (!mDisplayCameraDetails)
1796        {
1797                mWindow->setDebugText("");
1798        }
1799}
1800//-----------------------------------------------------------------------
1801void TerrainFrameListener::showStats(bool show)
1802{
1803        if (mDebugOverlay && mCullStatsOverlay)
1804        {
1805                if (show)
1806                {
1807                        mDebugOverlay->show();
1808                        mCullStatsOverlay->show();
1809                }
1810                else
1811                {
1812                        mDebugOverlay->hide();
1813                        mCullStatsOverlay->hide();
1814                }
1815        }
1816}
1817
1818//-----------------------------------------------------------------------
1819void TerrainFrameListener::toggleShowHelp()
1820{
1821        mShowHelp = !mShowHelp;
1822
1823        if (mShowHelp)
1824        {
1825                mHelpOverlay->show();
1826        }
1827        else
1828        {
1829                mHelpOverlay->hide();
1830        }
1831}
1832//-----------------------------------------------------------------------
1833void TerrainFrameListener::initOverlayElement(OverlayElement **elInfo, String ext,
1834                                                                                          String name, int top, String caption)
1835{
1836        OverlayElement *el =
1837                OverlayManager::getSingleton().getOverlayElement(ext + name);
1838
1839        (*elInfo) = OverlayManager::getSingleton().getOverlayElement(ext + name + "Info");
1840        (*elInfo)->setCaption(caption);
1841
1842        el->setTop(top);
1843        (*elInfo)->setTop(top);
1844}
1845//-----------------------------------------------------------------------
1846void TerrainFrameListener::initHelpOverlayElement(String name, int top)
1847{
1848        OverlayElement *el = OverlayManager::getSingleton().getOverlayElement(
1849                "Example/Visibility/Help/" + name);
1850
1851        el->setTop(top);
1852}
1853//-----------------------------------------------------------------------
1854void TerrainFrameListener::initHelpOverlay()
1855{
1856        const int vert_space = 15;
1857        int top = 30;
1858
1859        initHelpOverlayElement("ShowHelp", top); top += vert_space;
1860        initHelpOverlayElement("Stats", top); top += vert_space;
1861        initHelpOverlayElement("AppState", top); top += vert_space;
1862        initHelpOverlayElement("Recorded", top); top += vert_space;
1863        initHelpOverlayElement("Animation", top); top += vert_space;
1864        initHelpOverlayElement("Video", top); top += vert_space;
1865        initHelpOverlayElement("Screenshots", top); top += vert_space;
1866        initHelpOverlayElement("WriteOut", top); top += vert_space;
1867
1868
1869        top +=vert_space;
1870        initHelpOverlayElement("SceneDetail", top); top += vert_space;
1871        initHelpOverlayElement("DisplayCameraDetails", top); top += vert_space;
1872        initHelpOverlayElement("DisplayOctree", top); top += vert_space;
1873        initHelpOverlayElement("UseShadows", top); top += vert_space;
1874        initHelpOverlayElement("Filter", top); top += vert_space;
1875
1876        //-- visualization
1877        top += vert_space;
1878        initHelpOverlayElement("VizSection", top); top += vert_space;
1879        initHelpOverlayElement("Viz", top); top += vert_space;
1880        initHelpOverlayElement("NextVizMode", top); top += vert_space;
1881        initHelpOverlayElement("ZoomViz", top); top += vert_space;
1882
1883
1884        //-- visibility queries
1885        top += vert_space;
1886        initHelpOverlayElement("VisQuery", top); top += vert_space;
1887        initHelpOverlayElement("FromCameraQuery", top); top += vert_space;
1888        initHelpOverlayElement("FromPointQuery", top); top += vert_space;
1889        initHelpOverlayElement("QueryType", top); top += vert_space;
1890        initHelpOverlayElement("QueryTarget", top); top += vert_space;
1891
1892        //-- object generation
1893        top += vert_space;
1894        initHelpOverlayElement("SceneObjects", top); top += vert_space;
1895        initHelpOverlayElement("PlaceObjects", top); top += vert_space;
1896        initHelpOverlayElement("GenerateObjects", top); top += vert_space;
1897        initHelpOverlayElement("RemoveObjects", top); top += vert_space;
1898        initHelpOverlayElement("DropObject", top); top += vert_space;
1899
1900        OverlayElement *helpPanel = OverlayManager::getSingleton().getOverlayElement(
1901                "Example/Visibility/Help/HelpPanel");
1902
1903        helpPanel->setHeight(top + 10);
1904}
1905//-----------------------------------------------------------------------
1906void TerrainFrameListener::initVisStatsOverlay()
1907{
1908        const int border_height = 10;
1909        const int vert_space = 15;
1910
1911        //-- visibility culling stats overlay
1912        int top = border_height;
1913
1914        String ext = "Example/Visibility/";
1915       
1916        initOverlayElement(&mAlgorithmInfo, ext, "Algorithm", top,
1917                ": " + msAlgorithmCaptions[mCurrentAlgorithm]); top += vert_space;
1918
1919        initOverlayElement(&mThresholdInfo, ext, "Threshold", top, ": 0"); top += vert_space;
1920        initOverlayElement(&mTestGeometryForVisibleLeavesInfo, ext,
1921                                           "TestGeometryForVisibleLeaves", top, ": true"); top += vert_space;
1922        initOverlayElement(&mUseDepthPassInfo, ext, "UseDepthPass", top, ": false"); top += vert_space;
1923        initOverlayElement(&mAssumedVisibilityInfo, ext, "AssumedVisibility", top, ": 0"); top += vert_space;
1924        initOverlayElement(&mCurrentObjectTypeInfo, ext, "CurrentObjectType", top, ": "); top += vert_space;
1925        initOverlayElement(&mViewCellsInfo, ext, "ViewCells", top, ": "); top += vert_space;
1926        //initOverlayElement(&mHelpInfo, ext, "Help", top, ": "); top += vert_space;
1927
1928        OverlayElement *optionsPanel = OverlayManager::getSingleton().
1929                getOverlayElement("Example/Visibility/VisibilityPanel");
1930
1931        optionsPanel->setHeight(top + border_height);
1932
1933        top = border_height;
1934        //ext = "Example/Visibility/";
1935        initOverlayElement(&mFrustumCulledNodesInfo, ext, "FrustumCulledNodes", top, ": 0"); top += vert_space;
1936        initOverlayElement(&mQueryCulledNodesInfo, ext, "QueryCulledNodes", top, ": 0"); top += vert_space;
1937        initOverlayElement(&mTraversedNodesInfo, ext, "TraversedNodes", top, ": 0"); top += vert_space;
1938        initOverlayElement(&mHierarchyNodesInfo, ext, "HierarchyNodes", top, ": 0"); top += vert_space;
1939        initOverlayElement(&mRenderedNodesInfo, ext, "RenderedNodes", top, ": 0"); top += vert_space;
1940        initOverlayElement(&mObjectsCountInfo, ext, "ObjectsCount", top, ": 0"); top += vert_space;
1941        initOverlayElement(&mQueriesIssuedInfo, ext, "QueriesIssued", top, ": 0"); top += vert_space;
1942
1943        OverlayElement *visPanel = OverlayManager::getSingleton().
1944                getOverlayElement("Example/Visibility/VisibilityStatsPanel");
1945
1946        visPanel->setHeight(top + border_height);
1947}
1948//-----------------------------------------------------------------------
1949void TerrainFrameListener::initQueryOverlay()
1950{
1951        const int border_height = 10;
1952        const int vert_space = 15;
1953
1954        //-- visibility culling stats overlay
1955        int top = border_height + 25;
1956
1957        const String ext = "Example/Visibility/Query/";
1958           
1959        initOverlayElement(&mQueryTypeInfo , ext, "QueryType", top,     ": 0"); top += vert_space;
1960       
1961        initOverlayElement(&mQueryVisibleNodesInfo , ext, "VisibleNodes", top,  ": 0"); top += vert_space;
1962        initOverlayElement(&mQueryVisibleGeometryInfo , ext, "VisibleGeometry", top,    ": 0"); top += vert_space;
1963        initOverlayElement(&mQueryVisiblePatchInfo , ext, "VisiblePatches", top,        ": 0"); top += vert_space;
1964       
1965        initOverlayElement(&mQueryNodeVisibilityInfo , ext, "NodeVisibility", top,      ": 0"); top += vert_space;
1966        initOverlayElement(&mQueryGeometryVisibilityInfo , ext, "GeometryVisibility", top,      ": 0"); top += vert_space;
1967        initOverlayElement(&mQueryPatchVisibilityInfo , ext, "PatchVisibility", top,    ": 0"); top += vert_space;
1968
1969        OverlayElement *queryPanel =
1970                OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/QueryPanel");
1971
1972        queryPanel->setHeight(top + border_height);
1973}
1974//-----------------------------------------------------------------------
1975void TerrainFrameListener::setAlgorithm(const int algorithm)
1976{
1977        mCurrentAlgorithm = algorithm;
1978        applyCurrentAlgorithm();
1979}
Note: See TracBrowser for help on using the repository browser.