1.ogre的資源檔案用文本格式打開:
.material 可編輯
.mesh 不可編輯(需通過OgreXmlConverter.exe轉換才可看)
.skeleton 不可編輯(需通過OgreXmlConverter.exe轉換才可看)
.particle 可編輯
.overlay 可編輯
2.ogre表層腳本.overlay使用
Examples/MyLogo
{
zorder 100
container Panel(Examples/LogoPanel) // 名字不能重複
{
metrics_mode pixels
horz_align right // 定義x軸的零點為螢幕最右邊
vert_align top // 定義y軸的零點為螢幕最上邊
top 250
left -500
width 160
height 85
material Core/OgreText
}
}
3.ogre粒子腳本.particle使用
// Example emitted emitters
particle_system Examples/Fireworks1 // 注意前面的命名與overlay不同
{
material Examples/Flare
point_rendering false
particle_width 10
particle_height 10
cull_each false
quota 1000
emit_emitter_quota 10
billboard_type point
emitter Box // 這是盒子發射器,若是point,則為點發射器
{
angle 30
emission_rate 30
time_to_live 1
direction 0 1 0
velocity 0
colour_range_start 1 1 0
colour_range_end 0.3 1 0.3
width 60
height 60
depth 60
}
// Make em float downwards
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
// Give em some nice colours
affector ColourInterpolator // 顔色按一個粒子的生存期變化
{
time0 0
colour0 1 1 0
time1 0.5
colour1 1 0 0
time2 0.9
colour2 0 0 1
}
}
4.ogre的紋理支援
ogre的紋理最好是用png格式,它是ogre直接支援的格式,如果要用其他格式,如tga,
那必須在用ofusion導出檔案之前,确認紋理已經更新過,否則會出現沒貼圖的情況。
實際中用dds格式圖檔,因為其同比其它類型圖檔最小。
5.ogre中的實體和mesh
隻能通過實體設定材質,才能顯示實時修改材質的結果。
6.cegui改變滑鼠圖示
CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "TabButtonScrollLeftNormal");
所用的圖檔名字 圖檔中單個圖示的名字
7.cegui滑鼠坐标
CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();
8.直接判斷滑鼠是否按下
OIS::Mouse *inputM
if (inputM->getMouseState().buttonDown(OIS::MB_Right)){
mMainNode->yaw (Radian (2 * elapsedTime * inputM->getMouseState().X.rel));
}
取滑鼠在螢幕的x軸平移量
9.判斷滑鼠滾輪是前滾還是後滾
bool mouseMoved(const OIS::MouseEvent &arg)
{
if (arg.state.Z.rel){
if (arg.state.Z.rel > 0) ...;//前滾
if (arg.state.Z.rel < 0) ...;//後滾
}
}
10.滑鼠點選地面獲得坐标時,應注意滑鼠監聽的使用,如:
bool mouseMoved(const OIS::MouseEvent &arg)
{
CEGUI::Point mousePos = CEGUI::MouseCursor::getSingleton().getPosition();
Ray mouseRay = mCamera->getCameraToViewportRay(
mousePos.d_x/float(arg.state.width),
mousePos.d_y/float(arg.state.height));
}
這裡用的是cegui的滑鼠,但arg是ois的滑鼠事件,二者不比對,可能會造成滑鼠點選
螢幕取得的地面位置不正确。原因就是ois的螢幕寬高取的不能與cegui的滑鼠比對。
11.滑鼠移動速度控制
bool mouseMoved(const OIS::MouseEvent &arg)
{
CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
CEGUI::System::getSingleton().setMouseMoveScaling(2.0);
}
必須先有injectMouseMove,才能使setMouseMoveScaling起作用。
setMouseMoveScaling可以放在cegui定義的時候。
12.cegui改字型
由于先要建立CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"MyLookSkin.scheme");
故先修改.scheme中的字型<Font Name="SimSun-8" Filename="SimSun-8.font" />
對應需建立SimSun-8.font(内容如下)
<?xml version="1.0" ?>
<Font Name="SimSun-8" Filename="SimSun.ttc" Type="FreeType" Size="8"
NativeHorzRes="800" NativeVertRes="600" AutoScaled="true"/>
然後設定預設字型為"SimSun-8":
mGUISystem->setDefaultFont((CEGUI::utf8*)"SimSun-8");
13.ogre的綁定盒
一個對象若沒有綁定盒,其是不會顯示的。
若一個對象的綁定盒太小,則會由于綁定盒離開了錄影機的視口,而整個對象消失。
綁定盒的大小并不是不變的,當一個對象有動作時,其會自動根據對象的頂點的坐标變大或變小
14.ogre的材質腳本中關于從程式獲得的紋理處理原理:
我們通常會在材質腳本中看到如下的定義,
texture_unit
{
texture Refraction
}
這說明我們必須在程式中給予它一個紋理,此紋理名為“Refraction”,如下:
TexturePtr texture1 = TextureManager::getSingleton().createManual( "Reflection",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
512, 512, 0, PF_R8G8B8, TU_RENDERTARGET );
材質腳本會自動在記憶體的紋理名字中查找名為“Refraction”的紋理,并将其應用到對應材質中。
當然紋理的建立必須先于材質的應用。同時,也可以通過獲得紋理單元,直接給其賦予紋理。
// 材質中
texture_unit
{
}
// 程式中
MaterialPtr pMaterial = MaterialManager::getSingleton().getByName("test");
TextureUnitState* t = pMaterial.get()->getTechnique(0)->getPass(0)->getTextureUnitState(0);
t->setTextureName( "Tex", TEX_TYPE_2D);
15.設定視口的背景顔色
mWindow->getViewport(0)->setBackgroundColour(ColourValue::White);
16.把記憶體中紋理内容儲存為圖檔
// 建立小地圖紋理
TexturePtr texSmallMap = TextureManager::getSingleton().createManual("SmallMapTex",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D,
512, 512, 1, 0, PF_R8G8B8, TU_RENDERTARGET);
// 建立小地圖錄影機
Camera* pCamSmallMap = mSceneMgr->createCamera("SmallMapCam");
pCamSmallMap->setPosition(mCamera->getPosition().x,3800,mCamera->getPosition().z);
pCamSmallMap->pitch(Degree(-90));
pCamSmallMap->setAspectRatio(1);
// 用于擷取渲染目标
m_pRttTexMap = texSmallMap->getBuffer()->getRenderTarget();
Viewport *pVP = m_pRttTexMap->addViewport( pCamSmallMap );
pVP->setOverlaysEnabled(false);
pVP->setClearEveryFrame(true);
pVP->setBackgroundColour( ColourValue::White );
m_pRttTexMap->setAutoUpdated(false);
// 更新
m_pRttTexMap->update();
// 儲存為圖檔
m_pRttTexMap->writeContentsToFile("p1.jpg");
注意:通過錄影機拍照得到的圖檔,在地形是正方形平面時,才可以得到完整的小地圖。若地形有
高低起伏,則在地形邊緣凹下去的地方,拍照獲得圖檔部分是缺失的,這是由于凹下去的部分離
錄影機比較遠一些,以至于這些像素被忽略了。
17.材質中設定紋理的雙面都可見
直接添加以下到pass中:
cull_hardware none
cull_software none
18.粒子挂接骨骼會受骨骼的縮放影響的情況
當在粒子腳本中添加local_space true之後,粒子隻相對于挂接骨骼的對象空間移動,并受到骨骼
的縮放影響。一般,骨骼都是在3d max中給一個模型設定的,我們常常隻關注骨骼在模型上的位置,
而忽略了其縮放,但是在導出骨骼檔案時,縮放也會跟着一起導出來。以至于,粒子在挂接到對象
時會縮小,甚至小到看不到。解決辦法就是檢視骨骼檔案,看其是否有縮放值。
19.材質中需要在建立紋理單元時才可以設定的函數
// 若存在同名的紋理單元,則移除
if (mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(mTextureName)!=NULL){
mMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
}
// 建立新的紋理單元
TextureUnitState* texUnit =
mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(mTextureName);
// 設定字型的顔色,因為生成的圖檔是黑白相間的,是以要通過設定的顔色與圖檔混
// 合才能達到設定字型顔色的目的.
texUnit->setColourOperationEx(LBX_MODULATE,LBS_TEXTURE,LBS_MANUAL,mColor,mColor);
如上,setColourOperationEx函數就是必須在建立紋理單元後才可以使用的函數,若是你想單獨擷取
一個紋理單元,再設定setColourOperationEx函數,就會出錯,不知為什麼。
20.屏蔽實體的滑鼠選擇
一般我們使用滑鼠選擇,會先判斷滑鼠是否選擇了地形,然後在判斷是否選中模型實體。如下:
// 執行查詢
RaySceneQueryResult &result = mRaySceneQuery->execute();
RaySceneQueryResult::iterator itr;
// 周遊
for (itr = result.begin(); itr != result.end(); itr++, ++j)
{
if (itr->movable && itr->movable->getName().substr(0, 23)
!= "ETTerrain/Terrain/Tile["){
......
}
}
同樣的道理,我們可對實體的名字做一些修改,使其名字包含和地形一樣的判斷特征,就可以屏蔽了。
例如:
m_pEnt = mSceneMgr->createEntity( "ETTerrain/Terrain/Tile[robot", "robot.mesh");
21.ogre材質屬性iteration
此屬性可以設定目前pass使用的光源類型和渲染次數,如下
pass DynLighting
{
lighting on
iteration once_per_light point
scene_blend add
vertex_program_ref ET/Programs/VSDynLighting
{
}
fragment_program_ref ET/Programs/PSDynLighting
{
}
}
其中的shader是專門用于點光源的,若是程式中有其他類型的光源,則會顯示出錯誤的效果,為了避免
此類錯誤,在其前面做了一個限定iteration once_per_light point,這表明對每一個點光源隻渲染
一次。
22.陰影
目前ogre支援3種陰影,還不支援軟體陰影。要實作陰影,首先至少要有一個可投影的光源,以及一個
可以接受陰影的實體(在材質中有一項是專門處理陰影接受的,預設receive_shadows on)。
例如:
// 點光源
m_pLit = mSceneMgr->createLight("Light1");
m_pLit->setType(Light::LT_POINT);
m_pLit->setDiffuseColour(1.0, 0.0, 0.0);
m_pLit->setSpecularColour(0.0, 0.0, 0.0);
m_pLit->setVisible(true);
m_pLit->setPosition(280,160,280);
m_pLit->setAttenuation(10000,1,0.6,0.0);
m_pLit->setCastShadows(false); // 不投影
// 直射光源(預設是投影的)
m_pLit2 = mSceneMgr->createLight("Light3");
m_pLit2->setType(Light::LT_DIRECTIONAL);
m_pLit2->setDiffuseColour(1.0, 1.0, 1.0);
m_pLit2->setSpecularColour(1.0, 1.0, 1.0);
m_pLit2->setDirection(Vector3( 1, -1, 1 ));
mSceneMgr->setAmbientLight(ColourValue(0.7, 0.7, 0.7));
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
mSceneMgr->setShadowColour(ColourValue(0.5,0.5,0.5,0.1));
m_pRobot = mSceneMgr->createEntity("robot","robot.mesh");
m_pRobot->setCastShadows(false); // 初始是否接受投影由實體的材質決定,這裡強行改為了不投影
SceneNode* robotNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("robotNode",
Vector3(250,150,170));
robotNode->attachObject(m_pRobot);
robotNode->setScale(0.4, 0.4, 0.4);
23.查找資源是否存在
String meshName = "robot.mesh";
// 此判斷是查詢在media下的資源名字meshName是否存在
if(!ResourceGroupManager::getSingleton().resourceExists("General",meshName)){
assert(FALSE && "meshName is not found.");
}
// 此判斷是查詢在程式中是否已經建立了名字為meshName的模型
if(!MeshManager::getSingleton().resourceExists(meshName)){
assert(FALSE && "meshName is not found.");
}
24.彈出式消息框
MessageBox(NULL,"此模型不存在","error",MB_TASKMODAL);
25.ogre的日志管理器
可在某個函數或步驟要運作前添加:
LogManager::getSingleton().logMessage ("Caelum: Initialising Caelum system...");
在Ogre.log中檢視其資訊。
26.基于ExampleApplication.h加快錄影機速度
bool frameStarted(const FrameEvent& evt)
{
......
mCamera->moveRelative(mTranslateVector*5);
......
}
27.調整遠裁剪面和近裁剪面距離時出現的怪現象:
當你移動錄影機時,會發現模型上互相之間挨的比較近的面會重疊出現,産生閃爍現象,以下是出錯時
使用的遠裁剪面和近裁剪面距離設定:
mCamera->setNearClipDistance(0.01);
mCamera->setFarClipDistance(1000);
28.模型對光照的反應問題
假設環境光為黑色,場景中有一盞白點光源。
若是模型比較小,并在光照的範圍内,顯示沒問題。
若是模型比較大,而光照的範圍比較小,可能會出現模型全黑的情況。
我遇到的問題是,當有一塊比較大的地面模型時,無法對其進行局部照明,考慮是ogre對其先進行了包圍盒
檢查,發現地面模型在燈光範圍外,是以直接設定其無光。若是用ogre自帶的Plane,則沒問題。
29.ogre模型的陰影
若是不要求陰影很精确,可以用SHADOWTYPE_TEXTURE_MODULATIVE模式,此模式消耗最低,但最好效果在近看陰影時,也會呈現鋸齒邊緣,可通過投影基礎,過濾方式,紋理大小3個方面去優化,還有此模式下一個紋理隻儲存一個燈光産生的陰影:
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
mSceneMgr->setShadowTexturePixelFormat(PF_L8);
mSceneMgr->setShadowTextureCasterMaterial(Ogre::StringUtil::BLANK);
mSceneMgr->setShadowTextureReceiverMaterial(Ogre::StringUtil::BLANK);
mSceneMgr->setShadowTextureSelfShadow(false);
mSceneMgr->setShadowColour( ColourValue(0.3, 0.3, 0.3));
mSceneMgr->setShadowTextureSettings(2048,1);
mSceneMgr->setShadowFarDistance(600);
若是想用其它模式,可以用SHADOWTYPE_STENCIL_MODULATIVE模式,此模式下的模型需要EdgeList,若是你是用ofusion導出模型的,那在最後導出界面就有一個選項是EdgeList,選中就可以在此模式下看到陰影,否則,是看不到的。還可以對沒有EdgeList的模型使用OgreMeshUpgrade更新,同樣會産生EdgeList。但産生EdgeList的模型檔案明顯比以前大将近3倍,而且此模式下産生的陰影邊緣沒有過渡。
最後一種SHADOWTYPE_STENCIL_ADDITIVE同樣需要EdgeList,其支援多光源産生的多個陰影,但耗資源。
30.暫停粒子
ParticleSystem::setSpeedFactor(0.f)