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

Revision 924, 52.7 KB checked in by mattausch, 18 years ago (diff)

adding config loader

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