Archie OSG Step By Step③ OSG+VS2010+MFC单文档程序框架构建

注意工程类型应与下载的OSG库类型一样,我这里是Release版OSG库,生成Release版程序没问题,但是Debug版有错误,如需要生成Debug版程序,需要下载Debug版OSGbinary。

OSGbinary版库(OpenSceneGraph3.0.1forVS2010-X86-32bi)下载OSGbinary版下载 (已经编译好的lib,不用自己编译,直接使用即可)

需要自己增加两个环境变量,OSG_FILE_PATH 指定OSG 程序读取图形和模型文件时的搜索路径。如果环境变量为空或者没有设置,OSG 在读取图形和
模型文件时只搜索当前的目录。

1、项目名称3DVision



选择字符集为多字符集


2、第一步:修改doc类

public:
    //从属性面板上把建立新文档操作删除掉,因为不需要建立新文档,什么时候都不会需要这个功能
	//virtual BOOL OnNewDocument();

protected:
    //定义一个文件名称,用来存放用来读取的模型文件
    CString m_csFileName;


public: //类向导重载OnOpenDocument函数,
     virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
添加函数GetFileName专门用来获得文件名

 CString GetFileName() const{ return m_csFileName;};

// CMy3DVisionDoc 构造/析构

CMy3DVisionDoc::CMy3DVisionDoc()
{
	// 定义一个默认打开文件 
    m_csFileName="cow.osg";

}
删除掉重载的新建文档函数
//BOOL CMy3DVisionDoc::OnNewDocument()
//{
//  
//	if (!CDocument::OnNewDocument())
//		return FALSE;
//
//	// TODO: 在此添加重新初始化代码
//	// (SDI 文档将重用该文档)
//
//	return TRUE;
//}
新加的打开文档映射

BOOL CMy3DVisionDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
    //打开时,把文件名传入m_csFileName.
    m_csFileName=lpszPathName;
    if (!CDocument::OnOpenDocument(lpszPathName))
        return FALSE;
   

    return TRUE;
}

附加依赖性lib
OpenThreads.lib
osg.lib
osgDB.lib
osgFX.lib
osgGA.lib
osgManipulator.lib
osgParticle.lib
osgShadow.lib
osgSim.lib
osgTerrain.lib
osgText.lib
osgUtil.lib
osgViewer.lib

在当前项目下新建包含文件和库文件目录

第二步:添加OSG核心处理类


CorsOSG.h
#pragma once

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/api/Win32/GraphicsWindowWin32>

/*********osgGA =osg GUI ACTION 图形界面交互库*****************/
#include <osgGA/TrackballManipulator>
#include <osgGA/KeySwitchMatrixManipulator>

#include <osgDB/DatabasePager>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>
#include <string>
/************************************************************************/
/*        OSG核心类,在这里执行MFC对OSG的大部分的管理功能                 */
/************************************************************************/
class CCoreOSG
{
public:
//    CCoreOSG(void);
    ~CCoreOSG(void);
    // 构造函数获取上一级窗口句柄
    CCoreOSG(HWND hWnd);
    // 初始化OSG,参数filename为需要加入的模型
    void InitOSG(std::string filename);
    // 初始化操作器
    void InitManipulators(void);
    // 初始化场景
    void InitSceneGraph(void);
    // 初始化相机配置
    void InitCameraConfig(void);
    // 建立窗口
    void SetupWindow(void);
    // 建立相机
    void SetupCamera(void);
    // 每帧绘制前整理
    void PreFrameUpdate(void);
    // 每帧绘制后处理
    void PostFrameUpdate(void);

    // SetDone
    void Done(bool value)
    {
        mDone=value;
    }

    // getDone
    bool Done(void)
    {
        return mDone;
    }
    // 渲染,注意这里是静态的,可启用为全局线程
    static void Render(void* ptr);
    // 使用一个名称为filename的模型代替当前场景中的所有模型
    void ReplaceSceneData(std::string filename);
//    osgViewer::Viewer* GetViewer(void);
private:
    bool mDone;
    std::string m_ModelName;
    HWND m_hWnd;
    osgViewer::Viewer* mViewer;
    osg::ref_ptr<osg::Group> mRoot;
//    osg::ref_ptr<osg::Node> m_Node;
public:
    osg::ref_ptr<osg::Node> mModel;
private:
    osg::ref_ptr<osgGA::TrackballManipulator> trackball;
    osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator;
public:

    osgViewer::Viewer* GetViewer(void)
    {
        return mViewer;
    }
};

CoreOSG.cpp
#include "StdAfx.h"
#include "CoreOSG.h"



// 构造函数获取上一级窗口句柄
CCoreOSG::CCoreOSG(HWND hWnd):m_hWnd(hWnd)
{
}


CCoreOSG::~CCoreOSG()
{
    mViewer->setDone(true);
    Sleep(1000);
    mViewer->stopThreading();
    delete mViewer;
}




void CCoreOSG::InitOSG(std::string modelname)
{
    //存储取到的模型文件名称
    m_ModelName = modelname;

    // 初始化OSG的不同部分
    InitManipulators();
    InitSceneGraph();
    InitCameraConfig();
}

void CCoreOSG::InitManipulators(void)
{
    /*
    //创建一个trackball操作器
    trackball = new osgGA::TrackballManipulator();
    //创建一个KEY切换
    keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
    // 加入KEY切换
    keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get());
    //选择一个
    keyswitchManipulator->selectMatrixManipulator(0);// 0是索引值*/
    //创建一个trackball操作器
    trackball = new osgGA::TrackballManipulator();

    //创建一个KEY切换
    keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

    // 加入KEY切换
    keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get());



    //选择一个
    keyswitchManipulator->selectMatrixManipulator(0);// 0是索引值
}

