菜鸟学习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,顶点数据有点多哈~~~
地表我已经成功载入,也走了不少弯路...犯了很多低级错误...不然半天都可以搞定的事情,郁闷
天龙八部的地表算是比较难搞的了,至少我这样认为,由于自己没多少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,顶点数据有点多哈~~~
相关文章推荐
- 菜鸟学习OGRE和天龙八部之四: 地表贴图的实现
- 菜鸟学习OGRE和天龙八部之六: 地表和水面的normal搞定,光照正常了
- 菜鸟学习OGRE和天龙八部之十六: 网游视角跑图功能基本实现,包括人物,射线查询,鼠标decal等等
- 菜鸟学习OGRE和天龙八部之六: 地表和水面的normal搞定,光照正常了
- 菜鸟学习OGRE和天龙八部之十六: 网游视角跑图功能基本实现,包括人物,射线查询,鼠标decal等等
- 菜鸟学习OGRE和天龙八部之三: GridInfo和HeightMap文件的数据格式(已更正)
- 菜鸟学习OGRE和天龙八部之五: 水面TerrainLiquid基本搞定
- 菜鸟学习OGRE和天龙八部之一:OGRE+MFC+OIS
- 菜鸟学习OGRE和天龙八部之七: frame帧动画数据格式搞定,已修正关键帧
- 菜鸟学习OGRE和天龙八部之十七: 修正部分地图载入的通用性问题,附源码
- 菜鸟学习OGRE和天龙八部之七: frame帧动画数据格式搞定,已修正关键帧
- 菜鸟学习OGRE和天龙八部之八: 水面方格效果和光照BUG的修正
- 菜鸟学习OGRE和天龙八部之八: 水面方格效果和光照BUG的修正
- 菜鸟学习OGRE和天龙八部之十八: 获得档案(Archive)文件列表
- 菜鸟学习OGRE和天龙八部
- 菜鸟学习OGRE和天龙八部之七: frame帧动画数据格式搞定,已修正关键帧
- 菜鸟学习OGRE和天龙八部之十: frame动画基本搞定,遇到点问题
- 菜鸟学习OGRE和天龙八部之十四: 修正水面算法的一些BUG
- 菜鸟学习OGRE和天龙八部之三: GridInfo和HeightMap文件的数据格式(已更正)
- 菜鸟学习OGRE和天龙八部之五: 水面TerrainLiquid基本搞定