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

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