菜鸟也学Ogre-一步步搭建Ogre

这次的教程是完全脱离了wiki的框架,白手起家搭建Ogre。
Ogre的最基本的生命周期如下:
1.创建根对象;
2.定义Ogre将要用到的资源;
3.选择并设置渲染引擎(指的是DirectX,OpenGL等等);
4.创建渲染窗口;
5.初始化资源;
6.创建场景;
7.设置第三方库和插件;
8.创建帧监听;
9.开始渲染循环。


第一步:创建Root对象
Root对象是Ogre库的核心,它必须被最先创建。
在头文件中加入:
#include <OgreRoot.h>
private:
    Ogre::Root* mRoot;
    Ogre::String mPluginsCfg;


cpp文件如下:
BasicTutorial6::BasicTutorial6(void)
    : mRoot(0),
    mPluginsCfg(Ogre::StringUtil::BLANK)
{
}
//-------------------------------------------------------------------------------------
BasicTutorial6::~BasicTutorial6(void)
{
    delete mRoot;
}
bool BasicTutorial6::go(void)
{
#ifdef _DEBUG
    mPluginsCfg = "plugins_d.cfg";
#else
    mPluginsCfg = "plugins.cfg";
#endif
 
    // construct Ogre::Root
    mRoot = new Ogre::Root(mPluginsCfg);
 
    return true;
}
构造函数中,冒号后面是默认形参列表。Root对象真正的初始化是在go()中进行的。条件编译的作用是在编译debug版本和release版本时调用不同的资源。


第二步:加载资源
在头文件的私有成员中中加入
Ogre::String mResourcesCfg;
在构造函数的默认形参列表中加入代码,
BasicTutorial6::BasicTutorial6(void)
: mRoot(0),
mResourcesCfg(Ogre::StringUtil::BLANK),
mPluginsCfg(Ogre::StringUtil::BLANK) 
添加头文件:
#include <OgreConfigFile.h>
然后修改go():
bool BasicTutorial6::go(void)
{
#ifdef _DEBUG
    mResourcesCfg = "resources_d.cfg";
    mPluginsCfg = "plugins_d.cfg";
#else
    mResourcesCfg = "resources.cfg";
    mPluginsCfg = "plugins.cfg";
#endif


// set up resources
// Load resource paths from config file
Ogre::ConfigFile cf;
cf.load(mResourcesCfg);
// Go through all sections & settings in the file
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);
    }
}


在提起资源的时候,资源文件是分成几个部分的,包括Essential Popular,General,还有两种资源类型,包括FileSystem和Zip文件。while循环就是用于循环读取资源的。
代码写到这里,你可以尝试编译运行,然后查看相应的*.log文件。


第三步:创建渲染系统
渲染系统要么是DirectX,要么是OpenGL,demo里有一个参数对话框,在设置运行参数的时候很有用,我们把它添加上去。
在头文件中添加:
Ogre::RenderWindow* mWindow;
在go()中添加:
// configure
// Show the configuration dialog and initialise the system
if(!(mRoot->restoreConfig() || mRoot->showConfigDialog()))
{
    return false;
}
在if中我们先尝试恢复之前的设置,这样如果之前设置过,在运行就不用设置了,否则看能否从参数对话框中获取参数。
运用下面的语句能够同样到达设置参数的效果,
// Do not add this to the application
RenderSystem *rs = mRoot->getRenderSystemByName("Direct3D9 Rendering Subsystem");
// or use "OpenGL Rendering Subsystem"
mRoot->setRenderSystem(rs);
rs->setConfigOption("Full Screen", "No");
rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit colour");


第四步:创建一个渲染窗口
这个非常简单,在go()中加入下面的这条语句:
mWindow = mRoot->initialise(true, "Render Window");
这里还不能运行窗口。


第五步:初始化资源
在初始化资源之前,还需要做一件事,就是设置贴图坐标,在go()中加入代码:
// Set default mipmap level (note: some APIs ignore this)
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
// initialise all resource groups
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
注意go()中代码添加的顺序,一定是一步步来的。
每做完一步都试着编译运行一下,然后看一下运行日志。


第六步:创建一个场景
这里需要创建三个东西:SceneManager,Camera,Viewport.
首先加入头文件:
#include <OgreCamera.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
然后在头文件中加入:
Ogre::SceneManager* mSceneMgr;
Ogre::Camera* mCamera;
在go()中初始化:
// Create the SceneManager, in this case a generic one
mSceneMgr = mRoot->createSceneManager("DefaultSceneManager");
// Create the camera
mCamera = mSceneMgr->createCamera("PlayerCam");
 
