您的位置:首页 > 其它

菜鸟学习OGRE和天龙八部之四: 地表贴图的实现

2011-09-04 16:11 375 查看
国庆大假,没耍成,天天写代码,悲剧...

地表我已经成功载入,也走了不少弯路...犯了很多低级错误...不然半天都可以搞定的事情,郁闷

 

天龙八部的地表算是比较难搞的了,至少我这样认为,由于自己没多少OGRE经验,不清楚地形的载入过程,于是看TSM源码,

 

发现TSM真是破,破到无法解释啊,居然只支持一个地图一个纹理,看着天龙里面几十个纹理,我只有叹气啊

 

于是打算用ETM,发现ETM用了shade,和天龙的做法完全不同,天龙的地表做法很落后...估计是为了兼容老的显卡吧,

 

没有现成的管理器可以用,就自己做啦,既然每个网格都可能有不同的材质,那就把材质相同的网格做成一个mesh

 

具体方法有2种:

 

第一种:手动生成网格mesh,把材质相同的做成一个mesh, 注意最好分tile,把一个tile内的相同材质的网格才做出一个mesh,不然会提交整个地型的顶点,关于分tile,不再多说.

 

第二种:每个网格做一个mesh,生成一个实体, 再把材质相同的实体用staticgemety合并成一个实体, staticgemety只对材质相同的实体有效果, staticgemety的划分tile也十分方便,直接调用sg->setRegionDimensions();这个函数分区就行,

 

对比2种方法,第二种操作要简单一点点,因为生成单个网格实体和分tile都很容易,

 

至于怎么生成一个mesh,也有2中方发,手动生成mesh和使用manulObject

 

显然用manulObject更简单,都不用自己去操作硬件缓存,

 

思路就这些,思路有了,做起来就不成问题了

 

-------------------------------------------------------------------------------------

然后是材质问题

 

天龙只提供了一个材质模板,意味着地形的材质要我们去继承

显然不适合写个文件去继承,只有在程序中实现了

至于方法,也有4种至少:

第一种: 最囧的,在外部做一个material脚本....

第二种: 不用模板,直接代码生成材质,再操作材质的具体数据,麻烦

第三种: 直接用做一个字符串拼接成material脚本那样的格式,载入materialManager解析

第四种: 直接代码clone材质模板,再用别名更改纹理即可,小弟用的第4种

 

 

附上源码:

void TLBBTerrain::createLightMaterial()  

{  

    int tempIndex = -1;  

    for(int i = 0; i < mXSize*mZSize; ++ i){  

        // 如果此材质已经存在  

        if((tempIndex = findSameMaterial(mGridData[i], i)) >= 0){  

            // 用已有材质存入数组  

            mLightMaterialData.push_back(mLightMaterialData[tempIndex]);  

        }else{    

  

            if(mGridData[i].nSecondLayer >= 0 && mGridData[i].nFirstLayer >= 0){ // 看第二层是否存在,  

                // 拷贝第二层材质  

                MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[3])); // 先获得材质模板  

                if(materialTemplate.isNull()){  

                    OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");  

                }else{  

  

                    String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字  

                    MaterialPtr newMaterial = materialTemplate->clone(newMaterialName);    // 克隆材质   

                    AliasTextureNamePairList aliasList;          // 存储纹理别名的二叉树   

                    String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];  

                    String textureName2 = mTextureData[mPixMapData[mGridData[i].nSecondLayer].textureId];  

                    aliasList["<layer0>"] = textureName1;  

                    aliasList["<layer1>"] = textureName2;  

                    aliasList["<lightmap>"] = mLightMapName;  

                    newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理                                    

                    mLightMaterialData.push_back(newMaterialName);    // 存入材质数组  

                }  

  

            }else if(mGridData[i].nFirstLayer >= 0){  

                // 拷贝第一层材质  

                MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[1])); // 先获得材质模板  

                if(materialTemplate.isNull()){  

                    OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");  

                }else{  

                    String newMaterialName = "material"+StringConverter::toString(mMaterialNum);      // 材质名字  

                    MaterialPtr newMaterial = materialTemplate->clone(newMaterialName);    // 克隆材质   

                    AliasTextureNamePairList aliasList;           // 存储纹理别名的二叉树   

                    String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];  

                    aliasList["<layer0>"] = textureName1;  

                    aliasList["<lightmap>"] = mLightMapName;  

                    newMaterial->applyTextureAliases(aliasList);  // 用纹理别名更改纹理                                    

                    mLightMaterialData.push_back(newMaterialName);     // 存入材质数组  

                }  

                  

            }  

  

            ++ mMaterialNum;  

        }  

    }  

}  

-----------------------------------------------------------------------------------------------------------------------------------------------

然后说说图片的翻转操作问题

 

enum Operate

{

 FLIP_HORIZINTAL = 1,    // 图片水平翻转,即左右翻转

 FLIP_VERTICAL = 2,       // 图片垂直翻转,即上下翻转

 ANTICLOCKWISE_90 = 4,    // 逆时针旋转90度

 FLIP_DIAGONAL = 8       // 以三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则把右上的坐标复制到左下

};

 

1,2,4,8 这些数字的二进制的低位,就是0001   0010  0100  1000 

他们可以叠加, 但是也很容易查找到具体含有什么属性,按位与,就查找到是否具有某属性,这是游戏常用的方法

 

由于可有有多个操作叠加,所以更改纹理坐标的时候,一定要相对上一次的坐标操作,

 

 ------------------------------------------------------------------------------------------------------------------------------------

 

 

1024*768 32位模式下.debug版本截图,由于暂时没分tile,顶点数据有点多哈~~~

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