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的源码很适合想了解游戏引擎的新手研究,里面的东西不会很高深,各种设计模式也很值得去学习,无论是不是专业的游戏开发人员。待续...
Ogre1.8地形和天空盒的建立(一块地形)的更多相关文章
- Unity3D自定义地形的笔刷,刷出别样地形
是不是很简单呀,大家可以发挥想象刷出特殊的地形,小鸡呀,或者其他的logo之类(顶视图看上去效果很棒)的地形. 最后把我找的笔刷上传,Gizmos 注意: 如果文件夹及图片导入后,地形系统的笔刷无 ...
- [转]的C#实现三维数字地形漫游(基于Irrlicht)
马省轩 任丽娜 摘 要:本文采用C#编程语言,利用Irrlicht三维图形引擎实现了三维数字地形的漫游.为三维数字地形显示提供了较易实现的解决方案. 关键词:C# 高度图 Irrlicht引擎 ...
- [Ogre][地形]OgreTerrain分析以及使用
Ogre 1.7.2中的地形教程 ○读者可以对照着Ogre1.7.2中的terrain.h源码进行阅读加深理解,蓝色部分均为源码 ○去除了一些具体场景比如添加mesh,设置setAmbientLigh ...
- 转:修改ETM,用Ogre实现《天龙八部》地形与部分场景详解
本文主要讲的是<天龙八部>游戏的地形和一部分场景的具体实现,使用C++, Ogre1.6,我摸索了段时间,可能方法用的并不是最好的,但好歹实现了.文章可能讲得有点罗嗦,很多简单的东西都讲了 ...
- 关于Unity中地形的创建
地形创建 Raw图片格式是Unity可以导出的图片格式 Unity很强大,可以直接使用psd文件 地形创建实例 1.创建Unity工程和文件目录1:创建一个地形Terrain: GameObject- ...
- Unity3D游戏开发从零单排(三) - 极速创建狂拽酷炫的游戏地形
提要 在Unity工作流程内,地形是一个必不可少的重要元素.不论是游戏或虚拟现实都会使用到各种类型的地形效果,在这个教学中我们须要了解到地形的制作基本概念与,当中对于Unity的地形操作部分须要大量的 ...
- 使用着色器在WebGL3D场景中呈现行星表面地形
实验目的:按照一定规律生成类地行星地表地形区块,并用合理的方式将地形块显示出来 涉及知识:Babylon.js引擎应用.着色器编程.正态分布.数据处理.canvas像素操作 github地址:http ...
- Cesium原理篇:3最长的一帧之地形(1)
前面我们从宏观上分析了Cesium的整体调度以及网格方面的内容,通过前两篇,读者应该可以比较清楚的明白一个Tile是怎么来的吧(如果还不明白全是我的错).接下来,在前两篇的基础上,我们着重讨论一下地形 ...
- Cesium原理篇:3最长的一帧之地形(3:STK)
有了之前高度图的基础,再介绍STK的地形相对轻松一些.STK的地形是TIN三角网的,基于特征值,坦白说,相比STK而言,高度图属于淘汰技术,但高度图对数据的要求相对简单,而且支持实时构建网格,STK具 ...
随机推荐
- 【hdu2196】Computer
hdu 2196 computer 题意 给你一棵树,边有权值. 对于每一个点,求其与其距离最远的点的距离. 分析 思路1:树的直径 利用直径的性质进行求解,网上资料很多,这里不赘述. #includ ...
- 【C#】获取当前系统桌面、我的照片、我的文档等路径
获取当前系统桌面.我的照片.我的文档等路径 using System; using System.Collections.Generic; using System.ComponentModel; ...
- VBA对象模型(2)
Excel对象模型简介 在介绍Excel对象模型之前,让我们先来看一个简单的例子.大多数工厂都是按这样的结构进行设置的:最上层为工厂总部,第二层次分为各个车间,在车间下面又分各班组.就这样组织在一起, ...
- 函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
在dllimport中加入CallingConvention参数就行了,[DllImport(PCAP_DLL, CharSet = CharSet.Auto, CallingConvention = ...
- easyui 中重复加载两次url
之前一直在使用easyui中,忽视了官网上的小细节,类似于datagrid.combobox 等组件在使用的时候,它的数据加载方式分为两种: 官网中: ①在html中,比如: <table id ...
- weblogic部署ssh2应用出现异常
一般在domains\your_Domain\bin\startWebLogic.cmd 中找到set CLASSPATH=%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSPATH ...
- ASP.NET-遇到的错误汇总
错误:“未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序.” 在win7 64未上,读取Excel中的数据时报的错误, 解决方法:在生成"配置管理器中" ...
- mysql linux备份shell
#!/bin/bash# export and backup the activity.sql mysqldump -uname -password activity --skip-lock-ta ...
- FloatingActionButton增强版,一个按钮跳出多个按钮--第三方开源--FloatingActionButton
FloatingActionButton项目在github上的主页:https://github.com/futuresimple/android-floating-action-button F ...
- 常用的正则表达式(例如:匹配中文、匹配html)(转载)
匹配中文字符的正则表达式: [u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串 ...