BasicTutorial3_manual.h
#ifndef __BasicTutorial3_h_ #define __BasicTutorial3_h_ //1 begin #include <OgreTerrain.h> #include <OgreTerrainGroup.h> //1 end #include "BaseApplication.h" #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #endif class BasicTutorial3 : public BaseApplication { //1 begin private: Ogre::TerrainGlobalOptions* mTerrainGlobals; Ogre::TerrainGroup* mTerrainGroup; bool mTerrainImported; void defineTerrain(long x,long y); void initBlendMaps(Ogre::Terrain* terrain); void configureTerrainDefaults(Ogre::Light* light); //part2 1 begin OgreBites::Label* mInfoLabel; //part2 1 end //1 end public: BasicTutorial3(void); virtual ~BasicTutorial3(void); protected: virtual void createScene(void); virtual void createFrameListener(void); virtual void destroyScene(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); }; #endif // #ifndef __BasicTutorial3_h_
BasicTutorial3_manual.cpp
#include "BasicTutorial3_manual.h" //------------------------------------------------------------------------------------- BasicTutorial3::BasicTutorial3(void) { } //------------------------------------------------------------------------------------- BasicTutorial3::~BasicTutorial3(void) { } //1 begin void BasicTutorial3::destroyScene(void) { //part2 3 begin OGRE_DELETE mTerrainGroup; OGRE_DELETE mTerrainGlobals; //part2 3 end } void getTerrainImage(bool flipX,bool flipY,Ogre::Image& img) { //5 begin : get Terrain Image img.load("terrain.png",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if(flipX) img.flipAroundY(); if(flipY) img.flipAroundX(); //5 end } void BasicTutorial3::defineTerrain(long x,long y) { //4 begin : define terrain Ogre::String filename = mTerrainGroup->generateFilename(x,y); if(Ogre::ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup->getResourceGroup(),filename)) { mTerrainGroup->defineTerrain(x,y); } else { Ogre::Image img; getTerrainImage(x%2!=0,y%2!=0,img); mTerrainGroup->defineTerrain(x,y,&img); mTerrainImported=true; } //4 end } void BasicTutorial3::initBlendMaps(Ogre::Terrain* terrain) { //6 begin:init Blend Maps Ogre::TerrainLayerBlendMap* blendMap0 = terrain->getLayerBlendMap(1); Ogre::TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(2); Ogre::Real minHeight0=70; Ogre::Real fadeDist0=40; Ogre::Real minHeight1=70; Ogre::Real fadeDist1=15; float* pBlend0=blendMap0->getBlendPointer(); float* pBlend1=blendMap1->getBlendPointer(); for(Ogre::uint16 y=0;y<terrain->getLayerBlendMapSize();++y) { for(Ogre::uint16 x=0;x<terrain->getLayerBlendMapSize();++x) { Ogre::Real tx,ty; blendMap0->convertImageToTerrainSpace(x,y,&tx,&ty); Ogre::Real height = terrain->getHeightAtTerrainPosition(tx,ty); Ogre::Real val=(height-minHeight0)/fadeDist0; val=Ogre::Math::Clamp(val,(Ogre::Real)0,(Ogre::Real)1); *pBlend0++=val; val = (height-minHeight1)/fadeDist1; val=Ogre::Math::Clamp(val,(Ogre::Real)0,(Ogre::Real)1); *pBlend1++=val; } } blendMap0->dirty(); blendMap1->dirty(); blendMap0->update(); blendMap1->update(); //6 end } void BasicTutorial3::configureTerrainDefaults(Ogre::Light* light) { //3 begin : configure Terrain Defaults mTerrainGlobals->setMaxPixelError(8); //MaxPixelError decides how precise our terrain is going to be. A lower number will mean a more accurate terrain, at the cost of performance mTerrainGlobals->setCompositeMapDistance(3000);//CompositeMapDistance decides how far the Ogre terrain will render the lightmapped terrain. mTerrainGlobals->setLightMapDirection(light->getDerivedDirection()); mTerrainGlobals->setCompositeMapAmbient(mSceneMgr->getAmbientLight()); mTerrainGlobals->setCompositeMapDiffuse(light->getDiffuseColour()); Ogre::Terrain::ImportData& defaultimp=mTerrainGroup->getDefaultImportSettings(); defaultimp.terrainSize=513; defaultimp.worldSize=12000.0f; defaultimp.inputScale=600; defaultimp.minBatchSize=33; defaultimp.maxBatchSize=65; defaultimp.layerList.resize(3); defaultimp.layerList[0].worldSize=100; //'worldSize' decides how big each splat of textures is going to be. A smaller value will increase the resolution of the rendered texture layer. defaultimp.layerList[0].textureNames.push_back("dirt_grayrocky_diffusespecular.dds"); defaultimp.layerList[0].textureNames.push_back("dirt_grayrocky_normalheight.dds"); defaultimp.layerList[1].worldSize=30; defaultimp.layerList[1].textureNames.push_back("grass_green-01_diffusespecular.dds"); defaultimp.layerList[1].textureNames.push_back("greass_green-01_normalheight.dds"); defaultimp.layerList[2].worldSize=200; defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_diffusespecular.dds"); defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_normalheight.dds"); /* The default material generator takes two textures per layer: diffuse_specular - diffuse texture with a specular map in the alpha channel normal_height - normal map with a height map in the alpha channel */ //3 end } void BasicTutorial3::createScene(void) { //2 begin :First, let's modify our Camera object for our terrain. mCamera->setPosition(Ogre::Vector3(1683,50,2116)); mCamera->lookAt(Ogre::Vector3(1685,50,2116)); mCamera->setNearClipDistance(0.1); mCamera->setFarClipDistance(50000); if(mRoot->getRenderSystem()->getCapabilities()->hasCapability(Ogre::RSC_INFINITE_FAR_PLANE)) { mCamera->setFarClipDistance(0);//enable infinite far clip distance if we can } Ogre::Vector3 lightdir(0.55f,-0.3,0.75f); lightdir.normalise(); Ogre::Light* light=mSceneMgr->createLight("tstLight"); light->setType(Ogre::Light::LT_DIRECTIONAL); light->setDirection(lightdir); light->setDiffuseColour(Ogre::ColourValue::White); light->setSpecularColour(Ogre::ColourValue(0.4f,0.4f,0.4f)); mTerrainGlobals=OGRE_NEW Ogre::TerrainGlobalOptions(); //we create a new set of global terrain options, using the TerrainGlobalOptions class. This is an options class //that just stores default options for all terrains we will create and provides a few getters and setters. //There are also local options to each TerrainGroup called DefaultImportSettings, mTerrainGroup=OGRE_NEW Ogre::TerrainGroup(mSceneMgr,Ogre::Terrain::ALIGN_X_Z,513,12000.0f); //Then we construct our TerrainGroup object - a helper class to manage a grid of terrains but it does not do any paging //The TerrainGroup class constructor takes our SceneManager instance, Terrain alignment option, terrain size and terrain world size as parameters. mTerrainGroup->setFilenameConvention(Ogre::String("BasicTutorial3Terrain"),Ogre::String("dat")); //Then we tell the TerrainGroup what name we would like it to use when saving our terrain, using the setFilenameConvention function. mTerrainGroup->setOrigin(Ogre::Vector3::ZERO); configureTerrainDefaults(light); for(long x=0;x<=0;++x) for(long y=0;y<=0;++y) defineTerrain(x,y); mTerrainGroup->loadAllTerrains(true); //if we just imported our terrains, we would like our blendmaps to be calculated if(mTerrainImported) { Ogre::TerrainGroup::TerrainIterator ti=mTerrainGroup->getTerrainIterator(); while(ti.hasMoreElements()) { Ogre::Terrain* t=ti.getNext()->instance; initBlendMaps(t); } } mTerrainGroup->freeTemporaryResources();//Now, all there is left to do is clean up after the initial terrain creation //2 end //part3 1 begin:add a Sky //part3 1.1 begin //mSceneMgr->setSkyBox(true,"Examples/SpaceSkyBox"); //第3个参数是天空盒离摄像机的距离,默认为5000 // the fourth parameter sets whether or not the SkyBox is drawn before the rest of the scene or afterwards. // the fourth parameter that controls whether to draw the SkyBox first or not is set to true by default. // If the SkyBox is drawn first, then anything rendered afterwards (like our Terrain) will be drawn on top of it, //thus making the SkyBox always appear in the background //part3 1.1 end //part3 1.2|1.1 begin //mSceneMgr->setSkyDome(true, "Examples/CloudySky", 2, 8); // A giant cube is created around the Camera and rendered onto, but the biggest difference is that the texture is //"projected" onto the SkyBox in a spherical manner. You are still looking at a cube, but it looks as if the texture //is wrapped around the surface of a sphere. The primary drawback to this method is that the bottom of the cube //will be untextured, so you always need to have some type of terrain that hides the base. //you can turn the SkyDome off by calling 'mSceneMgr->setSkyDome(false, "");' //The third parameter is the curvature used for the SkyDome. The API reference suggests using values between 2 and 65; //lower for better distance effect, but higher values for less distortion and a smoother effect. Try setting //the third paramater to 2 and 65 and look at the difference. //The fourth parameter is the number of times the texture is tiled, which you will need to tweak depending on the //size of your texture. Be sure to note that this parameter is a Real value (floating point) and not an integer. //part3 1.2|1.1 end //part3 1.3|1.2 begin // This basic use of a SkyPlane is really only useful when you have high walls (or hills) all around //the viewpoint. // Ogre::Plane plane; // plane.d=1000; // plane.normal=Ogre::Vector3::NEGATIVE_UNIT_Y; // mSceneMgr->setSkyPlane(true,plane,"Examples/SpaceSkyPlane",1500,75); // that the fourth parameter is the size of the SkyPlane //the fifth parameter is how many times to tile the texture //The sixth parameter to the skyplane is the familiar "renderFirst" parameter which we have already covered //in the SkyBox and SkyDome sections. // The seventh parameter allows you to specify the curvature of the SkyPlane, so that we are no longer using //a plane, but a curved surface instead. //We also have to now set the number of x and y segments used to create the SkyPlane (initially the SkyPlane //was one big square, but if we want curvature we need to have the plane made up of smaller squares). //The eighth and ninth parameters to the function are the number of x and y segments, //you can clear the SkyPlane by calling 'mSceneMgr->setSkyPlane(false, Ogre::Plane(), "");' //part3 1.3|1.2 end //part3 1 end //part4 1 begin //Ogre::ColourValue fadeColour(0.9,0.9,0.9); //mWindow->getViewport(0)->setBackgroundColour(fadeColour); //part4 1.1 begin //mSceneMgr->setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 50, 500); //part4 1.1 end //The first parameter to the setFog function is the type of fog (in this case, linear). //The second parameter to setFog is the color of the fog we are using //The third parameter is not used in linear fog. The fourth and fifth parameters specify the range where the fog gets thicker. //part4 1.2 begin //mSceneMgr->setFog(Ogre::FOG_EXP, fadeColour, 0.005); //part4 1.2 end //part4 1.3 begin //mSceneMgr->setFog(Ogre::FOG_EXP2, fadeColour, 0.003); //part4 1.3 end //part4 1 end //part4 2 begin /* Ogre::ColourValue fadeColour(0.9, 0.9, 0.9); mSceneMgr->setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 300, 600); mWindow->getViewport(0)->setBackgroundColour(fadeColour); Ogre::Plane plane; plane.d = 100; plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y; mSceneMgr->setSkyPlane(true, plane, "Examples/CloudySky", 500, 20, true, 0.5, 150, 150);*/ //part4 2 end //part4 3 begin : fog as darkness Ogre::ColourValue fadeColour(0.1, 0.1, 0.1); mWindow->getViewport(0)->setBackgroundColour(fadeColour); mSceneMgr->setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 10, 150); Ogre::Plane plane; plane.d = 10; plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y; mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane", 100, 45, true, 0.5, 150, 150); //part4 3 end } void BasicTutorial3::createFrameListener(void) { //part2 2 begin BaseApplication::createFrameListener(); mInfoLabel=mTrayMgr->createLabel(OgreBites::TL_TOP,"TInfo","",350); //part2 2 end } bool BasicTutorial3::frameRenderingQueued(const Ogre::FrameEvent& evt) { bool ret=BaseApplication::frameRenderingQueued(evt); //part2 1 begin if(mTerrainGroup->isDerivedDataUpdateInProgress()) { mTrayMgr->moveWidgetToTray(mInfoLabel,OgreBites::TL_TOP,0); mInfoLabel->show(); if(mTerrainImported) { mInfoLabel->setCaption("Building terrain,please wait..."); } else { mInfoLabel->setCaption("Updating textures,patience..."); } } else { mTrayMgr->removeWidgetFromTray(mInfoLabel); mInfoLabel->hide(); if(mTerrainImported) { mTerrainGroup->saveAllTerrains(true); mTerrainImported=false; } } //part2 1 end return ret; } //1 end //------------------------------------------------------------------------------------- #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #ifdef __cplusplus extern "C" { #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char *argv[]) #endif { // Create application object BasicTutorial3 app; try { app.go(); } catch( Ogre::Exception& e ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; #endif } return 0; } #ifdef __cplusplus } #endif