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

Revision 187, 15.2 KB checked in by mattausch, 19 years ago (diff)

added animationbug fix (deleting while animation)fixed visibilityQueriesadditive shadow volumes fixed for octree
hack to fully empty queue after traversal
added demo for vienna model

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{
[187]229        Real scale = 3;
230        mSceneMgr->setOption("NodeVizScale", &scale);
231
[61]232        // Set ambient light
[175]233        mAmbientLight = ColourValue(0.5 , 0.5, 0.5);
[139]234        mSceneMgr->setAmbientLight(mAmbientLight);
[113]235       
[110]236        //-- create light
[111]237        mSunLight = mSceneMgr->createLight("SunLight");
238        mSunLight->setType(Light::LT_DIRECTIONAL);
239        //mSunLight->setType(Light::LT_SPOTLIGHT);
[112]240        //mSunLight->setSpotlightRange(Degree(30), Degree(50));
241
[111]242    mSunLight->setPosition(707, 2000, 500);
243        mSunLight->setCastShadows(true);
244
[173]245        // set light angle not too small over the surface, otherwise shadows textures will be broken
[113]246        Vector3 dir(0.5, 1, 0.5);
[110]247        dir.normalise();
[112]248        mSunLight->setDirection(dir);
249        //mSunLight->setDirection(Vector3::NEGATIVE_UNIT_Y);
[111]250        mSunLight->setDiffuseColour(1, 1, 1);
251        mSunLight->setSpecularColour(1, 1, 1);
[110]252
[137]253        // -- Fog
[61]254        // NB it's VERY important to set this before calling setWorldGeometry
255        // because the vertex program picked will be different
256        ColourValue fadeColour(0.93, 0.86, 0.76);
257        mWindow->getViewport(0)->setBackgroundColour(fadeColour);
258        //mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000);
[94]259       
[61]260        // Create a skybox
[175]261        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
[103]262       
[61]263        std::string terrain_cfg("terrain.cfg");
264#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
265        terrain_cfg = mResourcePath + terrain_cfg;
266#endif
[74]267        mSceneMgr->setWorldGeometry(terrain_cfg);
[75]268       
[161]269
[100]270        //-- CEGUI setup
[61]271        setupGui();
[100]272
[159]273        /* // occluder plane to test visibility
[160]274        Plane plane; plane.normal = Vector3::UNIT_Y;    plane.d = -60;
[111]275        MeshManager::getSingleton().createPlane("Myplane",
276                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
277                5000,5000,100,100,true,1,5,5,Vector3::UNIT_Z);
278        Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
279        pPlaneEnt->setMaterialName("Examples/Rockwall");
280        pPlaneEnt->setCastShadows(true);
[159]281        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt); */
282
[173]283        // Use 512x512 texture in GL since we can't go higher than the window res
284        mSceneMgr->setShadowTextureSettings(512, 2);
285
[112]286        mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
[159]287   
[111]288
[100]289        //-- terrain content setup
290
[80]291        // HACK: necessary to call once before the content creation for
292        // terrain initialisation
293        mSceneMgr->_renderScene(mCamera, mWindow->getViewport(0), true);
[74]294
[164]295        // ray query executor: needed to clamp to terrain
296        mRayQueryExecutor = new RayQueryExecutor(mSceneMgr);
297
298        mTerrainMinPos = EntityState::msMinPos = Vector3(0, 0, 0);
299        mTerrainMaxPos = EntityState::msMaxPos = Vector3(3000, 5000, 3000);
300
[82]301        mTerrainContentGenerator = new TerrainContentGenerator(mSceneMgr);
[110]302       
[160]303        // if no objects in file, we generate new objects
[110]304        if (!mTerrainContentGenerator->LoadObjects("objects.out"))
305        {
[160]306                // the objects are generated randomly distributed over the terrain
[175]307                generateScene(900, 0);
308                generateScene(500, 1);
309                generateScene(100, 2);
[110]310        }
[86]311
[175]312        // no limitations on height => it is possible for the user to put single
[164]313        // objects on peaks of the terrain (only few, not relevant for occlusion)
314        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
[61]315}
316//-----------------------------------------------------------------------
[160]317void  TestCullingTerrainApplication::generateScene(int num, int objectType)
318{
[173]319        Vector3 scale(TerrainFrameListener::msObjectScales[objectType],
320                                  TerrainFrameListener::msObjectScales[objectType],
321                                  TerrainFrameListener::msObjectScales[objectType]);
[160]322
[175]323        // to provide much occlusion,
324        // height is restricted to 50 => no objects are created on peaks
325        mTerrainContentGenerator->SetMinPos(Vector3(mTerrainMinPos));
326        mTerrainContentGenerator->SetMaxPos(Vector3(mTerrainMaxPos.x, 75.0f, mTerrainMaxPos.z));
327       
[173]328        mTerrainContentGenerator->SetScale(scale);
329        mTerrainContentGenerator->SetOffset(TerrainFrameListener::msObjectTerrainOffsets[objectType]);
330        mTerrainContentGenerator->GenerateScene(num, TerrainFrameListener::msObjectCaptions[objectType]);
331
[160]332        if (objectType != 0) // from our objects, only robot has animation phases
333                return;
334
335        EntityList *entList = mTerrainContentGenerator->GetGeneratedEntities();
336
337        //-- add animation state for new robots (located at the end of the list)
[175]338        for (int i = (int)entList->size() - num; i < (int)entList->size(); ++i)
[160]339        {
[161]340                mEntityStates.push_back(new EntityState((*entList)[i],
341                        EntityState::WAITING, Math::RangeRandom(0.5, 1.5)));
[160]342        }
[175]343
344        // no limitations anymore => it is possible for the user to put single
345        // objects on peaks of the terrain (only few, not relevant for occlusion)
346        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
[160]347}
348//-----------------------------------------------------------------------
[161]349void TestCullingTerrainApplication::updateAnimations(Real timeSinceLastFrame)
[160]350{
[161]351        for (int i = 0; i < (int)mEntityStates.size(); ++i)
352        {
[164]353                SceneNode *sn = mEntityStates[i]->GetEntity()->getParentSceneNode();
[161]354
355                mEntityStates[i]->update(timeSinceLastFrame);
356
357                if (mEntityStates[i]->GetState() == EntityState::MOVING)
358                {
[164]359                        Clamp2Terrain(sn, 0); //sn->setNodeVisible(false);
[161]360                }
361        }
[160]362}
363//-----------------------------------------------------------------------
[161]364EntityStates  &TestCullingTerrainApplication::getEntityStates()
[160]365{
[161]366        return mEntityStates;
[160]367}
368//-----------------------------------------------------------------------
[80]369void TestCullingTerrainApplication::setupGui()
[61]370{
[75]371         mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY,
372                 false, 3000, ST_EXTERIOR_CLOSE);
[61]373     mGUISystem = new CEGUI::System(mGUIRenderer);
374
375         // Mouse
376     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
377     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
[133]378         mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook",
379                                                                           (CEGUI::utf8*)"MouseArrow");
[61]380
[75]381         CEGUI::MouseCursor::getSingleton().show();
[61]382}
383//-----------------------------------------------------------------------
[80]384void TestCullingTerrainApplication::createFrameListener()
[61]385{
[133]386        mTerrainFrameListener = new TerrainFrameListener(mWindow, mCamera, mSceneMgr,
[160]387                mGUIRenderer, mTerrainContentGenerator, mVizCamera, mCamNode, mSunLight, this);
[120]388       
[115]389        mRoot->addFrameListener(mTerrainFrameListener);
[61]390}
391//-----------------------------------------------------------------------
[80]392void TestCullingTerrainApplication::chooseSceneManager()
[61]393{
394        mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE);
395}
[161]396//-----------------------------------------------------------------------
397bool TestCullingTerrainApplication::Clamp2Terrain(SceneNode *node, int terrainOffs)
398{
399        // clamp scene node to terrain
400        Vector3 pos = node->getPosition();
401        Vector3 queryResult;
402
403        if (mRayQueryExecutor->executeRayQuery(&queryResult,
404                        Vector3(pos.x, MAX_HEIGHT, pos.z), Vector3::NEGATIVE_UNIT_Y))
405        {
406        node->setPosition(pos.x, queryResult.y + terrainOffs, pos.z);
407                return true;
408        }
409
410        return false;
411}
412
413
[99]414/**************************************************************/
415/*      VisualizationRenderTargetListener implementation      */
416/**************************************************************/
[107]417//-----------------------------------------------------------------------
[99]418VisualizationRenderTargetListener::VisualizationRenderTargetListener(SceneManager *sceneMgr)
419:RenderTargetListener(), mSceneMgr(sceneMgr)
420{
421}
[61]422//-----------------------------------------------------------------------
[99]423void VisualizationRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt)
424{
[133]425        // visualization viewport
426        const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER;
[100]427        const bool nShowViz = !showViz;
428
[139]429        mSavedShadowTechnique = mSceneMgr->getShadowTechnique();
430        mSavedAmbientLight = mSceneMgr->getAmbientLight();
431
432        // -- ambient light must be full for visualization, shadows disabled
[113]433    if (showViz)
434        {
435                mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));
[139]436                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
[113]437        }
[139]438       
439    mSceneMgr->setOption("PrepareVisualization", &showViz);
[100]440        mSceneMgr->setOption("SkyBoxEnabled", &nShowViz);
441        //mSceneMgr->setOption("SkyPlaneEnabled", &showViz);
[99]442       
443        RenderTargetListener::preViewportUpdate(evt);
444}
445//-----------------------------------------------------------------------
446void VisualizationRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt)
447{
[139]448        // reset values
449        mSceneMgr->setShadowTechnique(mSavedShadowTechnique);
450        mSceneMgr->setAmbientLight(mSavedAmbientLight);
451       
[99]452        RenderTargetListener::postRenderTargetUpdate(evt);
453}
454//-----------------------------------------------------------------------
[61]455INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
456{
457    // Create application object
458    TestCullingTerrainApplication app;
459
460        try
461        {
462        app.go();
463    }
464        catch( Ogre::Exception& e )
465        {
[75]466        MessageBox( NULL, e.getFullDescription().c_str(),
467                        "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
[61]468    }   
469
470    return 0;
[160]471}
Note: See TracBrowser for help on using the repository browser.