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

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