参考:
http://blog.youkuaiyun.com/zhuzhao/article/details/4272052
http://www.ogre3d.org/tikiwiki/qtogre
http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Setting+Up+An+Application+-+QtCreator
还没工作的时候,就一直想学习一下ogre,但总找不到时间,工作之后更忙,最近难得有几天休息,就把Qt + Ogre 的开发些下来,做个笔记吧
准备工具:
Qt : 5.2.1 vc10 编译
编译器 : vc10
Ogre : SDK 1.8.1 (越新的版本,教程资料什么的都不容易找,所以还是用不要太新的,Qt我个人比较熟悉,所以就用最新的)
本来想用mingw的,但好像很不容易,尤其是之后还打算使用python作为脚本,就不折腾编译器了,默认使用vc10
IDE : QtCreator //之所以使用这个是因为Qt代码补全很好用(其实我不会用vc)。
第一步:
当然是先准备好上面的工具,Qt,Ogre直接下载现成的,对于我这个初学者,能减少无谓的劳动才是最好的,否则无端端陷入一个麻烦的BUG,大大打击兴趣
Ogre SDK 下载好后,不需要编译,直接解压到某个地方,设置系统变量(你也可以不设置,就是多敲点字就行)
例如:
OGRE_HOME = "D:\GameDev\OgreSDK_vc10_v1-8-1"
Qt设置运行环境的path
path = path + "D:\Qt\Qt5.2.1-vs\5.2.1\msvc2010_opengl\bin"
方便运行的时候找到Qt的库( Ogre也可以这样,- _ - ! 我个人不想设置就是了)
第二步:
配置QtCreator
选择创建一个QWidget Application.
不要ui文件,保留mainwindow.h mainwindow.cpp main.cpp
删掉mainwindow.h的代码,以下面的代码替换
mainwindow.h 代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <OGRE/Ogre.h>
#include <QWidget>
#include <QKeyEvent>
#include <QMouseEvent>
class OgreView : public QWidget
{
Q_OBJECT
public:
OgreView(QWidget* parent );
~OgreView();
//QSize minimumSizeHint() const;
//QSize sizeHint() const;
protected:
void setupView();//创建Ogre使用的内容,场景内容;
void update();//通过它,手动更新场景内容
void setupResources();//
void createScene();
void createLight();
void resizeEvent(QResizeEvent* evt);//窗口可能缩放
void timerEvent(QTimerEvent* evt);//可以设一时钟来更新窗口
void paintEvent(QPaintEvent* evt);//呵,当然得处理了
//消息响应
void keyPressEvent(QKeyEvent* evt);
void mousePressEvent(QMouseEvent* evt);
void mouseReleaseEvent(QMouseEvent* evt);
void wheelEvent(QWheelEvent* evt);
//有关Ogre
Ogre::RenderWindow* mRenderWindow;
Ogre::SceneManager* mSceneMgr;
Ogre::Camera* mCamera;
Ogre::Viewport* mVp;
Ogre::Root* mRoot;
Ogre::Light* mainLight;
Ogre::Entity* mainEnt;
Ogre::SceneNode* mainNode;
Ogre::Real angleX;
Ogre::Real angleY;
Ogre::Real rotX;
Ogre::Real rotY;
Ogre::Vector3 mDirection;
Ogre::Real mRotate;
Ogre::Vector2 mousePos;
bool mouseLeftPressed;
bool mouseRightPressed;
bool mouseMiddleBtn;
};
#endif // MAINWINDOW_H
删掉mainwindow.cpp代码,以下面的替换
#include "mainwindow.h"
OgreView::OgreView(QWidget* parent) : QWidget(parent,Qt::WindowFlags(Qt::MSWindowsOwnDC))
{
mRenderWindow = NULL;
mSceneMgr = NULL;
mVp = NULL;
mainEnt = NULL;
mainNode = NULL;
angleX = 1;
angleY = 1;
rotX = 1;
rotY = 1;
mDirection = NULL;
mRotate = 1;
mousePos = NULL;
mouseLeftPressed = false;
mouseRightPressed = false;
mouseMiddleBtn = false;
setupResources();
}
OgreView::~OgreView()
{
// destroy Viewport and RenderWindow
if( mVp )
{
mRenderWindow->removeViewport(mVp->getZOrder());
mVp = 0;
}
Ogre::Root::getSingleton().detachRenderTarget(mRenderWindow);
mRenderWindow = 0;
if(mRoot != NULL)
{
delete mRoot;
mRoot = 0;
}
}
void OgreView::setupResources()
{
mRoot = new Ogre::Root("plugins_d.cfg");
Ogre::ConfigFile cf;
cf.load("resources_d.cfg");
Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
Ogre::String secName, typeName, archName;
while(seci.hasMoreElements())
{
secName = seci.peekNextKey();
Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for(i=settings->begin(); i!=settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
}
}
mRoot->restoreConfig();
mRoot->initialise(false);
}
//一般都在这里写上场景初始化的一些信息
void OgreView::createScene()
{
qDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
mainEnt = mSceneMgr->createEntity("Head", "Sinbad.mesh");
mainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
mainNode->attachObject(mainEnt);
}
//创建灯光,没啥好说的
void OgreView::createLight()
{
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
mainLight = mSceneMgr->createLight("MainLight");
mainLight->setPosition(20,80,50);
}
//设置视角,创建摄像机
void OgreView::setupView()
{
if(mRenderWindow)
return;
//createRenderWindow,当然必须得自己手工建窗口了,把窗口句柄扒出来....
Ogre::NameValuePairList params;
params["externalWindowHandle"] = Ogre::StringConverter::toString((size_t)(HWND)winId());
mRenderWindow = mRoot->createRenderWindow("View", width(), height(), false, ¶ms);
//SceneManager
mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
//setup camera & viewport
mCamera = mSceneMgr->createCamera("PlayerCam");
mCamera->setPosition(Ogre::Vector3(0,0,80));
mCamera->lookAt(Ogre::Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
mVp = mRenderWindow->addViewport(mCamera);
mVp->setBackgroundColour(Ogre::ColourValue(0, 0.0, 0.0, 1));
mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth()) / Ogre::Real(mVp->getActualHeight()));
//resource
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
//创建场景
createScene();
//创建灯光
createLight();
//定时更新窗口,不走原来的自动路线。
startTimer(2);
}
void OgreView::paintEvent(QPaintEvent *evt)
{
Q_UNUSED(evt);
if(mRenderWindow == NULL)
setupView();
update();
}
void OgreView::timerEvent(QTimerEvent* evt)
{
Q_UNUSED(evt);
update();
}
void OgreView::update()
{
//手工更新场景内容,而不是进入到连续的循环中
if(mRenderWindow != NULL)
{
mRoot->renderOneFrame(); //顾名思义,渲染一帧就好了
}
}
void OgreView::resizeEvent(QResizeEvent *evt)
{
Q_UNUSED(evt);
if (mRenderWindow != NULL)
{
mRenderWindow->windowMovedOrResized();
mCamera->setAspectRatio(Ogre::Real(mVp->getActualWidth()) / Ogre::Real(mVp->getActualHeight()));
}
}
void OgreView::keyPressEvent(QKeyEvent* evt)
{
qDebug("keypressevent");
if(mainEnt != NULL && mainNode != NULL)
{
switch(evt->key())
{
case Qt::Key_W:
case Qt::Key_Up:
{
rotX = -0.1;
mainNode->pitch(Ogre::Radian(rotX));
break;
}
case Qt::Key_S:
case Qt::Key_Down:
{
rotX = 0.1;
mainNode->pitch(Ogre::Radian(rotX));
break;
}
case Qt::Key_A:
case Qt::Key_Left:
{
rotY = -0.1;
mainNode->yaw(Ogre::Radian(rotY));
break;
}
case Qt::Key_D:
case Qt::Key_Right:
{
rotY = 0.1;
mainNode->yaw(Ogre::Radian(rotY));
break;
}
}
}
}
void OgreView::mousePressEvent(QMouseEvent* evt)
{
qDebug("mousePressEvent");
if(evt->button() == Qt::LeftButton)
{
mouseLeftPressed = true;
}
if(evt->button() == Qt::RightButton)
{
mouseRightPressed = true;
mousePos = Ogre::Vector2(evt->x(), evt->y());
}
if(evt->button() == Qt::MidButton)
{
mouseMiddleBtn = true;
}
}
void OgreView::mouseReleaseEvent(QMouseEvent *evt)
{
qDebug("mouseReleaseEvent");
if(evt->button() == Qt::LeftButton)
{
mouseLeftPressed = false;
}
if(evt->button() == Qt::RightButton)
{
mouseRightPressed = false;
mousePos = Ogre::Vector2(evt->x(), evt->y());
}
if(evt->button() == Qt::MidButton)
{
mouseMiddleBtn = false;
}
}
void OgreView::wheelEvent(QWheelEvent* evt)
{
mDirection.z = -evt->delta()/12;
update();
mDirection.z = 0;
}
#include <QApplication>
#include <QWidget>
#include "mainwindow.h"
#include <QVBoxLayout>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget window;
window.resize(800, 600);
window.setWindowTitle("Simple example");
OgreView* ogreWidget = new OgreView(&window);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(ogreWidget);
window.setLayout(layout);
window.show();
return app.exec();
}
第三步:
配置工程
先写*.pro文件
由于输入输出使用了Qt,不需要OIS了,这里就没包括进来
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
DEFINES -= UNICODE
TARGET = qtclient
TEMPLATE = app
LIBS *= user32.lib
LIBS += -L$(OGRE_HOME)\\boost\\lib
release:LIBS += -L$(OGRE_HOME)\\lib\\release
debug:LIBS += -L$(OGRE_HOME)\\lib\\debug
INCLUDEPATH += $(OGRE_HOME)\\include
INCLUDEPATH += $(OGRE_HOME)\\include\\OGRE
INCLUDEPATH += $(OGRE_HOME)\\boost
TARGET = $$join(TARGET,,,d)
LIBS *= -lOgreMain_d
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
第四步(非必须):
配置生成与运行
然后再点击项目属性页
选择自定义处理步骤
添加 “C:\Windows\System32\cmd.exe” 到 命令
添加“/c copy debug\qtclientd.exe %OGRE_HOME%\bin\debug” 到参数
意思是编译生成的 *.exe 直接copy到ogre 的debug运行库目录中,你就可以不用手动复制了。
然后设置运行时的配置
设置working directory 的意思是,运行时,从这里找。
第四步不是必须的,但是设置之后,能省下你很多事情,尤其是调试信息方面。
来看下运行效果图: