zoukankan      html  css  js  c++  java
  • OGRE菜鸟笔记地形学习

    首先认识terrain.cfg中的几个参数,它们是理解ogre地形的基础。

    # The main world texture (if you wish theterrain manager to create a material for you)

    WorldTexture=terrain_texture.jpg

    # The detail texture (if you wish theterrain manager to create a material for you)

    DetailTexture=terrain_detail.jpg

    一张纹理图伸展开来覆盖整个儿地形。纹理图一般都是棕、绿、白或灰间杂的颜色,对应土地、草地、雪地或者岩石地形。因为地形纹理一般比要覆盖的地形小得多,故而当你距离很近地观察它时,地形一般会看起来比较模糊。为了帮助改善这一点,在近距离观察时,就要用到细节纹理,与地形纹理混合使用。细节纹理并不像地形纹理那样伸展得那么大,仅仅是减弱了近距离观察时产生的地形模糊现象。例子中的terrain_texture.jpg以及 terrain_detail.jpg这两个纹理可供实验使用。

    一个地形被分割为一小块儿一小块儿的像地砖一样的地形方块儿,由场景管理器按这些地形块儿的拓扑结构和观察者的距离依照不同的细节层次进行显示。

    最后,用一个指定了地形维度的世界坐标空间,将完整的地形投影到一个三维空间中。

    Terrain.cfg文件分析

    坐标系问题

        Terrain Scene Manager把纹理图的左上角作为世界原点(0,0,0),以从左到右为x正方向,从上到下为z正方向,从屏幕里到屏幕外为y正方向,符合右手坐标系。

    Basic Configuration Parameters

    1.WorldTexture: 指定地形纹理的名称。

    2.DetailTexture: 指定细节纹理的名称。

    3.DetailTile: 这个指定细节纹理在每个地形小块中重复次数,也就是说,如果这个值是n,细节纹理将在每个地形小块的n*n格中被显示。如果这个值设置过低,地形在近看时会模糊,反之则会在放眼观察时看起来有反复模式(露馅了,^_^) 。

    4.PageSource: 指定高度图数据的来源,默认为Heightmap.

    5.Heightmap.image: 指定高度图的名称。尺寸必须是方形,而且要符合2^n+1, 高度图越大,地形细节就越高,但是程序消耗的的资源也越多(包括程序启动时间)。

    6.PageSize: 地形将会有PageSize * PageSize那么大。如上所述,必须要符合2^n+1 (如65,129,257,513,1025)。

    对应terrain demo中的TERRAIN_SIZE,即一整块地形顶点数目,terrain damo中的TERRAIN_WORLD_SIZE是整个地形大小,TERRAIN_WORLD_SIZE/TERRAIN即缩放值,每个顶点之间距离的缩放值。计算代码见void Terrain::updateBaseScale()。

    7.TileSize: 地形小块有 TileSize * TileSize大小。这个数必须小于PageSize。这个数必须要符合2^n+1须要符合2^n+1。设的过小会严重影响性能,太大的话又会在场景的某些部分导致不必要的高细节。

    估计这个地形小块是用来做LOD的和可见性剔除的,问题是纵横各多少Tile是在哪里计算的?估计是由场景管理器来管理计算的并应用于Lod的。如果是通过TERRAIN_SIZE/TileSize这样简单的计算,为什么terrain的demo中纵横是各6个?

    8.MaxPixelError: 指定当决定哪个细节层次被使用时的最大允许误差。设置过高会导致地形撕裂,过低则会影响性能。

    9.PageWorldX, PageWorldZ: 设定地形在世界坐标系中的范围,地形越大,细节越低,地形使用的顶点数基于高度图,不是世界大小,你可以缩放地形到你想要的任意大小。

    10.MaxHeight: 在世界坐标系中地形的最大高度。高度图中的0..255 缩放到世界坐标系中的 0..MaxHeight。

    11.MaxMipMapLevel: 指定渲染地形使用的细节层次的数目。地形的远处和平坦处会以低细节渲染。

    Advanced Configuration Parameters

    有些高度图保存为raw格式,下列参数描述raw格式。

    12.Heightmap.raw.size: 指定高度图的尺寸,要求同上。

    13.Heightmap.raw.bpp: 指定每象素字节数,1=8 bits, 2=16 bits。

    14.Heightmap.flip: 如果设置为true,则翻转高度图。

    minBatch和maxBatch用于计算lod levels和树深度:
    lodLevels = log2(terrainSize - 1) - log2(minBatch - 1) + 1;
    treeDepth = log2( (terrainSize - 1) / (maxBatch - 1) ) + 1;

    树节点的vertexData不是每层都创建,而是隔几层创建一个大的,下几层共用,indexData是每层都要创建的,并且它只有两种大小:minBatch和maxBatch。另外叶子节点有lodlevel。
    这个要讲起来内容比较多,还是看源码(注释比较清晰)和chunked lod算法吧。

    场景管理器种类:

    ST_GENERIC,   普通场景
    ST_EXTERIOR_CLOSE, 室外封闭场景
    ST_EXTERIOR_FAR,  室外无限场景
    ST_INTERIOR   室内场景

    那么这些类型是怎么对应到相应的dll插件呢?各地形插件在代码中都会定义自身的类型:如e:\SDK\Ogre1.71\PlugIns\BSPSceneManager\src\OgreBspSceneManager.cpp

    mMetaData.sceneTypeMask = ST_INTERIOR;

    在SceneManager* SceneManagerEnumerator::createSceneManager中会根据需要创建的scenemanager找到对应的管理器插件并使用。

    待研究问题:

    1,定义了提醒材质层后OGRE是怎样让这些层的效果叠加的,代码在哪里?

                  Terrain::ImportData&defaultimp = mTerrainGroup->getDefaultImportSettings();

                  defaultimp.terrainSize= TERRAIN_SIZE;

                  defaultimp.worldSize= TERRAIN_WORLD_SIZE;

                  defaultimp.inputScale= 600; // 地形高度的缩放值

                  defaultimp.minBatchSize= 33;

                  defaultimp.maxBatchSize= 65;

                  //textures

                  defaultimp.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");

    留意mLayerUVMultiplier[i] = mWorldSize/ inst.worldSize;

    网上的资料:

    一张纹理,贴在地形上,你必须指定他的纹理可见度。比如我的一个地形,我需要在左边显示A纹理,右边显示B纹理,那也就是说A纹理的左边设置为可见,B纹理的右边设置为可见。那如何做到这一点呢?

    首先看一小段代码

    view plaincopy to clipboardprint?

       1.Ogre::TerrainLayerBlendMap* blendMap = terrain->getLayerBlendMap(l); 

       2.float* data = blendMap->getBlendPointer(); 

       3.for (int h = 0;h<100;h++) 

       4.{ 

      5.     for (int0;w<100;w++) 

      6.     { 

      7.         data[dataIndex] = 0.0f; 

      8.     } 

       9.} 

      10.blendMap->dirty(); 

      11.blendMap->update(); 

    Ogre::TerrainLayerBlendMap* blendMap =terrain->getLayerBlendMap(l); float* data = blendMap->getBlendPointer();for (int h = 0;h<100;h++) { for (int 0;w<100;w++) { data[dataIndex] = 0.0f; } } blendMap->dirty();blendMap->update();

    看开始两句,获取了Terrain的第X层纹理,然后获取了纹理系数data,然后我们把高100宽100的位置的混合系数设置为0,即不可见,混合系数取值为0~1之间,系数越大纹理越清晰,故0就是一点都不可见。

    混合的原理机制是这样的,对于每一个纹理层,都有一个保存每个像素的alpha混合值的值,可以通过Ogre::TerrainLayerBlendMap* blendMap1 = terrain->getLayerBlendMap(1)来获取第1层的这个混合数据,初始情况下都是0,也就是说默认情况下第1层对第0层的混合是0,那样你就只能看到0层,你可以通过修改这个数据来直接修改混合方式,这就像两张图像做混合,而每张混合图像代表了整个这个地形实例的表面图片,为了得到这个图像的边长,可以使用terrain->getLayerBlendMapSize(); 你还可以使用blendMap1->convertImageToTerrainSpace(x, y, &tx, &ty)来得到混合图像空间上(x,y)的那个像素对应的地形实例空间上的坐标。

    最修改了混合值之后,你需要使用

    blendMap1->dirty();

       blendMap1->update();

    来更新

    2,terrain.dat的文件分析

  • 相关阅读:
    板邓:解决Visual Studio 2017 安装程序清单签名验证失败
    板邓:PHP获取当前页面url地址、参数
    板邓:【WordPress文件解读】wp-config.php
    板邓:【WordPress文件解读】wp-load.php
    板邓:【WordPress文件解读】wp-blog-header.php
    读取符号库文件
    创建空间参考
    针对乱码中文进行编辑
    根据图层路径选择文件(存储)
    springboot实现数据库中数据导出Excel功能
  • 原文地址:https://www.cnblogs.com/CodeKnight/p/1870708.html
Copyright © 2011-2022 走看看