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

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