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

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