BaseCommand.h
/* ----------------------------------------------------------------------------- Filename: BaseCommand.h ----------------------------------------------------------------------------- This source file is generated by the Ogre AppWizard. Check out: http://conglomerate.berlios.de/wiki/doku.php?id=ogrewizards Based on the Example Framework for OGRE (Object-oriented Graphics Rendering Engine) Copyright (c) 2000-2007 The OGRE Team For the latest info, see http://www.ogre3d.org/ You may use this sample code for anything you like, it is not covered by the LGPL like the rest of the OGRE engine. ----------------------------------------------------------------------------- */ #ifndef __BaseCommand_h_ #define __BaseCommand_h_ #include "ExampleApplication.h" #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #include "../res/resource.h" #endif #include "BaseCommandFrameListener.h" ET::TerrainManager *gTerrainMgr = NULL; ET::SplattingManager *gSplatMgr = NULL; #ifdef USE_PARTICLEUNIVERSE ParticleUniverse::ParticleSystemManager *gParticleSystemMgr = NULL; ParticleUniverse::ParticleSystem *gExplosionParticleSystem = NULL; ParticleUniverse::ParticleSystem *gFireParticleSystem = NULL; #endif Caelum::CaelumSystem *gCaelumSystem = NULL; // Pointers to PagedGeometry class instances: PagedGeometry *gTrees = NULL; PagedGeometry *gGrass = NULL; PagedGeometry *gBushes = NULL; TreeLoader3D *gTreeLoader = NULL; GrassLoader *gGrassLoader = NULL; LogManager *gLogMgr = NULL; SoundManager *gSoundMgr = NULL; std::list< Vehicle *> gVehicles; int gExplosionSoundId; int gAirRaidSoundId; /******************* NOTES ******************* - Memory leak on gGrass when calling PagedGeometry::update() - Memory leak on gCaelumSystem *********************************************/ // For the grass loader inline float getTerrainHeight(const float x, const float z, void *userData = NULL) { return gTerrainMgr->getTerrainInfo().getHeightAt( x, z ); } class BaseCommandApp : public ExampleApplication { Caelum::FlatCloudLayer* mCloudLayer2; public: BaseCommandApp() { srand(time(NULL)); } ~BaseCommandApp() { if( gTrees ) { delete gTrees->getPageLoader(); SAFE_DELETE(gTrees) } if( gBushes ) { delete gBushes->getPageLoader(); SAFE_DELETE(gBushes) } if( gGrass ) { SAFE_DELETE(gGrassLoader); SAFE_DELETE(gGrass); } if (gCaelumSystem) { //delete mCloudLayer2; SAFE_DELETE(gCaelumSystem); //gCaelumSystem->shutdown (true); //gCaelumSystem = 0; } SAFE_DELETE(gSplatMgr); SAFE_DELETE(gTerrainMgr); SAFE_DELETE(gSoundMgr); for( std::list<Vehicle*>::iterator list_iter = gVehicles.begin(); list_iter != gVehicles.end(); ) { Vehicle *p = &**list_iter; SAFE_DELETE(p); list_iter++; } } protected: virtual void createCamera(void) { // Create the camera mCamera = mSceneMgr->createCamera("PlayerCam"); // position it at 500 in Z direction mCamera->setPosition(Vector3(0,100,80)); // Look back along -Z mCamera->lookAt(Vector3(500,0,500)); mCamera->setNearClipDistance(5); mCamera->setFarClipDistance(10000); // Default is 100000 } virtual bool configure(void) { // Show the configuration dialog and initialise the system // You can skip this and use root.restoreConfig() to load configuration // settings if you were sure there are valid ones saved in ogre.cfg if(/*mRoot->restoreConfig() ||*/ mRoot->showConfigDialog()) { // If returned true, user clicked OK so initialise // Here we choose to let the system create a default rendering window by passing 'true' mWindow = mRoot->initialise(true); // Let's add a nice window icon #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 HWND hwnd; mWindow->getCustomAttribute("WINDOW", (void*)&hwnd); LONG iconID = (LONG)LoadIcon( GetModuleHandle(0), MAKEINTRESOURCE(IDI_APPICON) ); SetClassLong( hwnd, GCL_HICON, iconID ); #endif return true; } else { return false; } } // Just override the mandatory create scene method virtual void createScene(void) { // Store a copy of the log manager to our global pointer gLogMgr = LogManager::getSingletonPtr(); gLogMgr->logMessage( "Initializing scene." ); // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5)); // Set a nice skybox mSceneMgr->setSkyBox(true, "SkyBox"); // Create a light Light* l = mSceneMgr->createLight("MainLight"); l->setPosition(20,80,50); initTerrain(); initTrees(); initGrass(); initBushes(); initOcean(); initClouds(); #ifdef USE_PARTICLEUNIVERSE initParticles(); #endif initTurret(); initSounds(); gLogMgr->logMessage( "Done initializing scene." ); } void initGrass() { //-------------------------------------- LOAD gGrass -------------------------------------- //Create and configure a new PagedGeometry instance for grass gGrass = new PagedGeometry(mCamera, 100); gGrass->addDetailLevel<GrassPage>(500); //Create a GrassLoader object gGrassLoader = new GrassLoader(gGrass); gGrass->setPageLoader(gGrassLoader); //Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance //Supply a height function to gGrassLoader so it can setLeader gGrass Y values //HeightFunction::initialize(mSceneMgr); gGrassLoader->setHeightFunction(&getTerrainHeight); //Add some grass to the scene with gGrassLoader::addLayer() GrassLayer *l = gGrassLoader->addLayer("3D-Diggers/plant1sprite"); //Configure the grass layer properties (size, density, animation properties, fade settings, etc.) l->setMinimumSize(2.5f, 2.5f); l->setMaximumSize(6.0f, 6.0f); l->setAnimationEnabled(true); //Enable animations l->setSwayDistribution(10.0f); //Sway fairly unsynchronized l->setSwayLength(0.5f); //Sway back and forth 0.5 units in length l->setSwaySpeed(0.5f); //Sway 1/2 a cycle every second l->setDensity(0.2f); //Relatively dense grass l->setFadeTechnique(FADETECH_GROW); //Distant gGrass should slowly raise out of the ground when coming in range l->setRenderTechnique(GRASSTECH_QUAD); //Draw gGrass as scattered quads //This sets a color map to be used when determining the color of each grass quad. setMapBounds() //is used to set the area which is affected by the color map. Here, "terrain_texture.jpg" is used //to color the grass to match the terrain under it. l->setColorMap("terrain_texture.jpg"); l->setMapBounds(TBounds(0, 0, 1500, 1500)); //(0,0)-(1500,1500) is the full boundaries of the terrain } void initClouds() { Caelum::CaelumSystem::CaelumComponent componentMask; componentMask = static_cast<Caelum::CaelumSystem::CaelumComponent> (Caelum::CaelumSystem::CAELUM_COMPONENT_CLOUDS); gCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), mSceneMgr, componentMask); //gCaelumSystem->setManageSceneFog(false); // Freeze cloud movement, we will update it manually //gCaelumSystem->setTimeScale(0); // Tweak the default layer float farClip = mCamera->getFarClipDistance(); // First layer by default creates a cloud at height 3000 gCaelumSystem->getCloudSystem()->getLayer(0)->setHeight(1200.f); gCaelumSystem->getCloudSystem()->getLayer(0)->setFadeDistances( farClip * 0.8f, farClip ); gCaelumSystem->getCloudSystem()->getLayer(0)->setCloudCover(0.5f); // Add another layer /* Caelum::FlatCloudLayer* layer = gCaelumSystem->getCloudSystem ()->createLayerAtHeight (1800.f); layer->setFadeDistances( farClip * 0.8f, farClip ); layer->setCloudCover (0.7f); layer->_ensureGeometry(); gCaelumSystem->getCloudSystem()->addLayer(layer); */ // Don't register, we will update the cloud system manually //mWindow->addListener (gCaelumSystem); //Root::getSingletonPtr()->addFrameListener (gCaelumSystem); } void initBushes() { //Create and configure a new PagedGeometry instance for gBushes gBushes = new PagedGeometry(mCamera, 100); gBushes->addDetailLevel<BatchPage>(1500, 50); //Create a new TreeLoader2D object for the gBushes //TreeLoader2D *bushLoader = new TreeLoader2D(gBushes, TBounds(0, 0, 1500, 1500)); TreeLoader3D *bushLoader = new TreeLoader3D(gBushes, TBounds(0, 0, 1500, 1500)); bushLoader->setMaximumScale(4.f); //Load a bush entity Entity *fern = mSceneMgr->createEntity("Fern", "farn1.mesh"); Entity *plant = mSceneMgr->createEntity("Plant", "plant2.mesh"); Entity *mushroom = mSceneMgr->createEntity("Mushroom", "shroom1_1.mesh"); Vector3 position; Radian yaw; Real scale; for (int i = 0; i < 200; i++) { position.x = Math::RangeRandom(0, 1500); position.z = Math::RangeRandom(0, 1500); // Make a clear path between the turret and the base if( !((position.x > 700.f && position.x < 950.f) && (position.z > 1000.0f && position.z < 1250.f))) { position.y = gTerrainMgr->getTerrainInfo().getHeightAt( position.x, position.z ); yaw = Degree(Math::RangeRandom(0, 360)); float rnd = Math::UnitRandom(); if (rnd < 0.3f) { scale = Math::RangeRandom(0.7f, 1.5f); //bushLoader->addTree(fern, position, yaw, scale); } else if (rnd < 0.7) { scale = Math::RangeRandom(2.0f, 4.f); //bushLoader->addTree(plant, position, yaw, scale); } else { scale = Math::RangeRandom(2.0f, 4.f); bushLoader->addTree(mushroom, position, yaw, scale); } } } gBushes->setPageLoader(bushLoader); } void initTrees() { //Create and configure a new PagedGeometry instance gTrees = new PagedGeometry(); gTrees->setCamera(mCamera); //Set the camera so PagedGeometry knows how to setLeader LODs gTrees->setPageSize(80); //Set the size of each page of geometry gTrees->setInfinite(); //Use infinite paging mode gTrees->addDetailLevel<BatchPage>(150, 50); //Use batches up to # units away, and fade for # more units gTrees->addDetailLevel<ImpostorPage>(1500, 250); //Use impostors up to # units, and for # more units // Load a tree entity Entity *myEntity = mSceneMgr->createEntity("Tree", "fir05_30.mesh"); Entity *tree2 = mSceneMgr->createEntity("Tree2", "fir14_25.mesh"); //Create a new TreeLoader3D object gTreeLoader = new TreeLoader3D(gTrees, TBounds(0, 0, 1500, 1500)); // Randomly place 20,000 copies of the tree on the terrain Vector3 position; Radian yaw; Real scale; for (int i = 0; i < 200; i++) { position.x = Math::RangeRandom(0, 1500); position.z = Math::RangeRandom(0, 1500); // Make a clear path between the turret and the base if( !((position.x > 500.f && position.x < 950.f) && (position.z > 500.0f && position.z < 1250.f))) { position.y = gTerrainMgr->getTerrainInfo().getHeightAt( position.x, position.z ); yaw = Degree(Math::RangeRandom(0, 360)); scale = Math::RangeRandom(0.5f, 0.6f); float rnd = Math::UnitRandom(); if (rnd < 0.5f) gTreeLoader->addTree(myEntity, position, yaw, scale); else gTreeLoader->addTree(tree2, position, yaw, scale); } } gTrees->setPageLoader(gTreeLoader); //Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance } #ifdef USE_PARTICLEUNIVERSE void initParticles() { gParticleSystemMgr = ParticleUniverse::ParticleSystemManager::getSingletonPtr(); gExplosionParticleSystem = gParticleSystemMgr->createParticleSystem("mySingleSystem", "explosionSystem", mSceneMgr); gExplosionParticleSystem->start(); mSceneMgr->getRootSceneNode()->createChildSceneNode("exnode")->attachObject( gExplosionParticleSystem ); gFireParticleSystem = gParticleSystemMgr->createParticleSystem("fireSystem", "fireSystem", mSceneMgr); gFireParticleSystem->start(); mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject( gFireParticleSystem ); } #endif void initTurret() { Entity *base = mSceneMgr->createEntity( "base", "base.mesh" ); Entity *turret = mSceneMgr->createEntity( "turret", "turret.mesh" ); Entity *turretgun = mSceneMgr->createEntity( "turretgun", "turretgun.mesh" ); base->setMaterialName( "turret/base" ); turret->setMaterialName( "turret/base" ); turretgun->setMaterialName( "turret/base" ); SceneNode *baseNode = mSceneMgr->getRootSceneNode()->createChildSceneNode( "turret" ); baseNode->pitch( -Radian(Math::HALF_PI) ); baseNode->roll( Radian(Math::HALF_PI) ); baseNode->scale( 5, 5, 5 ); float posY = gTerrainMgr->getTerrainInfo().getHeightAt( 866.f, 1229.f ); baseNode->setPosition( 866.f, posY + 1.f, 1229.f ); baseNode->attachObject( base ); // Attach cam to turret sceneNode too { Vector3 lookAt = baseNode->getPosition(); lookAt.normalise(); mCamera->detatchFromParent(); mCamera->setPosition(0.f, 0.f, 0.f); mCamera->lookAt(Vector3::UNIT_X); SceneNode *camnode = baseNode->createChildSceneNode( Vector3( 0.0f /* pull the cam a little back */, 0.f, 2.2f /* move the cam up a little bit */ ) ); camnode->pitch(Radian(Math::HALF_PI)); // Re-orient the cam to take into account the pitch needed by the turret camnode->attachObject( mCamera ); } SceneNode *turretNode = baseNode->createChildSceneNode( "turretnode", Vector3( 0, 0, 0.7 ) ); turretNode->attachObject( turret ); SceneNode *turretGunNode = turretNode->createChildSceneNode( "gunnode", Vector3( 1.5, 0, 0 ) ); turretGunNode->attachObject( turretgun ); } void initOcean() { // Define a plane mesh that will be used for the ocean surface Ogre::Plane oceanSurface; oceanSurface.normal = Ogre::Vector3::UNIT_Y; oceanSurface.d = 0; Ogre::MeshManager::getSingleton().createPlane("OceanSurface", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, oceanSurface, 10000, 10000, 50, 50, true, 1, 1, 1, Ogre::Vector3::UNIT_Z); Entity *mOceanSurfaceEnt = mSceneMgr->createEntity( "OceanSurface", "OceanSurface" ); mOceanSurfaceEnt->setCastShadows(false); mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(1250.f, 67.0f, 1250.f))->attachObject(mOceanSurfaceEnt); mOceanSurfaceEnt->setMaterialName("OceanCg"); } void initTerrain() { // create terrain manager gTerrainMgr = new ET::TerrainManager(mSceneMgr); gTerrainMgr->setLODErrorMargin(2, mCamera->getViewport()->getActualHeight()); gTerrainMgr->setUseLODMorphing(true, 0.2, "morphFactor"); // Load the height map Image image; image.load("level.bmp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); ET::TerrainInfo terrainInfo; ET::loadHeightmapFromImage( terrainInfo, image ); // set position and size of the terrain terrainInfo.setExtents(AxisAlignedBox(0, 0, 0, 1500, 500, 1500)); // now render it gTerrainMgr->createTerrain(terrainInfo); // Load blend map Image blendMap[3]; blendMap[0].load( "ETcoverage.0.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); blendMap[1].load( "ETcoverage.1.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); blendMap[2].load( "ETcoverage.2.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); // create the splatting manager gSplatMgr = new ET::SplattingManager("ETSplatting", "ET", 256, 256, 3); // specify number of splatting textures we need to handle gSplatMgr->setNumTextures(9); for( int i = 0; i < 3; i++) { gSplatMgr->loadMapFromImage( i, blendMap[i] ); } // create a manual lightmap texture TexturePtr lightmapTex = TextureManager::getSingleton().createManual( "ETLightmap", "ET", TEX_TYPE_2D, 128, 128, 1, PF_BYTE_RGB); Image lightmap; ET::createTerrainLightmap(terrainInfo, lightmap, 128, 128, Vector3(1, -1, 1), ColourValue::White, ColourValue(0.3, 0.3, 0.3)); lightmapTex->getBuffer(0, 0)->blitFromMemory(lightmap.getPixelBox(0, 0)); // load the terrain material and assign it MaterialPtr material (MaterialManager::getSingleton().getByName("ETTerrainMaterial")); gTerrainMgr->setMaterial(material); } void initSounds() { gSoundMgr = new SoundManager; gSoundMgr->Initialize(); gExplosionSoundId = gSoundMgr->CreateSound(String("51467_smcameron_missile_explosion.wav")); gAirRaidSoundId = gSoundMgr->CreateSound(String("57808_guitarguy1985_carterattack_fadeout.mp3")); } // Create new frame listener void createFrameListener(void) { mFrameListener= new BaseCommandFrameListener(mSceneMgr, mWindow, mCamera); mRoot->addFrameListener(mFrameListener); } }; #endif // #ifndef __BaseCommand_h_