source: trunk/VUT/work/TestCullingTerrain/TerrainFrameListener.cpp @ 316

Revision 316, 46.1 KB checked in by mattausch, 19 years ago (diff)

queries are realized as templates

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