// Position it at 80 in Z direction
mCamera->setPosition(Ogre::Vector3(0,0,80));
// Look back along -Z
mCamera->lookAt(Ogre::Vector3(0,0,-300));
mCamera->setNearClipDistance(5);
// Create one viewport, entire window
Ogre::Viewport* vp = mWindow->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
 
// Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(
    Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));


第七步:添加一些东西
在go()中添加:
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
 
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
headNode->attachObject(ogreHead);
 
// Set ambient light
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
 
// Create a light
Ogre::Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
在头文件中包含文件:
#include <OgreEntity.h>
第八步:渲染一帧来看看
在头文件中添加:
#include <OgreWindowEventUtilities.h>
在go()中添加:
while(true)
{
    // Pump window messages for nice behaviour
    Ogre::WindowEventUtilities::messagePump();
 
    if(mWindow->isClosed())
    {
        return false;
    }
 
    // Render a frame
    if(!mRoot->renderOneFrame()) return false;
}
编译运行,成功的话就能看到一个怪兽的头了!
但是我们还没有写任何鼠标和键盘的监听,所以关掉程序的方法只有alter+f4或是X窗口。
第九步:设置OIS
OIS是Ogre的最好输入工具。
添加头文件:
#include <OISEvents.h>
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h>
在类中加入私有成员:
// OIS Input devices
OIS::InputManager* mInputManager;
OIS::Mouse*    mMouse;
OIS::Keyboard* mKeyboard;
然后在编译的时候要加入相应的库
Include Directory $(OGRE_HOME)/include/OIS
Input Library OIS_d.lib/OIS.lib


在go()中将下面的代码加载渲染循环之前:
Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
 
mWindow->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
 
mInputManager = OIS::InputManager::createInputSystem( pl );
mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, false ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, false ));


接下来加入退出窗口,改变窗口大小的方法。
首先将类改为公有继承WindowEventLisrtener.
class BasicTutorial6: public Ogre::WindowEventListener
顺便复习一下C++中的继承。
公有继承时,积累中各成员属性保持不变,基类的private成员被隐藏,派生类的成员只能访问基类中的public/protected成员,派生类的对象只能访问基类中的public成员。


私有继承时基类中各成员属性均变为private,,基类的private成员被隐藏,派生类的成员只能访问基类中的public/protected成员,派生类的对象不能访问基类中的任何成员。


保护继承时基类中各成员属性均变为protected,,基类的private成员被隐藏,派生类的成员只能访问基类中的public/protected成员,派生类的对象不能访问基类中的任何成员。


接下来在头文件中加入下面两个方法:


// Ogre::WindowEventListener
virtual void windowResized(Ogre::RenderWindow* rw);
virtual void windowClosed(Ogre::RenderWindow* rw);


在cpp中写函数实现:


//Adjust mouse clipping area
void BasicTutorial6::windowResized(Ogre::RenderWindow* rw)
{
    unsigned int width, height, depth;
    int left, top;
    rw->getMetrics(width, height, depth, left, top);
 
    const OIS::MouseState &ms = mMouse->getMouseState();
    ms.width = width;
    ms.height = height;
}
 
//Unattach OIS before window shutdown (very important under Linux)
void BasicTutorial6::windowClosed(Ogre::RenderWindow* rw)
{
    //Only close for window that created OIS (the main window in these demos)
    if( rw == mWindow )
    {
        if( mInputManager )
        {
            mInputManager->destroyInputObject( mMouse );
            mInputManager->destroyInputObject( mKeyboard );
 
            OIS::InputManager::destroyInputSystem(mInputManager);
            mInputManager = 0;
        }
    }
}


在go()中加入代码:
//Set initial mouse clipping size
windowResized(mWindow);
 
//Register as a Window listener
Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);


在析构函数中加入:
//Remove ourself as a Window listener
Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
windowClosed(mWindow);
delete mRoot;
第十步:设置帧监听
首先将共有继承FrameListener:
class BasicTutorial6 : public Ogre::WindowEventListener, public Ogre::FrameListener


头文件中加入下面的方法声明:
// Ogre::FrameListener
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);


具体实现如下:
bool BasicTutorial6::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
    if(mWindow->isClosed())
        return false;
 
    //Need to capture/update each device
    mKeyboard->capture();
    mMouse->capture();
 
    if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
        return false;
 
    return true;
}


第十一步:注册帧监听
在go()中加入:
mRoot->addFrameListener(this);
mRoot->startRendering();


