國慶大假,沒耍成,天天寫代碼,悲劇...
地表我已經成功載入,也走了不少彎路...犯了很多低級錯誤...不然半天都可以搞定的事情,鬱悶
天龍八部的地表算是比較難搞的了,至少我這樣認為,由於自己沒多少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()<br />{<br />int tempIndex = -1;<br />for(int i = 0; i < mXSize*mZSize; ++ i){<br />// 如果此材質已經存在<br />if((tempIndex = findSameMaterial(mGridData[i], i)) >= 0){<br />// 用已有材質存入數組<br />mLightMaterialData.push_back(mLightMaterialData[tempIndex]);<br />}else{</p><p>if(mGridData[i].nSecondLayer >= 0 && mGridData[i].nFirstLayer >= 0){ // 看第二層是否存在,<br />// 拷貝第二層材質<br />MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[3])); // 先獲得材質模板<br />if(materialTemplate.isNull()){<br />OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");<br />}else{</p><p>String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材質名字<br />MaterialPtr newMaterial = materialTemplate->clone(newMaterialName); // 複製材質<br />AliasTextureNamePairList aliasList; // 儲存紋理別名的二叉樹<br />String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];<br />String textureName2 = mTextureData[mPixMapData[mGridData[i].nSecondLayer].textureId];<br />aliasList["<layer0>"] = textureName1;<br />aliasList["<layer1>"] = textureName2;<br />aliasList["<lightmap>"] = mLightMapName;<br />newMaterial->applyTextureAliases(aliasList); // 用紋理別名更改紋理<br />mLightMaterialData.push_back(newMaterialName); // 存入材質數組<br />}</p><p>}else if(mGridData[i].nFirstLayer >= 0){<br />// 拷貝第一層材質<br />MaterialPtr materialTemplate = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[1])); // 先獲得材質模板<br />if(materialTemplate.isNull()){<br />OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Material "+mTemplateData[0]+"doesn't exist!","TLBBTerrain::createMaterial");<br />}else{<br />String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材質名字<br />MaterialPtr newMaterial = materialTemplate->clone(newMaterialName); // 複製材質<br />AliasTextureNamePairList aliasList; // 儲存紋理別名的二叉樹<br />String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];<br />aliasList["<layer0>"] = textureName1;<br />aliasList["<lightmap>"] = mLightMapName;<br />newMaterial->applyTextureAliases(aliasList); // 用紋理別名更改紋理<br />mLightMaterialData.push_back(newMaterialName); // 存入材質數組<br />}</p><p>}</p><p>++ mMaterialNum;<br />}<br />}<br />}
-----------------------------------------------------------------------------------------------------------------------------------------------
然後說說圖片的翻轉操作問題
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,頂點資料有點多哈~~~