source: GTP/trunk/App/Demos/Geom/Demo_LodTrees/main.cpp @ 1783

Revision 1783, 14.4 KB checked in by gumbau, 18 years ago (diff)
RevLine 
[1092]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 "GeoLodTreeLibrary.h"
16#include "GeoMeshLoader.h"
17
18
19// Distance values
[1783]20#define dist_min 40
21#define dist_max 800
[1092]22
23//Global variables
24Geometry::GeoMeshLoader *meshloader=NULL;
[1104]25bool force_maxLODfactor = false;
[1783]26const int num_tree_types=10;
27Vector3 *centers=NULL;
[1092]28
29ColourValue color=ColourValue::Red;
30
31Camera* theCam;
32Entity* pPlaneEnt;
33
34OverlayElement* mInfo;
35OverlayElement* mInfo2;
[1561]36OverlayElement* mHelp;
[1092]37
[1561]38char HelpString[]="(F1) Help\n"
[1783]39                        "This demo shows an example of the LodTree model in action. The scene is composed of\n"
40                        "several tree groups which are associated to a LodTree object that manage the level\n"
41                        "of detail of both their trunk and leaves. The level of detail of the objects depends\n"
42                        "on the distance to the camera. When the camera goes away from them, the level of detail\n"
43                        "decreases, and when the camera gets closer to them increases to restore the original\n"
44                        "geometry of the model.\n"
45                        "The level of detail begins to decrease at a certain distance of each group, and stops\n"
[1561]46                        "decreasing when the objects reach the their minimum LOD. This 'lodding' distance is\n"
[1783]47                        "customizable from the source code of the demo.\n"
48                        "The user can compare the differences in performance disabling the LOD management while\n"
49                        "maintaining pressed F2.";
[1092]50
[1561]51char NoHelpString[]="(F1) Help\n";
[1092]52
[1561]53
54
[1540]55class LodTreeFrameListener : public ExampleFrameListener
[1092]56{
57        int manage;
[1783]58        Ogre::RaySceneQuery * raySceneQuery;
59        float *lodfactorBefore; // one lodfactor per LOD object type
60        Geometry::LodTreeLibrary **lod_tree_types;
[1092]61
62public:
63
[1783]64        LodTreeFrameListener(RenderWindow* win, Camera* cam,RaySceneQuery *rsq,Geometry::LodTreeLibrary **lod_trees)
[1092]65        : ExampleFrameListener(win, cam, false, false)
66    {
67                manage=1;
[1783]68                raySceneQuery=rsq;
69                lodfactorBefore=new float[num_tree_types];
70                for (int i=0; i<num_tree_types; i++)
71                        lodfactorBefore[i]=-1;
72                lod_tree_types=lod_trees;
[1092]73        }
74
75        bool frameStarted(const FrameEvent& evt)
76    {
77                Vector3 dist;
[1783]78                int inc2=0,d;
[1092]79                unsigned int nlod,diflods;
80
81                // Move upto 80 units/second
[1783]82                Real MoveFactor = 120.0 * evt.timeSinceLastFrame;
[1092]83
84                // Copy the current state of the input devices
85                mInputDevice->capture();
86
87                // If this is the first frame, pick a speed
88                if (evt.timeSinceLastFrame == 0)
89                {
90                        mMoveScale = 1;
91                        mRotScale = 0.1;
92                }
93                // Otherwise scale movement units by time passed since last frame
94                else
95                {
96                        // Move about 100 units per second,
97                        mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
98                        // Take about 10 seconds for full rotation
99                        mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
100                }
101
102                mRotX = 0;
103        mRotY = 0;
104            mTranslateVector = Vector3::ZERO;
105
106                //LOD selection
[1783]107                for (int i=0; i<num_tree_types; i++)
108                {       
109                        dist = centers[i] - mCamera->getPosition();
110                        int distance = dist.length();
[1092]111
[1783]112                        float lodfactor = 0.0f;
113                        if (distance < dist_min)
114                                lodfactor = 1.0f;
115                        else if (distance > dist_max)
116                                lodfactor = 0.0f;
117                        else
118                        {
119                lodfactor = (float)(distance - dist_min) / (float)(dist_max - dist_min);
120                                lodfactor = 1.0f - lodfactor;
121                        }
[1092]122
[1783]123                        assert(lodfactor>=0.0f);
124                        assert(lodfactor<=1.0f);
[1092]125
[1783]126                        if (force_maxLODfactor)
127                                lodfactor=1.0f;
[1104]128
[1783]129                        if (fabsf(lodfactorBefore[i]-lodfactor)>0.1f)
130                        {
131                                lod_tree_types[i]->GoToLod(lodfactor);
132                                lodfactorBefore[i]=lodfactor;
133                        }
[1092]134                }
135
[1540]136                // Move the cam
137                if(mInputDevice->isKeyDown(Ogre::KC_UP) ||
138                   mInputDevice->isKeyDown(Ogre::KC_W) ||
139                   mInputDevice->isKeyDown(Ogre::KC_NUMPAD5))
[1092]140                  mTranslateVector.z = -mMoveScale;
141
[1540]142                if(mInputDevice->isKeyDown(Ogre::KC_DOWN) ||
143                   mInputDevice->isKeyDown(Ogre::KC_S) ||
144                   mInputDevice->isKeyDown(Ogre::KC_NUMPAD2))
[1092]145                  mTranslateVector.z = mMoveScale;
146
[1540]147                if (mInputDevice->isKeyDown(Ogre::KC_A) ||
148                        mInputDevice->isKeyDown(Ogre::KC_NUMPAD1))
149                        mTranslateVector.x = -mMoveScale;
150
151                if (mInputDevice->isKeyDown(Ogre::KC_D) ||
152                        mInputDevice->isKeyDown(Ogre::KC_NUMPAD3))
153                        mTranslateVector.x = mMoveScale;
154
[1092]155                if(mInputDevice->isKeyDown(Ogre::KC_LEFT))
156                  mCamera->yaw(mRotScale);
157
[1104]158                force_maxLODfactor=mInputDevice->isKeyDown(Ogre::KC_F2);                 
159
[1092]160                if(mInputDevice->isKeyDown(Ogre::KC_RIGHT))
161                  mCamera->yaw(-mRotScale);
162
[1561]163                static bool newpush = true;
164                if (!mInputDevice->isKeyDown(Ogre::KC_F1))
165                        newpush = true;
166
167                static bool showing_help = false;
168                if (mInputDevice->isKeyDown(Ogre::KC_F1) && newpush)
169                {
170                        newpush = false;
171                        if (showing_help = !showing_help)
172                mHelp->setCaption(HelpString);
173                        else
174                mHelp->setCaption(NoHelpString);
175                }
176
177
[1092]178                if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
179                    return false;
180
181        if( mInputDevice->getMouseButton( 1 ) )
182        {
183            mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
184            mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
185        }
186        else
187        {
188            mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
189            mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
190        }
191
192                mCamera->yaw(mRotX);
193        mCamera->pitch(mRotY);
194        mCamera->moveRelative(mTranslateVector);
195
[1783]196                // make the camera walk onto the ground
197                Ogre::Ray ray(mCamera->getPosition()+Ogre::Vector3(0.0f,200.0f,0.0f), Ogre::Vector3::NEGATIVE_UNIT_Y);
198                raySceneQuery->setRay(ray);
199                RaySceneQueryResult &rayRes = raySceneQuery->execute();
200                RaySceneQueryResult::iterator itr = rayRes.begin();
201                if (itr != rayRes.end() && itr->worldFragment)
202                        mCamera->setPosition(itr->worldFragment->singleIntersection+Ogre::Vector3(0.0f,15.0f,0.0f));
203
[1092]204                return true;
205    }
206};
207
[1529]208class CustomIndexData : public Geometry::IndexData
209{
210private:
211        Ogre::Mesh *targetMesh;
212        Ogre::HardwareIndexBufferSharedPtr ibuf;
213        Ogre::RenderOperation mRenderOp;
214        unsigned long* pIdx;
215public:
216        CustomIndexData(Ogre::Mesh *ogremesh):Geometry::IndexData(){
217                targetMesh=ogremesh;
218                pIdx=NULL;
219        }
220        virtual ~CustomIndexData(void){}
221
222        virtual void Begin(unsigned int submeshid, unsigned int indexcount){
223                targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0);
224                ibuf = mRenderOp.indexData->indexBuffer;
225                mRenderOp.indexData->indexCount = indexcount;
226                pIdx = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
227        }
228        virtual void SetIndex(unsigned int i, unsigned int index){
[1783]229                pIdx[i] = index;
[1529]230        }
231        virtual void End(){
232                ibuf->unlock();
233        }
234
235        virtual void BorrowIndexData(const Geometry::IndexData *){}
236};
237
238
[1540]239class LodTreeApplication : public ExampleApplication
[1092]240{
241protected:
242public:
[1783]243    LodTreeApplication(){
244                raySceneQuery=NULL;
245                centers=new Vector3[num_tree_types]; // one center per object
246        }
[1540]247    ~LodTreeApplication(){}
[1092]248
[1783]249        Ogre::RaySceneQuery * raySceneQuery;
250        Geometry::LodTreeLibrary **lod_tree_types;
251
[1092]252protected:
253   
[1783]254    void chooseSceneManager(void)
255    {
256        // Get the SceneManager, in this case a generic one
257                mSceneMgr = mRoot->getSceneManager(Ogre::ST_EXTERIOR_CLOSE);
258    }
[1092]259
260
261    // Just override the mandatory create scene method
262    void createScene(void)
263    {
264        theCam = mCamera;
[1783]265                theCam->setPosition(500,100,dist_min+600);
[1092]266        // Set ambient light
[1124]267        mSceneMgr->setAmbientLight(ColourValue(0.4, 0.4, 0.4));
[1561]268                theCam->setNearClipDistance(0.1f);
[1092]269
[1783]270                mSceneMgr->setFog( FOG_EXP, Ogre::ColourValue(0.4f,0.5f,0.6f), 0.001 );
271
[1104]272        // Create a directional light
[1124]273                Light* l = mSceneMgr->createLight("MainLight");
[1104]274                l->setType(Light::LT_DIRECTIONAL);
[1783]275        l->setDirection(0.1,-1.0,-0.2);
[1092]276       
[1783]277                // terrain
278                mSceneMgr->setWorldGeometry( "terrain.cfg" );
[1092]279
[1783]280       
[1092]281        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
282
283        // My node to which all objects will be attached
284        SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
285
[1783]286                // initialize the rayscene queryer
287                raySceneQuery = mSceneMgr->createRayQuery(Ray());
[1092]288
[1783]289                // the blacksmith
290                Vector3 BS_center=Ogre::Vector3(780.0f,200.0f,650.0f);
291                Ogre::Ray ray(BS_center, Ogre::Vector3::NEGATIVE_UNIT_Y);
292                raySceneQuery->setRay(ray);
293                RaySceneQueryResult &rayRes = raySceneQuery->execute();
294                RaySceneQueryResult::iterator itr = rayRes.begin();
295                if (itr != rayRes.end() && itr->worldFragment)
296                        BS_center=itr->worldFragment->singleIntersection-Ogre::Vector3(0.0f,1.0f,0.0f);
[1092]297
[1783]298                Ogre::Entity *entBS = mSceneMgr->createEntity("blacksmith","../../../OgreStuff/media/models/blacksmith.mesh");
299                Ogre::SceneNode * nodeBS = mSceneMgr->getRootSceneNode()->createChildSceneNode();
300                nodeBS->attachObject(entBS);
301                nodeBS->translate(BS_center);
302                nodeBS->scale(0.1f,0.1f,0.1f);
[1092]303
[1783]304                lod_tree_types = new Geometry::LodTreeLibrary*[num_tree_types];
305
306                // trees
307                lod_tree_types[0] = CreateLODTrees("../../../OgreStuff/media/GT/ML06a_01.mesh",5,780,630,200,200,centers[0], 4.0f);
308                lod_tree_types[1] = CreateLODTrees("../../../OgreStuff/media/GT/ML13a_02.mesh",4,150,150,200,200,centers[1], 2.0f);
309                lod_tree_types[2] = CreateLODTrees("../../../OgreStuff/media/GT/ML15a_03.mesh",10,300,400,200,200,centers[2], 6.0f);
310                lod_tree_types[3] = CreateLODTrees("../../../OgreStuff/media/GT/ML06a_01.mesh",5,330,900,500,500,centers[3], 3.0f);
311                lod_tree_types[4] = CreateLODTrees("../../../OgreStuff/media/GT/ML13a_02.mesh",5,1100,900,300,300,centers[4], 2.0f);
312                lod_tree_types[5] = CreateLODTrees("../../../OgreStuff/media/GT/ML15a_03.mesh",10,1100,300,200,200,centers[5], 6.0f);
313                lod_tree_types[6] = CreateLODTrees("../../../OgreStuff/media/GT/ML06a_01.mesh",7,900,500,300,300,centers[6], 2.0f);
314                lod_tree_types[7] = CreateLODTrees("../../../OgreStuff/media/GT/ML13a_02.mesh",5,500,950,200,200,centers[7], 3.0f);
315                lod_tree_types[8] = CreateLODTrees("../../../OgreStuff/media/GT/ML15a_03.mesh",9,600,400,200,200,centers[8], 6.0f);
316                lod_tree_types[9] = CreateLODTrees("../../../OgreStuff/media/GT/ML06a_01.mesh",7,950,1100,200,200,centers[9], 2.5f);
317
318        // show overlay
319        Overlay* pOver = OverlayManager::getSingleton().getByName("Demo_LodStrips/Overlay");   
320        mInfo = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_1");
321                mInfo2 = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_2");
322                mHelp = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Help");
323                mHelp->setCaption(NoHelpString);
324            pOver->show();
325
326                mInfo->setCaption("Maintain F2 to disable LOD");
327
328    }
329
330    void destroyScene(void)
331        {
332                if (raySceneQuery)
333                        delete raySceneQuery;
334                delete[] lod_tree_types;
335        }
336
337    void createFrameListener(void)
338    {
339        mFrameListener= new LodTreeFrameListener(mWindow, mCamera, raySceneQuery, lod_tree_types);
340        mFrameListener->showDebugOverlay(true);
341        mRoot->addFrameListener(mFrameListener);
342    }
343
344        Geometry::LodTreeLibrary *CreateLODTrees(const char *filename, int numObjs, float cx, float cz, float w, float h, Vector3 &outcenter, float scale)
345        {
346                static int iname = 0;
347                char newMeshName[16]="";
348                sprintf(newMeshName,"tree_%d",iname);
349
350
[1092]351                // load LOD info from the object
352                meshloader=new Geometry::GeoMeshLoader;
[1783]353                Geometry::Mesh *themesh = meshloader->load((char*)filename);
[1092]354
[1306]355                if (!meshloader->GetLodStripsData())
356            OGRE_EXCEPT(1, "The loaded mesh does not contain LOD info for the trunk","LOD Demo");
357                if (!meshloader->GetTreeSimpSeq())
358            OGRE_EXCEPT(1, "The loaded mesh does not contain LOD info for the foliage","LOD Demo");
359
[1783]360                Ogre::Entity *entity = mSceneMgr->createEntity(newMeshName,filename);           
361                if (!entity->getMesh().unique())
362                {
363                        static int iclone = 0;
364                        char newCloneMesh[16]="";
365                        sprintf(newCloneMesh,"clonetree_%d",iclone++);
366                        entity->getMesh() = entity->getMesh()->clone(newCloneMesh);
367                }
368                Ogre::Mesh *ogreMesh = entity->getMesh().getPointer();
369                entity->setNormaliseNormals(true);
370
371                Geometry::LodTreeLibrary *mytree = new Geometry::LodTreeLibrary(
372                                                                                                meshloader->GetLodStripsData(),
[1529]373                                                                                                meshloader->GetTreeSimpSeq(),
374                                                                                                themesh,
[1783]375                                                                                                new CustomIndexData(ogreMesh) );
[1092]376
[1783]377                outcenter=Vector3::ZERO;
[1092]378
[1783]379                for (int i=0; i<numObjs; i++)
[1104]380                {
[1783]381                        char newTreeName[16]="";
382                        sprintf(newTreeName,"arbol_%d_%d",iname,i);
383                        Ogre::SceneNode * auxnode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
384                        Ogre::Entity *auxent = entity->clone(newTreeName);
385                        auxnode->attachObject( auxent );
[1092]386
[1783]387                        float kx = (rand()%100)/100.0f;
388                        float kz = (rand()%100)/100.0f;
[1092]389
[1783]390                        Ogre::Vector3 treepos(kx*(cx-w*0.5f) + (1.0f-kx)*(cx+w*0.5f), 200.0f,
391                                                                  kz*(cz-h*0.5f) + (1.0f-kz)*(cz+h*0.5f));
[1092]392
[1783]393                        Ogre::Ray ray(treepos,Ogre::Vector3::NEGATIVE_UNIT_Y);
394                        raySceneQuery->setRay(ray);
395                        RaySceneQueryResult &rayRes = raySceneQuery->execute();
396                        RaySceneQueryResult::iterator itr = rayRes.begin();
397                        if (itr != rayRes.end() && itr->worldFragment)
398                                treepos = itr->worldFragment->singleIntersection;
[1113]399
[1783]400                        auxnode->translate(treepos);
401                        auxnode->scale(scale,scale,scale);
402                        auxnode->rotate(Ogre::Vector3(0,1,0),Ogre::Degree(rand()%360));
403                        auxent->setNormaliseNormals(true);
404                        outcenter+=treepos;
405                }
406                outcenter/=numObjs;
407                iname++;
[1092]408
[1783]409                return mytree;
410        }
[1092]411
[1783]412        float Rand(float minN, float maxN)
413        {
414                return (((rand()%1000)/1000.0f)*(maxN-minN))+minN;
415        }
[1092]416
417};
418
419
420
421#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
422#define WIN32_LEAN_AND_MEAN
423#include "windows.h"
424#endif
425
426#ifdef __cplusplus
427extern "C" {
428#endif
429
430#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
431INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
432#else
433int main(int argc, char **argv)
434#endif
435{
436    // Create application object
[1540]437    LodTreeApplication app;
[1092]438
439    try {
440        app.go();
441    } catch( Exception& e ) {
442#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
443        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
444#else
445        std::cerr << "An exception has occured: " << e.getFullDescription();
446#endif
447    }
448
449
450    return 0;
451}
452
453#ifdef __cplusplus
454}
455#endif
Note: See TracBrowser for help on using the repository browser.