minecraft 加了我的世界1.7.10ic2expP里的Sky是什么地形 我知道是天空 可地形是天空是 这又是什么意思

Minecraft1.*的IC2EXP里的高炉如何增加热量啊_珍藏百科
Minecraft1.*的IC2EXP里的高炉如何增加热量啊
编辑: &&&来源:用户发布&&&发布时间:&&&查看次数:204
Minecraft1.*的IC2EXP里的高炉如何增加热量啊求大神解答
该问题暂无回答。
艺术人文相关
本文相关文章
- 关于我们 - 版权声明-
广告服务 - 友情链接 - 管理登录 -
Copyright &
All Rights Reserved
如有任何侵权、造谣信息请将网页地址和有法律效力的侵权造谣证明或判决书发往QQ:小时内删除。
苏ICP备号-1&【作死君的黑理论课堂】【永久更新】第二点五讲:论某个叫ic2EXP的mod的某个探矿仪用法 | minecraft小组 | 果壳网 科技有意思
28591人加入此小组
= =我又闲的无聊来发帖了这次说的是一些自我探测出的黑理论————————————以下是正片——————————————————————————第一讲——————————————讲到红石和钻石的生成,就要讲到区块这个东西,世界由区块组成,区块是16*256*16的一个柱子型物体而每个区块都由16个16*16*16的小区块构成,每个小区块内部生成是有一定规律的,所以才会有钻石和红石在y16以下生成,金矿在y32以下生成的说法但实际一个区块的大小并不只是那么大,实际它的大小是上达世界顶端y∞下至虚空底端y-∞的,但大多数小区块的作用相同,例如y-64到y-0494的地方会一直扣血,y-0494以下的地方会直接踢出游戏,y256到世界的一个顶端是完全的装饰用品,世界一个顶端再往上也会踢出游戏,y0到y-64是虚空缓冲段,而这几部分都是无方块的,所以不另作讨论(注:0494这个数字摘自minecraft wiki)这次讨论的主题是在y0到y15之间的钻石和红石生成,钻石和红石只在该层的小区块中生成,但生成次数不同,红石生成8次而钻石只生成1次,这也是红石比钻石多的关键所在而一个问题就出来了,为什么钻石在y12这一层附近比较多呢?在地表和地下有很多洞穴,这些洞穴有的只是不深的死路,而有的则是到地下岩浆湖的路,而地下岩浆湖在y10及以下生成,如同水在y62及以下生成一样,如果改动了这个设置,那么一些河流地形就会看起来很奇怪(在1.8里的自定义世界只调整水的生成高度会发现这个问题),例如应该有水的地方没有水一般深洞穴都是结束在岩浆湖这个深度,最深的也超不过y10,如果算上岩浆湖底就是y5,而从y5这层往下就是出现基岩的地方,所以最深处是y5的问题也是这样的,不算岩浆,洞穴结束在y12这一层,很巧钻石也在这层最多。在MC里有一个生成顺序,这导致洞穴内的裸露矿物比石头内的隐藏矿物要多一些,因为洞穴占了矿物的地方,而钻石只在y16以下生成,因此钻石在y11~15这四层生成较多,所以有了挖钻石去y12这个说法(感谢太极图同学的纠正)理论来讲,一个区块生成8块钻石矿,而最多四个区块的钻石矿能生成在一起,所以连续32个钻石矿一定在区块边界另外加十几张后来测试时的图首先是这个区块的地表样子(专门找了一个区块生成错误的来演示,这个区块是白桦树林M地形区块,而边上是海洋区块)y16这一层只能看见一个洞穴y15这里第一次出现了红石y14这一层的红石和上一层是一个矿脉的,图片上方还有两块红石,算做第二次出现y13这一层上方有几块红石,和之前是同一矿脉y12这一层第一次出现了钻石,上方偏左有一块红石,算做第三次y11这一层的钻石和上一层是一起的,同时左方第四次出现了红石,上方偏左那个没有与上一张图的有接触,算做第五次y10这一层的钻石和红石和上面的是同一矿脉y9这一层的红石同上y8这一层没有钻石和红石y7这一层同上y6这一层又一次出现了钻石,同时在左上方有几块红石,记第六次,同时这里开始出现gay岩粒子y5这一层的钻石也是矿脉y4这一层第七次出现红石y3这一层出现部分岩浆y2这一层在图左方出现第八次红石y1这一层只有gay岩,下方是虚空最后统计图:出现一次矿物放一块在墙上可以看出红石的确是生成了八次,但钻石却不同的生成了两次,具体原因未知注:本黑理论课堂所用客户端版本为1.7.2,版本不同所导致的不同请不要来找我————————————————第一章完————————————————第二讲:论坑爹的生物群系的生成方式在第一讲我们提到了区块这个概念,同时也表明了区块出错的样子那么现在来讨论以下地形的问题首先,地形的类型可大致分为沙漠,水,森林,冰原,草原,山脉六种,水按大小可分为沼泽,海洋和河流群系,其中海洋还可以分成浅海和深海;森林按照树木可分为橡树和白桦树混搭林,纯白桦树林,热带雨林,黑森林;草原分为热带草原和平原;山脉一般单独出现但有时和森林一起出现;冰原主要为雪原和冰刺之地;沙漠就没有什么特殊之分。在1.7之前,海洋是世界的十分之七,但1.7之后就颠倒了过来,这也导致蘑菇岛的难寻sex生物群系生成基本没有规律,所以沙漠边上就是雪原的事情也很常见,但主要有几条规律第一是海洋边上必定有沙滩第二是沙漠和平原之中普遍有一条河流穿过在这里要特殊说明一个问题,生物群系是区块的自身性质,与外界变化无关(也就是说你就算累死累活把蘑菇岛所有菌丝全挖光然后种上草那里还是叫蘑菇岛)所以总的来说,生物群系的生成还是要看mojang的源代码= =整体来说生物群系对于一个地区是永远不变的不信可以测试1.8的自定义地形,就算开了那个祝你好运那个自带的也能看出来好的第二讲到此结束好吧这个第二讲就是用来水的= =————————————————第二章完————————————————第二点五讲:论某ic2mod的OD(OV)探测器精确挖钻方法= =没错这次要来一个mod的东西首先呢,写这个第三个主要是因为果壳服十周目是1.7.10,且带上了ic2,AE,铁路,凿子,木匠等几个mod。然后我就发现大家把OD(OV)全都是扔进挖矿机去挖矿= =但是呢,OD和OV有一个精确探钻和绿宝石的能力首先根据第一讲的内容,钻石是每区块一次生成,但会有40次尝试,所以钻石分布就较少了绿宝石则是山脉地形每区块一次生成,尝试具体多少看1.8但钻石一般都是生成1~8个(当然就一个也没什么必要去挖),绿宝石是每次一个所以这就奠定了批量钻石的一个基础。而后OD探测仪的探测范围是以你为中心的13x13的距离,OV具体多少没有实际测量(最近忙着搞UU根本没时间弄个OV出来测试这测试那的)这就是第二个基础。首先,下矿你需要带的有:一把武器(推荐纳米剑),一套装甲(纳米量子都行= =),一个钻石电钻(你要是有时运三的我也不说啥),OD(OV)探矿仪(没有这个你就不用看了),一组食物(严重推荐胡萝卜)之后,一字型挖矿,每向前挖七个单位就探测一下,探测到钻石了,不要急着找,先向后退,找到钻石最初被探测到的位置,然后左右找到13x13的某个角落位置,之后向中间挖就行了具体贴图一会再搞———————————————第二点五章完————————————————PS:我都不知道我在说什么你们信么……PS2:这个仅仅是个人想法切勿当真(实际也有一定真实性= =)PS3:又开一个坑感觉自己萌萌哒~第一章日期:日 06:31:42第二章日期:日 02:04:14第二点五章日期:你等我贴图之后再说
+ 加入我的果篮
有错误关于洞穴表面生成的那个不是机制,而是算法导致的结果。在说算法之前,我们需要了解一个叫“区域”的概念。MC之中区块是指16x16x无穷大的垂直空间,这样的一片地方共用地图载入的内存以及一些其他的信息(比如史莱姆生成)。而区域则是区块的更进一步细分,为16x16x16的空间,着一个大小是用来达成视野载入、矿石生成、生物刷新的(这也就是为什么矿石生成区会是16进制)。而MC中矿石生成算法是“单位区域中生成指定量的矿石矿脉”,这也就是为什么每个区块都肯定能生成一个钻石矿脉的原因。在地图生成的过程中,地形最先生成,随后是大型结构-中型结构-小型结构。其中矿脉是小型结构,生成的顺序排在中型结构的洞穴和岩浆湖以及大型结构的峡谷、地下建筑之后。所以洞穴表面矿石多纯粹是因为洞穴挤占了原本属于矿石生成的位置而已。
引用 的话:有错误 关于洞穴表面生成的那个不是机制,而是算法导致的结果。 在说算法之前,我们需要了解一个叫“区域”的概念。MC之中区块是指16x16x无穷大的垂直空间,这样的一片地方共用地图载入的内存以及一些其他...= =说了是黑理论啊……当然是用来娱乐的啊
引用 的话:有错误 关于洞穴表面生成的那个不是机制,而是算法导致的结果。 在说算法之前,我们需要了解一个叫“区域”的概念。MC之中区块是指16x16x无穷大的垂直空间,这样的一片地方共用地图载入的内存以及一些其他...另外区域这个词我用的是小区块代表= =
..............................................................................................................................................................................
= =精华是闹哪样……
引用 的话:= =精华是闹哪样……用来玩的'来自
= =还是1.8的fill指令好啊
int main(int argc, char** argv) {
//真的太无聊么?
//建个野战PvP服来玩玩吧……
return (EXIT_SUCCESS);}
引用 的话:int main(int argc, char** argv) {
//真的太无聊么?
//建个野战PvP服来玩玩吧……
return (EXIT_SUCCESS);}what mean you say来自
引用 的话:int main(int argc, char** argv) { //真的太无聊么? //建个野战PvP服来玩玩吧…… return (EXIT_SUCCESS);}引用 的话:what mean you sayC++来的
= =怎么着也不能下第二页的说我前两天还更新了的说
(C)2016果壳网&&&&&京ICP备号-2&&&&&【Ogre编程入门与进阶】第八章 地形、天空与雾化效果
在一款完整的3D游戏或是三维动画中,大地和天空都是构建场景时不可缺少的元素,另外,伴随着游戏中的角色形象上变得越来越饱满,越来越细节化,游戏中的地形系统也随着时间的推移变得越来越真实,越来越复杂,我们可以想象一副具有真实感的地形会给玩家带来多大的震撼效果,因此,在游戏引擎中地形系统的重要性就不言而喻了。& & & & 目前,游戏中有很多种方法来制作地形系统,当然,每一种方法都有它的优势和弱项。它可以是你的任务看起来很简单,也可以是你的工作量大的惊人。地形制作的方法多种多样,本节我们会通过相应的示例展示给大家Ogre3D中一种实现地形的方法。当然有时候我们也需要在一望无际的天空中或是在辽阔无垠的大地上增加一点雾气朦胧的感觉,这就需要用到Ogre的雾化效果,通过学习这个章节我们可以知道在Ogre中使用雾化效果是一件很简单的事情。不过,Ogre中使用地形和天空等元素,就不像以前章节中,在场景中添加一个Ninja模型那么简单了。好,下面我们就进入Ogre中地形和天空的世界,看看Ogre中是如何使用这些元素的。8.1 地形& & & & 在开始学习“地形”的概念之前,我们先来了解一下“高度图”的概念。& & & & 高度图是一张简单的2D图片,由黑色、白色和之间的254种渐变灰度所生成,如下图所示:& & & & 这种方法的原理是每一种级别的灰度表示了不同的高度。色彩越亮的地方,地形就越高。& & & & 用高度图来制作地形是比较简单的,而且它可以生成一些最为真实的地形结构。在游戏中,我们通常可以在图形编辑器中,比如Photoshop中来制作高度图。用高度图的方式生产地形的优势是:制作简单,可以方便快速地做出大的变动,比较真实。但是这种方式同样也有它的劣势:很难做出小的修改,为了恢复正常可能会花费相当多的时间等。& & & & Ogre3D过去在地形上的支持很少,过去只是让你导入一个高度图,然后在上面放一层基本纹理和一细节纹理,在1.7版本之后,Ogre在里面单独加入了terrain的模块,在地形的支持上已经非常强大。&笔者注:& & & & 在1.7之前的Ogre版本中,如果我们想要在一个3D场景中创建并使用一个地形,就必须要用到Terrain Scene Manager这个类;但是在Ogre 1.7之后的版本中,我们就可以使用Ogre Terrain System这个类来取代Terrain Scene Manager了,事实上Ogre Terrain System使用起来要方便的多。&&& & & & 下面我们同样使用在前面章节保存的模板代码,通过一个示例程序逐步给大家讲解Ogre中的地形系统。& & & & 第一步,修改createScene函数中的内容如下:void&createScene(){&&&&&mCamera-&setPosition(Ogre::Vector3(16));&&&&&mCamera-&lookAt(Ogre::Vector3(60));&&&&&mCamera-&setNearClipDistance(0.1);&&&&&mCamera-&setFarClipDistance(50000);&&&&&if(mRoot-&getRenderSystem()-&getCapabilities()-&hasCapability(Ogre::RSC_INFINITE_FAR_PLANE))&&&& {&&&&&&&&&mCamera-&setFarClipDistance(0);&&//如果相机距离支持无限大就设置为无线距离&&&& }Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::TFO_ANISOTROPIC);&&&&&Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(7);}& & & & 这里我们修改的相机的位置和方向,调整了相机的远近裁剪距离,这是由于通常情况下,地形会相当的大,我们想要相机能看到很远的距离。最后几行的代码是设置材质的一些属性,这里是设置默认的各向异性值。& & & & 第二步,设置光源。Ogre::Vector3lightdir(0.55, -0.3, 0.75);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.4, 0.4, 0.4));mSceneMgr-&setAmbientLight(Ogre::ColourValue(0.2, 0.2, 0.2));& & & & 这里我们的地形组件使用定向光去计算地形光路图,同时我们增加了一个环境光源,用来平滑整个环境。& & & & 第三步,引入地形相关的头文件,并在VS2008中依次在菜单栏中点击:“项目——属性——配置属性——链接器——输入”,在“附加依赖项”处添加属性页中附加OgreTerrain_d.lib。然后在“项目——属性——配置属性——C/C++——附加包含目录”中添加地形相关的包含目录(你的Ogre根目录)/Components/Terrain/include)。#include&&OgreTerrain.h&#include&&OgreTerrainGroup.h&&& & & & 第四步,为我们的类添加如下几个private类型的类成员变量及成员函数:Ogre::TerrainGlobalOptions*mTerrainGlobals;Ogre::TerrainGroup*mTerrainGroup;bool&mTerrainsImported;&void&defineTerrain(long&x,&long&y);void&initBlendMaps(Ogre::Terrain*terrain);void&configureTerrainDefaults(Ogre::Light*light);& & & & 在构造函数中初始化成员变量,在析构函数中释放它们:Example1(){&&&&&mTerrainGroup&=&NULL;&&&&&mTerrainGlobals&=&NULL;}~Example1(){&&&&&if&(mTerrainGroup)&&&& {&&&&&&&&&OGRE_DELETE&mTerrainGroup;&&&& }&&&&&if&(mTerrainGlobals)&&&& {&&&&&&&&&OGRE_DELETE&mTerrainGlobals;&&&& }&&&&&&&&}& & & & 第五步,我们需要设置TerrainGlobalOptions,这是一个表示地形的总体特性的类,它可以设置地形的一些特征,首先你需要new出来一个,因此继续在createScene函数中添加如下代码:mTerrainGlobals&=&OGRE_NEW&Ogre::TerrainGlobalOptions();& & & & 第六步,我们构造一个TerrainGroup对象,用来帮助管理地形网格,继续添加如下代码。mTerrainGroup&=&OGRE_NEW&Ogre::TerrainGroup(mSceneMgr,Ogre::Terrain::ALIGN_X_Z, 513, 12000.0f);mTerrainGroup-&setFilenameConvention(Ogre::String(&Example1Terrain&),Ogre::String(&dat&));mTerrainGroup-&setOrigin(Ogre::Vector3::ZERO);configureTerrainDefaults(light);& & & & 这里TerrainGroup类的构造函数需要一个SceneManager类的实例,一个地形对齐选项,一个地形大小和一个地形世界大小作为参数。然后我们使用setFilenameConvention函数告诉TerrainGroup当我们想要保存地形的时候的名字前缀和后缀名。接着,我们设置起点的位置。最后一行,我们调用configureTerrainDefaults函数,这个函数的实现代码稍后会实现。第七步,定义地形并加载所有:for&(longx&= 0;x&&= 0; ++x)&&&&&for&(longy&= 0;y&&= 0; ++y)&&&&&&&&&defineTerrain(x,y);// sync load since we want everything in place when we startmTerrainGroup-&loadAllTerrains(true);& & & & 这里由于我们仅仅只有一个地形,我们将仅仅调用defineTerrain函数一次,同样,如果我们有多个地形那么就也可以在这里调用,defineTerrain函数的实现代码稍后我们也会提供。& & & & 第八步,现在,我们仅仅导入我们的地形:if&(mTerrainsImported){&&&&&Ogre::TerrainGroup::TerrainIteratorti&=mTerrainGroup-&getTerrainIterator();&&&&&while(ti.hasMoreElements())&&&& {&&&&&&&&&Ogre::Terrain*t&=ti.getNext()-&instance;&&&&&&&&&initBlendMaps(t);&&&& }}& & & & 第九步,初始地形创建后,我们需要做一些清除操作:mTerrainGroup-&freeTemporaryResources();& & & & 第十步,configureTerrainDefaults函数实现:&&&1&2&3&45&void&Example1 ::configureTerrainDefaults(Ogre::Light*light){// Configure globalmTerrainGlobals-&setMaxPixelError(8);// testing composite mapmTerrainGlobals-&setCompositeMapDistance(3000);// Important to set these so that the terrain knows what to use for derived (non-realtime) datamTerrainGlobals-&setLightMapDirection(light-&getDerivedDirection());mTerrainGlobals-&setCompositeMapAmbient(mSceneMgr-&getAmbientLight());mTerrainGlobals-&setCompositeMapDiffuse(light-&getDiffuseColour());}& & & & 这里,我们知道,TerrainGlobalOptions是一个表示地形的总体特征的类,它可以设置地形的一些特征,这里第1行代码,MaxPixelError决定了我们的地形的精度,这个值越小地形越精确,当然效率就越低。& & & & 在地形的渲染中,Ogre提供了一种组合贴图的渲染,就是在较远的地方使用一种贴图混合简单光影的方式来代替实际的纹理,这有很多应用,如这样可以在较远的地方不使用精细的纹理生成,提高效率;这样可以使用这个特性实现游戏中照亮与黑暗的效果。上面的第2~5行代码就是设置这方面的参数。首先设置在多远处开始使用组合贴图(第2行),然后设置产生组合贴图的光线方向(第3行),其次就是设置组合贴图的光影颜色(第4、5行)。例如上面这些代码中的意思就是在你的摄像机周围3000范围内看到地形,而之外则是我们定义的光影颜色。& & & & 完成了上面这些代码,我们还需要往configureTerrainDefaults函数体中继续添加如下代码:&67891011&12131415161718192021&// Configure default import settings for if we use imported imageOgre::Terrain::ImportData&defaultimp&=mTerrainGroup-&getDefaultImportSettings();defaultimp.terrainSize&= 513;defaultimp.worldSize&= 12000.0f;defaultimp.inputScale&= 600;defaultimp.minBatchSize&= 33;defaultimp.maxBatchSize&= 65;// texturesdefaultimp.layerList.resize(3);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&= 200;defaultimp.layerList[2].textureNames.push_back(&growth_weirdfungus-03_diffusespecular.dds&);defaultimp.layerList[2].textureNames.push_back(&growth_weirdfungus-03_normalheight.dds&);& & & & 这里,我们首先定义了一些ImportData值,我们通过getDefaultImportSettings()得到一个Terrain::ImportData类的实例,用来设置地形的一些具体属性,如,defaultimp.inputScale&= 600;(第9行)这是对导入数据(高度图)的高度值的缩放,这个属性很重要,我们知道高度图上的高度在图像的尺度上的范围是0-1(0为全黑),所以默认下,地形的高度将在0-1范围内,所以要使用这个值来对原始图片的像素值相乘,也就是这个值越大,地势越陡峭。其它还有一些属性的设置,比较简单,如terrainSize指的是地形大小(必须是2^n+1),maxBatchSize指的是最大的批次大小(必须是2^n+1,并且小于等于65),worldSize指的是地形的世界大小等等。& & & & 我们现在使用的新版Ogre的地形的纹理贴附是这样的:它允许地形上有几个纹理层次(数目取决于你的硬件),标记为0层,1层……n层,默认情况下你只能见到第0层,我们可以设置n+1层对之前n层纹理的混合结果的混合方式,如果不混合就只能看到第0层。& & & & 首先你要定义这些层的纹理是什么及纹理的大小。& & & & 上面的第12行代码是设置有几层纹理;第13行是设置该层纹理的空间大小;第14、15行是设置该层纹理的贴图和法向贴图。(注意这里我们之所以可以引用这些纹理图片文件是因为这些文件时Ogre在Media目录下自带的。)& & & & 第十一步,defineTerrain函数实现:void&Example1::defineTerrain(longx,longy){&&&&&Ogre::Stringfilename&=mTerrainGroup-&generateFilename(x,y);&&&&&if(Ogre::ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup-&getResourceGroup(),filename))&&&& {&&&&&&&&&mTerrainGroup-&defineTerrain(x,y);&&&& }&&&&&else&&&& {&&&&&&&&&Ogre::Imageimg;&&&&&&&&&getTerrainImage(x&% 2 != 0,y&% 2 != 0,img);&&&&&&&&&mTerrainGroup-&defineTerrain(x,y, &img);&&&&&&&&&mTerrainsImported&=&true;&&&& }}& & & & 这个函数的内容简单明了,可以看到我们首先是通过TerrainGroup的generateFilename函数生成纹理的名字,然后在我们的资源组中进行检查,看是否已经存在这个地形数据了,如果已经存在了,就不需要再次从一个图片中导入了,如果不存在我们就需要加载图片使用它去生成我们的地形。我们使用mTerrainGroup-&defineTerrain(x,y, &img);这个函数产生一个地形实例,地形组是指一个二维网格的地形群,这个函数是指在地形组这个网格的(x,y)处使用这个高度图产生一个地形实例,在Ogre中每个地形实例都是方形的,所以如果你想产生矩形就需要产生多个地形实例。另外,这里我们看到使用到了一个函数getTerrainImage,下面我们就来实现这个函数。& & & & 第十二步,getTerrainImage函数实现:void&Example1::getTerrainImage(boolflipX,boolflipY,Ogre::Image&img){&&&&&img.load(&terrain.png&,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);&&&&&if&(flipX)&&&&&&&&&img.flipAroundY();&&&&&if&(flipY)&&&&&&&&&img.flipAroundX();}& & & & 这个函数就是加载我们前面在第十一步中提到过的需要加载的图片,这个图片会用来生成对应的地形数据。& & & & 第十三步,initBlendMaps函数的实现:void&Example1::initBlendMaps(Ogre::Terrain*terrain){&&&&&Ogre::TerrainLayerBlendMap*blendMap0&=terrain-&getLayerBlendMap(1);&&&&&Ogre::TerrainLayerBlendMap*blendMap1&=terrain-&getLayerBlendMap(2);&&&&&Ogre::RealminHeight0&= 70;&&&&&Ogre::RealfadeDist0&= 40;&&&&&Ogre::RealminHeight1&= 70;&&&&&Ogre::RealfadeDist1&= 15;&&&&&float*&pBlend0&=&blendMap0-&getBlendPointer();&&&&&float*&pBlend1&=&blendMap1-&getBlendPointer();&&&&&for&(Ogre::uint16y&= 0;y&&terrain-&getLayerBlendMapSize(); ++y)&&&& {&&&&&&&&&for&(Ogre::uint16x&= 0;x&&terrain-&getLayerBlendMapSize(); ++x)&&&&&&&& {&&&&&&&&&&&&&&Ogre::Realtx,ty;&&&&&&&&&&&&&&blendMap0-&convertImageToTerrainSpace(x,y, &tx, &ty);&&&&&&&&&&&&&&Ogre::Realheight&=terrain-&getHeightAtTerrainPosition(tx,ty);&&&&&&&&&&&&&&Ogre::Realval&= (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();}& & & & 在产生了地形实例后,我们需要对地形的纹理层进行我们想要的混合方式,我们可以通过地形组的迭代器访问每一个地形实例,然后把对应的地形实例指针传递给这个函数。混合的原理机制是这样的:对于每一个纹理层,都有一个保存每个像素的alpha混合的值,可以通过Ogre::TerrainLayerBlendMap* blendMap0&=terrain-&getLayerBlendMap(1);这样的方式来获取第1层的这个混合数据,初始情况下都是0,也就是说,默认情况下第1层对第0层的混合是0,那样你就只能看到0层,你可以通过修改这个数据来直接修改混合方式,这就像两张图像做混合,而每张混合图像代表了整个这个地形实例的表面图片,为了得到这个图像的边长,可以使用terrain-&getLayerBlendMapSize();你还可以使用blendMap0-&convertImageToTerrainSpace(x,y, &tx, &ty);来得到混合图像空间上(x,y)的那个像素对应的地形实例空间上的坐标,我们修改了混合值之后,还需要使用blendMap0-&dirty();blendMap0-&update();来更新。& & & & 这就是我们使用的新版的Ogre的地形,虽然看起来操作要复杂的多,但是的确可以实现非常好的地形效果。编译并运行程序,你将会看到最终效果如下所示(注意,由于我们这里定义的地形数据量太大,如果你的电脑性能不是太好,可能要花很长时间才能看到下面的地形效果,所以大家在编译运行的时候请耐心等待一下,稍后我们会介绍到怎样优化这个问题):&& & & & 我们可以看到虽然通过这种方式能显示出很棒的地形效果,但是我们或许会发现,当我们每次运行程序的时候,由于地形的数据量计算,导致每次运行起我们的程序会很缓慢,解决这个问题有很多种方法,这里我们可以提供一种简单的方法,我们可以把地形数据内容保存到我们本地磁盘上,这样下次程序运行的时候就不需要这么大批量的计算了。因此,我们可以采用如下方法:& & & & 在createScene函数中的最后一行代码:mTerrainGroup-&freeTemporaryResources();之前加入下面这一句代码:mTerrainGroup-&saveAllTerrains(true);& & & & 然后编译运行程序,你将会发现第一次运行的时候,显示画面的时间还是很慢,但是当我们程序运行过一次之后,以后在运行的时候速度明显比原来快多了,原因很简单,因为我们把生成的地形数据在程序第一次运行的时候已经保存的本地磁盘上去了,以后程序运行的时候可以直接从本地磁盘读取地形数据。我们可以到media目录下查看一下,有一个名叫Example1Terrain_.dat的数据文件,这就是我们程序第一次运行后生成的地形数据文件。8.2 天空& & & & Ogre提供了三种类型的天空:天空盒,天空穹和天空面,本小节将对这三种类型的天空做详细的介绍。8.2.1天空盒
天空盒实际上是一个立方体,它包含了场景里所有的对象。在这一小节中,我们将会在8.1小节的基础上继续添加代码,来学习Ogre中天空的用法。将下面的代码添加到createScene函数中: mSceneMgr-&setSkyBox(true,&Examples/SpaceSkyBox&,5000,true);& & & & 编译并运行程序,我们可以看到如下效果:代码分析:
skybox函数有4个参数,下面分别介绍这4个参数的作用。& & & & 第一个参数,代表是否启用天空盒。如果我们想要取消天空盒,那么我们只须调用一句代码mSceneMgr-&setSkyBox( false, && ); 即可。& & & &&第二个参数,用来设置天空盒使用的材质脚本。& & & &&第三个参数,用来设定天空盒与摄像机的距离。& & & &&第四个参数,决定了天空盒是在其他对象之前渲染还是其他对象之后渲染。& & & &&下面,我们将第三个参数从默认的5000改为一个很小的值然后看看有什么效果:mSceneMgr-&setSkyBox(true, &Examples/SpaceSkyBox&, 10);&& & 编译并运行后,发现没有任何变化,效果如下图:& & 那么为什么我们修改了代码,却没有在程序结果中看到差异呢?& & 这是因为,第四个参数的默认值是true,也就是说天空盒会最先渲染,场景中其它的物体会渲染到天空盒之前,从而使天空盒看起来像是在背后。&笔者注:
这里有一点希望读者注意,我们不应该让第三个参数的取值小于摄像机的近裁剪距离,否则天空盒将不能显示。&
事实上,天空盒并不应该最先被渲染,因为如果最先渲染天空盒,那么其他的也将全部被渲染。但如果我们最后渲染天空盒,那么OGRE为了提高程序的运行效率,只会渲染天空盒中的可见部分。因此,我们可以来试一下最后渲染天空盒:mSceneMgr-&setSkyBox(true, &Examples/SpaceSkyBox&, 5000, false);
编译并运行,效果仍没有变化。
但是,实际上跟之前的结果是有那么一点不同之处的,那就是天空盒里不可见的部分没有被渲染。
下面,我们再试试如下的代码:mSceneMgr-&setSkyBox(true, &Examples/SpaceSkyBox&, 100, false);& & & & 当把天空盒设置的很近时,场景管理器中的一部分物体会被裁减掉。笔者注:
在程序中使用天空盒的时候一定要注意,setSkyBox函数的最后一个参数的默认值是true,也就是代表天空盒最先被渲染。为了不像上面的代码那样出现不正常的显示效果,就必须仔细使用这几个参数。例如:当我们选择最后渲染天空盒的时候,程序的运行速度会提高一些,但必须注意设置好参数,以免它遮住了场景中的其他物体。在实际应用中,我们大多会在程序中将第三个参数和第四个参数全部设置为默认值,以免出现错误的结果。&8.2.2 天空穹& & & &&天空穹和天空盒非常相似,在Ogre中创建一个天空穹要使用的函数是setSkyDome函数。天空穹也会创建一个包含了场景中所有对象的巨型立方体,但是它与天空盒最大的区别是:天空穹的贴图是用球体的方法投影到立方体上的。所以,天空穹其实还是一个立方体,只不过它的贴图看上去像贴到了一个球体上一样。& & & &&这种类型的天空的一个最大的缺陷就是:立方体的下面没有任何贴图(通常显示为黑色),所有必须要有一个其他的东西来将下面的黑洞遮住,以便让我们的场景看上去不是一个bug。& & & &&下面我们用一个实例来看看天空穹的效果。将8.2.1小节中添加的代码注释起来,然后在createScene函数中添加下面代码:mSceneMgr-&setSkyDome(true,&Examples/CloudySky&, 5, 8);& & & &&编译并运行程序,你将看到如下的效果:& & & &&为了让读者更好的理解天空穹的概念,我们把8.1小节中的关于地形的代码都暂时注释起来,让我们的场景中只存在一个“天空穹”。& & & &&之后,我们按下键盘上的R键,将其切换到网格状态,效果如下,可见,天空穹仍然是一个立方体,图为立方体的一角。& & & &&再次按R键,切换回来,滑动鼠标将视角移动到天空穹的底部,可以看到一片立方体状的黑色区域,同样可以验证天空穹仍然是立方体,这也是上文中提到的天空穹的一个缺陷,即立方体的下面没有任何贴图,所有必须要有一个其他的东西来将下面遮住。具体的效果图如下:代码分析:mSceneMgr-&setSkyDome(true,&Examples/CloudySky&, 5, 8);中的参数。天空穹的前两个参数和天空盒一样,这里就不再赘述了。& & & &&第三个参数是天空穹的弯曲程度。OGRE的API中建议使用2到65之间的数值,我们可以在程序中修改这个参数的值来看看不同取值下的不同效果。& & & &&将第三个参数改为为2,效果如下:& & & &&将第三个参数改为65,效果如下:& & & &&第四个参数用来设置贴图重复的次数,这个参数需要根据贴图的实际大小来设置,以便让贴图可以适应我们的程序。&笔者注:& & & &&读者应该特别注意一下这个参数的类型:这个参数是Real类型而不是整形。&& & & &&第五个参数和第六个参数分别用来设置天空穹的距离和渲染顺序,与天空盒的第三、四个参数类似,这里也就不再赘述了。&8.2.3 天空面& & & &&天空面与前两种类型的天空(天空盒和天空穹)有很大的区别。天空面使用一个平面来替代立方体,也就是说,我们仅仅把纹理映射到一个简单的面上,而不再映射到一个立方体上。下面我们通过实例来介绍天空面:& & & &&第一步:将8.2.2小节中createScene里所有天空穹的代码注释起来。& & & &&第二步:我们创建一个平面,设置平面是朝下的。需要注意的是,与前两个函数不同,setSkyPlane函数没有距离参数,不过,我们可以在Plane的d变量中设置它的距离。我们通过下面的代码来构建一个平面,将d变量的距离设置为1200:Ogre::Plane plane;plane.d = 1200;plane.normal&=&Ogre::Vector3::NEGATIVE_UNIT_Y;&&&&&& && & & &&第三步:利用setSkyPlane函数来创建一个天空面。定义好了平面之后,接下来我们就可以创建天空面了,具体代码如下:& & & &&mSceneMgr-&setSkyPlane(true,&plane,&Examples/SpaceSkyPlane&,1500,80);& & & &&setSkyPlane函数的前几个参数与之前的几种天空的类型类似,这里就不再一一详述了。第四个参数用来设定天空面的大小,在这里我们将其设置成为了的大小。& & & &&第五个参数是他重复的次数,这里我们设置的重复次数为80.&& & & &&下面编译并运行程序,效果如下:代码分析:& & mSceneMgr-&setSkyPlane(true, plane, &Examples/SpaceSkyPlane&, 1500, 55, true, 1.5f, 160, 160);& & 我们就这一行代码来看一下setSkyPlane这个函数每个参数的作用。& & & &&1. 第一个参数用来设置是否启用天空面。如果我们想要取消天空盒,那么我们只须调用一句代码mSceneMgr-&setSkyPlane( false, && ); 即可。& & & &&2. 第三个参数用来设置天空盒使用的材质脚本。& & & &&3. 第四个参数用来设置天空面的大小。& & & &&4. 第五个参数用来设置天空面重复的次数。& & & &&5. 第六个参数用来设置天空面的渲染顺序,它决定了天空面是最先被渲染还是最后被渲染。参数为true表明天空面最先被渲染,参数为false表明天空面最后被渲染。& & & &&6. 第七个参数用来设置天空面的弯曲度,这样一来就可以实现将平面弯曲成弧形的效果了。同时我们还需要设置x和y的线段数量,这是因为天空面是一个巨大的正方形,但是假如我们想将它弯曲那么就要将它切分成许多小正方形,以便我们可以实现弯曲的效果。& & & &&7. 第八个和第九个参数是x和y的线段数量了。因为天空面是一个大的正方形,若要将其弯曲就必须将其变成许多小的正方形,所以要设置x和y方向上的线段数量。& & & &&说明:我们创建的天空面有两个问题,第一,使用的纹理分辨率太低,平铺后效果不好。最主要的问题在于如果你朝边上看,将看到天空面的结束,使用天空面的基本观点是当你的景点周围都是高山或丘陵时使用天空面是有用的。& & & &&setSkyPlane的第六个参数类似天空盒和天空穹中的定义'是否先绘制'的参数,第七个参数允许你定义天空面的弯曲度,所以我们可以不再使用一个平面,而是有曲率的表面。现在,我们还必须设置x和y的段数(初始时天空面是一个大的正方形,但是如果我们想平面有曲率的话需要用许多小的正方形组成平 面),第八和第九个参数用来设置x和y的段数,代码如下:mSceneMgr-&setSkyPlane(true,plane,&Examples/SpaceSkyPlane&,1500,50,true,1.5f,150,150);& & & &&替换为这句代码后,我们再次编译运行,应该会发现现在的效果要比刚才的好多了:&笔者注:& & & &&这个天空面有一个缺陷,就是天空面的结尾处过度是十分不柔和的,如图所示:& & & &&天空面的这个缺陷使得天空面的使用在很多地方有了一定的局限性。不过天空面对显卡的要求比天空盒和天空穹对显卡的要求要低,可以大幅度的提升程序的运行效率。&& & & &&在本节中,我们介绍了三种不同的表现天空的方式,至于到底该使用哪种,完全取决于你的应用。如你要看你周围的一切,甚至是y的负方向,那么你只能选择天空盒;如果你有地形,或者类似地板之类的,那么使用天空穹看起来更真实;如果你看不到地平线,那么使用天空面看起来效果更好并且只需要一点点GPU代价。8.3 雾化效果& & & &&雾,在Ogre里是非常特别的。在场景中设置雾化效果,并不是我们通常想象的那样在某个地方创建“雾”的实体。实际上,雾只是一个滤镜。当场景中没有任何物体时,我们是看不见雾的。事实上,我们在窗口中看到的,只是视口(viewport)的背景色,因此,要想使雾的效果更加逼真,我们必须将视口的背景色设成“雾”的颜色。& & & &&在Ogre中,雾有两种,线性的雾和指数的雾。线性雾随着参数的变化“线性的”增加浓度,而指数雾随着参数的变化“指数的”增加浓度。下面我们通过实例向大家介绍这两种雾。8.3.1 线性雾& & & &&在开始增加代码之前,我们先将8.2小节中用到的代码全部注释起来。另外,在调用setWorldGeometry函数前首先要设置视口的背景颜色。我们可以用createViewport方法来设置,继续在createScene函数体中增加如下代码:Ogre::ColourValuefadeColour(0.9, 0.9, 0.9);mWindow-&getViewport(0)-&setBackgroundColour(fadeColour);mSceneMgr-&setFog(Ogre::FOG_LINEAR,fadeColour, 0.0, 50, 500);& & & &&编译并运行,你将会看到如下效果:代码分析:& & & &&上面的第三行代码中,第一个参数用来设置雾的类型,类型有两种:线性的或是指数的。第二个参数用来设置雾的颜色。第三个参数在线性雾里面是不用设置的。第四个和第五个参数是设置雾慢慢变浓的范围。这个慢慢变浓的范围如何理解呢?例如我们这里设置的变浓范围是60到550,这就意味着在摄像机的0到60的单位内是没有雾的,从60到550的单位内雾慢慢线性变浓,在550单位以外就全是雾了。&8.3.2 指数雾另一种雾的类型是指数雾。在这里,我们要设置雾的密度(第四个和第五个参数不需要设置)。添加代码如下:mSceneMgr-&setFog(Ogre::FOG_EXP, fadeColour, 0.005);编译运行这个程序,效果如下:&笔者注:& & & &&在这里,如果我们使用的是DirectX渲染器,会发现场景完全在雾的外面。改善这种现象的办法是在调用setWorldGeometry函数之前,先调用setFog函数。&& & & &&另外,还有一种更厉害的指数雾函数,这种指数雾,离摄像机越远它的浓度越强。我们只需要用FOG_EXP2替换上述代码中的FOG_EXP即可实现这种雾的效果,代码如下:mSceneMgr-&setFog(Ogre::FOG_EXP2, fadeColour, 0.004);&8.3.3 雾与天空面的配合使用& & & &&如果我们在程序中,想将雾的效果与天空盒或天空穹一起配合使用的话,就会遇到一些新的问题。因为天空盒或天空穹是立方体,而雾是球形的,我们接下来就通过一个例子来看一下这个问题究竟是如何产生的。& & & &&将createScene函数里的内容全部注释起来,添加如下的代码:Ogre::ColourValue fadeColour(0.8, 0.8, 0.8);mSceneMgr-&setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 11, 1400);mWindow-&getViewport(0)-&setBackgroundColour(fadeColour);mSceneMgr-&setSkyDome(true, &Examples/CloudySky&, 6, 8, 600);&& & & &&编译并运行程序,可以查看效果。蓝色的天空材质与底部的白色部分有一个明显的白色边缘,这看起来非常的不自然,如果这出现在场景中必然会是一个失败之举。& & & &&为了改善这种效果,我们可以选择使用天空面,而不是使用天空盒或是天空穹,因为天空面与其他两种类型的天空不同,它本质上是一个平面。& & & &&在createScene函数里用以下代码替换之前的代码:Ogre::ColourValue fadeColour(0.8, 0.8, 0.8);mSceneMgr-&setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 10, 1300);mWindow-&getViewport(0)-&setBackgroundColour(fadeColour);Ogre::Plane plane;plane.d = 110;plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y;mSceneMgr-&setSkyPlane(true, plane, &Examples/CloudySky&, 550, 25, true, 0.4, 160, 160);&编译并运行,可以查看效果。效果是不是比使用天空盒或天空穹的时候好多了,边界的过度柔和了很多,而且没有那种生硬的长方形的变色边界了,这让我们的场景看上去更加的柔美、舒服。&笔者注:& & & &&“暗雾”特效。在Ogre中有一个“暗雾”的特效。所谓“暗雾”,就是将雾的颜色设置的非常暗,而不把雾设置成明亮的颜色。我们同样通过代码来看看“暗雾”的效果。将createScene函数中的代码替换为如下:Ogre::ColourValue fadeColour(0.1, 0.1, 0.1);mWindow-&getViewport(0)-&setBackgroundColour(fadeColour);mSceneMgr-&setFog(Ogre::FOG_LINEAR, fadeColour, 0.0, 12, 160);Ogre::Plane plane;plane.d = 10;plane.normal = Ogre::Vector3::NEGATIVE_UNIT_Y;mSceneMgr-&setSkyPlane(true, plane, &Examples/SpaceSkyPlane&, 100, 45, true, 0.6, 160, 160);& & & &&编译运行程序,可以查看效果:& & & &&“暗雾”这种效果在实际中有什么应用呢?事实上,“暗雾”本身在使用方法上跟其他类型的雾是一样的,因为“暗雾”也是雾的一种,不过这种通过改变雾的颜色来达到不同效果的方法值得读者学习,在程序设计中,往往就会用到这种类似的小技巧来使我们的游戏或动画产生各式各样的不同特效,读者朋友应该在平时的学习和实践中不断积累这种小技巧,这样在设计大型游戏或动画的时候,灵感和方法就信手拈来了。PS:很久以前就打算把学习Ogre中遇到的知识分享给大家(虽然只是一些皮毛),但是说来惭愧,一直很懒,直到最近才抽出点时间写一些自己的理解(Ogre入门级的东西),所以难免会有很多不足之处,分享是一种快乐,同时也希望和大家多多交流!(由于在Word中写好的东西发布到CSDN页面需要重新排版(特别是有很多图片时),所以以后更新进度可能会比较慢,同时每章节发布的时间可能不一样(比如说我首选发布的是第二章,其实第一章就是介绍下Ogre的前世今生神马的,相信读者早就了解过~~~),但是我会尽量做到不影响大家阅读,还望大家谅解。)&上述内容很多引用了网上现有的翻译或者内容,在此一并谢过(个人感觉自己有些地方写得或者翻译的不好),还望见谅,转载请注明此项!上文来自:http://blog.csdn.net/zhanghua1816/article/details/
最新教程周点击榜
微信扫一扫

我要回帖

更多关于 我的世界ic2exp 的文章

 

随机推荐