source: GTP/trunk/App/Demos/Geom/Demo_LodStrips/main.cpp @ 1775

Revision 1775, 14.2 KB checked in by gumbau, 18 years ago (diff)

Improved Demo_LodStrips.exe
Changed Scene appearance.
Added F2 key (shadows on-off) and F3 key (manual vs automatic LOD).

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 "GeoLodStripsLibrary.h"
16#include "GeoMeshLoader.h"
17
18
19// Distance values
20#define dist_min 1100
21#define dist_max 2500
22
23// Model name
24#define model_name "dwarf2"
25
26
27//Global variables
28
29Entity* entity;
30Geometry::LodStripsLibrary* myStrips;
31Ogre::Mesh *ogreMesh=NULL;
32Geometry::GeoMeshLoader *meshloader=NULL;
33SceneNode* node;
34
35MaterialPtr *mat;
36
37ColourValue color=ColourValue::Red;
38
39Camera* theCam;
40Entity* pPlaneEnt;
41
42OverlayElement* mInfo;
43OverlayElement* mInfo2;
44OverlayElement* mHelp;
45OverlayElement* mLOD;
46OverlayElement* mShad;
47SceneManager* SceneMgrAux;
48
49char LODStringAuto[]="(F3) LOD Mode: AUTOMATIC";
50char LODStringManu[]="(F3) LOD Mode: MANUAL";
51char ShadON[]       ="(F2) Shadows ON";
52char ShadOFF[]      ="(F2) Shadows OFF";
53
54int degAA=0, degABAB=0;
55
56char HelpString[]="(F1) Quit Help\n"
57                        "This demo shows an example of the LODStrips model in action. The models in the scene\n"
58                        "are associated to a LodStrips object that manage their level of detail.\n"
59                        "The level of detail of the objects depend on the distance to the camera. When the\n"
60                        "camera goes away from them, the level of detail decreases, and when the camera gets\n"
61                        "closer to them the level of detail increases to restore the original geometry of the\n"
62                        "model.\n"
63                        "The current level of detail can be seen in real-time in the bottom-left corner of the screen.\n"
64                        "The level of detail begins to decrease at a certain distance of the crowd, and stops\n"
65                        "decreasing when the objects reach the their minimum LOD. This 'lodding' distance is\n"
66                        "customizable from the source code of the demo.\n\n"
67                        "(F3) LOD Mode   ( AUTOMATIC  vs  MANUAL )\n"
68                        "           MANUAL MODE:  Use (+) and (-) keys to change de LOD\n";
69
70char NoHelpString[]="\n\n\n\n\n\n\n\n\n\n\n\n\n(F1) Help\n";
71
72int num_ogres = 90;
73
74
75class CustomIndexData : public Geometry::IndexData
76{
77private:
78        Ogre::Mesh *targetMesh;
79        Ogre::HardwareIndexBufferSharedPtr ibuf;
80        Ogre::RenderOperation mRenderOp;
81        unsigned long* pIdx;
82public:
83        CustomIndexData(Ogre::Mesh *ogremesh):Geometry::IndexData(){
84                targetMesh=ogremesh;
85                pIdx=NULL;
86        }
87        virtual ~CustomIndexData(void){}
88
89        virtual void Begin(unsigned int submeshid, unsigned int indexcount){
90                targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0);
91                ibuf = mRenderOp.indexData->indexBuffer;
92                mRenderOp.indexData->indexCount = indexcount;
93                pIdx = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
94        }
95        virtual void SetIndex(unsigned int i, unsigned int index){
96                pIdx[i] = index; //lodStripsLib->dataRetrievalInterface->GetIndex(k+offset);
97        }
98        virtual void End(){
99                int v0, v1, v2, v3;
100                unsigned int i;
101
102                v0 = pIdx[0];
103                v1 = pIdx[1];
104                for ( i=2; i < mRenderOp.indexData->indexCount; i++)
105                {
106                        if ( v0 == v1 ) degAA++;
107                        v0 = v1;
108                        v1 = pIdx[i];
109                }
110
111                v0 = pIdx[0];
112                v1 = pIdx[1];
113                v2 = pIdx[2];
114                v3 = pIdx[3];
115        for ( i=4; i < mRenderOp.indexData->indexCount; i++)
116                {
117                        if ( ( v0 == v2 ) && ( v1 == v3 ) )
118                        {
119                                v0 = v2;
120                                v1 = v3;
121                                v2 = pIdx[i];
122                                if ( i < mRenderOp.indexData->indexCount )
123                                {
124                                        i++;
125                                        v3 = pIdx[i];
126                                }
127                                else v3 = -1;
128
129                                degABAB++;
130                        }
131                        else
132                        {
133                            v0 = v1;
134                            v1 = v2;
135                                v2 = v3;
136                                v3 = pIdx[i];
137                        }
138                }
139
140                ibuf->unlock();
141        }
142        virtual void BorrowIndexData(const Geometry::IndexData *){}
143};
144
145class FresnelFrameListener : public ExampleFrameListener
146{
147        float miButtonTimer;
148
149public:
150
151    FresnelFrameListener(RenderWindow* win, Camera* cam)
152        : ExampleFrameListener(win, cam, false, false)
153    {
154                miButtonTimer=0;
155        }
156
157        bool frameStarted(const FrameEvent& evt)
158    {
159                Vector3 dist;
160                int distance=0,inc2=0;
161            static int modo=0;
162                static int shadows=1;
163
164                float tiempo = evt.timeSinceLastFrame;
165                miButtonTimer -= tiempo;
166
167                if (shadows == 0)
168                {
169                        SceneMgrAux->setShadowTechnique(SHADOWTYPE_NONE);
170                }
171                else
172                {
173                        SceneMgrAux->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
174                }
175
176
177                // Move upto 80 units/second
178                Real MoveFactor = 180.0 * evt.timeSinceLastFrame;
179
180                // Copy the current state of the input devices
181                mInputDevice->capture();
182
183                // If this is the first frame, pick a speed
184                if (evt.timeSinceLastFrame == 0)
185                {
186                        mMoveScale = 1;
187                        mRotScale = 0.1;
188                }
189                // Otherwise scale movement units by time passed since last frame
190                else
191                {
192                        // Move about 100 units per second,
193                        mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
194                        // Take about 10 seconds for full rotation
195                        mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
196                }
197
198                mRotX = 0;
199        mRotY = 0;
200            mTranslateVector = Vector3::ZERO;
201
202                //LOD selection
203                static float lodfactor=0;
204                static float lodfactorBefore = -1.0f;
205               
206                dist = node->getPosition() - mCamera->getPosition();
207                distance =dist.length();
208
209                if ( modo == 0 )      //Automatic LOD
210                {
211                        int difdist = dist_max - dist_min;
212       
213                        int i=0;
214
215                        lodfactor = (float)(distance - dist_min) / (float)(dist_max - dist_min);
216                        lodfactor = 1.0f - lodfactor;
217                }
218                else
219                {
220          //  lodfactor = lodfactorBefore;
221                }
222
223                       
224        if (( mInputDevice->isKeyDown(Ogre::KC_ADD) ) && (modo == 1))
225                                lodfactor += 0.001f;
226            if (( mInputDevice->isKeyDown(Ogre::KC_SUBTRACT) ) && (modo == 1))
227                                lodfactor -= 0.001f;
228
229                if (lodfactor<0.0f)
230                        lodfactor=0.0f;
231                if (lodfactor>1.0f)
232                        lodfactor=1.0f;
233
234                if (fabsf(lodfactorBefore-lodfactor)>0.03f ||
235                        (lodfactorBefore>0.0f && lodfactor==0.0f) ||
236                        (lodfactorBefore<1.0f && lodfactor==1.0f))
237                {
238                        degAA=0; degABAB=0;
239                        myStrips->GoToLod(lodfactor);
240                        lodfactorBefore=lodfactor;
241                }
242
243                if ( mInputDevice->isKeyDown(Ogre::KC_F3) && ( miButtonTimer <= 0 ) )
244                {
245                            miButtonTimer = 0.5;
246                               
247                                if (modo == 0)
248                                {
249                                        modo=1;
250                                        mLOD->setCaption(LODStringManu);
251                                }
252                                else
253                                {
254                                        modo=0;
255                                        mLOD->setCaption(LODStringAuto);
256                                }
257                }
258
259                if ( mInputDevice->isKeyDown(Ogre::KC_F2) && ( miButtonTimer <= 0 ) )
260                {
261                            miButtonTimer = 0.5;
262                               
263                                if (shadows == 0)
264                                {
265                                        shadows = 1;
266                                        mShad->setCaption(ShadON);
267                                }
268                                else
269                                {
270                                        shadows = 0;
271                                        mShad->setCaption(ShadOFF);
272                                }
273                }
274
275                // Move the node
276                if(mInputDevice->isKeyDown(Ogre::KC_UP) ||
277                   mInputDevice->isKeyDown(Ogre::KC_W) ||
278                   mInputDevice->isKeyDown(Ogre::KC_NUMPAD5))
279                  mTranslateVector.z = -mMoveScale;
280
281                if(mInputDevice->isKeyDown(Ogre::KC_DOWN) ||
282                   mInputDevice->isKeyDown(Ogre::KC_S) ||
283                   mInputDevice->isKeyDown(Ogre::KC_NUMPAD2))
284                  mTranslateVector.z = mMoveScale;
285
286                if (mInputDevice->isKeyDown(Ogre::KC_A) ||
287                        mInputDevice->isKeyDown(Ogre::KC_NUMPAD1))
288                        mTranslateVector.x = -mMoveScale;
289
290                if (mInputDevice->isKeyDown(Ogre::KC_D) ||
291                        mInputDevice->isKeyDown(Ogre::KC_NUMPAD3))
292                        mTranslateVector.x = mMoveScale;
293
294/*              if (mInputDevice->isKeyDown(Ogre::KC_K))
295                        mCamera->setDetailLevel(SDL_WIREFRAME);*/
296
297                static bool newpush = true;
298                if (!mInputDevice->isKeyDown(Ogre::KC_F1))
299                        newpush = true;
300
301                static bool showing_help = false;
302                if (mInputDevice->isKeyDown(Ogre::KC_F1) && newpush)
303                {
304                        newpush = false;
305                        if (showing_help = !showing_help)
306                mHelp->setCaption(HelpString);
307                        else
308                mHelp->setCaption(NoHelpString);
309                }
310
311                if(mInputDevice->isKeyDown(Ogre::KC_LEFT))
312                  mCamera->yaw(mRotScale);
313
314                if(mInputDevice->isKeyDown(Ogre::KC_RIGHT))
315                  mCamera->yaw(-mRotScale);
316
317                if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
318                {
319                        delete myStrips;
320                        delete [] mat;
321                    return false;
322                }
323
324        if( mInputDevice->getMouseButton( 1 ) )
325        {
326            mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
327            mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
328        }
329        else
330        {
331            mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
332            mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
333        }
334
335                SceneMgrAux->setShadowFarDistance(distance + 200);
336
337                char cadena[256];
338        const RenderTarget::FrameStats& stats = mWindow->getStatistics();
339                               
340                sprintf(cadena,"\nDistance: %d\nLOD factor: %f\nTriangle Count: %d\nDegenerated AA: %d\nDegenerated ABAB: %d"
341                                     ,    distance,      lodfactor,stats.triangleCount,    degAA*num_ogres,    degABAB*num_ogres);
342                mInfo->setCaption(cadena);
343                sprintf(cadena,"Current FPS: %f\n",stats.lastFPS);
344                mInfo2->setCaption(cadena);
345
346                //sprintf(cadena,"LOD factor: %f",lodfactor);
347
348                //mInfo2->setCaption(cadena);
349
350                mCamera->yaw(mRotX);
351        mCamera->pitch(mRotY);
352        mCamera->moveRelative(mTranslateVector);
353
354                return true;
355    }
356
357};
358
359class LodStripsApplication : public ExampleApplication
360{
361protected:
362public:
363    LodStripsApplication() {}
364    ~LodStripsApplication() {}
365
366protected:
367
368    // Just override the mandatory create scene method
369    void createScene(void)
370    {
371                SceneMgrAux = mSceneMgr;
372        mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
373                mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
374                mSceneMgr->setShadowTextureSettings(2048,1);
375                mSceneMgr->setShadowFarDistance(1024);
376                mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
377
378                mat = new MaterialPtr[1];
379
380                theCam = mCamera;
381        theCam->setPosition(-35,50,dist_min-600.0f);
382        // Set ambient light
383
384        // Create a directional light
385        Light* l = mSceneMgr->createLight("MainLight");
386        l->setType(Light::LT_DIRECTIONAL);
387        l->setDirection(-0.5,-1.0,-1.0);
388                l->setCastShadows(true);
389
390        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
391
392        // My node to which all objects will be attached
393        SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
394
395        // Define a floor plane mesh
396                Plane plane( Vector3::UNIT_Y, 0 );
397
398                MeshManager::getSingleton().createPlane("ground",
399                        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
400                        20000,10000,6,6,true,1,250,250,Vector3::UNIT_Z);
401
402                Entity* groundEntity = mSceneMgr->createEntity( "GroundEntity", "ground" );
403                mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(groundEntity);
404               
405                groundEntity->setMaterialName("SnowTerrain");
406                groundEntity->setCastShadows(false);
407
408                std::string model_file=model_name;
409                model_file.append(".mesh");
410
411                //Models
412        entity = mSceneMgr->createEntity(model_name, "../../../OgreStuff/media/GT/ogrolod.mesh");
413                ogreMesh = entity->getMesh().getPointer();
414
415                // load LOD info from the object
416                meshloader=new Geometry::GeoMeshLoader;
417                Geometry::Mesh *themesh = meshloader->load("../../../OgreStuff/media/GT/ogrolod.mesh");
418
419        node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
420        node->attachObject( entity );
421                node->setVisible(false);               
422
423                std::string lod_file="../../media/GT/";
424                lod_file.append(model_name);
425                lod_file.append(".lod");
426
427                if (!meshloader->GetLodStripsData())
428            OGRE_EXCEPT(1, "The loaded mesh does not contain any LOD info","LOD Demo");
429
430                myStrips = new Geometry::LodStripsLibrary(      meshloader->GetLodStripsData(),
431                                                                                                        themesh,
432                                                                                                        new CustomIndexData(ogreMesh)   );
433               
434                entity->setNormaliseNormals(true);
435                entity->setMaterialName("LODStripsDemo/Ogro");
436
437
438                num_ogres=0;
439
440                for (int i=-4; i<4; i++) // 7
441                        for (int j=0; j<8; j++) // 4
442                        {
443                                char newObjName[16]="";
444                                sprintf(newObjName,"arbol_%d_%d",i,j);
445                                Ogre::SceneNode * auxnode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
446                                Ogre::Entity *auxen = entity->clone(newObjName);
447                                auxnode->attachObject(auxen);
448                                auxnode->rotate(Ogre::Vector3(0,1,0),Ogre::Degree(180.0f),Ogre::Node::TS_WORLD);
449                                auxnode->scale(30.0f,30.0f,30.0f);
450                                float randomsepx = (float)((rand()%18)-9);
451                                float randomsepy = (float)((rand()%12)-6);
452                                auxnode->translate(i*70.0f+randomsepx,-0.3f,-j*70.0f-randomsepx);
453                                auxen->setNormaliseNormals(true);
454                                auxen->setCastShadows(true);
455
456                                num_ogres++;
457                        }
458
459                node->translate(0,0,-500.0f);
460
461        // show overlay
462        Overlay* pOver = OverlayManager::getSingleton().getByName("Demo_LodStrips/Overlay");   
463        mInfo = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_1");
464                mInfo2 = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_2");
465                mHelp = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Help");
466                mLOD = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/ModoLOD");
467                mShad = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Shadows");
468                mHelp->setCaption(NoHelpString);
469                mLOD->setCaption(LODStringAuto);
470                mShad->setCaption(ShadON);
471                pOver->show();
472                //mWindow->getStatistics();
473
474    }
475
476    void createFrameListener(void)
477    {
478        mFrameListener= new FresnelFrameListener(mWindow, mCamera);
479        mFrameListener->showDebugOverlay(false);
480        mRoot->addFrameListener(mFrameListener);
481    }
482
483};
484
485
486
487#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
488#define WIN32_LEAN_AND_MEAN
489#include "windows.h"
490#endif
491
492#ifdef __cplusplus
493extern "C" {
494#endif
495
496#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
497INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
498#else
499int main(int argc, char **argv)
500#endif
501{
502    // Create application object
503    LodStripsApplication app;
504
505    try {
506        app.go();
507    } catch( Exception& e ) {
508#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
509        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
510#else
511        std::cerr << "An exception has occured: " << e.getFullDescription();
512#endif
513    }
514
515
516    return 0;
517}
518
519#ifdef __cplusplus
520}
521#endif
Note: See TracBrowser for help on using the repository browser.