1. 程式人生 > >實現Ogre的指令碼分離

實現Ogre的指令碼分離

目的

在研究天龍八部遊戲的原始碼之時, 發現 Ogre 材質的模板部分被單獨放在一個 material 檔案之內, 繼承模板的其他材質則位於另外的檔案, 當我使用Ogre 官方原始碼, 載入指令碼時其不會查詢位於其他material檔案內的基模板, 因此導致繼承的材質部分載入失敗.

分析

材質指令碼檔案

舉例, 指令碼檔案”女主角_臉01.material”其內的指令碼程式碼為

material 女主角_雞蛋臉_01  : premierBaseTemplate
{
      set_texture_alias <baseTexture> 女主角_雞蛋臉_01.TGA 
}

這裡材質”女主角_雞蛋臉_01” 由基礎材質 “premierBaseTemplate” 派生而來, 而材質 “premierBaseTemplate” 則位於 “actorBaseTemplate.material” 檔案中, 如果直接使用 Ogre 載入這兩個材質, 將無法正確載入派生材質.

分析原始碼

在分析原始碼和日誌的過程中, 我發現天龍八部原始碼其使用不同的指令碼載入器分析 material 指令碼, 其中天龍八部使用的是 MaterialSerializer 類的 parseScript() 函式分析”.material”字尾的指令碼, 而官方原始碼則使用 ScriptCompilerManager 類來分析 “.material” 字尾的指令碼, 而在 ScriptCompilerManager 的分析過程中, 其不會去查詢基材質是否已經載入, 這一點與 MaterialSerializer 的處理方法有所不同.

解決問題

因此, 為了讓 Ogre 預設使用 MaterialSerializer 類的相關函式來處理 “.material” 材質, 我們需要修改 Ogre 內載入器的註冊部分, 首先我們找到 ScriptCompilerManager 類的建構函式, 註釋掉 “.material” 的註冊

// mScriptPatterns.push_back("*.material"); 

現在, 我們在 MaterialManager 的建構函式內增加 “.material” 的註冊, 使得該管理器成為處理 “material” 指令碼的預設選擇

mScriptPatterns.push_back("*.material");
ResourceGroupManager::getSingleton()._registerScriptLoader(this);

最後一步, 在 MaterialManager 的 parseScript() 方法內, 註釋掉預設的指令碼處理, 使用 MaterialSerializer 類來處理指令碼.

// ScriptCompilerManager::getSingleton().parseScript(stream, groupName);
mSerializer->parseScript(stream, groupName);

結果

現在在直接載入”女主角_臉01.material”, 就可以看到正確的顯示結果了.

結果演示