OSG + MFC单文档 实现第一个程序

来源:互联网 发布:qq飞车a车数据库 编辑:程序博客网 时间:2024/05/20 11:48
OSG + MFC单文档 实现第一个程序

前言:本文参考OSG 例子编写,建立在读者已经学会配置OSG环境基础上。

1.首先创建一个MFC单文档程序,步骤省略部分为默认;



2.文件拓展名加入(*.ive),读者如果不需要加载此类型模型,可以不写;



3.暂时不需要ActiveX控件,取消;点击完成;



4.新建一个C++类,内容和OSG例子中的类相同,例如类名:CRenderOSG;


其 RenderOSG.h 文件内容:
#pragma once#include <osgViewer/Viewer>#include <osgViewer/ViewerEventHandlers>#include <osgViewer/api/win32/GraphicsWindowWin32>#include <osgGA/TrackballManipulator>#include <osgGA/KeySwitchMatrixManipulator>#include <osgDB/DatabasePager>#include <osgDB/Registry>#include <osgDB/ReadFile>#include <osgUtil/Optimizer>#include <string>class cOSG{public:    cOSG(HWND hWnd);    ~cOSG();    void InitOSG(std::string filename);   //初始化OSG,传入模型文件名    void InitManipulators(void);  //初始化操作器    void InitSceneGraph(void);  //初始化场景    void InitCameraConfig(void);  //相机配置    void SetupWindow(void);               //建立窗口    void SetupCamera(void);               //建立相机    void PreFrameUpdate(void);            //绘制前处理    void PostFrameUpdate(void);           //绘制后处理    void Done(bool value) { mDone = value; }    bool Done(void) { return mDone; }    static void Render(void* ptr);         //渲染    osgViewer::Viewer* getViewer() { return mViewer; }private:    bool mDone;    std::string m_ModelName;   //模型名    HWND m_hWnd;   //窗口句柄    osgViewer::Viewer* mViewer;    osg::ref_ptr<osg::Group> mRoot;        //根结点    osg::ref_ptr<osg::Node> mModel;        //模型文件    osg::ref_ptr<osgGA::TrackballManipulator> trackball;//操作器    osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator;   //加入keyswitch选择操作器};class CRenderingThread : public OpenThreads::Thread{public:    CRenderingThread( cOSG* ptr );    virtual ~CRenderingThread();    virtual void run();protected:    cOSG* _ptr;    bool _done;};