void CCoreOSG::InitSceneGraph(void)
{
    //初始化组
    mRoot = new osg::Group;
    //读取模型
    mModel = osgDB::readNodeFile(m_ModelName);

    // 优化模型
    osgUtil::Optimizer optimizer;
    optimizer.optimize(mModel.get());
    optimizer.reset();

    //把模型加入到场景中
    mRoot->addChild(mModel.get());
}


void CCoreOSG::InitCameraConfig(void)
{
    // 局部变量存放窗口矩形
    RECT rect;

    // 创建一个viewer
    mViewer = new osgViewer::Viewer();
    // 加入一个statshandler
    mViewer->addEventHandler(new osgViewer::StatsHandler);
    // 得到当前窗口矩形
    ::GetWindowRect(m_hWnd, &rect);

    // 初始化图形描述
    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;

    // 初始化窗口变量,为OSG所用
    osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);

    // 设置一些参数
    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;

    // 创建图形上下文
    osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());

    // 初始化一个相机
    osg::ref_ptr<osg::Camera> camera = new osg::Camera;

    camera->setGraphicsContext(gc);

	//相机视口设置
    camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));

	// 添加相机到VIEWER
    mViewer->addSlave(camera.get());
    // 添加操作器到VIEWER
    mViewer->setCameraManipulator(keyswitchManipulator.get());
    //设置数据
    mViewer->setSceneData(mRoot.get());
    // 实现VIEWER
    mViewer->realize();
}


// 建立窗口
void CCoreOSG::SetupWindow(void)
{
}

// 建立相机
void CCoreOSG::SetupCamera(void)
{
}

void CCoreOSG::PreFrameUpdate(void)
{
	// 帧前操作可在这里做一下
}

void CCoreOSG::PostFrameUpdate(void)
{
	// 帧后操作可在这里做一下
}


// 渲染,注意这里是静态的,可启用为全局线程
void CCoreOSG::Render(void* ptr)
{
    CCoreOSG* osg=(CCoreOSG*)ptr;
    osgViewer::Viewer* viewer=osg->GetViewer();
    //可以这样
    // view->run() or
    // while(!viewer->done()){viewer->frame();}
    // viewer->run();

    //也可以这样,建议这样
    while (!viewer->done())
    {
        osg->PreFrameUpdate();
        viewer->frame();
        osg->PostFrameUpdate();
        //Sleep(10);//让其他程序也占用CPU,放出MS

 
    }
	//退出了程序,弹出个对话框说一下
    AfxMessageBox("线程退出");
   
    _endthread();

}

void CCoreOSG::ReplaceSceneData(std::string filename)
{
    //移掉mRoot中所有的数据,这些数据将会被自动释放掉,不用手动处理
    mRoot->removeChildren(0, mRoot->getNumChildren());

    //加入要置换的模型
    mModel = osgDB::readNodeFile(filename);

    //优化
    osgUtil::Optimizer optimizer;
    optimizer.optimize(mModel.get());
    optimizer.reset();

    //添加孩子
    mRoot->addChild(mModel.get());
}

第三步:在view类中处理OSG

// 3DVisionView.h : CMy3DVisionView 类的接口
//

#pragma once

#include "CoreOSG.h"

添加类CCoreOSG

protected:
	
    // 添加类CCoreOSG
    CCoreOSG* mOSG;
    // 线程句柄
    HANDLE mThreadHandle;
    // 用于文件计数
    int iFileNum;

添加下列函数

public:
// 重写以下类型函数
    virtual void OnInitialUpdate();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnDestroy();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);


构造函数

// CMy3DVisionView 构造/析构

CMy3DVisionView::CMy3DVisionView()
    : mOSG(NULL)
    , iFileNum(0)
{
	// TODO: 在此处添加构造代码
    iFileNum=1;

}
 

如果多字符集

void CMy3DVisionView::OnInitialUpdate()
{
    //在这里控制一下打开文件的操作
    CView::OnInitialUpdate();
    if(iFileNum ==1)
    {
        //第一次打开默认飞机文件
        iFileNum ++ ;

        CString csFileName = GetDocument() ->GetFileName() ;

        mOSG ->InitOSG(csFileName.GetString()) ;

        mThreadHandle = (HANDLE)_beginthread(&CCoreOSG::Render, 0, mOSG) ;	
    }
    else
    {
        //后续打开,直接替掉模型就可以了
        iFileNum ++ ;
        CString csFileName = GetDocument() ->GetFileName() ;
        mOSG ->ReplaceSceneData(csFileName.GetString()) ;
    }
   

  
}

如果选的是Unicode字符集上面的CString类型需要转换。
int CMy3DVisionView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  在此添加您专用的创建代码
    mOSG=new CCoreOSG(m_hWnd);

    //return 0;
    return 1;
}

void CMy3DVisionView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    mOSG->GetViewer()->getEventQueue()->keyPress(nChar);
    if (nChar==VK_ESCAPE)
    {
        GetParent()->SendMessage(WM_CLOSE);
    }

   // CView::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CMy3DVisionView::OnDestroy()
{
    if (mOSG!=0)
    {
        delete mOSG;

    }
    WaitForSingleObject(mThreadHandle,1000);
    CView::OnDestroy();
    
}



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值