source: trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.cpp @ 175

Revision 175, 15.1 KB checked in by mattausch, 19 years ago (diff)

added trees

RevLine 
[61]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>
7
[100]8#include <Ogre.h>
[161]9
[115]10//#include "OgreReferenceAppLayer.h"
[100]11//#include "OgreRefAppWorld.h"
[61]12#include "TestCullingTerrainApplication.h"
[173]13#include "TerrainFrameListener.h"
[61]14
15#define WIN32_LEAN_AND_MEAN
[94]16#include <windows.h>
[61]17
[160]18
[173]19/**********************************************/
20/*             EntityState implementation     */
21/**********************************************/
[164]22
[173]23
[164]24Vector3 EntityState::msMinPos = Vector3::ZERO;
25Vector3 EntityState::msMaxPos = Vector3::ZERO;
26
[161]27EntityState::EntityState(Entity *ent, State entityState, Real speed):
28mEntity(ent), mState(entityState), mAnimationSpeed(speed)
29{
30        switch(entityState)
31        {
32        case MOVING:
33                mAnimationState = mEntity->getAnimationState("Walk");
34                break;
35        case WAITING:
36                mAnimationState = mEntity->getAnimationState("Idle");
37                break;
38        case STOP:
39                mAnimationState = NULL;
40                break;
41        default:
42                break;
43        }
44        // enable animation state
45        if (mAnimationState)
46        {
47                mAnimationState->setLoop(true);
48                mAnimationState->setEnabled(true);
49        }
50        mTimeElapsed = Math::RangeRandom(1, 5);
51}
52//-----------------------------------------------------------------------
[164]53EntityState::~EntityState()
54{
55        mAnimationState = NULL;
56        mEntity = NULL;
57}
58//-----------------------------------------------------------------------
[161]59Entity *EntityState::GetEntity()
60{
61        return mEntity;
62}
63//-----------------------------------------------------------------------
64EntityState::State EntityState::GetState()
65{
66        return mState;
67}
68//-----------------------------------------------------------------------
69void EntityState::update(Real timeSinceLastFrame)
70{
71        mTimeElapsed -= timeSinceLastFrame * mAnimationSpeed;
[164]72
73        if (!mEntity || !mAnimationState)
74                return;
[161]75       
76        if (mState == MOVING) // toggle between moving (longer) and waiting (short)
77        {
78                SceneNode *parent = mEntity->getParentSceneNode();
[164]79               
80                if (!parent)
81                        return;
[161]82
83                if (mTimeElapsed <= 0) // toggle animation state
84                {
85                        if (mAnimationState->getAnimationName() == "Idle")
86                        {
87                                SetAnimationState("Walk", true);
[164]88                               
89                                mTimeElapsed = walk_duration; // walk for mTimeElapsed units
[161]90
[164]91                                // choose random rotation
92                                Radian rnd = Radian(Math::UnitRandom() * Math::PI * rotate_factor);
[161]93
94                                //mEntity->getParentSceneNode()->rotate();
95                                parent->yaw(rnd);                                               
96                        }
97                        else
98                        {
99                                SetAnimationState("Idle", true);
[164]100                                mTimeElapsed = wait_duration; // wait for mTimeElapsed seconds
[161]101                        }
102                }
103
[164]104                if (mAnimationState->getAnimationName() == "Walk") // move forward
[161]105                {
[164]106                        // store old position, just in case we get out of bounds
[161]107                        Vector3 oldPos = parent->getPosition();
[164]108                        parent->translate(parent->getLocalAxes(), Vector3(move_factor * mAnimationSpeed, 0, 0));
[161]109
[164]110                        // HACK: if out of bounds => reset to old position and set animationstate to idle
[161]111                        if (OutOfBounds(parent))
112                        {
113                                parent->setPosition(oldPos);
[164]114                                SetAnimationState("Idle", true);
[161]115                               
[164]116                                mTimeElapsed = wait_duration;
[161]117                        }
118                }
119        }
120               
[164]121        // add time to drive animation
122        mAnimationState->addTime(timeSinceLastFrame * mAnimationSpeed);
[161]123}
124//-----------------------------------------------------------------------
125void EntityState::SetAnimationState(String stateStr, bool loop)
126{
[164]127        if (!mEntity)
128                return;
129
[161]130        mAnimationState = mEntity->getAnimationState(stateStr);
131        mAnimationState->setLoop(loop);
132        mAnimationState->setEnabled(true);
133}
134//-----------------------------------------------------------------------
135bool EntityState::OutOfBounds(SceneNode *node)
136{
137        Vector3 pos = node->getPosition();
138
139        if ((pos > msMinPos) && (pos < msMaxPos))
[164]140                return false;
[161]141
[164]142        return true;
[161]143}
[164]144
145
146
[160]147/*********************************************************/
148/*      TestCullingTerrainApplication implementation     */
149/*********************************************************/
150
151
[145]152TestCullingTerrainApplication::TestCullingTerrainApplication():
[164]153mTerrainContentGenerator(NULL), mRayQueryExecutor(NULL)
[145]154{
155}
[100]156//-----------------------------------------------------------------------
[61]157TestCullingTerrainApplication::~TestCullingTerrainApplication()
158{
[161]159        OGRE_DELETE(mTerrainContentGenerator);
160        OGRE_DELETE(mRayQueryExecutor);
[164]161
[161]162        deleteEntityStates();
163}
164//-----------------------------------------------------------------------
165void TestCullingTerrainApplication::deleteEntityStates()
166{
167        for (int i = 0; i < (int)mEntityStates.size(); ++i)
[122]168        {
[164]169                OGRE_DELETE(mEntityStates[i]);
[122]170        }
[164]171
[161]172        mEntityStates.clear();
[61]173}
174//-----------------------------------------------------------------------
[93]175void TestCullingTerrainApplication::createCamera()
[61]176{
[99]177        // create the camera
[103]178        mCamera = mSceneMgr->createCamera("PlayerCam");
[93]179       
[100]180        /** set a nice viewpoint
181        *       we use a camera node here and apply all transformations on it instead
182        *       of applying all transformations directly to the camera
183        *       because then the camera is displayed correctly in the visualization
184        */
[137]185        mCamNode = mSceneMgr->getRootSceneNode()->
186                createChildSceneNode("CamNode1", Vector3(707, 5000, 528));
[100]187        //mCamera->setPosition(707, 5000, 528);
188        mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
189        mCamNode->attachObject(mCamera);
[61]190
[100]191        //-- create visualization camera
192        mVizCamera = mSceneMgr->createCamera("VizCam");
193        mVizCamera->setPosition(mCamNode->getPosition());
194
195        mVizCamera->setNearClipDistance(1);
[93]196        mCamera->setNearClipDistance(1);
[61]197
[99]198        // infinite far plane?
[93]199        if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
200        {
[100]201                mVizCamera->setFarClipDistance(0);
[93]202                mCamera->setFarClipDistance(0);
203        }
204        else
205        {
[104]206                 mVizCamera->setFarClipDistance(20000);
207                 mCamera->setFarClipDistance(20000);
[99]208        }       
[61]209}
[99]210
[61]211//-----------------------------------------------------------------------
[99]212bool TestCullingTerrainApplication::setup()
213{
[145]214        bool carryOn = ExampleApplication::setup();
[99]215
[145]216        if (carryOn)
[144]217                createRenderTargetListener();
[99]218
[145]219        return carryOn;
[99]220}
221//-----------------------------------------------------------------------
222void TestCullingTerrainApplication::createRenderTargetListener()
223{
224        mWindow->addListener(new VisualizationRenderTargetListener(mSceneMgr));
225}
226//-----------------------------------------------------------------------
[75]227void TestCullingTerrainApplication::createScene()
[61]228{
229        // Set ambient light
[175]230        mAmbientLight = ColourValue(0.5 , 0.5, 0.5);
[139]231        mSceneMgr->setAmbientLight(mAmbientLight);
[113]232       
[110]233        //-- create light
[111]234        mSunLight = mSceneMgr->createLight("SunLight");
235        mSunLight->setType(Light::LT_DIRECTIONAL);
236        //mSunLight->setType(Light::LT_SPOTLIGHT);
[112]237        //mSunLight->setSpotlightRange(Degree(30), Degree(50));
238
[111]239    mSunLight->setPosition(707, 2000, 500);
240        mSunLight->setCastShadows(true);
241
[173]242        // set light angle not too small over the surface, otherwise shadows textures will be broken
[113]243        Vector3 dir(0.5, 1, 0.5);
[110]244        dir.normalise();
[112]245        mSunLight->setDirection(dir);
246        //mSunLight->setDirection(Vector3::NEGATIVE_UNIT_Y);
[111]247        mSunLight->setDiffuseColour(1, 1, 1);
248        mSunLight->setSpecularColour(1, 1, 1);
[110]249
[137]250        // -- Fog
[61]251        // NB it's VERY important to set this before calling setWorldGeometry
252        // because the vertex program picked will be different
253        ColourValue fadeColour(0.93, 0.86, 0.76);
254        mWindow->getViewport(0)->setBackgroundColour(fadeColour);
255        //mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
[94]256       
[61]257        // Create a skybox
[175]258        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
[103]259       
[61]260        std::string terrain_cfg("terrain.cfg");
261#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
262        terrain_cfg = mResourcePath + terrain_cfg;
263#endif
[74]264        mSceneMgr->setWorldGeometry(terrain_cfg);
[75]265       
[161]266
[100]267        //-- CEGUI setup
[61]268        setupGui();
[100]269
[159]270        /* // occluder plane to test visibility
[160]271        Plane plane; plane.normal = Vector3::UNIT_Y;    plane.d = -60;
[111]272        MeshManager::getSingleton().createPlane("Myplane",
273                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
274                5000,5000,100,100,true,1,5,5,Vector3::UNIT_Z);
275        Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
276        pPlaneEnt->setMaterialName("Examples/Rockwall");
277        pPlaneEnt->setCastShadows(true);
[159]278        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt); */
279
[173]280        // Use 512x512 texture in GL since we can't go higher than the window res
281        mSceneMgr->setShadowTextureSettings(512, 2);
282
[112]283        mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
[159]284   
[111]285
[100]286        //-- terrain content setup
287
[80]288        // HACK: necessary to call once before the content creation for
289        // terrain initialisation
290        mSceneMgr->_renderScene(mCamera, mWindow->getViewport(0), true);
[74]291
[164]292        // ray query executor: needed to clamp to terrain
293        mRayQueryExecutor = new RayQueryExecutor(mSceneMgr);
294
295        mTerrainMinPos = EntityState::msMinPos = Vector3(0, 0, 0);
296        mTerrainMaxPos = EntityState::msMaxPos = Vector3(3000, 5000, 3000);
297
[82]298        mTerrainContentGenerator = new TerrainContentGenerator(mSceneMgr);
[110]299       
[160]300        // if no objects in file, we generate new objects
[110]301        if (!mTerrainContentGenerator->LoadObjects("objects.out"))
302        {
[160]303                // the objects are generated randomly distributed over the terrain
[175]304                generateScene(900, 0);
305                generateScene(500, 1);
306                generateScene(100, 2);
[110]307        }
[86]308
[175]309        // no limitations on height => it is possible for the user to put single
[164]310        // objects on peaks of the terrain (only few, not relevant for occlusion)
311        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
[61]312}
313//-----------------------------------------------------------------------
[160]314void  TestCullingTerrainApplication::generateScene(int num, int objectType)
315{
[173]316        Vector3 scale(TerrainFrameListener::msObjectScales[objectType],
317                                  TerrainFrameListener::msObjectScales[objectType],
318                                  TerrainFrameListener::msObjectScales[objectType]);
[160]319
[175]320        // to provide much occlusion,
321        // height is restricted to 50 => no objects are created on peaks
322        mTerrainContentGenerator->SetMinPos(Vector3(mTerrainMinPos));
323        mTerrainContentGenerator->SetMaxPos(Vector3(mTerrainMaxPos.x, 75.0f, mTerrainMaxPos.z));
324       
[173]325        mTerrainContentGenerator->SetScale(scale);
326        mTerrainContentGenerator->SetOffset(TerrainFrameListener::msObjectTerrainOffsets[objectType]);
327        mTerrainContentGenerator->GenerateScene(num, TerrainFrameListener::msObjectCaptions[objectType]);
328
[160]329        if (objectType != 0) // from our objects, only robot has animation phases
330                return;
331
332        EntityList *entList = mTerrainContentGenerator->GetGeneratedEntities();
333
334        //-- add animation state for new robots (located at the end of the list)
[175]335        for (int i = (int)entList->size() - num; i < (int)entList->size(); ++i)
[160]336        {
[161]337                mEntityStates.push_back(new EntityState((*entList)[i],
338                        EntityState::WAITING, Math::RangeRandom(0.5, 1.5)));
[160]339        }
[175]340
341        // no limitations anymore => it is possible for the user to put single
342        // objects on peaks of the terrain (only few, not relevant for occlusion)
343        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
[160]344}
345//-----------------------------------------------------------------------
[161]346void TestCullingTerrainApplication::updateAnimations(Real timeSinceLastFrame)
[160]347{
[161]348        for (int i = 0; i < (int)mEntityStates.size(); ++i)
349        {
[164]350                SceneNode *sn = mEntityStates[i]->GetEntity()->getParentSceneNode();
[161]351
352                mEntityStates[i]->update(timeSinceLastFrame);
353
354                if (mEntityStates[i]->GetState() == EntityState::MOVING)
355                {
[164]356                        Clamp2Terrain(sn, 0); //sn->setNodeVisible(false);
[161]357                }
358        }
[160]359}
360//-----------------------------------------------------------------------
[161]361EntityStates  &TestCullingTerrainApplication::getEntityStates()
[160]362{
[161]363        return mEntityStates;
[160]364}
365//-----------------------------------------------------------------------
[80]366void TestCullingTerrainApplication::setupGui()
[61]367{
[75]368         mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY,
369                 false, 3000, ST_EXTERIOR_CLOSE);
[61]370     mGUISystem = new CEGUI::System(mGUIRenderer);
371
372         // Mouse
373     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
374     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
[133]375         mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook",
376                                                                           (CEGUI::utf8*)"MouseArrow");
[61]377
[75]378         CEGUI::MouseCursor::getSingleton().show();
[61]379}
380//-----------------------------------------------------------------------
[80]381void TestCullingTerrainApplication::createFrameListener()
[61]382{
[133]383        mTerrainFrameListener = new TerrainFrameListener(mWindow, mCamera, mSceneMgr,
[160]384                mGUIRenderer, mTerrainContentGenerator, mVizCamera, mCamNode, mSunLight, this);
[120]385       
[115]386        mRoot->addFrameListener(mTerrainFrameListener);
[61]387}
388//-----------------------------------------------------------------------
[80]389void TestCullingTerrainApplication::chooseSceneManager()
[61]390{
391        mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE);
392}
[161]393//-----------------------------------------------------------------------
394bool TestCullingTerrainApplication::Clamp2Terrain(SceneNode *node, int terrainOffs)
395{
396        // clamp scene node to terrain
397        Vector3 pos = node->getPosition();
398        Vector3 queryResult;
399
400        if (mRayQueryExecutor->executeRayQuery(&queryResult,
401                        Vector3(pos.x, MAX_HEIGHT, pos.z), Vector3::NEGATIVE_UNIT_Y))
402        {
403        node->setPosition(pos.x, queryResult.y + terrainOffs, pos.z);
404                return true;
405        }
406
407        return false;
408}
409
410
[99]411/**************************************************************/
412/*      VisualizationRenderTargetListener implementation      */
413/**************************************************************/
[107]414//-----------------------------------------------------------------------
[99]415VisualizationRenderTargetListener::VisualizationRenderTargetListener(SceneManager *sceneMgr)
416:RenderTargetListener(), mSceneMgr(sceneMgr)
417{
418}
[61]419//-----------------------------------------------------------------------
[99]420void VisualizationRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt)
421{
[133]422        // visualization viewport
423        const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER;
[100]424        const bool nShowViz = !showViz;
425
[139]426        mSavedShadowTechnique = mSceneMgr->getShadowTechnique();
427        mSavedAmbientLight = mSceneMgr->getAmbientLight();
428
429        // -- ambient light must be full for visualization, shadows disabled
[113]430    if (showViz)
431        {
432                mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));
[139]433                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
[113]434        }
[139]435       
436    mSceneMgr->setOption("PrepareVisualization", &showViz);
[100]437        mSceneMgr->setOption("SkyBoxEnabled", &nShowViz);
438        //mSceneMgr->setOption("SkyPlaneEnabled", &showViz);
[99]439       
440        RenderTargetListener::preViewportUpdate(evt);
441}
442//-----------------------------------------------------------------------
443void VisualizationRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt)
444{
[139]445        // reset values
446        mSceneMgr->setShadowTechnique(mSavedShadowTechnique);
447        mSceneMgr->setAmbientLight(mSavedAmbientLight);
448       
[99]449        RenderTargetListener::postRenderTargetUpdate(evt);
450}
451//-----------------------------------------------------------------------
[61]452INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
453{
454    // Create application object
455    TestCullingTerrainApplication app;
456
457        try
458        {
459        app.go();
460    }
461        catch( Ogre::Exception& e )
462        {
[75]463        MessageBox( NULL, e.getFullDescription().c_str(),
464                        "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
[61]465    }   
466
467    return 0;
[160]468}
Note: See TracBrowser for help on using the repository browser.