source: GTP/trunk/App/Demos/Vis/HillyTerrain/OGRE/TestCullingTerrainApplication.cpp @ 648

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

removed problems with bsp due to polygons equal to scene box faces. removing
this polyogns in a preprocessing step. also using this for vsp bsp tree, because it
is generally a good thing.

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(1024, 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(5000, 5000, 5000);
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(1000, 0); // create soldiers, trees, ninjas
308                generateScene(500, 1);
309                generateScene(100, 2);
310        }
311}
312//-----------------------------------------------------------------------
313void  TestCullingTerrainApplication::generateScene(int num, int objectType)
314{
315        float val = TerrainFrameListener::msObjectScales[objectType];
316        Vector3 scale(val, val, val);
317        const float maxHeight = 75;
318       
319        // In order to provide much occlusion,
320        // height is restricted to maxHeight => no objects are created on peaks
321        mTerrainContentGenerator->SetMinPos(Vector3(mTerrainMinPos));
322        mTerrainContentGenerator->SetMaxPos(Vector3(mTerrainMaxPos.x, maxHeight, mTerrainMaxPos.z));
323       
324        //std::stringstream d; d << "objscale: " << scale[0];
325        //Ogre::LogManager::getSingleton().logMessage(d.str());
326       
327        mTerrainContentGenerator->SetScale(scale);
328        mTerrainContentGenerator->SetOffset(TerrainFrameListener::msObjectTerrainOffsets[objectType]);
329        mTerrainContentGenerator->GenerateScene(num, TerrainFrameListener::msObjectCaptions[objectType]);
330
331        if (objectType != 0) // from our objects, only robot has animation phases
332                return;
333
334        EntityList *entList = mTerrainContentGenerator->GetGeneratedEntities();
335
336        //-- add animation state for new robots (located at the end of the list)
337        for (int i = (int)entList->size() - num; i < (int)entList->size(); ++i)
338        {
339                mEntityStates.push_back(new EntityState((*entList)[i],
340                        EntityState::WAITING, Math::RangeRandom(0.5, 1.5)));
341        }
342
343        // release limitations on height => it is possible for the user to put single
344        // objects on peaks of the terrain (will be only few, not relevant for occlusion)
345        mTerrainContentGenerator->SetMaxPos(mTerrainMaxPos);
346}
347//-----------------------------------------------------------------------
348void TestCullingTerrainApplication::updateAnimations(Real timeSinceLastFrame)
349{
350        for (int i = 0; i < (int)mEntityStates.size(); ++i)
351        {
352                SceneNode *sn = mEntityStates[i]->GetEntity()->getParentSceneNode();
353
354                mEntityStates[i]->update(timeSinceLastFrame);
355
356                if (mEntityStates[i]->GetState() == EntityState::MOVING)
357                {
358                        Clamp2Terrain(sn, 0); //sn->setNodeVisible(false);
359                }
360        }
361}
362//-----------------------------------------------------------------------
363EntityStates  &TestCullingTerrainApplication::getEntityStates()
364{
365        return mEntityStates;
366}
367//-----------------------------------------------------------------------
368void TestCullingTerrainApplication::setupGui()
369{
370         mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY,
371                 false, 3000, ST_EXTERIOR_CLOSE);
372     mGUISystem = new CEGUI::System(mGUIRenderer);
373
374         // Mouse
375     CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme");
376     CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");
377         mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook",
378                                                                           (CEGUI::utf8*)"MouseArrow");
379
380         CEGUI::MouseCursor::getSingleton().hide();
381}
382//-----------------------------------------------------------------------
383void TestCullingTerrainApplication::createFrameListener()
384{
385        mTerrainFrameListener = new TerrainFrameListener(mWindow, mCamera, mSceneMgr,
386                mGUIRenderer, mTerrainContentGenerator, mVizCamera, mCamNode, mSunLight, this);
387       
388        mRoot->addFrameListener(mTerrainFrameListener);
389}
390//-----------------------------------------------------------------------
391void TestCullingTerrainApplication::chooseSceneManager()
392{
393        mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE);
394}
395//-----------------------------------------------------------------------
396bool TestCullingTerrainApplication::Clamp2Terrain(SceneNode *node, int terrainOffs)
397{
398        // clamp scene node to terrain
399        Vector3 pos = node->getPosition();
400        Vector3 queryResult;
401
402        if (mRayQueryExecutor->executeRayQuery(&queryResult,
403                        Vector3(pos.x, MAX_HEIGHT, pos.z), Vector3::NEGATIVE_UNIT_Y))
404        {
405        node->setPosition(pos.x, queryResult.y + terrainOffs, pos.z);
406                return true;
407        }
408
409        return false;
410}
411
412
413/**************************************************************/
414/*      VisualizationRenderTargetListener implementation      */
415/**************************************************************/
416//-----------------------------------------------------------------------
417VisualizationRenderTargetListener::VisualizationRenderTargetListener(SceneManager *sceneMgr)
418:RenderTargetListener(), mSceneMgr(sceneMgr)
419{
420}
421//-----------------------------------------------------------------------
422void VisualizationRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt)
423{
424        // visualization viewport
425        const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER;
426        const bool nShowViz = !showViz;
427
428        mSavedShadowTechnique = mSceneMgr->getShadowTechnique();
429        mSavedAmbientLight = mSceneMgr->getAmbientLight();
430
431        // -- ambient light must be full for visualization, shadows disabled
432    if (showViz)
433        {
434                mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));
435                mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);
436        }
437       
438    mSceneMgr->setOption("PrepareVisualization", &showViz);
439        mSceneMgr->setOption("SkyBoxEnabled", &nShowViz);
440        //mSceneMgr->setOption("SkyPlaneEnabled", &showViz);
441       
442        RenderTargetListener::preViewportUpdate(evt);
443}
444//-----------------------------------------------------------------------
445void VisualizationRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt)
446{
447        // reset values
448        mSceneMgr->setShadowTechnique(mSavedShadowTechnique);
449        mSceneMgr->setAmbientLight(mSavedAmbientLight);
450       
451        RenderTargetListener::postRenderTargetUpdate(evt);
452}
453//-----------------------------------------------------------------------
454INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
455{
456    // Create application object
457    TestCullingTerrainApplication app;
458
459        try
460        {
461        app.go();
462    }
463        catch( Ogre::Exception& e )
464        {
465        MessageBox( NULL, e.getFullDescription().c_str(),
466                        "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
467    }   
468
469    return 0;
470}
Note: See TracBrowser for help on using the repository browser.