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

Revision 867, 51.0 KB checked in by mattausch, 18 years ago (diff)

kicked out toggling of arb / iv queries

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