source: GTP/trunk/App/Demos/Geom/Demo_LodManager/main.cpp @ 1819

Revision 1819, 16.5 KB checked in by gumbau, 17 years ago (diff)
Line 
1/*      ==========================================================================
2 *      (C) 2006 Universitat Jaume I
3 *      ==========================================================================
4 *      PROYECT:        GAME TOOLS
5 *      ==========================================================================*/
6/**     CONTENT:       
7        *
8        *
9        *       @file   main.cpp
10/** COMMENTS:
11        * Model must be in "media/models" folder.
12        * Lod file must be in "media/GT" folder.
13/*===========================================================================*/
14#include "ExampleApplication.h"
15#include "GeoLodManager.h"
16#include "GeoMeshLoader.h"
17#include "audiere.h"
18
19
20// Distance values
21#define dist_min 2000
22#define dist_max 2500
23
24// Model name
25//#define model_name "dwarf2"
26
27
28//Global variables
29Geometry::LodManager* lodManager = NULL;
30Geometry::Mesh  *the_lodstrips_mesh = NULL,
31                                *the_lodtree_mesh = NULL;
32Geometry::GeoMeshLoader *lodstrips_meshloader = NULL,
33                                                *lodtree_meshloader = NULL;
34Ogre::SceneManager *sceneManager = NULL;
35Ogre::Entity *orig_lodstrips_entity = NULL,
36                         *orig_lodtree_entity = NULL;
37
38                audiere::AudioDevicePtr device(audiere::OpenDevice());
39                audiere::OutputStreamPtr song(OpenSound(device,"../../musica.mp3",false));
40
41
42MaterialPtr *mat;
43
44ColourValue color=ColourValue::Red;
45
46Camera* theCam;
47Entity* pPlaneEnt;
48
49char HelpString[]="(F1) Quit this Help\n"
50                        "This demo shows an example of the LODManager in action. Every model in the scene\n"
51                        "has its own LodStrips object associated that manages its level of detail.\n"
52                        "Since the scene is highly populated, changing the LOD of every object independently\n"
53                        "would make the performance to fall.\n"
54                        "The LodManager makes efficient LOD computations by reusing previously calculated LODs.\n"
55                        "The level of detail of the objects depends on the distance to the camera. When the\n"
56                        "camera goes away from them, the level of detail decreases, and when the camera gets\n"
57                        "closer to them increases to restore the original geometry of the model.\n"
58                        "(F4) LODManager ON\n"
59                        "(F3) LODManager OFF\n\n"
60                        "IMPORTANT: to notice performance improvements the user must move the camera, since the\n"
61                        "LOD in only re-calculated when the camera position changes.";
62
63char NoHelpString[]="\n\n\n\n\n\n\n\n\n\n\n\n\n(F1) Help\n";
64
65OverlayElement* mLOD;
66OverlayElement* mInfo;
67OverlayElement* mInfo2;
68OverlayElement* mHelp;
69
70//Ogre::OverlayElement *mInfo, *mInfo2;
71
72// framerate test
73std::vector<float> framerates;
74const unsigned int msDelay = 1000;
75
76class CustomIndexData : public Geometry::IndexData
77{
78private:
79        Ogre::Mesh *targetMesh;
80        Ogre::HardwareIndexBufferSharedPtr ibuf;
81        unsigned long* pIdx;
82        Ogre::HardwareIndexBufferSharedPtr *orig_indexbuff;
83
84public:
85        CustomIndexData(Ogre::Mesh *ogremesh):Geometry::IndexData(){
86                targetMesh=ogremesh;
87                pIdx=NULL;
88                orig_indexbuff=new Ogre::HardwareIndexBufferSharedPtr[targetMesh->getNumSubMeshes()];
89                for (int i=0; i<targetMesh->getNumSubMeshes(); i++)
90                {
91                        Ogre::RenderOperation mRenderOp;
92                        targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOp,0);
93                        orig_indexbuff[i] = mRenderOp.indexData->indexBuffer;
94                }
95        }
96        virtual ~CustomIndexData(void){
97                delete[] orig_indexbuff;
98        }
99
100        virtual void Begin(unsigned int submeshid, unsigned int indexcount){
101                Ogre::RenderOperation mRenderOp;       
102                targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0);
103
104                // restore the original index data to modify it
105                mRenderOp.indexData->indexBuffer = orig_indexbuff[submeshid];
106
107                ibuf = mRenderOp.indexData->indexBuffer;
108                mRenderOp.indexData->indexCount = indexcount;
109                pIdx = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
110        }
111
112        virtual void SetIndex(unsigned int i, unsigned int index){
113                pIdx[i] = index;
114        }
115        virtual void End(){
116                ibuf->unlock();
117        }
118        virtual void BorrowIndexData(const Geometry::IndexData *idata){
119                CustomIndexData *custom_data = (CustomIndexData*)idata;
120                for (int i=0; i<targetMesh->getNumSubMeshes(); i++)
121                {
122                        Ogre::RenderOperation mRenderOp, mRenderOpParam;
123
124                        targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOp,0);                   
125                        custom_data->targetMesh->getSubMesh(i)->_getRenderOperation(mRenderOpParam,0);
126
127                        mRenderOp.indexData->indexBuffer = mRenderOpParam.indexData->indexBuffer;
128                        mRenderOp.indexData->indexCount  = mRenderOpParam.indexData->indexCount;
129                }
130        }
131};
132
133void AddNewLodStripsObj(void)
134{
135        const int troop_width = 30;
136        static int iname = 0;
137        int i = iname%troop_width;
138        int j = iname/troop_width;     
139
140        char newObjName[16]="";
141        sprintf(newObjName,"model_%d",iname);
142        char newMeshName[16]="";
143        sprintf(newMeshName,"mesh_%d",iname);
144        iname++;
145
146        Ogre::Mesh *ogreMesh = orig_lodstrips_entity->getMesh()->clone(newMeshName).getPointer();
147        Entity *entity = sceneManager->createEntity(newObjName,newMeshName);
148        entity->setNormaliseNormals(true);
149
150        Ogre::SceneNode * auxnode = sceneManager->getRootSceneNode()->createChildSceneNode();
151        auxnode->attachObject(entity);
152        auxnode->rotate(Ogre::Vector3(0,1,0),Ogre::Degree(180.0f),Ogre::Node::TS_WORLD);
153        auxnode->scale(30.0f,30.0f,30.0f);
154        float randomsepx = (float)((rand()%18)-9);
155        float randomsepy = (float)((rand()%12)-6);
156        auxnode->translate(i*120.0f+randomsepx,0.0f,-j*120.0f-randomsepx);
157//      auxnode->translate(0,0,-500.0f);
158
159        Geometry::LodStripsLibrary *myStrips = new Geometry::LodStripsLibrary(
160                                                        lodstrips_meshloader->GetLodStripsData(),
161                                                        the_lodstrips_mesh,
162                                                        new CustomIndexData(ogreMesh));
163
164        entity->setMaterialName("LODStripsDemo/Ogro");
165
166        // add the object to the manager
167        Ogre::Vector3 opos = auxnode->getPosition();
168        lodManager->AddLodObj("ogre",myStrips,Geometry::Vector3(opos.x,opos.y,opos.z));                         
169}
170
171
172void AddNewLodTreeObj(void)
173{
174        const int troop_width = 10;
175        static int iname = 0;
176        int i = iname%troop_width;
177        int j = iname/troop_width;     
178
179        char newObjName[16]="";
180        sprintf(newObjName,"tree_%d",iname);
181        char newMeshName[16]="";
182        sprintf(newMeshName,"tree_%d",iname);
183        iname++;
184
185        Ogre::Mesh *ogreMesh = orig_lodtree_entity->getMesh()->clone(newMeshName).getPointer();
186        Entity *entity = sceneManager->createEntity(newObjName,newMeshName);
187        entity->setNormaliseNormals(true);
188
189        Ogre::SceneNode * auxnode = sceneManager->getRootSceneNode()->createChildSceneNode();
190        auxnode->attachObject(entity);
191        auxnode->scale(11.0f,11.0f,11.0f);
192        auxnode->rotate(Ogre::Vector3(0,0,1),Ogre::Degree(rand()%360));
193        auxnode->rotate(Ogre::Vector3(1,0,0),Ogre::Radian(-3.14159f*0.5f),Ogre::Node::TS_WORLD);
194        float randomsepx = (float)((rand()%18)-9);
195        float randomsepy = (float)((rand()%12)-6);
196        auxnode->translate(i*60.0f+randomsepx,-1.0f,-j*60.0f-randomsepx);
197        auxnode->translate(300,0,-500.0f);
198
199        Geometry::LodTreeLibrary *myTree = new Geometry::LodTreeLibrary(
200                                                        lodtree_meshloader->GetLodStripsData(),
201                                                        lodtree_meshloader->GetTreeSimpSeq(),
202                                                        the_lodtree_mesh,
203                                                        new CustomIndexData(ogreMesh));
204
205        // load the right material for each part of the tree
206        for (int submesh=0; submesh < ogreMesh->getNumSubMeshes(); submesh++)
207        {
208                bool istrunk = myTree->GetLeavesSubMesh()!=submesh;
209                if (istrunk)
210                        entity->getSubEntity(submesh)->setMaterialName("Examples/Populifolia/trunk");
211                else
212                        entity->getSubEntity(submesh)->setMaterialName("Examples/Populifolia/leaf");
213        }
214
215
216        // add the object to the manager
217        Ogre::Vector3 opos = auxnode->getPosition();
218        lodManager->AddLodObj("tree",myTree,Geometry::Vector3(opos.x,opos.y,opos.z));                           
219}
220
221
222
223class LodManagerFrameListener : public ExampleFrameListener
224{
225        int manage;
226
227public:
228
229    LodManagerFrameListener(RenderWindow* win, Camera* cam)
230        : ExampleFrameListener(win, cam, false, false)
231    {
232                manage=1;
233        }
234
235        bool frameStarted(const FrameEvent& evt)
236    {
237                Vector3 dist;
238                int distance=0,inc2=0;
239
240                // test
241                static float timeLeft = 0;
242               
243                const RenderTarget::FrameStats& stats = mWindow->getStatistics();
244
245                static bool rec_stats = false;
246
247                if (mInputDevice->isKeyDown(Ogre::KC_J))
248                        rec_stats=true;
249
250                if (rec_stats)
251                {
252                        if (timeLeft <= 0.0f)
253                        {
254                                framerates.push_back(stats.lastFPS);
255                                timeLeft = msDelay;
256                        }
257                        timeLeft -= evt.timeSinceLastFrame * 1000.0f;   
258                }
259
260                // Move upto 80 units/second
261                Real MoveFactor = 180.0 * evt.timeSinceLastFrame;
262
263                // Copy the current state of the input devices
264                mInputDevice->capture();
265
266                // If this is the first frame, pick a speed
267                if (evt.timeSinceLastFrame == 0)
268                {
269                        mMoveScale = 1;
270                        mRotScale = 0.1;
271                }
272                // Otherwise scale movement units by time passed since last frame
273                else
274                {
275                        // Move about 100 units per second,
276                        mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
277                        // Take about 10 seconds for full rotation
278                        mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
279                }
280
281                mRotX = 0;
282        mRotY = 0;
283            mTranslateVector = Vector3::ZERO;
284               
285                lodManager->UpdateLOD(stats.lastFPS,90);
286
287                bool cam_moved=false;
288
289                if (mInputDevice->isKeyDown(Ogre::KC_F3))
290                {
291                        lodManager->always_calculate_lod = true;
292                        cam_moved = true;
293                }
294                if (mInputDevice->isKeyDown(Ogre::KC_F4))
295                {
296                        lodManager->always_calculate_lod = false;
297                        cam_moved = true;
298                }
299
300                //if (mInputDevice->isKeyDown(Ogre::KC_F7))
301                //{
302                //      lodManager->force_highest_lod = true;
303                //      cam_moved = true;
304                //}
305
306                //if (mInputDevice->isKeyDown(Ogre::KC_F8))
307                //{
308                //      lodManager->force_highest_lod = false;
309                //      cam_moved = true;
310                //}
311
312                // Move the cam
313                if(mInputDevice->isKeyDown(Ogre::KC_UP))
314                {
315                  mTranslateVector.z = -mMoveScale;
316                  cam_moved=true;
317                }
318
319                if(mInputDevice->isKeyDown(Ogre::KC_DOWN))
320                {
321                  mTranslateVector.z = mMoveScale;
322                  cam_moved=true;
323                }
324
325                // Instead of moving the ship left and right, rotate it using yaw()
326                if(mInputDevice->isKeyDown(Ogre::KC_LEFT))
327                {
328                  mCamera->yaw(mRotScale);
329                  cam_moved=true;
330                }
331
332                if(mInputDevice->isKeyDown(Ogre::KC_RIGHT))
333                {
334                  mCamera->yaw(-mRotScale);
335                  cam_moved=true;
336                }
337
338                if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
339                {
340                        delete lodManager;
341                        delete [] mat;
342                        FILE *f=fopen("fps.txt","wt");
343                        unsigned int ms = 0;
344                        for (std::vector<float>::iterator it = framerates.begin(); it != framerates.end(); it++, ms++)
345                                fprintf(f,"%u %f\n",ms,*it);
346                        fclose(f);
347                    return false;
348                }
349
350                static bool newpush = true;
351                if (!mInputDevice->isKeyDown(Ogre::KC_F1))
352                        newpush = true;
353
354                static bool showing_help = false;
355                if (mInputDevice->isKeyDown(Ogre::KC_F1) && newpush)
356                {
357                        newpush = false;
358                        if (showing_help = !showing_help)
359                mHelp->setCaption(HelpString);
360                        else
361                mHelp->setCaption(NoHelpString);
362                }
363
364        if( mInputDevice->getMouseButton( 1 ) )
365        {
366            mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
367            mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
368                        cam_moved=true;
369        }
370        else
371        {
372            mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
373            mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
374        }
375
376                char cadena[256];
377       
378                if ( lodManager->always_calculate_lod )         
379                        sprintf(cadena,"\n\nLOD Manager:  OFF\nTriangle Count: %d\n",stats.triangleCount);
380                else
381                        sprintf(cadena,"\n\nLOD Manager:  ON\nTriangle Count: %d\n",stats.triangleCount);
382
383                mInfo->setCaption(cadena);
384                mWindow->getStatistics();
385
386                sprintf(cadena,"Current FPS: %f\n",stats.lastFPS);
387                mInfo2->setCaption(cadena);
388
389
390                mCamera->yaw(mRotX);
391        mCamera->pitch(mRotY);
392        mCamera->moveRelative(mTranslateVector);
393
394                if (cam_moved)
395                        lodManager->UpdateCamera(Geometry::Vector3(mCamera->getPosition().x,mCamera->getPosition().y,mCamera->getPosition().z));
396
397                return true;
398    }
399};
400
401class LodManagerApplication : public ExampleApplication
402{
403public:
404    LodManagerApplication() {}
405
406    ~LodManagerApplication() {}
407protected:
408   
409    // Just override the mandatory create scene method
410    void createScene(void)
411    {
412                mat = new MaterialPtr[1];
413
414                theCam = mCamera;
415        theCam->setPosition(1900,200,800);
416        // Set ambient light
417                sceneManager = mSceneMgr;
418        mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
419
420                //SHADOWS
421                //mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
422                //mSceneMgr->setShadowTextureSettings(2048,1);
423                //mSceneMgr->setShadowFarDistance(2048);
424                //mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
425
426        // Create a point light
427        Light* l = mSceneMgr->createLight("MainLight");
428        l->setType(Light::LT_DIRECTIONAL);
429        l->setDirection(-0.5,-1.0,-1.0);
430
431       
432        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
433
434        // My node to which all objects will be attached
435        SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
436
437        // Define a floor plane mesh
438                Plane plane( Vector3::UNIT_Y, 0 );
439
440                MeshManager::getSingleton().createPlane("ground",
441                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
442                        40000,40000,6,6,true,1,200,200,Vector3::UNIT_Z);
443
444                Entity* groundEntity = mSceneMgr->createEntity( "GroundEntity", "ground" );
445                mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(groundEntity);
446               
447                groundEntity->setMaterialName("SnowTerrain");
448                groundEntity->setCastShadows(false);       
449
450
451                lodManager = new Geometry::LodManager(dist_min,dist_max,Geometry::Vector3(theCam->getPosition().x,theCam->getPosition().y,theCam->getPosition().z),100);
452                lodManager->UpdateCamera(Geometry::Vector3(     theCam->getPosition().x,
453                                                                                                        theCam->getPosition().y,
454                                                                                                        theCam->getPosition().z ));
455
456                // load the LodStrips info from the object /////////////////////////////////////////////////////////////////
457                lodstrips_meshloader=new Geometry::GeoMeshLoader;
458                the_lodstrips_mesh = lodstrips_meshloader->load("../../../OgreStuff/media/GT/ogrolod.mesh");
459
460                if (!lodstrips_meshloader->GetLodStripsData())
461            OGRE_EXCEPT(1, "The loaded mesh does not contain any LOD info","LOD Demo");
462
463                orig_lodstrips_entity = mSceneMgr->createEntity("orig_lods", "../../../OgreStuff/media/GT/ogrolod.mesh");
464
465
466                // load the LodTree info from the object //////////////////////////////////////////////////////////////////
467/*              lodtree_meshloader=new Geometry::GeoMeshLoader;
468                the_lodtree_mesh = lodtree_meshloader->load("../../../OgreStuff/media/GT/ML11.mesh");
469
470                if (!lodtree_meshloader->GetLodStripsData())
471            OGRE_EXCEPT(1, "The loaded mesh does not contain LODStrips info","LOD Demo");
472                if (!lodtree_meshloader->GetTreeSimpSeq())
473            OGRE_EXCEPT(1, "The loaded mesh does not contain LODTree info","LOD Demo");
474
475                orig_lodtree_entity = mSceneMgr->createEntity("orig_lodt", "../../../OgreStuff/media/GT/ML11.mesh");*/
476
477
478                // Add objects to the LodManager!
479
480/*              for (int i=0; i<25; i++)
481                        AddNewLodTreeObj();*/
482                //audiere::AudioDevicePtr device(audiere::OpenDevice());
483                //audiere::OutputStreamPtr song(OpenSound(device,"../../musica.mp3",false));
484                song->setVolume(0.5f);
485                song->setRepeat(true);
486                song->play();
487
488                for (int i=0; i<1200; i++)
489                        AddNewLodStripsObj();
490               
491
492        // show overlay
493        Overlay* pOver = OverlayManager::getSingleton().getByName("Demo_LodStrips/Overlay");   
494        mInfo = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_1");
495                mInfo2 = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_2");
496        mHelp = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Help");
497                mHelp->setCaption(NoHelpString);
498                pOver->show();
499//              pOver->hide();
500
501    }
502
503    void createFrameListener(void)
504    {
505        mFrameListener= new LodManagerFrameListener(mWindow, mCamera);
506        mFrameListener->showDebugOverlay(false);
507        mRoot->addFrameListener(mFrameListener);
508    }
509
510};
511
512
513
514#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
515#define WIN32_LEAN_AND_MEAN
516#include "windows.h"
517#endif
518
519#ifdef __cplusplus
520extern "C" {
521#endif
522
523#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
524INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
525#else
526int main(int argc, char **argv)
527#endif
528{
529    // Create application object
530    LodManagerApplication app;
531
532    try {
533        app.go();
534    } catch( Exception& e ) {
535#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
536        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
537#else
538        std::cerr << "An exception has occured: " << e.getFullDescription();
539#endif
540    }
541
542
543    return 0;
544}
545
546#ifdef __cplusplus
547}
548#endif
Note: See TracBrowser for help on using the repository browser.