第十一步:编译运行:
我的CMakeList.txt文件如下:
#/*
#-----------------------------------------------------------------------------
#Filename:    CMakeLists.txt
#-----------------------------------------------------------------------------
#
#This source file is part of the
#   ___                 __    __ _ _    _ 
#  /___\__ _ _ __ ___  / / /\ \ (_) | _(_)
# //  // _` | '__/ _ \ \ \/  \/ / | |/ / |
#/ \_// (_| | | |  __/  \  /\  /| |   <| |
#\___/ \__, |_|  \___|   \/  \/ |_|_|\_\_|
#      |___/                              
#      Tutorial Framework
#      http://www.ogre3d.org/tikiwiki/
#-----------------------------------------------------------------------------
#*/
cmake_minimum_required(VERSION 2.6)
 
project(OgreApp)
set(CMAKE_MODULE_PATH "/usr/local/lib/OGRE/cmake/;${CMAKE_MODULE_PATH}")
set(OGRE_SAMPLES_INCLUDEPATH "/home/tao/workspace/ogre_src_v1-8-0/Samples/Common/include/")
set(OGRE_INCLUDEPATH "/usr/local/include/OGRE")
set(CMAKE_C_FLAGS "-g")
if (CMAKE_BUILD_TYPE STREQUAL "")
  # CMake defaults to leaving CMAKE_BUILD_TYPE empty. This screws up
  # differentiation between debug and release builds.
  set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: None (CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif ()
 
set(CMAKE_DEBUG_POSTFIX "_d")
 
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/dist")
 
find_package(OGRE REQUIRED)
 
#if(NOT "${OGRE_VERSION_NAME}" STREQUAL "Cthugha")
#  message(SEND_ERROR "You need Ogre 1.7 Cthugha to build this.")
#endif()
 
find_package(OIS REQUIRED)


 
if(NOT OIS_FOUND)
message(SEND_ERROR "Failed to find OIS.")
endif()
 
# Find Boost
if (NOT OGRE_BUILD_PLATFORM_IPHONE)
if (WIN32 OR APPLE)
set(Boost_USE_STATIC_LIBS TRUE)
else ()
# Statically linking boost to a dynamic Ogre build doesn't work on Linux 64bit
set(Boost_USE_STATIC_LIBS ${OGRE_STATIC})
endif ()
if (MINGW)
# this is probably a bug in CMake: the boost find module tries to look for
# boost libraries with name libboost_*, but CMake already prefixes library
# search names with "lib". This is the workaround.
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "")
endif ()
set(Boost_ADDITIONAL_VERSIONS "1.44" "1.44.0" "1.42" "1.42.0" "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" )
# Components that need linking (NB does not include header-only components like bind)
set(OGRE_BOOST_COMPONENTS thread date_time)
find_package(Boost COMPONENTS ${OGRE_BOOST_COMPONENTS} QUIET)
if (NOT Boost_FOUND)
# Try again with the other type of libs
set(Boost_USE_STATIC_LIBS NOT ${Boost_USE_STATIC_LIBS})
find_package(Boost COMPONENTS ${OGRE_BOOST_COMPONENTS} QUIET)
endif()
find_package(Boost QUIET)
 
# Set up referencing of Boost
include_directories(${Boost_INCLUDE_DIR})
add_definitions(-DBOOST_ALL_NO_LIB)
set(OGRE_LIBRARIES ${OGRE_LIBRARIES} ${Boost_LIBRARIES})
endif()
 
set(HDRS
./TutorialApplication.h
)
 
set(SRCS
./TutorialApplication.cpp
)
 
include_directories( ${OIS_INCLUDE_DIRS}
${OGRE_INCLUDE_DIRS}
${OGRE_SAMPLES_INCLUDEPATH}
${OGRE_INCLUDEPATH}
)
 
add_executable(OgreApp WIN32 ${HDRS} ${SRCS})
 
set_target_properties(OgreApp PROPERTIES DEBUG_POSTFIX _d)
 
target_link_libraries(OgreApp ${OGRE_LIBRARIES} ${OIS_LIBRARIES} ${OGRE_Terrain_LIBRARIES})
 
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/bin)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dist/media)


set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/dist/bin)


install(TARGETS OgreApp
RUNTIME DESTINATION bin
CONFIGURATIONS All)
 
install(DIRECTORY ${CMAKE_SOURCE_DIR}/dist/media
DESTINATION ./
CONFIGURATIONS Release RelWithDebInfo Debug
)
 
install(FILES ${CMAKE_SOURCE_DIR}/dist/bin/plugins.cfg
${CMAKE_SOURCE_DIR}/dist/bin/resources.cfg
DESTINATION bin
CONFIGURATIONS Release RelWithDebInfo Debug
)


编译如果出现段错误之类的可以用gdb来调试,找到出现错误的代码,然后修改。

最终效果:


第十二步:打完收工——2012—7-19-2-48
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值