DirectX使用的是左手坐标系x正向右,y正向上,z正向前,即向屏幕里
Ogre/OpGL 使用的是右手坐标系 x正向右,y正向上,z正向自己,即向屏幕外
以下开发工具为 Visual Studio 2010, DirectX版本为:Microsoft DirectX SDK (June 2010)
Ogre版本为:OgreSDK_vc10_v1-7-3
注意:要想Ogre程序能运行,必须将Ogre库的dll文件路径配置进环境变量:
一:9个实体,随机出现一个,隐藏另一个,鼠标移到转动相机,按键盘移动相机.
(程序为游戏类编程/Ogre/Ogre1.73/FirstOGRE)
1:新建一个空的 win32控制台应用程序,命名为:FirstOGRE
2:添加一个 FirstOGRE.cpp文件
3:配置包含目录(包含Ogre的头文件的目录)和库目录(包含Ogre的lib文件的目录):
4:配置附加依赖项:
OgreRTShaderSystem_d.lib
OgreMain_d.lib
OIS_d.lib
5:将OgreSDK_vc10_v1-7-3安装目录下的 media目录拷贝到当前工程目录下,将OgreSDK_vc10_v1-7-3安装目录
下的 bin目录下的 debug目录下和 release目录的下后缀为 .cfg的文件拷贝到当前目录下, 并修改.cfg文件
内的配置内容(修改配置路径的内容):
6:添加一个 MyEntity
MyEntity.h:
#ifndef MyEntity_H_
#define MyEntity_H_
#include
class MyEntity
{
public:
MyEntity(Ogre::SceneManager*mSceneMgr, int i, int j);//创建实体,节点,并为节点创建动画.
~MyEntity(void);
public:
voidupdate(floatinterval);//动画
voidenable(); //随机显示实体
voiddisable();//让显示的实体隐藏
boolisEnable();//判断显示隐藏状态
private:
Ogre::Entity *m_pEnt; //创建的实体
Ogre::SceneNode *m_pSceneNode;//保存实体的节点
Ogre::AnimationState *m_pAnimState;//负责实体的动画
};
#endif
MyEntity.cpp:
#include "MyEntity.h"
MyEntity::MyEntity(Ogre::SceneManager*mSceneMgr,int i, int j)
{
using namespace Ogre;
m_pEnt = mSceneMgr->createEntity("myEntiy"+Ogre::StringConverter::toString(i*3+j),"Sinbad.mesh");//创建实体,并给实体命名
m_pEnt->setVisible(false);//默认情况下实体隐藏
m_pSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(50*i, 0, 50*j));//创建一个节点时,给节点一个位置
//pSceneNode->setScale(Ogre::Vector3(6.0f, 6.0f, 6.0f));//节点放大6倍
m_pSceneNode->attachObject(m_pEnt);//节点与实体关联
//创建实体的动画
Ogre::Animation *pAnimation =mSceneMgr->createAnimation("myEntiy"+Ogre::StringConverter::toString(i*3+j), 3.0f);//第一个为动画的名称,后一个为动画的时长
pAnimation->setInterpolationMode(Ogre::Animation::IM_SPLINE);//设置动画差值为样条插值
Ogre::NodeAnimationTrack*pTrack =pAnimation->createNodeTrack(0,m_pSceneNode);//创建一个轨迹动画,第一个值为索引,第二个为关联的节点
//在第秒,物体放大为整个物体的倍
Ogre::TransformKeyFrame*pKey =pTrack->createNodeKeyFrame(0.0f);
pKey->setScale(Ogre::Vector3(3.0f,3.0f, 3.0f));//物体放大3倍
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));//转换点
//在第秒后,物体放大为整个物体的倍
pKey = pTrack->createNodeKeyFrame(1.0f);
pKey->setScale(Ogre::Vector3(6.0f,6.0f, 6.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//在第秒后,物体放大为整个物体的倍
pKey = pTrack->createNodeKeyFrame(2.0f);
pKey->setScale(Ogre::Vector3(6.0f,6.0f, 6.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//在第秒后,物体放大为整个物体的倍
pKey = pTrack->createNodeKeyFrame(3.0f);
pKey->setScale(Ogre::Vector3(3.0f,3.0f, 3.0f));
pKey->setTranslate(Ogre::Vector3(50*i, 0, 50*j));
//通过上面的动画创建动画状态
m_pAnimState = mSceneMgr->createAnimationState("myEntiy"+Ogre::StringConverter::toString(i*3+j));
m_pAnimState->setEnabled(false);//初期动画为关闭
m_pAnimState->setLoop(true); //设置动画为循环播放
}
MyEntity::~MyEntity(void)
{
}
void MyEntity::update(floatinterval)
{
/*自己写的缩放动画
floatscale = 0.0f;
if(interval<= 0.5f) scale = 6.0f*interval;
elsescale = 6.0f*(1-interval);
m_pSceneNode->setScale(scale,scale, scale);
*/
m_pAnimState->setTimePosition(interval);//设置动画的起点
}
void MyEntity::enable()
{
if(!m_pEnt->getVisible()){
m_pAnimState->setEnabled(true);//设置动画为开启
m_pAnimState->setTimePosition(0.0f);//设置动画的起点
m_pEnt->setVisible(true);
}
}
void MyEntity::disable()
{
if(m_pEnt->getVisible())m_pEnt->setVisible(false);//隐藏
}
bool MyEntity::isEnable()
{
return m_pEnt->getVisible();//判断是否是显示
}
7:添加一个 MyEntityManager
MyEntityManager.h:
#ifndef MyEntityManager_H_
#define MyEntityManager_H_
#include "MyEntity.h"
class MyEntityManager//MyEntity的管理类
{
public:
MyEntityManager(Ogre::SceneManager*mSceneMgr);
~MyEntityManager(void);
public:
voidupdate(constFrameEvent&evt);//帧事件
private:
MyEntity*m_pMyEnt[9];//9个实体
MyEntity*m_pCurrentMyEnt;//记录当前可见实体
floatm_time;//用于时间累加,当大于等于1时,还原为0
};
#endif
MyEntityManager.cpp:
#include "MyEntityManager.h"
MyEntityManager::MyEntityManager(Ogre::SceneManager*mSceneMgr) : m_time(0.0f),m_pCurrentMyEnt(NULL)
{
/*Ogre::Entity*pEnt = mSceneMgr->createEntity("Sword", "Sword.mesh");
SceneNode*pSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
pSceneNode->setScale(Ogre::Vector3(6.0f,6.0f, 6.0f));
pSceneNode->attachObject(pEnt);*/
for(inti=0; i<3; i++){ //创建9个实体
for(intj=0; j<3; j++){
m_pMyEnt[i*3+j] =new MyEntity(mSceneMgr,i, j);
}
}
}
MyEntityManager::~MyEntityManager(void)
{
for(inti=0; i<9; i++){
deletem_pMyEnt[i];
m_pMyEnt[i] =NULL;
}
m_pCurrentMyEnt= NULL;
}
void MyEntityManager::update(constFrameEvent& evt)
{
m_time+= evt.timeSinceLastFrame;
if(m_time >= 1.0f){//当每过1秒,随机显示一个实体
if(NULL !=m_pCurrentMyEnt)m_pCurrentMyEnt->disable();
m_pCurrentMyEnt= m_pMyEnt[rand()%9];
m_pCurrentMyEnt->enable();
m_time= 0.0f; //还原为0.0f
}
if(NULL !=m_pCurrentMyEnt)m_pCurrentMyEnt->update(m_time);//更新显示的实体状态
}
8:添加一个监听类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
class MyEntityManager;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
//bufferedKeys,bufferedMouse,bufferedJoy:是否启用键盘,鼠标,手柄的缓冲,默认不启用,会导致不停地检查输入设备信息来确定按键是否按下或释放,鼠标是否移动等等,如果检测
// 不够快速,某一动作可能不会被发现,所以调用时,要启用缓冲,在缓冲模式下,OIS会记录所有输入设备的变化,并把它们通过消息告知应
// 用程序。在缓冲模式下不需要检查输入设备的状态,只需要处理OIS发送的消息。
MyEntityFrameListener(MyEntityManager *pMyEntMgr,RenderWindow*win,Camera*cam,bool bufferedKeys= false, bool bufferedMouse = false,bool bufferedJoy=false);
~MyEntityFrameListener(void);
public:
//virtualbool processUnbufferedKeyInput(const FrameEvent& evt); //键盘输入
//virtual bool processUnbufferedMouseInput(constFrameEvent& evt);//鼠标输入
virtualboolkeyPressed(constOIS::KeyEvent &arg);//启用bufferedKeys缓存,并继承了KeyListener,则使用此替代processUnbufferedKeyInput
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(const OIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
void moveCamera(); //移动相机
virtualboolframeEnded(constFrameEvent&evt); //循环刷新界面
private:
MyEntityManager*m_pMyEntMgr;//实体管理类,也是实体集合类
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
#include "MyEntityManager.h"
MyEntityFrameListener::MyEntityFrameListener(MyEntityManager *pMyEntMgr,RenderWindow*win,Camera* cam, bool bufferedKeys,bool bufferedMouse,bool bufferedJoy)
:ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy),m_pMyEntMgr(pMyEntMgr)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
if(NULL !=m_pMyEntMgr){
deletem_pMyEntMgr;
m_pMyEntMgr= NULL;
}
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
/*设置相机投影多边形模式,不用
caseOIS::KC_NUMPAD0:
case 0 :mCamera->setPolygonMode(PM_SOLID);
break;
caseOIS::KC_NUMPAD1:
case 1 : mCamera->setPolygonMode(PM_WIREFRAME);
break;
caseOIS::KC_NUMPAD2:
case 2 :mCamera->setPolygonMode(PM_POINTS);
break;*/
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent &arg)//释放按下的键
{
mTranslateVector= Vector3::ZERO;//防止按键释放后还继续移动相机
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent &arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)) {
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
mRotY= Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera()//移动相机
{
mCamera->yaw(mRotX); //绕y轴转动
mCamera->pitch(mRotY);//绕x轴转动
mCamera->moveRelative(mTranslateVector);//移动相机
mRotX= mRotY = 0; //防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
//ExampleFrameListener::frameEnded(evt);//可以不用
moveCamera();//移动相机
if(NULL !=m_pMyEntMgr)m_pMyEntMgr->update(evt);//每个一秒随机显示一个实体,隐藏另一个实体等
returntrue;
}
9:添加一个 应用程序类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityManager.h"
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
private:
MyEntityManager *m_pMyEntMgr;
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pMyEntMgr= NULL;
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if(NULL !=m_pMyEntMgr){
deletem_pMyEntMgr;
m_pMyEntMgr= NULL;
}
if(NULL ==m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(94.0f, 194.043f, 375.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机角度
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2",50);//设置天空盒
m_pMyEntMgr= new MyEntityManager(mSceneMgr);//创建9个实体
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(m_pMyEntMgr,mWindow,mCamera, true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
10:FirstOGRE.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationm;
m.go();
return0;
}
二:旋转节点,缩放节点,坐标空间移动旋转节点等,绑定相机旋转节点等
(程序为游戏类编程/Ogre/Ogre1.73/SecondOGRE)
1:新建一个 空的win32控制台应用程序,命名为:SecondOGRE.
2:添加一个 SecondOGRE.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst = NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
//创建地面
Planeplane(Vector3::UNIT_Y, -15);//通过法向量与恒定数创建一个Plane
MeshManager::getSingleton().createPlane("GrassPlane",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//宽度,高度
200, 200, // x方向段值,y方向段值,即面板分成多少个三角形
true, //创建一个垂直的法向量到面板
1, 5, 5, Vector3::UNIT_Z);// 2D纹理坐标设置的数量,在u,v方向重复的瓦片的数量,纹理方向
Entity*pEnt =mCamera->getSceneManager()->createEntity("GrassPlane","GrassPlane");
mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("GrassPlane")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");//设置材质 Examples/GrassFloor
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
5:添加一个类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移动相机
virtualboolframeEnded(constFrameEvent&evt);//循环刷新界面
protected:
voidcreateEntity1();//创建实体,绕各自自身轴旋转节点等
voidcreateEntity2();//创建实体,缩放节点等
// root节点没有父节点,其它节点都有父节点
voidcreateEntity3();//坐标空间,TS_PARENT(父节点空间),TS_WORLD(世界坐标空间),TS_LOCAL(自己的空间)
voidcreateEntity4();//在各个空间的移动
voidcreateEntity5();//在各个空间的转动
protected:
SceneManager*mSceneMgr;
SceneNode*m_pNode7;
SceneNode*m_pNode8;
SceneNode*m_pNode9;
SceneNode*m_pNode10;
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
mSceneMgr= cam->getSceneManager();
createEntity1();//创建实体,绕各自自身轴旋转节点等
createEntity2();//创建实体,缩放节点
createEntity3();//坐标空间,TS_PARENT(父节点空间),TS_WORLD(世界坐标空间),TS_LOCAL(自己的空间)
createEntity4();//在各个空间的移动
createEntity5();//在各个空间的转动
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//释放按下的键
{
mTranslateVector= Vector3::ZERO;//防止按键释放后还继续移动相机
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
mRotY= Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera() //移动相机
{
// mCamera->yaw(mRotX); //绕y轴转动
//mCamera->pitch(mRotY);//绕x轴转动
mCamera->moveRelative(mTranslateVector);//移动相机
// pNode7->translate(tran3, Node::TS_PARENT);//TS_PARENT时,点的位置:pos7+tran3
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();mOrientation = q*mOrientation;
//pNode8->translate(tran8,Node::TS_LOCAL);//TS_LOCAL时,点的位置:pos8+mOrientation*tran8
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();mOrientation = q*mOrientation;
//pNode9->translate(tran9,Node::TS_WORLD);//TS_WORLD时,点的位置:pos9+(mParent->_getDerivedOrientation().Inverse()*tran9)/mParent->_getDerivedScale())
//Quaternionq;q.FromAngleAxis(angle,axis);q.normalise();
//mOrientation =mOrientation*_getDerivedOrientation().Inverse()*q*_getDerivedOrientation();
m_pNode7->yaw(mRotY);//m_pNode7节点必须转,下面的3个节点才会绕着m_pNode7节点转
//m_pNode7节点转,会导致其子节点跟着转, 实际上不需要 m_pNode8->yaw +m_pNode8->lookAt
//**m_pNode8->yaw(mRotY);//,Node::TS_PARENT //加不加空间都绕着自身点转动
//**m_pNode8->lookAt(m_pNode7->getPosition(),Node::TS_WORLD);//可以防止m_pNode8自转
//**m_pNode9->yaw(mRotY);//,Node::TS_WORLD //加不加空间都绕着自身点转动
//**m_pNode9->lookAt(m_pNode7->getPosition(),Node::TS_WORLD);//可以防止m_pNode9自转
m_pNode10->yaw(mRotY,Node::TS_WORLD);//m_pNode10节点绑定的相机会绕着m_pNode7节点所在点转,但是
//m_pNode10节点是绕着自己所在的点转,而不是m_pNode7节点所在的点
//m_pNode10->lookAt(m_pNode7->getPosition(),Node::TS_WORLD);//不能调用,否则m_pNode10不会转
m_pNode10->pitch(mRotX);
mRotX= mRotY = Radian(0);//防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
moveCamera();//移动相机
returntrue;
}
void MyEntityFrameListener::createEntity1()//创建实体,绕各自自身轴旋转节点等
{
//在(0,0,0)点放置一个节点实体,用于与下面4个节点实体做对比
Entity*pEnt0 =mSceneMgr->createEntity("MyEntity0","Sinbad.mesh");
pEnt0->setMaterialName("Ogre/Skin");
SceneNode*pNode0 =mSceneMgr->createSceneNode("MyEntity0");
mSceneMgr->getRootSceneNode()->addChild(pNode0);//给根节点添加一个子节点
pNode0->attachObject(pEnt0);//给节点附上实体
pNode0->setPosition(0,0,0);//设置pNode1在根节点的位置
//用于下面3个节点的父节点
Entity*pEnt1 =mSceneMgr->createEntity("MyEntity1","Sinbad.mesh");
SceneNode*pNode1 =mSceneMgr->createSceneNode("MyEntity1");
mSceneMgr->getRootSceneNode()->addChild(pNode1);//给根节点添加一个子节点
pNode1->attachObject(pEnt1);//给节点附上实体
pNode1->setPosition(0, 0, -150);//设置pNode1在根节点的位置
//pitch:绕自身X轴转
Entity*pEnt2 =mSceneMgr->createEntity("MyEntity2","Sinbad.mesh");
SceneNode*pNode2 =mSceneMgr->createSceneNode("MyEntity2");
pNode1->addChild(pNode2);//为pNode1节点添加子节点pNode2
pNode2->attachObject(pEnt2);//节点2附上实体
pNode2->setPosition(10,0,0);//设置pNode2在pNode1中的位置
pNode2->pitch(Radian(Math::HALF_PI));//HALF_PI:PI的一半,及PI/2,绕X轴逆时针旋转PI/2
Vector3v2 =pNode2->getPosition();//取得的是10,0,0
// yaw:绕自身Y轴转
Entity*pEnt3 =mSceneMgr->createEntity("MyEntity3","Sinbad.mesh");
SceneNode*pNode3 =mSceneMgr->createSceneNode("MyEntity3");
pNode1->addChild(pNode3);//为pNode1节点添加子节点pNode3
pNode3->attachObject(pEnt3);
Vector3pos(0, 0, 0);
Vector3transVec(20, 0, 0);
pNode3->setPosition(pos);
pNode3->translate(transVec);//新的位置为:pos + transVec
pNode3->yaw(Degree(90.0f));//绕Y轴逆时针旋转90度,相当于Radian(Math::HALF_PI)
// roll:绕自身Z轴转
Entity*pEnt4 =mSceneMgr->createEntity("MyEntity4","Sinbad.mesh");
SceneNode*pNode4 =mSceneMgr->createSceneNode("MyEntity4");
pNode1->addChild(pNode4);
pNode4->attachObject(pEnt4);
pNode4->setPosition(30,0,0);//设置pNode4在pNode1中的位置
pNode4->roll(Radian(Math::HALF_PI));//绕Z轴逆时针旋转P1/2
}
void MyEntityFrameListener::createEntity2()//创建实体,缩放节点
{
Entity*pEnt5 =mSceneMgr->createEntity("MyEntity5","ninja.mesh");
SceneNode*pNode5 =mSceneMgr->createSceneNode("MyEntity5");
mSceneMgr->getRootSceneNode()->addChild(pNode5);
pNode5->attachObject(pEnt5);
pNode5->setPosition(60, 0, 0);
pNode5->scale(0.1f, 0.1f, 0.1f);//节点缩小为当前大小的0.1倍
Entity*pEnt6 =mSceneMgr->createEntity("MyEntity6","Sinbad.mesh");
SceneNode*pNode6 =mSceneMgr->getRootSceneNode()->
createChildSceneNode("MyEntity6",Vector3(70,0, 0));//为节点指定名称,指定位置
pNode6->attachObject(pEnt6);
pNode6->setScale(2.0f, 2.0f, 2.0f);//节点放大为原始大小的2倍
}
void MyEntityFrameListener::createEntity3()//坐标空间,TS_PARENT(父节点空间),TS_WORLD(世界坐标空间),TS_LOCAL(自己的空间)
{
//下面两个个节点的父节点
Entity*pEnt7 =mSceneMgr->createEntity("MyEntity7","Sinbad.mesh");
m_pNode7= mSceneMgr->getRootSceneNode()->createChildSceneNode("MyEntity7");
m_pNode7->attachObject(pEnt7);
m_pNode7->setPosition(Vector3(-30.0f,0.0f, -30.0f));
//用于在TS_PARENT空间绕转
Entity*pEnt8 =mSceneMgr->createEntity("MyEntity8","ninja.mesh");
m_pNode8= m_pNode7->createChildSceneNode("MyEntity8");
m_pNode8->attachObject(pEnt8);
m_pNode8->setPosition(0, 0, -20);
m_pNode8->scale(0.05f, 0.05f, 0.05f);
//用于在TS_WORLD空间绕转
Entity*pEnt9 =mSceneMgr->createEntity("MyEntity9","Sinbad.mesh");
m_pNode9= m_pNode7->createChildSceneNode("MyEntity9");
m_pNode9->attachObject(pEnt9);
m_pNode9->setPosition(0, 0, -30);
//非m_pNode7节点的子节点,但是绕着m_pNode7节点转
Vector3vPos =m_pNode7->getPosition();
RealfRadius =pEnt7->getBoundingRadius();
Vector3cameraNodePos(vPos.x,vPos.y, vPos.z-fRadius);//相机节点位置在模型实体后面
m_pNode10= mSceneMgr->getRootSceneNode()->createChildSceneNode("MyEntity10");
m_pNode10->attachObject(mCamera);
m_pNode10->setPosition(cameraNodePos);
m_pNode10->lookAt(vPos,Node::TS_WORLD);//要使相机能绕m_pNode7节点转,必须在此设置lookAt
//但是此m_pNode10节点还是绕着自己所在点转
Entity*pEnt10 =mSceneMgr->createEntity("MyEntity10","Sinbad.mesh");
pEnt10->setMaterialName("OceanHLSL_GLSL");
m_pNode10->attachObject(pEnt10);
}
void MyEntityFrameListener::createEntity4()//在各个空间的移动
{
//下面两个节点的父节点,转180度后,其自身的XZ坐标与世界空间的 XZ 方向相反
Entity*ent =mSceneMgr->createEntity("MyEntity11","Sinbad.mesh");
ent->setMaterialName("Ogre/Skin");
SceneNode*node =mSceneMgr->getRootSceneNode()->createChildSceneNode("Node11");
node->attachObject(ent);
node->setPosition(0,0,-100);
node->yaw(Degree(180.0f));//转180度
//此节点在父节点空间移动(translate(0,0,10)),即向世界空间的Z负方向移动,因为父节点转了180度
Entity*ent2 =mSceneMgr->createEntity("MyEntity12","Sinbad.mesh");
SceneNode*node2 =node->createChildSceneNode("node12");
node2->attachObject(ent2);
node2->setPosition(10,0,0);
node2->translate(0,0,10);
//在自身空间移动Node::TS_LOCAL
ent2= mSceneMgr->createEntity("MyEntity13","Sinbad.mesh");
ent2->setMaterialName("Examples/SphereMappedRustySteel");
node2= node->createChildSceneNode("node13");
node2->attachObject(ent2);
node2->yaw(Degree(45));
node2->setPosition(10,0,0);
node2->translate(0,0,10,Node::TS_LOCAL);
//此节点在世界空间移动,向世界空间的Z正方向移动,即向父节点空间Z负方向移动
Entity*ent3 =mSceneMgr->createEntity("MyEntity14","Sinbad.mesh");
ent3->setMaterialName("OceanHLSL_GLSL");
SceneNode*node3 =node->createChildSceneNode("node14");
node3->setPosition(20,0,0);
node3->translate(0,0,10,Node::TS_WORLD);
node3->attachObject(ent3);
}
void MyEntityFrameListener::createEntity5()//在各个空间的转动
{
Entity*ent =mSceneMgr->createEntity("MyEntity15","sinbad.mesh");
SceneNode*node =mSceneMgr->getRootSceneNode()->createChildSceneNode("Node15");
node->attachObject(ent);
Entity*ent2 =mSceneMgr->createEntity("MyEntity16","sinbad.mesh");
SceneNode*node2 =mSceneMgr->getRootSceneNode()->createChildSceneNode("Node16");
node2->attachObject(ent2);
node2->setPosition(10,0,0);
node2->yaw(Degree(90));//在自身空间转动
node2->roll(Degree(90));
Entity*ent3 =mSceneMgr->createEntity("MyEntity17","Sinbad.mesh");
SceneNode*node3 =node->createChildSceneNode("node17");
node3->attachObject(ent3);
node3->setPosition(20,0,0);
node3->yaw(Degree(90),Node::TS_WORLD);//在世界空间转动
node3->roll(Degree(90),Node::TS_WORLD);
}
六:SecondOGRE.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplication app;
app.go();
return 0;
}
三:通过面板(Plane)创建实体,灯光,阴影,相机,视口,简单移动模型等.
(程序为游戏类编程/Ogre/Ogre1.73/ LightCameraShadow)
1:新建一个空的 win32控制台应用程序, 命名为:LightCameraShadow
2:添加一个 LightCameraShadow.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
voidcreateLinghtAndMesh();//创建Plane,灯光,和Mesh
voidcreateNewCamera(); //创建相机,添加视口
private:
MyEntityFrameListener*m_pFrameLst;
SceneNode*m_pSinbadNode;//模型实体节点
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
/*
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f,0.5f, 0.5f));//设置环境光
Light *l =mSceneMgr->createLight("mainLight");
l->setPosition(20,80, 50);
Ogre::Vector3 pst =mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0,100.0f, 100.0f); //设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f,-0.3f, -0.00865638f, -0.0027f)); //设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
*/
createLinghtAndMesh();//创建Plane,灯光,和Mesh
createNewCamera(); //创建相机,添加视口
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(m_pSinbadNode,mWindow,mCamera,true,true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::createLinghtAndMesh()//创建Plane,灯光,和Mesh
{
//创建Plane
Ogre::Planeplane(Vector3::UNIT_Y,-10);//通过法向量与恒定数创建一个Plane
Ogre::MeshManager::getSingleton().createPlane("plane",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//宽度,高度
200, 200,//x方向段值,y方向段值,即面板分成多少个三角形
true, //创建一个垂直的法向量到面板
1, 5, 5, Vector3::UNIT_Z);//2D纹理坐标设置的数量,在u,v方向重复的瓦片的数量,纹理方向
Ogre::Entity*pEnt = mSceneMgr->createEntity("plane1","plane");
mSceneMgr->getRootSceneNode()->createChildSceneNode("plane1")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");
//创建灯光1,点光源,点光源有位置,无方向,参与阴影计算
Ogre::Light *pLight1=mSceneMgr->createLight("Light1");
pLight1->setType(Ogre::Light::LT_POINT);//点光源
pLight1->setPosition(100, 20, 0);
pLight1->setDiffuseColour(1.0f, 1.0f, 1.0f);//漫反射颜色
Ogre::Entity *pLightEnt1=mSceneMgr->createEntity("sphere1","sphere.mesh");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
Ogre::SceneNode *pLightNode1=pNode->createChildSceneNode("LightNode1");
pLightNode1->attachObject(pLightEnt1);
pLightNode1->setPosition(100, 20, 0);
pLightNode1->setScale(0.1f, 0.1f, 0.1f);
//创建灯光2,聚光灯,聚光灯有位置,有方向,参与阴影计算
Ogre::Light *pLight2=mSceneMgr->createLight("Light2");
pLight2->setType(Ogre::Light::LT_SPOTLIGHT);//聚光灯
pLight2->setPosition(0, 100, 0);//聚光灯的位置
pLight2->setDirection(Ogre::Vector3(1, -1, 0));//方向
pLight2->setSpotlightInnerAngle(Ogre::Degree(5.0f));//内角
pLight2->setSpotlightOuterAngle(Ogre::Degree(15.0f));//外角
pLight2->setSpotlightFalloff(0.0f);//衰减
pLight2->setDiffuseColour(Ogre::ColourValue(0.0f, 1.0f, 0.0f));//漫反射
Ogre::Entity *pLightEnt2=mSceneMgr->createEntity("sphere2","sphere.mesh");
Ogre::SceneNode *pLightNode2=pNode->createChildSceneNode("LightNode2");
pLightNode2->attachObject(pLightEnt2);//将实体关联到节点
//pLightNode2->attachObject(pLight2)将聚光灯关联到节点
pLightNode2->setPosition(0, 100, 0);//指定节点,也就是聚光灯的位置
pLightNode2->setScale(0.1f, 0.1f, 0.1f);
//创建灯光3,方向光,方向光没有位置,有方向,参与阴影计算
Ogre::Light *pLight3=mSceneMgr->createLight("Light3");
pLight3->setType(Ogre::Light::LT_DIRECTIONAL);//方向光
pLight3->setDiffuseColour(Ogre::ColourValue(1.0f, 0.0f, 0.0f));//漫反射
pLight3->setDirection(Ogre::Vector3(1, -1, 0));
//创建模型实体
Ogre::Entity *pSinbadEnt=mSceneMgr->createEntity("Sinbad1","Sinbad.mesh");
m_pSinbadNode= pNode->createChildSceneNode("Sinbad1");
m_pSinbadNode->attachObject(pSinbadEnt);
m_pSinbadNode->setPosition(Ogre::Vector3(61.0f, 4.0f, 0.0f));
m_pSinbadNode->setScale(3.0, 3.0, 3.0);
//添加阴影
mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
}
void MyExampleApplication::createNewCamera()//创建相机,添加视口
{
Camera*mpNewCamera =mSceneMgr->createCamera("MyCamera1");
mpNewCamera->setPosition(0, 100, 200);
mpNewCamera->lookAt(0, 0, 0);
mpNewCamera->setNearClipDistance(5);//近距离...从圆台到近面板...
//mpNewCamera->setPolygonMode(Ogre::PM_WIREFRAME);//多线段模式,PM_WIREFRAME(线框模式)
//mpNewCamera->setPolygonMode(Ogre::PM_POINTS); //点模式
//mpNewCamera->setPolygonMode(Ogre::PM_SOLID); //实线模式,也是默认模式
//创建视口(viewport),要想添加视口不崩,必须给视口设置一个ZOrder,且ZOrder全局唯一,
//当视口多余1个时,需要为每个视口指定left,top,width,height,否则ZOrder值大的会覆盖ZOrder值小的视口
Ogre::Viewport *pvp =mWindow->addViewport(mpNewCamera, 1, 0, 0, 0.2, 1);
pvp->setBackgroundColour(ColourValue(0.0f,0.0f, 1.0f));
mpNewCamera->setAspectRatio(Real(pvp->getActualWidth())/Real(pvp->getActualHeight()));
}
5:添加一个类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(SceneNode *pSinbadNode,RenderWindow*win,Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移动相机
virtualboolframeEnded(constFrameEvent&evt);//循环刷新界面
protected:
SceneNode*m_pSinbadNode;//模型实体节点
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(SceneNode*pSinbadNode,RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy),m_pSinbadNode(pSinbadNode)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//释放按下的键
{
mTranslateVector= Vector3::ZERO;//防止按键释放后还继续移动相机
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
mRotY= Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera() //移动相机
{
mCamera->yaw(mRotX); //绕Y轴转动
mCamera->pitch(mRotY);//绕X轴转动
mCamera->moveRelative(mTranslateVector);//移动相机
mRotX= mRotY = 0; //防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
//ExampleFrameListener::frameEnded(evt);//可以不用
m_pSinbadNode->translate(mTranslateVector);//模型移动
moveCamera();//移动相机
returntrue;
}
6:LightCameraShadow.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationapp;
app.go();
return0;
}
四:模型动画,走动,跳动,切换武器,攻击动画等和 相机跟踪,相机跟踪模型实体与跟踪旋转等,外带相机节点
绑定另一个模型实体,模型实体绕的是相机节点所在点转动, 而相机却是绕相机lookAt的点转动.
(程序为 游戏类编程/Ogre/Ogre1.73/ Animating)
1:新建一个空的 win32控制台应用程序, 命名为:Animating
2:添加一个 Animating.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
protected:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera, true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
5:添加一个类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移动相机
virtualboolframeEnded(constFrameEvent&evt);//循环刷新界面
voidcreateEntity();//创建实体
protected:
Entity *m_pSinbadEnt;//模型实体
SceneNode*m_pSinbadNode;//模型节点
AnimationState*m_pAniState;//动画
Entity*m_pSword1;//武器剑1
Entity*m_pSword2;//武器剑2
RibbonTrail*m_pSwordTrail;//丝带
boolm_bUseSword;//默认情况下为true,即剑在手上
Realm_fUseSwordTime;//使用武器动画时长
boolm_bAttack; //攻击动画是否启用
Realm_fAttackTime;//攻击时长
boolm_bJump; //跳
Realm_fJumpTime;//跳动时长
SceneNode*m_pCameraNode;//关联相机节点
Vector3m_moveVector;//移动向量
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
createEntity(); //创建实体
m_bAttack= false; //攻击动画不启用
m_fAttackTime= 0.0f;
m_bUseSword= true;//默认使用武器
m_fUseSwordTime= -1.0f; //防止动画重复,使用武器动画时长
m_bJump= false; //默认不跳
m_fJumpTime= 0.0f;
m_moveVector= Vector3::ZERO;
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x =moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x = -moveScale;//Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z =moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z = -moveScale;//Move camera backward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
case OIS::KC_E: //使用武器
{
m_fUseSwordTime= 0.0f;
if(m_bUseSword){//将武器放到背上
m_bUseSword= false;
} else{ //将武器放到手上
m_bUseSword= true;
}
}
break;
caseOIS::KC_SPACE://跳动
m_bJump= true;
break;
}
if(0 != mTranslateVector.x || 0 != mTranslateVector.z){ //走动
m_pAniState= m_pSinbadEnt->getAnimationState("RunBase");
m_pAniState->setEnabled(true);
m_pAniState= m_pSinbadEnt->getAnimationState("RunTop");
m_pAniState->setEnabled(true);
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//释放按下的键
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x = 0.0f;
break;
caseOIS::KC_W:
caseOIS::KC_UP:
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z = 0.0f;
break;
caseOIS::KC_PGUP:
caseOIS::KC_PGDOWN:
mTranslateVector.y = 0.0f;
break;
caseOIS::KC_SPACE://停止跳动
m_bJump= false;
break;
}
if(0 == mTranslateVector.x && 0 == mTranslateVector.z){ //停止走动
m_pAniState= m_pSinbadEnt->getAnimationState("RunBase");
m_pAniState->setEnabled(false);
m_pAniState= m_pSinbadEnt->getAnimationState("RunTop");
m_pAniState->setEnabled(false);
}
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.Y.rel * 0.13);//转为度数,如:Degree(180)
mRotY= Degree(-ms.X.rel * 0.13);//转为度数,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
m_bAttack= true;//开始攻击
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
m_bAttack= false;//停止攻击
returntrue;
}
void MyEntityFrameListener::moveCamera() //移动相机
{
m_pSinbadNode->yaw(mRotY);//模型实体节点绕自身Y轴转动
m_pCameraNode->yaw(mRotY,Node::TS_WORLD);//m_pCameraNode节点绑定的相机会绕着m_pSinbadNode节点所在点转,但是
//m_pCameraNode节点是绕着自己所在的点转,而不是m_pSinbadNode节点所在的点
m_pCameraNode->pitch(mRotX);
mRotX= mRotY = Radian(0);//防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
// *******************************换武器动画
m_pAniState= m_pSinbadEnt->getAnimationState("DrawSwords");
if(0.0f== m_fUseSwordTime){ //只要m_fUseSwordTime时间为0,就表示要切换武器
m_pAniState->setEnabled(true);
}
if(0.0f<= m_fUseSwordTime && m_fUseSwordTime <= m_pAniState->getLength()){ //值在0.0f与动画时长之间,就运行动画,一个完整的动画
m_pAniState->addTime(evt.timeSinceLastFrame);
m_fUseSwordTime+= evt.timeSinceLastFrame;
}
if (m_fUseSwordTime >=m_pAniState->getLength()){//动画结束
m_pAniState->setEnabled(false);
m_fUseSwordTime= -1.0f; //防止动画重复
m_pSinbadEnt->detachAllObjectsFromBone();
if(m_bUseSword){//使用武器
m_pSinbadEnt->attachObjectToBone("Handle.L",m_pSword1);
m_pSinbadEnt->attachObjectToBone("Handle.R",m_pSword2);
} else{ //卸载武器
m_pSinbadEnt->attachObjectToBone("Sheath.L",m_pSword1);
m_pSinbadEnt->attachObjectToBone("Sheath.R",m_pSword2);
}
}
//*******************************走动动画
if(0!= mTranslateVector.x|| 0 != mTranslateVector.z){
m_pAniState= m_pSinbadEnt->getAnimationState("RunBase");
m_pAniState->addTime(evt.timeSinceLastFrame);
m_pAniState= m_pSinbadEnt->getAnimationState("RunTop");
m_pAniState->addTime(evt.timeSinceLastFrame);
}
//*********************************攻击动画
if(0.0f== m_fAttackTime && m_bAttack){ //攻击开始
m_pAniState= m_pSinbadEnt->getAnimationState("SliceVertical");
m_pAniState->setEnabled(true);
m_pAniState= m_pSinbadEnt->getAnimationState("SliceHorizontal");
m_pAniState->setEnabled(true);
m_fAttackTime= evt.timeSinceLastFrame;
}
m_pAniState= m_pSinbadEnt->getAnimationState("SliceVertical");
if (m_pAniState->getLength()>m_fAttackTime && 0.0f < m_fAttackTime){ //一个完整的攻击
m_pAniState->addTime(evt.timeSinceLastFrame);
m_pAniState= m_pSinbadEnt->getAnimationState("SliceHorizontal");
m_pAniState->addTime(evt.timeSinceLastFrame);
m_fAttackTime+= evt.timeSinceLastFrame;
} else{
if(!m_bAttack && 0 !=m_fAttackTime){//停止攻击
m_pAniState= m_pSinbadEnt->getAnimationState("SliceVertical");
m_pAniState->setEnabled(false);
m_pAniState= m_pSinbadEnt->getAnimationState("SliceHorizontal");
m_pAniState->setEnabled(false);
m_fAttackTime= 0.0f;
} elseif(m_bAttack && 0 !=m_fAttackTime){//重复攻击
m_fAttackTime= evt.timeSinceLastFrame;
}
}
//************************************************跳动
if(m_bJump && 0.0f ==m_fJumpTime){ //跳动开始
m_pAniState= m_pSinbadEnt->getAnimationState("JumpLoop");
m_pAniState->setEnabled(true);
m_fJumpTime= evt.timeSinceLastFrame;
}
m_pAniState= m_pSinbadEnt->getAnimationState("JumpLoop");
if(m_pAniState->getLength()>m_fJumpTime && 0.0f < m_fJumpTime){ //一个完整的跳动
m_pAniState->addTime(evt.timeSinceLastFrame);
m_fJumpTime+= evt.timeSinceLastFrame;
m_pSinbadNode->setPosition(m_pSinbadNode->getPosition() +Vector3(0.0f,m_fJumpTime/5, 0.0f));
} else{ //模型实体下降,停止跳动
if(0< m_pSinbadNode->getPosition().y){
m_pSinbadNode->setPosition(m_pSinbadNode->getPosition() +Vector3(0.0f,-m_fJumpTime, 0.0f));
m_pAniState= m_pSinbadEnt->getAnimationState("JumpLoop");
m_pAniState->setEnabled(false);
} else{
m_pSinbadNode->setPosition(m_pSinbadNode->getPosition()*Vector3(1.0f,0.0f, 1.0f));
m_fJumpTime= 0.0f;
}
}
//****************走动
if(Vector3::ZERO!=mTranslateVector){ //有走动
m_moveVector= Vector3::ZERO;
m_moveVector+= mTranslateVector.x*m_pSinbadNode->getOrientation().xAxis();//x方向的走动
m_moveVector+= mTranslateVector.z*m_pSinbadNode->getOrientation().zAxis();//z方向的走动
m_moveVector.y = 0.0f;
m_pSinbadNode->translate(m_moveVector);
m_pCameraNode->translate(m_moveVector);
}
moveCamera();//转动相机
returntrue;
}
void MyEntityFrameListener::createEntity()
{
//创建地面
Planeplane(Vector3::UNIT_Y, -15);//通过法向量与恒定数创建一个Plane
MeshManager::getSingleton().createPlane("GrassPlane",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//宽度,高度
200, 200, //x方向段值,y方向段值,即面板分成多少个三角形
true, //创建一个垂直的法向量到面板
1, 5, 5, Vector3::UNIT_Z);//2D纹理坐标设置的数量,在u,v方向重复的瓦片的数量,纹理方向
Entity*pEnt =mCamera->getSceneManager()->createEntity("GrassPlane","GrassPlane");
mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("GrassPlane")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");//设置材质 Examples/GrassFloor
//添加阴影
mCamera->getSceneManager()->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
//创建模型实体
m_pSinbadEnt= mCamera->getSceneManager()->createEntity("Sinbad1","Sinbad.mesh");
m_pSinbadNode= mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("Sinbad1");
m_pSinbadNode->attachObject(m_pSinbadEnt);
m_pSinbadNode->setPosition(Vector3(500.0f,0.0f, 0.0f));//模型实体位置
m_pSinbadNode->setScale(3.0, 3.0, 3.0);
m_pSinbadEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);//骨架混合模式
//添加武器剑
m_pSword1= mCamera->getSceneManager()->createEntity("Sword1","Sword.mesh");
m_pSword2= mCamera->getSceneManager()->createEntity("Sword2","Sword.mesh");
m_pSinbadEnt->attachObjectToBone("Handle.L",m_pSword1);//将剑实体关联到骨骼
m_pSinbadEnt->attachObjectToBone("Handle.R",m_pSword2);//将剑实体关联到骨骼
//创建丝带
NameValuePairListparams;
params["numberOfChains"] ="2";
params["maxElements"] ="80";
m_pSwordTrail= (RibbonTrail*)mCamera->getSceneManager()->createMovableObject("RibbonTrail", ¶ms);
m_pSwordTrail->setMaterialName("Examples/LightRibbonTrail");
m_pSwordTrail->setTrailLength(20);
mCamera->getSceneManager()->getRootSceneNode()->attachObject(m_pSwordTrail);//将丝带关联到Root节点
for(inti = 0; i < 2;i++){
m_pSwordTrail->setInitialColour(i,1, 0.8, 0);
m_pSwordTrail->setColourChange(i,0.75, 1.25, 1.25, 1.25);
m_pSwordTrail->setWidthChange(i,1);
m_pSwordTrail->setInitialWidth(i,0.5);
}
m_pSwordTrail->setVisible(true);
m_pSwordTrail->addNode(m_pSword1->getParentNode());
m_pSwordTrail->addNode(m_pSword2->getParentNode());
//迭代所有动画
AnimationStateSet*pAnimSet =m_pSinbadEnt->getAllAnimationStates();
AnimationStateIteratoranimIter =pAnimSet->getAnimationStateIterator();
while(animIter.hasMoreElements()){
//std::cout<< animIter.getNext()->getAnimationName() << std::endl;
//animIter.getNext()->setLoop(true);
m_pAniState= pAnimSet->getAnimationState(animIter.getNext()->getAnimationName());
m_pAniState->setLoop(true);
}
m_pAniState= m_pSinbadEnt->getAnimationState("HandsClosed");
m_pAniState->setEnabled(true);
// **创建关联相机的节点
//确定相机节点位置,相机节点位置不是相机的位置
Vector3vPos =m_pSinbadNode->getPosition();
RealfRadius =m_pSinbadEnt->getBoundingRadius();
Vector3cameraNodePos(vPos.x,vPos.y, vPos.z-fRadius);//相机节点位置在模型实体后面
m_pCameraNode= mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode("myCameraNode");
m_pCameraNode->attachObject(mCamera); //相机节点绑定相机
m_pCameraNode->setPosition(cameraNodePos);//相机节点位置
m_pCameraNode->lookAt(vPos,Node::TS_WORLD);//相机节点看的位置,要使相机能绕m_pSinbadNode节点转,必须在
//此设置lookAt,但是此m_pCameraNode节点还是绕着自己所在点转
m_pCameraNode->setFixedYawAxis(true);
mCamera->setFixedYawAxis(true);
//关联的实体在自己所处点转动,而相机绕着主实体运动
Entity*pSinbadEnt111 =mCamera->getSceneManager()->createEntity("Sinbad12122","Sinbad.mesh");
pSinbadEnt111->setMaterialName("drbunsen_head");
m_pCameraNode->attachObject(pSinbadEnt111);
}
6:Animating.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplication app;
app.go();
return 0;
}
五:场景管理,创建一个与默认场景管理不同的管理,创建平板和实体,创建一个手工对象实体草叶等,使用三角形类型
创建实体,使用点索引构成三角形创建实体,使用静态几何类添加实体, 载入地图等.
(程序为游戏类编程/Ogre/Ogre1.73/SceneManagers)
1:新建一个空的 win32控制台应用程序,命名为:SceneManagers
2:添加一个 SceneManagers.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
class MyEntityFrameListener:public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false, bool bufferedMouse = false,boolbufferedJoy= false);
~MyEntityFrameListener(void);
public:
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
voidmoveCamera();//移动相机
virtualboolframeEnded(constFrameEvent&evt);//循环刷新界面
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RenderWindow*win,Camera*cam,bool bufferedKeys,boolbufferedMouse,boolbufferedJoy)
: ExampleFrameListener(win,cam, bufferedKeys,bufferedMouse,bufferedJoy)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
mTranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
mTranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
mTranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
mTranslateVector.z =moveScale; //Move camerabackward
break;
caseOIS::KC_PGUP:
mTranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
mTranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//释放按下的键
{
mTranslateVector= Vector3::ZERO;//防止按键释放后还继续移动相机
returntrue;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
mRotX= Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
mRotY= Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
}
returntrue;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
void MyEntityFrameListener::moveCamera() //移动相机
{
mCamera->yaw(mRotX); //绕Y轴转动
mCamera->pitch(mRotY);//绕X轴转动
mCamera->moveRelative(mTranslateVector);//移动相机
mRotX= mRotY = 0; //防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
//ExampleFrameListener::frameEnded(evt);//可以不用
moveCamera();//移动相机
returntrue;
}
5:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
virtualvoidchooseSceneManager(void);//创建一个与默认场景管理不同的管理
voidcreatePlaneAndEntity();//创建平板和实体,创建一个手工对象实体草叶等
voidcreateEntity1();//使用三角形类型创建实体
voidcreateEntity2();//使用点索引构成三角形创建实体,使用静态几何类添加实体.
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort= mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
std::cout <<mSceneMgr->getTypeName() <<"::"<< mSceneMgr->getName() <<std::endl;
//打印出场景管理类型名称和场景名称
createPlaneAndEntity();//创建平板和实体,创建一个手工对象实体草叶等
createEntity1();//使用三角形类型创建实体
createEntity2();//使用点索引构成三角形创建实体,使用静态几何类添加实体
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::chooseSceneManager(void)//创建一个与默认场景管理不同的管理,BspSceneManager
{
//ResourceGroupManager::getSingleton().addResourceLocation("media/packs/Sinbad.zip","Zip", "Popular");
//ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
constStringresGroupName= ResourceGroupManager::getSingleton().getWorldResourceGroupName();
ResourceGroupManager::getSingleton().addResourceLocation("media/packs/chiropteraDM.pk3","Zip", ResourceGroupManager::getSingleton().getWorldResourceGroupName(),true);
ResourceGroupManager::getSingleton().initialiseResourceGroup(ResourceGroupManager::getSingleton().getWorldResourceGroupName());
mSceneMgr= mRoot->createSceneManager("BspSceneManager");//默认为:mRoot->createSceneManager(ST_GENERIC,"ExampleSMInstance");
mSceneMgr->setWorldGeometry("maps/chiropteradm.bsp"); //载入地图
}
void MyExampleApplication::createPlaneAndEntity()//创建平板和实体,创建一个手工对象实体草叶等
{
//创建plane(面板)
Ogre::Planeplane(Vector3::UNIT_Y,-10);//通过法向量与恒定数创建一个Plane
Ogre::MeshManager::getSingleton().createPlane("GrassPlane",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,plane,
1500, 1500,//宽度,高度
200, 200, //x方向段值,y方向段值,即面板分成多少个三角形
true, //创建一个垂直的法向量到面板
1, 5, 5, Vector3::UNIT_Z);//2D纹理坐标设置的数量,在u,v方向重复的瓦片的数量,纹理方向
Ogre::Entity*pEnt = mSceneMgr->createEntity("GrassPlane","GrassPlane");
mSceneMgr->getRootSceneNode()->createChildSceneNode("GrassPlane")->attachObject(pEnt);
pEnt->setMaterialName("Examples/BeachStones");//设置材质 Examples/GrassFloor
}
void MyExampleApplication::createEntity1()//使用三角形类型创建实体
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("GrassBlades1");//创建一个手工对象草叶
pManual->begin("Examples/GrassBlades",RenderOperation::OT_TRIANGLE_LIST);//三角类型
//添加第一个三角形
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(0,1);
//添加第二个三角形
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
//添加第三个三角形
pManual->position(2.5, 0.0, 4.3);
pManual->textureCoord(1,1);
pManual->position(-2.5, 10.0, -4.3);
pManual->textureCoord(0,0);
pManual->position(-2.0, 0.0, -4.3);
pManual->textureCoord(0,1);
//添加第四个三角形
pManual->position(2.5, 0.0, 4.3);
pManual->textureCoord(1,1);
pManual->position(2.5, 10.0, 4.3);
pManual->textureCoord(1,0);
pManual->position(-2.5, 10.0, -4.3);
pManual->textureCoord(0,0);
//添加第五个三角形
pManual->position(2.5, 0.0, -4.3);
pManual->textureCoord(1,1);
pManual->position(-2.5, 10.0, 4.3);
pManual->textureCoord(0,0);
pManual->position(-2.0, 0.0, 4.3);
pManual->textureCoord(0,1);
//添加第六个三角形
pManual->position(2.5, 0.0, -4.3);
pManual->textureCoord(1,1);
pManual->position(2.5, 10.0, -4.3);
pManual->textureCoord(1,0);
pManual->position(-2.5, 10.0, 4.3);
pManual->textureCoord(0,0);
pManual->end();
//Ogre::SceneNode*pGrassNode =mSceneMgr->getRootSceneNode()->createChildSceneNode("GrassBlades");
//pGrassNode->attachObject(pManual);
pManual->convertToMesh("BladesOfGrass1");//将一个手工对象转为网格
for(inti=0; i<20; i++){
for(intj=0; j<20; j++){
Ogre::Entity *pEnt =mSceneMgr->createEntity("BladesOfGrass1");//通过转换的网格创建实体
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(i*3,-10,j*3));
pNode->attachObject(pEnt);
}
}
}
void MyExampleApplication::createEntity2()//使用点索引构成三角形创建实体,使用静态几何类添加实体.
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("GrassBlades2");//创建一个手工对象草叶
pManual->begin("Examples/GrassBlades",RenderOperation::OT_TRIANGLE_LIST);//三角类型
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(0,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(2.5, 0.0, 4.3);
pManual->textureCoord(1,1);
pManual->position(-2.5, 10.0, -4.3);
pManual->textureCoord(0,0);
pManual->position(-2.0, 0.0, -4.3);
pManual->textureCoord(0,1);
pManual->position(2.5, 10.0, 4.3);
pManual->textureCoord(1,0);
pManual->position(2.5, 0.0, -4.3);
pManual->textureCoord(1,1);
pManual->position(-2.5, 10.0, 4.3);
pManual->textureCoord(0,0);
pManual->position(-2.0, 0.0, 4.3);
pManual->textureCoord(0,1);
pManual->position(2.5, 10.0, -4.3);
pManual->textureCoord(1,0);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->index(4);
pManual->index(5);
pManual->index(6);
pManual->index(4);
pManual->index(7);
pManual->index(5);
pManual->index(8);
pManual->index(9);
pManual->index(10);
pManual->index(8);
pManual->index(11);
pManual->index(9);
pManual->end();
//Ogre::SceneNode*pGrassNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("GrassBlades");
//pGrassNode->attachObject(pManual);
pManual->convertToMesh("BladesOfGrass2");//将一个手工对象转为网格
Ogre::StaticGeometry *pField=mSceneMgr->createStaticGeometry("FieldOfGrass");//静态几何类
for(inti=30;i<50;i++){
for(intj=30;j<50;j++){
Ogre::Entity *pEnt =mSceneMgr->createEntity("BladesOfGrass2");
pField->addEntity(pEnt,Ogre::Vector3(i*3,-10,j*3));
}
}
pField->build();
}
6:SceneManagers.cpp的内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationapp;
app.go();
return0;
}
六:材质 (程序为游戏类编程/Ogre/Ogre1.73/Materials)
1:新建一个空的 win32控制台应用程序,命名为:Materials
2:添加一个 Materials.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyEntityFrameListener,内容与 五 中的MyEntityFrameListener一致
5:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
voidcreateManual();//重复纹理,边缘纹理,边框纹理,镜像纹理,滚动纹理
voidcreateManual1();//旋转纹理
voidcreateShader1();//纹理着色
voidcreateShader2();//颜色着色
voidsetEntMaterial();//给实体设置自定义的材质
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort= mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
//mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
//createManual();//重复纹理,边缘纹理,边框纹理,镜像纹理,滚动纹理
//createManual1();//旋转纹理
//createShader1();//纹理着色
//createShader2();//颜色着色
setEntMaterial();//给实体设置自定义的材质
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::createManual()//重复纹理,边缘纹理,边框纹理,镜像纹理,滚动纹理
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial5",RenderOperation::OT_TRIANGLE_LIST);//BaseWhiteNoLighting
/*
//构造四个点,以及四个点的纹理,用于重复纹理,边缘纹理,边框纹理,镜像纹理,纹理坐标大于1,为2
pManual->position(5.0,0.0, 0.0);
pManual->textureCoord(0,2);
pManual->position(-5.0,10.0, 0.0);
pManual->textureCoord(2,0);
pManual->position(-5.0,0.0, 0.0);
pManual->textureCoord(2,2);
pManual->position(5.0,10.0, 0.0);
pManual->textureCoord(0,0);
*/
//纹理坐标小于1块纹理,用于滚动纹理
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,0.2);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(0.2,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(0.2,0.2);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
//通过点索引构造两个三角形
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");//将手工对象转为Mesh
//通过Mesh创建实体
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createManual1()//旋转纹理
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial6",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,1);
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
//pEnt->setMaterialName("myMaterial7");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createShader1() //纹理着色
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial9",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->textureCoord(0,1);//纹理坐标
pManual->position(-5.0, 10.0, 0.0);
pManual->textureCoord(1,0);
pManual->position(-5.0, 0.0, 0.0);
pManual->textureCoord(1,1);
pManual->position(5.0, 10.0, 0.0);
pManual->textureCoord(0,0);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::createShader2()//颜色着色
{
Ogre::ManualObject *pManual=mSceneMgr->createManualObject("Quad");
pManual->begin("myMaterial10",RenderOperation::OT_TRIANGLE_LIST);
pManual->position(5.0, 0.0, 0.0);
pManual->colour(0, 0, 1);
pManual->position(-5.0, 10.0, 0.0);
pManual->colour(0, 1, 0);
pManual->position(-5.0, 0.0, 0.0);
pManual->colour(0, 1, 0);
pManual->position(5.0, 10.0, 0.0);
pManual->colour(0, 0, 1);
pManual->index(0);
pManual->index(1);
pManual->index(2);
pManual->index(0);
pManual->index(3);
pManual->index(1);
pManual->end();
pManual->convertToMesh("Quad");
Ogre::Entity *pEnt =mSceneMgr->createEntity("Quad");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
}
void MyExampleApplication::setEntMaterial()//给实体设置自定义的材质
{
Ogre::Entity *pEnt =mSceneMgr->createEntity("Entity1","Sinbad.mesh");
pEnt->setMaterialName("myMaterial11");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
pNode->scale(6.0, 6.0, 6.0);
}
//myMaterial.material, Ogre3DBeginnersGuideShaders.cg
6:myMaterial.material的内容:
//材质
//给材质命名
material myMaterial
{
//技术
technique
{
//通道
pass
{
//关闭灯光
lighting off
//场景混合,alpha混合
scene_blend alpha_blend
depth_write off
//漫反射顶点颜色
diffuse vertexcolor
texture_unit
{
texture terr_rock6.jpg//leaf.png
tex_address_mode clamp
}
}
}
}
/*四块纹理,用于重复纹理,边缘纹理,边框纹理,镜像纹理,纹理坐标大于1,为2
textureCoord(0,2);
textureCoord(2,0);
textureCoord(2,2);
textureCoord(0,0);
*/
//在大于1块纹理时,多余的纹理部分,重复模式纹理(重复绘制纹理)
material myMaterial1
{
technique
{
pass
{
texture_unit
{
texture leaf.png
}
}
}
}
//在大于1块纹理时,多余的纹理部分,材质不拉伸,材质边缘延伸填充
material myMaterial2
{
technique
{
pass
{
texture_unit
{
texture terr_rock6.jpg
//材质不拉伸,材质边缘延伸填充
tex_address_mode clamp
}
}
}
}
//在大于1块纹理时,多余的纹理部分由纹理边框产生
material myMaterial3
{
technique
{
pass
{
texture_unit
{
texture leaf.png
//边框模式,多余的纹理部分由边框产生
tex_address_modeborder
tex_border_colour 1.00.0 0.0
}
}
}
}
//在大于1块纹理时,多余的纹理部分,镜像产生
material myMaterial4
{
technique
{
pass
{
texture_unit
{
texture leaf.png
//镜像模式
tex_address_modemirror
}
}
}
}
/*纹理坐标小于1块纹理,用于滚动纹理
textureCoord(0,0.2);
textureCoord(0.2,0);
textureCoord(0.2,0.2);
textureCoord(0,0);
*/
//滚动纹理
material myMaterial5
{
technique
{
pass
{
texture_unit
{
texture leaf.png
scroll 0.8 0.8
scroll_anim 0.1 0.1
}
}
}
}
/*
textureCoord(0,1);
textureCoord(1,0);
textureCoord(1,1);
textureCoord(0,0);
*/
//旋转纹理
material myMaterial6
{
technique
{
pass
{
texture_unit
{
texture leaf.png
rotate_anim 0.1
}
}
}
}
//材质可以继承,继承上一期纹理的滚动属性
material myMaterial7 : myMaterial6
{
set_texture_alias texture1Water02.jpg
}
//******************纹理着色1*************************************************//
//片段着色
fragment_program MyFragmentShader1 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader1A
profiles ps_2_0 arbfp1
}
//顶点着色
vertex_program MyVertexShader1 cg
{
//嵌入一段cg程序
source Ogre3DBeginnersGuideShaders.cg
//指出该cg程序的入口函数,按cg标准,缺省入口为main
entry_point MyVertexShader1A
//D3D vs_1_1 标准,或openglarbvp1标准,Ogre自动检查是硬件是否支持
profiles vs_2_0 arbvp1
default_params
{
param_named_auto worldViewMatrixworldviewproj_matrix
/**
//下列参数为传入顶点的参数
param_named_autoworldViewProj worldviewproj_matrix //世界坐标矩阵
param_named_auto ambientambient_light_colour //环境光
param_named_autoobjSpaceLight light_position_object_space 0 //灯的位置
param_named_autolightColour light_diffuse_colour 0 //灯的颜色
param_named_auto offsetcustom 999 //offset特定参数,由程序设定
**/
}
}
material myMaterial8
{
technique
{
pass
{
vertex_program_refMyVertexShader1
{
}
fragment_program_refMyFragmentShader1
{
}
/*
alpha_rejection greater150 //alpha 使用的距离范围
scene_blendalpha_blend //场景混合方式为alpha
cull_hardware none //关闭硬件精细化
cull_software none //关闭软件精细化
*/
//贴图
texture_unit
{
texturegrass_1024.jpg
}
}
}
//如果显示卡不支持顶点程序,系统会选择使用下面的技术通道(普通贴图)
technique
{
pass
{
alpha_rejection greater150
scene_blend alpha_blend
cull_hardware none
cull_software none
texture_unit
{
texture gras_02.png
}
}
}
}
//******************纹理着色2*************************************************//
vertex_program MyVertexShader2 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader2A
profiles vs_2_0 arbvp1
default_params
{
param_named_autoworldViewMatrix worldviewproj_matrix
}
}
material myMaterial9
{
technique
{
pass
{
vertex_program_refMyVertexShader2
{
}
fragment_program_refMyFragmentShader1
{
}
texture_unit
{
textureterr_rock6.jpg
}
}
}
}
//******************颜色着色3*************************************************//
/**
pManual->colour(0, 0, 1);
pManual->colour(0, 1, 0);
pManual->colour(0, 1, 0);
pManual->colour(0, 0, 1);
**/
fragment_program MyFragmentShader3 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader3A
profiles ps_2_0 arbfp1
}
vertex_program MyVertexShader3 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader3A
profiles vs_2_0 arbvp1
default_params
{
param_named_auto worldViewMatrixworldviewproj_matrix
}
}
material myMaterial10
{
technique
{
pass
{
vertex_program_refMyVertexShader3
{
}
fragment_program_refMyFragmentShader3
{
}
}
}
}
//******************用于模型材质着色*************************************************//
fragment_program MyFragmentShader4 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_pointMyFragmentShader4A
profiles ps_2_0 arbfp1
}
vertex_program MyVertexShader4 cg
{
source Ogre3DBeginnersGuideShaders.cg
entry_point MyVertexShader4A
profiles vs_2_0 arbvp1
default_params
{
param_named_autoworldViewMatrix worldviewproj_matrix
//添加脉冲,系统内部变量使用param_named_auto
param_named_auto pulseTimetime
//自定义变量offset,前面只能用param_named
param_named offset float40.3 0.85 0.7 1
}
}
material myMaterial11
{
technique
{
pass
{
vertex_program_refMyVertexShader4
{
}
fragment_program_refMyFragmentShader4
{
}
texture_unit
{
texture leaf.png
}
}
}
}
7:Ogre3DBeginnersGuideShaders.cg的内容:
//****************纹理着色1*************************************//
//***片段着色
//half4 MyFragmentShader1A() : COLOR //这个是可以的,当有无纹理时都可以使用
//{
// half4 oColour =float4(0.0f, 0.0f, 1.0f, 0.0f);
// return oColour;
//}
//void MyFragmentShader1A(out float4 color:COLOR) //这个是可以的,当有无纹理时都可以使用
//{
// color = float4(0.0f, 0.5f,0.0f, 0.0f);
//}
void MyFragmentShader1A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
color =float4(temp_color.r+0.2, temp_color.g+0.3, temp_color.b+0.7, 0);
}
//***片段着色
//***顶点着色
void MyVertexShader1A(float4 position : POSITION, out float4oPosition : POSITION,
uniformfloat4x4 worldViewMatrix)
{
oPosition =mul(worldViewMatrix, position);
oPosition.z += oPosition.x;
oPosition.y += oPosition.x;
}
//****************纹理着色2*************************************//
void MyVertexShader2A(float4 position:POSITION, out float4oPosition:POSITION,
float2uv:TEXCOORD0, out float2 oUv:TEXCOORD0, uniform float4x4 worldViewMatrix)
{
oPosition = mul(worldViewMatrix,position);
oPosition.z += oPosition.x;
oPosition.y += oPosition.x;
oUv = uv+0.1;
}
//******************颜色着色3*************************************************//
void MyFragmentShader3A(float4 color : COLOR, out float4 oColor :COLOR)
{
oColor = color;
oColor.b = 0.5;
}
void MyVertexShader3A(float4 position:POSITION, out float4oPosition:POSITION,
float4color:COLOR, out float4 ocolor:COLOR, uniform float4x4 worldViewMatrix)
{
oPosition =mul(worldViewMatrix, position);
ocolor = color;
ocolor.b = 0.2;
}
//******************用于模型材质着色*************************************************//
void MyFragmentShader4A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
color =float4(temp_color.r+0.7, temp_color.g+0.5, temp_color.b+0.2, 0);
}
void MyVertexShader4A(uniform float pulseTime, float4position:POSITION, out float4 oPosition:POSITION,
float2uv:TEXCOORD0, out float2 oUv:TEXCOORD0, uniform float4x4 worldViewMatrix
,uniformfloat4 offset)
{
oPosition =mul(worldViewMatrix, position);
oPosition.x *=(2+sin(pulseTime));
oPosition *= offset;
oUv = uv;
}
//******************其它程序用于计算顶点摇摆的,在此不使用,保留****************************************//
//对每个顶点计算摇摆位置及颜色
/**
void grass_vp(float4 position : POSITION, //程序入口,参数在材料脚本确定
float3 normal : NORMAL,
float2 uv : TEXCOORD0,
out float4 oPosition :POSITION,
out float2 oUv : TEXCOORD0,
out float4 colour : COLOR,
uniform float4x4worldViewProj,
uniform float4 ambient,
uniform float4objSpaceLight,
uniform float4lightColour,
uniform float4 offset)
{
float4 mypos = position; //取得点的位置
//offset = float4(0.5, 0, 0, 0);
mypos = mypos + offset * mypos.yyyy; //位置偏移随y高度线性增加
oPosition = mul(worldViewProj, mypos); //变换为全局坐标
oUv = uv; //贴图UV
// get vertex light direction (support directional and point)
float3 light = normalize(
objSpaceLight.xyz - (position.xyz * objSpaceLight.w)); //计算入射光,主要反映用于Grass场景中的动态灯光
float diffuseFactor = max(dot(normal, light), 0); //由法线及入射光夹角,计算出反射光强度
colour = ambient + diffuseFactor * lightColour; //由场景光,及反射光强及颜色,计算出最终的顶点色彩
//这样,图形GPU将运行该CG程序,快速计算出顶点的位置及颜色及贴图坐标。
}
**/
七:组合材质以及视口的实现,组合材质设置参数,组合监听等
(程序为游戏类编程/Ogre/Ogre1.73/CompositorFramework)
1:新建一个空的 win32控制台应用程序,命名为:CompositorFramework
2:添加一个 CompositorFramework.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyEntityFrameListener,内容与 五 中的MyEntityFrameListener一致
5:添加一个 材质组合类,用于设置材质参数等:MyCompositorListener
MyCompositorListener.h:
//材质组合监听类,组合材质仅仅针对视口使用
#ifndef _MyCompositorListener_H_
#define _MyCompositorListener_H_
#include
using namespaceOgre;
class MyCompositorListener: public CompositorInstance::Listener
{
public:
MyCompositorListener(void);
~MyCompositorListener(void);
voidnotifyMaterialSetup(uint32pass_id,MaterialPtr&mat);
//virtualvoid notifyMaterialRender(uint32 pass_id, MaterialPtr &mat);
protected:
int m_index;
};
#endif
MyCompositorListener.cpp:
#include
#include "MyCompositorListener.h"
MyCompositorListener::MyCompositorListener(void)
{
m_index= 0;
}
MyCompositorListener::~MyCompositorListener(void)
{
}
void MyCompositorListener::notifyMaterialSetup(uint32pass_id,MaterialPtr&mat)
{
if(1 == m_index){//第二个pass里面才有下面两个参数,两个pass的pass_id都是0???
mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()->setNamedConstant("numpixels",1250.0f);
mat->getBestTechnique()->getPass(pass_id)->getFragmentProgramParameters()->setNamedConstant("factors",Vector3(1.0f, 0.0f, 0.0f));
}
m_index++;
}
6:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
#include "MyCompositorListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
voidcompositor();//组合,组合材质仅仅针对视口使用
voidcreateCamera(); //添加分屏,添加2个相机
voidcreateViewports();//添加分屏,添加3个视口
private:
MyEntityFrameListener*m_pFrameLst;
MyCompositorListener *m_pCompositorLst;
Ogre::Camera *mCamera2;
Ogre::Viewport *pVp1;
Ogre::Viewport *pVp2;
Ogre::Viewport *pVp3;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
m_pCompositorLst= NULL;
pVp1= NULL;
pVp2= NULL;
pVp3= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
if (NULL !=m_pCompositorLst){
deletem_pCompositorLst;
m_pCompositorLst= NULL;
}
//视口不在本类中释放空间
if (NULL !=pVp1){
pVp1= NULL;
}
if (NULL !=pVp2){
pVp2= NULL;
}
if (NULL !=pVp3){
pVp3= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort= mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 100.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
compositor();//组合,组合材质仅仅针对视口使用
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera,true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::compositor() //组合,组合材质仅仅针对视口使用,myMaterial.material, myCg.cg
{
Ogre::Entity *pEnt =mSceneMgr->createEntity("Entity1","Sinbad.mesh");
Ogre::SceneNode *pNode=mSceneMgr->getRootSceneNode()->createChildSceneNode("Node1");
pNode->attachObject(pEnt);
pNode->scale(3.0f, 3.0f, 3.0f);
CompositorManager::getSingleton().addCompositor(pVp1,"Compositor4");
CompositorManager::getSingleton().setCompositorEnabled(pVp1,"Compositor4",true);
//为视口的材质组合添加监听
m_pCompositorLst= new MyCompositorListener();
CompositorInstance*pComp =CompositorManager::getSingleton().getCompositorChain(pVp1)->getCompositor("Compositor4");
pComp->addListener(m_pCompositorLst);
}
void MyExampleApplication::createCamera()//添加分屏,添加2个相机
{
mCamera= mSceneMgr->createCamera("MyCamera1");
mCamera->setPosition(0,10,20);
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(5);
mCamera2= mSceneMgr->createCamera("MyCamera2");
mCamera2->setPosition(20,10,0);
mCamera2->lookAt(0,0,0);
mCamera2->setNearClipDistance(5);
}
void MyExampleApplication::createViewports()//添加分屏,添加3个视口
{
//一个相机mCamera可以创建多个视口,并且添加的各个视口的ZOrder必须唯一
pVp1= mWindow->addViewport(mCamera, 0, 0.0, 0.0, 0.5, 0.5);
pVp1->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
pVp2= mWindow->addViewport(mCamera, 1, 0.0, 0.5, 0.5, 1.0);
pVp2->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
pVp3= mWindow->addViewport(mCamera2, 3, 0.5, 0.0, 0.5, 1.0);
pVp3->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
//设置相机长宽比
mCamera->setAspectRatio(Real(pVp1->getActualWidth())/Real(pVp1->getActualHeight()));
mCamera2->setAspectRatio(Real(pVp3->getActualWidth())/Real(pVp3->getActualHeight()));
}
//myMaterial.material, myCg.cg
7:myMaterial.material的内容:
//****片段着色与 材质 与 组合
fragment_program MyFragmentShader1 cg
{
source myCg.cg
entry_pointMyFragmentShader1A
profiles ps_2_0 arbfp1
}
material Ogre3DBeginnersGuide/Comp1
{
technique
{
pass
{
fragment_program_refMyFragmentShader1
{
}
texture_unit
{
}
}
}
}
compositor Compositor1
{
technique
{
//定义可以修改的对象
texture scenetarget_width target_height PF_R8G8B8
//继承先前的场景,没有先前的场景会一片空白,targetscene的scene对应texture scene的scene
target scene
{
input previous
}
//定义合成语言的输出
target_output
{
//不需要任何输入
input none
//渲染,需要材质和场景
pass render_quad
{
materialOgre3DBeginnersGuide/Comp1
input 0 scene
}
}
}
}
//****片段着色与 材质 与 多个组合和在一起
fragment_program MyFragmentShader2 cg
{
source myCg.cg
entry_pointMyFragmentShader2A
profiles ps_2_0 arbfp1
}
material Ogre3DBeginnersGuide/Comp2
{
technique
{
pass
{
fragment_program_refMyFragmentShader2
{
}
texture_unit
{
}
}
}
}
compositor Compositor2
{
technique
{
texture scene target_widthtarget_height PF_R8G8B8
texture temp target_width target_height PF_R8G8B8
target scene
{
input previous
}
target temp
{
pass render_quad
{
materialOgre3DBeginnersGuide/Comp1
input 0 scene
}
}
target_output
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp2
input 0 temp
}
}
}
}
//****片段着色与 材质 与 自身重复组合
fragment_program MyFragmentShader3 cg
{
source myCg.cg
entry_pointMyFragmentShader3A
profiles ps_2_0 arbfp1
}
material Ogre3DBeginnersGuide/Comp3
{
technique
{
pass
{
fragment_program_refMyFragmentShader3
{
}
texture_unit
{
}
}
}
}
compositor Compositor3
{
technique
{
texture scene target_widthtarget_height PF_R8G8B8
target scene
{
input previous
}
target scene
{
pass render_quad
{
material Ogre3DBeginnersGuide/Comp2
input 0 scene
}
}
target_output
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp3
input 0 scene
}
}
}
}
//****片段着色与 材质 与 组合,在材质中添加像素数量等参数*******//
fragment_program MyFragmentShader4 cg
{
source myCg.cg
entry_pointMyFragmentShader4A
profiles ps_2_0 arbfp1
//传递给MyFragmentShader4A的参数,数字越大越清晰
default_params
{
param_named numpixelsfloat 50
param_named factors float4 0.2 0.6 0.3 0
}
}
material Ogre3DBeginnersGuide/Comp4
{
technique
{
pass
{
fragment_program_refMyFragmentShader4
{
}
texture_unit
{
}
}
}
}
compositor Compositor4
{
technique
{
texture scene target_widthtarget_height PF_R8G8B8
target scene
{
input previous
}
target scene
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp2
input 0 scene
}
}
target_output
{
input none
pass render_quad
{
materialOgre3DBeginnersGuide/Comp4
input 0 scene
}
}
}
}
8:myCg.cg的内容:
//以下为片段着色程序,片断着色程序对每个片断进行独立的颜色计算,最后输出颜色值的就是该片段最终显示的颜色。
//可以这样说,顶点着色程序主要进行几何方面的运算,而片段着色程序主要针对最终的颜色值进行计算。
void MyFragmentShader1A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
color =float4(1.0-temp_color.r, 1.0-temp_color.g, 1.0-temp_color.b, 0);
}
void MyFragmentShader2A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color =tex2D(texture, uv);
float greyvalue =temp_color.r*0.3 + temp_color.g*0.59 + temp_color.b*0.11;
color =float4(greyvalue,greyvalue,greyvalue,0);
}
void MyFragmentShader3A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture)
{
float4 temp_color = tex2D(texture,uv);
color =float4(temp_color.r+0.5, temp_color.g+0.2, temp_color.b+0.3, 0);
}
//在材质中添加像素数量numpixels和一个颜色通道(修改颜色值)
void MyFragmentShader4A(float2 uv:TEXCOORD0, out float4 color:COLOR,uniform sampler2D texture, uniform float numpixels, uniform float4 factors)
{
//float num = 50;
float num = numpixels;
float stepsize = 1.0/ num;
//floor楼面处理,numpixels越大越清晰,越小越不清晰
float2 fragment =float2(stepsize*floor(uv.x*num), stepsize*floor(uv.y*num));
color = tex2D(texture,fragment);
color *= factors;
}
八:实现类似于 Ogre的 ExampleApplication 与 ExampleFrameListener 的类
(程序为 游戏类编程/Ogre/Ogre1.73/Startup)
1:新建一个空的 win32控制台应用程序,命名为:Startup
2:添加一个 Startup.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyFrameListener
MyFrameListener.h:
#ifndef _MyFrameListener_H_
#define _MyFrameListener_H_
#include
using namespaceOgre;
#define OIS_DYNAMIC_LIB
#include
class MyFrameListener:public FrameListener,publicOIS::KeyListener,public OIS::MouseListener,public WindowEventListener
{
public:
MyFrameListener(RenderWindow*win, Camera* cam, bool bufferedKeys =false,bool bufferedMouse= false, bool bufferedJoy = false);
~MyFrameListener(void);
public:
//键盘事件
virtualboolkeyPressed(constOIS::KeyEvent &arg);
virtualboolkeyReleased(constOIS::KeyEvent &arg);
//鼠标事件
virtualboolmouseMoved(constOIS::MouseEvent &arg);
virtualboolmousePressed(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
virtualboolmouseReleased(constOIS::MouseEvent &arg,OIS::MouseButtonIDid);
//帧事件
virtualboolframeStarted(constOgre::FrameEvent&evt);
virtualboolframeRenderingQueued(constOgre::FrameEvent&evt);
virtualboolframeEnded(constOgre::FrameEvent&evt);
//移动相机
virtualvoidmoveCamera();
//渲染窗口事件
virtualvoidwindowResized(RenderWindow*rw);
virtualvoidwindowClosed(RenderWindow*rw);
protected:
// OIS输入控制对象
OIS::InputManager *m_pInputMgr;
OIS::Keyboard *m_pKeyboard;
OIS::Mouse *m_pMouse;
OIS::JoyStick *m_pJoy;
//渲染窗口和相机
Ogre::RenderWindow *m_pWindow;
Ogre::Camera *m_pCamera;
//相机移动转动事件
Ogre::Vector3m_TranslateVector;
Ogre::Radianm_RotX;
Ogre::Radianm_RotY;
bool m_bSysMouseShowFlag;//是否显示鼠标
};
#endif
MyFrameListener.cpp:
#include "MyFrameListener.h"
MyFrameListener::MyFrameListener(RenderWindow*win, Camera*cam, bool bufferedKeys, boolbufferedMouse,boolbufferedJoy)
: m_pWindow(win),m_pCamera(cam),m_TranslateVector(0.0f,0.0f, 0.0f), m_RotY(0), m_RotX(0)
{
m_bSysMouseShowFlag = false;//用于解决鼠标独占
ShowCursor(0); //用于解决鼠标独占
//创建OIS键盘,鼠标,手柄等对象
unsignedintwindowHandle= 0;
std::ostringstreamwindowHandleString;
win->getCustomAttribute("WINDOW",&windowHandle);
windowHandleString<< windowHandle;
OIS::ParamListparameters;
parameters.insert(std::make_pair(std::string("WINDOW"),windowHandleString.str()));
parameters.insert(std::make_pair(std::string("w32_mouse"),
std::string("DISCL_FOREGROUND"))); //用于解决鼠标独占
parameters.insert(std::make_pair(std::string("w32_mouse"),
std::string("DISCL_NONEXCLUSIVE")));//用于解决鼠标独占
m_pInputMgr= OIS::InputManager::createInputSystem(parameters);
m_pKeyboard= static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard,bufferedKeys));
m_pMouse= static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse,bufferedMouse));
try{
m_pJoy= static_cast<OIS::JoyStick*>(m_pInputMgr->createInputObject(OIS::OISJoyStick,bufferedJoy));
} catch(...){
m_pJoy= 0;
}
//以下键盘,鼠标回调函数需要在子类中被调用到,才会有keyPressed,mouseMoved等事件
m_pKeyboard->setEventCallback(this);
m_pMouse->setEventCallback(this);
//监听渲染窗口
WindowEventUtilities::addWindowEventListener(m_pWindow,this);
}
MyFrameListener::~MyFrameListener(void)
{
WindowEventUtilities::removeWindowEventListener(m_pWindow,this);//虚构时删除窗口的监听,渲染窗口关闭后,m_pWindow对应的值已经不存在
windowClosed(m_pWindow);
}
bool MyFrameListener::keyPressed(constOIS::KeyEvent&arg)
{
RealmoveScale = 0.2f;
switch(arg.key){
caseOIS::KC_A:
caseOIS::KC_LEFT:
m_TranslateVector.x = -moveScale;//Move camera left
break;
caseOIS::KC_D:
caseOIS::KC_RIGHT:
m_TranslateVector.x =moveScale; //Move camera RIGHT
break;
caseOIS::KC_W:
caseOIS::KC_UP:
m_TranslateVector.z = -moveScale;//Move camera forward
break;
caseOIS::KC_S:
caseOIS::KC_DOWN:
m_TranslateVector.z =moveScale;//Move camera backward
break;
caseOIS::KC_PGUP:
m_TranslateVector.y =moveScale; //Move camera up
break;
caseOIS::KC_PGDOWN:
m_TranslateVector.y = -moveScale;//Move camera down
break;
}
returntrue;
}
bool MyFrameListener::keyReleased(constOIS::KeyEvent&arg)
{
m_TranslateVector= Vector3::ZERO;//防止键释放后,相机还在移动
returntrue;
}
bool MyFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
//用于解决鼠标独占
if(arg.state.X.abs <m_pWindow->getViewport(0)->getActualLeft()+1
||(arg.state.Y.abs <m_pWindow->getViewport(0)->getActualTop()+1)
||(arg.state.X.abs >m_pWindow->getViewport(0)->getActualLeft()+m_pWindow->getViewport(0)->getActualWidth())
||(arg.state.Y.abs >m_pWindow->getViewport(0)->getActualTop()+m_pWindow->getViewport(0)->getActualHeight())){
if(!m_bSysMouseShowFlag){//鼠标移出界面
ShowCursor(1);
m_bSysMouseShowFlag=true;
}
} else{ //鼠标进入界面
if(m_bSysMouseShowFlag){
ShowCursor(0);
m_bSysMouseShowFlag= false;
}
}
if(!m_bSysMouseShowFlag){
constOIS::MouseState&ms =arg.state;
if(ms.buttonDown(OIS::MB_Left)){
} elseif(ms.buttonDown(OIS::MB_Right)) {
} else{
m_RotX= Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
m_RotY= Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
}
}
returntrue;
}
bool MyFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
returntrue;
}
bool MyFrameListener::frameStarted(constOgre::FrameEvent&evt)
{
if(NULL ==m_pWindow)returnfalse; //当窗口为NULL时,返回false,退出循环(Root->startRendering())
returntrue;
}
bool MyFrameListener::frameRenderingQueued(constOgre::FrameEvent&evt)
{
if(NULL !=m_pInputMgr){//捕捉键,鼠,手柄事件
m_pKeyboard->capture();
m_pMouse->capture();
if(m_pJoy)m_pJoy->capture();
}
returntrue;
}
bool MyFrameListener::frameEnded(constOgre::FrameEvent&evt)
{
moveCamera();//移动相机
returntrue;
}
void MyFrameListener::moveCamera()//移动相机
{
m_pCamera->pitch(m_RotX);
m_pCamera->yaw(m_RotY);
m_pCamera->moveRelative(m_TranslateVector);
m_RotX= m_RotY = 0.0f;
}
void MyFrameListener::windowResized(RenderWindow*rw)
{
}
void MyFrameListener::windowClosed(RenderWindow*rw)
{
if(rw ==m_pWindow)
{
if(m_pInputMgr)//释放键,鼠,手柄等对象
{
m_pInputMgr->destroyInputObject(m_pMouse);
m_pInputMgr->destroyInputObject(m_pKeyboard);
m_pInputMgr->destroyInputObject(m_pJoy);
OIS::InputManager::destroyInputSystem(m_pInputMgr);
m_pInputMgr= NULL;
}
m_pWindow= NULL;//窗口关闭时,此值置为NULL,用于退出循环(Root->startRendering())
}
}
5:添加一个类:MyApplication
MyApplication.h:
#ifndef _MyApplication_H_
#define _MyApplication_H_
#include "MyFrameListener.h"
#include
using namespaceOgre;
class MyApplication
{
public:
MyApplication(void);
~MyApplication(void);
public:
voidgo();
virtualvoidcreateScene(); //创建场景
virtualvoidcreateListener();//创建监听
protected:
Ogre::Root *m_pRoot;
Ogre::RenderWindow *m_pWindow;
Ogre::SceneManager *m_pSceneManager;
Ogre::Camera *m_pCamera;
Ogre::Viewport *m_pViewport;
Entity*m_pEnt;
MyFrameListener*m_pFrameLst;
};
#endif
MyApplication.cpp:
#include "MyApplication.h"
MyApplication::MyApplication(void)
{
m_pRoot= NULL;
m_pWindow= NULL;
m_pSceneManager= NULL;
m_pCamera= NULL;
m_pViewport= NULL;
m_pEnt= NULL;
m_pFrameLst= NULL;
}
MyApplication::~MyApplication(void)
{
m_pSceneManager->destroyAllEntities();
m_pEnt= NULL;
m_pSceneManager->getRootSceneNode()->removeAndDestroyAllChildren();
if(NULL !=m_pRoot){//释放root资源
m_pRoot->removeFrameListener(m_pFrameLst);
deletem_pRoot;
m_pRoot= NULL;
m_pFrameLst= NULL;
}
}
void MyApplication::go()
{
//创建Root,窗口,场景管理
m_pRoot= new Ogre::Root("plugins_d.cfg","ogre.cfg","ogre.log");
if(!m_pRoot->restoreConfig()){//启动时不显示Ogre的配置窗口,要求必须有ogre.cfg
if(!m_pRoot->showConfigDialog()){//启动时显示Ogre的配置窗口,如果没有ogre.cfg
return;
} else{
m_pRoot->saveConfig();//保存一个 ogre.cfg
}
}
m_pWindow= m_pRoot->initialise(true,"渲染窗口");
m_pSceneManager= m_pRoot->createSceneManager(Ogre::ST_GENERIC,"ExampleSMInstance");
//创建相机与视口
m_pCamera= m_pSceneManager->createCamera("Camera");
m_pCamera->setPosition(Vector3(0.0f,0.0f, 50.0f));
m_pCamera->lookAt(Vector3(0.0f,0.0f, 0.0f));
m_pCamera->setNearClipDistance(5);
m_pViewport= m_pWindow->addViewport(m_pCamera);
m_pViewport->setBackgroundColour(ColourValue(0.0f,0.0f, 0.0f));
m_pCamera->setAutoAspectRatio(Real(m_pViewport->getActualWidth())/Real(m_pViewport->getActualHeight()));
//载入单个资源
//ResourceGroupManager::getSingleton().addResourceLocation("media/packs/Sinbad.zip","Zip", "Popular");
//ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
//从文件载入资源
ConfigFilecf;
cf.load("resources_d.cfg");
ConfigFile::SectionIteratorsectionIter= cf.getSectionIterator();
StringsectionName,typeName,dataName;
while(sectionIter.hasMoreElements()){
sectionName= sectionIter.peekNextKey();
ConfigFile::SettingsMultiMap *settings=sectionIter.getNext();
ConfigFile::SettingsMultiMap::iteratormultiMapIter;
for(multiMapIter =settings->begin();multiMapIter!= settings->end();multiMapIter++){
typeName= multiMapIter->first;
dataName= multiMapIter->second;
ResourceGroupManager::getSingleton().addResourceLocation(dataName,typeName,sectionName);
}
}
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
createScene(); //创建场景
createListener();//创建监听
m_pRoot->startRendering();//开始渲染,需要FrameListener类的frameStarted或frameRenderingQueued或frameEnded函数返回false才会退出循环
}
void MyApplication::createScene()//创建场景
{
m_pEnt= m_pSceneManager->createEntity("Sinbad.mesh");//创建实体
m_pSceneManager->getRootSceneNode()->attachObject(m_pEnt);
}
void MyApplication::createListener()//创建监听,Root类必须有帧监听类,否则startRendering无法退出,其它看上面的startRendering后的解释
{
m_pFrameLst= new MyFrameListener(m_pWindow,m_pCamera,true,true, true);
m_pRoot->addFrameListener(m_pFrameLst);
}
6:Startup.cpp的内容:
#include "MyApplication.h"
int main(){
MyApplicationapp;
app.go();
return0;
}
九:粒子系统和扩展Ogre3D (程序为 游戏类编程/Ogre/Ogre1.73/ParticleSystems)
1:新建一个空的 win32控制台应用程序,命名为:ParticleSystems
2:添加一个 ParticleSystems.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:添加一个类:MyEntityFrameListener,内容与 五 中的MyEntityFrameListener一致
5:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include "MyEntityFrameListener.h"
class MyExampleApplication:public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
voidcreateScene(void);//创建屏幕(设置灯光,材质,相机,创建实体节点等)
voidcreateFrameListener(void);//创建帧监听
voidcreateParticle();//创建粒子系统
private:
MyEntityFrameListener*m_pFrameLst;
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst= NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
deletem_pFrameLst;
m_pFrameLst= NULL;
}
}
void MyExampleApplication::createScene(void)
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));//设置环境光
Light*l =mSceneMgr->createLight("mainLight");
l->setPosition(20, 80, 50);
Ogre::Vector3pst = mCamera->getPosition();
Ogre::Quaternionort = mCamera->getOrientation();
mCamera->setPosition(0, 100.0f, 500.0f);//设置摄像机位置
mCamera->setOrientation(Ogre::Quaternion(0.953763f, -0.3f, -0.00865638f,-0.0027f));//设置摄像机方向
mSceneMgr->setSkyBox(true,"Examples/SceneSkyBox2", 50);//设置天空盒
createParticle();//创建粒子系统
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst= new MyEntityFrameListener(mWindow,mCamera, true,true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
void MyExampleApplication::createParticle()//创建粒子系统
{
//通过模板创建粒子系统,粒子系统需要一个发射器,粒子,颜色修改器
Ogre::ParticleSystem*partSystem= mSceneMgr->createParticleSystem("Smoke","MySwarm");//MySmokePoint Examples/Smoke Examples/Fireworks
SceneNode*pNode =mSceneMgr->getRootSceneNode()->createChildSceneNode();
pNode->attachObject(partSystem);
pNode->setPosition(1, 10, 0);
}
//myParticle.particle,myMaterial.material
6:myMaterial.material的内容:
//材质
//给材质命名
material myMaterial
{
//技术
technique
{
//通道
pass
{
//关闭灯光
lighting off
//场景混合,alpha混合
scene_blend alpha_blend
depth_write off
//漫反射顶点颜色
diffuse vertexcolor
texture_unit
{
texture smoke.png
//tex_address_modeclamp,//材质不拉伸,材质边缘延伸填充,具体看材质方面的实例
}
}
}
}
7:myParticle.particle的内容:
//粒子系统:需要一个发射器,粒子,颜色修改器等
//billboard_type point: 粒子的头尾与XZ面是垂直的
//billboard_type oriented_self: 粒子的头尾连线是指向原点的,即与XZ平面有夹角,(激光射线,焰火,隨着粒子改变方向,公告板也重定向它自己面向这个方向)
//billboard_type oriented_common:粒子的头尾连线都是平行于XY面(粒子面向一个共同的固定的方向向量),(暴风雨,流星,较oriented_self略快)
//perpendicular_common:粒子垂直于一个共同的固定的方向向量
//perpendicular_self: 粒子垂直于它们自己的方向向量
//billboard_type oriented_common与common_direction 0 -1 0改变粒子在Y轴的方向,common_direction好像无法与billboard_type point结合
//***************************点粒子系统***************************//
particle_system MySmoke_Point_oriented_self
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Point
{
emission_rate 100
direction 0 1 0
angle 30
velocity 20
time_to_live 10
colour_range_start 1 0 0 1
colour_range_end 0.5 0.5 0.5 0.1
}
}
particle_system MySmoke_Point_point
{
//粒子材质名称,粒子宽度,粒子高度myMaterial
material Examples/Flare2
particle_width 5
particle_height 5
//粒子配额(数量)和 类型 point 与 oriented_self的区别是,point粒子的头尾与XZ面是垂直的,
//而oriented_self的头尾连线是指向原点的,即与XZ平面有夹角
quota 500
billboard_type point
//点发射器
emitter Point
{
//每秒发出10个
emission_rate 100
//发射方向
direction 0 1 0
//速度
velocity 20
//最小速度和最大速度
//velocity_min 50
//velocity_max80
//角度,粒子存活时长10秒,顶点颜色
angle 30
//time_to_live10//粒子存活时长10秒
//粒子存活最短时长和最大时长
time_to_live_min1
time_to_live_max6
//colour 1 0 0 1//顶点颜色
//顶点起始颜色和结束颜色
//colour_range_start 1 0 0 1
//colour_range_end 0.5 0.5 0.5 0.1
//连续发射时长,和等待发射时长,发1秒,隔1秒
//duration 1
//repeat_delay 1
}
//在粒子存活时段,放大5倍大小
affector Scaler
{
rate 5
}
//导流面板,粒子碰到此面板,会向面板的法向量方向运动
affector DeflectorPlane
{
//面板点,面板法向量
plane_point 00 80 0
plane_normal -1 -1 0
bounce 1.0
}
//颜色图片,给材质加颜色,相当于colour等
affector ColourImage
{
imagesmokecolors.png
}
//添加随机???
//affectorDirectionRandomiser
//{
// randomness 100
//1代表100%,0代表0%, 保持速度,即速度不改变
// scope 1
// keep_velocity true
//}
//不同时段,粒子颜色不同
/*
affector ColourInterpolator
{
time0 0
colour0 1 0 0
time1 0.25
colour1 0 1 0
time2 0.5
colour2 0 0 1
time3 0.75
colour3 0 0.5 1
time4 1
colour4 0.5 0.5 0
}*/
/*
//颜色推子,可以改变粒子颜色度
affector ColourFader
{
red -0.25
green -0.25
blue -0.25
}
affector ColourFader2
{
red1 -1
green1 -1
blue1 -1
state_change 2
red2 +1
green2 +1
blue2 +1
}
*/
}
particle_system MySmoke_Point_oriented_common
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Point
{
emission_rate 100
direction 0 1 0
angle 30
velocity 20
time_to_live 10
colour_range_start 1 0 0 1
colour_range_end 0.5 0.5 0.5 0.1
}
}
//***************************盒子粒子系统***************************//
particle_system MySmoke_Box_oriented_self
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Box
{
height 10
width 10
depth 10
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Box_point
{
//粒子材质名称,粒子宽度,粒子高度
material Examples/Flare2
particle_width 5
particle_height 5
//粒子配额(数量)和点类型
quota 5000
billboard_type point
//盒子发射器
emitter Box
{
//定义盒子,高宽深
height 10
width 10
depth 10
//每秒发出100个,发射方向,速度
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Box_oriented_common
{
material Examples/Flare2
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Box
{
height 10
width 10
depth 10
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
//***************************环状粒子系统***************************//
particle_system MySmoke_Ring_oriented_self
{
material myMaterial
particle_width 5
particle_height 5
quota 5000
billboard_type oriented_self
emitter Ring
{
height 50
width 50
inner_height 0.9
inner_width 0.9
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
particle_system MySmoke_Ring_point
{
//粒子材质名称,粒子宽度,粒子高度
material myMaterial
particle_width 5
particle_height 5
sorted true
//粒子配额(数量)和点类型
quota 500
billboard_type point
emitter Ring
{
//高宽
height 10
width 10
//内部90%部分不发射粒子(百分比)
inner_height 0.9
inner_width 0.9
//每秒发出10个,发射方向,速度
emission_rate 50
direction 0 1 0
velocity 20
time_to_live 10
//angle 30
}
//不同时间段,颜色不同
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.50
colour1 0 1 0
time2 0.70
colour2 0 0 1
}
}
particle_system MySmoke_Ring_oriented_common
{
material myMaterial
particle_width 5
particle_height 5
quota 5000
billboard_typeoriented_common
emitter Ring
{
height 50
width 50
inner_height 0.9
inner_width 0.9
emission_rate 100
direction 0 1 0
velocity 20
//angle 30
}
}
//***************************粒子系统实例***************************//
//一烟冲天
particle_system MySmoke
{
material myMaterial
particle_width 5
particle_height 5
sorted true
quota 500
billboard_type point
emitter Point
{
emission_rate 25
direction 0 1 0
velocity 20
time_to_live 10
}
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.50
colour1 0 1 0
time2 0.70
colour2 0 0 1
}
affector Scaler
{
rate 3
}
affector ColourFader2
{
red1 -0.25
green1 -0.25
blue1 -0.25
state_change 2
red2 +0.25
green2 +0.25
blue2 +0.25
}
}
//烟花爆竹粒子系统(使用了多点发射器)
particle_system myFirework
{
material myMaterial
particle_width 5
particle_height 5
quota 1000
billboard_type point
point_rendering false
cull_each false
//每次发射的数量
emit_emitter_quota 10
//发射器(emitterBox)使用多点发射:explosion
emitter Box
{
height 50
width 50
depth 50
name mainEmitter
emit_emitter explosion
time_to_live 3
direction 0 100 0
velocity 200
}
//explosion:通过Box发射器,爆炸之后得emitterPoint....
emitter Point
{
name explosion
duration 0.1
repeat_delay_min 2
repeat_delay_max 3
emission_rate 1000
direction 0 100 0
velocity 80
angle 90
colour_range_start 0.50.6 0.7
colour_range_end 1 0.7 0.8
}
//下坠向量
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
//不同时间段,颜色不同
affector ColourInterpolator
{
time0 0.00
colour0 1 0 0
time1 0.25
colour1 0 1 0
time2 0.50
colour2 0 0 1
}
}
//下雨粒子系统
particle_system myRain
{
//粒子材质名称,粒子宽度,粒子高度
material Examples/Droplet
particle_width 50
particle_height 100
//粒子配额(数量)和点类型
quota 500
//直线下坠,直线方向沿Y轴方向(common_direction0 -1 0向Y轴方向)
billboard_type oriented_common
common_direction 0 -1 0
//盒子发射器,
emitter Box
{
angle 0
//定义盒子,高宽深
height 500
width 500
depth 500
//每秒发出10个,发射方向,速度
emission_rate 100
direction 0 -10 0
velocity 200
}
//下落或上升,取决于force_vector的值
affector LinearForce
{
force_vector 0 -100 0
force_application add
}
}
//billboard_type oriented_self + angle 360 + affector DeflectorPlane实现
//在粒子在Box里面随机方向运动加碰撞转向运动
particle_system MySwarm
{
material Examples/Flare2
particle_width 12
particle_height 24
quota 500
billboard_type oriented_self
emitter Box
{
angle 360
height 100
width 100
depth 100
emission_rate 50
direction 0 1 0
velocity 20
}
affector DeflectorPlane
{
plane_point 0 -50 0
plane_normal 0 1 0
bounce 1
}
affector DeflectorPlane
{
plane_point 0 50 0
plane_normal 0 -1 0
bounce 1
}
affector DeflectorPlane
{
plane_point 50 0 0
plane_normal -1 0 0
bounce 1
}
affector DeflectorPlane
{
plane_point -50 0 0
plane_normal 1 0 0
bounce 1
}
affector DeflectorPlane
{
plane_point 0 0 50
plane_normal 0 0 -1
bounce 1
}
affector DeflectorPlane
{
plane_point 0 0 -50
plane_normal 0 0 1
bounce 1
}
}
十:主角实体运动与 障碍物判断,怪物实体向 主角 实体 方向 运动等
(程序为 游戏类编程/Ogre/Ogre1.73/AITest(简单的测试))
1:新建一个空的 win32控制台应用程序,命名为:AITest
2:添加一个 AITest.cpp文件.
3:配置跟 FirstOGRE的3,4,5项一样.
4:代码 看:AITest(简单的测试)
十一:地形编程(读取地形配置文件的地形编程)。(程序为游戏类编程/Ogre/Ogre1.73/TerrainCfgFile)
1:新建一个空的 win32控制台应用程序, 命名为:TerrainCfgFile
2:添加一个 TerrainCfgFile.cpp文件,内容:
#include "MyExampleApplication.h"
int main(){
MyExampleApplicationapp;
app.go();
return 0;
}
3:配置跟 FirstOGRE的3,4,5项一样.
4:在3的基础上,需要添加Ogre目录:
5:需要多引入一个地形库:OgreTerrain_d.lib
6:添加一个类:MyExampleApplication
MyExampleApplication.h:
#ifndef _MyExampleApplication_H_
#define _MyExampleApplication_H_
#include
#include
#include
#include "MyEntityFrameListener.h"
using namespaceOgre;
class MyExampleApplication :public ExampleApplication
{
public:
MyExampleApplication(void);
~MyExampleApplication(void);
public:
virtual void chooseSceneManager(void);//创建屏幕管理
virtual void createCamera(void); //创建相机
void createScene(void); //创建屏幕(设置灯光,材质,相机,创建实体节点等)
void createFrameListener(void);//创建帧监听
protected:
MyEntityFrameListener *m_pFrameLst;
RaySceneQuery *m_pRaySceneQuery;//射线碰撞查询器
TerrainGlobalOptions *m_pTerrainGlobals;//地形全局配置
TerrainGroup *m_pTerrainGroup; //地形分组对象
};
#endif
MyExampleApplication.cpp:
#include "MyExampleApplication.h"
MyExampleApplication::MyExampleApplication(void)
{
m_pFrameLst = NULL;
}
MyExampleApplication::~MyExampleApplication(void)
{
if (NULL !=m_pFrameLst){
mRoot->removeFrameListener(m_pFrameLst);//删除监听
delete m_pFrameLst;
m_pFrameLst = NULL;
}
}
void MyExampleApplication::chooseSceneManager(void)//创建屏幕管理
{
mSceneMgr = mRoot->createSceneManager(ST_EXTERIOR_CLOSE,"ExampleSMInstance2");//室外封闭场景
}
void MyExampleApplication::createCamera(void)
{
mSceneMgr = mRoot->getSceneManager("ExampleSMInstance2");//根据管理器名称获取屏幕管理器
mCamera = mSceneMgr->createCamera("plyerCam2");//创建摄像机
mCamera->setPosition(Vector3(707.0f, 150.0f, 528.0f));//摄像机位置
mCamera->lookAt(Vector3(0.0f, 0.0f, -300.0f));//摄像机的目标点
mCamera->setNearClipDistance(1); //摄像机近距
mCamera->setFarClipDistance(1000);//摄像机远距
}
void MyExampleApplication::createScene(void)
{
//地形相关
mSceneMgr = mRoot->getSceneManager("ExampleSMInstance2");
mSceneMgr->setAmbientLight(ColourValue(0.5f, 0.5f, 0.5f));//设置场景的环境光
Light *l =mSceneMgr->createLight("MainLight");//创建灯光
l->setPosition(20.0f,80.0f, 50.0f); //设置灯光位置
mSceneMgr->setFog(FogMode::FOG_LINEAR,ColourValue(0.93f, 0.16f, 0.76f), 0.001,500, 1000);//设置雾
mWindow->getViewport(0)->setBackgroundColour(ColourValue(0.93f,0.86f, 0.76f));//设置视口背景
//***************地形块的全局配置
m_pTerrainGlobals = newOgre::TerrainGlobalOptions();
m_pTerrainGlobals->setLayerBlendMapSize(64);//设置地形层混合图大小为64x64
m_pTerrainGlobals->setMaxPixelError(8);
m_pTerrainGlobals->setCompositeMapDistance(3000);
m_pTerrainGlobals->setLightMapDirection(l->getDerivedDirection());//设置光线方向,所有地形均采用同一个方向的光
m_pTerrainGlobals->setCompositeMapAmbient(mSceneMgr->getAmbientLight());//设置环境光
m_pTerrainGlobals->setCompositeMapDiffuse(l->getDiffuseColour());//设置漫反射光
m_pTerrainGlobals->setLightMapSize(1500);//设置光线图的大小,这个数字越小,地图的阴影将越粗糙
//***************创建地形分组对象,该对象用于创建以及管理地形块
m_pTerrainGroup = newTerrainGroup(mSceneMgr,Terrain::ALIGN_X_Z,1500, 1500);
m_pTerrainGroup->setOrigin(Vector3(750, 0, 750));
//***************通过地形分组创建地形块
//设置地形默认属性
Terrain::ImportData&defalutImp =m_pTerrainGroup->getDefaultImportSettings();
defalutImp.terrainSize= 1500;
defalutImp.worldSize = 1500;
defalutImp.inputScale = 1;
defalutImp.minBatchSize=33;
defalutImp.maxBatchSize=65;
//设置纹理
defalutImp.layerList.resize(1);
defalutImp.layerList[0].worldSize = 8;//每层贴图wordsize取8为佳
defalutImp.layerList[0].textureNames.push_back("terrain_texture.jpg");
//defalutImp.layerList[0].textureNames.push_back(750);
//设置地形默认属性
Terrain::ImportData&defaultimp =m_pTerrainGroup->getDefaultImportSettings();
defalutImp.terrainSize= 1500;
defalutImp.worldSize = 1500;
defalutImp.inputScale = 1;
defalutImp.minBatchSize=33;
defalutImp.maxBatchSize=65;
m_pTerrainGroup->defineTerrain(100,100, 10.0f);
//mSceneMgr->setWorldGeometry("myTerrain.cfg"); //设置世界几何体
//是否支持无限远的面投影
mCamera = mSceneMgr->getCamera("plyerCam2");//获取相机
if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE)){
mCamera->setFarClipDistance(0);
}
//创建射线碰撞查询器,由摄像机位置向Y轴负向发射线进行查询
m_pRaySceneQuery = mSceneMgr->createRayQuery(Ray(mCamera->getPosition(),Vector3::NEGATIVE_UNIT_Y));
}
void MyExampleApplication::createFrameListener(void)
{
m_pFrameLst = new MyEntityFrameListener(m_pRaySceneQuery,mWindow,mCamera,true, true, true);//启用各输入设备的缓冲
mRoot->addFrameListener(m_pFrameLst);
}
7:添加一个类:MyEntityFrameListener
MyEntityFrameListener.h:
#ifndef MyEntityFrameListener_H_
#define MyEntityFrameListener_H_
#include "ogre/exampleframelistener.h"
using namespaceOgre;
class MyEntityFrameListener :public ExampleFrameListener,publicOIS::KeyListener,public OIS::MouseListener
{
public:
MyEntityFrameListener(RaySceneQuery*pRaySceneQuery,RenderWindow*win,Camera* cam, bool bufferedKeys = false,bool bufferedMouse=false, bool bufferedJoy = false);
~MyEntityFrameListener(void);
public:
virtual bool keyPressed(constOIS::KeyEvent &arg);
virtual bool keyReleased(constOIS::KeyEvent &arg);
virtual bool mouseMoved(constOIS::MouseEvent &arg);
virtual bool mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid);
virtual bool mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid);
void moveCamera();//移动相机
virtual bool frameEnded(constFrameEvent& evt);//循环刷新界面
protected:
SceneManager *mSceneMgr;
RaySceneQuery *m_pRaySceneQuery;//射线碰撞查询器
};
#endif
MyEntityFrameListener.cpp:
#include "MyEntityFrameListener.h"
MyEntityFrameListener::MyEntityFrameListener(RaySceneQuery *pRaySceneQuery,RenderWindow*win,Camera*cam,bool bufferedKeys,bool bufferedMouse,bool bufferedJoy)
: ExampleFrameListener(win,cam,bufferedKeys,bufferedMouse,bufferedJoy)
{
//启用了键鼠柄的缓冲,就能使用它们的回调函数
mKeyboard->setEventCallback(this);
mMouse->setEventCallback(this);
m_pRaySceneQuery = pRaySceneQuery;//射线碰撞查询器
mSceneMgr = cam->getSceneManager();
}
MyEntityFrameListener::~MyEntityFrameListener(void)
{
}
bool MyEntityFrameListener::keyPressed(constOIS::KeyEvent&arg)//键盘的键按下
{
Real moveScale= 0.2f;
switch(arg.key){
case OIS::KC_A:
case OIS::KC_LEFT:
mTranslateVector.x= -moveScale;//Movecamera left
break;
case OIS::KC_D:
case OIS::KC_RIGHT:
mTranslateVector.x=moveScale; //Move camera RIGHT
break;
case OIS::KC_W:
case OIS::KC_UP:
mTranslateVector.z= -moveScale;//Movecamera forward
break;
case OIS::KC_S:
case OIS::KC_DOWN:
mTranslateVector.z=moveScale; //Move camera backward
break;
case OIS::KC_PGUP:
mTranslateVector.y=moveScale; //Move camera up
break;
case OIS::KC_PGDOWN:
mTranslateVector.y= -moveScale;//Movecamera down
break;
}
return true;
}
bool MyEntityFrameListener::keyReleased(constOIS::KeyEvent&arg)//释放按下的键
{
mTranslateVector = Vector3::ZERO;//防止按键释放后还继续移动相机
return true;
}
bool MyEntityFrameListener::mouseMoved(constOIS::MouseEvent&arg)
{
const OIS::MouseState &ms=arg.state;
if(ms.buttonDown(OIS::MB_Left)) {
} else if(ms.buttonDown(OIS::MB_Right)){
} else {
mRotX = Degree(-ms.Y.rel * 0.13);//转为弧度,如:Degree(180)
mRotY = Degree(-ms.X.rel * 0.13);//转为弧度,如:Degree(180)
}
return true;
}
bool MyEntityFrameListener::mousePressed(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
return true;
}
bool MyEntityFrameListener::mouseReleased(constOIS::MouseEvent&arg,OIS::MouseButtonIDid)
{
return true;
}
void MyEntityFrameListener::moveCamera() //移动相机
{
mCamera->yaw(mRotY); //绕Y轴转动
mCamera->pitch(mRotX);//绕X轴转动
mCamera->moveRelative(mTranslateVector);//移动相机
mRotX = mRotY =Radian(0); //防止鼠标不转动后继续转动相机
}
bool MyEntityFrameListener::frameEnded(constFrameEvent& evt)
{
moveCamera(); //移动相机
static Ray updateRay;//定义一个射线变量
updateRay.setOrigin(mCamera->getPosition());//设置原点为摄像机的位置
updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);//设置方向为Y轴方向
m_pRaySceneQuery->setRay(updateRay);//碰撞查询器设置射线
RaySceneQueryResult &qryResult=m_pRaySceneQuery->execute();//执行碰撞查询
//遍历查询结果
RaySceneQueryResult::iteratoritrRaySQRst =qryResult.begin();
if(itrRaySQRst !=qryResult.end()&&itrRaySQRst->worldFragment){
mCamera->setPosition(mCamera->getPosition().x,itrRaySQRst->worldFragment->singleIntersection.y
+100, mCamera->getPosition().z);//将摄像机设置成地表的位置偏移10
}
return true;
}
8:添加一个地形配置文件:myTerrain.cfg,放在Media目录下,内容为:
#WorldTexture,DetailTexture仅用作纹理
#主世界纹理,通过纹理管理器创建一个材质
WorldTexture=terrain_texture.jpg
#详细纹理,通过纹理管理器创建一个材质 waves2.dds
DetailTexture=terrain_detail.jpg
#平铺的瓦片数
DetailTile=3
#高位图资源(相当于模型),指定的高位图,图片为png格式
PageSource=Heightmap
Heightmap.image=terrain.png
#图片大小,图片顶点数,尺寸必须是方形,必须是(2^n)+1
PageSize=513
#每一个瓦块大小,必须是(2^n)+1
TileSize=65
#Heightmap.image=waveNM1.raw
#如果使用的是RAW格式的图片,指定RAW格式图片大小,必须是(2^n)+1
#Heightmap.raw.size=513
#指定使用的像素bit度(1 = 8bit, 2=16bit)
#Heightmap.raw.bpp=1
#如果设置为true,则翻转高度图
#Heightmap.flip=true
#当LOD时允许最大的误差,过高会导致地形撕裂,过低则会影响性能
MaxPixelError=3
#在世界单元中一个地形页的大小
PageWorldX=1500
PageWorldZ=1500
#地形的最大高度,用于相乘
MaxHeight=200
#渲染地形使用的细节层次的数目。地形的远处和平坦处会以低细节渲染
MaxMipMapLevel=5
#VertexNormals=yes
#VertexColors=yes
#UseTriStrips=yes
#使用顶点端变形LODs
VertexProgramMorph=yes
#The proportional distance range at which the LODmorph starts to take effect
#This is as a proportion of the distance betweenthe current LODs effective range,
#and the effective range of the next lower LOD
#LOD融合开始点:高低LOD之间距离之比
LODMorphStart=0.2
#This following section is for if you want toprovide your own terrain shading routine
#Note that since you define your textures withinthe material this makes the
#WorldTexture and DetailTexture settingsredundant
#The name of the vertex program parameter youwish to bind the morph LOD factor to
#this is 0 when there is no adjustment (highest)to 1 when the morph takes it completely
#to the same position as the next lower LOD
#USE THIS IF YOU USE HIGH-LEVEL VERTEX PROGRAMSWITH LOD MORPHING
#MorphLODFactorParamName=morphFactor
#The index of the vertex program parameter youwish to bind the morph LOD factor to
#this is 0 when there is no adjustment (highest)to 1 when the morph takes it completely
#to the same position as the next lower LOD
#USE THIS IF YOU USE ASSEMBLER VERTEX PROGRAMSWITH LOD MORPHING
#MorphLODFactorParamIndex=4
#The name of the material you will define toshade the terrain
#CustomMaterialName=Ogre/Skin