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

Revision 254, 46.2 KB checked in by mattausch, 19 years ago (diff)

added some hack for video recording

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