• Ogre1.8地形和天空盒的建立(一块地形)


    转自:http://www.cnblogs.com/WindyMax/

    研究Ogre的程序笔记

    编译环境 WIN7 32  VS2008   Ogre的版本 1.8

    Ogre的地形算法是采用Geometry MIPMap的算法,当然贴图也是采用MIPMap的算法,这里有Ogre LOD算法的论文解释:http://www.flipcode.com/articles/article_geomipmaps.pdf

    看到Ogre的Terrain,突然也想自己实现一个地形的打算,不过估计要过一段时间了,现在来说,ClipMap算法应该更适应现在的游戏,具体的内容可以查看http://www.docin.com/p-118698727.html,对于了解现在LOD的地形算法,这是一篇相当不错的论文

    关于Ogre地形的代码解释,网上很多高手都已经给出很全面的解释了,我也就不多说了

    #include <Ogre.h>
    #include <OIS/OIS.h>
    #include <iostream>
    #include <OgreTerrain.h>
    #include <OgreTerrainLayerBlendMap.h>
    #include <OgreTerrainGroup.h>
    
    class MyFrameListener : public Ogre::FrameListener
    {
    private:
    	OIS::InputManager *m_pInputManage;
    	OIS::Keyboard *m_pKeyBoard;
    	OIS::Mouse *m_pMouse;
    	Ogre::Camera *m_pCamera;
    	Ogre::Viewport *m_pViewport;
    	Ogre::Timer m_Time;
    
    	bool m_bWirmline;
    
    	float m_fMovementSpeed;
    
    public:
    	MyFrameListener( Ogre::RenderWindow *pWin, Ogre::Camera *pCamera, Ogre::Viewport *pViewport )
    	{
    		m_pCamera = pCamera;
    		m_fMovementSpeed = 10;
    
    		m_Time.reset();
    
    		m_pViewport = pViewport;
    		m_bWirmline = true;
    
    		OIS::ParamList Params;
    		size_t WindowHandle = 0;
    		std::ostringstream WinHandleString;
    		pWin->getCustomAttribute( "WINDOW", &WindowHandle );
    		WinHandleString<<WindowHandle;
    
    		Params.insert( std::make_pair( "WINDOW", WinHandleString.str() ) );
    
    		m_pInputManage = OIS::InputManager::createInputSystem( Params );
    
    		m_pKeyBoard = static_cast<OIS::Keyboard*>( m_pInputManage->createInputObject( OIS::OISKeyboard, false ) );
    		m_pMouse = static_cast<OIS::Mouse*>( m_pInputManage->createInputObject( OIS::OISMouse, false ) );
    
    	}
    	~MyFrameListener()
    	{
    		m_pInputManage->destroyInputObject( m_pKeyBoard );
    		m_pInputManage->destroyInputObject( m_pMouse );
    		OIS::InputManager::destroyInputSystem( m_pInputManage );
    	}
    
    
    	bool frameStarted( const Ogre::FrameEvent& evt )
    	{
    		m_pKeyBoard->capture();
    		bool bWalk = false;
    		if( m_pKeyBoard->isKeyDown( OIS::KC_ESCAPE ) )
    		{
    			return false;
    		}
    		if( m_pKeyBoard->isKeyDown( OIS::KC_R ) && m_Time.getMilliseconds() > 250 )
    		{
    			m_Time.reset();
    			if( m_bWirmline )
    			{
    				m_pCamera->setPolygonMode( Ogre::PolygonMode::PM_WIREFRAME );
    				m_bWirmline = false;
    			}
    			else
    			{
    				m_pCamera->setPolygonMode( Ogre::PolygonMode::PM_SOLID );
    				m_bWirmline = true;
    			}
    		}
    		Ogre::Vector3 translate( 0, 0, 0 );
    
    		if( m_pKeyBoard->isKeyDown( OIS::KC_W ) )
    		{
    			translate += Ogre::Vector3( 0, 0, -1 );
    		}
    		if( m_pKeyBoard->isKeyDown( OIS::KC_S ) )
    		{
    			translate += Ogre::Vector3( 0, 0, 1 );
    		}
    		if( m_pKeyBoard->isKeyDown( OIS::KC_D ) )
    		{
    			translate += Ogre::Vector3( 1, 0, 0 );
    		}
    		if( m_pKeyBoard->isKeyDown( OIS::KC_A ) )
    		{
    			translate += Ogre::Vector3( -1, 0, 0 );
    		}
    
    		m_pCamera->moveRelative( translate * m_fMovementSpeed * evt.timeSinceLastFrame * m_fMovementSpeed * 8 );
    
    		m_pMouse->capture();
    
    		float fDotX = m_pMouse->getMouseState().X.rel * evt.timeSinceLastFrame * -1;
    		float fDotY = m_pMouse->getMouseState().Y.rel * evt.timeSinceLastFrame * -1;
    
    		m_pCamera->yaw( Ogre::Radian( fDotX ) );
    		m_pCamera->pitch( Ogre::Radian( fDotY ) );
    
    
    		return true;
    	}
    
    	bool frameRenderingQueued( const Ogre::FrameEvent& evt )
    	{
    		return true;
    	}
    
    	bool frameEnded( const Ogre::FrameEvent& evt)
    	{
    		return true;
    	}
    };
    
    class MyApplication
    {
    private:
    	Ogre::Root *m_pRoot;
    	Ogre::SceneManager *m_pSceneManage;
    	MyFrameListener *m_pFrameListener;
    	bool m_bKeepRunning;
    	Ogre::TerrainGlobalOptions *m_pTerrGloOp;
    	Ogre::TerrainGroup *m_pTerrGroup;
    	bool m_bLoadNewMap;
    
    public:
    	MyApplication()
    		: m_pRoot( NULL ),
    		m_pSceneManage( NULL ),
    		m_pFrameListener( NULL ),
    		m_bKeepRunning( true ),
    		m_pTerrGloOp( NULL ),
    		m_bLoadNewMap( false )
    	{
    	}
    
    	~MyApplication()
    	{
    		if( m_pTerrGloOp )
    		{
    			delete m_pTerrGloOp;
    		}
    		if( m_pTerrGroup )
    		{
    			delete m_pTerrGroup;
    		}
    
    		if( m_pRoot )
    		{
    			delete m_pRoot;
    			m_pRoot = NULL;
    		}
    	}
    
    	void RenderOneFrame()
    	{
    		Ogre::WindowEventUtilities::messagePump();
    		m_bKeepRunning = m_pRoot->renderOneFrame();
    	}
    
    	bool KeepRunning()
    	{
    		return m_bKeepRunning;
    	}
    
    	void LoadResources()
    	{
    		Ogre::ConfigFile cf;
    		cf.load( "resources_d.cfg" );
    		Ogre::ConfigFile::SectionIterator SecIter = cf.getSectionIterator();
    		Ogre::String SectionName, DataName, TypeName;
    
    		while( SecIter.hasMoreElements() )
    		{
    			SectionName = SecIter.peekNextKey();
    			Ogre::ConfigFile::SettingsMultiMap *SetMap = SecIter.getNext();
    			Ogre::ConfigFile::SettingsMultiMap::iterator SetIter;
    			for( SetIter = SetMap->begin(); SetIter != SetMap->end(); ++SetIter )
    			{
    				TypeName = SetIter->first;
    				DataName = SetIter->second;
    				Ogre::ResourceGroupManager::getSingleton().addResourceLocation( DataName, TypeName, SectionName );
    			}
    		}
    
    		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
    	}
    
    	int StartUp()
    	{
    		if( !m_pRoot )
    		{
    			m_pRoot = new Ogre::Root( "plugins_d.cfg" );
    			if( !m_pRoot->showConfigDialog() )
    			{
    				return -1;
    			}
    		}
    		Ogre::RenderWindow *pWindow = m_pRoot->initialise( true );
    
    		m_pSceneManage = m_pRoot->createSceneManager( Ogre::ST_GENERIC );
    		Ogre::Camera *pCamera = m_pSceneManage->createCamera( "Camera1" );
    		pCamera->setPosition( 0, 1400, 100 );
    		pCamera->lookAt( 0, 0, 0 );
    		pCamera->setNearClipDistance( 5 );
    
    		Ogre::Viewport *pViewport = pWindow->addViewport( pCamera );
    		pViewport->setBackgroundColour( Ogre::ColourValue( 0, 0, 0, 1 ) );
    		pCamera->setAspectRatio( Ogre::Real( pViewport->getActualWidth() ) / Ogre::Real( pViewport->getActualHeight() ) );
    
    		LoadResources();
    		CreateScene();
    		m_pFrameListener = new MyFrameListener( pWindow, pCamera, pViewport );
    		m_pRoot->addFrameListener( m_pFrameListener );
    		return 0;
    
    	}
    	void ConfigureTerrain( Ogre::Light *pLight )
    	{
    		m_pTerrGloOp = new Ogre::TerrainGlobalOptions();
    		m_pTerrGloOp->setMaxPixelError( 8 );
    		m_pTerrGloOp->setCompositeMapDistance( 3000 );
    		m_pTerrGloOp->setCompositeMapAmbient( m_pSceneManage->getAmbientLight() );
    		m_pTerrGloOp->setLightMapDirection( pLight->getDerivedDirection() );
    		m_pTerrGloOp->setCompositeMapDiffuse( pLight->getDiffuseColour() );
    
    		m_pTerrGroup = new Ogre::TerrainGroup( m_pSceneManage, Ogre::Terrain::ALIGN_X_Z, 513, 12000 );
    		m_pTerrGroup->setFilenameConvention( Ogre::String( "SaveTerrain" ), Ogre::String( "dat" ) );
    		m_pTerrGroup->setOrigin( Ogre::Vector3::ZERO );
    		Ogre::Terrain::ImportData &Imp = m_pTerrGroup->getDefaultImportSettings();
    		Imp.maxBatchSize = 65;  //一个tile中最多包含的顶点数
    		Imp.minBatchSize = 33;  //一个tile中最少包含的顶点数
    		Imp.inputScale = 600;
    
    		Imp.layerList.resize( 3 );
    		Imp.layerList[0].worldSize = 100;
    		Imp.layerList[0].textureNames.push_back( "dirt_grayrocky_diffusespecular.dds" );
    		Imp.layerList[0].textureNames.push_back( "dirt_grayrocky_normalheight.dds" );
    		Imp.layerList[1].worldSize = 30;
    		Imp.layerList[1].textureNames.push_back( "grass_green-01_diffusespecular.dds" );
    		Imp.layerList[1].textureNames.push_back( "grass_green-01_normalheight.dds" );
    		Imp.layerList[2].worldSize = 200;
    		Imp.layerList[2].textureNames.push_back( "growth_weirdfungus-03_diffusespecular.dds" );
    		Imp.layerList[2].textureNames.push_back( "growth_weirdfungus-03_normalheight.dds" );
    	}
    
    	void InitBlend( Ogre::Terrain *pTerrain )
    	{
    		Ogre::TerrainLayerBlendMap *pBlend1 = pTerrain->getLayerBlendMap( 1 );
    		Ogre::TerrainLayerBlendMap *pBlend2 = pTerrain->getLayerBlendMap( 2 );
    		Ogre::Real MinHeight1 = 70;
    		Ogre::Real FadeDist1 = 40;
    		Ogre::Real MinHeight2 = 70;
    		Ogre::Real FadeDist2 = 15;
    		float *pBlend1Point = pBlend1->getBlendPointer();
    		float *pBlend2Point = pBlend2->getBlendPointer();
    		for( Ogre::uint16 y = 0; y < pTerrain->getLayerBlendMapSize(); ++y )
    		{
    			for( Ogre::uint16 x = 0; x <pTerrain->getLayerBlendMapSize(); ++x )
    			{
    				Ogre::Real tx, ty;
    				pBlend1->convertImageToTerrainSpace( x, y, &tx, &ty );
    				Ogre::Real height = pTerrain->getHeightAtTerrainPosition( tx, ty );
    				Ogre::Real val = ( height - MinHeight1 ) / FadeDist1;
    				val = Ogre::Math::Clamp( val, static_cast<Ogre::Real>( 0 ), static_cast<Ogre::Real>( 1 ) );
    				*pBlend1Point++ = val;
    
    				val = ( height - MinHeight2 ) / FadeDist2;
    				val = Ogre::Math::Clamp( val, static_cast<Ogre::Real>( 0 ), static_cast<Ogre::Real>( 1 ) );
    				*pBlend2Point++ = val;
    			}
    		}
    
    		pBlend1->dirty();
    		pBlend2->dirty();
    		pBlend1->update();
    		pBlend2->update();
    	}
    
    	void GetTerrainImage( bool bFlipx, bool bFlipy, Ogre::Image &img )
    	{
    		img.load( "terrain.png", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
    		if( bFlipx )
    		{
    			img.flipAroundY();
    		}
    		if( bFlipy )
    		{
    			img.flipAroundX();
    		}
    	}
    
    	void DefineTerrain( long x, long y )
    	{
    		Ogre::String FileName = m_pTerrGroup->generateFilename( x, y );
    		if( Ogre::ResourceGroupManager::getSingleton().resourceExists( m_pTerrGroup->getResourceGroup(), FileName ) )
    		{
    			m_pTerrGroup->defineTerrain( x, y );
    		}
    		else
    		{
    			Ogre::Image img;
    			GetTerrainImage( x % 2, y % 2, img );
    			m_pTerrGroup->defineTerrain( x, y, &img );
    			m_bLoadNewMap = true;
    		}
    	}
    
    	void CreateScene()
    	{
    
    		Ogre::Light *pLight = m_pSceneManage->createLight( "Light1" );
    		pLight->setType( Ogre::Light::LT_DIRECTIONAL );
    		pLight->setDirection( Ogre::Vector3(0.55, -0.3, 0.75) );
    		pLight->setSpecularColour( Ogre::ColourValue( 0.4f, 0.4f, 0.4f ) );
    		pLight->setDiffuseColour( Ogre::ColourValue::White );
    
    		m_pSceneManage->setAmbientLight( Ogre::ColourValue( 0.2f, 0.2f, 0.2f ) );
    
    		ConfigureTerrain( pLight );
    
    		DefineTerrain( 0, 0 );
    
    		m_pTerrGroup->loadAllTerrains( true );
    
    		Ogre::TerrainGroup::TerrainIterator iter = m_pTerrGroup->getTerrainIterator();
    		while( iter.hasMoreElements() )
    		{
    			Ogre::Terrain *t = iter.getNext()->instance;
    			InitBlend( t );
    		}
    
    		if( m_bLoadNewMap )
    		{
    			//如果要反复修改TerrainGroup的数据,就不必保存地形了
    			m_pTerrGroup->saveAllTerrains( true );  //注意,保存的是地形顶点和TerrainGroup的数据,TerrainGlobalOption的数据不会被保存
    			m_bLoadNewMap =false;
    		}
    
    		m_pTerrGroup->freeTemporaryResources();
    		Ogre::ColourValue FadeColour( 0.9, 0.9, 0.9 );
    		m_pSceneManage->setFog( Ogre::FOG_LINEAR, FadeColour, 0.0f, 15000.0f, 28000.0f );
    		Ogre::Plane plane;
    		plane.d = 1000;
    		plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y;
    		m_pSceneManage->_setSkyPlane( true, plane, "Examples/CloudySky", 500, 20, true, 0.5f, 150, 150 );
    	}
    };
    
    
    int main()
    {
    
    	MyApplication app;
    	app.StartUp();
    	while( app.KeepRunning() )
    	{
    		app.RenderOneFrame();
    	}
    
    	return 0;
    }
    

      

    不过在这里主要讲下Terrain::getLayerBlendMapSize()函数,这个函数返回的是Terrain的mLayerBlendMapSize。一开始没有设置的话,mLayerBlendMapSize默认是1024。也就是说将Blend Layer平铺完这个地形,然后分成1024个“区域”,然后计算高度平铺适合的纹理,混合等。可以通过Ogre::TerrainGlobalOptions::setLayerBlendMapSize( value )函数设置...= =~~一开始困扰了我很久。

    总得来说,Ogre的源码很适合想了解游戏引擎的新手研究,里面的东西不会很高深,各种设计模式也很值得去学习,无论是不是专业的游戏开发人员。待续...

  • 相关阅读:
    css 超出两行省略号,超出一行省略号
    css 去掉i标签默认斜体样式
    Spring 使用单选按钮
    Spring Maven工程引入css,js
    Sping 补充完成修改功能
    Spring 控制器层如何启用验证?
    Spring 控制器层如何调用DAO层
    spring boot工程如何启用 热启动功能
    Spring 视图层如何显示验证消息提示
    Sping POJO中如何添加验证规则和验证消息提示
  • 原文地址:https://www.cnblogs.com/hnfxs/p/3254670.html
Copyright © 2020-2023  润新知