需要用到的外部图片资源:

在ogre调用时需要多用到的几个外部dll:

OgreTerrain_d.dll

需要添加头文件

#include "Ogre\Ogre.h"
#include "Ogre\OgreFileSystemLayer.h"
#include "Ogre\OgreTerrain.h"
#include "Ogre\OgreTerrainGroup.h"
#include "Ogre\OgreTerrainQuadTreeNode.h"
#include "Ogre\OgreTerrainMaterialGeneratorA.h"
#include "Ogre\OgreTerrainPaging.h"

定义类初始化需要的结构体

struct CrisTerrainInitStruct
{
CrisTerrainInitStruct():m_scenemanager(NULL),fMaxHoriz(1000),fMinHoriz(0),sMapFilename(""),sElevationFilename(""),fMapSize(TERRAIN_WORLD_SIZE)
{
fInputScale = fMaxHoriz - fMinHoriz;
}
SceneManager* m_scenemanager;
String sMapFilename; //地图卫星图片
String sElevationFilename;//高程图
Real fMinHoriz;//最低点
Real fMaxHoriz;//最高点
Real fMapSize;//地形边长
Real fInputScale; //地形高低差 对比像素的0~1 .可以不需要设置
//位置放在000点,
};

类的外部接口

void Init(CrisTerrainInitStruct* sInitData);

实现的一些重要步骤:

第一步  创建地形全局配置 TerrainGlobalOptions

mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
//TerrainGlobalOptions是一个类,定义了地形块的一些全局变量和默认值,需要的话我们可以改变他的变量参数,我们后面再做改变。

 第二步  创建地形分组Ogre::TerrainGroup

//实例化一个TerrainGroup对象

mTerrainGroup = OGRE_NEW TerrainGroup(mSceneMgr, Terrain::ALIGN_X_Z, TERRAIN_SIZE, m_sInitData->fMapSize);

第三步  配置地图块参数 configureTerrainDefaults

configureTerrainDefaults();

第四步  创建地形分块

//defineTerrain方法首先要指定该块地形在地形分组中的索引位置,然后第三个参数必须指定高度数据,用灰度图创建山地地形
for (long x = TERRAIN_PAGE_MIN_X; x <= TERRAIN_PAGE_MAX_X; ++x)
for (long y = TERRAIN_PAGE_MIN_Y; y <= TERRAIN_PAGE_MAX_Y; ++y)
defineTerrain(x, y, blankTerrain);

下面是我的代码:

头文件:

