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

Line 
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
8#include <Ogre.h>
9
10//#include "OgreReferenceAppLayer.h"
11//#include "OgreRefAppWorld.h"
12#include "TestCullingTerrainApplication.h"
13#include "TerrainFrameListener.h"
14
15#define WIN32_LEAN_AND_MEAN
16#include <windows.h>
17
18
19/**********************************************/
20/*             EntityState implementation     */
21/**********************************************/
22
23
24Vector3 EntityState::msMinPos = Vector3::ZERO;
25Vector3 EntityState::msMaxPos = Vector3::ZERO;
26
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//-----------------------------------------------------------------------
53EntityState::~EntityState()
54{
55        mAnimationState = NULL;
56        mEntity = NULL;
57}
58//-----------------------------------------------------------------------
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;
72
73        if (!mEntity || !mAnimationState)
74                return;
75       
76        if (mState == MOVING) // toggle between moving (longer) and waiting (short)
77        {
78                SceneNode *parent = mEntity->getParentSceneNode();
79               
80                if (!parent)
81                        return;
82
83                if (mTimeElapsed <= 0) // toggle animation state
84                {
85                        if (mAnimationState->getAnimationName() == "Idle")
86                        {
87                                SetAnimationState("Walk", true);
88                               
89                                mTimeElapsed = walk_duration; // walk for mTimeElapsed units
90
91                                // choose random rotation
92                                Radian rnd = Radian(Math::UnitRandom() * Math::PI * rotate_factor);
93
94                                //mEntity->getParentSceneNode()->rotate();
95                                parent->yaw(rnd);                                               
96                        }
97                        else
98                        {
99                                SetAnimationState("Idle", true);
100                                mTimeElapsed = wait_duration; // wait for mTimeElapsed seconds
101                        }
102                }
103
104                if (mAnimationState->getAnimationName() == "Walk") // move forward
105                {
106                        // store old position, just in case we get out of bounds
107                        Vector3 oldPos = parent->getPosition();
108                        parent->translate(parent->getLocalAxes(), Vector3(move_factor * mAnimationSpeed, 0, 0));
109
110                        // HACK: if out of bounds => reset to old position and set animationstate to idle
111                        if (OutOfBounds(parent))
112                        {
113                                parent->setPosition(oldPos);
114                                SetAnimationState("Idle", true);
115                               
116                                mTimeElapsed = wait_duration;
117                        }
118                }
119        }
120               
121        // add time to drive animation
122        mAnimationState->addTime(timeSinceLastFrame * mAnimationSpeed);
123}
124//-----------------------------------------------------------------------
125void EntityState::SetAnimationState(String stateStr, bool loop)
126{
127        if (!mEntity)
128                return;
129
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))
140                return false;
141
142        return true;
143}
144
145
146
147/*********************************************************/
148/*      TestCullingTerrainApplication implementation     */
149/*********************************************************/
150
151
152TestCullingTerrainApplication::TestCullingTerrainApplication():
153mTerrainContentGenerator(NULL), mRayQueryExecutor(NULL)
154{
155}
156//-----------------------------------------------------------------------
157TestCullingTerrainApplication::~TestCullingTerrainApplication()
158{
159        OGRE_DELETE(mTerrainContentGenerator);
160        OGRE_DELETE(mRayQueryExecutor);
161
162        deleteEntityStates();
163}
164//-----------------------------------------------------------------------
165void TestCullingTerrainApplication::deleteEntityStates()
166{
167        for (int i = 0; i < (int)mEntityStates.size(); ++i)
168        {
169                OGRE_DELETE(mEntityStates[i]);
170        }
171
172        mEntityStates.clear();
173}
174//-----------------------------------------------------------------------
175void TestCullingTerrainApplication::createCamera()
176{
177        // create the camera
178        mCamera = mSceneMgr->createCamera("PlayerCam");
179       
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        */
185        mCamNode = mSceneMgr->getRootSceneNode()->
186                createChildSceneNode("CamNode1", Vector3(707, 5000, 528));
187        //mCamera->setPosition(707, 5000, 528);
188        mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329));
189        mCamNode->attachObject(mCamera);
190
191        //-- create visualization camera
192        mVizCamera = mSceneMgr->createCamera("VizCam");
193        mVizCamera->setPosition(mCamNode->getPosition());
194
195        mVizCamera->setNearClipDistance(1);
196        mCamera->setNearClipDistance(1);
197
198        // infinite far plane?
199        if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
200        {
201                mVizCamera->setFarClipDistance(0);
202                mCamera->setFarClipDistance(0);
203        }
204        else
205        {
206                 mVizCamera->setFarClipDistance(20000);
207                 mCamera->setFarClipDistance(20000);
208        }       
209}
210
211//-----------------------------------------------------------------------
212bool TestCullingTerrainApplication::setup()
213{
214        bool carryOn = ExampleApplication::setup();
215
216        if (carryOn)
217                createRenderTargetListener();
218
219        return carryOn;
220}
221//-----------------------------------------------------------------------
222void TestCullingTerrainApplication::createRenderTargetListener()
223{
224        mWindow->addListener(new VisualizationRenderTargetListener(mSceneMgr));
225}
226//-----------------------------------------------------------------------
227void TestCullingTerrainApplication::createScene()
228{
229        Real scale = 3;
230        mSceneMgr->setOption("NodeVizScale", &scale);
231
232        // Set ambient light
233        mAmbientLight = ColourValue(0.5 , 0.5, 0.5);
234        mSceneMgr->setAmbientLight(mAmbientLight);
235       
236        //-- create light
237        mSunLight = mSceneMgr->createLight("SunLight");
238        mSunLight->setType(Light::LT_DIRECTIONAL);
239        //mSunLight->setType(Light::LT_SPOTLIGHT);
240        //mSunLight->setSpotlightRange(Degree(30), Degree(50));
241
242    mSunLight->setPosition(707, 2000, 500);
243        mSunLight->setCastShadows(true);
244
245        // set light angle not too small over the surface, otherwise shadows textures will be broken
246        Vector3 dir(0.5, 1, 0.5);
247        dir.normalise();
248        mSunLight->setDirection(dir);
249        //mSunLight->setDirection(Vector3::NEGATIVE_UNIT_Y);
250        mSunLight->setDiffuseColour(1, 1, 1);
251        mSunLight->setSpecularColour(1, 1, 1);
252
253        // -- Fog
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);
259       
260        // Create a skybox
261        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 5000, true);
262       
263        std::string terrain_cfg("terrain.cfg");
264#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
265        terrain_cfg = mResourcePath + terrain_cfg;
266#endif
267        mSceneMgr->setWorldGeometry(terrain_cfg);
268       
269
270        //-- CEGUI setup
271        setupGui();
272
273        /* // occluder plane to test visibility
274        Plane plane; plane.normal = Vector3::UNIT_Y;    plane.d = -60;
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);
281        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt); */
282
283        // Use 512x512 texture in GL since we can't go higher than the window res
284        mSceneMgr->setShadowTextureSettings(512, 2);
285
286        mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
287   
288
289        //-- terrain content setup
290
291        // HACK: necessary to call once before the content creation for
292        // terrain initialisation
293        mSceneMgr->_renderScene(mCamera, mWindow->getViewport(0), true);
294
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
301        mTerrainContentGenerator = new TerrainContentGenerator(mSceneMgr);
302       
303        // if no objects in file, we generate new objects
304        if (!mTerrainContentGenerator->LoadObjects("objects.out"))
305        {
306                // the objects are generated randomly distributed over the terrain
307                generateScene(900, 0);
308                generateScene(500, 1);
309                generateScene(100, 2);
310        }
311
312        // no limitations on height => it is possible for the user to put single
313        // objects on peaks of the terrain (only few, not relevant for occlusion)
314        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
315}
316//-----------------------------------------------------------------------
317void  TestCullingTerrainApplication::generateScene(int num, int objectType)
318{
319        Vector3 scale(TerrainFrameListener::msObjectScales[objectType],
320                                  TerrainFrameListener::msObjectScales[objectType],
321                                  TerrainFrameListener::msObjectScales[objectType]);
322
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       
328        mTerrainContentGenerator->SetScale(scale);
329        mTerrainContentGenerator->SetOffset(TerrainFrameListener::msObjectTerrainOffsets[objectType]);
330        mTerrainContentGenerator->GenerateScene(num, TerrainFrameListener::msObjectCaptions[objectType]);
331
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)
338        for (int i = (int)entList->size() - num; i < (int)entList->size(); ++i)
339        {
340                mEntityStates.push_back(new EntityState((*entList)[i],
341                        EntityState::WAITING, Math::RangeRandom(0.5, 1.5)));
342        }
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);
347}
348//-----------------------------------------------------------------------
349void TestCullingTerrainApplication::updateAnimations(Real timeSinceLastFrame)
350{
351        for (int i = 0; i < (int)mEntityStates.size(); ++i)
352        {
353                SceneNode *sn = mEntityStates[i]->GetEntity()->getParentSceneNode();
354
355                mEntityStates[i]->update(timeSinceLastFrame);
356
357                if (mEntityStates[i]->GetState() == EntityState::MOVING)
358                {
359                        Clamp2Terrain(sn, 0); //sn->setNodeVisible(false);
360                }
361        }
362}
363//-----------------------------------------------------------------------
364EntityStates  &TestCullingTerrainApplication::getEntityStates()
365{
366        return mEntityStates;
367}
368//-----------------------------------------------------------------------
369void TestCullingTerrainApplication::setupGui()
370{
371         mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY,
372                 false, 3000, ST_EXTERIOR_CLOSE);
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");
378         mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook",
379                                                                           (CEGUI::utf8*)"MouseArrow");
380
381         CEGUI::MouseCursor::getSingleton().show();
382}
383//-----------------------------------------------------------------------
384void TestCullingTerrainApplication::createFrameListener()
385{
386        mTerrainFrameListener = new TerrainFrameListener(mWindow, mCamera, mSceneMgr,
387                mGUIRenderer, mTerrainContentGenerator, mVizCamera, mCamNode, mSunLight, this);
388       
389        mRoot->addFrameListener(mTerrainFrameListener);
390}
391//-----------------------------------------------------------------------
392void TestCullingTerrainApplication::chooseSceneManager()
393{
394        mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE);
395}
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
414/**************************************************************/
415/*      VisualizationRenderTargetListener implementation      */
416/**************************************************************/
417//-----------------------------------------------------------------------
418VisualizationRenderTargetListener::VisualizationRenderTargetListener(SceneManager *sceneMgr)
419:RenderTargetListener(), mSceneMgr(sceneMgr)
420{
421}
422//-----------------------------------------------------------------------
423void VisualizationRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt)
424{
425        // visualization viewport
426        const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER;
427        const bool nShowViz = !showViz;
428
429        mSavedShadowTechnique = mSceneMgr->getShadowTechnique();
430        mSavedAmbientLight = mSceneMgr->getAmbientLight();
431
432        // -- ambient light must be full for visualization, shadows disabled
433    if (showViz)
434        {
435                mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));
436                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
437        }
438       
439    mSceneMgr->setOption("PrepareVisualization", &showViz);
440        mSceneMgr->setOption("SkyBoxEnabled", &nShowViz);
441        //mSceneMgr->setOption("SkyPlaneEnabled", &showViz);
442       
443        RenderTargetListener::preViewportUpdate(evt);
444}
445//-----------------------------------------------------------------------
446void VisualizationRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt)
447{
448        // reset values
449        mSceneMgr->setShadowTechnique(mSavedShadowTechnique);
450        mSceneMgr->setAmbientLight(mSavedAmbientLight);
451       
452        RenderTargetListener::postRenderTargetUpdate(evt);
453}
454//-----------------------------------------------------------------------
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        {
466        MessageBox( NULL, e.getFullDescription().c_str(),
467                        "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
468    }   
469
470    return 0;
471}
Note: See TracBrowser for help on using the repository browser.