使用WTL+OGRE编写3D程序(1) - 基本框架

本文介绍如何将OGRE图像引擎与WTL结合使用,通过自定义控件COgreSceneBoxImpl实现图形渲染,并探讨了控件所需实现的消息响应函数。

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的兄弟都知道这种常用的写法了,下面的代码展示的是一个基本框架,其中各个函数的处理过程我都暂时删掉了,后面会说到:

 

#ifndef _DRACULAX_OGRE_SCENEBOX_H
#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图形会被场景本身附着的控件所覆盖。

        一篇写不开,下一节我会把控件所需要实现的消息响应函数挨个解释。

内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,涵盖正向与逆向运动学求解、正向动力学控制,并采用拉格朗日-欧拉法推导逆向动力学方程,所有内容均通过Matlab代码实现。同时结合RRT路径规划与B样条优化技术,提升机械臂运动轨迹的合理性与平滑性。文中还涉及多种先进算法与仿真技术的应用,如状态估计中的UKF、AUKF、EKF等滤波方法,以及PINN、INN、CNN-LSTM等神经网络模型在工程问题中的建模与求解,展示了Matlab在机器人控制、智能算法与系统仿真中的强大能力。; 适合人群:具备一定Ma六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)tlab编程基础,从事机器人控制、自动化、智能制造、人工智能等相关领域的科研人员及研究生;熟悉运动学、动力学建模或对神经网络在控制系统中应用感兴趣的工程技术人员。; 使用场景及目标:①实现六自由度机械臂的精确运动学与动力学建模;②利用人工神经网络解决传统解析方法难以处理的非线性控制问题;③结合路径规划与轨迹优化提升机械臂作业效率;④掌握基于Matlab的状态估计、数据融合与智能算法仿真方法; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点理解运动学建模与神经网络控制的设计流程,关注算法实现细节与仿真结果分析,同时参考文中提及的多种优化与估计方法拓展研究思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值