使用WTL+OGRE编写3D程序(1) - 基本框架
来源:互联网 发布:js 判断是否是正整数 编辑:程序博客网 时间:2024/06/05 17:25
OGRE是一款十分出色的开源图像引擎,很适合游戏开发爱好者使用。但是本文并不是主要针对游戏开发,而是主要针对实验室的3D研究人员。据我所知,很多从事3D渲染研究的实验室的研究生、博士生都使用基本的3D API,包括Direct3D和OpenGL进行开发。这样做的原因其实也很明显:使用基本的3D API可以对渲染过程进行最好、最细致的控制。但是,对于需要展示渲染结果的项目和研究来说,使用基本的API开发显然时间耗费较长,而且很多细节都需要亲力亲为,开发难度也较大。
使用OGRE可以最大限度的减少对琐碎的渲染细节的关注,或者说让我们集中更多的经历在更需要关注的细节上(80-20定理)。除了一个方面——GUI,OGRE并没有自己的GUI系统(Overlay其实已经没有什么用处),大家都知道使用CEGUI可以配合OGRE做出很漂亮的界面,但是对于研究项目来说,即没有必要,也不可能(很显然,因为研究项目一般都缺少美工,更不会花时间在界面上,这在教授们眼中是一钱不值得)。从另一方面,CEGUI并不是那么好用,和VC提供的即拖即放的界面设计对比,CEGUI还是比较垃圾。所以本文的题目是WTL+OGRE,相信很明白了:OGRE处理图像渲染,WTL/ATL负责界面处理。
——写给MFC程序员:如果你精通MFC,读这篇文章不会碰到任何问题,只要记住下面的代码确实不是MFC,而是WTL/ATL。
废话半天了,进入正题。要想将OGRE和WTL一起使用,最重要的问题就是渲染窗口的创建和窗口消息的处理,要知道我们写的不是全屏程序而是窗口程序,而且要把图形显示在一个控件或对话框上,这和OGRE的默认程序(ExampleAppliation)是不同的。
先看一下基本框架:
为了将图形渲染在一个控件上,我们需要首先建立一个自定义控件的模版 COgreSceneBoxImpl,熟悉WTL的兄弟都知道这种常用的写法了,下面的代码展示的是一个基本框架,其中各个函数的处理过程我都暂时删掉了,后面会说到:
#define _DRACULAX_OGRE_SCENEBOX_H
#pragma warning(disable:4819)
#include <atlctrls.h>
#include <atlmisc.h>
#include <Ogre.h>
using namespace Ogre;
#ifndef FALSE_RETURN
#define FALSE_RETURN(h, r) if(!h) return r;
#endif
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { delete (p); (p) = NULL; }
#endif
// template for ogre rendering static box
template <class T, class TBase = CStatic, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE COgreSceneBoxImpl : public ATL::CWindowImpl< T, TBase, TWinTraits>
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
// constructor
COgreSceneBoxImpl()
: m_pRoot(NULL)
, m_pRenderWindow(NULL)
, m_pSceneManager(NULL)
, m_pDefCamera(NULL)
, m_pDefViewport(NULL)
, m_bPause(FALSE)
{
}
// destructor
~COgreSceneBoxImpl()
{
SAFE_DELETE(m_pRoot);
}
public:
BEGIN_MSG_MAP(COgreSceneBoxImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_QUIT, OnQuit)
END_MSG_MAP()
// Message Handler
public:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 1; // no background needed
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
if(wParam != NULL)
{
pT->Render((HDC)wParam);
}
else
{
CPaintDC dc(m_hWnd);
pT->Render(dc.m_hDC);
}
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
}
LRESULT OnQuit(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
}
// Overrideables methods(default implement)
public:
// Load Plugin
BOOL LoadPlugin()
{
}
// Select Render System
BOOL SelectRenderSystem()
{
}
// Create Render Window
BOOL CreateRenderWindow()
{
}
// Create Scene Manager
BOOL CreateSceneManager()
{
}
// Create Default Camera and viewport
BOOL CreateDefaultCamera()
{
}
// Render one Frame
VOID Render(CDCHandle dc)
{
}
// release resource
VOID ReleaseOgre() { }
// Load resources
BOOL LoadResource()
{
}
// method must be overwrited
public:
// Create Scene
BOOL CreateScene() { ATLASSERT(FALSE); return FALSE; }
// public methods
public:
// Init ogre
BOOL Initialize()
{
}
// overridden to provide proper initialization
BOOL SubclassWindow(HWND hWnd)
{
#if (_MSC_VER >= 1300)
BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
#else //!(_MSC_VER >= 1300)
typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass;
BOOL bRet = _baseClass::SubclassWindow(hWnd);
#endif //!(_MSC_VER >= 1300)
if(bRet)
{
ModifyStyle(0, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
Initialize();
}
return bRet;
}
// Pause render
VOID Pause(BOOL bPause)
{
m_bPause = bPause;
}
// data
public:
Root* m_pRoot; // Ogre scene root
SceneManager* m_pSceneManager; // scene manager
RenderWindow* m_pRenderWindow; // render window
Camera* m_pDefCamera; // default camera
Viewport* m_pDefViewport; // default viewport
BOOL m_bPause; // pause render
};
class COgreSceneBox : public COgreSceneBoxImpl<COgreSceneBox>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_OgreSceneBox"), GetWndClassName())
};
需要解释的唯一一点是控件的风格:WS_CLIPCHILEREN 是必须的,如果没有这个标志,绘制时3D图形会被场景本身附着的控件所覆盖。
一篇写不开,下一节我会把控件所需要实现的消息响应函数挨个解释。
- 使用WTL+OGRE编写3D程序(1) - 基本框架
- 使用WTL+OGRE编写3D程序(1) - 基本框架
- 使用WTL+OGRE编写3D程序(3) - 场景的创建和渲染
- 使用WTL+OGRE编写3D程序(3) - 场景的创建和渲染
- 使用WTL+OGRE编写3D程序(2) - 窗口消息函数
- 使用WTL+OGRE编写3D程序(4) - 多窗口的渲染
- 使用WTL+OGRE编写3D程序(2) - 窗口消息函数
- 使用WTL+OGRE编写3D程序(4) - 多窗口的渲染
- OGRE+CG学习日记[1]-简单的3D程序
- Ogre 3D程序设计 Ogre材质1
- JavaSE基本框架的编写程序
- OGRE 3D 程序设计 Ogre 材质1 (转)
- OGRE 3D 程序设计 Ogre 材质1 转
- 新书预告《OGRE 3D 游戏开发框架指南》
- 使用Ogre 3D 运动模型 -----OGRE 3D 1.7 Beginner‘s Guide中文版 第五章
- OGRE 3D程序设计(1)
- OGRE 3D游戏
- Ogre 3D 配置
- 使用ATL开发ActiveX控件(添加事件,自己整理)
- PostgreSQL中删除重复行(保留一行)
- QTcpSocket如何阻塞readyRead()信号
- Qt多继承方式注意点
- poj 2112 Optimal Milking(最大费用流+dinic算法+二分搜索)
- 使用WTL+OGRE编写3D程序(1) - 基本框架
- MySQL 用户授权和bin-log日志和主从复制、读写分离(2)
- 使用WTL+OGRE编写3D程序(2) - 窗口消息函数
- jquery的事件委托小结利用与避免事件的冒泡
- 使用WTL+OGRE编写3D程序(3) - 场景的创建和渲染
- 使用Swing编写win7简易计算器5——M运算符
- 软件项目管理系统-仓库领用-领用一览
- C++模板的 主版本模板类、全特化、偏特化
- 使用WTL+OGRE编写3D程序(4) - 多窗口的渲染