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

Revision 679, 48.0 KB checked in by mattausch, 19 years ago (diff)

debug version: fixing render cost with bsp splits
removed natfx trees

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