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

Revision 154, 34.6 KB checked in by mattausch, 19 years ago (diff)

added item buffer queries.

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 "OgreItemBufferQueryManager.h"
12#include "OgreOcclusionQueriesQueryManager.h"
13
14
15
16
[115]17// output file for frame info
18const char* frames_out_filename = "frame.out";
19// output file for object positions / orientations
20const char* objects_out_filename = "objects.out";
21
22
[154]23// --- captions for overlays
24
[135]25String currentAlgorithmCaptions[GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS] =
[115]26{
[135]27        "View Frustum Culling",
[115]28        "Stop and Wait Culling",
29        "Coherent Hierarchical Culling"
30};
31
[154]32String queryTypeCaptions[] =
[135]33{
[154]34        "from camera",
35        "from viewpoint"
[135]36};
[115]37
[154]38String queryRelativeVisCaptions[] =
39{
40        "visible pixels",
41        "relative visibility"
42};
43
44String queryMethodCaptions[] =
45{
46        "occlusion queries",
47        "item buffer"
48};
49
[115]50//-----------------------------------------------------------------------
[133]51TerrainFrameListener::TerrainFrameListener(RenderWindow* win, Camera* cam,
[115]52                                                                           SceneManager *sceneManager,
53                                                                           CEGUI::Renderer *renderer,
54                                                                           TerrainContentGenerator *sceneGenerator,
55                                                                           Camera *vizCamera,
[121]56                                                                           SceneNode *camNode,
57                                                                           Light *sunLight):
[115]58mCamera(cam),
59mWindow(win),
60mNumScreenShots(0),
[120]61mTimeDelay(0),
[115]62mSceneDetailIndex(0),
63mMoveScale(0.0f),
64mRotScale(0.0f),
65mTranslateVector(Vector3::ZERO),
66mAniso(1),
67mFiltering(TFO_BILINEAR),
68mGUIRenderer(renderer),
69mSceneMgr(sceneManager),
70mCurrentObject(NULL),
71mTerrainContentGenerator(sceneGenerator),
72mVisibilityThreshold(0),
[146]73mAssumedVisibility(0),
[130]74mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING),
75//mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING),
[115]76mNodeVizMode(NODEVIZ_NONE),
77mVizCameraHeight(Real(2500.0)),
78mCamNode(camNode),
79mAppState(WALKTHROUGH),
80mCurrentFrame(0),
81mTimeElapsed(0),
82mRotateSpeed(72),
[120]83mMoveSpeed(50),
84mVizCamera(vizCamera),
85mStatsOn(true),
86mShutdownRequested(false),
87mLMouseDown(false),
88mRMouseDown(false),
89mShowOctree(false),
90mUseDepthPass(false),
91mUseOptimization(true),
92mShowVisualization(false),
93mCullCamera(false),
94mRecord(false),
[139]95mShowShadows(false),
[120]96mShowHelp(false),
97mDisplayCameraDetails(false),
[121]98mVisualizeCulledNodes(false),
[133]99mSunLight(sunLight),
[135]100mShiftPressed(false),
[151]101mShowQueryStats(false),
102mQueryManager(NULL),
103mVisibilityManager(NULL)
[115]104{
[130]105        //mInputDevice = PlatformManager::getSingleton().createInputReader();
106        //mInputDevice->initialise(win, true, true);
[135]107
[130]108        mEventProcessor = new EventProcessor();
109       
110        mEventProcessor->initialise(win);
111        mEventProcessor->startProcessingEvents();
[120]112        mEventProcessor->addMouseListener(this);
[115]113        mEventProcessor->addMouseMotionListener(this);
[133]114        mEventProcessor->addKeyListener(this);
[115]115
[130]116        mInputDevice = mEventProcessor->getInputReader();
117       
118
[115]119        // create ray query executor, used to place objects in terrain
120        mRayQueryExecutor = new RayQueryExecutor(mSceneMgr);
121       
[120]122        mHelpOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/HelpOverlay");
123        mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
[135]124        mQueryOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/QueryOverlay");
[115]125
[120]126        //-- visibility culling stats overlay
127        mCullStatsOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/DemoOverlay");
128       
[115]129        mAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/AlgorithmInfo");
130        mThresholdInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/ThresholdInfo");
[146]131        mUseOptimizationInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/UseOptimizationInfo");
132        mUseDepthPassInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/UseDepthPassInfo");
133        mAssumedVisibilityInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/AssumedVisibilityInfo");
134
[115]135        mFrustumCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/FrustumCulledNodesInfo");
136        mQueryCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/QueryCulledNodesInfo");
137    mTraversedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/TraversedNodesInfo");
138        mHierarchyNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/HierarchyNodesInfo");
139        mRenderedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/RenderedNodesInfo");
140        mObjectsInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/ObjectsInfo");
141        mQueriesIssuedInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/QueriesIssuedInfo");
142       
[135]143        mAlgorithmInfo->setCaption(": " + currentAlgorithmCaptions[mCurrentAlgorithm]);
[115]144        mThresholdInfo->setCaption(": 0");
145        mFrustumCulledNodesInfo->setCaption(": 0");
146        mQueryCulledNodesInfo->setCaption(": 0");
147        mTraversedNodesInfo->setCaption(": 0");
148        mHierarchyNodesInfo->setCaption(": 0");
149        mRenderedNodesInfo->setCaption(": 0");
150        mObjectsInfo->setCaption(": 0");
151        mUseOptimizationInfo->setCaption(": true");
152        mUseDepthPassInfo->setCaption(": false");
153        mQueriesIssuedInfo->setCaption(": 0");
[146]154        mAssumedVisibilityInfo->setCaption(": 0");
[115]155
[135]156
157        //-- visibility query stats overlay
158        mQueryTypeInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/QueryTypeInfo");
159        mQueryVisibleNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/VisibleNodesInfo");
160    mQueryVisibleGeometryInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/VisibleGeometryInfo");
161        mQueryNodeVisibilityInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/NodeVisibilityInfo");
162        mQueryGeometryVisibilityInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/GeometryVisibilityInfo");
163
[120]164        // show stats overlays
165        showStats(true);
166        //mHelpOverlay->show();
[115]167
168        // set culling algorithm type
169        setAlgorithm(mCurrentAlgorithm);
170
171        // set scene manager options
172        mSceneMgr->setOption("UseOptimization", &mUseOptimization);
[120]173
174        // apply delayed rendering (i.e., transparents after hierarchical culling pass)
175        // only if optimization is not used
176        bool delayRenderTransparents = !mUseOptimization;
177
178        mSceneMgr->setOption("DelayRenderTransparents", &delayRenderTransparents);
[115]179        mSceneMgr->setOption("UseDepthPass", &mUseDepthPass);
[120]180       
[115]181        mSceneMgr->setOption("ShowOctree", &mShowOctree);
182        mSceneMgr->setOption("CullCamera", &mCullCamera);
[139]183        mSceneMgr->setOption("PrepareVisualization", &mShowVisualization);
[130]184
[147]185        // reset statistics
186        resetStats();
[115]187}
188//-----------------------------------------------------------------------
[133]189TerrainFrameListener::~TerrainFrameListener()
[115]190{
191        delete mRayQueryExecutor;
[130]192        delete mEventProcessor;
[151]193
194        if (mQueryManager)
195        {
196                delete mQueryManager;
197                mQueryManager = NULL;
198        }
[115]199}
200//-----------------------------------------------------------------------
[133]201void TerrainFrameListener::mouseMoved(MouseEvent *e)
[115]202{
203        // Update CEGUI with the mouse motion
204    CEGUI::System::getSingleton().injectMouseMove(e->getRelX() *
205                mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight());
206}
207//-----------------------------------------------------------------------
[133]208void TerrainFrameListener::mousePressed(MouseEvent* e)
[115]209{
210     // Left mouse button down
211     if (e->getButtonID() & InputEvent::BUTTON0_MASK)
212     {
213                 CEGUI::MouseCursor::getSingleton().hide();
214
215                 // Setup the ray scene query
216         Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY());
217                 
[130]218                 //Vector3 queryResult; mRayQueryExecutor->executeRayQuery(&queryResult, mouseRay);
219                 
[115]220                 // Get results, create a node/entity on the position
221                 mCurrentObject = mTerrainContentGenerator->GenerateSceneObject(
[137]222                         mouseRay.getOrigin()/*queryResult*/, Vector3::ZERO, "robot");
[115]223               
224         mLMouseDown = true;
225     }
226     // Right mouse button down
227     else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
228     {
229         CEGUI::MouseCursor::getSingleton().hide();
230         mRMouseDown = true;
231     }
[133]232}
[115]233//-----------------------------------------------------------------------
[133]234void TerrainFrameListener::mouseReleased(MouseEvent* e)
[115]235{
236    // Left mouse button up
237    if (e->getButtonID() & InputEvent::BUTTON0_MASK)
238    {
239                CEGUI::MouseCursor::getSingleton().show();
240        mLMouseDown = false;
241    }
242    // Right mouse button up
243    else if (e->getButtonID() & InputEvent::BUTTON1_MASK)
244    {
245        CEGUI::MouseCursor::getSingleton().show();
246        mRMouseDown = false;
247    }
248}
249//-----------------------------------------------------------------------
[133]250void TerrainFrameListener::mouseDragged(MouseEvent *e)
[115]251 {
252         // If we are dragging the left mouse button.           
253         if (mLMouseDown)
254     {
255                 Vector3 queryResult;
256                 Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY());
257
258                 if (mRayQueryExecutor->executeRayQuery(&queryResult, mouseRay))
259                 {
260                         if (mCurrentObject)
261                         {
262                                 mCurrentObject->setPosition(queryResult);
263                         }
264                 }
265     }
266         // If we are dragging the right mouse button.
267         if (mRMouseDown)
268         {
269                 //mCamera->yaw(-e->getRelX() * mRotateSpeed);
270                 //mCamera->pitch(-e->getRelY() * mRotateSpeed);
271                 mCamNode->yaw(-e->getRelX() * mRotateSpeed);
272                 mCamNode->pitch(-e->getRelY() * mRotateSpeed);
273         }
274}
275//-----------------------------------------------------------------------
[133]276bool TerrainFrameListener::frameStarted(const FrameEvent &evt)
[115]277{
278        if (mWindow->isClosed())
[130]279        {
[115]280        return false;
[130]281        }
[115]282
[139]283        if (mDisplayCameraDetails)
284    {
285        // Print camera details
286        mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) +
287                        " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation()));
288    }
[122]289
[130]290        //-- IMPORTANT: must be set, otherwise terrain is not rendered correctly
291        int terrainLevelIdx = 0;
292        mSceneMgr->setOption("TerrainLevelIdx", &terrainLevelIdx);
[115]293
[130]294        //-- setup what is needed for immediate mouse/key movement
295        if (mTimeDelay >= 0)
296        {
297                mTimeDelay -= evt.timeSinceLastFrame;
298        }
[115]299
[130]300        // If this is the first frame, pick a speed
301        if (evt.timeSinceLastFrame == 0)
302        {
303                mMoveScale = 1;
304                mRotScale = 0.1;
305        }
306        // Otherwise scale movement units by time passed since last frame
307        else
308        {
309                // Move about 100 units per second,
310                mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
311                // Take about 10 seconds for full rotation
312                mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
313        }
[115]314
[130]315        mRotX = 0;
316        mRotY = 0;
317        mTranslateVector = Vector3::ZERO;
[115]318
[130]319        if (!processUnbufferedKeyInput(evt))
320        {
321                return false;
322        }
323/*      if (!processUnbufferedMouseInput(evt))
[133]324        {       return false;   }*/
325
[130]326        // --- set parameters for visualization
327        if (mShowVisualization)
328        {
[115]329                // important for visualization => draw octree bounding boxes
330                mSceneMgr->setOption("ShowOctree", &mShowVisualization);
[130]331               
332                // ---- setup visualization camera
[115]333
334                mVizCamera->setPosition(0, 0, 0);
335                mVizCamera->setOrientation(Quaternion::IDENTITY);
336
337                Vector3 camPos = mCamNode->getPosition();
338                mVizCamera->setPosition(camPos.x, mVizCameraHeight, camPos.z);
339
340                // point down -Z axis
341                mVizCamera->pitch(Radian(Degree(270.0)));
[130]342
[115]343                // rotation arounnd X axis
344                mVizCamera->yaw(Math::ATan2(-mCamera->getDerivedDirection().x,
345                        -mCamera->getDerivedDirection().z));
346               
347                // move by a constant so view plane is on bottom of viewport
348                mVizCamera->moveRelative(Vector3(0, 800, 0));
349        }
350
[130]351        //-- set application state
[115]352        switch (mAppState)
353        {
354        case REPLAY:
355                setCurrentFrameInfo(evt.timeSinceLastFrame);
356                break;
357        case WALKTHROUGH:
358                //-- if we are recording camera status per frame
359                if (mRecord)
360                {
361                        addFrameInfo(mCamNode, evt.timeSinceLastFrame);
362                        // print recording message
363                        mWindow->setDebugText("Recording frame " +
364                                StringConverter::toString(mFrameInfo.size() - 1));
365                }       
[133]366                // move camera according to input
[130]367                moveCamera();
[133]368                // clamp camera so we always walk along the terrain
[130]369                Clamp2Terrain();
[133]370                break;
[130]371
[115]372        default:
373                break;
374        };     
[130]375
[115]376        return true;
377}
378//-----------------------------------------------------------------------
[154]379void TerrainFrameListener::ApplyVisibilityQuery(bool fromPoint, bool relativeVisibility,
380                                                                                                bool useItemBuffer)
[130]381{
[151]382        // TODO: change this (does not work with other scene manager plugins)
[154]383        VisibilityTerrainSceneManager *sm =
384                dynamic_cast<VisibilityTerrainSceneManager *>(mSceneMgr);
[151]385
[154]386        if (useItemBuffer)
387        {
388                mQueryManager = new ItemBufferQueryManager(sm->GetHierarchyInterface(),
389                        mWindow->getViewport(0));
390        }
391        else
392        {
393                mQueryManager = new OcclusionQueriesQueryManager(sm->GetHierarchyInterface(),
394                        mWindow->getViewport(0));
395        }
[151]396
397        sm->GetVisibilityManager()->SetQueryManager(mQueryManager);
398
[130]399        InfoContainer<GtpVisibility::NodeInfo> visibleNodes;
400        InfoContainer<GtpVisibility::MeshInfo> visibleGeometry;
401
[133]402        if (fromPoint)
403        {
[151]404                mQueryManager->
[140]405                        ComputeFromPointVisibility(mCamNode->getPosition(), &visibleNodes,
[144]406                                                                           &visibleGeometry, relativeVisibility);
[133]407        }
408        else
409        {
[151]410                mQueryManager->ComputeCameraVisibility(*mCamera,
[144]411                            &visibleNodes, &visibleGeometry, relativeVisibility);
[133]412        }
[130]413
[135]414        float averageNodeVis = 0;
415        float averageGeometryVis = 0;
[151]416        int geomSize = 0;
417        int nodesSize = 0;
[135]418
[141]419        InfoContainer<GtpVisibility::MeshInfo>::iterator geomIt, geomIt_end = visibleGeometry.end();
420
421        for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt)
[130]422        {
[151]423                // add if not 0
424                if ((*geomIt).GetVisiblePixels())
425                {
426                        float vis = relativeVisibility ?
427                                (*geomIt).ComputeRelativeVisibility() : (float)(*geomIt).GetVisiblePixels();
428       
429                        averageGeometryVis += vis;
430                        ++geomSize;
431                       
[154]432                        std::stringstream d; d << "Geometry " << geomSize << " visibility: " << vis;
[151]433                        LogManager::getSingleton().logMessage(d.str());
434                }
[130]435        }
[141]436
437        InfoContainer<GtpVisibility::NodeInfo>::iterator nodesIt, nodesIt_end = visibleNodes.end();
438
439        for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++nodesIt)
[130]440        {
[151]441                // add if not 0
442                if ((*nodesIt).GetVisiblePixels())
443                {
444                        float vis = relativeVisibility ?
445                                (*nodesIt).ComputeRelativeVisibility() : (float)(*nodesIt).GetVisiblePixels();
[145]446               
[151]447                        averageNodeVis += vis;
448                        ++nodesSize;
449
450                        std::stringstream d; d << "Node visibility: " << vis;
451                        LogManager::getSingleton().logMessage(d.str());
452                }       
[130]453        }
454
[151]455        if (nodesSize)
456                averageNodeVis /= (float)nodesSize;
457        if (geomSize)
458                averageGeometryVis /= (float)geomSize;
[135]459
460        //-- update visibility queries stats
461    try
462        {
[154]463                char str[100];
464               
465                sprintf(str, ": %s, %s, %s",
466                                queryTypeCaptions[fromPoint ?  1 : 0].c_str(),
467                                queryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str(),
468                                queryMethodCaptions[useItemBuffer ? 1 : 0].c_str());
[135]469
470                mQueryTypeInfo->setCaption(str);
471
[153]472                sprintf(str, ": %d", (int)nodesSize);
[135]473                mQueryVisibleNodesInfo->setCaption(str);
474       
[153]475                sprintf(str,": %d", (int)geomSize);
[135]476                mQueryVisibleGeometryInfo->setCaption(str);
477               
478                sprintf(str,": %3.3f", averageNodeVis);
479                mQueryNodeVisibilityInfo->setCaption(str);
480
481                sprintf(str,": %3.3f", averageGeometryVis);
482                mQueryGeometryVisibilityInfo->setCaption(str);
483        }
484        catch (...)
485        {
486                // ignore
487        }
488
489        // show the results
490        if (!mShowQueryStats)
491        {
492                mQueryOverlay->show();
493                mShowQueryStats = true;
494        }
[151]495
496        delete mQueryManager;
[130]497}
498//-----------------------------------------------------------------------
[133]499void TerrainFrameListener::Clamp2Terrain()
[115]500{
[140]501        // clamp camera to terrain
[115]502        Vector3 camPos = mCamNode->getPosition();
503        Vector3 queryResult;
504
505        if (mRayQueryExecutor->executeRayQuery(&queryResult,
506                        Vector3(camPos.x, 5000.0f, camPos.z), Vector3::NEGATIVE_UNIT_Y))
507        {
[141]508                const int terrainOffs = 10;
509                mCamNode->setPosition(camPos.x, queryResult.y + terrainOffs, camPos.z);
[115]510        }
511}
512//-----------------------------------------------------------------------
[133]513bool TerrainFrameListener::frameEnded(const FrameEvent& evt)
[115]514{
515        if (mShutdownRequested)
516                return false;
517
[120]518    updateStats();
[115]519
520        return true;
521}
522//-----------------------------------------------------------------------
[133]523void TerrainFrameListener::moveCamera()
[115]524{
525        // move node rather than camera so orientation is right in the visualization
526        mCamNode->yaw(mRotX);
527        mCamNode->pitch(mRotY);
528        mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector);
529}
530//-----------------------------------------------------------------------
[133]531void TerrainFrameListener::writeFrames()
[115]532{
533        std::ofstream ofstr(frames_out_filename);
534       
535        std::vector<frame_info>::const_iterator it, it_end;
536
537        it_end = mFrameInfo.end();
[135]538        for (it = mFrameInfo.begin(); it < it_end; ++it)
[115]539        {
540                ofstr << StringConverter::toString((*it).position) << " "
[130]541                          << StringConverter::toString((*it).orientation) << " "
542                          << StringConverter::toString((*it).timeElapsed) << "\n";
[115]543        }
544        ofstr.close();
545}
546//-----------------------------------------------------------------------
[133]547void TerrainFrameListener::loadFrames()
[115]548{
549        std::ifstream ifstr(frames_out_filename);
550        char line[256];
551        frame_info info;
552
553        // reset current values
554        mFrameInfo.clear();
555        mCurrentFrame = 0;
556       
557        while (!ifstr.eof())
558        {
559                ifstr.getline(line, 256);
560                sscanf(line, "%f %f %f %f %f %f %f %f", &info.position.x, &info.position.y, &info.position.z,
[135]561                           &info.orientation.w, &info.orientation.x, &info.orientation.y, &info.orientation.z,
562                           &info.timeElapsed);
[115]563               
564                mFrameInfo.push_back(info);
565               
[140]566                // std::stringstream d; d << StringConverter::toString(info.position) << " " << StringConverter::toString(info.orientation);
567                // LogManager::getSingleton().logMessage(d.str());
[115]568        }
569        ifstr.close();
570}
571//-----------------------------------------------------------------------
[133]572void TerrainFrameListener::nextAppState()
[115]573{
574        mCurrentFrame = 0;
575
576        // if last state was replay state
577        if (mAppState == REPLAY)
578        {
579                // reset debug text and write frame info to file
580                mWindow->setDebugText("");
581                writeFrames();
582               
[147]583                float avgFps = (float)mAvgFps / (float)mFrameCount;
584
[121]585                //-- write out stats for recorded walkthrough
[115]586                std::stringstream d;
[135]587                d << "Algorithm: " << currentAlgorithmCaptions[mCurrentAlgorithm] << "\n"
[147]588                  //<< "avg. FPS: " << mWindow->getAverageFPS() << "\n"
589                  << "avg. FPS: " << avgFps << "\n"
[115]590                  << "best FPS: " << mWindow->getBestFPS() << "\n"
591                  << "worst FPS: " << mWindow->getWorstFPS() << "\n"
592                  << "best frame time: " <<     mWindow->getBestFrameTime() << "\n"
593                  << "worst frame time: " << mWindow->getWorstFrameTime();
594               
595                LogManager::getSingleton().logMessage(d.str());
596        }
597       
598        //-- set the next státe
599        mAppState = (mAppState + 1) % STATE_NUM;
600
601        // replay recorded walkthrough
602        if (mAppState == REPLAY)
603        {
604                // no recording during replay
605                mRecord = false;
606
607                // load recorded walkthrough
608                if (mFrameInfo.size() == 0)
609                {
610                        loadFrames();
611                }
612
613                // if there are no recorded frames => set next state
614                if (mFrameInfo.size() == 0)
615                {
616                        nextAppState();
617                }
618                else
619                {
620                        mWindow->setDebugText("Replay");
621                       
[147]622                        // reset, because we measure fps stats during walkthrough (warning: average fps broken)
[115]623                        mWindow->resetStatistics();
[147]624                        resetStats();
[115]625
626                        //-- initialise frame data
627                        mTimeElapsed = 0;
628
629                        mCamNode->setPosition(mFrameInfo[0].position);
630                        mCamNode->setOrientation(mFrameInfo[0].orientation);
631                }
632        }
633
634}
635//-----------------------------------------------------------------------
[133]636void TerrainFrameListener::toggleRecord()
[115]637{
638        mRecord = !mRecord;
639
640        // clear previous camera path
641        if (mRecord)
642                mFrameInfo.clear();
643        else
644                mWindow->setDebugText("");
645}
646//-----------------------------------------------------------------------
[133]647void TerrainFrameListener::changeThreshold(int incr)
[115]648{
649        mVisibilityThreshold += incr;
650        if(mVisibilityThreshold < 0) mVisibilityThreshold = 0;
651       
652        char str[100]; sprintf(str,": %d", mVisibilityThreshold);
653
654        mSceneMgr->setOption("Threshold", &mVisibilityThreshold);
655        mThresholdInfo->setCaption(str);
656}
657//-----------------------------------------------------------------------
[146]658void TerrainFrameListener::changeAssumedVisibility(int incr)
659{
660        mAssumedVisibility += incr;
661        if(mAssumedVisibility < 0) mAssumedVisibility = 0;
662       
663        char str[100]; sprintf(str,": %d", mAssumedVisibility);
664
665        mSceneMgr->setOption("AssumedVisibility", &mAssumedVisibility);
666        mAssumedVisibilityInfo->setCaption(str);
667}
668//-----------------------------------------------------------------------
[133]669void TerrainFrameListener::zoomVizCamera(int zoom)
[115]670{
671        mVizCameraHeight += zoom;
672        if(mVizCameraHeight < 0) mVizCameraHeight = 0;
673}
674//-----------------------------------------------------------------------
[133]675void TerrainFrameListener::nextAlgorithm()
[115]676{
677        mCurrentAlgorithm = (mCurrentAlgorithm + 1) %
678                GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS,
679
680        setAlgorithm(mCurrentAlgorithm);
681}
682//-----------------------------------------------------------------------
[133]683void TerrainFrameListener::setAlgorithm(int algorithm)
[115]684{
[135]685        mAlgorithmInfo->setCaption(": " + currentAlgorithmCaptions[mCurrentAlgorithm]);
[115]686        mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm);
687}
688//-----------------------------------------------------------------------
[147]689void TerrainFrameListener::resetStats()
690{
691        mAvgFps = 0;
692        mFrameCount = 0;
693}
694//-----------------------------------------------------------------------
[133]695void TerrainFrameListener::updateStats()
[115]696{
697        unsigned int opt = 0;
698        char str[100];
699       
[147]700        static String currFpsString = "Current FPS: ";
701        static String avgFpsString = "Average FPS: ";
702        static String bestFpsString = "Best FPS: ";
703        static String worstFpsString = "Worst FPS: ";
704        static String trisString = "Triangle Count: ";
[115]705
[147]706        mAvgFps += mWindow->getStatistics().lastFPS;
707        ++ mFrameCount;
708       
709        float avgFps = (float)mAvgFps / (float)mFrameCount;
710   
[115]711        // update stats when necessary
[135]712    try
713        {
[115]714                OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
715                OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
716                OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
717                OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
718
719                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
720
[147]721                //guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
722                guiAvg->setCaption(avgFpsString + StringConverter::toString(avgFps));
723                guiCurr->setCaption(currFpsString + StringConverter::toString(stats.lastFPS));
724                guiBest->setCaption(bestFpsString + StringConverter::toString(stats.bestFPS)
[115]725                        +" "+StringConverter::toString(stats.bestFrameTime)+" ms");
[147]726                guiWorst->setCaption(worstFpsString + StringConverter::toString(stats.worstFPS)
[115]727                        +" "+StringConverter::toString(stats.worstFrameTime)+" ms");
728
729                OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
[147]730        guiTris->setCaption(trisString + StringConverter::toString(stats.triangleCount));
[115]731
732                OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
733                guiDbg->setCaption(mWindow->getDebugText());
734
735                //-- culling stats
736                mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt);
737                mFrustumCulledNodesInfo->setCaption(str);
738       
739                mSceneMgr->getOption("NumQueriesIssued", &opt); sprintf(str,": %d", opt);
740                mQueriesIssuedInfo->setCaption(str);
741
742                mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt);
743                mQueryCulledNodesInfo->setCaption(str);
744       
745                mSceneMgr->getOption("NumTraversedNodes", &opt); sprintf(str,": %d", opt);
746                mTraversedNodesInfo->setCaption(str);
747
748                mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt);
749                mHierarchyNodesInfo->setCaption(str);
750
751                mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt);
752                mRenderedNodesInfo->setCaption(str);
753
754                sprintf(str,": %d", mTerrainContentGenerator->GetObjectCount());
755                mObjectsInfo->setCaption(str);
756        }
[135]757        catch (...)
[115]758        {
[135]759                // ignore
[115]760        }
761}
762//-----------------------------------------------------------------------
[133]763void TerrainFrameListener::toggleUseOptimization()
[115]764{
765        mUseOptimization = !mUseOptimization;
766        mSceneMgr->setOption("UseOptimization", &mUseOptimization);
[133]767       
768        // disable optimization which tests geometry instead of aabb
769        // for delayed rendering (i.e., render transparents after all the solids)
770        // because otherwise visible transparents could be skipped
[115]771        bool delayedRendering = !mUseOptimization;
772        mSceneMgr->setOption("DelayRenderTransparents", &delayedRendering);
773
774        if (mUseOptimization)
[133]775        {
[115]776                mUseOptimizationInfo->setCaption(": true");
[133]777        }
[115]778        else
[133]779        {
[115]780                mUseOptimizationInfo->setCaption(": false");
[133]781        }
[115]782}
783//-----------------------------------------------------------------------
[133]784void TerrainFrameListener::toggleShowOctree()
[115]785{
786        mShowOctree = !mShowOctree;
787
788        mSceneMgr->setOption("ShowOctree", &mShowOctree);
789}
790//-----------------------------------------------------------------------
[133]791void TerrainFrameListener::toggleUseDepthPass()
[115]792{
793        mUseDepthPass = !mUseDepthPass;
794
795        mSceneMgr->setOption("UseDepthPass", &mUseDepthPass);
796       
797        if (mUseDepthPass)
[120]798        {
[115]799                mUseDepthPassInfo->setCaption(": true");
[120]800        }
[115]801        else
[120]802        {
[115]803                mUseDepthPassInfo->setCaption(": false");
[120]804        }
[115]805}
806//-----------------------------------------------------------------------
[133]807void TerrainFrameListener::toggleShowViz()
[115]808{
[139]809        mVisualizeCulledNodes = mShowVisualization = !mShowVisualization;
810       
[115]811        // create viewport with priority VIZ_VIEWPORT_Z_ORDER:
812        // will be rendered over standard viewport
813        if (mShowVisualization)
814        {       
815                Viewport *vizvp = mWindow->addViewport(mVizCamera,
816                        VIZ_VIEWPORT_Z_ORDER, 0.6, 0.6, 0.4, 0.4);
817                               
818                vizvp->setBackgroundColour(ColourValue(0.0, 0.3, 0.2, 1));
819
820                vizvp->setOverlaysEnabled(false);
821                // Alter the camera aspect ratio to match the viewport
822        mVizCamera->setAspectRatio(Real(vizvp->getActualWidth()) /
[139]823                                                                   Real(vizvp->getActualHeight()));
[115]824               
825                mSceneMgr->setOption("VisualizeCulledNodes", &mVisualizeCulledNodes);
826                //vizvp->setClearEveryFrame(false);
827
828                // Create a skyplane (for visualization background)
829                /*
830                Plane plane;
831                plane.d = -1000;
832                plane.normal = Vector3::UNIT_Y;
833                mSceneMgr->setSkyPlane(true, plane, "Examples/TransparentTest", 4000, 75, false);
834                */
835        }
836        else
837        {
[139]838                // remove visualization viewport
[115]839                mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER);
[139]840
841                // octree bounding boxes are shown for visualization purpose, reset now
[115]842                mSceneMgr->setOption("ShowOctree", &mShowOctree);
843        }
844}
845//-----------------------------------------------------------------------
[139]846void TerrainFrameListener::toggleShowShadows()
[115]847{
[139]848        mShowShadows = !mShowShadows;
[115]849
[139]850        mSunLight->setCastShadows(mShowShadows);
[115]851
[139]852        if (mShowShadows)
[115]853        {
854                mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
[139]855                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
856                //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);           
[115]857        }
858        else
859        {
860                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
861        }
862
863}
864//-----------------------------------------------------------------------
[133]865void TerrainFrameListener::nextNodeVizMode()
[115]866{
867        mNodeVizMode = (mNodeVizMode + 1) % NODEVIZ_MODES_NUM;
868
[120]869        bool renderNodesForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES) ||
870                (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
[115]871        bool renderNodesContentForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT);
872        //bool renderNodesContentForViz = mNodeVizMode == NODEVIZ_RENDER_GEOMETRY;
873
874        mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz);
875        mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz);
876}
877//-----------------------------------------------------------------------
[133]878void TerrainFrameListener::keyPressed(KeyEvent* e)
[115]879{
[133]880        switch(e->getKey())
881        {
882        case KC_ESCAPE:
[115]883                mShutdownRequested = true;
884                e->consume();
885                return;
[133]886
887        case KC_SPACE:
888                nextAlgorithm();
889                break;
890       
891        case KC_F:
892                nextFilter();
893                break;
894        case KC_R:
895                nextSceneDetailLevel();
896                break;
897        case KC_P:
898                toggleDisplayCameraDetails();
899                break;
900        case KC_O:
901                toggleUseOptimization();
902                break;
903        case KC_T:
904                toggleShowOctree();
905                break;
906        case KC_X:
907                toggleUseDepthPass();
908                break;
909        case KC_S:
[139]910                toggleShowShadows();
[133]911                break;
912
913        case KC_SUBTRACT:
914                changeThreshold(-10);
915                break;
916        case KC_ADD:
917                changeThreshold(10);
918                break;
919
920        //-- visualization
921        case KC_1:
922                toggleShowViz();
923                break;
924        case KC_2:
925                nextNodeVizMode();
926                break;
927
928        case KC_F1:
929                toggleShowHelp();
930                break;
931        case KC_F2:
932                toggleShowStats();
933                break;
934        case KC_F3:
935                nextAppState();
936                break;
937        case KC_F4:
938                toggleRecord();
939                break;
940        case KC_F5:
[154]941                ApplyVisibilityQuery(false, mShiftPressed, false);
[133]942                break;
943        case KC_F6:
[154]944                ApplyVisibilityQuery(true, mShiftPressed, false);
[133]945                break;
[154]946        case KC_F7:
947                ApplyVisibilityQuery(false, mShiftPressed, true);
948                break;
949        case KC_F8:
950                ApplyVisibilityQuery(true, mShiftPressed, true);
951                break;
[133]952        case KC_F11:
953                takeScreenShot();
954                break;
955        case KC_F12:
956                mTerrainContentGenerator->WriteObjects(objects_out_filename);
957                break;
958
[146]959        case KC_8:
960                changeAssumedVisibility(-1);
961                break;
962        case KC_9:
963                changeAssumedVisibility(1);
964                break;
[133]965        case KC_LSHIFT:
[135]966                mShiftPressed = true;
[133]967                break;
968        //KEY_PRESSED(KC_F3, 0.3, writeFrames());
969        //KEY_PRESSED(KC_F4, 0.3, loadFrames());
970        default:
971                break;
[115]972        }
973
974        CEGUI::System::getSingleton().injectKeyDown(e->getKey());
975        CEGUI::System::getSingleton().injectChar(e->getKeyChar());
976        e->consume();
977}
978//-----------------------------------------------------------------------
[133]979void TerrainFrameListener::keyReleased(KeyEvent* e)
[115]980{
[135]981        if (e->getKey() == KC_LSHIFT)
982        {
983                mShiftPressed = false;
984        }
985       
[115]986        CEGUI::System::getSingleton().injectKeyUp(e->getKey());
987        e->consume();
988}
989//-----------------------------------------------------------------------
[133]990void TerrainFrameListener::keyClicked(KeyEvent* e)
[115]991{
992        // Do nothing
993        e->consume();
994}
995//-----------------------------------------------------------------------
[133]996void TerrainFrameListener::addFrameInfo(SceneNode *camNode, Real timeElapsed)
[115]997{
998        frame_info info;
999        info.orientation = mCamNode->getOrientation();
1000        info.position = mCamNode->getPosition();
1001        info.timeElapsed = timeElapsed;
1002
1003        mFrameInfo.push_back(info);
1004}
1005//-----------------------------------------------------------------------
[133]1006void TerrainFrameListener::setCurrentFrameInfo(Real timeElapsed)
[115]1007{
1008        //-- find current frame relative to elapsed frame time         
1009        mTimeElapsed -= timeElapsed;
1010
1011        while ((mTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1))
1012        {
1013                mTimeElapsed += mFrameInfo[mCurrentFrame ++].timeElapsed;
1014        }
1015
1016        frame_info new_frame = mFrameInfo[mCurrentFrame];
1017        frame_info old_frame = mFrameInfo[mCurrentFrame - 1];
1018               
1019        //-- interpolate frames
1020        Real factor = 1;
1021
1022        if (old_frame.timeElapsed > 0)
[133]1023        {
[115]1024                factor = mTimeElapsed / old_frame.timeElapsed;
[133]1025        }
[115]1026
[133]1027        Vector3 camPos = old_frame.position + factor
1028                * (new_frame.position - old_frame.position);
[115]1029        Quaternion camOrienation = Quaternion::Slerp(factor, old_frame.orientation,
1030                new_frame.orientation, true);
1031
1032        mCamNode->setPosition(camPos);
1033        mCamNode->setOrientation(camOrienation);
1034       
1035        // stop replay after a full walkthrough
1036        if (mCurrentFrame == (int)mFrameInfo.size() - 1)
1037        {
1038                nextAppState();
1039        }
1040}
1041//-----------------------------------------------------------------------   
[133]1042bool TerrainFrameListener::processUnbufferedKeyInput(const FrameEvent& evt)
[115]1043{
[135]1044        bool cursorPressed = false;
1045       
[120]1046        /* Move camera forward by keypress. */
1047    if (mInputDevice->isKeyDown(KC_UP))
1048        {
1049                mTranslateVector.z = -mMoveScale;
[135]1050                cursorPressed = true;
[120]1051        }
[115]1052    /* Move camera backward by keypress. */
[120]1053    if (mInputDevice->isKeyDown(KC_DOWN))
[115]1054    {
[120]1055                mTranslateVector.z = mMoveScale;
[135]1056                cursorPressed = true;
[115]1057    }
1058
1059    if (mInputDevice->isKeyDown(KC_RIGHT))
1060    {
1061        mCamNode->yaw(-mRotScale);
[135]1062                cursorPressed = true;
[115]1063    }
1064       
1065    if (mInputDevice->isKeyDown(KC_LEFT))
1066    {
1067        mCamNode->yaw(mRotScale);
[135]1068                cursorPressed = true;
[115]1069    }
[133]1070        // visualization camera
1071        if (mInputDevice->isKeyDown(KC_3))
1072        {
1073                zoomVizCamera(50);
1074        }
1075        if (mInputDevice->isKeyDown(KC_4))
1076        {
1077                zoomVizCamera(-50);
1078        }
[115]1079
[135]1080        // show the results
1081        if (cursorPressed && mShowQueryStats)
1082        {
1083                mQueryOverlay->hide();
1084                mShowQueryStats = false;
1085        }
[115]1086
1087    // Return true to continue rendering
1088    return true;
1089}
1090//-----------------------------------------------------------------------
[133]1091void TerrainFrameListener::nextFilter()
[120]1092{
[133]1093        switch (mFiltering)
[120]1094        {
1095        case TFO_BILINEAR:
1096                mFiltering = TFO_TRILINEAR;
1097                mAniso = 1;
1098                break;
1099        case TFO_TRILINEAR:
1100                mFiltering = TFO_ANISOTROPIC;
1101                mAniso = 8;
1102                break;
1103        case TFO_ANISOTROPIC:
1104                mFiltering = TFO_BILINEAR;
1105                mAniso = 1;
1106                break;
1107        default:
1108                break;
1109        }
1110
1111    MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
1112    MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
1113
[133]1114        // reload stats
[120]1115    showStats(mStatsOn);
1116}
1117//-----------------------------------------------------------------------
[133]1118void TerrainFrameListener::nextSceneDetailLevel()
[120]1119{
[133]1120        mSceneDetailIndex = (mSceneDetailIndex + 1) % 3;
1121        switch (mSceneDetailIndex)
[120]1122        {
[133]1123                case 0:
1124                        mCamera->setDetailLevel(SDL_SOLID);
1125                        break;
1126                case 1:
1127                        mCamera->setDetailLevel(SDL_WIREFRAME);
1128                        break;
1129                case 2:
1130                        mCamera->setDetailLevel(SDL_POINTS);
1131                        break;
[120]1132        }
1133}
1134//-----------------------------------------------------------------------
[133]1135void TerrainFrameListener::takeScreenShot()
[120]1136{
1137        char tmp[20];
1138        sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots);
1139    mWindow->writeContentsToFile(tmp);
1140    mWindow->setDebugText(String("Wrote ") + tmp);
1141}
1142//-----------------------------------------------------------------------
[133]1143void TerrainFrameListener::toggleDisplayCameraDetails()
[120]1144{
1145        mDisplayCameraDetails = !mDisplayCameraDetails;
1146       
1147    if (!mDisplayCameraDetails)
[133]1148        {
[120]1149                mWindow->setDebugText("");
[115]1150        }
1151}
[120]1152//-----------------------------------------------------------------------
[133]1153void TerrainFrameListener::showStats(bool show)
[115]1154{
[120]1155        if (mDebugOverlay && mCullStatsOverlay)
[115]1156        {
1157                if (show)
1158                {
1159                        mDebugOverlay->show();
[120]1160                        mCullStatsOverlay->show();
[115]1161                }
1162                else
1163                {
1164                        mDebugOverlay->hide();
[120]1165                        mCullStatsOverlay->hide();
[115]1166                }
1167        }
1168}
[120]1169//-----------------------------------------------------------------------
[133]1170void TerrainFrameListener::toggleShowStats()
[120]1171{
1172        mStatsOn = !mStatsOn;
[115]1173
[120]1174        showStats(mStatsOn);
1175}
1176//-----------------------------------------------------------------------
[133]1177void TerrainFrameListener::toggleShowHelp()
[120]1178{
1179        mShowHelp = !mShowHelp;
[115]1180
[120]1181        if (mShowHelp)
1182        {
1183                mHelpOverlay->show();
1184        }
1185        else
1186        {
1187                mHelpOverlay->hide();
1188        }
[133]1189}
Note: See TracBrowser for help on using the repository browser.