RenderOSG.cpp 文件内容如下:
// MFC_OSG.cpp : implementation of the cOSG class//#include "stdafx.h"#include "RenderOSG.h"cOSG::cOSG(HWND hWnd) :   m_hWnd(hWnd) {}cOSG::~cOSG(){    mViewer->setDone(true);    Sleep(1000);    mViewer->stopThreading();    delete mViewer;}void cOSG::InitOSG(std::string modelname){    // Store the name of the model to load    m_ModelName = modelname;    // Init different parts of OSG    InitManipulators();    InitSceneGraph();    InitCameraConfig();}void cOSG::InitManipulators(void){    // Create a trackball manipulator    trackball = new osgGA::TrackballManipulator();    // Create a Manipulator Switcher    keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;    // Add our trackball manipulator to the switcher    keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get());    // Init the switcher to the first manipulator (in this case the only manipulator)    keyswitchManipulator->selectMatrixManipulator(0);  // Zero based index Value}void cOSG::InitSceneGraph(void){    // Init the main Root Node/Group    mRoot  = new osg::Group;    // Load the Model from the model name    mModel = osgDB::readNodeFile(m_ModelName);    if (!mModel) return;    // Optimize the model    osgUtil::Optimizer optimizer;    optimizer.optimize(mModel.get());    optimizer.reset();    // Add the model to the scene    mRoot->addChild(mModel.get());}void cOSG::InitCameraConfig(void){    // Local Variable to hold window size data    RECT rect;    // Create the viewer for this window    mViewer = new osgViewer::Viewer();    // Add a Stats Handler to the viewer    mViewer->addEventHandler(new osgViewer::StatsHandler);        // Get the current window size    ::GetWindowRect(m_hWnd, &rect);    // Init the GraphicsContext Traits    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;    // Init the Windata Variable that holds the handle for the Window to display OSG in.    osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);    // Setup the traits parameters    traits->x = 0;    traits->y = 0;    traits->width = rect.right - rect.left;    traits->height = rect.bottom - rect.top;    traits->windowDecoration = false;    traits->doubleBuffer = true;    traits->sharedContext = 0;    traits->setInheritedWindowPixelFormat = true;    traits->inheritedWindowData = windata;    // Create the Graphics Context    osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());    // Init Master Camera for this View    osg::ref_ptr<osg::Camera> camera = mViewer->getCamera();    // Assign Graphics Context to the Camera    camera->setGraphicsContext(gc);    // Set the viewport for the Camera    camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));    // Set projection matrix and camera attribtues    camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);    camera->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.4f, 1.0f));    camera->setProjectionMatrixAsPerspective(        30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0, 1000.0);    // Add the Camera to the Viewer    //mViewer->addSlave(camera.get());    mViewer->setCamera(camera.get());    // Add the Camera Manipulator to the Viewer    mViewer->setCameraManipulator(keyswitchManipulator.get());    // Set the Scene Data    mViewer->setSceneData(mRoot.get());    // Realize the Viewer    mViewer->realize();    // Correct aspect ratio    /*double fovy,aspectRatio,z1,z2;    mViewer->getCamera()->getProjectionMatrixAsPerspective(fovy,aspectRatio,z1,z2);    aspectRatio=double(traits->width)/double(traits->height);    mViewer->getCamera()->setProjectionMatrixAsPerspective(fovy,aspectRatio,z1,z2);*/}void cOSG::PreFrameUpdate(){    // Due any preframe updates in this routine}void cOSG::PostFrameUpdate(){    // Due any postframe updates in this routine}void cOSG::Render(void* ptr){    cOSG* osg = (cOSG*)ptr;    osgViewer::Viewer* viewer = osg->getViewer();    // You have two options for the main viewer loop    //      viewer->run()   or    //      while(!viewer->done()) { viewer->frame(); }    //viewer->run();    while(!viewer->done())    {        osg->PreFrameUpdate();        viewer->frame();        osg->PostFrameUpdate();        //Sleep(10);         // Use this command if you need to allow other processes to have cpu time    }    // For some reason this has to be here to avoid issue:     // if you have multiple OSG windows up     // and you exit one then all stop rendering    AfxMessageBox(_T("Exit Rendering Thread"));    _endthread();}CRenderingThread::CRenderingThread( cOSG* ptr ):   OpenThreads::Thread(), _ptr(ptr), _done(false){}CRenderingThread::~CRenderingThread(){    _done = true;    while( isRunning() )        OpenThreads::Thread::YieldCurrentThread();}void CRenderingThread::run(){    if ( !_ptr )    {        _done = true;        return;    }    osgViewer::Viewer* viewer = _ptr->getViewer();    do    {        _ptr->PreFrameUpdate();        viewer->frame();        _ptr->PostFrameUpdate();    } while ( !testCancel() && !viewer->done() && !_done );}


5.完成上述操作后,通过类向导添加如下消息响应:



6.在XXXView.h 中,头文件别忘了,添加如下成员变量:
protected:    cOSG* mOSG;    //HANDLE mThreadHandle;    CRenderingThread* mThreadHandle;

构造函数对指针进行初始化:
CZZU_OSGView::CZZU_OSGView():mOSG(0L){// TODO: 在此处添加构造代码}


7.在OnCreate函数中,添加:
int CZZU_OSGView::OnCreate(LPCREATESTRUCT lpCreateStruct){if (CView::OnCreate(lpCreateStruct) == -1)return -1;// Now that the window is created setup OSGmOSG = new cOSG(m_hWnd);return 0;}


8.在OnDestroy()函数中,进行 delete:
void CZZU_OSGView::OnDestroy(){delete mThreadHandle;if(mOSG != 0) delete mOSG;//WaitForSingleObject(mThreadHandle, 1000);CView::OnDestroy();}


9.OnEraseBkgnd()函数,返回真:
BOOL CZZU_OSGView::OnEraseBkgnd(CDC* pDC){// TODO: 在此添加消息处理程序代码和/或调用默认值//return CView::OnEraseBkgnd(pDC);return true;}


10.为了防止按Esc退出渲染,需要在OnKeyDown ()函数中,
void CZZU_OSGView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: 在此添加消息处理程序代码和/或调用默认值//CView::OnKeyDown(nChar, nRepCnt, nFlags);// 防止按Esc退出if(nChar == VK_ESCAPE){GetParent()->SendMessage(WM_CLOSE);}}


11.运行程序,发现什么都没有;


12.需要添加一个虚函数,实现更新;


更新函数代码如下:
void CZZU_OSGView::OnInitialUpdate(){CView::OnInitialUpdate();// Init the osg classmOSG->InitOSG("cow.osg");// Start the thread to do OSG Rendering//mThreadHandle = (HANDLE)_beginthread(&cOSG::Render, 0, mOSG); mThreadHandle = new CRenderingThread(mOSG);mThreadHandle->start();}


13.完成上述,运行程序: