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

Revision 346, 46.8 KB checked in by mattausch, 19 years ago (diff)

updated terrain removed debug messages from chc

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