#pragma once
#define DebugTerrain
#include "Ogre\Ogre.h"
#include "Ogre\OgreFileSystemLayer.h"
#include "CrisConfig\CrisConfig.h"
#include "Ogre\OgreTerrain.h"
#include "Ogre\OgreTerrainGroup.h"
#include "Ogre\OgreTerrainQuadTreeNode.h"
#include "Ogre\OgreTerrainMaterialGeneratorA.h"
#include "Ogre\OgreTerrainPaging.h" //分页多少
#define TERRAIN_PAGE_MIN_X 0
#define TERRAIN_PAGE_MIN_Y 0
#define TERRAIN_PAGE_MAX_X 0
#define TERRAIN_PAGE_MAX_Y 0 #define TERRAIN_FILE_PREFIX String("testTerrain")
#define TERRAIN_FILE_SUFFIX String("dat")
#define TERRAIN_WORLD_SIZE 1200.0f
#define TERRAIN_SIZE 513 using namespace Ogre; struct CrisTerrainInitStruct
{
CrisTerrainInitStruct():m_scenemanager(NULL),fMaxHoriz(1000),fMinHoriz(0),sMapFilename(""),sElevationFilename(""),fMapSize(TERRAIN_WORLD_SIZE)
{
fInputScale = fMaxHoriz - fMinHoriz;
}
SceneManager* m_scenemanager;
String sMapFilename; //地图卫星图片
String sElevationFilename;//高程图
Real fMinHoriz;//最低点
Real fMaxHoriz;//最高点
Real fMapSize;//地形边长
Real fInputScale; //地形高低差 对比像素的0~1 .可以不需要设置
//位置放在000点,
}; class CrisTerrain
{
public:
CrisTerrain();
~CrisTerrain();
void Init(CrisTerrainInitStruct* sInitData); //void setTerrainImage(const Ogre::String& szCfgFilename = "terrain_texture.jpg"); protected:
TerrainGlobalOptions* mTerrainGlobals;
TerrainGroup* mTerrainGroup;
TerrainPaging* mTerrainPaging;
PageManager* mPageManager; void testOption();//为了小样例测试加载的,在大工程中可以直接不用
private:
CrisTerrainInitStruct* m_sInitData;
void loadConfigFile(const Ogre::String& szCfgFilename = ""); Ogre::String m_szConfigFileName;
CCrisConfigManager m_hConfigMgr; bool mFly;
Real mFallVelocity;
Real mBrushSizeTerrainSpace; Real mHeightUpdateCountDown;
Real mHeightUpdateRate;
Vector3 mTerrainPos;
bool mTerrainsImported; SceneManager* mSceneMgr; /** @brief 实例化地形 */
void setupContent();
/** @brief 实例化地形参数 */
void configureTerrainDefaults();
void initBlendMaps(Terrain* terrain);
void defineTerrain(long x, long y, bool flat = false);
void getTerrainImage(bool flipX, bool flipY, Image& img); };

  实现文件:

#include "Terrain.h"

