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
#include
#include /*********osgGA =osg GUI ACTION 图形界面交互库*****************/
#include
#include #include
#include
#include
#include #include
#include
/************************************************************************/
/* 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);// SetDonevoid Done(bool value){mDone=value;}// getDonebool 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 mRoot;
// osg::ref_ptr m_Node;
public:osg::ref_ptr mModel;
private:osg::ref_ptr trackball;osg::ref_ptr 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;// 创建一个viewermViewer = new osgViewer::Viewer();// 加入一个statshandlermViewer->addEventHandler(new osgViewer::StatsHandler);// 得到当前窗口矩形::GetWindowRect(m_hWnd, &rect);// 初始化图形描述osg::ref_ptr traits = new osg::GraphicsContext::Traits;// 初始化窗口变量,为OSG所用osg::ref_ptr 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 camera = new osg::Camera;camera->setGraphicsContext(gc);//相机视口设置camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));// 添加相机到VIEWERmViewer->addSlave(camera.get());// 添加操作器到VIEWERmViewer->setCameraManipulator(keyswitchManipulator.get());//设置数据mViewer->setSceneData(mRoot.get());// 实现VIEWERmViewer->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:// 添加类CCoreOSGCCoreOSG* 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();} 本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
