关于ogre的地形学习笔记
OGRE地形听说是很好弄,弄好了也不是很好用,其他的我也不是很懂,冒然前行碰了一鼻子灰,碰了两天,在前辈们的基础之上明白了一点,写给初级的!
ogre地形的建设主要几步搞定就行。
当然,如果你看不见是因为摄像机忘记放置了,那么这篇不适合你。
其他不说,咱们单说地形。(唉,公司都年会去了,我还这地形呢)()))
擦干眼泪开始,谁叫咱连个实习生都不算呢。
第一步,说一个类 TerrainGlobalOptions 字面意思:地形全局属性
让我来说说我对ogre地形的组建方法:其实就是一个小方块*一个小方块,所以一个大的地形有n*n个小的地形组成。那么在建立时我们就关心小的就行了,但是,有很多属性小方块们是一样的,所以,如果还要在建立他们时加上,就有点浪费资源了,所以,用一个TerrainGlobalOptions类来管理,地形的统一属性不失为一个好方法。所以,这就是TerrainGlobalOptions 的作用。
1 mTerrainGlobals=OGRE_NEW TerrainGlobalOptions();
关于对象的属性设置,稍后再说。
第二步,再说一个类 TerrainGroup 地形分块属性 顾名思义,用来设置分块的属性的
1 mTerrainGroup=OGRE_NEW TerrainGroup(mSceneMgr,Terrain::ALIGN_X_Z,513,12000); //第三个属性是用来设置模糊变化的最小块的
2
3 mTerrainGroup->setFilenameConvention(Ogre::String("MyTerrain"),Ogre::String("dat"));
4
5 mTerrainGroup->setOrigin(Vector3::ZERO);
6
7 //OGRE_NEW ====new
第二句:设置这块地形的名字 叫“MyTerrain.dat”他是给保存并且后面函数用的。
第三句:设置原点,以后的分组都以这个点为相对点。
第三步:配置地形块属性
1 configTerrainDefaults(light);
这里我们新建了一个函数 并将我们的方向光作为参数传进去。在这个函数里面完成对地形的配置,包括全局的,和分组的。
1 mTerrainGlobals->setMaxPixelError(8);
2
3 mTerrainGlobals->setCompositeMapDistance(3000);
4
5 mTerrainGlobals->setLightMapDirection(light->getDirection());
6
7 mTerrainGlobals->setCompositeMapAmbient(mSceneMgr->getAmbientLight());
8
9 mTerrainGlobals->setCompositeMapDiffuse(light->getDiffuseColour());
全局函数配置 英文解释:MaxPixelError decides how precise(精确) our terrain is going to be. A lower number will mean a more accurate(精确) terrain, at the cost of performance (because of more vertices(顶点))
指定当决定哪个细节层次被使用时的最大允许误差。设置过高会导致地形撕裂,过低则会影响性能。.
第二行 :到底多远才用composite map,不是靠LOD决定的,而是靠这个参数mTerrainGlobals->setCompositeMapDistance(3000);
三四五行:分别是指地形环境光,方向光之类的属性(用到了传进来的环境光)
1
2
3 Terrain::ImportData &defaultimp=mTerrainGroup->getDefaultImportSettings();
4
5 defaultimp.terrainSize=513;
6
7 defaultimp.worldSize=12000;
8
9 defaultimp.inputScale=300;
10
11 defaultimp.minBatchSize=33;
12
13 defaultimp.maxBatchSize=65;
14
15
设置属性第二条,分组属性设置 分块的属性 例如inputScale 的大小 就是设置对于灰度图的拉伸比例。(注:这里讲一下我对这的理解,因为地形的高低是由生成它的灰度图的样子决定的,但是,灰度图的是8位的,所以只能表示相对值 2^8=256 表示的高度范围太小,如果采用十六位的话那就是 2^16=64k 珠穆朗玛峰高度8848m 已经足够了,但是为啥不用一个字节的要用一个字的呢,占用内存少啊!!!所以八位居多啊,这样,就需要伸缩比例了(inputScale)!知道了吧)
1 defaultimp.layerList.resize(3); // //重新塑造list大小申请空间来放置要贴图
2
3 defaultimp.layerList[0].worldSize=100;
4
5 defaultimp.layerList[0].textureNames.push_back("xiaost_DIFFUSE.jpg");
6
7 defaultimp.layerList[0].textureNames.push_back("xiaost_NORMAL.jpg");
8
9 defaultimp.layerList[1].worldSize=30;
10
11 defaultimp.layerList[1].textureNames.push_back("xiaost_DIFFUSE.jpg");
12
13 defaultimp.layerList[1].textureNames.push_back("xiaost_NORMAL.jpg");
14
15 defaultimp.layerList[2].worldSize=200;
16
17 defaultimp.layerList[2].textureNames.push_back("shitou_DIFFUSE.jpg");
18
19 defaultimp.layerList[2].textureNames.push_back("shitou_NORMAL.jpg");
以上添加了三层纹理用来构建地形的地表。其中worldSize是用来表示,你想用多大的一张图来贴花!!呵呵
第四步:创建地形分块
下面就开始了defineTerrain(0,0,false);
第五步:混合纹理
实现的效果(别人做的图片):
所以,为了实现混合区域的效果,做以下几个步骤;
1 Ogre::TerrainLayerBlendMap * blendMap0=terrain->getLayerBlendMap(1);
2
3 //以下四个常量是用来计算出随着地形的高低混合的因子的大小的
4
5 Real minHeight0=100;
6
7 Real fadeDist0=40;
8
9 Real minHeight1=100;
10
11 Real fadeDist1=20;
12
13
14
15 float * pBlend1=blendMap0->getBlendPointer();//这个是获取纹理地图的起始位置
16
17 for (Ogre::uint16 y=0;y<terrain->getLayerBlendMapSize();++y)
18
19 {
20
21 for (Ogre::uint16 x=0;x<terrain->getLayerBlendMapSize();++x)
22
23 {
24
25 Ogre::Real tx,ty;
26
27 blendMap0->convertImageToTerrainSpace(x,y,&tx,&ty); //将纹理坐标转化为地形坐标blendMap1->convertImageToTerrainSpace(x, y, &tx, &ty)来得到混合图像空间上(x,y)的那个像素对应的地形实例空间上的坐标。
28
29 Ogre::Real height=terrain->getHeightAtTerrainPosition(tx,ty);//取得在想(x,y)坐标的地形高度
30
31
32
33 Ogre::Real val=(height-minHeight0)/fadeDist0;
34
35 val=Ogre::Math::Clamp(val,(Ogre::Real)0,(Ogre::Real)1);
36
37
38
39 *pBlend1++=val;//设置混合因/***
40
41 /************************************************************************/
42
43 /* 经常会遇到内存读取错误在这总结一下:
44
45 原因一:内存过界
46
47 原因二:对象未初始化
48
49 解决办法调试,加断点看看对象是否有值*/
50
51 /************************************************************************/
52
53 //val=(height-minHeight1)/fadeDist1;
54
55 //val=Ogre::Math::Clamp(val,(Ogre::Real)0,(Ogre::Real)1);
56
57
58
59
60
61 }
62
63
64
65 }
66
67 blendMap0->dirty();
68
69 blendMap0->update();
注释写的挺清楚了。主要就是获得图层,设置混合系数,刷新图层之类的工作。
我实现的效果如图:(自己画一个灰度图,找了两个鹅卵石,我觉得加上水更好看,下次加上水效果)
混合效果