CrisTerrain::CrisTerrain(): mTerrainGroup(0)
, mTerrainPaging(0)
, mPageManager(0)
, mFallVelocity(0)
, mBrushSizeTerrainSpace(0.02)
, mHeightUpdateCountDown(0)
, mTerrainPos(0,0,0)
, mTerrainsImported(false)
{ } CrisTerrain::~CrisTerrain()
{ } void CrisTerrain::Init(CrisTerrainInitStruct* sInitData)
{
mSceneMgr = sInitData->m_scenemanager;
m_sInitData = sInitData;
setupContent();
//loadConfigFile("terrain.cfg");
} void CrisTerrain::loadConfigFile(const String& szFilename)
{
if(!szFilename.empty())
m_szConfigFileName = szFilename;
else
return; //m_hConfigMgr.LoadFromResourceSystem(m_szConfigFileName);
//String worldTexture = m_hConfigMgr.GetValueString("Ter", "WorldTexture", "testter.jpg");
//OutputDebugString(worldTexture.c_str()); } //void CrisTerrain::setTerrainImage(const Ogre::String& szCfgFilename)
//{
// Terrain::ImportData& defaultimp = mTerrainGroup->getDefaultImportSettings();
// defaultimp.terrainSize = TERRAIN_SIZE;//不太了解,调试中,这个值越小,地图边缘锯齿现象越严重,太小的话,运行起来程序会跑死、出错
// defaultimp.worldSize = m_sInitData->fMapSize;//假设为a,那么地图大小为 a x a
// defaultimp.inputScale = 60;//决定地图最大落差(高度),即位图中白色和黑色部分的高度差
// defaultimp.minBatchSize = 33;
// defaultimp.maxBatchSize = 65;
// // textures
// defaultimp.layerList.resize(3);//这里设置了3层纹理,DDS为一种高级的纹理模式,DirectDrawSurface,觉得难以理解的话
////可以理解为一种特殊的.jpg图片模式,但是用DDS质材的话可以接收并显示地形阴影,用JPG就显示不出来,而且据我调试观
////察发现,第一个.dds质材是用来显示纹理图形,第二个.dds才是用来接收和显示阴影的
//
// defaultimp.layerList[0].worldSize = 1;//这个值关系到此贴图的细致程度,太大的话图片被拉伸得很大,看起来模糊
// defaultimp.layerList[0].textureNames.push_back(szCfgFilename);
// defaultimp.layerList[0].textureNames.push_back(szCfgFilename);
// defaultimp.layerList[1].worldSize = 1;
// defaultimp.layerList[1].textureNames.push_back(szCfgFilename);
// defaultimp.layerList[1].textureNames.push_back(szCfgFilename);
// defaultimp.layerList[2].worldSize = 2;
// defaultimp.layerList[2].textureNames.push_back(szCfgFilename);
// defaultimp.layerList[2].textureNames.push_back(szCfgFilename);
//
// mTerrainGroup->loadAllTerrains(true);
//
// if (mTerrainsImported)
// {
// TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator();
// while(ti.hasMoreElements())
// {
// Terrain* t = ti.getNext()->instance;
// initBlendMaps(t);
// }
// }
//
// mTerrainGroup->freeTemporaryResources();
//} void CrisTerrain::testOption()
{
//mEditMarker = mSceneMgr->createEntity("editMarker", "sphere.mesh");
//mEditNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
//mEditNode->attachObject(mEditMarker);
//mEditNode->setScale(0.05, 0.05, 0.05); Ogre::FileSystemLayer* mFSLayer = OGRE_NEW_T(Ogre::FileSystemLayer, Ogre::MEMCATEGORY_GENERAL)(OGRE_VERSION_NAME);
ResourceGroupManager::getSingleton().createResourceGroup("Terrain");
ResourceGroupManager::getSingleton().addResourceLocation(mFSLayer->getWritablePath(""), "FileSystem", "Terrain", false, false); MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
MaterialManager::getSingleton().setDefaultAnisotropy(7); //mSceneMgr->setFog(FOG_LINEAR, ColourValue(0.7, 0.7, 0.8), 0, 1000, 2500); LogManager::getSingleton().setLogDetail(LL_BOREME); mSceneMgr->setAmbientLight(ColourValue(0.6, 0.6, 0.6)); //// create a few entities on the terrain
//Entity* e = mSceneMgr->createEntity("tudorhouse.mesh");
//Vector3 entPos(mTerrainPos.x + 2043, 0, mTerrainPos.z + 1715);
//Quaternion rot;
//entPos.y = mTerrainGroup->getHeightAtWorldPosition(entPos) + 65.5 + mTerrainPos.y;
//rot.FromAngleAxis(Degree(Math::RangeRandom(-180, 180)), Vector3::UNIT_Y);
//SceneNode* sn = mSceneMgr->getRootSceneNode()->createChildSceneNode(entPos, rot);
//sn->setScale(Vector3(0.12, 0.12, 0.12));
//sn->attachObject(e); //mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
} void CrisTerrain::setupContent()
{
bool blankTerrain = false;
//blankTerrain = true; mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
//TerrainGlobalOptions是一个类,定义了地形块的一些全局变量和默认值,需要的话我们可以改变他的变量参数,我们后面再做改变。 #ifdef DebugTerrain
testOption();
#endif //创建地形分组Ogre::TerrainGroup
/*实例化一个TerrainGroup对象
参数1:为他指定场管理器、
参数2:地形的平铺方向,平铺方向一般采用ALIGN_X_Z,也就是采用Y作为高度
参数3:unit16 TERRAINSIZE=2~n+1,比如512+1=513,不符合公式的可能会导致地图显示异常,表示“The
size of each terrain down one edge in vertices (2^n+1)”楼主只能理解意思,不能完全正确
表达其中的专有名词,实际调试中,这个参数影响地图边缘的锯齿度,越小锯齿越明显,取值太小
的话,运行会错误;
参数4:Real TERRAINWORLDSIZE,地图大小,表示地图正方形的边长)
*/
mTerrainGroup = OGRE_NEW TerrainGroup(mSceneMgr, Terrain::ALIGN_X_Z, TERRAIN_SIZE, m_sInitData->fMapSize);
//定义命名前缀
mTerrainGroup->setFilenameConvention(TERRAIN_FILE_PREFIX, TERRAIN_FILE_SUFFIX);
//设置了该地形组的起始位置,在以后创建的地形块中均采用此位置作为相对位置
mTerrainGroup->setOrigin(mTerrainPos);
mTerrainGroup->setResourceGroup("Terrain"); //配置地图块参数 configureTerrainDefaults
configureTerrainDefaults(); for (long x = TERRAIN_PAGE_MIN_X; x <= TERRAIN_PAGE_MAX_X; ++x)
for (long y = TERRAIN_PAGE_MIN_Y; y <= TERRAIN_PAGE_MAX_Y; ++y)
defineTerrain(x, y, blankTerrain); // 开始前加载好
mTerrainGroup->loadAllTerrains(true); if (mTerrainsImported)
{
TerrainGroup::TerrainIterator ti = mTerrainGroup->getTerrainIterator();
while(ti.hasMoreElements())
{
Terrain* t = ti.getNext()->instance;
initBlendMaps(t);
}
} mTerrainGroup->freeTemporaryResources();
} void CrisTerrain::getTerrainImage(bool flipX, bool flipY, Image& img)
{
img.load(m_sInitData->sElevationFilename, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
if (flipX)
img.flipAroundY();
if (flipY)
img.flipAroundX(); } void CrisTerrain::defineTerrain(long x, long y, bool flat)
{
// if a file is available, use it
// if not, generate file from import // Usually in a real project you'll know whether the compact terrain data is
// available or not; I'm doing it this way to save distribution size if (flat)
{
mTerrainGroup->defineTerrain(x, y, 0.0f);
}
else
{
String filename = mTerrainGroup->generateFilename(x, y);
if (ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup->getResourceGroup(), filename))
{
mTerrainGroup->defineTerrain(x, y);
}
else
{
Image img;
getTerrainImage(x % 2 != 0, y % 2 != 0, img);
mTerrainGroup->defineTerrain(x, y, &img);
mTerrainsImported = true;
} }
} void CrisTerrain::configureTerrainDefaults()
{
// Configure global
mTerrainGlobals->setMaxPixelError(8);
// testing composite map
mTerrainGlobals->setCompositeMapDistance(3000);//距离镜头超过3000部分使用地图合成(CompositeMap)模式表现
//mTerrainGlobals->setUseRayBoxDistanceCalculation(true);
//mTerrainGlobals->getDefaultMaterialGenerator()->setDebugLevel(1);
//mTerrainGlobals->setLightMapSize(256); // Configure default import settings for if we use imported image
Terrain::ImportData& defaultimp = mTerrainGroup->getDefaultImportSettings();
defaultimp.terrainSize = TERRAIN_SIZE;//不太了解,调试中,这个值越小,地图边缘锯齿现象越严重,太小的话,运行起来程序会跑死、出错
defaultimp.worldSize = m_sInitData->fMapSize;//假设为a,那么地图大小为 a x a
defaultimp.inputScale = m_sInitData->fInputScale;//决定地图最大落差(高度),即位图中白色和黑色部分的高度差
defaultimp.minBatchSize = 33;
defaultimp.maxBatchSize = 65;
// textures
defaultimp.layerList.resize(3);//这里设置了3层纹理,DDS为一种高级的纹理模式,DirectDrawSurface,觉得难以理解的话
//可以理解为一种特殊的.jpg图片模式,但是用DDS质材的话可以接收并显示地形阴影,用JPG就显示不出来,而且据我调试观
//察发现,第一个.dds质材是用来显示纹理图形,第二个.dds才是用来接收和显示阴影的 defaultimp.layerList[0].worldSize = m_sInitData->fMapSize;//这个值关系到此贴图的细致程度,太大的话图片被拉伸得很大,看起来模糊
defaultimp.layerList[0].textureNames.push_back(m_sInitData->sMapFilename);
defaultimp.layerList[0].textureNames.push_back(m_sInitData->sMapFilename);
defaultimp.layerList[1].worldSize = m_sInitData->fMapSize;
defaultimp.layerList[1].textureNames.push_back("white2.dds");
defaultimp.layerList[1].textureNames.push_back("white2.dds");
defaultimp.layerList[2].worldSize = m_sInitData->fMapSize;
defaultimp.layerList[2].textureNames.push_back("white2.dds");
defaultimp.layerList[2].textureNames.push_back("white2.dds"); //defaultimp.layerList[0].worldSize = 100;//这个值关系到此贴图的细致程度,太大的话图片被拉伸得很大,看起来模糊
//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("grass_green-01_normalheight.dds");
//defaultimp.layerList[2].worldSize = 100;
//defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_diffusespecular.dds");
//defaultimp.layerList[2].textureNames.push_back("growth_weirdfungus-03_normalheight.dds");
} void CrisTerrain::initBlendMaps(Terrain* terrain)
{
TerrainLayerBlendMap* blendMap0 = terrain->getLayerBlendMap(1);
TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(2);
Real minHeight0 = 70;
Real fadeDist0 = 40;
Real minHeight1 = 70;
Real fadeDist1 = 15;
float* pBlend1 = blendMap1->getBlendPointer();
for (Ogre::uint16 y = 0; y < terrain->getLayerBlendMapSize(); ++y)
{
for (Ogre::uint16 x = 0; x < terrain->getLayerBlendMapSize(); ++x)
{
Real tx, ty; blendMap0->convertImageToTerrainSpace(x, y, &tx, &ty);
Real height = terrain->getHeightAtTerrainPosition(tx, ty);
Real val = (height - minHeight0) / fadeDist0;
Math::Clamp(val, (Real)0, (Real)1); val = (height - minHeight1) / fadeDist1;
val = Math::Clamp(val, (Real)0, (Real)1);
*pBlend1++ = val; }
}
blendMap0->dirty();
blendMap1->dirty();
//blendMap0->loadImage("blendmap1.png", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
blendMap0->update();
blendMap1->update(); // set up a colour map
/*
if (!terrain->getGlobalColourMapEnabled())
{
terrain->setGlobalColourMapEnabled(true);
Image colourMap;
colourMap.load("testcolourmap.jpg", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
terrain->getGlobalColourMap()->loadImage(colourMap);
}
*/ }

  

[Ogre][地形][原创]基于OgreTerrain的地形实现的更多相关文章

  1. [转]的C#实现三维数字地形漫游(基于Irrlicht)

    马省轩  任丽娜 摘  要:本文采用C#编程语言,利用Irrlicht三维图形引擎实现了三维数字地形的漫游.为三维数字地形显示提供了较易实现的解决方案. 关键词:C#   高度图 Irrlicht引擎 ...

  2. Ogre 编辑器二(用Ogre的地形组件加载天龙八部地形)

    主界面如上文设计完成后,场景刚开始添加了是Ogre例子里的,发现场景里实物太少,于是想到直接把天龙的场景拿下来,天龙网上有源码,参考了下,把天龙的地形用Ogre的地形组件完成了下,如下是效果图: 因为 ...

  3. WorldWind源码剖析系列:地形瓦片类TerrainTile和地形瓦片服务类TerrainTileService

    地形瓦片类TerrainTile 用来抽象封装用户漫游中所请求的地形瓦片数据类型. 地形瓦片服务类TerrainTileService提供了从BIL(Binary Interleaved by Lin ...

  4. (原创)基于FPGA的调光流水灯(Verilog,CPLD/FPGA)

    1.Abstract     前几天做了一个呼吸灯,觉得确实挺有意思的:可惜的是只有一个灯管亮,板子上有四个灯,要是能让这些灯有序地亮起来,那应该更有趣味了!跟传统的一样,逻辑上做成一个流水灯的样式, ...

  5. (原创)基于MCU的频率可调,占空比可调的PWM实现(MCU,MCS-51/MSP430)

    1.Abstract     做这个是受朋友之邀,用在控制电机转动的方面.他刚好在一家好的单位实习,手头工作比较多,无暇分身,所以找我帮忙做个模型.要求很明晰,PWM的频率在0~1KHz范围内,占空比 ...

  6. [原创]基于VueJs的前后端分离框架搭建之完全攻略

    首先请原谅本文标题取的有点大,但并非为了哗众取宠.本文取这个标题主要有3个原因,这也是写作本文的初衷: (1)目前国内几乎搜索不到全面讲解如何搭建前后端分离框架的文章,讲前后端分离框架思想的就更少了, ...

  7. [原创]基于SpringAOP开发的方法调用链分析框架

    新人熟悉项目必备工具!基于SpringAOP开发的一款方法调用链分析插件,简单到只需要一个注解,异步非阻塞,完美嵌入Spring Cloud.Dubbo项目!再也不用担心搞不懂项目! 很多新人进入一家 ...

  8. [原创]基于Zynq PS与PL之间寄存器映射 Standalone & Linux 例程

    基于Zynq PS与PL之间寄存器映射 Standalone & Linux 例程 待添加完善中

  9. [原创]基于Zynq AXI-Bram Standalone & Linux 例程

    基于Zynq AXI-Bram Standalone & Linux 例程 待添加完善中

随机推荐

  1. mybatis-spring

    现成的中文文档 首先,项目依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifa ...

  2. arping 通知网关刷新IP

     arping -c 2 -I em1 -s 192.168.110.12  192.168.110.1  

  3. Process启动.exe,当.exe内部抛出异常时,总会弹出一个错误提示框,阻止Process进入结束

    public class TaskProcess { [DllImport("kernel32.dll", SetLastError = true)] public static ...

  4. GTA项目 三, 使用 bootstrap table展示界面,使得data和UI分离

    /** bootstrap-table - v1.5.0 - 2014-12-12* https://github.com/wenzhixin/bootstrap-table* Copyright ( ...

  5. Cocoapods注意点

    1 安装和升级$ sudo gem install cocoapods $ pod setup 2 更换为taobao的源 $ gem sources -r https://rubygems.org/ ...

  6. Java相对路径读取文件

    不管你是新手还是老鸟,在程序中读取资源文件总会遇到一些找不到文件的问题,这与Java底层的实现有关,不能算bug,只要方法得当,问题还是可以解决的. 项目的文件夹结构: repathtest ├─sr ...

  7. 求树的重心(POJ1655)

    题意:给出一颗n(n<=2000)个结点的树,删除其中的一个结点,会形成一棵树,或者多棵树,定义删除任意一个结点的平衡度为最大的那棵树的结点个数,问删除哪个结点后,可以让平衡度最小,即求树的重心 ...

  8. How to wipe silicon to CPU 如何给CPU正确涂抹硅脂

    随 着计算机性能的提升,CPU的功耗也在不断的增大,虽然现在由于改进了工艺使得在功耗方面得到了一定的缓解,但由于近年来显卡性能的不断增强,也开始走上 了CPU功耗性能成正比的老路,功耗依然还是一个值得 ...

  9. 20145207 《Java程序设计》第4周学习总结

    前言 又到了大家最喜欢的前言时间,哈哈哈.我这个人啊,就是比较爱闲聊.正式在学校呆的第一天时间就在这里敲代码,自己都觉得自己伟大.不过好无聊呀....这周的内容说实话讲我还是挺感兴趣的,因为书上的例子 ...

  10. [原创]java WEB学习笔记70:Struts2 学习之路-- 输入验证,声明式验证,声明是验证原理

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...