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

Revision 1813, 15.7 KB checked in by gumbau, 18 years ago (diff)

Demos updated to the last version of Ogre

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